mirror of https://github.com/buster-so/buster.git
expand logic for auto change layout
This commit is contained in:
parent
0b6707bed3
commit
35f7a7c49d
|
@ -4,7 +4,6 @@ import React from 'react';
|
||||||
import { ShareAssetType, ShareRole } from '@/api/asset_interfaces';
|
import { ShareAssetType, ShareRole } from '@/api/asset_interfaces';
|
||||||
import { Text } from '@/components/ui/typography';
|
import { Text } from '@/components/ui/typography';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { R } from 'node_modules/@tanstack/react-query-devtools/build/modern/ReactQueryDevtools-Cn7cKi7o';
|
|
||||||
|
|
||||||
export const IndividualSharePerson: React.FC<{
|
export const IndividualSharePerson: React.FC<{
|
||||||
name?: string;
|
name?: string;
|
||||||
|
@ -20,8 +19,6 @@ export const IndividualSharePerson: React.FC<{
|
||||||
onUpdateShareRole(email, v);
|
onUpdateShareRole(email, v);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(role, assetType);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-8 items-center justify-between space-x-2 overflow-hidden">
|
<div className="flex h-8 items-center justify-between space-x-2 overflow-hidden">
|
||||||
<div className="flex h-full items-center space-x-1.5 overflow-hidden">
|
<div className="flex h-full items-center space-x-1.5 overflow-hidden">
|
||||||
|
|
|
@ -8,6 +8,7 @@ export const useGetFileLink = () => {
|
||||||
const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber);
|
const dashboardVersionNumber = useChatLayoutContextSelector((x) => x.dashboardVersionNumber);
|
||||||
const metricId = useChatLayoutContextSelector((x) => x.metricId);
|
const metricId = useChatLayoutContextSelector((x) => x.metricId);
|
||||||
const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId);
|
const dashboardId = useChatLayoutContextSelector((x) => x.dashboardId);
|
||||||
|
const messageId = useChatLayoutContextSelector((x) => x.messageId);
|
||||||
|
|
||||||
const getFileLink = useMemoizedFn(
|
const getFileLink = useMemoizedFn(
|
||||||
({
|
({
|
||||||
|
@ -114,12 +115,18 @@ export const useGetFileLink = () => {
|
||||||
versionNumber?: number;
|
versionNumber?: number;
|
||||||
fileType: FileType;
|
fileType: FileType;
|
||||||
fileId: string;
|
fileId: string;
|
||||||
}) => {
|
}): boolean => {
|
||||||
if (fileType === 'metric') {
|
if (fileType === 'metric') {
|
||||||
return versionNumber === metricVersionNumber && fileId === metricId;
|
return versionNumber === metricVersionNumber && fileId === metricId;
|
||||||
} else if (fileType === 'dashboard') {
|
} else if (fileType === 'dashboard') {
|
||||||
return versionNumber === dashboardVersionNumber && fileId === dashboardId;
|
return versionNumber === dashboardVersionNumber && fileId === dashboardId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileType === 'reasoning') {
|
||||||
|
return fileId === messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -136,7 +143,11 @@ export const useGetFileLink = () => {
|
||||||
chatId?: string;
|
chatId?: string;
|
||||||
versionNumber?: number;
|
versionNumber?: number;
|
||||||
useVersionHistoryMode?: boolean;
|
useVersionHistoryMode?: boolean;
|
||||||
}) => {
|
}): {
|
||||||
|
link: string | undefined;
|
||||||
|
isSelected: boolean;
|
||||||
|
selectedVersionNumber: number | undefined;
|
||||||
|
} => {
|
||||||
const link = getFileLink({ fileId, fileType, chatId, versionNumber, useVersionHistoryMode });
|
const link = getFileLink({ fileId, fileType, chatId, versionNumber, useVersionHistoryMode });
|
||||||
const isSelected = getFileIsSelected({ versionNumber, fileType, fileId });
|
const isSelected = getFileIsSelected({ versionNumber, fileType, fileId });
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,6 @@ const useChatIndividualContext = ({
|
||||||
|
|
||||||
useAutoChangeLayout({
|
useAutoChangeLayout({
|
||||||
lastMessageId: currentMessageId,
|
lastMessageId: currentMessageId,
|
||||||
onSetSelectedFile,
|
|
||||||
selectedFileId,
|
selectedFileId,
|
||||||
chatId
|
chatId
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,26 +2,33 @@
|
||||||
|
|
||||||
import { useGetChatMessageMemoized, useGetChatMessage } from '@/api/buster_rest/chats';
|
import { useGetChatMessageMemoized, useGetChatMessage } from '@/api/buster_rest/chats';
|
||||||
import type { SelectedFile } from '../interfaces';
|
import type { SelectedFile } from '../interfaces';
|
||||||
import { useEffect, useRef } from 'react';
|
import { MutableRefObject, useEffect, useRef } from 'react';
|
||||||
import findLast from 'lodash/findLast';
|
import findLast from 'lodash/findLast';
|
||||||
import { BusterChatResponseMessage_file } from '@/api/asset_interfaces/chat';
|
import { BusterChatResponseMessage_file } from '@/api/asset_interfaces/chat';
|
||||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||||
import { useGetFileLink } from '@/context/Assets/useGetFileLink';
|
import { useGetFileLink } from '@/context/Assets/useGetFileLink';
|
||||||
import { useChatLayoutContextSelector } from '../ChatLayoutContext';
|
import { useChatLayoutContextSelector } from '../ChatLayoutContext';
|
||||||
import { usePrevious } from '@/hooks';
|
import { useMemoizedFn, usePrevious } from '@/hooks';
|
||||||
|
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||||
|
|
||||||
export const useAutoChangeLayout = ({
|
export const useAutoChangeLayout = ({
|
||||||
lastMessageId,
|
lastMessageId,
|
||||||
onSetSelectedFile,
|
|
||||||
selectedFileId,
|
selectedFileId,
|
||||||
chatId
|
chatId
|
||||||
}: {
|
}: {
|
||||||
lastMessageId: string;
|
lastMessageId: string;
|
||||||
onSetSelectedFile: (file: SelectedFile) => void;
|
|
||||||
selectedFileId: string | undefined;
|
selectedFileId: string | undefined;
|
||||||
chatId: 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 isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode);
|
||||||
|
const isCompletedStream = useGetChatMessage(lastMessageId, (x) => x?.isCompletedStream);
|
||||||
|
|
||||||
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
|
||||||
const previousLastMessageId = useRef<string | null>(null);
|
const previousLastMessageId = useRef<string | null>(null);
|
||||||
const reasoningMessagesLength = useGetChatMessage(
|
const reasoningMessagesLength = useGetChatMessage(
|
||||||
|
@ -31,26 +38,24 @@ export const useAutoChangeLayout = ({
|
||||||
const getChatMessageMemoized = useGetChatMessageMemoized();
|
const getChatMessageMemoized = useGetChatMessageMemoized();
|
||||||
const { getFileLinkMeta } = useGetFileLink();
|
const { getFileLinkMeta } = useGetFileLink();
|
||||||
|
|
||||||
const isCompletedStream = useGetChatMessage(lastMessageId, (x) => x?.isCompletedStream);
|
|
||||||
const previousIsCompletedStream = usePrevious(isCompletedStream);
|
const previousIsCompletedStream = usePrevious(isCompletedStream);
|
||||||
|
|
||||||
const hasReasoning = !!reasoningMessagesLength;
|
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(() => {
|
useEffect(() => {
|
||||||
|
//this will trigger when the chat is streaming and is has not completed yet (new chat)
|
||||||
if (
|
if (
|
||||||
!isCompletedStream &&
|
!isCompletedStream &&
|
||||||
hasReasoning &&
|
hasReasoning &&
|
||||||
previousLastMessageId.current !== lastMessageId &&
|
previousLastMessageId.current !== lastMessageId &&
|
||||||
chatId
|
chatId
|
||||||
) {
|
) {
|
||||||
onSetSelectedFile({ id: lastMessageId, type: 'reasoning' });
|
handle_isStreaming({ previousLastMessageId, onSetSelectedFile, lastMessageId });
|
||||||
previousLastMessageId.current = lastMessageId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//we check for false because on initial load, the isCompletedStream is false
|
//this will when the chat is completed and it WAS streaming
|
||||||
if (isCompletedStream && previousIsCompletedStream === false) {
|
else if (isCompletedStream && previousIsCompletedStream === false) {
|
||||||
|
//
|
||||||
const chatMessage = getChatMessageMemoized(lastMessageId);
|
const chatMessage = getChatMessageMemoized(lastMessageId);
|
||||||
const lastFileId = findLast(chatMessage?.response_message_ids, (id) => {
|
const lastFileId = findLast(chatMessage?.response_message_ids, (id) => {
|
||||||
const responseMessage = chatMessage?.response_messages[id];
|
const responseMessage = chatMessage?.response_messages[id];
|
||||||
|
@ -60,6 +65,7 @@ export const useAutoChangeLayout = ({
|
||||||
| BusterChatResponseMessage_file
|
| BusterChatResponseMessage_file
|
||||||
| undefined;
|
| undefined;
|
||||||
|
|
||||||
|
//this will trigger when the chat was streaming (new chat)
|
||||||
if (lastFileId && lastFile) {
|
if (lastFileId && lastFile) {
|
||||||
const { link, isSelected, selectedVersionNumber } = getFileLinkMeta({
|
const { link, isSelected, selectedVersionNumber } = getFileLinkMeta({
|
||||||
fileId: lastFileId,
|
fileId: lastFileId,
|
||||||
|
@ -76,14 +82,115 @@ export const useAutoChangeLayout = ({
|
||||||
) {
|
) {
|
||||||
onSetSelectedFile({
|
onSetSelectedFile({
|
||||||
id: lastFileId,
|
id: lastFileId,
|
||||||
type: lastFile.file_type
|
type: lastFile.file_type,
|
||||||
|
versionNumber: selectedVersionNumber
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (link && !selectedVersionNumber && !isVersionHistoryMode) {
|
if (link) {
|
||||||
onChangePage(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]);
|
}, [isCompletedStream, hasReasoning, lastMessageId]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handle_isStreaming = ({
|
||||||
|
previousLastMessageId,
|
||||||
|
onSetSelectedFile,
|
||||||
|
lastMessageId
|
||||||
|
}: {
|
||||||
|
previousLastMessageId: MutableRefObject<string | null>;
|
||||||
|
onSetSelectedFile: (file: SelectedFile) => void;
|
||||||
|
lastMessageId: string;
|
||||||
|
}) => {
|
||||||
|
previousLastMessageId.current = lastMessageId;
|
||||||
|
onSetSelectedFile({ id: lastMessageId, type: 'reasoning', versionNumber: undefined });
|
||||||
|
};
|
||||||
|
|
|
@ -3,7 +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;
|
versionNumber: number | undefined; // will be undefined for reasoning files
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChatLayoutView = 'chat' | 'file' | 'both';
|
export type ChatLayoutView = 'chat' | 'file' | 'both';
|
||||||
|
|
Loading…
Reference in New Issue