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';