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 +2 -0
- web/src/components/file-upload-modal/index.tsx +10 -4
- web/src/hooks/knowledgeHook.ts +7 -1
- web/src/less/mixins.less +14 -0
- web/src/locales/en.ts +3 -0
- web/src/locales/zh-traditional.ts +3 -0
- web/src/locales/zh.ts +3 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.less +4 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-card/index.tsx +12 -2
- web/src/pages/add-knowledge/components/knowledge-chunk/components/chunk-toolbar/index.tsx +18 -1
- web/src/pages/add-knowledge/components/knowledge-chunk/constant.ts +4 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/hooks.ts +12 -0
- web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx +15 -4
- web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx +0 -3
- web/src/pages/add-knowledge/components/knowledge-file/index.less +8 -2
- web/src/pages/add-knowledge/components/knowledge-file/index.tsx +2 -1
- web/src/pages/file-manager/file-upload-modal/index.less +0 -8
- web/src/pages/file-manager/file-upload-modal/index.tsx +0 -136
- web/src/pages/file-manager/index.tsx +1 -1
- web/src/pages/knowledge/hooks.ts +19 -0
- web/src/pages/knowledge/index.tsx +17 -8
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
|
| 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 |
-
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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 |
-
[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
|
|
|
| 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
|
| 13 |
-
const {
|
|
|
|
|
|
|
| 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 |
-
|
| 28 |
-
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
<ModalManager>
|
| 31 |
{({ visible, hideModal, showModal }) => (
|
| 32 |
<>
|
|
@@ -70,4 +79,4 @@ const Knowledge = () => {
|
|
| 70 |
);
|
| 71 |
};
|
| 72 |
|
| 73 |
-
export default
|
|
|
|
| 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;
|