From 35f7a7c49dce2e39d5d0408ac0594bf986a1ef92 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Mon, 14 Apr 2025 14:03:51 -0600 Subject: [PATCH] expand logic for auto change layout --- .../ShareMenu/IndividualSharePerson.tsx | 3 - web/src/context/Assets/useGetFileLink.tsx | 15 +- .../ChatLayout/ChatContext/ChatContext.tsx | 1 - .../ChatContext/useAutoChangeLayout.ts | 133 ++++++++++++++++-- web/src/layouts/ChatLayout/interfaces.ts | 2 +- 5 files changed, 134 insertions(+), 20 deletions(-) diff --git a/web/src/components/features/ShareMenu/IndividualSharePerson.tsx b/web/src/components/features/ShareMenu/IndividualSharePerson.tsx index 9967bb978..ec8f890e9 100644 --- a/web/src/components/features/ShareMenu/IndividualSharePerson.tsx +++ b/web/src/components/features/ShareMenu/IndividualSharePerson.tsx @@ -4,7 +4,6 @@ import React from 'react'; import { ShareAssetType, ShareRole } from '@/api/asset_interfaces'; import { Text } from '@/components/ui/typography'; import { useMemoizedFn } from '@/hooks'; -import { R } from 'node_modules/@tanstack/react-query-devtools/build/modern/ReactQueryDevtools-Cn7cKi7o'; export const IndividualSharePerson: React.FC<{ name?: string; @@ -20,8 +19,6 @@ export const IndividualSharePerson: React.FC<{ onUpdateShareRole(email, v); }); - console.log(role, assetType); - return (
diff --git a/web/src/context/Assets/useGetFileLink.tsx b/web/src/context/Assets/useGetFileLink.tsx index 165a51f8a..03197cd35 100644 --- a/web/src/context/Assets/useGetFileLink.tsx +++ b/web/src/context/Assets/useGetFileLink.tsx @@ -8,6 +8,7 @@ export const useGetFileLink = () => { const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber); const metricId = useChatLayoutContextSelector((x) => x.metricId); const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId); + const messageId = useChatLayoutContextSelector((x) => x.messageId); const getFileLink = useMemoizedFn( ({ @@ -114,12 +115,18 @@ export const useGetFileLink = () => { versionNumber?: number; fileType: FileType; fileId: string; - }) => { + }): boolean => { if (fileType === 'metric') { return versionNumber === metricVersionNumber && fileId === metricId; } else if (fileType === 'dashboard') { return versionNumber === dashboardVersionNumber && fileId === dashboardId; } + + if (fileType === 'reasoning') { + return fileId === messageId; + } + + return false; } ); @@ -136,7 +143,11 @@ export const useGetFileLink = () => { chatId?: string; versionNumber?: number; useVersionHistoryMode?: boolean; - }) => { + }): { + link: string | undefined; + isSelected: boolean; + selectedVersionNumber: number | undefined; + } => { const link = getFileLink({ fileId, fileType, chatId, versionNumber, useVersionHistoryMode }); const isSelected = getFileIsSelected({ versionNumber, fileType, fileId }); diff --git a/web/src/layouts/ChatLayout/ChatContext/ChatContext.tsx b/web/src/layouts/ChatLayout/ChatContext/ChatContext.tsx index c62d97620..dc62599b0 100644 --- a/web/src/layouts/ChatLayout/ChatContext/ChatContext.tsx +++ b/web/src/layouts/ChatLayout/ChatContext/ChatContext.tsx @@ -50,7 +50,6 @@ const useChatIndividualContext = ({ useAutoChangeLayout({ lastMessageId: currentMessageId, - onSetSelectedFile, selectedFileId, chatId }); diff --git a/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts b/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts index 7e1921a01..65b1f7600 100644 --- a/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts +++ b/web/src/layouts/ChatLayout/ChatContext/useAutoChangeLayout.ts @@ -2,26 +2,33 @@ import { useGetChatMessageMemoized, useGetChatMessage } from '@/api/buster_rest/chats'; import type { SelectedFile } from '../interfaces'; -import { useEffect, useRef } from 'react'; +import { MutableRefObject, useEffect, useRef } from 'react'; import findLast from 'lodash/findLast'; import { BusterChatResponseMessage_file } from '@/api/asset_interfaces/chat'; import { useAppLayoutContextSelector } from '@/context/BusterAppLayout'; import { useGetFileLink } from '@/context/Assets/useGetFileLink'; import { useChatLayoutContextSelector } from '../ChatLayoutContext'; -import { usePrevious } from '@/hooks'; +import { useMemoizedFn, usePrevious } from '@/hooks'; +import { BusterRoutes, createBusterRoute } from '@/routes'; export const useAutoChangeLayout = ({ lastMessageId, - onSetSelectedFile, selectedFileId, chatId }: { lastMessageId: string; - onSetSelectedFile: (file: SelectedFile) => void; selectedFileId: string | undefined; chatId: string | undefined; }) => { + const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile); + const messageId = useChatLayoutContextSelector((x) => x.messageId); + const metricId = useChatLayoutContextSelector((x) => x.metricId); + const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId); + const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber); + const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber); const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode); + const isCompletedStream = useGetChatMessage(lastMessageId, (x) => x?.isCompletedStream); + const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage); const previousLastMessageId = useRef(null); const reasoningMessagesLength = useGetChatMessage( @@ -31,26 +38,24 @@ export const useAutoChangeLayout = ({ const getChatMessageMemoized = useGetChatMessageMemoized(); const { getFileLinkMeta } = useGetFileLink(); - const isCompletedStream = useGetChatMessage(lastMessageId, (x) => x?.isCompletedStream); const previousIsCompletedStream = usePrevious(isCompletedStream); const hasReasoning = !!reasoningMessagesLength; - //change the page to reasoning file if we get a reasoning message - //change the page to the file if we get a file useEffect(() => { + //this will trigger when the chat is streaming and is has not completed yet (new chat) if ( !isCompletedStream && hasReasoning && previousLastMessageId.current !== lastMessageId && chatId ) { - onSetSelectedFile({ id: lastMessageId, type: 'reasoning' }); - previousLastMessageId.current = lastMessageId; + handle_isStreaming({ previousLastMessageId, onSetSelectedFile, lastMessageId }); } - //we check for false because on initial load, the isCompletedStream is false - if (isCompletedStream && previousIsCompletedStream === false) { + //this will when the chat is completed and it WAS streaming + else if (isCompletedStream && previousIsCompletedStream === false) { + // const chatMessage = getChatMessageMemoized(lastMessageId); const lastFileId = findLast(chatMessage?.response_message_ids, (id) => { const responseMessage = chatMessage?.response_messages[id]; @@ -60,6 +65,7 @@ export const useAutoChangeLayout = ({ | BusterChatResponseMessage_file | undefined; + //this will trigger when the chat was streaming (new chat) if (lastFileId && lastFile) { const { link, isSelected, selectedVersionNumber } = getFileLinkMeta({ fileId: lastFileId, @@ -76,14 +82,115 @@ export const useAutoChangeLayout = ({ ) { onSetSelectedFile({ id: lastFileId, - type: lastFile.file_type + type: lastFile.file_type, + versionNumber: selectedVersionNumber }); } - if (link && !selectedVersionNumber && !isVersionHistoryMode) { + if (link) { onChangePage(link); } + return; + } + } + //this will trigger on a page refresh and the chat is completed + else if (isCompletedStream && chatId) { + const isChatOnlyMode = !metricId && !dashboardId && !messageId; + if (isChatOnlyMode) { + return; + } + + const chatMessage = getChatMessageMemoized(lastMessageId); + + //reasoning_message_mode + if (messageId) { + const messageExists = !!chatMessage?.reasoning_message_ids.find((id) => id === messageId); + if (messageExists) { + return; + } else { + onChangePage( + createBusterRoute({ + route: BusterRoutes.APP_CHAT_ID, + chatId + }) + ); + } + } + + //dashboard_mode + if (dashboardId) { + if (!dashboardVersionNumber) { + const lastMatchingDashboardInChat = chatMessage?.response_message_ids.reduce< + BusterChatResponseMessage_file | undefined + >((acc, messageId) => { + const message = chatMessage?.response_messages[messageId]!; + const isFile = + message.type === 'file' && + message.file_type === 'dashboard' && + message.id === dashboardId; + if (isFile) { + return message; + } + return acc; + }, undefined); + + if (lastMatchingDashboardInChat) { + onChangePage( + createBusterRoute({ + route: BusterRoutes.APP_CHAT_ID_DASHBOARD_ID_VERSION_NUMBER, + dashboardId: lastMatchingDashboardInChat.id, + versionNumber: lastMatchingDashboardInChat.version_number, + chatId + }) + ); + } + } else { + return; + } + } + + //metric_mode + if (metricId) { + if (!metricVersionNumber) { + const lastMatchingMetricInChat = chatMessage?.response_message_ids.reduce< + BusterChatResponseMessage_file | undefined + >((acc, messageId) => { + const message = chatMessage?.response_messages[messageId]!; + const isFile = + message.type === 'file' && message.file_type === 'metric' && message.id === metricId; + if (isFile) { + return message; + } + return acc; + }, undefined); + + if (lastMatchingMetricInChat) { + onChangePage( + createBusterRoute({ + route: BusterRoutes.APP_CHAT_ID_METRIC_ID_VERSION_NUMBER, + metricId, + versionNumber: lastMatchingMetricInChat.version_number, + chatId + }) + ); + } + } else { + return; + } } } }, [isCompletedStream, hasReasoning, lastMessageId]); }; + +const handle_isStreaming = ({ + previousLastMessageId, + onSetSelectedFile, + lastMessageId +}: { + previousLastMessageId: MutableRefObject; + onSetSelectedFile: (file: SelectedFile) => void; + lastMessageId: string; +}) => { + previousLastMessageId.current = lastMessageId; + onSetSelectedFile({ id: lastMessageId, type: 'reasoning', versionNumber: undefined }); +}; diff --git a/web/src/layouts/ChatLayout/interfaces.ts b/web/src/layouts/ChatLayout/interfaces.ts index 3a18a2354..d54dcd666 100644 --- a/web/src/layouts/ChatLayout/interfaces.ts +++ b/web/src/layouts/ChatLayout/interfaces.ts @@ -3,7 +3,7 @@ import type { FileType } from '@/api/asset_interfaces'; export type SelectedFile = { id: string; type: FileType; - versionNumber?: number; + versionNumber: number | undefined; // will be undefined for reasoning files }; export type ChatLayoutView = 'chat' | 'file' | 'both';