From 73c2f4d4183fa097b32b294f1cee96769d227cda Mon Sep 17 00:00:00 2001 From: balibabu <cike8899@users.noreply.github.com> Date: Fri, 22 Mar 2024 11:35:25 +0800 Subject: [PATCH] feat: add hooks for document table and refactor document-related modal (#141) * feat: add hooks for document table * refactor: refactor document-related modal --- web/src/hooks/documentHooks.ts | 142 ++++++++++- ...entSetModal.tsx => chunk-method-modal.tsx} | 155 +++++------ .../knowledge-file/create-file-modal.tsx | 49 ++++ .../knowledge-file/createEFileModal.tsx | 78 ------ .../components/knowledge-file/hooks.ts | 241 ++++++++++++++++++ .../components/knowledge-file/index.tsx | 229 ++++++----------- .../components/knowledge-file/model.ts | 13 +- .../parsing-action-cell/index.tsx | 53 +--- .../knowledge-file/rename-modal/index.tsx | 56 ++-- .../knowledge-setting/category-panel.tsx | 6 +- .../components/knowledge-setting/index.tsx | 4 +- web/src/pages/chat/index.tsx | 2 +- 12 files changed, 626 insertions(+), 402 deletions(-) rename web/src/pages/add-knowledge/components/knowledge-file/{segmentSetModal.tsx => chunk-method-modal.tsx} (55%) create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/create-file-modal.tsx delete mode 100644 web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx create mode 100644 web/src/pages/add-knowledge/components/knowledge-file/hooks.ts diff --git a/web/src/hooks/documentHooks.ts b/web/src/hooks/documentHooks.ts index a79f9d1..536da8b 100644 --- a/web/src/hooks/documentHooks.ts +++ b/web/src/hooks/documentHooks.ts @@ -1,8 +1,10 @@ -import { IChunk } from '@/interfaces/database/knowledge'; +import { IChunk, IKnowledgeFile } from '@/interfaces/database/knowledge'; import { api_host } from '@/utils/api'; import { buildChunkHighlights } from '@/utils/documentUtils'; -import { useMemo } from 'react'; +import { useCallback, useMemo } from 'react'; import { IHighlight } from 'react-pdf-highlighter'; +import { useDispatch, useSelector } from 'umi'; +import { useGetKnowledgeSearchParams } from './routeHook'; export const useGetDocumentUrl = (documentId: string) => { const url = useMemo(() => { @@ -19,3 +21,139 @@ export const useGetChunkHighlights = (selectedChunk: IChunk): IHighlight[] => { return highlights; }; + +export const useFetchDocumentList = () => { + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const dispatch = useDispatch(); + + const fetchKfList = useCallback(() => { + return dispatch<any>({ + type: 'kFModel/getKfList', + payload: { + kb_id: knowledgeId, + }, + }); + }, [dispatch, knowledgeId]); + + return fetchKfList; +}; + +export const useSetDocumentStatus = () => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const setDocumentStatus = useCallback( + (status: boolean, documentId: string) => { + dispatch({ + type: 'kFModel/updateDocumentStatus', + payload: { + doc_id: documentId, + status: Number(status), + kb_id: knowledgeId, + }, + }); + }, + [dispatch, knowledgeId], + ); + + return setDocumentStatus; +}; + +export const useSelectDocumentList = () => { + const list: IKnowledgeFile[] = useSelector( + (state: any) => state.kFModel.data, + ); + return list; +}; + +export const useSaveDocumentName = () => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const saveName = useCallback( + (documentId: string, name: string) => { + return dispatch<any>({ + type: 'kFModel/document_rename', + payload: { + doc_id: documentId, + name: name, + kb_id: knowledgeId, + }, + }); + }, + [dispatch, knowledgeId], + ); + + return saveName; +}; + +export const useCreateDocument = () => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const createDocument = useCallback( + (name: string) => { + try { + return dispatch<any>({ + type: 'kFModel/document_create', + payload: { + name, + kb_id: knowledgeId, + }, + }); + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }, + [dispatch, knowledgeId], + ); + + return createDocument; +}; + +export const useSetDocumentParser = () => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const setDocumentParser = useCallback( + (parserId: string, documentId: string) => { + try { + return dispatch<any>({ + type: 'kFModel/document_change_parser', + payload: { + parser_id: parserId, + doc_id: documentId, + kb_id: knowledgeId, + }, + }); + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }, + [dispatch, knowledgeId], + ); + + return setDocumentParser; +}; + +export const useRemoveDocument = (documentId: string) => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const removeDocument = useCallback(() => { + try { + return dispatch<any>({ + type: 'kFModel/document_rm', + payload: { + doc_id: documentId, + kb_id: knowledgeId, + }, + }); + } catch (errorInfo) { + console.log('Failed:', errorInfo); + } + }, [dispatch, knowledgeId, documentId]); + + return removeDocument; +}; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx similarity index 55% rename from web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx rename to web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx index ea7a9e8..69d5e91 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/segmentSetModal.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/chunk-method-modal.tsx @@ -1,86 +1,69 @@ -import { - useFetchTenantInfo, - useSelectParserList, -} from '@/hooks/userSettingHook'; -import { Modal, Space, Tag } from 'antd'; -import React, { useEffect, useState } from 'react'; -import { useDispatch, useSelector } from 'umi'; -import styles from './index.less'; -const { CheckableTag } = Tag; -interface kFProps { - getKfList: () => void; - parser_id: string; - doc_id: string; -} -const SegmentSetModal: React.FC<kFProps> = ({ - getKfList, - parser_id, - doc_id, -}) => { - const dispatch = useDispatch(); - const kFModel = useSelector((state: any) => state.kFModel); - const [selectedTag, setSelectedTag] = useState(''); - const { isShowSegmentSetModal } = kFModel; - const parserList = useSelectParserList(); - - useFetchTenantInfo(); - - useEffect(() => { - setSelectedTag(parser_id); - }, [parser_id]); - - const handleCancel = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowSegmentSetModal: false, - }, - }); - }; - - const handleOk = async () => { - const retcode = await dispatch<any>({ - type: 'kFModel/document_change_parser', - payload: { - parser_id: selectedTag, - doc_id, - }, - }); - - if (retcode === 0 && getKfList) { - getKfList(); - handleCancel(); - } - }; - - const handleChange = (tag: string, checked: boolean) => { - const nextSelectedTag = checked ? tag : selectedTag; - setSelectedTag(nextSelectedTag); - }; - - return ( - <Modal - title="Category" - open={isShowSegmentSetModal} - onOk={handleOk} - onCancel={handleCancel} - > - <Space size={[0, 8]} wrap> - <div className={styles.tags}> - {parserList.map((x) => { - return ( - <CheckableTag - key={x.value} - checked={selectedTag === x.value} - onChange={(checked) => handleChange(x.value, checked)} - > - {x.label} - </CheckableTag> - ); - })} - </div> - </Space> - </Modal> - ); -}; -export default SegmentSetModal; +import { IModalManagerChildrenProps } from '@/components/modal-manager'; +import { + useFetchTenantInfo, + useSelectParserList, +} from '@/hooks/userSettingHook'; +import { Modal, Space, Tag } from 'antd'; +import React, { useEffect, useState } from 'react'; + +import styles from './index.less'; + +const { CheckableTag } = Tag; + +interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> { + loading: boolean; + onOk: (parserId: string) => void; + showModal?(): void; + parser_id: string; +} + +const ChunkMethodModal: React.FC<IProps> = ({ + parser_id, + onOk, + hideModal, + visible, +}) => { + const [selectedTag, setSelectedTag] = useState(''); + const parserList = useSelectParserList(); + + useFetchTenantInfo(); + + useEffect(() => { + setSelectedTag(parser_id); + }, [parser_id]); + + const handleOk = async () => { + onOk(selectedTag); + }; + + const handleChange = (tag: string, checked: boolean) => { + const nextSelectedTag = checked ? tag : selectedTag; + setSelectedTag(nextSelectedTag); + }; + + return ( + <Modal + title="Chunk Method" + open={visible} + onOk={handleOk} + onCancel={hideModal} + > + <Space size={[0, 8]} wrap> + <div className={styles.tags}> + {parserList.map((x) => { + return ( + <CheckableTag + key={x.value} + checked={selectedTag === x.value} + onChange={(checked) => handleChange(x.value, checked)} + > + {x.label} + </CheckableTag> + ); + })} + </div> + </Space> + </Modal> + ); +}; +export default ChunkMethodModal; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/create-file-modal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/create-file-modal.tsx new file mode 100644 index 0000000..8e23d42 --- /dev/null +++ b/web/src/pages/add-knowledge/components/knowledge-file/create-file-modal.tsx @@ -0,0 +1,49 @@ +import { IModalManagerChildrenProps } from '@/components/modal-manager'; +import { Form, Input, Modal } from 'antd'; +import React from 'react'; + +type FieldType = { + name?: string; +}; + +interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> { + loading: boolean; + onOk: (name: string) => void; + showModal?(): void; +} + +const FileCreatingModal: React.FC<IProps> = ({ visible, hideModal, onOk }) => { + const [form] = Form.useForm(); + + const handleOk = async () => { + const values = await form.validateFields(); + onOk(values.name); + }; + + return ( + <Modal + title="File Name" + open={visible} + onOk={handleOk} + onCancel={hideModal} + > + <Form + form={form} + name="validateOnly" + labelCol={{ span: 4 }} + wrapperCol={{ span: 20 }} + style={{ maxWidth: 600 }} + autoComplete="off" + > + <Form.Item<FieldType> + label="File Name" + name="name" + rules={[{ required: true, message: 'Please input name!' }]} + > + <Input /> + </Form.Item> + </Form> + </Modal> + ); +}; +export default FileCreatingModal; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx b/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx deleted file mode 100644 index 3447f20..0000000 --- a/web/src/pages/add-knowledge/components/knowledge-file/createEFileModal.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { Form, Input, Modal } from 'antd'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; -import { useDispatch, useSelector } from 'umi'; - -type FieldType = { - name?: string; -}; -interface kFProps { - getKfList: () => void; - kb_id: string; -} - -const FileCreatingModal: React.FC<kFProps> = ({ getKfList, kb_id }) => { - const dispatch = useDispatch(); - const [form] = Form.useForm(); - const kFModel = useSelector((state: any) => state.kFModel); - const { isShowCEFwModal } = kFModel; - const { t } = useTranslation(); - - const handleCancel = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowCEFwModal: false, - }, - }); - }; - - const createDocument = async () => { - try { - const values = await form.validateFields(); - const retcode = await dispatch<any>({ - type: 'kFModel/document_create', - payload: { - name: values.name, - kb_id, - }, - }); - if (retcode === 0) { - getKfList && getKfList(); - } - } catch (errorInfo) { - console.log('Failed:', errorInfo); - } - }; - - const handleOk = async () => { - createDocument(); - }; - - return ( - <Modal - title="File Name" - open={isShowCEFwModal} - onOk={handleOk} - onCancel={handleCancel} - > - <Form - form={form} - name="validateOnly" - labelCol={{ span: 4 }} - wrapperCol={{ span: 20 }} - style={{ maxWidth: 600 }} - autoComplete="off" - > - <Form.Item<FieldType> - label="File Name" - name="name" - rules={[{ required: true, message: 'Please input name!' }]} - > - <Input /> - </Form.Item> - </Form> - </Modal> - ); -}; -export default FileCreatingModal; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts new file mode 100644 index 0000000..3618908 --- /dev/null +++ b/web/src/pages/add-knowledge/components/knowledge-file/hooks.ts @@ -0,0 +1,241 @@ +import { useSetModalState } from '@/hooks/commonHooks'; +import { + useCreateDocument, + useFetchDocumentList, + useSaveDocumentName, + useSetDocumentParser, +} from '@/hooks/documentHooks'; +import { useGetKnowledgeSearchParams } from '@/hooks/routeHook'; +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; +import { useFetchTenantInfo } from '@/hooks/userSettingHook'; +import { Pagination } from '@/interfaces/common'; +import { IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { PaginationProps } from 'antd'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useDispatch, useNavigate, useSelector } from 'umi'; +import { KnowledgeRouteKey } from './constant'; + +export const useFetchDocumentListOnMount = () => { + const { knowledgeId } = useGetKnowledgeSearchParams(); + const fetchDocumentList = useFetchDocumentList(); + const dispatch = useDispatch(); + + useFetchTenantInfo(); + + useEffect(() => { + if (knowledgeId) { + fetchDocumentList(); + dispatch({ + type: 'kFModel/pollGetDocumentList-start', + payload: knowledgeId, + }); + } + return () => { + dispatch({ + type: 'kFModel/pollGetDocumentList-stop', + }); + }; + }, [knowledgeId, dispatch, fetchDocumentList]); + + return { fetchDocumentList }; +}; + +export const useGetPagination = (fetchDocumentList: () => void) => { + const dispatch = useDispatch(); + const kFModel = useSelector((state: any) => state.kFModel); + + const setPagination = useCallback( + (pageNumber = 1, pageSize?: number) => { + const pagination: Pagination = { + current: pageNumber, + } as Pagination; + if (pageSize) { + pagination.pageSize = pageSize; + } + dispatch({ + type: 'kFModel/setPagination', + payload: pagination, + }); + }, + [dispatch], + ); + + const onPageChange: PaginationProps['onChange'] = useCallback( + (pageNumber: number, pageSize: number) => { + setPagination(pageNumber, pageSize); + fetchDocumentList(); + }, + [fetchDocumentList, setPagination], + ); + + const pagination: PaginationProps = useMemo(() => { + return { + showQuickJumper: true, + total: kFModel.total, + showSizeChanger: true, + current: kFModel.pagination.currentPage, + pageSize: kFModel.pagination.pageSize, + pageSizeOptions: [1, 2, 10, 20, 50, 100], + onChange: onPageChange, + }; + }, [kFModel, onPageChange]); + + return { + pagination, + setPagination, + total: kFModel.total, + searchString: kFModel.searchString, + }; +}; + +export const useSelectDocumentListLoading = () => { + return useOneNamespaceEffectsLoading('kFModel', [ + 'getKfList', + 'updateDocumentStatus', + ]); +}; + +export const useNavigateToOtherPage = () => { + const navigate = useNavigate(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const linkToUploadPage = useCallback(() => { + navigate(`/knowledge/dataset/upload?id=${knowledgeId}`); + }, [navigate, knowledgeId]); + + const toChunk = useCallback( + (id: string) => { + navigate( + `/knowledge/${KnowledgeRouteKey.Dataset}/chunk?id=${knowledgeId}&doc_id=${id}`, + ); + }, + [navigate, knowledgeId], + ); + + return { linkToUploadPage, toChunk }; +}; + +export const useHandleSearchChange = (setPagination: () => void) => { + const dispatch = useDispatch(); + const { knowledgeId } = useGetKnowledgeSearchParams(); + + const throttledGetDocumentList = useCallback(() => { + dispatch({ + type: 'kFModel/throttledGetDocumentList', + payload: knowledgeId, + }); + }, [dispatch, knowledgeId]); + + const handleInputChange = useCallback( + (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { + const value = e.target.value; + dispatch({ type: 'kFModel/setSearchString', payload: value }); + setPagination(); + throttledGetDocumentList(); + }, + [setPagination, throttledGetDocumentList, dispatch], + ); + + return { handleInputChange }; +}; + +export const useSetSelectedRecord = () => { + const [currentRecord, setCurrentRecord] = useState<IKnowledgeFile>( + {} as IKnowledgeFile, + ); + + const setRecord = (record: IKnowledgeFile) => () => { + setCurrentRecord(record); + }; + + return { currentRecord, setRecord }; +}; + +export const useRenameDocument = (documentId: string) => { + const saveName = useSaveDocumentName(); + + const { + visible: renameVisible, + hideModal: hideRenameModal, + showModal: showRenameModal, + } = useSetModalState(); + const loading = useOneNamespaceEffectsLoading('kFModel', ['document_rename']); + + const onRenameOk = useCallback( + async (name: string) => { + const ret = await saveName(documentId, name); + if (ret === 0) { + hideRenameModal(); + } + }, + [hideRenameModal, saveName, documentId], + ); + + return { + renameLoading: loading, + onRenameOk, + renameVisible, + hideRenameModal, + showRenameModal, + }; +}; + +export const useCreateEmptyDocument = () => { + const createDocument = useCreateDocument(); + + const { + visible: createVisible, + hideModal: hideCreateModal, + showModal: showCreateModal, + } = useSetModalState(); + const loading = useOneNamespaceEffectsLoading('kFModel', ['document_create']); + + const onCreateOk = useCallback( + async (name: string) => { + const ret = await createDocument(name); + if (ret === 0) { + hideCreateModal(); + } + }, + [hideCreateModal, createDocument], + ); + + return { + createLoading: loading, + onCreateOk, + createVisible, + hideCreateModal, + showCreateModal, + }; +}; + +export const useChangeDocumentParser = (documentId: string) => { + const setDocumentParser = useSetDocumentParser(); + + const { + visible: changeParserVisible, + hideModal: hideChangeParserModal, + showModal: showChangeParserModal, + } = useSetModalState(); + const loading = useOneNamespaceEffectsLoading('kFModel', [ + 'document_change_parser', + ]); + + const onChangeParserOk = useCallback( + async (parserId: string) => { + const ret = await setDocumentParser(parserId, documentId); + if (ret === 0) { + hideChangeParserModal(); + } + }, + [hideChangeParserModal, setDocumentParser, documentId], + ); + + return { + changeParserLoading: loading, + onChangeParserOk, + changeParserVisible, + hideChangeParserModal, + showChangeParserModal, + }; +}; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx index 02a159c..7c36b6c 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/index.tsx @@ -1,12 +1,9 @@ -import { KnowledgeRouteKey } from '@/constants/knowledge'; -import { useKnowledgeBaseId } from '@/hooks/knowledgeHook'; import { - useFetchTenantInfo, - useSelectParserList, -} from '@/hooks/userSettingHook'; -import { Pagination } from '@/interfaces/common'; + useSelectDocumentList, + useSetDocumentStatus, +} from '@/hooks/documentHooks'; +import { useSelectParserList } from '@/hooks/userSettingHook'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; -import { getOneNamespaceEffectsLoading } from '@/utils/storeUtil'; import { FileOutlined, FileTextOutlined, @@ -25,133 +22,57 @@ import { Tag, } from 'antd'; import type { ColumnsType } from 'antd/es/table'; -import { PaginationProps } from 'antd/lib'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { useDispatch, useNavigate, useSelector } from 'umi'; -import CreateEPModal from './createEFileModal'; -import styles from './index.less'; +import { useMemo } from 'react'; +import ChunkMethodModal from './chunk-method-modal'; +import CreateFileModal from './create-file-modal'; +import { + useChangeDocumentParser, + useCreateEmptyDocument, + useFetchDocumentListOnMount, + useGetPagination, + useHandleSearchChange, + useNavigateToOtherPage, + useRenameDocument, + useSetSelectedRecord, +} from './hooks'; import ParsingActionCell from './parsing-action-cell'; import ParsingStatusCell from './parsing-status-cell'; import RenameModal from './rename-modal'; -import SegmentSetModal from './segmentSetModal'; -const KnowledgeFile = () => { - const dispatch = useDispatch(); - const kFModel = useSelector((state: any) => state.kFModel); - const effects = useSelector((state: any) => state.loading.effects); - const { data, total } = kFModel; - const knowledgeBaseId = useKnowledgeBaseId(); +import styles from './index.less'; - const loading = getOneNamespaceEffectsLoading('kFModel', effects, [ - 'getKfList', - 'updateDocumentStatus', - ]); - const [doc_id, setDocId] = useState('0'); - const [parser_id, setParserId] = useState('0'); - let navigate = useNavigate(); +const KnowledgeFile = () => { + const data = useSelectDocumentList(); + const { fetchDocumentList } = useFetchDocumentListOnMount(); const parserList = useSelectParserList(); - - const getKfList = useCallback(() => { - const payload = { - kb_id: knowledgeBaseId, - }; - - dispatch({ - type: 'kFModel/getKfList', - payload, - }); - }, [dispatch, knowledgeBaseId]); - - const throttledGetDocumentList = () => { - dispatch({ - type: 'kFModel/throttledGetDocumentList', - payload: knowledgeBaseId, - }); - }; - - const setPagination = useCallback( - (pageNumber = 1, pageSize?: number) => { - const pagination: Pagination = { - current: pageNumber, - } as Pagination; - if (pageSize) { - pagination.pageSize = pageSize; - } - dispatch({ - type: 'kFModel/setPagination', - payload: pagination, - }); - }, - [dispatch], - ); - - const onPageChange: PaginationProps['onChange'] = useCallback( - (pageNumber: number, pageSize: number) => { - setPagination(pageNumber, pageSize); - getKfList(); - }, - [getKfList, setPagination], - ); - - const pagination: PaginationProps = useMemo(() => { - return { - showQuickJumper: true, - total, - showSizeChanger: true, - current: kFModel.pagination.currentPage, - pageSize: kFModel.pagination.pageSize, - pageSizeOptions: [1, 2, 10, 20, 50, 100], - onChange: onPageChange, - }; - }, [total, kFModel.pagination, onPageChange]); - - useEffect(() => { - if (knowledgeBaseId) { - getKfList(); - dispatch({ - type: 'kFModel/pollGetDocumentList-start', - payload: knowledgeBaseId, - }); - } - return () => { - dispatch({ - type: 'kFModel/pollGetDocumentList-stop', - }); - }; - }, [knowledgeBaseId, dispatch, getKfList]); - - const handleInputChange = ( - e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, - ) => { - const value = e.target.value; - dispatch({ type: 'kFModel/setSearchString', payload: value }); - setPagination(); - throttledGetDocumentList(); - }; - - const onChangeStatus = (e: boolean, doc_id: string) => { - dispatch({ - type: 'kFModel/updateDocumentStatus', - payload: { - doc_id, - status: Number(e), - kb_id: knowledgeBaseId, - }, - }); - }; - - const showCEFModal = useCallback(() => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowCEFwModal: true, - }, - }); - }, [dispatch]); - - const linkToUploadPage = useCallback(() => { - navigate(`/knowledge/dataset/upload?id=${knowledgeBaseId}`); - }, [navigate, knowledgeBaseId]); + const { pagination, setPagination, total, searchString } = + useGetPagination(fetchDocumentList); + const onChangeStatus = useSetDocumentStatus(); + const { linkToUploadPage, toChunk } = useNavigateToOtherPage(); + + const { handleInputChange } = useHandleSearchChange(setPagination); + const { currentRecord, setRecord } = useSetSelectedRecord(); + const { + renameLoading, + onRenameOk, + renameVisible, + hideRenameModal, + showRenameModal, + } = useRenameDocument(currentRecord.id); + const { + createLoading, + onCreateOk, + createVisible, + hideCreateModal, + showCreateModal, + } = useCreateEmptyDocument(); + const { + changeParserLoading, + onChangeParserOk, + changeParserVisible, + hideChangeParserModal, + showChangeParserModal, + } = useChangeDocumentParser(currentRecord.id); const actionItems: MenuProps['items'] = useMemo(() => { return [ @@ -172,7 +93,7 @@ const KnowledgeFile = () => { { type: 'divider' }, { key: '2', - onClick: showCEFModal, + onClick: showCreateModal, label: ( <div> <Button type="link"> @@ -184,18 +105,7 @@ const KnowledgeFile = () => { // disabled: true, }, ]; - }, [linkToUploadPage, showCEFModal]); - - const toChunk = (id: string) => { - navigate( - `/knowledge/${KnowledgeRouteKey.Dataset}/chunk?id=${knowledgeBaseId}&doc_id=${id}`, - ); - }; - - const setDocumentAndParserId = (record: IKnowledgeFile) => () => { - setDocId(record.id); - setParserId(record.parser_id); - }; + }, [linkToUploadPage, showCreateModal]); const columns: ColumnsType<IKnowledgeFile> = [ { @@ -255,8 +165,12 @@ const KnowledgeFile = () => { key: 'action', render: (_, record) => ( <ParsingActionCell - knowledgeBaseId={knowledgeBaseId} - setDocumentAndParserId={setDocumentAndParserId(record)} + setDocumentAndParserId={setRecord(record)} + showRenameModal={() => { + setRecord(record)(); + showRenameModal(); + }} + showChangeParserModal={showChangeParserModal} record={record} ></ParsingActionCell> ), @@ -268,8 +182,6 @@ const KnowledgeFile = () => { className: `${styles.column}`, })); - useFetchTenantInfo(); - return ( <div className={styles.datasetWrapper}> <h3>Dataset</h3> @@ -283,7 +195,7 @@ const KnowledgeFile = () => { <Space> <Input placeholder="Seach your files" - value={kFModel.searchString} + value={searchString} style={{ width: 220 }} allowClear onChange={handleInputChange} @@ -305,13 +217,26 @@ const KnowledgeFile = () => { pagination={pagination} scroll={{ scrollToFirstRowOnChange: true, x: 1300, y: 'fill' }} /> - <CreateEPModal getKfList={getKfList} kb_id={knowledgeBaseId} /> - <SegmentSetModal - getKfList={getKfList} - parser_id={parser_id} - doc_id={doc_id} + <CreateFileModal + visible={createVisible} + hideModal={hideCreateModal} + loading={createLoading} + onOk={onCreateOk} + /> + <ChunkMethodModal + parser_id={currentRecord.parser_id} + onOk={onChangeParserOk} + visible={changeParserVisible} + hideModal={hideChangeParserModal} + loading={changeParserLoading} /> - <RenameModal></RenameModal> + <RenameModal + visible={renameVisible} + onOk={onRenameOk} + loading={renameLoading} + hideModal={hideRenameModal} + initialName={currentRecord.name} + ></RenameModal> </div> ); }; diff --git a/web/src/pages/add-knowledge/components/knowledge-file/model.ts b/web/src/pages/add-knowledge/components/knowledge-file/model.ts index a2a40d4..6644647 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/model.ts +++ b/web/src/pages/add-knowledge/components/knowledge-file/model.ts @@ -164,6 +164,10 @@ const model: DvaModel<KFModelState> = { const { data } = yield call(kbService.document_create, payload); const { retcode } = data; if (retcode === 0) { + put({ + type: 'getKfList', + payload: { kb_id: payload.kb_id }, + }); put({ type: 'kFModel/updateState', payload: { @@ -192,9 +196,16 @@ const model: DvaModel<KFModelState> = { return retcode; }, *document_change_parser({ payload = {} }, { call, put }) { - const { data } = yield call(kbService.document_change_parser, payload); + const { data } = yield call( + kbService.document_change_parser, + omit(payload, ['kb_id']), + ); const { retcode } = data; if (retcode === 0) { + put({ + type: 'getKfList', + payload: { kb_id: payload.kb_id }, + }); put({ type: 'updateState', payload: { diff --git a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx index 49cb0b1..4bb04d6 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx @@ -1,5 +1,8 @@ import showDeleteConfirm from '@/components/deleting-confirm'; +import { useRemoveDocument } from '@/hooks/documentHooks'; import { IKnowledgeFile } from '@/interfaces/database/knowledge'; +import { api_host } from '@/utils/api'; +import { downloadFile } from '@/utils/fileUtil'; import { DeleteOutlined, DownloadOutlined, @@ -7,37 +10,27 @@ import { ToolOutlined, } from '@ant-design/icons'; import { Button, Dropdown, MenuProps, Space, Tooltip } from 'antd'; -import { useDispatch } from 'umi'; import { isParserRunning } from '../utils'; -import { api_host } from '@/utils/api'; -import { downloadFile } from '@/utils/fileUtil'; import styles from './index.less'; interface IProps { - knowledgeBaseId: string; record: IKnowledgeFile; setDocumentAndParserId: () => void; + showRenameModal: () => void; + showChangeParserModal: () => void; } const ParsingActionCell = ({ - knowledgeBaseId, record, setDocumentAndParserId, + showRenameModal, + showChangeParserModal, }: IProps) => { - const dispatch = useDispatch(); const documentId = record.id; const isRunning = isParserRunning(record.run); - const removeDocument = () => { - dispatch({ - type: 'kFModel/document_rm', - payload: { - doc_id: documentId, - kb_id: knowledgeBaseId, - }, - }); - }; + const removeDocument = useRemoveDocument(documentId); const onRmDocument = () => { if (!isRunning) { @@ -52,39 +45,13 @@ const ParsingActionCell = ({ }); }; - const setCurrentRecord = () => { - dispatch({ - type: 'kFModel/setCurrentRecord', - payload: record, - }); - }; - - const showSegmentSetModal = () => { - dispatch({ - type: 'kFModel/updateState', - payload: { - isShowSegmentSetModal: true, - }, - }); - }; - - const showRenameModal = () => { - if (!isRunning) { - setCurrentRecord(); - dispatch({ - type: 'kFModel/setIsShowRenameModal', - payload: true, - }); - } - }; - const chunkItems: MenuProps['items'] = [ { key: '1', label: ( <div> - <Button type="link" onClick={showSegmentSetModal}> - Category + <Button type="link" onClick={showChangeParserModal}> + Chunk Method </Button> </div> ), diff --git a/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx b/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx index a80d7f4..b93a179 100644 --- a/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-file/rename-modal/index.tsx @@ -1,46 +1,30 @@ -import { useKnowledgeBaseId } from '@/hooks/knowledgeHook'; +import { IModalManagerChildrenProps } from '@/components/modal-manager'; import { Form, Input, Modal } from 'antd'; import { useEffect } from 'react'; -import { useDispatch, useSelector } from 'umi'; -const RenameModal = () => { +interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> { + loading: boolean; + initialName: string; + onOk: (name: string) => void; + showModal?(): void; +} + +const RenameModal = ({ + visible, + onOk, + loading, + initialName, + hideModal, +}: IProps) => { const [form] = Form.useForm(); - const dispatch = useDispatch(); - const kFModel = useSelector((state: any) => state.kFModel); - const loading = useSelector( - (state: any) => state.loading.effects['kFModel/document_rename'], - ); - const knowledgeBaseId = useKnowledgeBaseId(); - const isModalOpen = kFModel.isShowRenameModal; - const initialName = kFModel.currentRecord?.name; - const documentId = kFModel.currentRecord?.id; type FieldType = { name?: string; }; - const closeModal = () => { - dispatch({ - type: 'kFModel/setIsShowRenameModal', - payload: false, - }); - }; - const handleOk = async () => { const ret = await form.validateFields(); - - dispatch({ - type: 'kFModel/document_rename', - payload: { - doc_id: documentId, - name: ret.name, - kb_id: knowledgeBaseId, - }, - }); - }; - - const handleCancel = () => { - closeModal(); + onOk(ret.name); }; const onFinish = (values: any) => { @@ -52,17 +36,17 @@ const RenameModal = () => { }; useEffect(() => { - if (isModalOpen) { + if (visible) { form.setFieldValue('name', initialName); } - }, [initialName, documentId, form, isModalOpen]); + }, [initialName, form, visible]); return ( <Modal title="Rename" - open={isModalOpen} + open={visible} onOk={handleOk} - onCancel={handleCancel} + onCancel={hideModal} okButtonProps={{ loading }} > <Form diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx index 1d0b7e0..84af184 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-setting/category-panel.tsx @@ -35,7 +35,11 @@ const CategoryPanel = ({ chunkMethod }: { chunkMethod: string }) => { <Title level={5} className={styles.topTitle}> {item.title} Category </Title> - <Text>{item.description}</Text> + <p + dangerouslySetInnerHTML={{ + __html: item.description, + }} + ></p> <Title level={5}>{item.title} Image Examples</Title> <Text> We've prepared detailed visual guides to make understanding easier diff --git a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx index fa2c377..0ef3ff6 100644 --- a/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx +++ b/web/src/pages/add-knowledge/components/knowledge-setting/index.tsx @@ -21,10 +21,10 @@ const Configuration = () => { <Divider></Divider> <Spin spinning={loading}> <Row gutter={32}> - <Col span={12}> + <Col span={8}> <ConfigurationForm form={form}></ConfigurationForm> </Col> - <Col span={12}> + <Col span={16}> <CategoryPanel chunkMethod={chunkMethod}></CategoryPanel> </Col> </Row> diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 88c3bca..1839140 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -1,4 +1,5 @@ import { ReactComponent as ChatAppCube } from '@/assets/svg/chat-app-cube.svg'; +import RenameModal from '@/components/rename-modal'; import { DeleteOutlined, EditOutlined, FormOutlined } from '@ant-design/icons'; import { Avatar, @@ -34,7 +35,6 @@ import { useSelectFirstDialogOnMount, } from './hooks'; -import RenameModal from '@/components/rename-modal'; import styles from './index.less'; const Chat = () => { -- GitLab