mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-06-04 11:24:00 +08:00
feat: add hooks for document table and refactor document-related modal (#141)
* feat: add hooks for document table * refactor: refactor document-related modal
This commit is contained in:
parent
6c6b144de2
commit
73c2f4d418
@ -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;
|
||||
};
|
||||
|
@ -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;
|
@ -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;
|
@ -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;
|
241
web/src/pages/add-knowledge/components/knowledge-file/hooks.ts
Normal file
241
web/src/pages/add-knowledge/components/knowledge-file/hooks.ts
Normal file
@ -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,
|
||||
};
|
||||
};
|
@ -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';
|
||||
|
||||
import styles from './index.less';
|
||||
|
||||
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();
|
||||
|
||||
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
|
||||
'getKfList',
|
||||
'updateDocumentStatus',
|
||||
]);
|
||||
const [doc_id, setDocId] = useState('0');
|
||||
const [parser_id, setParserId] = useState('0');
|
||||
let navigate = useNavigate();
|
||||
const data = useSelectDocumentList();
|
||||
const { fetchDocumentList } = useFetchDocumentListOnMount();
|
||||
const parserList = useSelectParserList();
|
||||
const { pagination, setPagination, total, searchString } =
|
||||
useGetPagination(fetchDocumentList);
|
||||
const onChangeStatus = useSetDocumentStatus();
|
||||
const { linkToUploadPage, toChunk } = useNavigateToOtherPage();
|
||||
|
||||
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 { 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}
|
||||
/>
|
||||
<RenameModal></RenameModal>
|
||||
<ChunkMethodModal
|
||||
parser_id={currentRecord.parser_id}
|
||||
onOk={onChangeParserOk}
|
||||
visible={changeParserVisible}
|
||||
hideModal={hideChangeParserModal}
|
||||
loading={changeParserLoading}
|
||||
/>
|
||||
<RenameModal
|
||||
visible={renameVisible}
|
||||
onOk={onRenameOk}
|
||||
loading={renameLoading}
|
||||
hideModal={hideRenameModal}
|
||||
initialName={currentRecord.name}
|
||||
></RenameModal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -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: {
|
||||
|
@ -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>
|
||||
),
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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 = () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user