From f11f7a9cff2909819c64ed1e193a98edfd9317d7 Mon Sep 17 00:00:00 2001 From: balibabu Date: Thu, 25 Apr 2024 19:06:24 +0800 Subject: [PATCH] feat: add file icon to table of FileManager #345 (#543) ### What problem does this PR solve? feat: add file icon to table of FileManager #345 fix: modify datasetDescription ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/assets/svg/file-icon/folder.svg | 18 +++ web/src/base.ts | 48 +++++++ web/src/hooks/fileManagerHooks.ts | 6 +- web/src/hooks/knowledgeHook.ts | 6 +- web/src/hooks/logicHooks.ts | 55 +++++++- web/src/interfaces/common.ts | 1 + web/src/locales/en.ts | 2 +- web/src/locales/zh-traditional.ts | 2 +- web/src/locales/zh.ts | 2 +- .../pages/file-manager/action-cell/index.tsx | 29 ++-- .../connect-to-knowledge-modal/index.tsx | 29 ++-- web/src/pages/file-manager/file-toolbar.tsx | 13 +- .../file-manager/file-upload-modal/index.tsx | 13 +- web/src/pages/file-manager/hooks.ts | 132 ++++++++---------- web/src/pages/file-manager/index.less | 4 + web/src/pages/file-manager/index.tsx | 54 +++++-- web/src/pages/file-manager/model.ts | 48 ++++++- web/src/pages/knowledge/model.ts | 2 +- web/src/utils/fileUtil.ts | 9 -- 19 files changed, 318 insertions(+), 155 deletions(-) create mode 100644 web/src/assets/svg/file-icon/folder.svg create mode 100644 web/src/base.ts diff --git a/web/src/assets/svg/file-icon/folder.svg b/web/src/assets/svg/file-icon/folder.svg new file mode 100644 index 0000000000..e522b7823a --- /dev/null +++ b/web/src/assets/svg/file-icon/folder.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/base.ts b/web/src/base.ts new file mode 100644 index 0000000000..b453ca4831 --- /dev/null +++ b/web/src/base.ts @@ -0,0 +1,48 @@ +import isObject from 'lodash/isObject'; +import { DvaModel } from 'umi'; +import { BaseState } from './interfaces/common'; + +type State = Record; +type DvaModelKey = keyof DvaModel; + +export const modelExtend = ( + baseModel: Partial>, + extendModel: DvaModel, +): DvaModel => { + return Object.keys(extendModel).reduce>((pre, cur) => { + const baseValue = baseModel[cur as DvaModelKey]; + const value = extendModel[cur as DvaModelKey]; + + if (isObject(value) && isObject(baseValue) && typeof value !== 'string') { + const key = cur as Exclude, 'namespace'>; + + pre[key] = { + ...baseValue, + ...value, + } as any; + } else { + pre[cur as DvaModelKey] = value as any; + } + + return pre; + }, {} as DvaModel); +}; + +export const paginationModel: Partial> = { + state: { + searchString: '', + pagination: { + total: 0, + current: 1, + pageSize: 10, + }, + }, + reducers: { + setSearchString(state, { payload }) { + return { ...state, searchString: payload }; + }, + setPagination(state, { payload }) { + return { ...state, pagination: { ...state.pagination, ...payload } }; + }, + }, +}; diff --git a/web/src/hooks/fileManagerHooks.ts b/web/src/hooks/fileManagerHooks.ts index 0c863e8a3f..ce34653363 100644 --- a/web/src/hooks/fileManagerHooks.ts +++ b/web/src/hooks/fileManagerHooks.ts @@ -103,14 +103,14 @@ export const useUploadFile = () => { const dispatch = useDispatch(); const uploadFile = useCallback( - (file: UploadFile, parentId: string, path: string) => { + (fileList: UploadFile[], parentId: string) => { try { return dispatch({ type: 'fileManager/uploadFile', payload: { - file, + file: fileList, parentId, - path, + path: fileList.map((file) => (file as any).webkitRelativePath), }, }); } catch (errorInfo) { diff --git a/web/src/hooks/knowledgeHook.ts b/web/src/hooks/knowledgeHook.ts index 2904aee07b..d2562c97b6 100644 --- a/web/src/hooks/knowledgeHook.ts +++ b/web/src/hooks/knowledgeHook.ts @@ -127,13 +127,13 @@ export const useFetchKnowledgeBaseConfiguration = () => { export const useFetchKnowledgeList = ( shouldFilterListWithoutDocument: boolean = false, -): { list: IKnowledge[]; loading: boolean } => { +) => { const dispatch = useDispatch(); const loading = useOneNamespaceEffectsLoading('knowledgeModel', ['getList']); const knowledgeModel = useSelector((state: any) => state.knowledgeModel); const { data = [] } = knowledgeModel; - const list = useMemo(() => { + const list: IKnowledge[] = useMemo(() => { return shouldFilterListWithoutDocument ? data.filter((x: IKnowledge) => x.chunk_num > 0) : data; @@ -149,7 +149,7 @@ export const useFetchKnowledgeList = ( fetchList(); }, [fetchList]); - return { list, loading }; + return { list, loading, fetchList }; }; export const useSelectFileThumbnails = () => { diff --git a/web/src/hooks/logicHooks.ts b/web/src/hooks/logicHooks.ts index b1319dc455..f9d628059d 100644 --- a/web/src/hooks/logicHooks.ts +++ b/web/src/hooks/logicHooks.ts @@ -1,9 +1,12 @@ import { LanguageTranslationMap } from '@/constants/common'; +import { Pagination } from '@/interfaces/common'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; import { IChangeParserConfigRequestBody } from '@/interfaces/request/document'; -import { useCallback, useState } from 'react'; +import { PaginationProps } from 'antd'; +import { useCallback, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { useSetModalState } from './commonHooks'; +import { useDispatch } from 'umi'; +import { useSetModalState, useTranslate } from './commonHooks'; import { useSetDocumentParser } from './documentHooks'; import { useOneNamespaceEffectsLoading } from './storeHooks'; import { useSaveSetting } from './userSettingHook'; @@ -62,3 +65,51 @@ export const useChangeLanguage = () => { return changeLanguage; }; + +export const useGetPagination = ( + total: number, + page: number, + pageSize: number, + onPageChange: PaginationProps['onChange'], +) => { + const { t } = useTranslate('common'); + + const pagination: PaginationProps = useMemo(() => { + return { + showQuickJumper: true, + total, + showSizeChanger: true, + current: page, + pageSize: pageSize, + pageSizeOptions: [1, 2, 10, 20, 50, 100], + onChange: onPageChange, + showTotal: (total) => `${t('total')} ${total}`, + }; + }, [t, onPageChange, page, pageSize, total]); + + return { + pagination, + }; +}; + +export const useSetPagination = (namespace: string) => { + const dispatch = useDispatch(); + + const setPagination = useCallback( + (pageNumber = 1, pageSize?: number) => { + const pagination: Pagination = { + current: pageNumber, + } as Pagination; + if (pageSize) { + pagination.pageSize = pageSize; + } + dispatch({ + type: `${namespace}/setPagination`, + payload: pagination, + }); + }, + [dispatch, namespace], + ); + + return setPagination; +}; diff --git a/web/src/interfaces/common.ts b/web/src/interfaces/common.ts index 76a385fee5..180f20856c 100644 --- a/web/src/interfaces/common.ts +++ b/web/src/interfaces/common.ts @@ -1,6 +1,7 @@ export interface Pagination { current: number; pageSize: number; + total: number; } export interface BaseState { diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index e23684613f..2666319d61 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -70,7 +70,7 @@ export default { namePlaceholder: 'Please input name!', doc: 'Docs', datasetDescription: - "Hey, don't forget to adjust the chunk after adding the dataset! 😉", + '😉 Questions and answers can only be answered after the parsing is successful.', addFile: 'Add file', searchFiles: 'Search your files', localFiles: 'Local files', diff --git a/web/src/locales/zh-traditional.ts b/web/src/locales/zh-traditional.ts index e6b500e1b5..c0b559cc0f 100644 --- a/web/src/locales/zh-traditional.ts +++ b/web/src/locales/zh-traditional.ts @@ -69,7 +69,7 @@ export default { name: '名稱', namePlaceholder: '請輸入名稱', doc: '文件', - datasetDescription: '嘿,添加數據集後別忘了調整解析塊!😉', + datasetDescription: '😉 解析成功後才能問答哦。', addFile: '新增文件', searchFiles: '搜索文件', localFiles: '本地文件', diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index 72595257d1..3674806067 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -69,7 +69,7 @@ export default { name: '名称', namePlaceholder: '请输入名称', doc: '文档', - datasetDescription: '嘿,添加数据集后别忘了调整解析块! 😉', + datasetDescription: '😉 解析成功后才能问答哦。', addFile: '新增文件', searchFiles: '搜索文件', localFiles: '本地文件', diff --git a/web/src/pages/file-manager/action-cell/index.tsx b/web/src/pages/file-manager/action-cell/index.tsx index 2cd390e760..3107e611ea 100644 --- a/web/src/pages/file-manager/action-cell/index.tsx +++ b/web/src/pages/file-manager/action-cell/index.tsx @@ -17,7 +17,8 @@ interface IProps { record: IFile; setCurrentRecord: (record: any) => void; showRenameModal: (record: IFile) => void; - showConnectToKnowledgeModal: (ids: string[]) => void; + showConnectToKnowledgeModal: (record: IFile) => void; + setSelectedRowKeys(keys: string[]): void; } const ActionCell = ({ @@ -25,11 +26,15 @@ const ActionCell = ({ setCurrentRecord, showRenameModal, showConnectToKnowledgeModal, + setSelectedRowKeys, }: IProps) => { const documentId = record.id; const beingUsed = false; const { t } = useTranslate('knowledgeDetails'); - const { handleRemoveFile } = useHandleDeleteFile([documentId]); + const { handleRemoveFile } = useHandleDeleteFile( + [documentId], + setSelectedRowKeys, + ); const onDownloadDocument = () => { downloadFile({ @@ -48,7 +53,7 @@ const ActionCell = ({ }; const onShowConnectToKnowledgeModal = () => { - showConnectToKnowledgeModal([documentId]); + showConnectToKnowledgeModal(record); }; return ( @@ -79,14 +84,16 @@ const ActionCell = ({ > - + {record.type !== 'folder' && ( + + )} ); }; diff --git a/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx b/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx index 4c10f9d558..0dbfdf7238 100644 --- a/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx +++ b/web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx @@ -1,14 +1,16 @@ import { useFetchKnowledgeList } from '@/hooks/knowledgeHook'; import { IModalProps } from '@/interfaces/common'; import { Form, Modal, Select, SelectProps } from 'antd'; +import { useEffect } from 'react'; const ConnectToKnowledgeModal = ({ visible, hideModal, onOk, -}: IModalProps) => { + initialValue, +}: IModalProps & { initialValue: string[] }) => { const [form] = Form.useForm(); - const { list } = useFetchKnowledgeList(); + const { list, fetchList } = useFetchKnowledgeList(); const options: SelectProps['options'] = list?.map((item) => ({ label: item.name, @@ -18,11 +20,16 @@ const ConnectToKnowledgeModal = ({ const handleOk = async () => { const values = await form.getFieldsValue(); const knowledgeIds = values.knowledgeIds ?? []; - if (knowledgeIds.length > 0) { - return onOk?.(knowledgeIds); - } + return onOk?.(knowledgeIds); }; + useEffect(() => { + if (visible) { + form.setFieldValue('knowledgeIds', initialValue); + fetchList(); + } + }, [visible, fetchList, initialValue, form]); + return (
- +