From a3391c4d550d9d8899feffe30be1399ea2b6a6fe Mon Sep 17 00:00:00 2001 From: balibabu Date: Mon, 20 Jan 2025 16:49:45 +0800 Subject: [PATCH] Feat: Rename document name #3221 (#4544) ### What problem does this PR solve? Feat: Rename document name #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/components/rename-dialog/index.tsx | 56 ++++++------- .../components/rename-dialog/rename-form.tsx | 79 +++++++++++++++++++ web/src/pages/files/action-cell.tsx | 43 ++++++++-- web/src/pages/files/files-table.tsx | 24 +++++- web/src/pages/files/hooks.ts | 4 + 5 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 web/src/components/rename-dialog/rename-form.tsx diff --git a/web/src/components/rename-dialog/index.tsx b/web/src/components/rename-dialog/index.tsx index 369b726fa87..97c48f0e685 100644 --- a/web/src/components/rename-dialog/index.tsx +++ b/web/src/components/rename-dialog/index.tsx @@ -1,49 +1,39 @@ -import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, - DialogTrigger, } from '@/components/ui/dialog'; -import { Input } from '@/components/ui/input'; -import { Label } from '@/components/ui/label'; +import { LoadingButton } from '@/components/ui/loading-button'; +import { IModalProps } from '@/interfaces/common'; +import { TagRenameId } from '@/pages/add-knowledge/constant'; +import { useTranslation } from 'react-i18next'; +import { RenameForm } from './rename-form'; + +export function RenameDialog({ + hideModal, + initialName, + onOk, + loading, +}: IModalProps & { initialName: string }) { + const { t } = useTranslation(); -export function RenameDialog() { return ( - - - - + - Edit profile + {t('common.rename')} -
-
- - -
-
- - -
-
+ - + + {t('common.save')} +
diff --git a/web/src/components/rename-dialog/rename-form.tsx b/web/src/components/rename-dialog/rename-form.tsx new file mode 100644 index 00000000000..27af77bd9db --- /dev/null +++ b/web/src/components/rename-dialog/rename-form.tsx @@ -0,0 +1,79 @@ +'use client'; + +import { zodResolver } from '@hookform/resolvers/zod'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; + +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { IModalProps } from '@/interfaces/common'; +import { TagRenameId } from '@/pages/add-knowledge/constant'; +import { useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; + +export function RenameForm({ + initialName, + hideModal, + onOk, +}: IModalProps & { initialName: string }) { + const { t } = useTranslation(); + const FormSchema = z.object({ + name: z + .string() + .min(1, { + message: t('common.namePlaceholder'), + }) + .trim(), + }); + + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { name: '' }, + }); + + async function onSubmit(data: z.infer) { + const ret = await onOk?.(data.name); + if (ret) { + hideModal?.(); + } + } + + useEffect(() => { + form.setValue('name', initialName); + }, [form, initialName]); + + return ( +
+ + ( + + {t('common.name')} + + + + + + )} + /> + + + ); +} diff --git a/web/src/pages/files/action-cell.tsx b/web/src/pages/files/action-cell.tsx index f56d596e606..d91422fe264 100644 --- a/web/src/pages/files/action-cell.tsx +++ b/web/src/pages/files/action-cell.tsx @@ -4,26 +4,49 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, - DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; +import { useDownloadFile } from '@/hooks/file-manager-hooks'; import { IFile } from '@/interfaces/database/file-manager'; import { CellContext } from '@tanstack/react-table'; import { EllipsisVertical, Link2, Trash2 } from 'lucide-react'; import { useCallback } from 'react'; -import { UseHandleConnectToKnowledgeReturnType } from './hooks'; +import { useTranslation } from 'react-i18next'; +import { + UseHandleConnectToKnowledgeReturnType, + UseRenameCurrentFileReturnType, +} from './hooks'; type IProps = Pick, 'row'> & - Pick; + Pick & + Pick; -export function ActionCell({ row, showConnectToKnowledgeModal }: IProps) { +export function ActionCell({ + row, + showConnectToKnowledgeModal, + showFileRenameModal, +}: IProps) { + const { t } = useTranslation(); const record = row.original; + const documentId = record.id; + const { downloadFile } = useDownloadFile(); const handleShowConnectToKnowledgeModal = useCallback(() => { showConnectToKnowledgeModal(record); }, [record, showConnectToKnowledgeModal]); + const onDownloadDocument = useCallback(() => { + downloadFile({ + id: documentId, + filename: record.name, + }); + }, [documentId, downloadFile, record.name]); + + const handleShowFileRenameModal = useCallback(() => { + showFileRenameModal(record); + }, [record, showFileRenameModal]); + return (
diff --git a/web/src/pages/files/files-table.tsx b/web/src/pages/files/files-table.tsx index d22420eb1e3..ed3f7643956 100644 --- a/web/src/pages/files/files-table.tsx +++ b/web/src/pages/files/files-table.tsx @@ -14,6 +14,7 @@ import { import { ArrowUpDown } from 'lucide-react'; import * as React from 'react'; +import { RenameDialog } from '@/components/rename-dialog'; import SvgIcon from '@/components/svg-icon'; import { TableEmpty, TableSkeleton } from '@/components/table-skeleton'; import { Badge } from '@/components/ui/badge'; @@ -41,7 +42,11 @@ import { getExtension } from '@/utils/document-util'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { ActionCell } from './action-cell'; -import { useHandleConnectToKnowledge, useNavigateToOtherFolder } from './hooks'; +import { + useHandleConnectToKnowledge, + useNavigateToOtherFolder, + useRenameCurrentFile, +} from './hooks'; import { LinkToDatasetDialog } from './link-to-dataset-dialog'; export function FilesTable() { @@ -64,6 +69,14 @@ export function FilesTable() { onConnectToKnowledgeOk, connectToKnowledgeLoading, } = useHandleConnectToKnowledge(); + const { + fileRenameVisible, + showFileRenameModal, + hideFileRenameModal, + onFileRenameOk, + initialFileName, + fileRenameLoading, + } = useRenameCurrentFile(); const { pagination, data, loading, setPagination } = useFetchFileList(); @@ -208,6 +221,7 @@ export function FilesTable() { ); }, @@ -341,6 +355,14 @@ export function FilesTable() { loading={connectToKnowledgeLoading} > )} + {fileRenameVisible && ( + + )} ); } diff --git a/web/src/pages/files/hooks.ts b/web/src/pages/files/hooks.ts index 9a891d711ba..3b13e719edb 100644 --- a/web/src/pages/files/hooks.ts +++ b/web/src/pages/files/hooks.ts @@ -90,6 +90,10 @@ export const useRenameCurrentFile = () => { }; }; +export type UseRenameCurrentFileReturnType = ReturnType< + typeof useRenameCurrentFile +>; + export const useSelectBreadcrumbItems = () => { const parentFolderList = useFetchParentFolderList();