mirror of https://github.com/buster-so/buster.git
chat file headers
This commit is contained in:
parent
2fe395b5ea
commit
8b21e0d50c
|
@ -1,18 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import type { ChatSplitterProps } from './ChatSplitter';
|
|
||||||
|
|
||||||
interface ChatContainerProps {
|
|
||||||
chatHeaderText: string;
|
|
||||||
chatHeaderOptions: ChatSplitterProps['chatHeaderOptions'];
|
|
||||||
chatContent: ChatSplitterProps['chatContent'];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ChatContainer: React.FC<ChatContainerProps> = React.memo(({ chatHeaderText }) => {
|
|
||||||
return (
|
|
||||||
<div className="h-full w-full bg-red-500">
|
|
||||||
{/* <Button onClick={onToggleClick}>Toggle {toggleClose.toString()}</Button> */}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
ChatContainer.displayName = 'ChatContainer';
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
import type { ChatSplitterProps } from '../ChatSplitter';
|
||||||
|
import { ChatContainerHeader } from './ChatContainerHeader';
|
||||||
|
import { SelectedFile } from '../interfaces';
|
||||||
|
import { ChatContainerContentContainer } from './ChatContainerContentContainer';
|
||||||
|
|
||||||
|
interface ChatContainerProps {
|
||||||
|
chatContent: ChatSplitterProps['chatContent'];
|
||||||
|
selectedFile: SelectedFile | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatContainer: React.FC<ChatContainerProps> = React.memo(
|
||||||
|
({ chatContent, selectedFile }) => {
|
||||||
|
return (
|
||||||
|
<div className="flex h-full w-full flex-col">
|
||||||
|
<ChatContainerHeader selectedFile={selectedFile} />
|
||||||
|
<ChatContainerContentContainer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ChatContainer.displayName = 'ChatContainer';
|
|
@ -0,0 +1,5 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const ChatContainerContentContainer: React.FC = () => {
|
||||||
|
return <div className="h-full w-full bg-red-200">ChatContainerContentContainer</div>;
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { appContentHeaderHeight } from '@/components/layout/AppContentHeader';
|
||||||
|
import { createStyles } from 'antd-style';
|
||||||
|
import React from 'react';
|
||||||
|
import { SelectedFile } from '../../interfaces';
|
||||||
|
import { useChatSplitterContextSelector } from '../../ChatSplitterContext';
|
||||||
|
import { Text } from '@/components/text';
|
||||||
|
import { ChatContainerHeaderOptions } from './ChatContainerHeaderOptions';
|
||||||
|
import { ChatContainerHeaderTitle } from './ChatContainerHeaderTitle';
|
||||||
|
|
||||||
|
export const ChatContainerHeader: React.FC<{
|
||||||
|
selectedFile: SelectedFile | undefined;
|
||||||
|
}> = React.memo(({ selectedFile }) => {
|
||||||
|
const { cx, styles } = useStyles();
|
||||||
|
const hasFile = useChatSplitterContextSelector((state) => state.hasFile);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cx('flex w-full items-center justify-between space-x-2 px-4', styles.header)}>
|
||||||
|
{hasFile && (
|
||||||
|
<>
|
||||||
|
<ChatContainerHeaderTitle />
|
||||||
|
<ChatContainerHeaderOptions />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ChatContainerHeader.displayName = 'ChatContainerHeader';
|
||||||
|
|
||||||
|
const useStyles = createStyles(({ token }) => ({
|
||||||
|
header: {
|
||||||
|
height: appContentHeaderHeight
|
||||||
|
}
|
||||||
|
}));
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AppMaterialIcons } from '@/components';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const ChatContainerHeaderOptions: React.FC<{}> = React.memo(() => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button type="text" icon={<AppMaterialIcons icon="more_horiz" />} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ChatContainerHeaderOptions.displayName = 'ChatContainerHeaderOptions';
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Text } from '@/components/text';
|
||||||
|
import React from 'react';
|
||||||
|
import { useChatSplitterContextSelector } from '../../ChatSplitterContext';
|
||||||
|
|
||||||
|
export const ChatContainerHeaderTitle: React.FC<{}> = React.memo(() => {
|
||||||
|
const hasFile = useChatSplitterContextSelector((state) => state.hasFile);
|
||||||
|
const selectedFileTitle = useChatSplitterContextSelector((state) => state.selectedFileTitle);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<Text>{selectedFileTitle}</Text>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ChatContainerHeaderTitle.displayName = 'ChatContainerHeaderTitle';
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './ChatContainerHeader';
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './ChatContainer';
|
|
@ -1,51 +1,44 @@
|
||||||
import React, { useEffect, useImperativeHandle, useMemo, useRef } from 'react';
|
import React, { useMemo, useRef } from 'react';
|
||||||
import { AppSplitter, AppSplitterRef } from '@/components/layout/AppSplitter';
|
import { AppSplitter, AppSplitterRef } from '@/components/layout/AppSplitter';
|
||||||
import { AppChatMessageFileType } from '@/components/messages/AppChatMessageContainer';
|
|
||||||
import { ChatContainer } from './ChatContainer';
|
import { ChatContainer } from './ChatContainer';
|
||||||
import { FileContainer } from './FileContainer';
|
import { FileContainer } from './FileContainer';
|
||||||
import { useUpdateEffect } from 'ahooks';
|
|
||||||
import { ChatSplitterContextProvider } from './ChatSplitterContext';
|
import { ChatSplitterContextProvider } from './ChatSplitterContext';
|
||||||
import { useChatSplitter } from './ChatSplitterContext/useChatSplitter';
|
import { useChatSplitter } from './ChatSplitterContext';
|
||||||
import { SelectedFile } from './interfaces';
|
import { SelectedFile } from './interfaces';
|
||||||
|
|
||||||
export interface ChatSplitterProps {
|
export interface ChatSplitterProps {
|
||||||
chatHeaderText: string;
|
|
||||||
chatHeaderOptions?: [];
|
chatHeaderOptions?: [];
|
||||||
chatContent?: React.ReactNode;
|
chatContent?: React.ReactNode;
|
||||||
fileHeader?: React.ReactNode;
|
showChatCollapse?: boolean;
|
||||||
defaultShowFile?: boolean;
|
defaultShowLayout?: 'chat' | 'file' | 'both';
|
||||||
defaultSelectedFile?: SelectedFile;
|
defaultSelectedFile?: SelectedFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChatSplitter: React.FC<ChatSplitterProps> = React.memo(
|
export const ChatSplitter: React.FC<ChatSplitterProps> = React.memo(
|
||||||
({
|
({ defaultSelectedFile, defaultShowLayout = 'chat', chatHeaderOptions, chatContent }) => {
|
||||||
chatHeaderText,
|
|
||||||
defaultShowFile = false,
|
|
||||||
defaultSelectedFile,
|
|
||||||
chatHeaderOptions,
|
|
||||||
chatContent,
|
|
||||||
fileHeader
|
|
||||||
}) => {
|
|
||||||
const appSplitterRef = useRef<AppSplitterRef>(null);
|
const appSplitterRef = useRef<AppSplitterRef>(null);
|
||||||
|
|
||||||
const defaultLayout = useMemo(() => {
|
const defaultLayout = useMemo(() => {
|
||||||
return defaultShowFile ? ['20%', '80%'] : ['100%', '0%'];
|
if (defaultShowLayout === 'chat') {
|
||||||
}, [defaultShowFile]);
|
return ['100%', '0%'];
|
||||||
|
}
|
||||||
|
if (defaultShowLayout === 'file') {
|
||||||
|
return ['0%', '100%'];
|
||||||
|
}
|
||||||
|
return ['325px', 'auto'];
|
||||||
|
}, [defaultShowLayout]);
|
||||||
|
|
||||||
const useChatSplitterProps = useChatSplitter({ defaultSelectedFile, appSplitterRef });
|
const useChatSplitterProps = useChatSplitter({
|
||||||
|
defaultSelectedFile,
|
||||||
|
appSplitterRef
|
||||||
|
});
|
||||||
const { selectedFile, hasFile } = useChatSplitterProps;
|
const { selectedFile, hasFile } = useChatSplitterProps;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChatSplitterContextProvider useChatSplitterProps={useChatSplitterProps}>
|
<ChatSplitterContextProvider useChatSplitterProps={useChatSplitterProps}>
|
||||||
<AppSplitter
|
<AppSplitter
|
||||||
ref={appSplitterRef}
|
ref={appSplitterRef}
|
||||||
leftChildren={
|
leftChildren={<ChatContainer selectedFile={selectedFile} chatContent={chatContent} />}
|
||||||
<ChatContainer
|
|
||||||
chatHeaderText={chatHeaderText}
|
|
||||||
chatHeaderOptions={chatHeaderOptions}
|
|
||||||
chatContent={chatContent}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
rightChildren={<FileContainer selectedFile={selectedFile} />}
|
rightChildren={<FileContainer selectedFile={selectedFile} />}
|
||||||
autoSaveId="chat-splitter"
|
autoSaveId="chat-splitter"
|
||||||
defaultLayout={defaultLayout}
|
defaultLayout={defaultLayout}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
useContextSelector
|
useContextSelector
|
||||||
} from '@fluentui/react-context-selector';
|
} from '@fluentui/react-context-selector';
|
||||||
import { useChatSplitter } from './useChatSplitter';
|
import { useChatSplitter } from './useChatSplitter';
|
||||||
import { AppSplitterRef } from '@/components/layout/AppSplitter';
|
|
||||||
|
|
||||||
const ChatSplitterContext = createContext<ReturnType<typeof useChatSplitter>>(
|
const ChatSplitterContext = createContext<ReturnType<typeof useChatSplitter>>(
|
||||||
{} as ReturnType<typeof useChatSplitter>
|
{} as ReturnType<typeof useChatSplitter>
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export * from './ChatSplitterContext';
|
export * from './ChatSplitterContext';
|
||||||
|
export * from './useChatSplitter';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
import { SelectedFile } from '../interfaces';
|
import { SelectedFile } from '../interfaces';
|
||||||
import { useUpdateEffect } from 'ahooks';
|
import { useUpdateEffect } from 'ahooks';
|
||||||
import type { AppSplitterRef } from '@/components/layout/AppSplitter';
|
import type { AppSplitterRef } from '@/components/layout/AppSplitter';
|
||||||
|
@ -14,6 +14,11 @@ export const useChatSplitter = ({ appSplitterRef, defaultSelectedFile }: UseChat
|
||||||
|
|
||||||
const hasFile = !!selectedFile;
|
const hasFile = !!selectedFile;
|
||||||
|
|
||||||
|
const selectedFileTitle: string = useMemo(() => {
|
||||||
|
if (!selectedFile) return '';
|
||||||
|
return 'This is a test';
|
||||||
|
}, [selectedFile]);
|
||||||
|
|
||||||
const onSetSelectedFile = (file: SelectedFile) => {
|
const onSetSelectedFile = (file: SelectedFile) => {
|
||||||
setSelectedFile(file);
|
setSelectedFile(file);
|
||||||
};
|
};
|
||||||
|
@ -25,13 +30,12 @@ export const useChatSplitter = ({ appSplitterRef, defaultSelectedFile }: UseChat
|
||||||
appSplitterRef.current?.animateWidth('50%', 'right');
|
appSplitterRef.current?.animateWidth('50%', 'right');
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
// appSplitterRef.current.animateWidth('200px', 'left');
|
|
||||||
|
|
||||||
appSplitterRef.current?.animateWidth('100px', 'right');
|
appSplitterRef.current?.animateWidth('100px', 'right');
|
||||||
}
|
}
|
||||||
}, [defaultSelectedFile]);
|
}, [defaultSelectedFile]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
selectedFileTitle,
|
||||||
hasFile,
|
hasFile,
|
||||||
selectedFile,
|
selectedFile,
|
||||||
onSetSelectedFile
|
onSetSelectedFile
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { ChatSplitterProps } from './ChatSplitter';
|
import type { ChatSplitterProps } from '../ChatSplitter';
|
||||||
import { SelectedFile } from './interfaces';
|
import { SelectedFile } from '../interfaces';
|
||||||
|
|
||||||
interface FileContainerProps {
|
interface FileContainerProps {
|
||||||
selectedFile: SelectedFile | undefined;
|
selectedFile: SelectedFile | undefined;
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './FileContainer';
|
|
@ -11,7 +11,10 @@ export default function Page() {
|
||||||
const [toggleClose, setToggleClose] = useState(false);
|
const [toggleClose, setToggleClose] = useState(false);
|
||||||
const ref = useRef<AppSplitterRef>(null);
|
const ref = useRef<AppSplitterRef>(null);
|
||||||
|
|
||||||
const [defaultFile, setDefaultFile] = useState<SelectedFile | undefined>(undefined);
|
const [defaultFile, setDefaultFile] = useState<SelectedFile | undefined>({
|
||||||
|
id: '1',
|
||||||
|
type: 'metric'
|
||||||
|
});
|
||||||
|
|
||||||
const onToggleClick = useMemoizedFn(() => {
|
const onToggleClick = useMemoizedFn(() => {
|
||||||
if (toggleClose) {
|
if (toggleClose) {
|
||||||
|
@ -25,7 +28,7 @@ export default function Page() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen w-screen border">
|
<div className="h-screen w-screen border">
|
||||||
<ChatSplitter chatHeaderText="Chat" defaultSelectedFile={defaultFile} />
|
<ChatSplitter defaultShowLayout="both" defaultSelectedFile={defaultFile} />
|
||||||
|
|
||||||
<Button onClick={() => setDefaultFile({ id: '1', type: 'metric' })}>Set Default File</Button>
|
<Button onClick={() => setDefaultFile({ id: '1', type: 'metric' })}>Set Default File</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue