feat: save the selected parser to the backend on the upload file page and upload document (#54)

* feat: add pagination to document table

* feat: fetch document list by page

* feat: poll the document list

* feat: upload document

* feat: save the selected parser to the backend on the upload file page
This commit is contained in:
balibabu
2024-02-05 12:01:27 +08:00
committed by GitHub
parent 51482f3e2a
commit f305776217
18 changed files with 629 additions and 82 deletions

View File

@@ -1,5 +1,9 @@
import { KnowledgeRouteKey } from '@/constants/knowledge';
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
import {
useDeleteDocumentById,
useKnowledgeBaseId,
} from '@/hooks/knowledgeHook';
import { Pagination } from '@/interfaces/common';
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
import { getOneNamespaceEffectsLoading } from '@/utils/stroreUtil';
import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
@@ -15,8 +19,8 @@ import {
Tag,
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { debounce } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { PaginationProps } from 'antd/lib';
import React, { useEffect, useMemo, useState } from 'react';
import { useDispatch, useNavigate, useSelector } from 'umi';
import CreateEPModal from './createEFileModal';
import styles from './index.less';
@@ -30,50 +34,90 @@ const KnowledgeFile = () => {
const dispatch = useDispatch();
const kFModel = useSelector((state: any) => state.kFModel);
const effects = useSelector((state: any) => state.loading.effects);
const { data } = kFModel;
const { data, total } = kFModel;
const knowledgeBaseId = useKnowledgeBaseId();
const { removeDocument } = useDeleteDocumentById();
const loading = getOneNamespaceEffectsLoading('kFModel', effects, [
'getKfList',
'updateDocumentStatus',
]);
const [inputValue, setInputValue] = useState('');
const [doc_id, setDocId] = useState('0');
const [parser_id, setParserId] = useState('0');
let navigate = useNavigate();
const getKfList = (keywords?: string) => {
const getKfList = () => {
const payload = {
kb_id: knowledgeBaseId,
keywords,
};
if (!keywords) {
delete payload.keywords;
}
dispatch({
type: 'kFModel/getKfList',
payload,
});
};
const throttledGetDocumentList = () => {
dispatch({
type: 'kFModel/throttledGetDocumentList',
payload: knowledgeBaseId,
});
};
const setPagination = (pageNumber = 1, pageSize?: number) => {
const pagination: Pagination = {
current: pageNumber,
} as Pagination;
if (pageSize) {
pagination.pageSize = pageSize;
}
dispatch({
type: 'kFModel/setPagination',
payload: pagination,
});
};
const onPageChange: PaginationProps['onChange'] = (pageNumber, pageSize) => {
setPagination(pageNumber, pageSize);
getKfList();
};
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]);
useEffect(() => {
if (knowledgeBaseId) {
getKfList();
dispatch({
type: 'kFModel/pollGetDocumentList-start',
payload: knowledgeBaseId,
});
}
return () => {
dispatch({
type: 'kFModel/pollGetDocumentList-stop',
});
};
}, [knowledgeBaseId]);
const debounceChange = debounce(getKfList, 300);
const debounceCallback = useCallback(
(value: string) => debounceChange(value),
[],
);
const handleInputChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const value = e.target.value;
setInputValue(value);
debounceCallback(e.target.value);
dispatch({ type: 'kFModel/setSearchString', payload: value });
setPagination();
throttledGetDocumentList();
};
const onChangeStatus = (e: boolean, doc_id: string) => {
dispatch({
type: 'kFModel/updateDocumentStatus',
@@ -85,13 +129,7 @@ const KnowledgeFile = () => {
});
};
const onRmDocument = () => {
dispatch({
type: 'kFModel/document_rm',
payload: {
doc_id,
kb_id: knowledgeBaseId,
},
});
removeDocument(doc_id);
};
const showCEFModal = () => {
dispatch({
@@ -226,7 +264,6 @@ const KnowledgeFile = () => {
key: 'action',
render: (_, record) => (
<ParsingActionCell
documentId={doc_id}
knowledgeBaseId={knowledgeBaseId}
setDocumentAndParserId={setDocumentAndParserId(record)}
record={record}
@@ -248,12 +285,12 @@ const KnowledgeFile = () => {
<div className={styles.filter}>
<Space>
<h3>Total</h3>
<Tag color="purple">100 files</Tag>
<Tag color="purple">{total} files</Tag>
</Space>
<Space>
<Input
placeholder="Seach your files"
value={inputValue}
value={kFModel.searchString}
style={{ width: 220 }}
allowClear
onChange={handleInputChange}
@@ -272,7 +309,7 @@ const KnowledgeFile = () => {
columns={finalColumns}
dataSource={data}
loading={loading}
pagination={false}
pagination={pagination}
scroll={{ scrollToFirstRowOnChange: true, x: true, y: 'fill' }}
/>
<CreateEPModal getKfList={getKfList} kb_id={knowledgeBaseId} />

View File

@@ -1,3 +1,4 @@
import { BaseState } from '@/interfaces/common';
import { IKnowledgeFile } from '@/interfaces/database/knowledge';
import kbService from '@/services/kbService';
import { message } from 'antd';
@@ -6,14 +7,16 @@ import pick from 'lodash/pick';
import { Nullable } from 'typings';
import { DvaModel } from 'umi';
export interface KFModelState {
export interface KFModelState extends BaseState {
isShowCEFwModal: boolean;
isShowTntModal: boolean;
isShowSegmentSetModal: boolean;
isShowRenameModal: boolean;
tenantIfo: any;
data: IKnowledgeFile[];
total: number;
currentRecord: Nullable<IKnowledgeFile>;
searchString: string;
}
const model: DvaModel<KFModelState> = {
@@ -25,7 +28,13 @@ const model: DvaModel<KFModelState> = {
isShowRenameModal: false,
tenantIfo: {},
data: [],
total: 0,
currentRecord: null,
searchString: '',
pagination: {
current: 1,
pageSize: 10,
},
},
reducers: {
updateState(state, { payload }) {
@@ -40,6 +49,12 @@ const model: DvaModel<KFModelState> = {
setCurrentRecord(state, { payload }) {
return { ...state, currentRecord: payload };
},
setSearchString(state, { payload }) {
return { ...state, searchString: payload };
},
setPagination(state, { payload }) {
return { ...state, pagination: { ...state.pagination, ...payload } };
},
},
subscriptions: {
setup({ dispatch, history }) {
@@ -69,22 +84,41 @@ const model: DvaModel<KFModelState> = {
callback && callback(res);
}
},
*getKfList({ payload = {} }, { call, put }) {
const { data, response } = yield call(
kbService.get_document_list,
payload,
);
const { retcode, data: res, retmsg } = data;
*getKfList({ payload = {} }, { call, put, select }) {
const state: KFModelState = yield select((state: any) => state.kFModel);
const requestBody = {
...payload,
page: state.pagination.current,
page_size: state.pagination.pageSize,
};
if (state.searchString) {
requestBody['keywords'] = state.searchString;
}
const { data } = yield call(kbService.get_document_list, requestBody);
const { retcode, data: res } = data;
if (retcode === 0) {
yield put({
type: 'updateState',
payload: {
data: res,
data: res.docs,
total: res.total,
},
});
}
},
throttledGetDocumentList: [
function* ({ payload }, { call, put }) {
yield put({ type: 'getKfList', payload: { kb_id: payload } });
},
{ type: 'throttle', ms: 1000 }, // TODO: Provide type support for this effect
],
pollGetDocumentList: [
function* ({ payload }, { call, put }) {
yield put({ type: 'getKfList', payload: { kb_id: payload } });
},
{ type: 'poll', delay: 5000 }, // TODO: Provide type support for this effect
],
*updateDocumentStatus({ payload = {} }, { call, put }) {
const { data, response } = yield call(
kbService.document_change_status,
@@ -106,11 +140,12 @@ const model: DvaModel<KFModelState> = {
const { retcode, data: res, retmsg } = data;
if (retcode === 0) {
message.success('删除成功!');
put({
yield put({
type: 'getKfList',
payload: { kb_id: payload.kb_id },
});
}
return retcode;
},
*document_rename({ payload = {} }, { call, put }) {
const { data } = yield call(

View File

@@ -5,19 +5,18 @@ import { Button, Dropdown, MenuProps, Space, Tooltip } from 'antd';
import { useDispatch } from 'umi';
interface IProps {
documentId: string;
knowledgeBaseId: string;
record: IKnowledgeFile;
setDocumentAndParserId: () => void;
}
const ParsingActionCell = ({
documentId,
knowledgeBaseId,
record,
setDocumentAndParserId,
}: IProps) => {
const dispatch = useDispatch();
const documentId = record.id;
const removeDocument = () => {
dispatch({

View File

@@ -18,8 +18,7 @@ const SegmentSetModal: React.FC<kFProps> = ({
const kFModel = useSelector((state: any) => state.kFModel);
const settingModel = useSelector((state: any) => state.settingModel);
const [selectedTag, setSelectedTag] = useState('');
const { tenantIfo = {} } = settingModel;
const { parser_ids = '' } = tenantIfo;
const parser_ids = settingModel?.tenantIfo?.parser_ids ?? '';
const { isShowSegmentSetModal } = kFModel;
const { t } = useTranslation();

View File

@@ -1,7 +1,8 @@
import { useKnowledgeBaseId } from '@/hooks/knowledgeHook';
import uploadService from '@/services/uploadService';
import type { UploadProps } from 'antd';
import { Button, Upload } from 'antd';
import React from 'react';
import { Link } from 'umi';
interface PropsType {
kb_id: string;
getKfList: () => void;
@@ -12,6 +13,8 @@ type UploadRequestOption = Parameters<
>[0];
const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => {
const knowledgeBaseId = useKnowledgeBaseId();
const createRequest: (props: UploadRequestOption) => void = async function ({
file,
onSuccess,
@@ -30,9 +33,9 @@ const FileUpload: React.FC<PropsType> = ({ kb_id, getKfList }) => {
showUploadList: false,
};
return (
<Upload {...uploadProps}>
<Button type="link"></Button>
</Upload>
// <Upload {...uploadProps}>
<Link to={`/knowledge/dataset/upload?id=${knowledgeBaseId}`}></Link>
// </Upload>
);
};