mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Render dialog list #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -2,6 +2,7 @@ import Editor, { loader } from '@monaco-editor/react';
|
||||
import { INextOperatorForm } from '../../interface';
|
||||
|
||||
import { FormContainer } from '@/components/form-container';
|
||||
import { useIsDarkTheme } from '@/components/theme-provider';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
@ -46,6 +47,7 @@ function CodeForm({ node }: INextOperatorForm) {
|
||||
const formData = node?.data.form as ICodeForm;
|
||||
const { t } = useTranslation();
|
||||
const values = useValues(node);
|
||||
const isDarkTheme = useIsDarkTheme();
|
||||
|
||||
const form = useForm<FormSchemaType>({
|
||||
defaultValues: values,
|
||||
@ -94,7 +96,7 @@ function CodeForm({ node }: INextOperatorForm) {
|
||||
<FormControl>
|
||||
<Editor
|
||||
height={300}
|
||||
theme="vs-dark"
|
||||
theme={isDarkTheme ? 'vs-dark' : 'vs'}
|
||||
language={formData.lang}
|
||||
options={{
|
||||
minimap: { enabled: false },
|
||||
|
||||
@ -10,7 +10,7 @@ import { useCallback } from 'react';
|
||||
import { AgentCard } from './agent-card';
|
||||
import { useRenameAgent } from './use-rename-agent';
|
||||
|
||||
export default function Agent() {
|
||||
export default function Agents() {
|
||||
const { data, pagination, setPagination, searchString, handleInputChange } =
|
||||
useFetchAgentListByPage();
|
||||
const { navigateToAgentTemplates } = useNavigatePage();
|
||||
|
||||
@ -53,7 +53,7 @@ export default function Datasets() {
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="py-4 text-foreground">
|
||||
<section className="py-4 flex-1 flex flex-col">
|
||||
<ListFilterBar
|
||||
title={t('header.knowledgeBase')}
|
||||
searchString={searchString}
|
||||
@ -69,16 +69,18 @@ export default function Datasets() {
|
||||
{t('knowledgeList.createKnowledgeBase')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
<div className="flex flex-wrap gap-4 max-h-[78vh] overflow-auto px-8">
|
||||
{kbs.map((dataset) => {
|
||||
return (
|
||||
<DatasetCard
|
||||
dataset={dataset}
|
||||
key={dataset.id}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
);
|
||||
})}
|
||||
<div className="flex-1">
|
||||
<div className="flex flex-wrap gap-4 max-h-[78vh] overflow-auto px-8">
|
||||
{kbs.map((dataset) => {
|
||||
return (
|
||||
<DatasetCard
|
||||
dataset={dataset}
|
||||
key={dataset.id}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 px-8">
|
||||
<RAGFlowPagination
|
||||
|
||||
@ -1,52 +1,45 @@
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { MoreButton } from '@/components/more-button';
|
||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import { formatPureDate } from '@/utils/date';
|
||||
import { ChevronRight, Trash2 } from 'lucide-react';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import { ChatDropdown } from './chat-dropdown';
|
||||
import { useRenameChat } from './hooks/use-rename-chat';
|
||||
|
||||
interface IProps {
|
||||
export type IProps = {
|
||||
data: IDialog;
|
||||
}
|
||||
} & Pick<ReturnType<typeof useRenameChat>, 'showChatRenameModal'>;
|
||||
|
||||
export function ChatCard({ data }: IProps) {
|
||||
export function ChatCard({ data, showChatRenameModal }: IProps) {
|
||||
const { navigateToChat } = useNavigatePage();
|
||||
|
||||
return (
|
||||
<Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard">
|
||||
<CardContent className="p-4">
|
||||
<div className="flex justify-between mb-4">
|
||||
{data.icon ? (
|
||||
<div
|
||||
className="w-[70px] h-[70px] rounded-xl bg-cover"
|
||||
style={{ backgroundImage: `url(${data.icon})` }}
|
||||
/>
|
||||
) : (
|
||||
<Avatar className="w-[70px] h-[70px]">
|
||||
<AvatarImage src="https://github.com/shadcn.png" />
|
||||
<AvatarFallback>CN</AvatarFallback>
|
||||
</Avatar>
|
||||
)}
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-2">{data.name}</h3>
|
||||
<p>An app that does things An app that does things</p>
|
||||
<section className="flex justify-between pt-3">
|
||||
<div>
|
||||
Search app
|
||||
<p className="text-sm opacity-80">
|
||||
{formatPureDate(data.update_time)}
|
||||
<Card key={data.id} className="w-40" onClick={navigateToChat(data.id)}>
|
||||
<CardContent className="p-2.5 pt-2 group">
|
||||
<section className="flex justify-between mb-2">
|
||||
<div className="flex gap-2 items-center">
|
||||
<RAGFlowAvatar
|
||||
className="size-6 rounded-lg"
|
||||
avatar={data.icon}
|
||||
name={data.name || 'CN'}
|
||||
></RAGFlowAvatar>
|
||||
</div>
|
||||
<ChatDropdown chat={data} showChatRenameModal={showChatRenameModal}>
|
||||
<MoreButton></MoreButton>
|
||||
</ChatDropdown>
|
||||
</section>
|
||||
<div className="flex justify-between items-end">
|
||||
<div className="w-full">
|
||||
<h3 className="text-lg font-semibold mb-2 line-clamp-1">
|
||||
{data.name}
|
||||
</h3>
|
||||
<p className="text-xs text-text-sub-title">{data.description}</p>
|
||||
<p className="text-xs text-text-sub-title">
|
||||
{formatDate(data.update_time)}
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-x-2">
|
||||
<Button variant="icon" size="icon" onClick={navigateToChat}>
|
||||
<ChevronRight className="h-6 w-6" />
|
||||
</Button>
|
||||
<Button variant="icon" size="icon">
|
||||
<Trash2 />
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
64
web/src/pages/next-chats/chat-dropdown.tsx
Normal file
64
web/src/pages/next-chats/chat-dropdown.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { useRemoveDialog } from '@/hooks/use-chat-request';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import { PenLine, Trash2 } from 'lucide-react';
|
||||
import { MouseEventHandler, PropsWithChildren, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRenameChat } from './hooks/use-rename-chat';
|
||||
|
||||
export function ChatDropdown({
|
||||
children,
|
||||
showChatRenameModal,
|
||||
chat,
|
||||
}: PropsWithChildren &
|
||||
Pick<ReturnType<typeof useRenameChat>, 'showChatRenameModal'> & {
|
||||
chat: IDialog;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { removeDialog } = useRemoveDialog();
|
||||
|
||||
const handleShowChatRenameModal: MouseEventHandler<HTMLDivElement> =
|
||||
useCallback(
|
||||
(e) => {
|
||||
e.stopPropagation();
|
||||
showChatRenameModal(chat);
|
||||
},
|
||||
[chat, showChatRenameModal],
|
||||
);
|
||||
|
||||
const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => {
|
||||
removeDialog([chat.id]);
|
||||
}, [chat.id, removeDialog]);
|
||||
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={handleShowChatRenameModal}>
|
||||
{t('common.rename')} <PenLine />
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
||||
<DropdownMenuItem
|
||||
className="text-text-delete-red"
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{t('common.delete')} <Trash2 />
|
||||
</DropdownMenuItem>
|
||||
</ConfirmDeleteDialog>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
45
web/src/pages/next-chats/hooks/use-rename-chat.ts
Normal file
45
web/src/pages/next-chats/hooks/use-rename-chat.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useSetDialog } from '@/hooks/use-chat-request';
|
||||
import { IDialog } from '@/interfaces/database/chat';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export const useRenameChat = () => {
|
||||
const [chat, setChat] = useState<IDialog>({} as IDialog);
|
||||
const {
|
||||
visible: chatRenameVisible,
|
||||
hideModal: hideChatRenameModal,
|
||||
showModal: showChatRenameModal,
|
||||
} = useSetModalState();
|
||||
const { setDialog, loading } = useSetDialog();
|
||||
|
||||
const onChatRenameOk = useCallback(
|
||||
async (name: string) => {
|
||||
const ret = await setDialog({
|
||||
...chat,
|
||||
name,
|
||||
});
|
||||
|
||||
if (ret === 0) {
|
||||
hideChatRenameModal();
|
||||
}
|
||||
},
|
||||
[setDialog, chat, hideChatRenameModal],
|
||||
);
|
||||
|
||||
const handleShowChatRenameModal = useCallback(
|
||||
async (record: IDialog) => {
|
||||
setChat(record);
|
||||
showChatRenameModal();
|
||||
},
|
||||
[showChatRenameModal],
|
||||
);
|
||||
|
||||
return {
|
||||
chatRenameLoading: loading,
|
||||
initialChatName: chat?.name,
|
||||
onChatRenameOk,
|
||||
chatRenameVisible,
|
||||
hideChatRenameModal,
|
||||
showChatRenameModal: handleShowChatRenameModal,
|
||||
};
|
||||
};
|
||||
@ -1,25 +1,72 @@
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useFetchChatAppList } from '@/hooks/chat-hooks';
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import { useFetchDialogList } from '@/hooks/use-chat-request';
|
||||
import { pick } from 'lodash';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ChatCard } from './chat-card';
|
||||
import { useRenameChat } from './hooks/use-rename-chat';
|
||||
|
||||
export default function ChatList() {
|
||||
const { data: chatList } = useFetchChatAppList();
|
||||
const { data: chatList, setPagination, pagination } = useFetchDialogList();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
initialChatName,
|
||||
chatRenameVisible,
|
||||
showChatRenameModal,
|
||||
hideChatRenameModal,
|
||||
onChatRenameOk,
|
||||
chatRenameLoading,
|
||||
} = useRenameChat();
|
||||
|
||||
const handlePageChange = useCallback(
|
||||
(page: number, pageSize?: number) => {
|
||||
setPagination({ page, pageSize });
|
||||
},
|
||||
[setPagination],
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="p-8">
|
||||
<ListFilterBar title="Chat apps">
|
||||
<Button variant={'tertiary'} size={'sm'}>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
Create app
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-8">
|
||||
{chatList.map((x) => {
|
||||
return <ChatCard key={x.id} data={x}></ChatCard>;
|
||||
})}
|
||||
<section className="flex flex-col w-full flex-1">
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar title="Chat apps">
|
||||
<Button>
|
||||
<Plus className="size-2.5" />
|
||||
{t('chat.createChat')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<div className="flex flex-wrap gap-4 px-8">
|
||||
{chatList.map((x) => {
|
||||
return (
|
||||
<ChatCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showChatRenameModal={showChatRenameModal}
|
||||
></ChatCard>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
{chatRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideChatRenameModal}
|
||||
onOk={onChatRenameOk}
|
||||
initialName={initialChatName}
|
||||
loading={chatRenameLoading}
|
||||
></RenameDialog>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user