mirror of https://github.com/buster-so/buster.git
use client on select assets
This commit is contained in:
parent
2eb938f597
commit
e79f1e7e05
|
@ -7,7 +7,7 @@ import {
|
|||
} from './eventInterfaces';
|
||||
|
||||
export enum ChatsResponses {
|
||||
'/chats/list:getThreadsList' = '/chats/list:getThreadsList',
|
||||
'/chats/list:getChatsList' = '/chats/list:getChatsList',
|
||||
'/chats/unsubscribe:unsubscribe' = '/chats/unsubscribe:unsubscribe',
|
||||
'/chats/get:getChat' = '/chats/get:getChat',
|
||||
'/chats/post:initializeChat' = '/chats/post:initializeChat',
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ChatListHeader } from './_ChatsListContainer/ChatListHeader';
|
|||
|
||||
export default function ChatsPage() {
|
||||
return (
|
||||
<AppPageLayout headerVariant="list" header={<ChatListHeader />}>
|
||||
<AppPageLayout headerSizeVariant="list" header={<ChatListHeader />}>
|
||||
<ChatListContainer />
|
||||
</AppPageLayout>
|
||||
);
|
||||
|
|
|
@ -16,9 +16,17 @@ export const AppPageLayout: React.FC<
|
|||
header?: React.ReactNode;
|
||||
scrollable?: boolean;
|
||||
className?: string;
|
||||
headerVariant?: 'default' | 'list';
|
||||
headerSizeVariant?: 'default' | 'list';
|
||||
headerBorderVariant?: 'default' | 'ghost';
|
||||
}>
|
||||
> = ({ children, header, scrollable = false, className = '', headerVariant = 'default' }) => {
|
||||
> = ({
|
||||
children,
|
||||
header,
|
||||
scrollable = false,
|
||||
className = '',
|
||||
headerSizeVariant = 'default',
|
||||
headerBorderVariant = 'default'
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
@ -26,7 +34,11 @@ export const AppPageLayout: React.FC<
|
|||
scrollable && 'overflow-y-auto',
|
||||
className
|
||||
)}>
|
||||
{header && <AppPageLayoutHeader variant={headerVariant}>{header}</AppPageLayoutHeader>}
|
||||
{header && (
|
||||
<AppPageLayoutHeader sizeVariant={headerSizeVariant} borderVariant={headerBorderVariant}>
|
||||
{header}
|
||||
</AppPageLayoutHeader>
|
||||
)}
|
||||
<AppPageLayoutContent scrollable={scrollable}>{children}</AppPageLayoutContent>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -3,13 +3,21 @@ 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 justify-between gap-x-2.5 border-b',
|
||||
'bg-page-background flex max-h-[38px] min-h-[38px] items-center justify-between gap-x-2.5 ',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
sizeVariant: {
|
||||
default: 'px-4.5',
|
||||
list: 'px-7.5'
|
||||
},
|
||||
borderVariant: {
|
||||
default: 'border-b',
|
||||
ghost: 'border-b-0'
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
borderVariant: 'default',
|
||||
sizeVariant: 'default'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -20,6 +28,8 @@ export const AppPageLayoutHeader: React.FC<
|
|||
className?: string;
|
||||
} & VariantProps<typeof headerVariants>
|
||||
>
|
||||
> = ({ children, className = '', variant = 'default' }) => {
|
||||
return <div className={cn(headerVariants({ variant }), className)}>{children}</div>;
|
||||
> = ({ children, className = '', sizeVariant = 'default', borderVariant = 'default' }) => {
|
||||
return (
|
||||
<div className={cn(headerVariants({ sizeVariant, borderVariant }), className)}>{children}</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ export const useBusterChatListByFilter = (
|
|||
route: '/chats/list',
|
||||
payload: filters
|
||||
},
|
||||
responseEvent: '/chats/list:getThreadsList',
|
||||
responseEvent: '/chats/list:getChatsList',
|
||||
options: queryKeys['chatsGetList'](filters)
|
||||
});
|
||||
|
||||
|
|
|
@ -136,6 +136,10 @@ export const useChatStreamMessage = () => {
|
|||
const _generatingResponseMessageCallback = useMemoizedFn(
|
||||
(_: null, d: ChatEvent_GeneratingResponseMessage) => {
|
||||
const { message_id, response_message, chat_id } = d;
|
||||
console.log(response_message?.id);
|
||||
|
||||
if (!response_message?.id) return;
|
||||
|
||||
const responseMessageId = response_message.id;
|
||||
const foundResponseMessage: undefined | ChatMessageResponseMessage =
|
||||
chatMessageResponseMessagesRef.current[message_id]?.[responseMessageId];
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { useChatIndividualContextSelector } from '@chatLayout/ChatContext';
|
||||
import { ReasoningMessageContainer } from './ReasoningMessageContainer';
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use client';
|
||||
|
||||
import type { BusterChatMessageReasoning } from '@/api/asset_interfaces';
|
||||
import React, { useMemo } from 'react';
|
||||
import { ReasoningMessageSelector } from './ReasoningMessages';
|
||||
|
|
|
@ -19,6 +19,7 @@ export const ChatContainer = React.memo(({}: ChatContainerProps) => {
|
|||
return (
|
||||
<AppPageLayout
|
||||
header={<ChatHeader showScrollOverflow={showScrollOverflow} />}
|
||||
headerBorderVariant="ghost"
|
||||
className="flex h-full w-full min-w-[295px] flex-col">
|
||||
<ChatContent chatContentRef={chatContentRef} />
|
||||
</AppPageLayout>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { useChatIndividualContextSelector } from '../../ChatContext';
|
||||
import { ChatMessageBlock } from './ChatMessageBlock';
|
||||
import { ChatInput } from './ChatInput';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
export const ChatContent: React.FC<{ chatContentRef: React.RefObject<HTMLDivElement> }> =
|
||||
React.memo(({ chatContentRef }) => {
|
||||
const { styles } = useStyles();
|
||||
const chatMessageIds = useChatIndividualContextSelector((state) => state.chatMessageIds);
|
||||
// const chatMessages = useBusterChatContextSelector((state) => state.chatsMessages);
|
||||
|
||||
|
@ -17,7 +17,7 @@ export const ChatContent: React.FC<{ chatContentRef: React.RefObject<HTMLDivElem
|
|||
<div ref={chatContentRef} className="h-full w-full overflow-y-auto">
|
||||
<div className="pb-8">
|
||||
{chatMessageIds?.map((messageId) => (
|
||||
<div key={messageId} className={styles.messageBlock}>
|
||||
<div key={messageId} className={'hover:bg-item-hover'}>
|
||||
<div className={autoClass}>
|
||||
<ChatMessageBlock key={messageId} messageId={messageId} />
|
||||
</div>
|
||||
|
@ -33,11 +33,3 @@ export const ChatContent: React.FC<{ chatContentRef: React.RefObject<HTMLDivElem
|
|||
});
|
||||
|
||||
ChatContent.displayName = 'ChatContent';
|
||||
|
||||
const useStyles = createStyles(({ token, css }) => ({
|
||||
messageBlock: css`
|
||||
&:hover {
|
||||
background-color: ${token.controlItemBgHover};
|
||||
}
|
||||
`
|
||||
}));
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Text } from '@/components/ui';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
|
||||
export const AIWarning = React.memo(() => {
|
||||
return (
|
||||
<div className="w-full truncate overflow-hidden text-center">
|
||||
<Text size="xs" type="tertiary" className="truncate">
|
||||
<Text size="xs" variant="tertiary" truncate>
|
||||
Our AI may make mistakes. Check important info.
|
||||
</Text>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { BusterChatMessageResponse } from '@/api/asset_interfaces';
|
|||
import { createStyles } from 'antd-style';
|
||||
import { ChatResponseMessageSelector } from './ChatResponseMessageSelector';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { Text } from '@/components/ui';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { AppMaterialIcons } from '@/components/ui';
|
||||
import pluralize from 'pluralize';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
|
|
|
@ -5,7 +5,6 @@ import { ShimmerText } from '@/components/ui/typography/ShimmerText';
|
|||
import { useMemoizedFn } from 'ahooks';
|
||||
import { motion } from 'framer-motion';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { AppMaterialIcons } from '@/components/ui';
|
||||
import { Stars } from '@/components/ui/icons';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { BusterChatMessageRequest } from '@/api/asset_interfaces';
|
||||
import { createStyles } from 'antd-style';
|
||||
import React from 'react';
|
||||
import { Text } from '@/components/ui';
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import { MessageContainer } from './MessageContainer';
|
||||
|
||||
export const ChatUserMessage: React.FC<{ requestMessage: BusterChatMessageRequest }> = React.memo(
|
||||
|
@ -12,9 +12,7 @@ export const ChatUserMessage: React.FC<{ requestMessage: BusterChatMessageReques
|
|||
|
||||
return (
|
||||
<MessageContainer senderName={sender_name} senderId={sender_id} senderAvatar={sender_avatar}>
|
||||
<Text className="" lineHeight={undefined}>
|
||||
{request}
|
||||
</Text>
|
||||
<Text>{request}</Text>
|
||||
</MessageContainer>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { ChatHeaderOptions } from './ChatHeaderOptions';
|
||||
import { ChatHeaderTitle } from './ChatHeaderTitle';
|
||||
import { useChatIndividualContextSelector } from '../../ChatContext';
|
||||
import { cn } from '@/lib/classMerge';
|
||||
import { AppPageLayoutHeader } from '@/components/ui/layouts/AppPageLayoutHeader';
|
||||
|
||||
export const ChatHeader: React.FC<{
|
||||
showScrollOverflow: boolean;
|
||||
|
@ -11,19 +11,13 @@ export const ChatHeader: React.FC<{
|
|||
const hasFile = useChatIndividualContextSelector((state) => state.hasFile);
|
||||
const chatTitle = useChatIndividualContextSelector((state) => state.chatTitle);
|
||||
|
||||
if (!hasFile && !chatTitle) return null;
|
||||
|
||||
return (
|
||||
<AppPageLayoutHeader
|
||||
className={cn(
|
||||
'relative z-2 flex w-full items-center justify-between space-x-2 border-b-0 px-4 transition-shadow',
|
||||
showScrollOverflow && 'shadow-scroll-indicator'
|
||||
)}>
|
||||
{hasFile && chatTitle && (
|
||||
<>
|
||||
<ChatHeaderTitle />
|
||||
<ChatHeaderOptions />
|
||||
</>
|
||||
)}
|
||||
</AppPageLayoutHeader>
|
||||
<>
|
||||
<ChatHeaderTitle />
|
||||
<ChatHeaderOptions />
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use client';
|
||||
|
||||
import { AppMaterialIcons } from '@/components/ui';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { Text } from '@/components/ui';
|
||||
'use client';
|
||||
|
||||
import { Text } from '@/components/ui/typography';
|
||||
import React from 'react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useChatIndividualContextSelector } from '../../ChatContext';
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
'use client';
|
||||
|
||||
import { useMessageIndividual } from '@/context/Chats';
|
||||
import type { SelectedFile } from '../interfaces';
|
||||
import { usePrevious } from 'ahooks';
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export const useAutoChangeLayout = ({
|
||||
lastMessageId,
|
||||
|
||||
onSetSelectedFile
|
||||
}: {
|
||||
lastMessageId: string;
|
||||
onSetSelectedFile: (file: SelectedFile) => void;
|
||||
}) => {
|
||||
const hasSeeningReasoningPage = useRef(false); //used when there is a delay in page load
|
||||
const message = useMessageIndividual(lastMessageId);
|
||||
const reasoningMessagesLength = message?.reasoning?.length;
|
||||
const previousReasoningMessagesLength = usePrevious(reasoningMessagesLength);
|
||||
const isCompletedStream = message?.isCompletedStream;
|
||||
const isLoading = !isCompletedStream;
|
||||
const hasReasoning = !!reasoningMessagesLength;
|
||||
const previousIsEmpty = previousReasoningMessagesLength === 0;
|
||||
|
||||
console.log(isLoading, previousIsEmpty, hasReasoning, message);
|
||||
|
||||
//change the page to reasoning file if we get a reasoning message
|
||||
useEffect(() => {
|
||||
if (isLoading && previousIsEmpty && hasReasoning) {
|
||||
if (isLoading && !hasSeeningReasoningPage.current && hasReasoning) {
|
||||
hasSeeningReasoningPage.current = true;
|
||||
onSetSelectedFile({ id: lastMessageId, type: 'reasoning' });
|
||||
}
|
||||
}, [isLoading, hasReasoning, previousIsEmpty]);
|
||||
}, [isLoading, hasReasoning]);
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ export const ChatLayout: React.FC<ChatSplitterProps> = React.memo(
|
|||
<AppSplitter
|
||||
ref={appSplitterRef}
|
||||
leftChildren={<ChatContainer />}
|
||||
rightChildren={<FileContainer children={children} />}
|
||||
rightChildren={<FileContainer>{children}</FileContainer>}
|
||||
autoSaveId="chat-splitter"
|
||||
defaultLayout={defaultSplitterLayout}
|
||||
rightHidden={renderViewLayoutKey === 'chat'}
|
||||
|
|
|
@ -4,7 +4,7 @@ import React from 'react';
|
|||
import { useChatLayoutContextSelector } from '../../ChatLayoutContext';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import { AppTooltip } from '@/components/ui';
|
||||
import { AppTooltip } from '@/components/ui/tooltip';
|
||||
|
||||
export const CreateChatButton = React.memo(() => {
|
||||
const onCollapseFileClick = useChatLayoutContextSelector((x) => x.onCollapseFileClick);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import type { FileContainerSegmentProps } from './interfaces';
|
||||
import type { DashboardFileView, FileView } from '../../ChatLayoutContext/useChatFileLayout';
|
||||
import type { FileView } from '../../ChatLayoutContext/useChatFileLayout';
|
||||
import { AppSegmented } from '@/components/ui/segmented';
|
||||
import { useChatLayoutContextSelector } from '../../ChatLayoutContext';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
|
@ -19,7 +19,14 @@ export const DashboardContainerHeaderSegment: React.FC<FileContainerSegmentProps
|
|||
onSetFileView({ fileView: fileView.value });
|
||||
});
|
||||
|
||||
return <AppSegmented options={segmentOptions} value={selectedFileView} onChange={onChange} />;
|
||||
return (
|
||||
<AppSegmented
|
||||
type="button"
|
||||
options={segmentOptions}
|
||||
value={selectedFileView}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { CollapseFileButton } from './CollapseFileButton';
|
||||
import { FileType } from '@/api/asset_interfaces';
|
||||
import type { FileType } from '@/api/asset_interfaces';
|
||||
import { FileContainerSegmentProps, FileContainerButtonsProps } from './interfaces';
|
||||
import { DashboardContainerHeaderButtons } from './DashboardContainerHeaderButtons';
|
||||
import { DashboardContainerHeaderSegment } from './DashboardContainerHeaderSegment';
|
||||
|
@ -8,7 +10,6 @@ import { MetricContainerHeaderSegment } from './MetricContainerHeaderSegment';
|
|||
import { MetricContainerHeaderButtons } from './MetricContainerHeaderButtons';
|
||||
import { useChatLayoutContextSelector } from '../../ChatLayoutContext';
|
||||
import { ReasoningContainerHeaderSegment } from './ReasoningContainerHeaderSegment';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export const FileContainerHeader: React.FC = React.memo(() => {
|
||||
const selectedFileType = useChatLayoutContextSelector((x) => x.selectedFileType);
|
||||
|
@ -37,11 +38,7 @@ export const FileContainerHeader: React.FC = React.memo(() => {
|
|||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'border-b',
|
||||
'flex w-full items-center justify-between space-x-1 overflow-hidden px-3'
|
||||
)}>
|
||||
<>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<CollapseFileButton
|
||||
collapseDirection={collapseDirection}
|
||||
|
@ -52,7 +49,7 @@ export const FileContainerHeader: React.FC = React.memo(() => {
|
|||
{selectedFileView && <SelectedFileSegment selectedFileView={selectedFileView} />}
|
||||
</div>
|
||||
<SelectedFileButtons selectedFileView={selectedFileView} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,14 @@ export const MetricContainerHeaderSegment: React.FC<FileContainerSegmentProps> =
|
|||
onSetFileView({ fileView: fileView.value });
|
||||
});
|
||||
|
||||
return <AppSegmented options={segmentOptions} value={selectedFileView} onChange={onChange} />;
|
||||
return (
|
||||
<AppSegmented
|
||||
type="button"
|
||||
options={segmentOptions}
|
||||
value={selectedFileView}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { FileContainerSegmentProps } from './interfaces';
|
||||
import { AppSegmented } from '@/components/ui/segmented';
|
||||
|
@ -18,7 +20,14 @@ export const ReasoningContainerHeaderSegment: React.FC<FileContainerSegmentProps
|
|||
onSetFileView({ fileView: fileView.value });
|
||||
});
|
||||
|
||||
return <AppSegmented options={segmentOptions} value={selectedFileView} onChange={onChange} />;
|
||||
return (
|
||||
<AppSegmented
|
||||
type="button"
|
||||
options={segmentOptions}
|
||||
value={selectedFileView}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue