From 17748b1ddb569824936e9c47d3d6b79e1bcd49e2 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Fri, 11 Apr 2025 12:43:19 -0600 Subject: [PATCH] finalized some prefetch logic --- .../api/buster_rest/chats/queryRequests.ts | 5 +- .../buster_rest/dashboards/queryRequests.ts | 5 +- .../api/buster_rest/metrics/queryRequests.ts | 73 +++++++++---------- web/src/components/ui/charts/BusterChart.tsx | 5 +- .../ChartLoadingComponents.tsx | 3 +- web/src/context/Chats/useChatStreamMessage.ts | 5 +- .../context/Metrics/useIsMetricReadOnly.tsx | 3 +- .../Metrics/useOriginalMetricStore.tsx | 6 +- .../DashboardViewDashboardController.tsx | 7 +- .../MetricStylingApp/MetricStylingApp.tsx | 2 +- .../MetricViewChart/MetricViewChart.tsx | 16 ++-- .../MetricViewResultsController.tsx | 5 +- .../AppAssetCheckLayout.tsx | 1 + .../AppAssetCheckLayout/useGetAsset.tsx | 73 +++++++++++-------- .../ChatContainer/ChatContent/ChatContent.tsx | 9 ++- .../ChatContent/ChatMessageBlock.tsx | 4 +- .../ChatResponseMessage_File.tsx | 2 +- .../ChatResponseMessages.tsx | 6 +- .../useSelectedFile/createSelectedFile.ts | 17 ++++- .../useSelectedFile/useSelectedFile.ts | 18 ++++- .../MetricThreeDotMenu.tsx | 2 +- web/src/layouts/ChatLayout/interfaces.ts | 1 + 22 files changed, 167 insertions(+), 101 deletions(-) diff --git a/web/src/api/buster_rest/chats/queryRequests.ts b/web/src/api/buster_rest/chats/queryRequests.ts index 27660c9c4..bf769ed52 100644 --- a/web/src/api/buster_rest/chats/queryRequests.ts +++ b/web/src/api/buster_rest/chats/queryRequests.ts @@ -84,7 +84,10 @@ export const useGetChat = ( if (lastMessage) { Object.values(lastMessage.response_messages).forEach((responseMessage) => { if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') { - prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient); + prefetchGetMetricDataClient( + { id: responseMessage.id, version_number: responseMessage.version_number }, + queryClient + ); } }); } diff --git a/web/src/api/buster_rest/dashboards/queryRequests.ts b/web/src/api/buster_rest/dashboards/queryRequests.ts index b03a4f514..15b7326e9 100644 --- a/web/src/api/buster_rest/dashboards/queryRequests.ts +++ b/web/src/api/buster_rest/dashboards/queryRequests.ts @@ -61,7 +61,10 @@ const useGetDashboardAndInitializeMetrics = () => { const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey); const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric); queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric); - prefetchGetMetricDataClient({ id: metric.id }, queryClient); + prefetchGetMetricDataClient( + { id: metric.id, version_number: metric.version_number }, + queryClient + ); } }); diff --git a/web/src/api/buster_rest/metrics/queryRequests.ts b/web/src/api/buster_rest/metrics/queryRequests.ts index ba4e6a95b..e6dc0bcbd 100644 --- a/web/src/api/buster_rest/metrics/queryRequests.ts +++ b/web/src/api/buster_rest/metrics/queryRequests.ts @@ -34,6 +34,31 @@ import { import { useParams, useSearchParams } from 'next/navigation'; import { useOriginalMetricStore } from '@/context/Metrics/useOriginalMetricStore'; 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. @@ -54,21 +79,7 @@ export const useGetMetric = ( const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError); const { password } = getAssetPassword(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 versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp }); const options = useMemo(() => { return metricsQueryKeys.metricsGetMetric(id!, versionNumber); @@ -78,7 +89,10 @@ export const useGetMetric = ( const result = await getMetric({ id: id!, password, version_number: versionNumber }); const oldMetric = queryClient.getQueryData(options.queryKey); const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null); - setOriginalMetric(updatedMetric); + + const isLatestVersion = + updatedMetric.version_number === last(updatedMetric.versions)?.version_number; + if (isLatestVersion) setOriginalMetric(updatedMetric); return updatedMetric; }); @@ -128,28 +142,13 @@ export const useGetMetricData = ( ) => { const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword); const { password } = getAssetPassword(id!); - + const versionNumber = useGetMetricVersionNumber({ versionNumber: versionNumberProp }); const { isFetched: isFetchedMetric, - error: errorMetric, + isError: isErrorMetric, + dataUpdatedAt, data: fetchedMetricData - } = useGetMetric({ id }, { 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]); - + } = useGetMetric({ id, versionNumber }, { select: (x) => x.id }); const queryFn = useMemoizedFn(() => { return getMetricData({ id: id!, version_number: versionNumber, password }); }); @@ -158,7 +157,7 @@ export const useGetMetricData = ( ...metricsQueryKeys.metricsGetData(id!, versionNumber), queryFn, enabled: () => { - return !!id && isFetchedMetric && !errorMetric && !!fetchedMetricData; + return !!id && isFetchedMetric && !isErrorMetric && !!fetchedMetricData && !!dataUpdatedAt; }, select: params?.select, ...params @@ -166,7 +165,7 @@ export const useGetMetricData = ( }; export const prefetchGetMetricDataClient = async ( - { id, version_number }: { id: string; version_number?: number }, + { id, version_number }: { id: string; version_number: number | undefined }, queryClient: QueryClient ) => { const options = metricsQueryKeys.metricsGetData(id, version_number); diff --git a/web/src/components/ui/charts/BusterChart.tsx b/web/src/components/ui/charts/BusterChart.tsx index 9c779199d..d4182707e 100644 --- a/web/src/components/ui/charts/BusterChart.tsx +++ b/web/src/components/ui/charts/BusterChart.tsx @@ -83,7 +83,10 @@ export const BusterChart: React.FC = React.memo( }); 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 ; } diff --git a/web/src/components/ui/charts/LoadingComponents/ChartLoadingComponents.tsx b/web/src/components/ui/charts/LoadingComponents/ChartLoadingComponents.tsx index 86ba8962f..21b651636 100644 --- a/web/src/components/ui/charts/LoadingComponents/ChartLoadingComponents.tsx +++ b/web/src/components/ui/charts/LoadingComponents/ChartLoadingComponents.tsx @@ -11,7 +11,8 @@ export const PreparingYourRequestLoader: React.FC<{ useShimmer?: boolean; }> = ({ className = '', text = 'Processing your request...', error, useShimmer = true }) => { return ( -
+
{error || useShimmer === false ? ( {error || text} ) : ( diff --git a/web/src/context/Chats/useChatStreamMessage.ts b/web/src/context/Chats/useChatStreamMessage.ts index 6c9453438..8489c171e 100644 --- a/web/src/context/Chats/useChatStreamMessage.ts +++ b/web/src/context/Chats/useChatStreamMessage.ts @@ -71,7 +71,10 @@ export const useChatStreamMessage = () => { if (lastMessage?.response_message_ids) { Object.values(lastMessage.response_messages).forEach((responseMessage) => { if (responseMessage.type === 'file' && responseMessage.file_type === 'metric') { - prefetchGetMetricDataClient({ id: responseMessage.id }, queryClient); + prefetchGetMetricDataClient( + { id: responseMessage.id, version_number: responseMessage.version_number }, + queryClient + ); } }); } diff --git a/web/src/context/Metrics/useIsMetricReadOnly.tsx b/web/src/context/Metrics/useIsMetricReadOnly.tsx index f9816f73f..2d9a5ea43 100644 --- a/web/src/context/Metrics/useIsMetricReadOnly.tsx +++ b/web/src/context/Metrics/useIsMetricReadOnly.tsx @@ -23,7 +23,8 @@ export const useIsMetricReadOnly = ({ enabled: false, select: (x) => ({ permission: x.permission, - versions: x.versions + versions: x.versions, + version_number: x.version_number }) } ); diff --git a/web/src/context/Metrics/useOriginalMetricStore.tsx b/web/src/context/Metrics/useOriginalMetricStore.tsx index caaea85ba..1c31b5b9e 100644 --- a/web/src/context/Metrics/useOriginalMetricStore.tsx +++ b/web/src/context/Metrics/useOriginalMetricStore.tsx @@ -2,11 +2,7 @@ import type { IBusterMetric } from '@/api/asset_interfaces/metric'; import { create } from 'zustand'; -import { compareObjectsByKeys } from '@/lib/objects'; -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'; +import { useMount } from '@/hooks'; type OriginalMetricStore = { originalMetrics: Record; diff --git a/web/src/controllers/DashboardController/DashboardViewDashboardController/DashboardViewDashboardController.tsx b/web/src/controllers/DashboardController/DashboardViewDashboardController/DashboardViewDashboardController.tsx index 691948834..5f3e15da0 100644 --- a/web/src/controllers/DashboardController/DashboardViewDashboardController/DashboardViewDashboardController.tsx +++ b/web/src/controllers/DashboardController/DashboardViewDashboardController/DashboardViewDashboardController.tsx @@ -24,12 +24,11 @@ export const DashboardViewDashboardController: React.FC<{ } = useGetDashboard({ id: dashboardId }); const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig(); - const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode); const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal); const metrics = dashboardResponse?.metrics; const dashboard = dashboardResponse?.dashboard; - const { isReadOnly } = useIsDashboardReadOnly({ + const { isReadOnly, isViewingOldVersion, isVersionHistoryMode } = useIsDashboardReadOnly({ dashboardId, readOnly: readOnlyProp }); @@ -65,7 +64,9 @@ export const DashboardViewDashboardController: React.FC<{ readOnly={isReadOnly} /> - {!isVersionHistoryMode && } + {!isVersionHistoryMode && !isViewingOldVersion && ( + + )}
); diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/MetricStylingApp.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/MetricStylingApp.tsx index a03b16088..f519e976c 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/MetricStylingApp.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricEditController/MetricStylingApp/MetricStylingApp.tsx @@ -22,7 +22,7 @@ export const MetricStylingApp: React.FC<{ MetricStylingAppSegments.VISUALIZE ); 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; diff --git a/web/src/controllers/MetricController/MetricViewChart/MetricViewChart.tsx b/web/src/controllers/MetricController/MetricViewChart/MetricViewChart.tsx index 6548a5b2c..1b4850068 100644 --- a/web/src/controllers/MetricController/MetricViewChart/MetricViewChart.tsx +++ b/web/src/controllers/MetricController/MetricViewChart/MetricViewChart.tsx @@ -33,7 +33,9 @@ export const MetricViewChart: React.FC<{ time_frame, permission, evaluation_score, - evaluation_summary + evaluation_summary, + version_number, + versions }) => ({ name, description, @@ -41,7 +43,9 @@ export const MetricViewChart: React.FC<{ permission, evaluation_score, evaluation_summary, - chart_config + chart_config, + version_number, + versions }) } ); @@ -49,7 +53,7 @@ export const MetricViewChart: React.FC<{ data: metricData, isFetched: isFetchedMetricData, error: metricDataError - } = useGetMetricData({ id: metricId }); + } = useGetMetricData({ id: metricId }, { enabled: false }); const { mutate: updateMetric } = useUpdateMetric({ saveToServer: false @@ -57,7 +61,7 @@ export const MetricViewChart: React.FC<{ const { name, description, time_frame, evaluation_score, evaluation_summary } = metric || {}; const isTable = metric?.chart_config.selectedChartType === ChartType.Table; - const { isReadOnly, isVersionHistoryMode } = useIsMetricReadOnly({ + const { isReadOnly, isVersionHistoryMode, isViewingOldVersion } = useIsMetricReadOnly({ metricId, readOnly: readOnlyProp }); @@ -110,7 +114,9 @@ export const MetricViewChart: React.FC<{ /> - {!isVersionHistoryMode && } + {!isVersionHistoryMode && !isViewingOldVersion && ( + + )}
); } diff --git a/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx b/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx index 2005208dc..8a5ae7a48 100644 --- a/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx +++ b/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx @@ -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 || ''); diff --git a/web/src/layouts/AppAssetCheckLayout/AppAssetCheckLayout.tsx b/web/src/layouts/AppAssetCheckLayout/AppAssetCheckLayout.tsx index 3fdfeaf8a..6f18b5580 100644 --- a/web/src/layouts/AppAssetCheckLayout/AppAssetCheckLayout.tsx +++ b/web/src/layouts/AppAssetCheckLayout/AppAssetCheckLayout.tsx @@ -6,6 +6,7 @@ import { AppPasswordAccess } from '@/controllers/AppPasswordAccess'; import { AppNoPageAccess } from '@/controllers/AppNoPageAccess'; import { useGetAsset } from './useGetAsset'; import { FileIndeterminateLoader } from '@/components/features/FileIndeterminateLoader'; +import { useParams, useSearchParams } from 'next/navigation'; export type AppAssetCheckLayoutProps = { assetId: string; diff --git a/web/src/layouts/AppAssetCheckLayout/useGetAsset.tsx b/web/src/layouts/AppAssetCheckLayout/useGetAsset.tsx index 8685e6fd0..ce6fa44e6 100644 --- a/web/src/layouts/AppAssetCheckLayout/useGetAsset.tsx +++ b/web/src/layouts/AppAssetCheckLayout/useGetAsset.tsx @@ -3,6 +3,8 @@ import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics'; import { useGetDashboard } from '@/api/buster_rest/dashboards'; import { RustApiError } from '@/api/buster_rest/errors'; +import { useSearchParams } from 'next/navigation'; +import { useMemo } from 'react'; interface BaseGetAssetProps { assetId: string; @@ -15,6 +17,7 @@ interface MetricAssetProps extends BaseGetAssetProps { interface DashboardAssetProps extends BaseGetAssetProps { type: 'dashboard'; + versionNumber?: number; } type UseGetAssetProps = MetricAssetProps | DashboardAssetProps; @@ -29,47 +32,55 @@ type UseGetAssetReturn = { }; export const useGetAsset = (props: UseGetAssetProps): UseGetAssetReturn => { + 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 - const { - error: errorMetric, - isError: isErrorMetric, - dataUpdatedAt, - isFetched: isFetchedMetric - } = useGetMetric( + const { error: errorMetric, isFetched: isFetchedMetric } = useGetMetric( { - id: props.assetId, - versionNumber: props.type === 'metric' ? props.versionNumber : undefined + id: props.type === 'metric' ? props.assetId : undefined, + versionNumber }, - { - 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 - } + { enabled: props.type === 'metric' && !!props.assetId } ); + const { isFetched: isFetchedMetricData } = useGetMetricData({ + id: props.assetId, + versionNumber + }); + //dashboard const { isFetched: isFetchedDashboard, error: errorDashboard, isError: isErrorDashboard - } = useGetDashboard( - { - id: props.type === 'dashboard' ? props.assetId : undefined - }, - { enabled: props.type === 'dashboard' && !!props.assetId } - ); + } = useGetDashboard({ + id: props.type === 'dashboard' ? props.assetId : undefined, + versionNumber + }); const { hasAccess, passwordRequired, isPublic } = getAssetAccess({ error: props.type === 'metric' ? errorMetric : errorDashboard diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatContent.tsx b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatContent.tsx index cd877610d..07862d2ae 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatContent.tsx +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatContent.tsx @@ -30,9 +30,14 @@ export const ChatContent: React.FC<{}> = React.memo(() => { return ( <>
- {chatMessageIds?.map((messageId) => ( + {chatMessageIds?.map((messageId, index) => (
- +
))}
diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatMessageBlock.tsx b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatMessageBlock.tsx index 7bef6aa20..6e1dafdf4 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatMessageBlock.tsx +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatMessageBlock.tsx @@ -8,7 +8,8 @@ import { useGetChatMessage } from '@/api/buster_rest/chats'; export const ChatMessageBlock: React.FC<{ messageId: string; chatId: string; -}> = React.memo(({ messageId, chatId }) => { + messageIndex: number; +}> = React.memo(({ messageId, chatId, messageIndex }) => { const messageExists = useGetChatMessage(messageId, (message) => message?.id); const requestMessage = useGetChatMessage(messageId, (message) => message?.request_message); const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream); @@ -29,6 +30,7 @@ export const ChatMessageBlock: React.FC<{ isCompletedStream={isCompletedStream!} messageId={messageId} chatId={chatId} + messageIndex={messageIndex} /> ); diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessage_File/ChatResponseMessage_File.tsx b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessage_File/ChatResponseMessage_File.tsx index 01b0b8624..9919dbb1e 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessage_File/ChatResponseMessage_File.tsx +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessage_File/ChatResponseMessage_File.tsx @@ -34,7 +34,7 @@ export const ChatResponseMessage_File: React.FC = Reac const onLinkClick = useMemoizedFn(() => { if (isSelectedFile) onSetSelectedFile(null); - onSetSelectedFile({ id, type: file_type }); + onSetSelectedFile({ id, type: file_type, versionNumber: responseMessage.version_number }); }); useMount(() => { diff --git a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessages.tsx b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessages.tsx index e15c5c69d..438cea190 100644 --- a/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessages.tsx +++ b/web/src/layouts/ChatLayout/ChatContainer/ChatContent/ChatResponseMessages/ChatResponseMessages.tsx @@ -9,17 +9,19 @@ interface ChatResponseMessagesProps { isCompletedStream: boolean; messageId: string; chatId: string; + messageIndex: number; } export const ChatResponseMessages: React.FC = React.memo( - ({ chatId, isCompletedStream, messageId }) => { + ({ chatId, isCompletedStream, messageId, messageIndex }) => { const responseMessageIds = useGetChatMessage(messageId, (x) => x?.response_message_ids || [])!; const lastReasoningMessageId = useGetChatMessage( messageId, (x) => x?.reasoning_message_ids?.[x.reasoning_message_ids.length - 1] ); const finalReasoningMessage = useGetChatMessage(messageId, (x) => x?.final_reasoning_message); - const showReasoningMessage = !!lastReasoningMessageId || !isCompletedStream; + const showReasoningMessage = + messageIndex === 0 ? !!lastReasoningMessageId || !isCompletedStream : true; return ( diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/createSelectedFile.ts b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/createSelectedFile.ts index 4ac514990..6cb012cc8 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/createSelectedFile.ts +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/createSelectedFile.ts @@ -4,19 +4,30 @@ import { useGetChatParams } from '../useGetChatParams'; export const createSelectedFile = ( params: ReturnType ): SelectedFile | null => { - const { metricId, collectionId, datasetId, dashboardId, chatId, messageId } = params; + const { + metricId, + collectionId, + datasetId, + dashboardId, + chatId, + messageId, + metricVersionNumber, + dashboardVersionNumber + } = params; if (metricId) { return { id: metricId, - type: 'metric' + type: 'metric', + versionNumber: metricVersionNumber }; } if (dashboardId) { return { id: dashboardId, - type: 'dashboard' + type: 'dashboard', + versionNumber: dashboardVersionNumber }; } diff --git a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts index c882a73f6..100199258 100644 --- a/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts +++ b/web/src/layouts/ChatLayout/ChatLayoutContext/useSelectedFile/useSelectedFile.ts @@ -31,8 +31,7 @@ export const useSelectedFile = ({ * @param file */ const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => { - const handleFileCollapse = - !file || (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right')); + const handleFileCollapse = shouldCloseSplitter(file, selectedFile, appSplitterRef); if (file && chatParams.chatId) { const link = createChatAssetRoute({ @@ -61,3 +60,18 @@ export const useSelectedFile = ({ }; export type SelectedFileParams = ReturnType; + +const shouldCloseSplitter = ( + file: SelectedFile | null, + selectedFile: SelectedFile | null, + appSplitterRef: React.RefObject +) => { + 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; +}; diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx index b2a810f60..4eb6fbc7d 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainerHeader/MetricContainerHeaderButtons/MetricThreeDotMenu.tsx @@ -403,7 +403,7 @@ const useSQLEditorSelectMenu = () => { const useDownloadCSVSelectMenu = ({ metricId }: { metricId: string }) => { 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 }); return useMemo( diff --git a/web/src/layouts/ChatLayout/interfaces.ts b/web/src/layouts/ChatLayout/interfaces.ts index 657d13f24..3a18a2354 100644 --- a/web/src/layouts/ChatLayout/interfaces.ts +++ b/web/src/layouts/ChatLayout/interfaces.ts @@ -3,6 +3,7 @@ import type { FileType } from '@/api/asset_interfaces'; export type SelectedFile = { id: string; type: FileType; + versionNumber?: number; }; export type ChatLayoutView = 'chat' | 'file' | 'both';