balibabu commited on
Commit
8e109c7
·
1 Parent(s): 9593f88

fix: filter knowledge list by keywords and clear the selected file list after the file is uploaded successfully and add ellipsis pattern to chunk list (#628)

Browse files

### What problem does this PR solve?

#627
fix: filter knowledge list by keywords
fix: clear the selected file list after the file is uploaded
successfully
feat: add ellipsis pattern to chunk list

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)

web/src/components/chunk-method-modal/index.tsx CHANGED
@@ -48,6 +48,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
48
  visible,
49
  documentExtension,
50
  parserConfig,
 
51
  }) => {
52
  const { parserList, handleChange, selectedTag } = useFetchParserListOnMount(
53
  documentId,
@@ -109,6 +110,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
109
  onOk={handleOk}
110
  onCancel={hideModal}
111
  afterClose={afterClose}
 
112
  >
113
  <Space size={[0, 8]} wrap>
114
  <Form.Item label={t('chunkMethod')} className={styles.chunkMethod}>
 
48
  visible,
49
  documentExtension,
50
  parserConfig,
51
+ loading,
52
  }) => {
53
  const { parserList, handleChange, selectedTag } = useFetchParserListOnMount(
54
  documentId,
 
110
  onOk={handleOk}
111
  onCancel={hideModal}
112
  afterClose={afterClose}
113
+ confirmLoading={loading}
114
  >
115
  <Space size={[0, 8]} wrap>
116
  <Form.Item label={t('chunkMethod')} className={styles.chunkMethod}>
web/src/components/file-upload-modal/index.tsx CHANGED
@@ -68,15 +68,20 @@ const FileUploadModal = ({
68
  const [fileList, setFileList] = useState<UploadFile[]>([]);
69
  const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
70
 
 
 
 
 
 
71
  const onOk = async () => {
72
  const ret = await onFileUploadOk?.([...fileList, ...directoryFileList]);
73
- if (ret !== undefined && ret === 0) {
74
- setFileList([]);
75
- setDirectoryFileList([]);
76
- }
77
  return ret;
78
  };
79
 
 
 
 
 
80
  const items: TabsProps['items'] = [
81
  {
82
  key: '1',
@@ -110,6 +115,7 @@ const FileUploadModal = ({
110
  onOk={onOk}
111
  onCancel={hideModal}
112
  confirmLoading={loading}
 
113
  >
114
  <Flex gap={'large'} vertical>
115
  <Segmented
 
68
  const [fileList, setFileList] = useState<UploadFile[]>([]);
69
  const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
70
 
71
+ const clearFileList = () => {
72
+ setFileList([]);
73
+ setDirectoryFileList([]);
74
+ };
75
+
76
  const onOk = async () => {
77
  const ret = await onFileUploadOk?.([...fileList, ...directoryFileList]);
 
 
 
 
78
  return ret;
79
  };
80
 
81
+ const afterClose = () => {
82
+ clearFileList();
83
+ };
84
+
85
  const items: TabsProps['items'] = [
86
  {
87
  key: '1',
 
115
  onOk={onOk}
116
  onCancel={hideModal}
117
  confirmLoading={loading}
118
+ afterClose={afterClose}
119
  >
120
  <Flex gap={'large'} vertical>
121
  <Segmented
web/src/hooks/knowledgeHook.ts CHANGED
@@ -125,13 +125,19 @@ export const useFetchKnowledgeBaseConfiguration = () => {
125
  }, [fetchKnowledgeBaseConfiguration]);
126
  };
127
 
 
 
 
 
 
 
128
  export const useFetchKnowledgeList = (
129
  shouldFilterListWithoutDocument: boolean = false,
130
  ) => {
131
  const dispatch = useDispatch();
132
  const loading = useOneNamespaceEffectsLoading('knowledgeModel', ['getList']);
133
 
134
- const knowledgeModel = useSelector((state: any) => state.knowledgeModel);
135
  const { data = [] } = knowledgeModel;
136
  const list: IKnowledge[] = useMemo(() => {
137
  return shouldFilterListWithoutDocument
 
125
  }, [fetchKnowledgeBaseConfiguration]);
126
  };
127
 
128
+ export const useSelectKnowledgeList = () => {
129
+ const knowledgeModel = useSelector((state) => state.knowledgeModel);
130
+ const { data = [] } = knowledgeModel;
131
+ return data;
132
+ };
133
+
134
  export const useFetchKnowledgeList = (
135
  shouldFilterListWithoutDocument: boolean = false,
136
  ) => {
137
  const dispatch = useDispatch();
138
  const loading = useOneNamespaceEffectsLoading('knowledgeModel', ['getList']);
139
 
140
+ const knowledgeModel = useSelector((state) => state.knowledgeModel);
141
  const { data = [] } = knowledgeModel;
142
  const list: IKnowledge[] = useMemo(() => {
143
  return shouldFilterListWithoutDocument
web/src/less/mixins.less CHANGED
@@ -42,3 +42,17 @@
42
  }
43
  }
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
  }
44
  }
45
+
46
+ .textEllipsis() {
47
+ overflow: hidden;
48
+ text-overflow: ellipsis;
49
+ white-space: nowrap;
50
+ }
51
+
52
+ .multipleLineEllipsis(@line) {
53
+ display: -webkit-box;
54
+ -webkit-box-orient: vertical;
55
+ -webkit-line-clamp: @line;
56
+ overflow: hidden;
57
+ text-overflow: ellipsis;
58
+ }
web/src/locales/en.ts CHANGED
@@ -64,6 +64,7 @@ export default {
64
  name: 'Name',
65
  namePlaceholder: 'Please input name!',
66
  doc: 'Docs',
 
67
  },
68
  knowledgeDetails: {
69
  dataset: 'Dataset',
@@ -278,6 +279,8 @@ export default {
278
  keyword: 'Keyword',
279
  function: 'Function',
280
  chunkMessage: 'Please input value!',
 
 
281
  },
282
  chat: {
283
  createAssistant: 'Create an Assistant',
 
64
  name: 'Name',
65
  namePlaceholder: 'Please input name!',
66
  doc: 'Docs',
67
+ searchKnowledgePlaceholder: 'Search',
68
  },
69
  knowledgeDetails: {
70
  dataset: 'Dataset',
 
279
  keyword: 'Keyword',
280
  function: 'Function',
281
  chunkMessage: 'Please input value!',
282
+ full: 'Full text',
283
+ ellipse: 'Ellipse',
284
  },
285
  chat: {
286
  createAssistant: 'Create an Assistant',
web/src/locales/zh-traditional.ts CHANGED
@@ -64,6 +64,7 @@ export default {
64
  name: '名稱',
65
  namePlaceholder: '請輸入名稱',
66
  doc: '文件',
 
67
  },
68
  knowledgeDetails: {
69
  dataset: '數據集',
@@ -251,6 +252,8 @@ export default {
251
  keyword: '關鍵詞',
252
  function: '函數',
253
  chunkMessage: '請輸入值!',
 
 
254
  },
255
  chat: {
256
  createAssistant: '新建助理',
 
64
  name: '名稱',
65
  namePlaceholder: '請輸入名稱',
66
  doc: '文件',
67
+ searchKnowledgePlaceholder: '搜索',
68
  },
69
  knowledgeDetails: {
70
  dataset: '數據集',
 
252
  keyword: '關鍵詞',
253
  function: '函數',
254
  chunkMessage: '請輸入值!',
255
+ full: '全文',
256
+ ellipse: '省略',
257
  },
258
  chat: {
259
  createAssistant: '新建助理',
web/src/locales/zh.ts CHANGED
@@ -64,6 +64,7 @@ export default {
64
  name: '名称',
65
  namePlaceholder: '请输入名称',
66
  doc: '文档',
 
67
  },
68
  knowledgeDetails: {
69
  dataset: '数据集',
@@ -268,6 +269,8 @@ export default {
268
  keyword: '关键词',
269
  function: '函数',
270
  chunkMessage: '请输入值!',
 
 
271
  },
272
  chat: {
273
  createAssistant: '新建助理',
 
64
  name: '名称',
65
  namePlaceholder: '请输入名称',
66
  doc: '文档',
67
+ searchKnowledgePlaceholder: '搜索',
68
  },
69
  knowledgeDetails: {
70
  dataset: '数据集',
 
269
  keyword: '关键词',
270
  function: '函数',
271
  chunkMessage: '请输入值!',
272
+ full: '全文',
273
+ ellipse: '省略',
274
  },
275
  chat: {
276
  createAssistant: '新建助理',
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less CHANGED
@@ -14,6 +14,10 @@
14
  .chunkText;
15
  }
16
 
 
 
 
 
17
  .chunkCard {
18
  width: 100%;
19
  }
 
14
  .chunkText;
15
  }
16
 
17
+ .contentEllipsis {
18
+ .multipleLineEllipsis(3);
19
+ }
20
+
21
  .chunkCard {
22
  width: 100%;
23
  }
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx CHANGED
@@ -4,6 +4,7 @@ import { Card, Checkbox, CheckboxProps, Flex, Popover, Switch } from 'antd';
4
  import classNames from 'classnames';
5
  import { useState } from 'react';
6
 
 
7
  import styles from './index.less';
8
 
9
  interface IProps {
@@ -14,6 +15,7 @@ interface IProps {
14
  handleCheckboxClick: (chunkId: string, checked: boolean) => void;
15
  selected: boolean;
16
  clickChunkCard: (chunkId: string) => void;
 
17
  }
18
 
19
  const ChunkCard = ({
@@ -24,6 +26,7 @@ const ChunkCard = ({
24
  switchChunk,
25
  selected,
26
  clickChunkCard,
 
27
  }: IProps) => {
28
  const available = Number(item.available_int);
29
  const [enabled, setEnabled] = useState(available === 1);
@@ -68,8 +71,15 @@ const ChunkCard = ({
68
  onDoubleClick={handleContentDoubleClick}
69
  onClick={handleContentClick}
70
  className={styles.content}
71
- dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
72
- ></section>
 
 
 
 
 
 
 
73
  <div>
74
  <Switch checked={enabled} onChange={onChange} />
75
  </div>
 
4
  import classNames from 'classnames';
5
  import { useState } from 'react';
6
 
7
+ import { ChunkTextMode } from '../../constant';
8
  import styles from './index.less';
9
 
10
  interface IProps {
 
15
  handleCheckboxClick: (chunkId: string, checked: boolean) => void;
16
  selected: boolean;
17
  clickChunkCard: (chunkId: string) => void;
18
+ textMode: ChunkTextMode;
19
  }
20
 
21
  const ChunkCard = ({
 
26
  switchChunk,
27
  selected,
28
  clickChunkCard,
29
+ textMode,
30
  }: IProps) => {
31
  const available = Number(item.available_int);
32
  const [enabled, setEnabled] = useState(available === 1);
 
71
  onDoubleClick={handleContentDoubleClick}
72
  onClick={handleContentClick}
73
  className={styles.content}
74
+ >
75
+ <div
76
+ dangerouslySetInnerHTML={{ __html: item.content_with_weight }}
77
+ className={classNames({
78
+ [styles.contentEllipsis]: textMode === ChunkTextMode.Ellipse,
79
+ })}
80
+ ></div>
81
+ </section>
82
+
83
  <div>
84
  <Switch checked={enabled} onChange={onChange} />
85
  </div>
web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx CHANGED
@@ -22,12 +22,18 @@ import {
22
  Popover,
23
  Radio,
24
  RadioChangeEvent,
 
 
25
  Space,
 
26
  } from 'antd';
27
  import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
28
  import { Link, useDispatch, useSelector } from 'umi';
 
29
  import { ChunkModelState } from '../../model';
30
 
 
 
31
  interface IProps {
32
  checked: boolean;
33
  getChunkList: () => void;
@@ -35,6 +41,7 @@ interface IProps {
35
  createChunk: () => void;
36
  removeChunk: () => void;
37
  switchChunk: (available: number) => void;
 
38
  }
39
 
40
  const ChunkToolBar = ({
@@ -44,6 +51,7 @@ const ChunkToolBar = ({
44
  createChunk,
45
  removeChunk,
46
  switchChunk,
 
47
  }: IProps) => {
48
  const { documentInfo, available, searchString }: ChunkModelState =
49
  useSelector((state: any) => state.chunkModel);
@@ -170,9 +178,18 @@ const ChunkToolBar = ({
170
  <ArrowLeftOutlined />
171
  </Link>
172
  <FilePdfOutlined />
173
- {documentInfo.name}
 
 
174
  </Space>
175
  <Space>
 
 
 
 
 
 
 
176
  <Popover content={content} placement="bottom" arrow={false}>
177
  <Button>
178
  {t('bulk')}
 
22
  Popover,
23
  Radio,
24
  RadioChangeEvent,
25
+ Segmented,
26
+ SegmentedProps,
27
  Space,
28
+ Typography,
29
  } from 'antd';
30
  import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
31
  import { Link, useDispatch, useSelector } from 'umi';
32
+ import { ChunkTextMode } from '../../constant';
33
  import { ChunkModelState } from '../../model';
34
 
35
+ const { Text } = Typography;
36
+
37
  interface IProps {
38
  checked: boolean;
39
  getChunkList: () => void;
 
41
  createChunk: () => void;
42
  removeChunk: () => void;
43
  switchChunk: (available: number) => void;
44
+ changeChunkTextMode(mode: ChunkTextMode): void;
45
  }
46
 
47
  const ChunkToolBar = ({
 
51
  createChunk,
52
  removeChunk,
53
  switchChunk,
54
+ changeChunkTextMode,
55
  }: IProps) => {
56
  const { documentInfo, available, searchString }: ChunkModelState =
57
  useSelector((state: any) => state.chunkModel);
 
178
  <ArrowLeftOutlined />
179
  </Link>
180
  <FilePdfOutlined />
181
+ <Text ellipsis={{ tooltip: documentInfo.name }} style={{ width: 150 }}>
182
+ {documentInfo.name}
183
+ </Text>
184
  </Space>
185
  <Space>
186
+ <Segmented
187
+ options={[
188
+ { label: t(ChunkTextMode.Full), value: ChunkTextMode.Full },
189
+ { label: t(ChunkTextMode.Ellipse), value: ChunkTextMode.Ellipse },
190
+ ]}
191
+ onChange={changeChunkTextMode as SegmentedProps['onChange']}
192
+ />
193
  <Popover content={content} placement="bottom" arrow={false}>
194
  <Button>
195
  {t('bulk')}
web/src/pages/add-knowledge/components/knowledge-chunk/constant.ts ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ export enum ChunkTextMode {
2
+ Full = 'full',
3
+ Ellipse = 'ellipse',
4
+ }
web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts CHANGED
@@ -4,6 +4,7 @@ import { buildChunkHighlights } from '@/utils/documentUtils';
4
  import { useCallback, useMemo, useState } from 'react';
5
  import { IHighlight } from 'react-pdf-highlighter';
6
  import { useSelector } from 'umi';
 
7
 
8
  export const useSelectDocumentInfo = () => {
9
  const documentInfo: IKnowledgeFile = useSelector(
@@ -63,3 +64,14 @@ export const useSelectChunkListLoading = () => {
63
  'switch_chunk',
64
  ]);
65
  };
 
 
 
 
 
 
 
 
 
 
 
 
4
  import { useCallback, useMemo, useState } from 'react';
5
  import { IHighlight } from 'react-pdf-highlighter';
6
  import { useSelector } from 'umi';
7
+ import { ChunkTextMode } from './constant';
8
 
9
  export const useSelectDocumentInfo = () => {
10
  const documentInfo: IKnowledgeFile = useSelector(
 
64
  'switch_chunk',
65
  ]);
66
  };
67
+
68
+ // Switch chunk text to be fully displayed or ellipse
69
+ export const useChangeChunkTextMode = () => {
70
+ const [textMode, setTextMode] = useState<ChunkTextMode>(ChunkTextMode.Full);
71
+
72
+ const changeChunkTextMode = useCallback((mode: ChunkTextMode) => {
73
+ setTextMode(mode);
74
+ }, []);
75
+
76
+ return { textMode, changeChunkTextMode };
77
+ };
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx CHANGED
@@ -10,6 +10,7 @@ import CreatingModal from './components/chunk-creating-modal';
10
  import ChunkToolBar from './components/chunk-toolbar';
11
  import DocumentPreview from './components/document-preview/preview';
12
  import {
 
13
  useHandleChunkCardClick,
14
  useSelectChunkListLoading,
15
  useSelectDocumentInfo,
@@ -35,6 +36,7 @@ const Chunk = () => {
35
  const { handleChunkCardClick, selectedChunkId } = useHandleChunkCardClick();
36
  const isPdf = documentInfo.type === 'pdf';
37
  const { t } = useTranslation();
 
38
 
39
  const getChunkList = useFetchChunkList();
40
 
@@ -87,9 +89,10 @@ const Chunk = () => {
87
  },
88
  [],
89
  );
90
- const showSelectedChunkWarning = () => {
 
91
  message.warning(t('message.pleaseSelectChunk'));
92
- };
93
 
94
  const handleRemoveChunk = useCallback(async () => {
95
  if (selectedChunkIds.length > 0) {
@@ -100,7 +103,7 @@ const Chunk = () => {
100
  } else {
101
  showSelectedChunkWarning();
102
  }
103
- }, [selectedChunkIds, documentId, removeChunk]);
104
 
105
  const switchChunk = useCallback(
106
  async (available?: number, chunkIds?: string[]) => {
@@ -125,7 +128,13 @@ const Chunk = () => {
125
  getChunkList();
126
  }
127
  },
128
- [dispatch, documentId, getChunkList, selectedChunkIds],
 
 
 
 
 
 
129
  );
130
 
131
  useEffect(() => {
@@ -147,6 +156,7 @@ const Chunk = () => {
147
  removeChunk={handleRemoveChunk}
148
  checked={selectedChunkIds.length === data.length}
149
  switchChunk={switchChunk}
 
150
  ></ChunkToolBar>
151
  <Divider></Divider>
152
  <Flex flex={1} gap={'middle'}>
@@ -175,6 +185,7 @@ const Chunk = () => {
175
  switchChunk={switchChunk}
176
  clickChunkCard={handleChunkCardClick}
177
  selected={item.chunk_id === selectedChunkId}
 
178
  ></ChunkCard>
179
  ))}
180
  </Space>
 
10
  import ChunkToolBar from './components/chunk-toolbar';
11
  import DocumentPreview from './components/document-preview/preview';
12
  import {
13
+ useChangeChunkTextMode,
14
  useHandleChunkCardClick,
15
  useSelectChunkListLoading,
16
  useSelectDocumentInfo,
 
36
  const { handleChunkCardClick, selectedChunkId } = useHandleChunkCardClick();
37
  const isPdf = documentInfo.type === 'pdf';
38
  const { t } = useTranslation();
39
+ const { changeChunkTextMode, textMode } = useChangeChunkTextMode();
40
 
41
  const getChunkList = useFetchChunkList();
42
 
 
89
  },
90
  [],
91
  );
92
+
93
+ const showSelectedChunkWarning = useCallback(() => {
94
  message.warning(t('message.pleaseSelectChunk'));
95
+ }, [t]);
96
 
97
  const handleRemoveChunk = useCallback(async () => {
98
  if (selectedChunkIds.length > 0) {
 
103
  } else {
104
  showSelectedChunkWarning();
105
  }
106
+ }, [selectedChunkIds, documentId, removeChunk, showSelectedChunkWarning]);
107
 
108
  const switchChunk = useCallback(
109
  async (available?: number, chunkIds?: string[]) => {
 
128
  getChunkList();
129
  }
130
  },
131
+ [
132
+ dispatch,
133
+ documentId,
134
+ getChunkList,
135
+ selectedChunkIds,
136
+ showSelectedChunkWarning,
137
+ ],
138
  );
139
 
140
  useEffect(() => {
 
156
  removeChunk={handleRemoveChunk}
157
  checked={selectedChunkIds.length === data.length}
158
  switchChunk={switchChunk}
159
+ changeChunkTextMode={changeChunkTextMode}
160
  ></ChunkToolBar>
161
  <Divider></Divider>
162
  <Flex flex={1} gap={'middle'}>
 
185
  switchChunk={switchChunk}
186
  clickChunkCard={handleChunkCardClick}
187
  selected={item.chunk_id === selectedChunkId}
188
+ textMode={textMode}
189
  ></ChunkCard>
190
  ))}
191
  </Space>
web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx CHANGED
@@ -23,7 +23,6 @@ import {
23
  useFetchDocumentListOnMount,
24
  useGetPagination,
25
  useHandleSearchChange,
26
- useNavigateToOtherPage,
27
  } from './hooks';
28
  import styles from './index.less';
29
 
@@ -44,7 +43,6 @@ const DocumentToolbar = ({
44
  const { handleInputChange } = useHandleSearchChange(setPagination);
45
  const removeDocument = useRemoveDocument();
46
  const showDeleteConfirm = useShowDeleteConfirm();
47
- const { linkToUploadPage } = useNavigateToOtherPage();
48
  const runDocumentByIds = useRunDocument();
49
  const { knowledgeId } = useGetKnowledgeSearchParams();
50
  const changeStatus = useSetDocumentStatus();
@@ -77,7 +75,6 @@ const DocumentToolbar = ({
77
  </Button>
78
  </div>
79
  ),
80
- // disabled: true,
81
  },
82
  ];
83
  }, [showDocumentUploadModal, showCreateModal, t]);
 
23
  useFetchDocumentListOnMount,
24
  useGetPagination,
25
  useHandleSearchChange,
 
26
  } from './hooks';
27
  import styles from './index.less';
28
 
 
43
  const { handleInputChange } = useHandleSearchChange(setPagination);
44
  const removeDocument = useRemoveDocument();
45
  const showDeleteConfirm = useShowDeleteConfirm();
 
46
  const runDocumentByIds = useRunDocument();
47
  const { knowledgeId } = useGetKnowledgeSearchParams();
48
  const changeStatus = useSetDocumentStatus();
 
75
  </Button>
76
  </div>
77
  ),
 
78
  },
79
  ];
80
  }, [showDocumentUploadModal, showCreateModal, t]);
web/src/pages/add-knowledge/components/knowledge-file/index.less CHANGED
@@ -1,6 +1,12 @@
1
  .datasetWrapper {
2
- padding: 30px;
3
- flex: 1;
 
 
 
 
 
 
4
  }
5
 
6
  .filter {
 
1
  .datasetWrapper {
2
+ padding: 30px 30px 0;
3
+ height: 100%;
4
+ }
5
+
6
+ .documentTable {
7
+ tbody {
8
+ // height: calc(100vh - 508px);
9
+ }
10
  }
11
 
12
  .filter {
web/src/pages/add-knowledge/components/knowledge-file/index.tsx CHANGED
@@ -179,7 +179,8 @@ const KnowledgeFile = () => {
179
  // loading={loading}
180
  pagination={pagination}
181
  rowSelection={rowSelection}
182
- scroll={{ scrollToFirstRowOnChange: true, x: 1300, y: 'fill' }}
 
183
  />
184
  <CreateFileModal
185
  visible={createVisible}
 
179
  // loading={loading}
180
  pagination={pagination}
181
  rowSelection={rowSelection}
182
+ className={styles.documentTable}
183
+ scroll={{ scrollToFirstRowOnChange: true, x: 1300 }}
184
  />
185
  <CreateFileModal
186
  visible={createVisible}
web/src/pages/file-manager/file-upload-modal/index.less DELETED
@@ -1,8 +0,0 @@
1
- .uploader {
2
- :global {
3
- .ant-upload-list {
4
- max-height: 40vh;
5
- overflow-y: auto;
6
- }
7
- }
8
- }
 
 
 
 
 
 
 
 
 
web/src/pages/file-manager/file-upload-modal/index.tsx DELETED
@@ -1,136 +0,0 @@
1
- import { useTranslate } from '@/hooks/commonHooks';
2
- import { IModalProps } from '@/interfaces/common';
3
- import { InboxOutlined } from '@ant-design/icons';
4
- import {
5
- Flex,
6
- Modal,
7
- Segmented,
8
- Tabs,
9
- TabsProps,
10
- Upload,
11
- UploadFile,
12
- UploadProps,
13
- } from 'antd';
14
- import { Dispatch, SetStateAction, useState } from 'react';
15
-
16
- import styles from './index.less';
17
-
18
- const { Dragger } = Upload;
19
-
20
- const FileUpload = ({
21
- directory,
22
- fileList,
23
- setFileList,
24
- }: {
25
- directory: boolean;
26
- fileList: UploadFile[];
27
- setFileList: Dispatch<SetStateAction<UploadFile[]>>;
28
- }) => {
29
- const { t } = useTranslate('fileManager');
30
- const props: UploadProps = {
31
- multiple: true,
32
- onRemove: (file) => {
33
- const index = fileList.indexOf(file);
34
- const newFileList = fileList.slice();
35
- newFileList.splice(index, 1);
36
- setFileList(newFileList);
37
- },
38
- beforeUpload: (file) => {
39
- setFileList((pre) => {
40
- return [...pre, file];
41
- });
42
-
43
- return false;
44
- },
45
- directory,
46
- fileList,
47
- };
48
-
49
- return (
50
- <Dragger {...props} className={styles.uploader}>
51
- <p className="ant-upload-drag-icon">
52
- <InboxOutlined />
53
- </p>
54
- <p className="ant-upload-text">{t('uploadTitle')}</p>
55
- <p className="ant-upload-hint">{t('uploadDescription')}</p>
56
- </Dragger>
57
- );
58
- };
59
-
60
- const FileUploadModal = ({
61
- visible,
62
- hideModal,
63
- loading,
64
- onOk: onFileUploadOk,
65
- }: IModalProps<UploadFile[]>) => {
66
- const { t } = useTranslate('fileManager');
67
- const [value, setValue] = useState<string | number>('local');
68
- const [fileList, setFileList] = useState<UploadFile[]>([]);
69
- const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
70
-
71
- const onOk = async () => {
72
- const ret = await onFileUploadOk?.([...fileList, ...directoryFileList]);
73
- console.info(ret);
74
- if (ret !== undefined && ret === 0) {
75
- setFileList([]);
76
- setDirectoryFileList([]);
77
- }
78
- return ret;
79
- };
80
-
81
- const items: TabsProps['items'] = [
82
- {
83
- key: '1',
84
- label: t('file'),
85
- children: (
86
- <FileUpload
87
- directory={false}
88
- fileList={fileList}
89
- setFileList={setFileList}
90
- ></FileUpload>
91
- ),
92
- },
93
- {
94
- key: '2',
95
- label: t('directory'),
96
- children: (
97
- <FileUpload
98
- directory
99
- fileList={directoryFileList}
100
- setFileList={setDirectoryFileList}
101
- ></FileUpload>
102
- ),
103
- },
104
- ];
105
-
106
- return (
107
- <>
108
- <Modal
109
- title={t('uploadFile')}
110
- open={visible}
111
- onOk={onOk}
112
- onCancel={hideModal}
113
- confirmLoading={loading}
114
- >
115
- <Flex gap={'large'} vertical>
116
- <Segmented
117
- options={[
118
- { label: t('local'), value: 'local' },
119
- { label: t('s3'), value: 's3' },
120
- ]}
121
- block
122
- value={value}
123
- onChange={setValue}
124
- />
125
- {value === 'local' ? (
126
- <Tabs defaultActiveKey="1" items={items} />
127
- ) : (
128
- t('comingSoon', { keyPrefix: 'common' })
129
- )}
130
- </Flex>
131
- </Modal>
132
- </>
133
- );
134
- };
135
-
136
- export default FileUploadModal;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
web/src/pages/file-manager/index.tsx CHANGED
@@ -16,13 +16,13 @@ import {
16
  useSelectFileListLoading,
17
  } from './hooks';
18
 
 
19
  import RenameModal from '@/components/rename-modal';
20
  import SvgIcon from '@/components/svg-icon';
21
  import { useTranslate } from '@/hooks/commonHooks';
22
  import { formatNumberWithThousandsSeparator } from '@/utils/commonUtil';
23
  import { getExtension } from '@/utils/documentUtils';
24
  import ConnectToKnowledgeModal from './connect-to-knowledge-modal';
25
- import FileUploadModal from './file-upload-modal';
26
  import FolderCreateModal from './folder-create-modal';
27
  import styles from './index.less';
28
 
 
16
  useSelectFileListLoading,
17
  } from './hooks';
18
 
19
+ import FileUploadModal from '@/components/file-upload-modal';
20
  import RenameModal from '@/components/rename-modal';
21
  import SvgIcon from '@/components/svg-icon';
22
  import { useTranslate } from '@/hooks/commonHooks';
23
  import { formatNumberWithThousandsSeparator } from '@/utils/commonUtil';
24
  import { getExtension } from '@/utils/documentUtils';
25
  import ConnectToKnowledgeModal from './connect-to-knowledge-modal';
 
26
  import FolderCreateModal from './folder-create-modal';
27
  import styles from './index.less';
28
 
web/src/pages/knowledge/hooks.ts ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useSelectKnowledgeList } from '@/hooks/knowledgeHook';
2
+ import { useState } from 'react';
3
+
4
+ export const useSearchKnowledge = () => {
5
+ const [searchString, setSearchString] = useState<string>('');
6
+
7
+ const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
8
+ setSearchString(e.target.value);
9
+ };
10
+ return {
11
+ searchString,
12
+ handleInputChange,
13
+ };
14
+ };
15
+
16
+ export const useSelectKnowledgeListByKeywords = (keywords: string) => {
17
+ const list = useSelectKnowledgeList();
18
+ return list.filter((x) => x.name.includes(keywords));
19
+ };
web/src/pages/knowledge/index.tsx CHANGED
@@ -1,16 +1,19 @@
1
  import ModalManager from '@/components/modal-manager';
2
  import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
3
  import { useSelectUserInfo } from '@/hooks/userSettingHook';
4
- import { PlusOutlined } from '@ant-design/icons';
5
- import { Button, Empty, Flex, Space, Spin } from 'antd';
6
  import KnowledgeCard from './knowledge-card';
7
  import KnowledgeCreatingModal from './knowledge-creating-modal';
8
 
9
  import { useTranslation } from 'react-i18next';
 
10
  import styles from './index.less';
11
 
12
- const Knowledge = () => {
13
- const { list, loading } = useFetchKnowledgeList();
 
 
14
  const userInfo = useSelectUserInfo();
15
  const { t } = useTranslation('translation', { keyPrefix: 'knowledgeList' });
16
 
@@ -24,9 +27,15 @@ const Knowledge = () => {
24
  <p className={styles.description}>{t('description')}</p>
25
  </div>
26
  <Space size={'large'}>
27
- {/* <Button icon={<FilterIcon />} className={styles.filterButton}>
28
- Filters
29
- </Button> */}
 
 
 
 
 
 
30
  <ModalManager>
31
  {({ visible, hideModal, showModal }) => (
32
  <>
@@ -70,4 +79,4 @@ const Knowledge = () => {
70
  );
71
  };
72
 
73
- export default Knowledge;
 
1
  import ModalManager from '@/components/modal-manager';
2
  import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
3
  import { useSelectUserInfo } from '@/hooks/userSettingHook';
4
+ import { PlusOutlined, SearchOutlined } from '@ant-design/icons';
5
+ import { Button, Empty, Flex, Input, Space, Spin } from 'antd';
6
  import KnowledgeCard from './knowledge-card';
7
  import KnowledgeCreatingModal from './knowledge-creating-modal';
8
 
9
  import { useTranslation } from 'react-i18next';
10
+ import { useSearchKnowledge, useSelectKnowledgeListByKeywords } from './hooks';
11
  import styles from './index.less';
12
 
13
+ const KnowledgeList = () => {
14
+ const { searchString, handleInputChange } = useSearchKnowledge();
15
+ const { loading } = useFetchKnowledgeList();
16
+ const list = useSelectKnowledgeListByKeywords(searchString);
17
  const userInfo = useSelectUserInfo();
18
  const { t } = useTranslation('translation', { keyPrefix: 'knowledgeList' });
19
 
 
27
  <p className={styles.description}>{t('description')}</p>
28
  </div>
29
  <Space size={'large'}>
30
+ <Input
31
+ placeholder={t('searchKnowledgePlaceholder')}
32
+ value={searchString}
33
+ style={{ width: 220 }}
34
+ allowClear
35
+ onChange={handleInputChange}
36
+ prefix={<SearchOutlined />}
37
+ />
38
+
39
  <ModalManager>
40
  {({ visible, hideModal, showModal }) => (
41
  <>
 
79
  );
80
  };
81
 
82
+ export default KnowledgeList;