update how we pass around on click events

This commit is contained in:
Nate Kelley 2025-03-29 17:37:22 -06:00
parent 34c6f6840f
commit ab58050270
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
34 changed files with 167 additions and 116 deletions

View File

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

View File

@ -54,6 +54,7 @@ const useGetDashboardAndInitializeMetrics = () => {
const prevMetric = queryClient.getQueryData(queryKeys.metricsGetMetric(metric.id).queryKey);
const upgradedMetric = upgradeMetricToIMetric(metric, prevMetric);
queryClient.setQueryData(queryKeys.metricsGetMetric(metric.id).queryKey, upgradedMetric);
console.log('prefetching metric', metric.id);
prefetchGetMetricDataClient({ id: metric.id }, queryClient);
}
});

View File

@ -3,6 +3,9 @@ import { upgradeMetricToIMetric } from '@/lib/metrics';
import { QueryClient } from '@tanstack/react-query';
import { getMetric_server, listMetrics, listMetrics_server } from './requests';
/*
*/
export const prefetchGetMetric = async (
params: Parameters<typeof getMetric_server>[0],
queryClientProp?: QueryClient

View File

@ -22,7 +22,6 @@ import { useBusterAssetsContextSelector } from '@/context/Assets/BusterAssetsPro
import { useGetUserFavorites } from '../users';
import type { IBusterMetric } from '@/api/asset_interfaces/metric';
import { create } from 'mutative';
import { isServer } from '@tanstack/react-query';
import {
useAddAssetToCollection,
useRemoveAssetFromCollection
@ -106,7 +105,6 @@ export const useGetMetricData = ({
version_number?: number;
}) => {
const searchParams = useSearchParams();
const queryClient = useQueryClient();
const queryVersionNumber = searchParams.get('metric_version_number');
const version_number = useMemo(() => {
@ -114,12 +112,9 @@ export const useGetMetricData = ({
}, [version_number_prop, queryVersionNumber]);
const queryFn = useMemoizedFn(() => {
console.log('hit!', isServer, metricsQueryKeys.metricsGetData(id, version_number).queryKey);
return getMetricData({ id, version_number });
});
console.log('data here!');
return useQuery({
...metricsQueryKeys.metricsGetData(id, version_number),
queryFn

View File

@ -1,8 +1,11 @@
'use server';
import { MetricController } from '@/controllers/MetricController';
import { AppAssetCheckLayout } from '@/layouts/AppAssetCheckLayout';
export default async function MetricPage(props: { params: Promise<{ metricId: string }> }) {
const [params] = await Promise.all([props.params]);
const params = await props.params;
const { metricId } = params;
return (

View File

@ -34,7 +34,7 @@ export default function Page({
const onClearSelectedDataSource = useMemoizedFn(() => {
setSelectedDataSource(null);
onChangePage(createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD }));
onChangePage({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD });
});
useEffect(() => {

View File

@ -55,7 +55,7 @@ export const NewDatasetModal: React.FC<{
});
const onAddDataSourceClick = useMemoizedFn(() => {
onChangePage(createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD }));
onChangePage({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD });
setTimeout(() => {
onClose();
}, 450);

View File

@ -38,7 +38,6 @@ export const VersionHistoryPanel = React.memo(
return (
<AppPageLayout
headerClassName="border-l"
header={useMemo(
() => (
<PanelHeader removeVersionHistoryQueryParams={removeVersionHistoryQueryParams} />

View File

@ -40,10 +40,7 @@ export const AppPageLayout: React.FC<
)}>
{header && (
<AppPageLayoutHeader
className={cn(
headerBorderVariant === 'ghost' && 'relative z-10 -mt-[1px]',
headerClassName
)}
className={cn(headerBorderVariant === 'ghost' && '-mt-[0.5px]', headerClassName)}
sizeVariant={headerSizeVariant}
borderVariant={headerBorderVariant}>
{header}

View File

@ -3,7 +3,7 @@ import React from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
const headerVariants = cva(
'bg-page-background flex max-h-[38px] min-h-[38px] items-center z-10 justify-between gap-x-2.5 relative',
'bg-page-background flex max-h-[38px] min-h-[38px] items-center justify-between gap-x-2.5 relative',
{
variants: {
sizeVariant: {

View File

@ -48,8 +48,7 @@ export const Default: Story = {
args: {
isSelectedFile: false,
isCompletedStream: true,
responseMessage: mockResponseMessage,
onClick: fn()
responseMessage: mockResponseMessage
}
};
@ -57,8 +56,7 @@ export const Selected: Story = {
args: {
isSelectedFile: true,
isCompletedStream: true,
responseMessage: mockResponseMessage,
onClick: fn()
responseMessage: mockResponseMessage
}
};
@ -66,8 +64,7 @@ export const Streaming: Story = {
args: {
isSelectedFile: false,
isCompletedStream: false,
responseMessage: mockResponseMessage,
onClick: fn()
responseMessage: mockResponseMessage
}
};
@ -78,7 +75,6 @@ export const LongFileName: Story = {
responseMessage: {
...mockResponseMessage,
file_name: 'very_long_file_name_that_should_truncate_in_the_ui.txt'
},
onClick: fn()
}
}
};

View File

@ -12,10 +12,9 @@ import { cn } from '@/lib/classMerge';
export const StreamingMessage_File: React.FC<{
isSelectedFile: boolean;
onClick: () => void;
responseMessage: BusterChatResponseMessage_file;
isCompletedStream: boolean;
}> = React.memo(({ isCompletedStream, responseMessage, onClick, isSelectedFile }) => {
}> = React.memo(({ isCompletedStream, responseMessage, isSelectedFile }) => {
const {
file_name,
version_number,
@ -28,7 +27,6 @@ export const StreamingMessage_File: React.FC<{
<motion.div
id={id}
{...itemAnimationConfig}
onClick={onClick}
className={cn(
'border-border hover:border-text-tertiary flex cursor-pointer flex-col items-center overflow-hidden rounded border transition-all duration-200 hover:shadow',
isSelectedFile && 'border-black shadow'

View File

@ -23,7 +23,7 @@ import {
} from './chatStreamMessageHelper';
import { useGetChatMemoized } from '@/api/buster_rest/chats';
import { useChatUpdate } from './useChatUpdate';
import { prefetchGetMetricDataClient } from '@/api/buster_rest/metrics';
import { prefetchGetMetricDataClient, prefetchGetMetric } from '@/api/buster_rest/metrics';
export const useChatStreamMessage = () => {
const queryClient = useQueryClient();
@ -62,7 +62,20 @@ export const useChatStreamMessage = () => {
const queryKey = options.queryKey;
queryClient.setQueryData(queryKey, message);
chatRefMessages.current[message.id] = message;
prefetchGetMetricDataClient({ id: message.id }, queryClient);
}
}
);
const prefetchLastMessageMetricData = useMemoizedFn(
(iChat: IBusterChat, iChatMessages: Record<string, IBusterChatMessage>) => {
const lastMessageId = iChat.message_ids[iChat.message_ids.length - 1];
const lastMessage = iChatMessages[lastMessageId];
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);
}
});
}
}
);
@ -73,6 +86,7 @@ export const useChatStreamMessage = () => {
normalizeChatMessage(iChatMessages);
onUpdateChat(iChat);
removeBlackBoxMessage({ messageId: iChat.message_ids[iChat.message_ids.length - 1] });
prefetchLastMessageMetricData(iChat, iChatMessages);
});
const stopChatCallback = useMemoizedFn((chatId: string) => {

View File

@ -10,6 +10,11 @@ import { FileIndeterminateLoader } from '@/components/features/FileIndeterminate
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
import { MetricViewError } from './MetricViewError';
/*
TODO: consider makiing this a server component that fetches the metric and metric data?
As long as we have a loading.tsx component that can handle the loading state, this should work?
*/
export const MetricController: React.FC<{
metricId: string;
}> = React.memo(({ metricId }) => {

View File

@ -1,5 +1,4 @@
import React from 'react';
import { Text, Title } from '@/components/ui/typography';
import { StatusCard } from '@/components/ui/card/StatusCard';
export const MetricViewError: React.FC<{ error: string | undefined }> = ({

View File

@ -13,7 +13,6 @@ interface ReasoningControllerProps {
export const ReasoningController: React.FC<ReasoningControllerProps> = ({ chatId, messageId }) => {
const { data: hasChat } = useGetChat({ id: chatId || '' }, (x) => !!x.id);
const reasoningMessageIds = useGetChatMessage(messageId, (x) => x?.reasoning_message_ids);
const isCompletedStream = useGetChatMessage(messageId, (x) => x?.isCompletedStream);

View File

@ -2,31 +2,46 @@ import type { FileType } from '@/api/asset_interfaces';
import { AppTooltip } from '@/components/ui/tooltip';
import { ArrowUpRight } from '@/components/ui/icons';
import { Button } from '@/components/ui/buttons';
import React from 'react';
import React, { useMemo } from 'react';
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout/ChatLayoutContext';
import { useMemoizedFn } from '@/hooks';
import Link from 'next/link';
import { createChatAssetRoute } from '@/layouts/ChatLayout/ChatLayoutContext/helpers';
export const ReasoningFileButtons = React.memo(
({ fileType, fileId, type }: { fileType: FileType; fileId: string; type: 'file' | 'status' }) => {
const onSetSelectedFile = useChatLayoutContextSelector((state) => state.onSetSelectedFile);
const onOpenFile = useMemoizedFn((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
e.stopPropagation();
onSetSelectedFile({
id: fileId,
({
fileType,
fileId,
type,
chatId
}: {
fileType: FileType;
fileId: string;
type: 'file' | 'status';
chatId: string;
}) => {
const href = useMemo(() => {
return createChatAssetRoute({
chatId: chatId,
assetId: fileId,
type: fileType
});
});
}, [chatId, fileId, fileType]);
if (type === 'status') return null;
return (
<div>
<AppTooltip title="Open file" sideOffset={12}>
<Button onClick={onOpenFile} variant="ghost" prefix={<ArrowUpRight />}></Button>
</AppTooltip>
</div>
<AppTooltip title="Open file" sideOffset={12}>
<Link
href={href || ''}
prefetch
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}>
<Button variant="ghost" prefix={<ArrowUpRight />} />
</Link>
</AppTooltip>
);
}
);

View File

@ -37,7 +37,7 @@ export const ReasoningMessage_File: React.FC<ReasoningMessageFileProps> = React.
const buttons = !isCompletedStream ? (
<StreamingMessageStatus status={status} />
) : (
<ReasoningFileButtons fileType={file_type} fileId={version_id} type="file" />
<ReasoningFileButtons fileType={file_type} chatId={chatId} fileId={version_id} type="file" />
);
return (

View File

@ -6,13 +6,18 @@ import { ReasoningMessagePills } from './ReasoningMessagePills';
export const ReasoningMessagePillContainer: React.FC<{
pillContainer: BusterChatMessageReasoning_pillContainer;
isCompletedStream: boolean;
}> = React.memo(({ pillContainer, isCompletedStream }) => {
chatId: string;
}> = React.memo(({ pillContainer, isCompletedStream, chatId }) => {
return (
<div className="flex flex-col space-y-1">
<Text size="xs" variant="tertiary">
{pillContainer.title}
</Text>
<ReasoningMessagePills pills={pillContainer.pills} isCompletedStream={isCompletedStream} />
<ReasoningMessagePills
chatId={chatId}
pills={pillContainer.pills}
isCompletedStream={isCompletedStream}
/>
</div>
);
});

View File

@ -1,14 +1,11 @@
import type { BusterChatMessageReasoning_pill } from '@/api/asset_interfaces/chat';
import React, { useMemo } from 'react';
import type { BusterChatMessageReasoning_pill, FileType } from '@/api/asset_interfaces/chat';
import React from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { useMemoizedFn } from '@/hooks';
import { Popover } from '@/components/ui/tooltip/Popover';
import {
isOpenableFile,
useChatLayoutContextSelector
} from '@/layouts/ChatLayout/ChatLayoutContext';
import { type SelectedFile } from '@/layouts/ChatLayout/interfaces';
import { cn } from '@/lib/classMerge';
import Link from 'next/link';
import { createChatAssetRoute } from '@/layouts/ChatLayout/ChatLayoutContext/helpers';
const duration = 0.25;
@ -44,24 +41,19 @@ const pillVariants = {
export const ReasoningMessagePills: React.FC<{
pills: BusterChatMessageReasoning_pill[];
isCompletedStream: boolean;
}> = React.memo(({ pills = [], isCompletedStream }) => {
const onSetSelectedFile = useChatLayoutContextSelector((x) => x.onSetSelectedFile);
chatId: string;
}> = React.memo(({ pills = [], isCompletedStream, chatId }) => {
const useAnimation = !isCompletedStream;
const handlePillClick = useMemoizedFn(
(pill: Pick<BusterChatMessageReasoning_pill, 'id' | 'type'>) => {
if (isOpenableFile(pill.type)) {
onSetSelectedFile(pill as SelectedFile);
}
}
);
const isClickablePill = useMemo(() => {
return pills.some((pill) => isOpenableFile(pill.type));
}, [pills]);
const onClick = isClickablePill ? handlePillClick : undefined;
const makeHref = useMemoizedFn((pill: Pick<BusterChatMessageReasoning_pill, 'id' | 'type'>) => {
const link = createChatAssetRoute({
chatId: chatId,
assetId: pill.id,
type: pill.type as FileType
});
if (link) return link;
return '';
});
return (
<AnimatePresence initial={!isCompletedStream}>
@ -71,7 +63,9 @@ export const ReasoningMessagePills: React.FC<{
animate={pills.length > 0 ? 'visible' : 'hidden'}
className={'flex w-full flex-wrap gap-1.5 overflow-hidden'}>
{pills.map((pill) => (
<Pill key={pill.id} useAnimation={useAnimation} {...pill} onClick={onClick} />
<Link href={makeHref(pill)}>
<Pill key={pill.id} useAnimation={useAnimation} {...pill} />
</Link>
))}
</motion.div>
</AnimatePresence>

View File

@ -78,6 +78,8 @@ const InteractiveLoadingWrapper = () => {
setPillContainers([...pillContainers, newContainer]);
};
const chatId = '123';
const message: BusterChatMessageReasoning_pills = {
...mockReasoningMessage,
status: 'loading',
@ -89,7 +91,7 @@ const InteractiveLoadingWrapper = () => {
<Button onClick={addNewContainer} variant="default">
Add New Container
</Button>
<ReasoningMessagePillsContainer {...message} isCompletedStream={false} />
<ReasoningMessagePillsContainer {...message} chatId={chatId} isCompletedStream={false} />
</div>
);
};

View File

@ -32,8 +32,9 @@ export const ReasoningMessagePillsContainer: React.FC<
BusterChatMessageReasoning_pills & {
status: NonNullable<BusterChatMessageReasoning_pills['status']>;
isCompletedStream: boolean;
chatId: string;
}
> = ({ pill_containers, status, isCompletedStream }) => {
> = ({ pill_containers, status, isCompletedStream, chatId }) => {
const hasPills = !!pill_containers && pill_containers.length > 0;
if (!hasPills) return null;
@ -50,6 +51,7 @@ export const ReasoningMessagePillsContainer: React.FC<
key={index}
pillContainer={pill_container}
isCompletedStream={isCompletedStream}
chatId={chatId}
/>
</motion.div>
))}

View File

@ -5,7 +5,7 @@ import { useGetChatMessage } from '@/api/buster_rest/chats';
import { ReasoningMessagePillsContainer } from './ReasoningMessagePillsContainer';
export const ReasoningMessage_PillsContainer: React.FC<ReasoningMessageProps> = React.memo(
({ reasoningMessageId, messageId, isCompletedStream }) => {
({ reasoningMessageId, messageId, isCompletedStream, chatId }) => {
const reasoningMessage = useGetChatMessage(
messageId,
(x) => x?.reasoning_messages[reasoningMessageId]
@ -19,6 +19,7 @@ export const ReasoningMessage_PillsContainer: React.FC<ReasoningMessageProps> =
{...reasoningMessagePills}
status={status}
isCompletedStream={isCompletedStream}
chatId={chatId}
/>
);
}

View File

@ -1,10 +1,11 @@
'use server';
import React from 'react';
import { ShareAssetType } from '@/api/asset_interfaces';
import { AppPasswordAccess } from '@/controllers/AppPasswordAccess';
import { AppNoPageAccess } from '@/controllers/AppNoPageAccess';
import { prefetchAssetCheck } from '@/api/buster_rest/assets';
import { dehydrate, HydrationBoundary } from '@tanstack/react-query';
import { queryKeys } from '@/api/query_keys';
export type AppAssetCheckLayoutProps = {
assetId: string;

View File

@ -55,13 +55,6 @@ export const ChatResponseMessage_File: React.FC<ChatResponseMessageProps> = Reac
return '';
}, [chatId, file_type, id]);
const onClick = useMemoizedFn(() => {
onSetSelectedFile({
id,
type: file_type
});
});
useMount(() => {
if (href) {
router.prefetch(href);
@ -69,11 +62,10 @@ export const ChatResponseMessage_File: React.FC<ChatResponseMessageProps> = Reac
});
return (
<Link href={href} prefetch>
<Link href={href} prefetch onClick={() => onSetSelectedFile({ id, type: file_type })}>
<StreamingMessage_File
isCompletedStream={isCompletedStream}
responseMessage={responseMessage}
onClick={onClick}
isSelectedFile={isSelectedFile}
/>
</Link>

View File

@ -27,6 +27,7 @@ export const ChatResponseMessages: React.FC<ChatResponseMessagesProps> = React.m
finalReasoningMessage={finalReasoningMessage}
isCompletedStream={isCompletedStream}
messageId={messageId}
chatId={chatId}
/>
{responseMessageIds.map((responseMessageId, index) => (

View File

@ -10,6 +10,8 @@ import { useChatLayoutContextSelector } from '../../../ChatLayoutContext';
import { useGetChatMessage } from '@/api/buster_rest/chats';
import { useQuery } from '@tanstack/react-query';
import { queryKeys } from '@/api/query_keys';
import Link from 'next/link';
import { BusterRoutes, createBusterRoute } from '@/routes';
const animations = {
initial: { opacity: 0 },
@ -23,7 +25,8 @@ export const ChatResponseReasoning: React.FC<{
finalReasoningMessage: string | undefined | null;
isCompletedStream: boolean;
messageId: string;
}> = React.memo(({ reasoningMessageId, isCompletedStream, messageId }) => {
chatId: string;
}> = React.memo(({ reasoningMessageId, isCompletedStream, messageId, chatId }) => {
const lastMessageTitle = useGetChatMessage(
messageId,
(x) => x?.reasoning_messages?.[reasoningMessageId ?? '']?.title
@ -46,29 +49,31 @@ export const ChatResponseReasoning: React.FC<{
return lastMessageTitle || 'Thinking...';
}, [lastMessageTitle, finalReasoningMessage, blackBoxMessage]);
const onClickReasoning = useMemoizedFn(() => {
onSetSelectedFile({
type: 'reasoning',
id: messageId
const href = useMemo(() => {
return createBusterRoute({
route: BusterRoutes.APP_CHAT_ID_REASONING_ID,
messageId,
chatId
});
});
}, [isReasonginFileSelected, messageId]);
return (
<AnimatePresence initial={!isCompletedStream} mode="wait">
<motion.div
{...animations}
key={text}
className="mb-3.5 flex h-[14px] max-h-[14px] w-fit cursor-pointer items-center"
onClick={onClickReasoning}>
{!showShimmerText ? (
<Text variant={'secondary'} className="hover:text-text-default hover:underline">
{text}
</Text>
) : (
<ShimmerText text={text ?? ''} />
)}
</motion.div>
</AnimatePresence>
<Link href={href}>
<AnimatePresence initial={!isCompletedStream} mode="wait">
<motion.div
{...animations}
key={text}
className="mb-3.5 flex h-[14px] max-h-[14px] w-fit cursor-pointer items-center">
{!showShimmerText ? (
<Text variant={'secondary'} className="hover:text-text-default hover:underline">
{text}
</Text>
) : (
<ShimmerText text={text ?? ''} />
)}
</motion.div>
</AnimatePresence>
</Link>
);
});

View File

@ -28,7 +28,7 @@ export const ChatContainerHeaderDropdown: React.FC<{
chatId &&
deleteChat([chatId], {
onSuccess: () => {
onChangePage(createBusterRoute({ route: BusterRoutes.APP_CHAT }));
onChangePage({ route: BusterRoutes.APP_CHAT });
}
})
},

View File

@ -50,7 +50,8 @@ const useChatIndividualContext = ({
useAutoChangeLayout({
lastMessageId: currentMessageId,
onSetSelectedFile,
selectedFileId
selectedFileId,
chatId
});
return React.useMemo(

View File

@ -5,15 +5,19 @@ import type { SelectedFile } from '../interfaces';
import { useEffect, useRef } from 'react';
import findLast from 'lodash/findLast';
import { BusterChatResponseMessage_file } from '@/api/asset_interfaces/chat';
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
import { BusterRoutes } from '@/routes';
export const useAutoChangeLayout = ({
lastMessageId,
onSetSelectedFile,
selectedFileId
selectedFileId,
chatId
}: {
lastMessageId: string;
onSetSelectedFile: (file: SelectedFile) => void;
selectedFileId: string | undefined;
chatId: string | undefined;
}) => {
const previousLastMessageId = useRef<string | null>(null);
const reasoningMessagesLength = useGetChatMessage(
@ -27,9 +31,12 @@ export const useAutoChangeLayout = ({
//change the page to reasoning file if we get a reasoning message
useEffect(() => {
// console.log(isCompletedStream, hasReasoning, lastMessageId, previousLastMessageId.current);
if (!isCompletedStream && hasReasoning && previousLastMessageId.current !== lastMessageId) {
// hasSeeningReasoningPage.current = true;
if (
!isCompletedStream &&
hasReasoning &&
previousLastMessageId.current !== lastMessageId &&
chatId
) {
onSetSelectedFile({ id: lastMessageId, type: 'reasoning' });
previousLastMessageId.current = lastMessageId;
}
@ -48,5 +55,5 @@ export const useAutoChangeLayout = ({
onSetSelectedFile({ id: lastFileId, type: lastFile.file_type });
}
}
}, [isCompletedStream, hasReasoning, lastMessageId]);
}, [isCompletedStream, chatId, hasReasoning, lastMessageId]);
};

View File

@ -57,6 +57,6 @@ export const createChatAssetRoute = ({
type: FileType;
}) => {
const routeBuilder = chatRouteRecord[type];
if (!routeBuilder) return '';
if (!routeBuilder) return null;
return routeBuilder(chatId, assetId);
};

View File

@ -6,6 +6,9 @@ import { useMemoizedFn } from '@/hooks';
import { createSelectedFile } from './createSelectedFile';
import type { useGetChatParams } from '../useGetChatParams';
import type { AppSplitterRef } from '@/components/ui/layouts/AppSplitter';
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
import { BusterRoutes, createBusterRoute } from '@/routes';
import { createChatAssetRoute } from '../helpers';
export const useSelectedFile = ({
animateOpenSplitter,
@ -17,6 +20,7 @@ export const useSelectedFile = ({
chatParams: ReturnType<typeof useGetChatParams>;
}) => {
const { metricVersionNumber, dashboardVersionNumber } = chatParams;
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
const selectedFile: SelectedFile | null = useMemo(() => {
return createSelectedFile(chatParams);
@ -29,13 +33,24 @@ export const useSelectedFile = ({
}, [selectedFile?.type, metricVersionNumber, dashboardVersionNumber]);
/**
* @description Opens the splitter if the file is not already open. If the file is already open, it will collapse the splitter. This does NOT set the selected file. You should do that with a Link
* @description Opens the splitter if the file is not already open.
* If the file is already open, it will collapse the splitter.
* You should do try to set the selected file with a Link!
* @param file
*/
const onSetSelectedFile = useMemoizedFn(async (file: SelectedFile | null) => {
const handleFileCollapse =
!file || (file?.id === selectedFile?.id && !appSplitterRef.current?.isSideClosed('right'));
if (file && chatParams.chatId) {
const link = createChatAssetRoute({
chatId: chatParams.chatId,
assetId: file?.id,
type: file?.type
});
if (link) onChangePage(link);
}
if (handleFileCollapse) {
animateOpenSplitter('left');
return;

View File

@ -90,7 +90,7 @@ export const FileContainer: React.FC<FileContainerProps> = ({ children }) => {
),
[]
)}
headerClassName="border-l">
headerClassName="">
<AppSplitter
ref={appSplitterRef}
autoSaveId={autoSaveId}

View File

@ -193,7 +193,7 @@ const useDeleteDashboardSelectMenu = ({ dashboardId }: { dashboardId: string })
icon: <Trash />,
onClick: async () => {
await deleteDashboard({ dashboardId });
onChangePage(createBusterRoute({ route: BusterRoutes.APP_DASHBOARDS }));
onChangePage({ route: BusterRoutes.APP_DASHBOARDS });
}
}),
[dashboardId]