balibabu commited on
Commit
e52051a
·
1 Parent(s): e94059c

feat: add batch operations for document list (#302)

Browse files

### What problem does this PR solve?

document list needs to be batch operated


Issue link: #301

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

web/src/assets/svg/cancel.svg ADDED
web/src/assets/svg/delete.svg ADDED
web/src/assets/svg/disable.svg ADDED
web/src/assets/svg/enable.svg ADDED
web/src/assets/svg/run.svg CHANGED
web/src/hooks/documentHooks.ts CHANGED
@@ -155,23 +155,26 @@ export const useSetDocumentParser = () => {
155
  return setDocumentParser;
156
  };
157
 
158
- export const useRemoveDocument = (documentId: string) => {
159
  const dispatch = useDispatch();
160
  const { knowledgeId } = useGetKnowledgeSearchParams();
161
 
162
- const removeDocument = useCallback(() => {
163
- try {
164
- return dispatch<any>({
165
- type: 'kFModel/document_rm',
166
- payload: {
167
- doc_id: documentId,
168
- kb_id: knowledgeId,
169
- },
170
- });
171
- } catch (errorInfo) {
172
- console.log('Failed:', errorInfo);
173
- }
174
- }, [dispatch, knowledgeId, documentId]);
 
 
 
175
 
176
  return removeDocument;
177
  };
@@ -204,11 +207,11 @@ export const useRunDocument = () => {
204
  const dispatch = useDispatch();
205
 
206
  const runDocumentByIds = useCallback(
207
- (ids: string[]) => {
208
  try {
209
  return dispatch<any>({
210
  type: 'kFModel/document_run',
211
- payload: { doc_ids: ids, run: 1 },
212
  });
213
  } catch (errorInfo) {
214
  console.log('Failed:', errorInfo);
 
155
  return setDocumentParser;
156
  };
157
 
158
+ export const useRemoveDocument = () => {
159
  const dispatch = useDispatch();
160
  const { knowledgeId } = useGetKnowledgeSearchParams();
161
 
162
+ const removeDocument = useCallback(
163
+ (documentId: string) => {
164
+ try {
165
+ return dispatch<any>({
166
+ type: 'kFModel/document_rm',
167
+ payload: {
168
+ doc_id: documentId,
169
+ kb_id: knowledgeId,
170
+ },
171
+ });
172
+ } catch (errorInfo) {
173
+ console.log('Failed:', errorInfo);
174
+ }
175
+ },
176
+ [dispatch, knowledgeId],
177
+ );
178
 
179
  return removeDocument;
180
  };
 
207
  const dispatch = useDispatch();
208
 
209
  const runDocumentByIds = useCallback(
210
+ (payload: any) => {
211
  try {
212
  return dispatch<any>({
213
  type: 'kFModel/document_run',
214
+ payload,
215
  });
216
  } catch (errorInfo) {
217
  console.log('Failed:', errorInfo);
web/src/locales/en.ts CHANGED
@@ -75,7 +75,8 @@ export default {
75
  chunkNumber: 'Chunk Number',
76
  uploadDate: 'Upload Date',
77
  chunkMethod: 'Chunk Method',
78
- enabled: 'Enabled',
 
79
  action: 'Action',
80
  parsingStatus: 'Parsing Status',
81
  processBeginAt: 'Process Begin At',
@@ -102,6 +103,7 @@ export default {
102
  view: 'View',
103
  filesSelected: 'Files Selected',
104
  upload: 'Upload',
 
105
  runningStatus0: 'UNSTART',
106
  runningStatus1: 'Parsing',
107
  runningStatus2: 'CANCEL',
@@ -130,6 +132,8 @@ export default {
130
  uploadDescription:
131
  'Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files.',
132
  chunk: 'Chunk',
 
 
133
  },
134
  knowledgeConfiguration: {
135
  titleDescription:
 
75
  chunkNumber: 'Chunk Number',
76
  uploadDate: 'Upload Date',
77
  chunkMethod: 'Chunk Method',
78
+ enabled: 'Enable',
79
+ disabled: 'Disable',
80
  action: 'Action',
81
  parsingStatus: 'Parsing Status',
82
  processBeginAt: 'Process Begin At',
 
103
  view: 'View',
104
  filesSelected: 'Files Selected',
105
  upload: 'Upload',
106
+ run: 'Run',
107
  runningStatus0: 'UNSTART',
108
  runningStatus1: 'Parsing',
109
  runningStatus2: 'CANCEL',
 
132
  uploadDescription:
133
  'Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files.',
134
  chunk: 'Chunk',
135
+ bulk: 'Bulk',
136
+ cancel: 'Cancel',
137
  },
138
  knowledgeConfiguration: {
139
  titleDescription:
web/src/locales/zh.ts CHANGED
@@ -75,6 +75,7 @@ export default {
75
  uploadDate: '上传日期',
76
  chunkMethod: '解析方法',
77
  enabled: '启用',
 
78
  action: '动作',
79
  parsingStatus: '解析状态',
80
  processBeginAt: '流程开始于',
@@ -100,6 +101,7 @@ export default {
100
  view: '看法',
101
  filesSelected: '选定的文件',
102
  upload: '上传',
 
103
  runningStatus0: '未启动',
104
  runningStatus1: '解析中',
105
  runningStatus2: '取消',
@@ -127,6 +129,8 @@ export default {
127
  uploadDescription:
128
  '支持单次或批量上传。 严禁上传公司数据或其他违禁文件。',
129
  chunk: '解析块',
 
 
130
  },
131
  knowledgeConfiguration: {
132
  titleDescription: '在这里更新您的知识库详细信息,尤其是解析方法。',
 
75
  uploadDate: '上传日期',
76
  chunkMethod: '解析方法',
77
  enabled: '启用',
78
+ disabled: '禁用',
79
  action: '动作',
80
  parsingStatus: '解析状态',
81
  processBeginAt: '流程开始于',
 
101
  view: '看法',
102
  filesSelected: '选定的文件',
103
  upload: '上传',
104
+ run: '启动',
105
  runningStatus0: '未启动',
106
  runningStatus1: '解析中',
107
  runningStatus2: '取消',
 
129
  uploadDescription:
130
  '支持单次或批量上传。 严禁上传公司数据或其他违禁文件。',
131
  chunk: '解析块',
132
+ bulk: '批量',
133
+ cancel: '取消',
134
  },
135
  knowledgeConfiguration: {
136
  titleDescription: '在这里更新您的知识库详细信息,尤其是解析方法。',
web/src/pages/add-knowledge/components/knowledge-dataset/knowledge-upload-file/index.tsx CHANGED
@@ -219,7 +219,7 @@ const KnowledgeUploadFile = () => {
219
 
220
  const runSelectedDocument = () => {
221
  const ids = fileListRef.current.map((x) => x.response.id);
222
- runDocumentByIds(ids);
223
  };
224
 
225
  const handleNextClick = () => {
 
219
 
220
  const runSelectedDocument = () => {
221
  const ids = fileListRef.current.map((x) => x.response.id);
222
+ runDocumentByIds({ doc_ids: ids, run: 1 });
223
  };
224
 
225
  const handleNextClick = () => {
web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { ReactComponent as CancelIcon } from '@/assets/svg/cancel.svg';
2
+ import { ReactComponent as DeleteIcon } from '@/assets/svg/delete.svg';
3
+ import { ReactComponent as DisableIcon } from '@/assets/svg/disable.svg';
4
+ import { ReactComponent as EnableIcon } from '@/assets/svg/enable.svg';
5
+ import { ReactComponent as RunIcon } from '@/assets/svg/run.svg';
6
+ import { useShowDeleteConfirm, useTranslate } from '@/hooks/commonHooks';
7
+ import {
8
+ useRemoveDocument,
9
+ useRunDocument,
10
+ useSetDocumentStatus,
11
+ } from '@/hooks/documentHooks';
12
+ import { useGetKnowledgeSearchParams } from '@/hooks/routeHook';
13
+ import {
14
+ DownOutlined,
15
+ FileOutlined,
16
+ FileTextOutlined,
17
+ PlusOutlined,
18
+ SearchOutlined,
19
+ } from '@ant-design/icons';
20
+ import { Button, Dropdown, Flex, Input, MenuProps, Space } from 'antd';
21
+ import { useCallback, useMemo } from 'react';
22
+ import {
23
+ useFetchDocumentListOnMount,
24
+ useGetPagination,
25
+ useHandleSearchChange,
26
+ useNavigateToOtherPage,
27
+ } from './hooks';
28
+ import styles from './index.less';
29
+
30
+ interface IProps {
31
+ selectedRowKeys: string[];
32
+ showCreateModal(): void;
33
+ }
34
+
35
+ const DocumentToolbar = ({ selectedRowKeys, showCreateModal }: IProps) => {
36
+ const { t } = useTranslate('knowledgeDetails');
37
+ const { fetchDocumentList } = useFetchDocumentListOnMount();
38
+ const { setPagination, searchString } = useGetPagination(fetchDocumentList);
39
+ const { handleInputChange } = useHandleSearchChange(setPagination);
40
+ const removeDocument = useRemoveDocument();
41
+ const showDeleteConfirm = useShowDeleteConfirm();
42
+ const { linkToUploadPage } = useNavigateToOtherPage();
43
+ const runDocumentByIds = useRunDocument();
44
+ const { knowledgeId } = useGetKnowledgeSearchParams();
45
+ const changeStatus = useSetDocumentStatus();
46
+
47
+ const actionItems: MenuProps['items'] = useMemo(() => {
48
+ return [
49
+ {
50
+ key: '1',
51
+ onClick: linkToUploadPage,
52
+ label: (
53
+ <div>
54
+ <Button type="link">
55
+ <Space>
56
+ <FileTextOutlined />
57
+ {t('localFiles')}
58
+ </Space>
59
+ </Button>
60
+ </div>
61
+ ),
62
+ },
63
+ { type: 'divider' },
64
+ {
65
+ key: '2',
66
+ onClick: showCreateModal,
67
+ label: (
68
+ <div>
69
+ <Button type="link">
70
+ <FileOutlined />
71
+ {t('emptyFiles')}
72
+ </Button>
73
+ </div>
74
+ ),
75
+ // disabled: true,
76
+ },
77
+ ];
78
+ }, [linkToUploadPage, showCreateModal, t]);
79
+
80
+ const handleDelete = useCallback(() => {
81
+ showDeleteConfirm({
82
+ onOk: () => {
83
+ selectedRowKeys.forEach((id) => {
84
+ removeDocument(id);
85
+ });
86
+ },
87
+ });
88
+ }, [removeDocument, showDeleteConfirm, selectedRowKeys]);
89
+
90
+ const runDocument = useCallback(
91
+ (run: number) => {
92
+ runDocumentByIds({
93
+ doc_ids: selectedRowKeys,
94
+ run,
95
+ knowledgeBaseId: knowledgeId,
96
+ });
97
+ },
98
+ [runDocumentByIds, selectedRowKeys, knowledgeId],
99
+ );
100
+
101
+ const handleRunClick = useCallback(() => {
102
+ runDocument(1);
103
+ }, [runDocument]);
104
+
105
+ const handleCancelClick = useCallback(() => {
106
+ runDocument(2);
107
+ }, [runDocument]);
108
+
109
+ const onChangeStatus = useCallback(
110
+ (enabled: boolean) => {
111
+ selectedRowKeys.forEach((id) => {
112
+ changeStatus(enabled, id);
113
+ });
114
+ },
115
+ [selectedRowKeys, changeStatus],
116
+ );
117
+
118
+ const handleEnableClick = useCallback(() => {
119
+ onChangeStatus(true);
120
+ }, [onChangeStatus]);
121
+
122
+ const handleDisableClick = useCallback(() => {
123
+ onChangeStatus(false);
124
+ }, [onChangeStatus]);
125
+
126
+ const disabled = selectedRowKeys.length === 0;
127
+
128
+ const items: MenuProps['items'] = useMemo(() => {
129
+ return [
130
+ {
131
+ key: '0',
132
+ onClick: handleEnableClick,
133
+ label: (
134
+ <Flex gap={10}>
135
+ <EnableIcon></EnableIcon>
136
+ <b>{t('enabled')}</b>
137
+ </Flex>
138
+ ),
139
+ },
140
+ {
141
+ key: '1',
142
+ onClick: handleDisableClick,
143
+ label: (
144
+ <Flex gap={10}>
145
+ <DisableIcon></DisableIcon>
146
+ <b>{t('disabled')}</b>
147
+ </Flex>
148
+ ),
149
+ },
150
+ { type: 'divider' },
151
+ {
152
+ key: '2',
153
+ onClick: handleRunClick,
154
+ label: (
155
+ <Flex gap={10}>
156
+ <RunIcon></RunIcon>
157
+ <b>{t('run')}</b>
158
+ </Flex>
159
+ ),
160
+ },
161
+ {
162
+ key: '3',
163
+ onClick: handleCancelClick,
164
+ label: (
165
+ <Flex gap={10}>
166
+ <CancelIcon />
167
+ <b>{t('cancel')}</b>
168
+ </Flex>
169
+ ),
170
+ },
171
+ { type: 'divider' },
172
+ {
173
+ key: '4',
174
+ onClick: handleDelete,
175
+ label: (
176
+ <Flex gap={10}>
177
+ <span className={styles.deleteIconWrapper}>
178
+ <DeleteIcon width={18} />
179
+ </span>
180
+ <b>{t('delete', { keyPrefix: 'common' })}</b>
181
+ </Flex>
182
+ ),
183
+ },
184
+ ];
185
+ }, [handleDelete, handleRunClick, handleCancelClick, t]);
186
+
187
+ return (
188
+ <div className={styles.filter}>
189
+ <Dropdown
190
+ menu={{ items }}
191
+ placement="bottom"
192
+ arrow={false}
193
+ disabled={disabled}
194
+ >
195
+ <Button>
196
+ <Space>
197
+ <b> {t('bulk')}</b>
198
+ <DownOutlined />
199
+ </Space>
200
+ </Button>
201
+ </Dropdown>
202
+ <Space>
203
+ <Input
204
+ placeholder={t('searchFiles')}
205
+ value={searchString}
206
+ style={{ width: 220 }}
207
+ allowClear
208
+ onChange={handleInputChange}
209
+ prefix={<SearchOutlined />}
210
+ />
211
+
212
+ <Dropdown menu={{ items: actionItems }} trigger={['click']}>
213
+ <Button type="primary" icon={<PlusOutlined />}>
214
+ {t('addFile')}
215
+ </Button>
216
+ </Dropdown>
217
+ </Space>
218
+ </div>
219
+ );
220
+ };
221
+
222
+ export default DocumentToolbar;
web/src/pages/add-knowledge/components/knowledge-file/hooks.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { useSetModalState } from '@/hooks/commonHooks';
2
  import {
3
  useCreateDocument,
4
  useFetchDocumentList,
@@ -11,7 +11,7 @@ import { useFetchTenantInfo } from '@/hooks/userSettingHook';
11
  import { Pagination } from '@/interfaces/common';
12
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
13
  import { PaginationProps } from 'antd';
14
- import { useCallback, useEffect, useMemo } from 'react';
15
  import { useDispatch, useNavigate, useSelector } from 'umi';
16
  import { KnowledgeRouteKey } from './constant';
17
 
@@ -43,6 +43,7 @@ export const useFetchDocumentListOnMount = () => {
43
  export const useGetPagination = (fetchDocumentList: () => void) => {
44
  const dispatch = useDispatch();
45
  const kFModel = useSelector((state: any) => state.kFModel);
 
46
 
47
  const setPagination = useCallback(
48
  (pageNumber = 1, pageSize?: number) => {
@@ -77,8 +78,9 @@ export const useGetPagination = (fetchDocumentList: () => void) => {
77
  pageSize: kFModel.pagination.pageSize,
78
  pageSizeOptions: [1, 2, 10, 20, 50, 100],
79
  onChange: onPageChange,
 
80
  };
81
- }, [kFModel, onPageChange]);
82
 
83
  return {
84
  pagination,
@@ -227,3 +229,16 @@ export const useChangeDocumentParser = (documentId: string) => {
227
  showChangeParserModal,
228
  };
229
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useSetModalState, useTranslate } from '@/hooks/commonHooks';
2
  import {
3
  useCreateDocument,
4
  useFetchDocumentList,
 
11
  import { Pagination } from '@/interfaces/common';
12
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
13
  import { PaginationProps } from 'antd';
14
+ import { useCallback, useEffect, useMemo, useState } from 'react';
15
  import { useDispatch, useNavigate, useSelector } from 'umi';
16
  import { KnowledgeRouteKey } from './constant';
17
 
 
43
  export const useGetPagination = (fetchDocumentList: () => void) => {
44
  const dispatch = useDispatch();
45
  const kFModel = useSelector((state: any) => state.kFModel);
46
+ const { t } = useTranslate('common');
47
 
48
  const setPagination = useCallback(
49
  (pageNumber = 1, pageSize?: number) => {
 
78
  pageSize: kFModel.pagination.pageSize,
79
  pageSizeOptions: [1, 2, 10, 20, 50, 100],
80
  onChange: onPageChange,
81
+ showTotal: (total) => `${t('total')} ${total}`,
82
  };
83
+ }, [kFModel, onPageChange, t]);
84
 
85
  return {
86
  pagination,
 
229
  showChangeParserModal,
230
  };
231
  };
232
+
233
+ export const useGetRowSelection = () => {
234
+ const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
235
+
236
+ const rowSelection = {
237
+ selectedRowKeys,
238
+ onChange: (newSelectedRowKeys: React.Key[]) => {
239
+ setSelectedRowKeys(newSelectedRowKeys);
240
+ },
241
+ };
242
+
243
+ return rowSelection;
244
+ };
web/src/pages/add-knowledge/components/knowledge-file/index.less CHANGED
@@ -8,15 +8,13 @@
8
  display: flex;
9
  margin: 10px 0;
10
  justify-content: space-between;
11
- padding: 24px 20px;
12
-
13
- // .search {
14
- // flex: 1;
15
- // }
16
 
17
- // .operate {
18
- // width: 200px;
19
- // }
20
  }
21
 
22
  .img {
 
8
  display: flex;
9
  margin: 10px 0;
10
  justify-content: space-between;
11
+ padding: 24px 0;
12
+ align-items: center;
13
+ }
 
 
14
 
15
+ .deleteIconWrapper {
16
+ width: 22px;
17
+ text-align: center;
18
  }
19
 
20
  .img {
web/src/pages/add-knowledge/components/knowledge-file/index.tsx CHANGED
@@ -4,36 +4,21 @@ import {
4
  useSelectDocumentList,
5
  useSetDocumentStatus,
6
  } from '@/hooks/documentHooks';
 
7
  import { useSelectParserList } from '@/hooks/userSettingHook';
8
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
9
  import { getExtension } from '@/utils/documentUtils';
10
- import {
11
- FileOutlined,
12
- FileTextOutlined,
13
- PlusOutlined,
14
- SearchOutlined,
15
- } from '@ant-design/icons';
16
- import type { MenuProps } from 'antd';
17
- import {
18
- Button,
19
- Divider,
20
- Dropdown,
21
- Flex,
22
- Input,
23
- Space,
24
- Switch,
25
- Table,
26
- Tag,
27
- } from 'antd';
28
  import type { ColumnsType } from 'antd/es/table';
29
- import { useMemo } from 'react';
30
  import CreateFileModal from './create-file-modal';
 
31
  import {
32
  useChangeDocumentParser,
33
  useCreateEmptyDocument,
34
  useFetchDocumentListOnMount,
35
  useGetPagination,
36
- useHandleSearchChange,
37
  useNavigateToOtherPage,
38
  useRenameDocument,
39
  } from './hooks';
@@ -41,20 +26,15 @@ import ParsingActionCell from './parsing-action-cell';
41
  import ParsingStatusCell from './parsing-status-cell';
42
  import RenameModal from './rename-modal';
43
 
44
- import { useSetSelectedRecord } from '@/hooks/logicHooks';
45
- import { useTranslation } from 'react-i18next';
46
  import styles from './index.less';
47
 
48
  const KnowledgeFile = () => {
49
  const data = useSelectDocumentList();
50
  const { fetchDocumentList } = useFetchDocumentListOnMount();
51
  const parserList = useSelectParserList();
52
- const { pagination, setPagination, total, searchString } =
53
- useGetPagination(fetchDocumentList);
54
  const onChangeStatus = useSetDocumentStatus();
55
- const { linkToUploadPage, toChunk } = useNavigateToOtherPage();
56
-
57
- const { handleInputChange } = useHandleSearchChange(setPagination);
58
  const { currentRecord, setRecord } = useSetSelectedRecord();
59
  const {
60
  renameLoading,
@@ -81,38 +61,7 @@ const KnowledgeFile = () => {
81
  keyPrefix: 'knowledgeDetails',
82
  });
83
 
84
- const actionItems: MenuProps['items'] = useMemo(() => {
85
- return [
86
- {
87
- key: '1',
88
- onClick: linkToUploadPage,
89
- label: (
90
- <div>
91
- <Button type="link">
92
- <Space>
93
- <FileTextOutlined />
94
- {t('localFiles')}
95
- </Space>
96
- </Button>
97
- </div>
98
- ),
99
- },
100
- { type: 'divider' },
101
- {
102
- key: '2',
103
- onClick: showCreateModal,
104
- label: (
105
- <div>
106
- <Button type="link">
107
- <FileOutlined />
108
- {t('emptyFiles')}
109
- </Button>
110
- </div>
111
- ),
112
- // disabled: true,
113
- },
114
- ];
115
- }, [linkToUploadPage, showCreateModal, t]);
116
 
117
  const columns: ColumnsType<IKnowledgeFile> = [
118
  {
@@ -161,7 +110,7 @@ const KnowledgeFile = () => {
161
  render: (_, { status, id }) => (
162
  <>
163
  <Switch
164
- defaultChecked={status === '1'}
165
  onChange={(e) => {
166
  onChangeStatus(e, id);
167
  }}
@@ -201,36 +150,17 @@ const KnowledgeFile = () => {
201
  <h3>{t('dataset')}</h3>
202
  <p>{t('datasetDescription')}</p>
203
  <Divider></Divider>
204
- <div className={styles.filter}>
205
- <Space>
206
- <h3>{t('total', { keyPrefix: 'common' })}</h3>
207
- <Tag color="purple">
208
- {total} {t('files')}
209
- </Tag>
210
- </Space>
211
- <Space>
212
- <Input
213
- placeholder={t('searchFiles')}
214
- value={searchString}
215
- style={{ width: 220 }}
216
- allowClear
217
- onChange={handleInputChange}
218
- prefix={<SearchOutlined />}
219
- />
220
-
221
- <Dropdown menu={{ items: actionItems }} trigger={['click']}>
222
- <Button type="primary" icon={<PlusOutlined />}>
223
- {t('addFile')}
224
- </Button>
225
- </Dropdown>
226
- </Space>
227
- </div>
228
  <Table
229
  rowKey="id"
230
  columns={finalColumns}
231
  dataSource={data}
232
  // loading={loading}
233
  pagination={pagination}
 
234
  scroll={{ scrollToFirstRowOnChange: true, x: 1300, y: 'fill' }}
235
  />
236
  <CreateFileModal
 
4
  useSelectDocumentList,
5
  useSetDocumentStatus,
6
  } from '@/hooks/documentHooks';
7
+ import { useSetSelectedRecord } from '@/hooks/logicHooks';
8
  import { useSelectParserList } from '@/hooks/userSettingHook';
9
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
10
  import { getExtension } from '@/utils/documentUtils';
11
+ import { Divider, Flex, Switch, Table } from 'antd';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  import type { ColumnsType } from 'antd/es/table';
13
+ import { useTranslation } from 'react-i18next';
14
  import CreateFileModal from './create-file-modal';
15
+ import DocumentToolbar from './document-toolbar';
16
  import {
17
  useChangeDocumentParser,
18
  useCreateEmptyDocument,
19
  useFetchDocumentListOnMount,
20
  useGetPagination,
21
+ useGetRowSelection,
22
  useNavigateToOtherPage,
23
  useRenameDocument,
24
  } from './hooks';
 
26
  import ParsingStatusCell from './parsing-status-cell';
27
  import RenameModal from './rename-modal';
28
 
 
 
29
  import styles from './index.less';
30
 
31
  const KnowledgeFile = () => {
32
  const data = useSelectDocumentList();
33
  const { fetchDocumentList } = useFetchDocumentListOnMount();
34
  const parserList = useSelectParserList();
35
+ const { pagination } = useGetPagination(fetchDocumentList);
 
36
  const onChangeStatus = useSetDocumentStatus();
37
+ const { toChunk } = useNavigateToOtherPage();
 
 
38
  const { currentRecord, setRecord } = useSetSelectedRecord();
39
  const {
40
  renameLoading,
 
61
  keyPrefix: 'knowledgeDetails',
62
  });
63
 
64
+ const rowSelection = useGetRowSelection();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  const columns: ColumnsType<IKnowledgeFile> = [
67
  {
 
110
  render: (_, { status, id }) => (
111
  <>
112
  <Switch
113
+ checked={status === '1'}
114
  onChange={(e) => {
115
  onChangeStatus(e, id);
116
  }}
 
150
  <h3>{t('dataset')}</h3>
151
  <p>{t('datasetDescription')}</p>
152
  <Divider></Divider>
153
+ <DocumentToolbar
154
+ selectedRowKeys={rowSelection.selectedRowKeys as string[]}
155
+ showCreateModal={showCreateModal}
156
+ ></DocumentToolbar>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  <Table
158
  rowKey="id"
159
  columns={finalColumns}
160
  dataSource={data}
161
  // loading={loading}
162
  pagination={pagination}
163
+ rowSelection={rowSelection}
164
  scroll={{ scrollToFirstRowOnChange: true, x: 1300, y: 'fill' }}
165
  />
166
  <CreateFileModal
web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx CHANGED
@@ -30,12 +30,12 @@ const ParsingActionCell = ({
30
  const documentId = record.id;
31
  const isRunning = isParserRunning(record.run);
32
  const { t } = useTranslate('knowledgeDetails');
33
- const removeDocument = useRemoveDocument(documentId);
34
  const showDeleteConfirm = useShowDeleteConfirm();
35
 
36
  const onRmDocument = () => {
37
  if (!isRunning) {
38
- showDeleteConfirm({ onOk: removeDocument });
39
  }
40
  };
41
 
 
30
  const documentId = record.id;
31
  const isRunning = isParserRunning(record.run);
32
  const { t } = useTranslate('knowledgeDetails');
33
+ const removeDocument = useRemoveDocument();
34
  const showDeleteConfirm = useShowDeleteConfirm();
35
 
36
  const onRmDocument = () => {
37
  if (!isRunning) {
38
+ showDeleteConfirm({ onOk: () => removeDocument(documentId) });
39
  }
40
  };
41
 
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.less CHANGED
@@ -18,8 +18,7 @@
18
 
19
  .operationIcon {
20
  text-align: center;
21
- margin-right: 20%;
22
- width: 20px;
23
  &:hover {
24
  cursor: pointer;
25
  }
 
18
 
19
  .operationIcon {
20
  text-align: center;
21
+ display: flex;
 
22
  &:hover {
23
  cursor: pointer;
24
  }
web/src/pages/add-knowledge/components/knowledge-file/parsing-status-cell/index.tsx CHANGED
@@ -1,19 +1,19 @@
 
1
  import { ReactComponent as RefreshIcon } from '@/assets/svg/refresh.svg';
2
  import { ReactComponent as RunIcon } from '@/assets/svg/run.svg';
3
  import { useTranslate } from '@/hooks/commonHooks';
 
4
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
5
- import { CloseCircleOutlined } from '@ant-design/icons';
6
  import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
7
  import { useTranslation } from 'react-i18next';
8
  import reactStringReplace from 'react-string-replace';
9
- import { useDispatch } from 'umi';
10
  import { RunningStatus, RunningStatusMap } from '../constant';
11
  import { isParserRunning } from '../utils';
12
  import styles from './index.less';
13
 
14
  const iconMap = {
15
  [RunningStatus.UNSTART]: RunIcon,
16
- [RunningStatus.RUNNING]: CloseCircleOutlined,
17
  [RunningStatus.CANCEL]: RefreshIcon,
18
  [RunningStatus.DONE]: RefreshIcon,
19
  [RunningStatus.FAIL]: RefreshIcon,
@@ -78,10 +78,10 @@ const PopoverContent = ({ record }: IProps) => {
78
  };
79
 
80
  export const ParsingStatusCell = ({ record }: IProps) => {
81
- const dispatch = useDispatch();
82
  const text = record.run;
83
  const runningStatus = RunningStatusMap[text];
84
  const { t } = useTranslation();
 
85
 
86
  const isRunning = isParserRunning(text);
87
 
@@ -90,18 +90,15 @@ export const ParsingStatusCell = ({ record }: IProps) => {
90
  const label = t(`knowledgeDetails.runningStatus${text}`);
91
 
92
  const handleOperationIconClick = () => {
93
- dispatch({
94
- type: 'kFModel/document_run',
95
- payload: {
96
- doc_ids: [record.id],
97
- run: isRunning ? 2 : 1,
98
- knowledgeBaseId: record.kb_id,
99
- },
100
  });
101
  };
102
 
103
  return (
104
- <Flex justify={'space-between'}>
105
  <Popover content={<PopoverContent record={record}></PopoverContent>}>
106
  <Tag color={runningStatus.color}>
107
  {isRunning ? (
 
1
+ import { ReactComponent as CancelIcon } from '@/assets/svg/cancel.svg';
2
  import { ReactComponent as RefreshIcon } from '@/assets/svg/refresh.svg';
3
  import { ReactComponent as RunIcon } from '@/assets/svg/run.svg';
4
  import { useTranslate } from '@/hooks/commonHooks';
5
+ import { useRunDocument } from '@/hooks/documentHooks';
6
  import { IKnowledgeFile } from '@/interfaces/database/knowledge';
 
7
  import { Badge, DescriptionsProps, Flex, Popover, Space, Tag } from 'antd';
8
  import { useTranslation } from 'react-i18next';
9
  import reactStringReplace from 'react-string-replace';
 
10
  import { RunningStatus, RunningStatusMap } from '../constant';
11
  import { isParserRunning } from '../utils';
12
  import styles from './index.less';
13
 
14
  const iconMap = {
15
  [RunningStatus.UNSTART]: RunIcon,
16
+ [RunningStatus.RUNNING]: CancelIcon,
17
  [RunningStatus.CANCEL]: RefreshIcon,
18
  [RunningStatus.DONE]: RefreshIcon,
19
  [RunningStatus.FAIL]: RefreshIcon,
 
78
  };
79
 
80
  export const ParsingStatusCell = ({ record }: IProps) => {
 
81
  const text = record.run;
82
  const runningStatus = RunningStatusMap[text];
83
  const { t } = useTranslation();
84
+ const runDocumentByIds = useRunDocument();
85
 
86
  const isRunning = isParserRunning(text);
87
 
 
90
  const label = t(`knowledgeDetails.runningStatus${text}`);
91
 
92
  const handleOperationIconClick = () => {
93
+ runDocumentByIds({
94
+ doc_ids: [record.id],
95
+ run: isRunning ? 2 : 1,
96
+ knowledgeBaseId: record.kb_id,
 
 
 
97
  });
98
  };
99
 
100
  return (
101
+ <Flex justify={'space-between'} align="center">
102
  <Popover content={<PopoverContent record={record}></PopoverContent>}>
103
  <Tag color={runningStatus.color}>
104
  {isRunning ? (