import message from '@/components/ui/message'; import { IFetchFileListResult, IFolder, } from '@/interfaces/database/file-manager'; import fileManagerService from '@/services/file-manager-service'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useDebounce } from 'ahooks'; import { PaginationProps } from 'antd'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useSearchParams } from 'umi'; import { useGetPaginationWithRouter, useHandleSearchChange, } from './logic-hooks'; import { useSetPaginationParams } from './route-hook'; export const enum FileApiAction { UploadFile = 'uploadFile', FetchFileList = 'fetchFileList', MoveFile = 'moveFile', CreateFolder = 'createFolder', FetchParentFolderList = 'fetchParentFolderList', DeleteFile = 'deleteFile', } export const useGetFolderId = () => { const [searchParams] = useSearchParams(); const id = searchParams.get('folderId') as string; return id ?? ''; }; export const useUploadFile = () => { const { setPaginationParams } = useSetPaginationParams(); const { t } = useTranslation(); const queryClient = useQueryClient(); const { data, isPending: loading, mutateAsync, } = useMutation({ mutationKey: [FileApiAction.UploadFile], mutationFn: async (params: { fileList: File[]; parentId: string }) => { const fileList = params.fileList; const pathList = params.fileList.map( (file) => (file as any).webkitRelativePath, ); const formData = new FormData(); formData.append('parent_id', params.parentId); fileList.forEach((file: any, index: number) => { formData.append('file', file); formData.append('path', pathList[index]); }); try { const ret = await fileManagerService.uploadFile(formData); if (ret?.data.code === 0) { message.success(t('message.uploaded')); setPaginationParams(1); queryClient.invalidateQueries({ queryKey: [FileApiAction.FetchFileList], }); } return ret?.data?.code; } catch (error) {} }, }); return { data, loading, uploadFile: mutateAsync }; }; export interface IMoveFileBody { src_file_ids: string[]; dest_file_id: string; // target folder id } export const useMoveFile = () => { const queryClient = useQueryClient(); const { t } = useTranslation(); const { data, isPending: loading, mutateAsync, } = useMutation({ mutationKey: [FileApiAction.MoveFile], mutationFn: async (params: IMoveFileBody) => { const { data } = await fileManagerService.moveFile(params); if (data.code === 0) { message.success(t('message.operated')); queryClient.invalidateQueries({ queryKey: [FileApiAction.FetchFileList], }); } return data.code; }, }); return { data, loading, moveFile: mutateAsync }; }; export const useCreateFolder = () => { const { setPaginationParams } = useSetPaginationParams(); const queryClient = useQueryClient(); const { t } = useTranslation(); const { data, isPending: loading, mutateAsync, } = useMutation({ mutationKey: [FileApiAction.CreateFolder], mutationFn: async (params: { parentId: string; name: string }) => { const { data } = await fileManagerService.createFolder({ ...params, type: 'folder', }); if (data.code === 0) { message.success(t('message.created')); setPaginationParams(1); queryClient.invalidateQueries({ queryKey: [FileApiAction.FetchFileList], }); } return data.code; }, }); return { data, loading, createFolder: mutateAsync }; }; export const useFetchParentFolderList = () => { const id = useGetFolderId(); const { data } = useQuery({ queryKey: [FileApiAction.FetchParentFolderList, id], initialData: [], enabled: !!id, queryFn: async () => { const { data } = await fileManagerService.getAllParentFolder({ fileId: id, }); return data?.data?.parent_folders?.toReversed() ?? []; }, }); return data; }; export interface IListResult { searchString: string; handleInputChange: React.ChangeEventHandler; pagination: PaginationProps; setPagination: (pagination: { page: number; pageSize: number }) => void; loading: boolean; } export const useFetchFileList = () => { const { searchString, handleInputChange } = useHandleSearchChange(); const { pagination, setPagination } = useGetPaginationWithRouter(); const id = useGetFolderId(); const debouncedSearchString = useDebounce(searchString, { wait: 500 }); const { data, isFetching: loading } = useQuery({ queryKey: [ FileApiAction.FetchFileList, { id, debouncedSearchString, ...pagination, }, ], initialData: { files: [], parent_folder: {} as IFolder, total: 0 }, gcTime: 0, queryFn: async () => { const { data } = await fileManagerService.listFile({ parent_id: id, keywords: debouncedSearchString, page_size: pagination.pageSize, page: pagination.current, }); return data?.data; }, }); const onInputChange: React.ChangeEventHandler = useCallback( (e) => { setPagination({ page: 1 }); handleInputChange(e); }, [handleInputChange, setPagination], ); return { ...data, searchString, handleInputChange: onInputChange, pagination: { ...pagination, total: data?.total }, setPagination, loading, }; }; export const useDeleteFile = () => { const { setPaginationParams } = useSetPaginationParams(); const queryClient = useQueryClient(); const { t } = useTranslation(); const { data, isPending: loading, mutateAsync, } = useMutation({ mutationKey: [FileApiAction.DeleteFile], mutationFn: async (params: { fileIds: string[]; parentId: string }) => { const { data } = await fileManagerService.removeFile(params); if (data.code === 0) { message.success(t('message.deleted')); setPaginationParams(1); // TODO: There should be a better way to paginate the request list queryClient.invalidateQueries({ queryKey: [FileApiAction.FetchFileList], }); } return data.code; }, }); return { data, loading, deleteFile: mutateAsync }; };