### What problem does this PR solve? Feat: Rename agent #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.x
| import { IFlow } from '@/interfaces/database/flow'; | import { IFlow } from '@/interfaces/database/flow'; | ||||
| import flowService from '@/services/flow-service'; | import flowService from '@/services/flow-service'; | ||||
| import { useQuery } from '@tanstack/react-query'; | |||||
| import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | |||||
| import { useDebounce } from 'ahooks'; | import { useDebounce } from 'ahooks'; | ||||
| import { message } from 'antd'; | |||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
| import { | import { | ||||
| useGetPaginationWithRouter, | useGetPaginationWithRouter, | ||||
| export const enum AgentApiAction { | export const enum AgentApiAction { | ||||
| FetchAgentList = 'fetchAgentList', | FetchAgentList = 'fetchAgentList', | ||||
| UpdateAgentSetting = 'updateAgentSetting', | |||||
| DeleteAgent = 'deleteAgent', | |||||
| } | } | ||||
| export const useFetchAgentListByPage = () => { | export const useFetchAgentListByPage = () => { | ||||
| setPagination, | setPagination, | ||||
| }; | }; | ||||
| }; | }; | ||||
| export const useUpdateAgentSetting = () => { | |||||
| const queryClient = useQueryClient(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: [AgentApiAction.UpdateAgentSetting], | |||||
| mutationFn: async (params: any) => { | |||||
| const ret = await flowService.settingCanvas(params); | |||||
| if (ret?.data?.code === 0) { | |||||
| message.success('success'); | |||||
| queryClient.invalidateQueries({ | |||||
| queryKey: [AgentApiAction.FetchAgentList], | |||||
| }); | |||||
| } else { | |||||
| message.error(ret?.data?.data); | |||||
| } | |||||
| return ret?.data?.code; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, updateAgentSetting: mutateAsync }; | |||||
| }; | |||||
| export const useDeleteAgent = () => { | |||||
| const queryClient = useQueryClient(); | |||||
| const { | |||||
| data, | |||||
| isPending: loading, | |||||
| mutateAsync, | |||||
| } = useMutation({ | |||||
| mutationKey: [AgentApiAction.DeleteAgent], | |||||
| mutationFn: async (canvasIds: string[]) => { | |||||
| const { data } = await flowService.removeCanvas({ canvasIds }); | |||||
| if (data.code === 0) { | |||||
| queryClient.invalidateQueries({ | |||||
| queryKey: [AgentApiAction.FetchAgentList], | |||||
| }); | |||||
| } | |||||
| return data?.data ?? []; | |||||
| }, | |||||
| }); | |||||
| return { data, loading, deleteAgent: mutateAsync }; | |||||
| }; |
| export type DatasetCardProps = { | export type DatasetCardProps = { | ||||
| data: IFlow; | data: IFlow; | ||||
| } & Pick<ReturnType<typeof useRenameAgent>, 'showDatasetRenameModal'>; | |||||
| } & Pick<ReturnType<typeof useRenameAgent>, 'showAgentRenameModal'>; | |||||
| export function AgentCard({ data, showDatasetRenameModal }: DatasetCardProps) { | |||||
| export function AgentCard({ data, showAgentRenameModal }: DatasetCardProps) { | |||||
| const { navigateToAgent } = useNavigatePage(); | const { navigateToAgent } = useNavigatePage(); | ||||
| return ( | return ( | ||||
| </Avatar> | </Avatar> | ||||
| </div> | </div> | ||||
| <AgentDropdown | <AgentDropdown | ||||
| showDatasetRenameModal={showDatasetRenameModal} | |||||
| dataset={data} | |||||
| showAgentRenameModal={showAgentRenameModal} | |||||
| agent={data} | |||||
| > | > | ||||
| <MoreButton></MoreButton> | <MoreButton></MoreButton> | ||||
| </AgentDropdown> | </AgentDropdown> |
| DropdownMenuSeparator, | DropdownMenuSeparator, | ||||
| DropdownMenuTrigger, | DropdownMenuTrigger, | ||||
| } from '@/components/ui/dropdown-menu'; | } from '@/components/ui/dropdown-menu'; | ||||
| import { useDeleteKnowledge } from '@/hooks/use-knowledge-request'; | |||||
| import { useDeleteAgent } from '@/hooks/use-agent-request'; | |||||
| import { IFlow } from '@/interfaces/database/flow'; | import { IFlow } from '@/interfaces/database/flow'; | ||||
| import { PenLine, Trash2 } from 'lucide-react'; | import { PenLine, Trash2 } from 'lucide-react'; | ||||
| import { MouseEventHandler, PropsWithChildren, useCallback } from 'react'; | import { MouseEventHandler, PropsWithChildren, useCallback } from 'react'; | ||||
| export function AgentDropdown({ | export function AgentDropdown({ | ||||
| children, | children, | ||||
| showDatasetRenameModal, | |||||
| dataset, | |||||
| showAgentRenameModal, | |||||
| agent: agent, | |||||
| }: PropsWithChildren & | }: PropsWithChildren & | ||||
| Pick<ReturnType<typeof useRenameAgent>, 'showDatasetRenameModal'> & { | |||||
| dataset: IFlow; | |||||
| Pick<ReturnType<typeof useRenameAgent>, 'showAgentRenameModal'> & { | |||||
| agent: IFlow; | |||||
| }) { | }) { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { deleteKnowledge } = useDeleteKnowledge(); | |||||
| const { deleteAgent } = useDeleteAgent(); | |||||
| const handleShowDatasetRenameModal: MouseEventHandler<HTMLDivElement> = | |||||
| const handleShowAgentRenameModal: MouseEventHandler<HTMLDivElement> = | |||||
| useCallback( | useCallback( | ||||
| (e) => { | (e) => { | ||||
| e.stopPropagation(); | e.stopPropagation(); | ||||
| showDatasetRenameModal(dataset); | |||||
| showAgentRenameModal(agent); | |||||
| }, | }, | ||||
| [dataset, showDatasetRenameModal], | |||||
| [agent, showAgentRenameModal], | |||||
| ); | ); | ||||
| const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => { | const handleDelete: MouseEventHandler<HTMLDivElement> = useCallback(() => { | ||||
| deleteKnowledge(dataset.id); | |||||
| }, [dataset.id, deleteKnowledge]); | |||||
| deleteAgent([agent.id]); | |||||
| }, [agent.id, deleteAgent]); | |||||
| return ( | return ( | ||||
| <DropdownMenu> | <DropdownMenu> | ||||
| <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger> | <DropdownMenuTrigger asChild>{children}</DropdownMenuTrigger> | ||||
| <DropdownMenuContent> | <DropdownMenuContent> | ||||
| <DropdownMenuItem onClick={handleShowDatasetRenameModal}> | |||||
| <DropdownMenuItem onClick={handleShowAgentRenameModal}> | |||||
| {t('common.rename')} <PenLine /> | {t('common.rename')} <PenLine /> | ||||
| </DropdownMenuItem> | </DropdownMenuItem> | ||||
| <DropdownMenuSeparator /> | <DropdownMenuSeparator /> |
| const { navigateToAgentTemplates } = useNavigatePage(); | const { navigateToAgentTemplates } = useNavigatePage(); | ||||
| const { | const { | ||||
| datasetRenameLoading, | |||||
| initialDatasetName, | |||||
| onDatasetRenameOk, | |||||
| datasetRenameVisible, | |||||
| hideDatasetRenameModal, | |||||
| showDatasetRenameModal, | |||||
| agentRenameLoading, | |||||
| initialAgentName, | |||||
| onAgentRenameOk, | |||||
| agentRenameVisible, | |||||
| hideAgentRenameModal, | |||||
| showAgentRenameModal, | |||||
| } = useRenameAgent(); | } = useRenameAgent(); | ||||
| const handlePageChange = useCallback( | const handlePageChange = useCallback( | ||||
| <AgentCard | <AgentCard | ||||
| key={x.id} | key={x.id} | ||||
| data={x} | data={x} | ||||
| showDatasetRenameModal={showDatasetRenameModal} | |||||
| showAgentRenameModal={showAgentRenameModal} | |||||
| ></AgentCard> | ></AgentCard> | ||||
| ); | ); | ||||
| })} | })} | ||||
| onChange={handlePageChange} | onChange={handlePageChange} | ||||
| ></RAGFlowPagination> | ></RAGFlowPagination> | ||||
| </div> | </div> | ||||
| {datasetRenameVisible && ( | |||||
| {agentRenameVisible && ( | |||||
| <RenameDialog | <RenameDialog | ||||
| hideModal={hideDatasetRenameModal} | |||||
| onOk={onDatasetRenameOk} | |||||
| initialName={initialDatasetName} | |||||
| loading={datasetRenameLoading} | |||||
| hideModal={hideAgentRenameModal} | |||||
| onOk={onAgentRenameOk} | |||||
| initialName={initialAgentName} | |||||
| loading={agentRenameLoading} | |||||
| ></RenameDialog> | ></RenameDialog> | ||||
| )} | )} | ||||
| </section> | </section> |
| import { useSetModalState } from '@/hooks/common-hooks'; | import { useSetModalState } from '@/hooks/common-hooks'; | ||||
| import { useUpdateKnowledge } from '@/hooks/use-knowledge-request'; | |||||
| import { useUpdateAgentSetting } from '@/hooks/use-agent-request'; | |||||
| import { IFlow } from '@/interfaces/database/flow'; | import { IFlow } from '@/interfaces/database/flow'; | ||||
| import { omit } from 'lodash'; | |||||
| import { pick } from 'lodash'; | |||||
| import { useCallback, useState } from 'react'; | import { useCallback, useState } from 'react'; | ||||
| export const useRenameAgent = () => { | export const useRenameAgent = () => { | ||||
| const [dataset, setDataset] = useState<IFlow>({} as IFlow); | |||||
| const [agent, setAgent] = useState<IFlow>({} as IFlow); | |||||
| const { | const { | ||||
| visible: datasetRenameVisible, | |||||
| hideModal: hideDatasetRenameModal, | |||||
| showModal: showDatasetRenameModal, | |||||
| visible: agentRenameVisible, | |||||
| hideModal: hideAgentRenameModal, | |||||
| showModal: showAgentRenameModal, | |||||
| } = useSetModalState(); | } = useSetModalState(); | ||||
| const { saveKnowledgeConfiguration, loading } = useUpdateKnowledge(true); | |||||
| const { updateAgentSetting, loading } = useUpdateAgentSetting(); | |||||
| const onDatasetRenameOk = useCallback( | |||||
| const onAgentRenameOk = useCallback( | |||||
| async (name: string) => { | async (name: string) => { | ||||
| const ret = await saveKnowledgeConfiguration({ | |||||
| ...omit(dataset, [ | |||||
| 'id', | |||||
| 'update_time', | |||||
| 'nickname', | |||||
| 'tenant_avatar', | |||||
| 'tenant_id', | |||||
| ]), | |||||
| kb_id: dataset.id, | |||||
| name, | |||||
| const ret = await updateAgentSetting({ | |||||
| ...pick(agent, ['id', 'avatar', 'description', 'permission']), | |||||
| title: name, | |||||
| }); | }); | ||||
| if (ret.code === 0) { | |||||
| hideDatasetRenameModal(); | |||||
| if (ret === 0) { | |||||
| hideAgentRenameModal(); | |||||
| } | } | ||||
| }, | }, | ||||
| [saveKnowledgeConfiguration, dataset, hideDatasetRenameModal], | |||||
| [updateAgentSetting, agent, hideAgentRenameModal], | |||||
| ); | ); | ||||
| const handleShowDatasetRenameModal = useCallback( | |||||
| const handleShowAgentRenameModal = useCallback( | |||||
| async (record: IFlow) => { | async (record: IFlow) => { | ||||
| setDataset(record); | |||||
| showDatasetRenameModal(); | |||||
| setAgent(record); | |||||
| showAgentRenameModal(); | |||||
| }, | }, | ||||
| [showDatasetRenameModal], | |||||
| [showAgentRenameModal], | |||||
| ); | ); | ||||
| return { | return { | ||||
| datasetRenameLoading: loading, | |||||
| initialDatasetName: dataset?.title, | |||||
| onDatasetRenameOk, | |||||
| datasetRenameVisible, | |||||
| hideDatasetRenameModal, | |||||
| showDatasetRenameModal: handleShowDatasetRenameModal, | |||||
| agentRenameLoading: loading, | |||||
| initialAgentName: agent?.title, | |||||
| onAgentRenameOk, | |||||
| agentRenameVisible, | |||||
| hideAgentRenameModal, | |||||
| showAgentRenameModal: handleShowAgentRenameModal, | |||||
| }; | }; | ||||
| }; | }; |