finalized some prefetch logic

This commit is contained in:
Nate Kelley 2025-04-11 12:43:19 -06:00
parent 06b4236388
commit 17748b1ddb
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
22 changed files with 167 additions and 101 deletions

View File

@ -84,7 +84,10 @@ export const useGetChat = <TData = IBusterChat>(
if (lastMessage) { if (lastMessage) {
Object.values(lastMessage.response_messages).forEach((responseMessage) => { Object.values(lastMessage.response_messages).forEach((responseMessage) => {
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') { if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient); prefetchGetMetricDataClient(
{ id: responseMessage.id, version_number: responseMessage.version_number },
queryClient
);
} }
}); });
} }

View File

@ -61,7 +61,10 @@ const useGetDashboardAndInitializeMetrics = () => {
const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey); const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey);
const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric); const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric);
queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric); queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric);
prefetchGetMetricDataClient({ id: metric.id }, queryClient); prefetchGetMetricDataClient(
{ id: metric.id, version_number: metric.version_number },
queryClient
);
} }
}); });

View File

@ -34,6 +34,31 @@ import {
import { useParams, useSearchParams } from 'next/navigation'; import { useParams, useSearchParams } from 'next/navigation';
import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore'; import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore';
import { RustApiError } from '../../buster_rest/errors'; import { RustApiError } from '../../buster_rest/errors';
import last from 'lodash/last';
const useGetMetricVersionNumber = ({
versionNumber: versionNumberProp
}: {
versionNumber?: number | null; //if null it will not use a params from the query params
}) => {
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
versionNumber: string | undefined;
metricId: string | undefined;
};
const versionNumberQueryParam = useSearchParams().get('metric_version_number');
const versionNumberFromParams = metricIdPathParam
? versionNumberQueryParam || versionNumberPathParam
: undefined;
const versionNumber = useMemo(() => {
if (versionNumberProp === null) return undefined;
return versionNumberProp || versionNumberFromParams
? parseInt(versionNumberFromParams!)
: undefined;
}, [versionNumberProp, versionNumberFromParams]);
return versionNumber;
};
/** /**
* This is a hook that will use the version number from the URL params if it exists. * This is a hook that will use the version number from the URL params if it exists.
@ -54,21 +79,7 @@ export const useGetMetric = <TData = IBusterMetric>(
const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError); const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError);
const { password } = getAssetPassword(id!); const { password } = getAssetPassword(id!);
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as { const versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp });
versionNumber: string | undefined;
metricId: string | undefined;
};
const versionNumberQueryParam = useSearchParams().get('versionNumber');
const versionNumberFromParams = metricIdPathParam
? versionNumberQueryParam || versionNumberPathParam
: undefined;
const versionNumber = useMemo(() => {
if (versionNumberProp === null) return undefined;
return versionNumberProp || versionNumberFromParams
? parseInt(versionNumberFromParams!)
: undefined;
}, [versionNumberProp, versionNumberFromParams]);
const options = useMemo(() => { const options = useMemo(() => {
return metricsQueryKeys.metricsGetMetric(id!, versionNumber); return metricsQueryKeys.metricsGetMetric(id!, versionNumber);
@ -78,7 +89,10 @@ export const useGetMetric = <TData = IBusterMetric>(
const result = await getMetric({ id: id!, password, version_number: versionNumber }); const result = await getMetric({ id: id!, password, version_number: versionNumber });
const oldMetric = queryClient.getQueryData(options.queryKey); const oldMetric = queryClient.getQueryData(options.queryKey);
const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null); const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null);
setOriginalMetric(updatedMetric);
const isLatestVersion =
updatedMetric.version_number === last(updatedMetric.versions)?.version_number;
if (isLatestVersion) setOriginalMetric(updatedMetric);
return updatedMetric; return updatedMetric;
}); });
@ -128,28 +142,13 @@ export const useGetMetricData = <TData = IBusterMetricData>(
) => { ) => {
const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword); const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword);
const { password } = getAssetPassword(id!); const { password } = getAssetPassword(id!);
const versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp });
const { const {
isFetched: isFetchedMetric, isFetched: isFetchedMetric,
error: errorMetric, isError: isErrorMetric,
dataUpdatedAt,
data: fetchedMetricData data: fetchedMetricData
} = useGetMetric({ id }, { select: (x) => x.id }); } = useGetMetric({ id, versionNumber }, { select: (x) => x.id });
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
versionNumber: string | undefined;
metricId: string | undefined;
};
const versionNumberQueryParam = useSearchParams().get('versionNumber');
const versionNumberFromParams = metricIdPathParam
? versionNumberQueryParam || versionNumberPathParam
: undefined;
const versionNumber = useMemo(() => {
if (versionNumberProp === null) return undefined;
return versionNumberProp || versionNumberFromParams
? parseInt(versionNumberFromParams!)
: undefined;
}, [versionNumberProp, versionNumberFromParams]);
const queryFn = useMemoizedFn(() => { const queryFn = useMemoizedFn(() => {
return getMetricData({ id: id!, version_number: versionNumber, password }); return getMetricData({ id: id!, version_number: versionNumber, password });
}); });
@ -158,7 +157,7 @@ export const useGetMetricData = <TData = IBusterMetricData>(
...metricsQueryKeys.metricsGetData(id!, versionNumber), ...metricsQueryKeys.metricsGetData(id!, versionNumber),
queryFn, queryFn,
enabled: () => { enabled: () => {
return !!id && isFetchedMetric && !errorMetric && !!fetchedMetricData; return !!id && isFetchedMetric && !isErrorMetric && !!fetchedMetricData && !!dataUpdatedAt;
}, },
select: params?.select, select: params?.select,
...params ...params
@ -166,7 +165,7 @@ export const useGetMetricData = <TData = IBusterMetricData>(
}; };
export const prefetchGetMetricDataClient = async ( export const prefetchGetMetricDataClient = async (
{ id, version_number }: { id: string; version_number?: number }, { id, version_number }: { id: string; version_number: number | undefined },
queryClient: QueryClient queryClient: QueryClient
) => { ) => {
const options = metricsQueryKeys.metricsGetData(id, version_number); const options = metricsQueryKeys.metricsGetData(id, version_number);

View File

@ -83,7 +83,10 @@ export const BusterChart: React.FC<BusterChartProps> = React.memo(
}); });
const SwitchComponent = useMemoizedFn(() => { const SwitchComponent = useMemoizedFn(() => {
if (loading || error || !isMounted) { //chartjs need the parent to be mounted to render the chart. It is intermitent when it throws when the parent is not mounted.
if (!isMounted && selectedChartType !== ChartType.Table) return null;
if (loading || error) {
return <PreparingYourRequestLoader error={error} />; return <PreparingYourRequestLoader error={error} />;
} }

View File

@ -11,7 +11,8 @@ export const PreparingYourRequestLoader: React.FC<{
useShimmer?: boolean; useShimmer?: boolean;
}> = ({ className = '', text = 'Processing your request...', error, useShimmer = true }) => { }> = ({ className = '', text = 'Processing your request...', error, useShimmer = true }) => {
return ( return (
<div className={`flex h-full w-full items-center justify-center space-x-1.5 ${className}`}> <div
className={`flex h-full min-h-24 w-full items-center justify-center space-x-1.5 ${className}`}>
{error || useShimmer === false ? ( {error || useShimmer === false ? (
<span className="text-text-tertiary flex items-center text-center">{error || text}</span> <span className="text-text-tertiary flex items-center text-center">{error || text}</span>
) : ( ) : (

View File

@ -71,7 +71,10 @@ export const useChatStreamMessage = () => {
if (lastMessage?.response_message_ids) { if (lastMessage?.response_message_ids) {
Object.values(lastMessage.response_messages).forEach((responseMessage) => { Object.values(lastMessage.response_messages).forEach((responseMessage) => {
if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') { if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') {
prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient); prefetchGetMetricDataClient(
{ id: responseMessage.id, version_number: responseMessage.version_number },
queryClient
);
} }
}); });
} }

View File

@ -23,7 +23,8 @@ export const useIsMetricReadOnly = ({
enabled: false, enabled: false,
select: (x) => ({ select: (x) => ({
permission: x.permission, permission: x.permission,
versions: x.versions versions: x.versions,
version_number: x.version_number
}) })
} }
); );

View File

@ -2,11 +2,7 @@
import type { IBusterMetric } from '@/api/asset_interfaces/metric'; import type { IBusterMetric } from '@/api/asset_interfaces/metric';
import { create } from 'zustand'; import { create } from 'zustand';
import { compareObjectsByKeys } from '@/lib/objects'; import { useMount } from '@/hooks';
import { useGetMetric } from '@/api/buster_rest/metrics/queryRequests';
import { useMemoizedFn, useMount } from '@/hooks';
import { useQueryClient } from '@tanstack/react-query';
import { metricsQueryKeys } from '@/api/query_keys/metric';
type OriginalMetricStore = { type OriginalMetricStore = {
originalMetrics: Record<string, IBusterMetric>; originalMetrics: Record<string, IBusterMetric>;

View File

@ -24,12 +24,11 @@ export const DashboardViewDashboardController: React.FC<{
} = useGetDashboard({ id: dashboardId }); } = useGetDashboard({ id: dashboardId });
const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig(); const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig();
const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode);
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal); const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
const metrics = dashboardResponse?.metrics; const metrics = dashboardResponse?.metrics;
const dashboard = dashboardResponse?.dashboard; const dashboard = dashboardResponse?.dashboard;
const { isReadOnly } = useIsDashboardReadOnly({ const { isReadOnly, isViewingOldVersion, isVersionHistoryMode } = useIsDashboardReadOnly({
dashboardId, dashboardId,
readOnly: readOnlyProp readOnly: readOnlyProp
}); });
@ -65,7 +64,9 @@ export const DashboardViewDashboardController: React.FC<{
readOnly={isReadOnly} readOnly={isReadOnly}
/> />
{!isVersionHistoryMode && <DashboardSavePopup dashboardId={dashboardId} />} {!isVersionHistoryMode && !isViewingOldVersion && (
<DashboardSavePopup dashboardId={dashboardId} />
)}
</div> </div>
</ScrollArea> </ScrollArea>
); );

View File

@ -22,7 +22,7 @@ export const MetricStylingApp: React.FC<{
MetricStylingAppSegments.VISUALIZE MetricStylingAppSegments.VISUALIZE
); );
const { data: chartConfig } = useGetMetric({ id: metricId }, { select: (x) => x.chart_config }); const { data: chartConfig } = useGetMetric({ id: metricId }, { select: (x) => x.chart_config });
const { data: metricData } = useGetMetricData({ id: metricId }); const { data: metricData } = useGetMetricData({ id: metricId }, { enabled: false });
if (!chartConfig) return null; if (!chartConfig) return null;

View File

@ -33,7 +33,9 @@ export const MetricViewChart: React.FC<{
time_frame, time_frame,
permission, permission,
evaluation_score, evaluation_score,
evaluation_summary evaluation_summary,
version_number,
versions
}) => ({ }) => ({
name, name,
description, description,
@ -41,7 +43,9 @@ export const MetricViewChart: React.FC<{
permission, permission,
evaluation_score, evaluation_score,
evaluation_summary, evaluation_summary,
chart_config chart_config,
version_number,
versions
}) })
} }
); );
@ -49,7 +53,7 @@ export const MetricViewChart: React.FC<{
data: metricData, data: metricData,
isFetched: isFetchedMetricData, isFetched: isFetchedMetricData,
error: metricDataError error: metricDataError
} = useGetMetricData({ id: metricId }); } = useGetMetricData({ id: metricId }, { enabled: false });
const { mutate: updateMetric } = useUpdateMetric({ const { mutate: updateMetric } = useUpdateMetric({
saveToServer: false saveToServer: false
@ -57,7 +61,7 @@ export const MetricViewChart: React.FC<{
const { name, description, time_frame, evaluation_score, evaluation_summary } = metric || {}; const { name, description, time_frame, evaluation_score, evaluation_summary } = metric || {};
const isTable = metric?.chart_config.selectedChartType === ChartType.Table; const isTable = metric?.chart_config.selectedChartType === ChartType.Table;
const { isReadOnly, isVersionHistoryMode } = useIsMetricReadOnly({ const { isReadOnly, isVersionHistoryMode, isViewingOldVersion } = useIsMetricReadOnly({
metricId, metricId,
readOnly: readOnlyProp readOnly: readOnlyProp
}); });
@ -110,7 +114,9 @@ export const MetricViewChart: React.FC<{
/> />
</AnimatePresenceWrapper> </AnimatePresenceWrapper>
{!isVersionHistoryMode && <MetricSaveFilePopup metricId={metricId} />} {!isVersionHistoryMode && !isViewingOldVersion && (
<MetricSaveFilePopup metricId={metricId} />
)}
</div> </div>
); );
} }

View File

@ -38,7 +38,10 @@ export const MetricViewResults: React.FC<{ metricId: string }> = React.memo(({ m
}) })
} }
); );
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData({ id: metricId }); const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData(
{ id: metricId },
{ enabled: false }
);
const [sql, setSQL] = useState(metric?.sql || ''); const [sql, setSQL] = useState(metric?.sql || '');

View File

@ -6,6 +6,7 @@ import { AppPasswordAccess } from '@/controllers/AppPasswordAccess';
import { AppNoPageAccess } from '@/controllers/AppNoPageAccess'; import { AppNoPageAccess } from '@/controllers/AppNoPageAccess';
import { useGetAsset } from './useGetAsset'; import { useGetAsset } from './useGetAsset';
import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader'; import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader';
import { useParams, useSearchParams } from 'next/navigation';
export type AppAssetCheckLayoutProps = { export type AppAssetCheckLayoutProps = {
assetId: string; assetId: string;

View File

@ -3,6 +3,8 @@
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics'; import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
import { useGetDashboard } from '@/api/buster_rest/dashboards'; import { useGetDashboard } from '@/api/buster_rest/dashboards';
import { RustApiError } from '@/api/buster_rest/errors'; import { RustApiError } from '@/api/buster_rest/errors';
import { useSearchParams } from 'next/navigation';
import { useMemo } from 'react';
interface BaseGetAssetProps { interface BaseGetAssetProps {
assetId: string; assetId: string;
@ -15,6 +17,7 @@ interface MetricAssetProps extends BaseGetAssetProps {
interface DashboardAssetProps extends BaseGetAssetProps { interface DashboardAssetProps extends BaseGetAssetProps {
type: 'dashboard'; type: 'dashboard';
versionNumber?: number;
} }
type UseGetAssetProps = MetricAssetProps | DashboardAssetProps; type UseGetAssetProps = MetricAssetProps | DashboardAssetProps;
@ -29,47 +32,55 @@ type UseGetAssetReturn<T extends UseGetAssetProps> = {
}; };
export const useGetAsset = (props: UseGetAssetProps): UseGetAssetReturn<typeof props> => { export const useGetAsset = (props: UseGetAssetProps): UseGetAssetReturn<typeof props> => {
const searchParams = useSearchParams();
const metricVersionNumber = searchParams.get('metric_version_number');
const dashboardVersionNumber = searchParams.get('dashboard_version_number');
const queryParamVersionNumber: number | undefined = useMemo(() => {
if (props.type === 'metric' && metricVersionNumber) {
return parseInt(metricVersionNumber);
}
if (props.type === 'dashboard' && dashboardVersionNumber) {
return parseInt(dashboardVersionNumber);
}
return undefined;
}, [props.type, metricVersionNumber, dashboardVersionNumber]);
const versionNumber: number | undefined = useMemo(() => {
if (props.type === 'metric') {
if (props.versionNumber) return props.versionNumber;
if (queryParamVersionNumber) return queryParamVersionNumber;
}
if (props.type === 'dashboard') {
if (props.versionNumber) return props.versionNumber;
if (queryParamVersionNumber) return queryParamVersionNumber;
}
return undefined;
}, [props, queryParamVersionNumber]);
//metric //metric
const { const { error: errorMetric, isFetched: isFetchedMetric } = useGetMetric(
error: errorMetric,
isError: isErrorMetric,
dataUpdatedAt,
isFetched: isFetchedMetric
} = useGetMetric(
{ {
id: props.assetId, id: props.type === 'metric' ? props.assetId : undefined,
versionNumber: props.type === 'metric' ? props.versionNumber : undefined versionNumber
}, },
{ { enabled: props.type === 'metric' && !!props.assetId }
enabled: props.type === 'metric' && !!props.assetId
}
);
const { isFetched: isFetchedMetricData } = useGetMetricData(
{
id: props.assetId,
versionNumber: props.type === 'metric' ? props.versionNumber : undefined
},
{
enabled:
props.type === 'metric' &&
!!props.assetId &&
isFetchedMetric &&
!!dataUpdatedAt && //This is a hack to prevent the query from being run when the asset is not fetched.
!isErrorMetric
}
); );
const { isFetched: isFetchedMetricData } = useGetMetricData({
id: props.assetId,
versionNumber
});
//dashboard //dashboard
const { const {
isFetched: isFetchedDashboard, isFetched: isFetchedDashboard,
error: errorDashboard, error: errorDashboard,
isError: isErrorDashboard isError: isErrorDashboard
} = useGetDashboard( } = useGetDashboard({
{ id: props.type === 'dashboard' ? props.assetId : undefined,
id: props.type === 'dashboard' ? props.assetId : undefined versionNumber
}, });
{ enabled: props.type === 'dashboard' && !!props.assetId }
);
const { hasAccess, passwordRequired, isPublic } = getAssetAccess({ const { hasAccess, passwordRequired, isPublic } = getAssetAccess({
error: props.type === 'metric' ? errorMetric : errorDashboard error: props.type === 'metric' ? errorMetric : errorDashboard

View File

@ -30,9 +30,14 @@ export const ChatContent: React.FC<{}> = React.memo(() => {
return ( return (
<> <>
<div className="mb-40 flex h-full w-full flex-col overflow-hidden"> <div className="mb-40 flex h-full w-full flex-col overflow-hidden">
{chatMessageIds?.map((messageId) => ( {chatMessageIds?.map((messageId, index) => (
<div key={messageId} className={autoClass}> <div key={messageId} className={autoClass}>
<ChatMessageBlock key={messageId} messageId={messageId} chatId={chatId || ''} /> <ChatMessageBlock
key={messageId}
messageId={messageId}
chatId={chatId || ''}
messageIndex={index}
/>
</div> </div>
))} ))}
</div> </div>

View File

@ -8,7 +8,8 @@ import { useGetChatMessage } from '@/api/buster_rest/chats';
export const ChatMessageBlock: React.FC<{ export const ChatMessageBlock: React.FC<{
messageId: string; messageId: string;
chatId: string; chatId: string;
}> = React.memo(({ messageId, chatId }) => { messageIndex: number;
}> = React.memo(({ messageId, chatId, messageIndex }) => {
const messageExists = useGetChatMessage(messageId, (message) => message?.id); const messageExists = useGetChatMessage(messageId, (message) => message?.id);
const requestMessage = useGetChatMessage(messageId, (message) => message?.request_message); const requestMessage = useGetChatMessage(messageId, (message) => message?.request_message);
const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream); const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream);
@ -29,6 +30,7 @@ export const ChatMessageBlock: React.FC<{
isCompletedStream={isCompletedStream!} isCompletedStream={isCompletedStream!}
messageId={messageId} messageId={messageId}
chatId={chatId} chatId={chatId}
messageIndex={messageIndex}
/> />
</div> </div>
); );

View File

@ -34,7 +34,7 @@ export const ChatResponseMessage_File: React.FC<ChatResponseMessageProps> = Reac
const onLinkClick = useMemoizedFn(() => { const onLinkClick = useMemoizedFn(() => {
if (isSelectedFile) onSetSelectedFile(null); if (isSelectedFile) onSetSelectedFile(null);
onSetSelectedFile({ id, type: file_type }); onSetSelectedFile({ id, type: file_type, versionNumber: responseMessage.version_number });
}); });
useMount(() => { useMount(() => {

View File

@ -9,17 +9,19 @@ interface ChatResponseMessagesProps {
isCompletedStream: boolean; isCompletedStream: boolean;
messageId: string; messageId: string;
chatId: string; chatId: string;
messageIndex: number;
} }
export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.memo( export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.memo(
({ chatId, isCompletedStream, messageId }) => { ({ chatId, isCompletedStream, messageId, messageIndex }) => {
const responseMessageIds = useGetChatMessage(messageId, (x) => x?.response_message_ids || [])!; const responseMessageIds = useGetChatMessage(messageId, (x) => x?.response_message_ids || [])!;
const lastReasoningMessageId = useGetChatMessage( const lastReasoningMessageId = useGetChatMessage(
messageId, messageId,
(x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1] (x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1]
); );
const finalReasoningMessage = useGetChatMessage(messageId, (x) => x?.final_reasoning_message); const finalReasoningMessage = useGetChatMessage(messageId, (x) => x?.final_reasoning_message);
const showReasoningMessage = !!lastReasoningMessageId || !isCompletedStream; const showReasoningMessage =
messageIndex === 0 ? !!lastReasoningMessageId || !isCompletedStream : true;
return ( return (
<MessageContainer className="flex w-full flex-col space-y-3 overflow-hidden"> <MessageContainer className="flex w-full flex-col space-y-3 overflow-hidden">

View File

@ -4,19 +4,30 @@ import { useGetChatParams } from '../useGetChatParams';
export const createSelectedFile = ( export const createSelectedFile = (
params: ReturnType<typeof useGetChatParams> params: ReturnType<typeof useGetChatParams>
): SelectedFile | null => { ): SelectedFile | null => {
const { metricId, collectionId, datasetId, dashboardId, chatId, messageId } = params; const {
metricId,
collectionId,
datasetId,
dashboardId,
chatId,
messageId,
metricVersionNumber,
dashboardVersionNumber
} = params;
if (metricId) { if (metricId) {
return { return {
id: metricId, id: metricId,
type: 'metric' type: 'metric',
versionNumber: metricVersionNumber
}; };
} }
if (dashboardId) { if (dashboardId) {
return { return {
id: dashboardId, id: dashboardId,
type: 'dashboard' type: 'dashboard',
versionNumber: dashboardVersionNumber
}; };
} }

View File

@ -31,8 +31,7 @@ export const useSelectedFile = ({
* @param file * @param file
*/ */
const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => { const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => {
const handleFileCollapse = const handleFileCollapse = shouldCloseSplitter(file, selectedFile, appSplitterRef);
!file || (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right'));
if (file && chatParams.chatId) { if (file && chatParams.chatId) {
const link = createChatAssetRoute({ const link = createChatAssetRoute({
@ -61,3 +60,18 @@ export const useSelectedFile = ({
}; };
export type SelectedFileParams = ReturnType<typeof useSelectedFile>; export type SelectedFileParams = ReturnType<typeof useSelectedFile>;
const shouldCloseSplitter = (
file: SelectedFile | null,
selectedFile: SelectedFile | null,
appSplitterRef: React.RefObject<AppSplitterRef | null>
) => {
if (!file) return false;
if (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right')) {
if (!!file?.versionNumber && !!selectedFile?.versionNumber) {
return file.versionNumber === selectedFile.versionNumber;
}
return true;
}
return false;
};

View File

@ -403,7 +403,7 @@ const useSQLEditorSelectMenu = () => {
const useDownloadCSVSelectMenu = ({ metricId }: { metricId: string }) => { const useDownloadCSVSelectMenu = ({ metricId }: { metricId: string }) => {
const [isDownloading, setIsDownloading] = useState(false); const [isDownloading, setIsDownloading] = useState(false);
const { data: metricData } = useGetMetricData({ id: metricId }); const { data: metricData } = useGetMetricData({ id: metricId }, { enabled: false });
const { data: name } = useGetMetric({ id: metricId }, { select: (x) => x.name }); const { data: name } = useGetMetric({ id: metricId }, { select: (x) => x.name });
return useMemo( return useMemo(

View File

@ -3,6 +3,7 @@ import type { FileType } from '@/api/asset_interfaces';
export type SelectedFile = { export type SelectedFile = {
id: string; id: string;
type: FileType; type: FileType;
versionNumber?: number;
}; };
export type ChatLayoutView = 'chat' | 'file' | 'both'; export type ChatLayoutView = 'chat' | 'file' | 'both';