diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index ee8b2144c..645a32b89 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -1,22 +1,60 @@ import { IFlow } from '@/interfaces/database/flow'; import flowService from '@/services/flow-service'; import { useQuery } from '@tanstack/react-query'; +import { useDebounce } from 'ahooks'; +import { useCallback } from 'react'; +import { + useGetPaginationWithRouter, + useHandleSearchChange, +} from './logic-hooks'; export const enum AgentApiAction { FetchAgentList = 'fetchAgentList', } -export const useFetchAgentList = () => { - const { data, isFetching: loading } = useQuery({ - queryKey: [AgentApiAction.FetchAgentList], - initialData: [], +export const useFetchAgentListByPage = () => { + const { searchString, handleInputChange } = useHandleSearchChange(); + const { pagination, setPagination } = useGetPaginationWithRouter(); + const debouncedSearchString = useDebounce(searchString, { wait: 500 }); + + const { data, isFetching: loading } = useQuery<{ + kbs: IFlow[]; + total: number; + }>({ + queryKey: [ + AgentApiAction.FetchAgentList, + { + debouncedSearchString, + ...pagination, + }, + ], + initialData: { kbs: [], total: 0 }, gcTime: 0, queryFn: async () => { - const { data } = await flowService.listCanvas(); + const { data } = await flowService.listCanvasTeam({ + keywords: debouncedSearchString, + page_size: pagination.pageSize, + page: pagination.current, + }); return data?.data ?? []; }, }); - return { data, loading }; + const onInputChange: React.ChangeEventHandler = useCallback( + (e) => { + // setPagination({ page: 1 }); // TODO: 这里导致重复请求 + handleInputChange(e); + }, + [handleInputChange], + ); + + return { + data: data.kbs, + loading, + searchString, + handleInputChange: onInputChange, + pagination: { ...pagination, total: data?.total }, + setPagination, + }; }; diff --git a/web/src/pages/agents/agent-card.tsx b/web/src/pages/agents/agent-card.tsx index dd72295ac..41ef85003 100644 --- a/web/src/pages/agents/agent-card.tsx +++ b/web/src/pages/agents/agent-card.tsx @@ -1,56 +1,47 @@ +import { MoreButton } from '@/components/more-button'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; -import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { IFlow } from '@/interfaces/database/flow'; -import { formatPureDate } from '@/utils/date'; -import { ChevronRight, Trash2 } from 'lucide-react'; +import { formatDate } from '@/utils/date'; +import { AgentDropdown } from './agent-dropdown'; +import { useRenameAgent } from './use-rename-agent'; -interface IProps { +export type DatasetCardProps = { data: IFlow; -} +} & Pick, 'showDatasetRenameModal'>; -export function AgentCard({ data }: IProps) { +export function AgentCard({ data, showDatasetRenameModal }: DatasetCardProps) { const { navigateToAgent } = useNavigatePage(); return ( - - -
- {data.avatar ? ( -
- ) : ( - - - CN + + +
+
+ + + CN - )} -
-

{data.title}

-

An app that does things An app that does things

-
-
- Search app -

- {formatPureDate(data.update_time)} +

+ + + +
+
+
+

+ {data.title} +

+

{data.description}

+

+ {formatDate(data.update_time)}

-
- - -
-
+
); diff --git a/web/src/pages/agents/agent-dropdown.tsx b/web/src/pages/agents/agent-dropdown.tsx new file mode 100644 index 000000000..d9030e7c2 --- /dev/null +++ b/web/src/pages/agents/agent-dropdown.tsx @@ -0,0 +1,64 @@ +import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; +import { useDeleteKnowledge } from '@/hooks/use-knowledge-request'; +import { IFlow } from '@/interfaces/database/flow'; +import { PenLine, Trash2 } from 'lucide-react'; +import { MouseEventHandler, PropsWithChildren, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { useRenameAgent } from './use-rename-agent'; + +export function AgentDropdown({ + children, + showDatasetRenameModal, + dataset, +}: PropsWithChildren & + Pick, 'showDatasetRenameModal'> & { + dataset: IFlow; + }) { + const { t } = useTranslation(); + const { deleteKnowledge } = useDeleteKnowledge(); + + const handleShowDatasetRenameModal: MouseEventHandler = + useCallback( + (e) => { + e.stopPropagation(); + showDatasetRenameModal(dataset); + }, + [dataset, showDatasetRenameModal], + ); + + const handleDelete: MouseEventHandler = useCallback(() => { + deleteKnowledge(dataset.id); + }, [dataset.id, deleteKnowledge]); + + return ( + + {children} + + + {t('common.rename')} + + + + { + e.preventDefault(); + }} + onClick={(e) => { + e.stopPropagation(); + }} + > + {t('common.delete')} + + + + + ); +} diff --git a/web/src/pages/agents/index.tsx b/web/src/pages/agents/index.tsx index 117275e27..7bb80780c 100644 --- a/web/src/pages/agents/index.tsx +++ b/web/src/pages/agents/index.tsx @@ -1,33 +1,76 @@ import ListFilterBar from '@/components/list-filter-bar'; +import { RenameDialog } from '@/components/rename-dialog'; import { Button } from '@/components/ui/button'; -import { useFetchFlowList } from '@/hooks/flow-hooks'; +import { RAGFlowPagination } from '@/components/ui/ragflow-pagination'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; +import { useFetchAgentListByPage } from '@/hooks/use-agent-request'; +import { pick } from 'lodash'; import { Plus } from 'lucide-react'; +import { useCallback } from 'react'; import { AgentCard } from './agent-card'; +import { useRenameAgent } from './use-rename-agent'; export default function Agent() { - const { data } = useFetchFlowList(); + const { data, pagination, setPagination, searchString, handleInputChange } = + useFetchAgentListByPage(); const { navigateToAgentTemplates } = useNavigatePage(); + const { + datasetRenameLoading, + initialDatasetName, + onDatasetRenameOk, + datasetRenameVisible, + hideDatasetRenameModal, + showDatasetRenameModal, + } = useRenameAgent(); + + const handlePageChange = useCallback( + (page: number, pageSize?: number) => { + setPagination({ page, pageSize }); + }, + [setPagination], + ); + return (
- -
-
+
{data.map((x) => { - return ; + return ( + + ); })}
+
+ +
+ {datasetRenameVisible && ( + + )}
); } diff --git a/web/src/pages/agents/use-rename-agent.ts b/web/src/pages/agents/use-rename-agent.ts new file mode 100644 index 000000000..2022ee6fd --- /dev/null +++ b/web/src/pages/agents/use-rename-agent.ts @@ -0,0 +1,53 @@ +import { useSetModalState } from '@/hooks/common-hooks'; +import { useUpdateKnowledge } from '@/hooks/use-knowledge-request'; +import { IFlow } from '@/interfaces/database/flow'; +import { omit } from 'lodash'; +import { useCallback, useState } from 'react'; + +export const useRenameAgent = () => { + const [dataset, setDataset] = useState({} as IFlow); + const { + visible: datasetRenameVisible, + hideModal: hideDatasetRenameModal, + showModal: showDatasetRenameModal, + } = useSetModalState(); + const { saveKnowledgeConfiguration, loading } = useUpdateKnowledge(true); + + const onDatasetRenameOk = useCallback( + async (name: string) => { + const ret = await saveKnowledgeConfiguration({ + ...omit(dataset, [ + 'id', + 'update_time', + 'nickname', + 'tenant_avatar', + 'tenant_id', + ]), + kb_id: dataset.id, + name, + }); + + if (ret.code === 0) { + hideDatasetRenameModal(); + } + }, + [saveKnowledgeConfiguration, dataset, hideDatasetRenameModal], + ); + + const handleShowDatasetRenameModal = useCallback( + async (record: IFlow) => { + setDataset(record); + showDatasetRenameModal(); + }, + [showDatasetRenameModal], + ); + + return { + datasetRenameLoading: loading, + initialDatasetName: dataset?.title, + onDatasetRenameOk, + datasetRenameVisible, + hideDatasetRenameModal, + showDatasetRenameModal: handleShowDatasetRenameModal, + }; +}; diff --git a/web/src/pages/home/agent-list.tsx b/web/src/pages/home/agent-list.tsx index 043862957..ee5965e27 100644 --- a/web/src/pages/home/agent-list.tsx +++ b/web/src/pages/home/agent-list.tsx @@ -1,8 +1,8 @@ -import { useFetchAgentList } from '@/hooks/use-agent-request'; +import { useFetchAgentListByPage } from '@/hooks/use-agent-request'; import { ApplicationCard } from './application-card'; export function Agents() { - const { data } = useFetchAgentList(); + const { data } = useFetchAgentListByPage(); return data .slice(0, 10)