balibabu
commited on
Commit
·
7c6cf75
1
Parent(s):
21cd893
feat: translate FileManager #345 (#558)
Browse files### What problem does this PR solve?
#345
feat: translate FileManager
feat: batch delete files from the file table in the knowledge base
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/.umirc.ts +1 -1
- web/src/hooks/documentHooks.ts +2 -2
- web/src/interfaces/common.ts +1 -1
- web/src/layouts/components/header/index.tsx +2 -2
- web/src/locales/en.ts +21 -0
- web/src/locales/zh-traditional.ts +21 -1
- web/src/locales/zh.ts +24 -3
- web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx +1 -3
- web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx +1 -1
- web/src/pages/file-manager/action-cell/index.tsx +1 -1
- web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx +6 -2
- web/src/pages/file-manager/file-toolbar.tsx +26 -19
- web/src/pages/file-manager/file-upload-modal/index.less +8 -0
- web/src/pages/file-manager/file-upload-modal/index.tsx +22 -16
- web/src/pages/file-manager/folder-create-modal/index.tsx +1 -1
- web/src/pages/file-manager/hooks.ts +21 -3
- web/src/pages/file-manager/index.less +7 -0
- web/src/pages/file-manager/index.tsx +31 -13
- web/src/pages/file-manager/model.ts +9 -0
- web/src/utils/commonUtil.ts +6 -0
web/.umirc.ts
CHANGED
@@ -27,7 +27,7 @@ export default defineConfig({
|
|
27 |
devtool: 'source-map',
|
28 |
proxy: {
|
29 |
'/v1': {
|
30 |
-
target: 'http://
|
31 |
changeOrigin: true,
|
32 |
// pathRewrite: { '^/v1': '/v1' },
|
33 |
},
|
|
|
27 |
devtool: 'source-map',
|
28 |
proxy: {
|
29 |
'/v1': {
|
30 |
+
target: 'http://123.60.95.134:9380/',
|
31 |
changeOrigin: true,
|
32 |
// pathRewrite: { '^/v1': '/v1' },
|
33 |
},
|
web/src/hooks/documentHooks.ts
CHANGED
@@ -160,12 +160,12 @@ export const useRemoveDocument = () => {
|
|
160 |
const { knowledgeId } = useGetKnowledgeSearchParams();
|
161 |
|
162 |
const removeDocument = useCallback(
|
163 |
-
(
|
164 |
try {
|
165 |
return dispatch<any>({
|
166 |
type: 'kFModel/document_rm',
|
167 |
payload: {
|
168 |
-
doc_id:
|
169 |
kb_id: knowledgeId,
|
170 |
},
|
171 |
});
|
|
|
160 |
const { knowledgeId } = useGetKnowledgeSearchParams();
|
161 |
|
162 |
const removeDocument = useCallback(
|
163 |
+
(documentIds: string[]) => {
|
164 |
try {
|
165 |
return dispatch<any>({
|
166 |
type: 'kFModel/document_rm',
|
167 |
payload: {
|
168 |
+
doc_id: documentIds,
|
169 |
kb_id: knowledgeId,
|
170 |
},
|
171 |
});
|
web/src/interfaces/common.ts
CHANGED
@@ -14,5 +14,5 @@ export interface IModalProps<T> {
|
|
14 |
hideModal(): void;
|
15 |
visible: boolean;
|
16 |
loading?: boolean;
|
17 |
-
onOk?(payload?: T): Promise<
|
18 |
}
|
|
|
14 |
hideModal(): void;
|
15 |
visible: boolean;
|
16 |
loading?: boolean;
|
17 |
+
onOk?(payload?: T): Promise<any> | void;
|
18 |
}
|
web/src/layouts/components/header/index.tsx
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import { ReactComponent as StarIon } from '@/assets/svg/chat-star.svg';
|
2 |
-
|
3 |
import { ReactComponent as KnowledgeBaseIcon } from '@/assets/svg/knowledge-base.svg';
|
4 |
import { ReactComponent as Logo } from '@/assets/svg/logo.svg';
|
5 |
import { useTranslate } from '@/hooks/commonHooks';
|
@@ -25,7 +25,7 @@ const RagHeader = () => {
|
|
25 |
() => [
|
26 |
{ path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon },
|
27 |
{ path: '/chat', name: t('chat'), icon: StarIon },
|
28 |
-
|
29 |
],
|
30 |
[t],
|
31 |
);
|
|
|
1 |
import { ReactComponent as StarIon } from '@/assets/svg/chat-star.svg';
|
2 |
+
import { ReactComponent as FileIcon } from '@/assets/svg/file-management.svg';
|
3 |
import { ReactComponent as KnowledgeBaseIcon } from '@/assets/svg/knowledge-base.svg';
|
4 |
import { ReactComponent as Logo } from '@/assets/svg/logo.svg';
|
5 |
import { useTranslate } from '@/hooks/commonHooks';
|
|
|
25 |
() => [
|
26 |
{ path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon },
|
27 |
{ path: '/chat', name: t('chat'), icon: StarIon },
|
28 |
+
{ path: '/file', name: t('fileManager'), icon: FileIcon },
|
29 |
],
|
30 |
[t],
|
31 |
);
|
web/src/locales/en.ts
CHANGED
@@ -22,6 +22,7 @@ export default {
|
|
22 |
languagePlaceholder: 'select your language',
|
23 |
copy: 'Copy',
|
24 |
copied: 'Copied',
|
|
|
25 |
},
|
26 |
login: {
|
27 |
login: 'Sign in',
|
@@ -52,6 +53,7 @@ export default {
|
|
52 |
home: 'Home',
|
53 |
setting: '用户设置',
|
54 |
logout: '登出',
|
|
|
55 |
},
|
56 |
knowledgeList: {
|
57 |
welcome: 'Welcome back',
|
@@ -459,6 +461,7 @@ export default {
|
|
459 |
renamed: 'Renamed',
|
460 |
operated: 'Operated',
|
461 |
updated: 'Updated',
|
|
|
462 |
200: 'The server successfully returns the requested data.',
|
463 |
201: 'Create or modify data successfully.',
|
464 |
202: 'A request has been queued in the background (asynchronous task).',
|
@@ -480,6 +483,24 @@ export default {
|
|
480 |
networkAnomaly: 'network anomaly',
|
481 |
hint: 'hint',
|
482 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
483 |
footer: {
|
484 |
profile: 'All rights reserved @ React',
|
485 |
},
|
|
|
22 |
languagePlaceholder: 'select your language',
|
23 |
copy: 'Copy',
|
24 |
copied: 'Copied',
|
25 |
+
comingSoon: 'Coming Soon',
|
26 |
},
|
27 |
login: {
|
28 |
login: 'Sign in',
|
|
|
53 |
home: 'Home',
|
54 |
setting: '用户设置',
|
55 |
logout: '登出',
|
56 |
+
fileManager: 'File Management',
|
57 |
},
|
58 |
knowledgeList: {
|
59 |
welcome: 'Welcome back',
|
|
|
461 |
renamed: 'Renamed',
|
462 |
operated: 'Operated',
|
463 |
updated: 'Updated',
|
464 |
+
uploaded: 'Uploaded',
|
465 |
200: 'The server successfully returns the requested data.',
|
466 |
201: 'Create or modify data successfully.',
|
467 |
202: 'A request has been queued in the background (asynchronous task).',
|
|
|
483 |
networkAnomaly: 'network anomaly',
|
484 |
hint: 'hint',
|
485 |
},
|
486 |
+
fileManager: {
|
487 |
+
name: 'Name',
|
488 |
+
uploadDate: 'Upload Date',
|
489 |
+
knowledgeBase: 'Knowledge Base',
|
490 |
+
size: 'Size',
|
491 |
+
action: 'Action',
|
492 |
+
addToKnowledge: 'Add to Knowledge Base',
|
493 |
+
pleaseSelect: 'Please select',
|
494 |
+
newFolder: 'New Folder',
|
495 |
+
file: 'File',
|
496 |
+
uploadFile: 'Upload File',
|
497 |
+
directory: 'Directory',
|
498 |
+
uploadTitle: 'Click or drag file to this area to upload',
|
499 |
+
uploadDescription:
|
500 |
+
'Support for a single or bulk upload. Strictly prohibited from uploading company data or other banned files.',
|
501 |
+
local: 'Local uploads',
|
502 |
+
s3: 'S3 uploads',
|
503 |
+
},
|
504 |
footer: {
|
505 |
profile: 'All rights reserved @ React',
|
506 |
},
|
web/src/locales/zh-traditional.ts
CHANGED
@@ -22,6 +22,7 @@ export default {
|
|
22 |
languagePlaceholder: '請選擇語言',
|
23 |
copy: '複製',
|
24 |
copied: '複製成功',
|
|
|
25 |
},
|
26 |
login: {
|
27 |
login: '登入',
|
@@ -52,6 +53,7 @@ export default {
|
|
52 |
home: '首頁',
|
53 |
setting: '用戶設置',
|
54 |
logout: '登出',
|
|
|
55 |
},
|
56 |
knowledgeList: {
|
57 |
welcome: '歡迎回來',
|
@@ -218,7 +220,7 @@ export default {
|
|
218 |
您只需與<i>'ragflow'</i>交談即可列出所有符合資格的候選人。
|
219 |
</p>
|
220 |
`,
|
221 |
-
table: `支持<p><b>excel</b>和<b>csv/txt</b>格式文件。</p><p>以下是一些提示: <ul> <li>对于Csv或Txt文件,列之间的分隔符为 <em><b>tab</b></em>。</li> <li>第一行必须是列标题。</li> <li
|
222 |
picture: `
|
223 |
<p>支持圖像文件。視頻即將推出。</p><p>
|
224 |
如果圖片中有文字,則應用 OCR 提取文字作為其文字描述。
|
@@ -424,6 +426,7 @@ export default {
|
|
424 |
renamed: '重命名成功',
|
425 |
operated: '操作成功',
|
426 |
updated: '更新成功',
|
|
|
427 |
200: '服務器成功返回請求的數據。',
|
428 |
201: '新建或修改數據成功。',
|
429 |
202: '一個請求已經進入後台排隊(異步任務)。',
|
@@ -444,6 +447,23 @@ export default {
|
|
444 |
networkAnomaly: '網絡異常',
|
445 |
hint: '提示',
|
446 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
447 |
footer: {
|
448 |
profile: '“保留所有權利 @ react”',
|
449 |
},
|
|
|
22 |
languagePlaceholder: '請選擇語言',
|
23 |
copy: '複製',
|
24 |
copied: '複製成功',
|
25 |
+
comingSoon: '即將推出',
|
26 |
},
|
27 |
login: {
|
28 |
login: '登入',
|
|
|
53 |
home: '首頁',
|
54 |
setting: '用戶設置',
|
55 |
logout: '登出',
|
56 |
+
fileManager: '文件管理',
|
57 |
},
|
58 |
knowledgeList: {
|
59 |
welcome: '歡迎回來',
|
|
|
220 |
您只需與<i>'ragflow'</i>交談即可列出所有符合資格的候選人。
|
221 |
</p>
|
222 |
`,
|
223 |
+
table: `支持<p><b>excel</b>和<b>csv/txt</b>格式文件。</p><p>以下是一些提示: <ul> <li>对于Csv或Txt文件,列之间的分隔符为 <em><b>tab</b></em>。</li> <li>第一行必须是列标题。</li> <li>列标题必须是有意义的术语,以便我们的大語言模型能够理解。列举一些同义词时最好使用斜杠<i>'/'</i>来分隔,甚至更好使用方括号枚举值,例如 <i>“性別/性別(男性,女性)”</i>.<p>以下是标题的一些示例:<ol> <li>供应商/供货商<b>'tab'</b>顏色(黃色、紅色、棕色)<b>'tab'</b>性別(男、女)<b>'tab'</B>尺码(m、l、xl、xxl)</li> <li>姓名/名字<b>'tab'</b>電話/手機/微信<b>'tab'</b>最高学历(高中,职高,硕士,本科,博士,初中,中技,中专,专科,专升本,mpa,mba,emba)</li> </ol> </p> </li> <li>表中的每一行都将被视为一个块。</li> </ul>`,
|
224 |
picture: `
|
225 |
<p>支持圖像文件。視頻即將推出。</p><p>
|
226 |
如果圖片中有文字,則應用 OCR 提取文字作為其文字描述。
|
|
|
426 |
renamed: '重命名成功',
|
427 |
operated: '操作成功',
|
428 |
updated: '更新成功',
|
429 |
+
uploaded: '上傳成功',
|
430 |
200: '服務器成功返回請求的數據。',
|
431 |
201: '新建或修改數據成功。',
|
432 |
202: '一個請求已經進入後台排隊(異步任務)。',
|
|
|
447 |
networkAnomaly: '網絡異常',
|
448 |
hint: '提示',
|
449 |
},
|
450 |
+
fileManager: {
|
451 |
+
name: '名稱',
|
452 |
+
uploadDate: '上傳日期',
|
453 |
+
knowledgeBase: '知識庫',
|
454 |
+
size: '大小',
|
455 |
+
action: '操作',
|
456 |
+
addToKnowledge: '添加到知識庫',
|
457 |
+
pleaseSelect: '請選擇',
|
458 |
+
newFolder: '新建文件夾',
|
459 |
+
uploadFile: '上傳文件',
|
460 |
+
uploadTitle: '點擊或拖拽文件至此區域即可上傳',
|
461 |
+
uploadDescription: '支持單次或批量上傳。嚴禁上傳公司數據或其他違禁文件。',
|
462 |
+
file: '文件',
|
463 |
+
directory: '文件夾',
|
464 |
+
local: '本地上傳',
|
465 |
+
s3: 'S3 上傳',
|
466 |
+
},
|
467 |
footer: {
|
468 |
profile: '“保留所有權利 @ react”',
|
469 |
},
|
web/src/locales/zh.ts
CHANGED
@@ -22,6 +22,7 @@ export default {
|
|
22 |
languagePlaceholder: '请选择语言',
|
23 |
copy: '复制',
|
24 |
copied: '复制成功',
|
|
|
25 |
},
|
26 |
login: {
|
27 |
login: '登录',
|
@@ -52,6 +53,7 @@ export default {
|
|
52 |
home: '首页',
|
53 |
setting: '用户设置',
|
54 |
logout: '登出',
|
|
|
55 |
},
|
56 |
knowledgeList: {
|
57 |
welcome: '欢迎回来',
|
@@ -225,7 +227,7 @@ export default {
|
|
225 |
<ul>
|
226 |
<li>对于 csv 或 txt 文件,列之间的分隔符为 <em><b>TAB</b></em>。</li>
|
227 |
<li>第一行必须是列标题。</li>
|
228 |
-
<li
|
229 |
列举一些同义词时最好使用斜杠<i>'/'</i>来分隔,甚至更好
|
230 |
使用方括号枚举值,例如 <i>'gender/sex(male,female)'</i>.<p>
|
231 |
以下是标题的一些示例:<ol>
|
@@ -298,7 +300,7 @@ export default {
|
|
298 |
systemTip:
|
299 |
'当LLM回答问题时,你需要LLM遵循的说明,比如角色设计、答案长度和答案语言等。',
|
300 |
topN: 'Top N',
|
301 |
-
topNTip:
|
302 |
variable: '变量',
|
303 |
variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。
|
304 |
这些变量用于填写提示中的“系统”部分,以便给LLM一个提示。
|
@@ -315,7 +317,7 @@ export default {
|
|
315 |
improvise: '即兴创作',
|
316 |
precise: '精确',
|
317 |
balance: '平衡',
|
318 |
-
freedomTip:
|
319 |
temperature: '温度',
|
320 |
temperatureMessage: '温度是必填项',
|
321 |
temperatureTip:
|
@@ -441,6 +443,7 @@ export default {
|
|
441 |
renamed: '重命名成功',
|
442 |
operated: '操作成功',
|
443 |
updated: '更新成功',
|
|
|
444 |
200: '服务器成功返回请求的数据。',
|
445 |
201: '新建或修改数据成功。',
|
446 |
202: '一个请求已经进入后台排队(异步任务)。',
|
@@ -461,6 +464,24 @@ export default {
|
|
461 |
networkAnomaly: '网络异常',
|
462 |
hint: '提示',
|
463 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
464 |
footer: {
|
465 |
profile: 'All rights reserved @ React',
|
466 |
},
|
|
|
22 |
languagePlaceholder: '请选择语言',
|
23 |
copy: '复制',
|
24 |
copied: '复制成功',
|
25 |
+
comingSoon: '即将推出',
|
26 |
},
|
27 |
login: {
|
28 |
login: '登录',
|
|
|
53 |
home: '首页',
|
54 |
setting: '用户设置',
|
55 |
logout: '登出',
|
56 |
+
fileManager: '文件管理',
|
57 |
},
|
58 |
knowledgeList: {
|
59 |
welcome: '欢迎回来',
|
|
|
227 |
<ul>
|
228 |
<li>对于 csv 或 txt 文件,列之间的分隔符为 <em><b>TAB</b></em>。</li>
|
229 |
<li>第一行必须是列标题。</li>
|
230 |
+
<li>列标题必须是有意义的术语,以便我们的大语言模型能够理解。
|
231 |
列举一些同义词时最好使用斜杠<i>'/'</i>来分隔,甚至更好
|
232 |
使用方括号枚举值,例如 <i>'gender/sex(male,female)'</i>.<p>
|
233 |
以下是标题的一些示例:<ol>
|
|
|
300 |
systemTip:
|
301 |
'当LLM回答问题时,你需要LLM遵循的说明,比如角色设计、答案长度和答案语言等。',
|
302 |
topN: 'Top N',
|
303 |
+
topNTip: `并非所有相似度得分高于“相似度阈值”的块都会被提供给大语言模型。 LLM 只能看到这些“Top N”块。`,
|
304 |
variable: '变量',
|
305 |
variableTip: `如果您使用对话 API,变量可能会帮助您使用不同的策略与客户聊天。
|
306 |
这些变量用于填写提示中的“系统”部分,以便给LLM一个提示。
|
|
|
317 |
improvise: '即兴创作',
|
318 |
precise: '精确',
|
319 |
balance: '平衡',
|
320 |
+
freedomTip: `“精确”意味着大语言模型会保守并谨慎地回答你的问题。 “即兴发挥”意味着你希望大语言模型能够自由地畅所欲言。 “平衡”是谨慎与自由之间的平衡。`,
|
321 |
temperature: '温度',
|
322 |
temperatureMessage: '温度是必填项',
|
323 |
temperatureTip:
|
|
|
443 |
renamed: '重命名成功',
|
444 |
operated: '操作成功',
|
445 |
updated: '更新成功',
|
446 |
+
uploaded: '上传成功',
|
447 |
200: '服务器成功返回请求的数据。',
|
448 |
201: '新建或修改数据成功。',
|
449 |
202: '一个请求已经进入后台排队(异步任务)。',
|
|
|
464 |
networkAnomaly: '网络异常',
|
465 |
hint: '提示',
|
466 |
},
|
467 |
+
fileManager: {
|
468 |
+
name: '名称',
|
469 |
+
uploadDate: '上传日期',
|
470 |
+
knowledgeBase: '知识库',
|
471 |
+
size: '大小',
|
472 |
+
action: '操作',
|
473 |
+
addToKnowledge: '添加到知识库',
|
474 |
+
pleaseSelect: '请选择',
|
475 |
+
newFolder: '新建文件夹',
|
476 |
+
uploadFile: '上传文件',
|
477 |
+
uploadTitle: '点击或拖拽文件至此区域即可上传',
|
478 |
+
uploadDescription:
|
479 |
+
'支持单次或批量上传。 严禁上传公司数据或其他违禁文件。',
|
480 |
+
file: '文件',
|
481 |
+
directory: '文件夹',
|
482 |
+
local: '本地上传',
|
483 |
+
s3: 'S3 上传',
|
484 |
+
},
|
485 |
footer: {
|
486 |
profile: 'All rights reserved @ React',
|
487 |
},
|
web/src/pages/add-knowledge/components/knowledge-file/document-toolbar.tsx
CHANGED
@@ -80,9 +80,7 @@ const DocumentToolbar = ({ selectedRowKeys, showCreateModal }: IProps) => {
|
|
80 |
const handleDelete = useCallback(() => {
|
81 |
showDeleteConfirm({
|
82 |
onOk: () => {
|
83 |
-
selectedRowKeys
|
84 |
-
removeDocument(id);
|
85 |
-
});
|
86 |
},
|
87 |
});
|
88 |
}, [removeDocument, showDeleteConfirm, selectedRowKeys]);
|
|
|
80 |
const handleDelete = useCallback(() => {
|
81 |
showDeleteConfirm({
|
82 |
onOk: () => {
|
83 |
+
removeDocument(selectedRowKeys);
|
|
|
|
|
84 |
},
|
85 |
});
|
86 |
}, [removeDocument, showDeleteConfirm, selectedRowKeys]);
|
web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx
CHANGED
@@ -35,7 +35,7 @@ const ParsingActionCell = ({
|
|
35 |
|
36 |
const onRmDocument = () => {
|
37 |
if (!isRunning) {
|
38 |
-
showDeleteConfirm({ onOk: () => removeDocument(documentId) });
|
39 |
}
|
40 |
};
|
41 |
|
|
|
35 |
|
36 |
const onRmDocument = () => {
|
37 |
if (!isRunning) {
|
38 |
+
showDeleteConfirm({ onOk: () => removeDocument([documentId]) });
|
39 |
}
|
40 |
};
|
41 |
|
web/src/pages/file-manager/action-cell/index.tsx
CHANGED
@@ -38,7 +38,7 @@ const ActionCell = ({
|
|
38 |
|
39 |
const onDownloadDocument = () => {
|
40 |
downloadFile({
|
41 |
-
url: `${api_host}/
|
42 |
filename: record.name,
|
43 |
});
|
44 |
};
|
|
|
38 |
|
39 |
const onDownloadDocument = () => {
|
40 |
downloadFile({
|
41 |
+
url: `${api_host}/file/get/${documentId}`,
|
42 |
filename: record.name,
|
43 |
});
|
44 |
};
|
web/src/pages/file-manager/connect-to-knowledge-modal/index.tsx
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
2 |
import { IModalProps } from '@/interfaces/common';
|
3 |
import { Form, Modal, Select, SelectProps } from 'antd';
|
@@ -8,9 +9,11 @@ const ConnectToKnowledgeModal = ({
|
|
8 |
hideModal,
|
9 |
onOk,
|
10 |
initialValue,
|
|
|
11 |
}: IModalProps<string[]> & { initialValue: string[] }) => {
|
12 |
const [form] = Form.useForm();
|
13 |
const { list, fetchList } = useFetchKnowledgeList();
|
|
|
14 |
|
15 |
const options: SelectProps['options'] = list?.map((item) => ({
|
16 |
label: item.name,
|
@@ -32,10 +35,11 @@ const ConnectToKnowledgeModal = ({
|
|
32 |
|
33 |
return (
|
34 |
<Modal
|
35 |
-
title=
|
36 |
open={visible}
|
37 |
onOk={handleOk}
|
38 |
onCancel={hideModal}
|
|
|
39 |
>
|
40 |
<Form form={form}>
|
41 |
<Form.Item name="knowledgeIds" noStyle>
|
@@ -43,7 +47,7 @@ const ConnectToKnowledgeModal = ({
|
|
43 |
mode="multiple"
|
44 |
allowClear
|
45 |
style={{ width: '100%' }}
|
46 |
-
placeholder=
|
47 |
options={options}
|
48 |
/>
|
49 |
</Form.Item>
|
|
|
1 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
2 |
import { useFetchKnowledgeList } from '@/hooks/knowledgeHook';
|
3 |
import { IModalProps } from '@/interfaces/common';
|
4 |
import { Form, Modal, Select, SelectProps } from 'antd';
|
|
|
9 |
hideModal,
|
10 |
onOk,
|
11 |
initialValue,
|
12 |
+
loading,
|
13 |
}: IModalProps<string[]> & { initialValue: string[] }) => {
|
14 |
const [form] = Form.useForm();
|
15 |
const { list, fetchList } = useFetchKnowledgeList();
|
16 |
+
const { t } = useTranslate('fileManager');
|
17 |
|
18 |
const options: SelectProps['options'] = list?.map((item) => ({
|
19 |
label: item.name,
|
|
|
35 |
|
36 |
return (
|
37 |
<Modal
|
38 |
+
title={t('addToKnowledge')}
|
39 |
open={visible}
|
40 |
onOk={handleOk}
|
41 |
onCancel={hideModal}
|
42 |
+
confirmLoading={loading}
|
43 |
>
|
44 |
<Form form={form}>
|
45 |
<Form.Item name="knowledgeIds" noStyle>
|
|
|
47 |
mode="multiple"
|
48 |
allowClear
|
49 |
style={{ width: '100%' }}
|
50 |
+
placeholder={t('pleaseSelect')}
|
51 |
options={options}
|
52 |
/>
|
53 |
</Form.Item>
|
web/src/pages/file-manager/file-toolbar.tsx
CHANGED
@@ -20,12 +20,12 @@ import {
|
|
20 |
import { useMemo } from 'react';
|
21 |
import {
|
22 |
useFetchDocumentListOnMount,
|
|
|
23 |
useHandleDeleteFile,
|
24 |
useHandleSearchChange,
|
25 |
useSelectBreadcrumbItems,
|
26 |
} from './hooks';
|
27 |
|
28 |
-
import { Link } from 'umi';
|
29 |
import styles from './index.less';
|
30 |
|
31 |
interface IProps {
|
@@ -35,20 +35,6 @@ interface IProps {
|
|
35 |
setSelectedRowKeys: (keys: string[]) => void;
|
36 |
}
|
37 |
|
38 |
-
const itemRender: BreadcrumbProps['itemRender'] = (
|
39 |
-
currentRoute,
|
40 |
-
params,
|
41 |
-
items,
|
42 |
-
) => {
|
43 |
-
const isLast = currentRoute?.path === items[items.length - 1]?.path;
|
44 |
-
|
45 |
-
return isLast ? (
|
46 |
-
<span>{currentRoute.title}</span>
|
47 |
-
) : (
|
48 |
-
<Link to={`${currentRoute.path}`}>{currentRoute.title}</Link>
|
49 |
-
);
|
50 |
-
};
|
51 |
-
|
52 |
const FileToolbar = ({
|
53 |
selectedRowKeys,
|
54 |
showFolderCreateModal,
|
@@ -59,6 +45,26 @@ const FileToolbar = ({
|
|
59 |
useFetchDocumentListOnMount();
|
60 |
const { handleInputChange, searchString } = useHandleSearchChange();
|
61 |
const breadcrumbItems = useSelectBreadcrumbItems();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
const actionItems: MenuProps['items'] = useMemo(() => {
|
64 |
return [
|
@@ -70,7 +76,7 @@ const FileToolbar = ({
|
|
70 |
<Button type="link">
|
71 |
<Space>
|
72 |
<FileTextOutlined />
|
73 |
-
{t('
|
74 |
</Space>
|
75 |
</Button>
|
76 |
</div>
|
@@ -83,12 +89,13 @@ const FileToolbar = ({
|
|
83 |
label: (
|
84 |
<div>
|
85 |
<Button type="link">
|
86 |
-
<
|
87 |
-
|
|
|
|
|
88 |
</Button>
|
89 |
</div>
|
90 |
),
|
91 |
-
// disabled: true,
|
92 |
},
|
93 |
];
|
94 |
}, [t, showFolderCreateModal, showFileUploadModal]);
|
|
|
20 |
import { useMemo } from 'react';
|
21 |
import {
|
22 |
useFetchDocumentListOnMount,
|
23 |
+
useHandleBreadcrumbClick,
|
24 |
useHandleDeleteFile,
|
25 |
useHandleSearchChange,
|
26 |
useSelectBreadcrumbItems,
|
27 |
} from './hooks';
|
28 |
|
|
|
29 |
import styles from './index.less';
|
30 |
|
31 |
interface IProps {
|
|
|
35 |
setSelectedRowKeys: (keys: string[]) => void;
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
const FileToolbar = ({
|
39 |
selectedRowKeys,
|
40 |
showFolderCreateModal,
|
|
|
45 |
useFetchDocumentListOnMount();
|
46 |
const { handleInputChange, searchString } = useHandleSearchChange();
|
47 |
const breadcrumbItems = useSelectBreadcrumbItems();
|
48 |
+
const { handleBreadcrumbClick } = useHandleBreadcrumbClick();
|
49 |
+
|
50 |
+
const itemRender: BreadcrumbProps['itemRender'] = (
|
51 |
+
currentRoute,
|
52 |
+
params,
|
53 |
+
items,
|
54 |
+
) => {
|
55 |
+
const isLast = currentRoute?.path === items[items.length - 1]?.path;
|
56 |
+
|
57 |
+
return isLast ? (
|
58 |
+
<span>{currentRoute.title}</span>
|
59 |
+
) : (
|
60 |
+
<span
|
61 |
+
className={styles.breadcrumbItemButton}
|
62 |
+
onClick={() => handleBreadcrumbClick(currentRoute.path)}
|
63 |
+
>
|
64 |
+
{currentRoute.title}
|
65 |
+
</span>
|
66 |
+
);
|
67 |
+
};
|
68 |
|
69 |
const actionItems: MenuProps['items'] = useMemo(() => {
|
70 |
return [
|
|
|
76 |
<Button type="link">
|
77 |
<Space>
|
78 |
<FileTextOutlined />
|
79 |
+
{t('uploadFile', { keyPrefix: 'fileManager' })}
|
80 |
</Space>
|
81 |
</Button>
|
82 |
</div>
|
|
|
89 |
label: (
|
90 |
<div>
|
91 |
<Button type="link">
|
92 |
+
<Space>
|
93 |
+
<FolderOpenOutlined />
|
94 |
+
{t('newFolder', { keyPrefix: 'fileManager' })}
|
95 |
+
</Space>
|
96 |
</Button>
|
97 |
</div>
|
98 |
),
|
|
|
99 |
},
|
100 |
];
|
101 |
}, [t, showFolderCreateModal, showFileUploadModal]);
|
web/src/pages/file-manager/file-upload-modal/index.less
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import { IModalProps } from '@/interfaces/common';
|
2 |
import { InboxOutlined } from '@ant-design/icons';
|
3 |
import {
|
@@ -12,6 +13,8 @@ import {
|
|
12 |
} from 'antd';
|
13 |
import { Dispatch, SetStateAction, useState } from 'react';
|
14 |
|
|
|
|
|
15 |
const { Dragger } = Upload;
|
16 |
|
17 |
const FileUpload = ({
|
@@ -23,6 +26,7 @@ const FileUpload = ({
|
|
23 |
fileList: UploadFile[];
|
24 |
setFileList: Dispatch<SetStateAction<UploadFile[]>>;
|
25 |
}) => {
|
|
|
26 |
const props: UploadProps = {
|
27 |
multiple: true,
|
28 |
onRemove: (file) => {
|
@@ -43,17 +47,12 @@ const FileUpload = ({
|
|
43 |
};
|
44 |
|
45 |
return (
|
46 |
-
<Dragger {...props}>
|
47 |
<p className="ant-upload-drag-icon">
|
48 |
<InboxOutlined />
|
49 |
</p>
|
50 |
-
<p className="ant-upload-text">
|
51 |
-
|
52 |
-
</p>
|
53 |
-
<p className="ant-upload-hint">
|
54 |
-
Support for a single or bulk upload. Strictly prohibited from uploading
|
55 |
-
company data or other banned files.
|
56 |
-
</p>
|
57 |
</Dragger>
|
58 |
);
|
59 |
};
|
@@ -64,18 +63,25 @@ const FileUploadModal = ({
|
|
64 |
loading,
|
65 |
onOk: onFileUploadOk,
|
66 |
}: IModalProps<UploadFile[]>) => {
|
|
|
67 |
const [value, setValue] = useState<string | number>('local');
|
68 |
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
69 |
const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
|
70 |
|
71 |
-
const onOk = () => {
|
72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
};
|
74 |
|
75 |
const items: TabsProps['items'] = [
|
76 |
{
|
77 |
key: '1',
|
78 |
-
label: '
|
79 |
children: (
|
80 |
<FileUpload
|
81 |
directory={false}
|
@@ -86,7 +92,7 @@ const FileUploadModal = ({
|
|
86 |
},
|
87 |
{
|
88 |
key: '2',
|
89 |
-
label: '
|
90 |
children: (
|
91 |
<FileUpload
|
92 |
directory
|
@@ -100,7 +106,7 @@ const FileUploadModal = ({
|
|
100 |
return (
|
101 |
<>
|
102 |
<Modal
|
103 |
-
title=
|
104 |
open={visible}
|
105 |
onOk={onOk}
|
106 |
onCancel={hideModal}
|
@@ -109,8 +115,8 @@ const FileUploadModal = ({
|
|
109 |
<Flex gap={'large'} vertical>
|
110 |
<Segmented
|
111 |
options={[
|
112 |
-
{ label: '
|
113 |
-
{ label: '
|
114 |
]}
|
115 |
block
|
116 |
value={value}
|
@@ -119,7 +125,7 @@ const FileUploadModal = ({
|
|
119 |
{value === 'local' ? (
|
120 |
<Tabs defaultActiveKey="1" items={items} />
|
121 |
) : (
|
122 |
-
'
|
123 |
)}
|
124 |
</Flex>
|
125 |
</Modal>
|
|
|
1 |
+
import { useTranslate } from '@/hooks/commonHooks';
|
2 |
import { IModalProps } from '@/interfaces/common';
|
3 |
import { InboxOutlined } from '@ant-design/icons';
|
4 |
import {
|
|
|
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 = ({
|
|
|
26 |
fileList: UploadFile[];
|
27 |
setFileList: Dispatch<SetStateAction<UploadFile[]>>;
|
28 |
}) => {
|
29 |
+
const { t } = useTranslate('fileManager');
|
30 |
const props: UploadProps = {
|
31 |
multiple: true,
|
32 |
onRemove: (file) => {
|
|
|
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 |
};
|
|
|
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}
|
|
|
92 |
},
|
93 |
{
|
94 |
key: '2',
|
95 |
+
label: t('directory'),
|
96 |
children: (
|
97 |
<FileUpload
|
98 |
directory
|
|
|
106 |
return (
|
107 |
<>
|
108 |
<Modal
|
109 |
+
title={t('uploadFile')}
|
110 |
open={visible}
|
111 |
onOk={onOk}
|
112 |
onCancel={hideModal}
|
|
|
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}
|
|
|
125 |
{value === 'local' ? (
|
126 |
<Tabs defaultActiveKey="1" items={items} />
|
127 |
) : (
|
128 |
+
t('comingSoon', { keyPrefix: 'common' })
|
129 |
)}
|
130 |
</Flex>
|
131 |
</Modal>
|
web/src/pages/file-manager/folder-create-modal/index.tsx
CHANGED
@@ -35,7 +35,7 @@ const FolderCreateModal = ({ visible, hideModal, loading, onOk }: IProps) => {
|
|
35 |
|
36 |
return (
|
37 |
<Modal
|
38 |
-
title={'
|
39 |
open={visible}
|
40 |
onOk={handleOk}
|
41 |
onCancel={handleCancel}
|
|
|
35 |
|
36 |
return (
|
37 |
<Modal
|
38 |
+
title={t('newFolder', { keyPrefix: 'fileManager' })}
|
39 |
open={visible}
|
40 |
onOk={handleOk}
|
41 |
onCancel={handleCancel}
|
web/src/pages/file-manager/hooks.ts
CHANGED
@@ -244,14 +244,14 @@ export const useHandleUploadFile = () => {
|
|
244 |
const id = useGetFolderId();
|
245 |
|
246 |
const onFileUploadOk = useCallback(
|
247 |
-
async (fileList: UploadFile[]) => {
|
248 |
-
console.info('fileList', fileList);
|
249 |
if (fileList.length > 0) {
|
250 |
-
const ret = await uploadFile(fileList, id);
|
251 |
console.info(ret);
|
252 |
if (ret === 0) {
|
253 |
hideFileUploadModal();
|
254 |
}
|
|
|
255 |
}
|
256 |
},
|
257 |
[uploadFile, hideFileUploadModal, id],
|
@@ -295,6 +295,7 @@ export const useHandleConnectToKnowledge = () => {
|
|
295 |
if (ret === 0) {
|
296 |
hideConnectToKnowledgeModal();
|
297 |
}
|
|
|
298 |
},
|
299 |
[connectToKnowledge, hideConnectToKnowledgeModal, id, record.id],
|
300 |
);
|
@@ -320,3 +321,20 @@ export const useHandleConnectToKnowledge = () => {
|
|
320 |
showConnectToKnowledgeModal: handleShowConnectToKnowledgeModal,
|
321 |
};
|
322 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
const id = useGetFolderId();
|
245 |
|
246 |
const onFileUploadOk = useCallback(
|
247 |
+
async (fileList: UploadFile[]): Promise<number | undefined> => {
|
|
|
248 |
if (fileList.length > 0) {
|
249 |
+
const ret: number = await uploadFile(fileList, id);
|
250 |
console.info(ret);
|
251 |
if (ret === 0) {
|
252 |
hideFileUploadModal();
|
253 |
}
|
254 |
+
return ret;
|
255 |
}
|
256 |
},
|
257 |
[uploadFile, hideFileUploadModal, id],
|
|
|
295 |
if (ret === 0) {
|
296 |
hideConnectToKnowledgeModal();
|
297 |
}
|
298 |
+
return ret;
|
299 |
},
|
300 |
[connectToKnowledge, hideConnectToKnowledgeModal, id, record.id],
|
301 |
);
|
|
|
321 |
showConnectToKnowledgeModal: handleShowConnectToKnowledgeModal,
|
322 |
};
|
323 |
};
|
324 |
+
|
325 |
+
export const useHandleBreadcrumbClick = () => {
|
326 |
+
const navigate = useNavigate();
|
327 |
+
const setPagination = useSetPagination('fileManager');
|
328 |
+
|
329 |
+
const handleBreadcrumbClick = useCallback(
|
330 |
+
(path?: string) => {
|
331 |
+
if (path) {
|
332 |
+
setPagination();
|
333 |
+
navigate(path);
|
334 |
+
}
|
335 |
+
},
|
336 |
+
[setPagination, navigate],
|
337 |
+
);
|
338 |
+
|
339 |
+
return { handleBreadcrumbClick };
|
340 |
+
};
|
web/src/pages/file-manager/index.less
CHANGED
@@ -20,3 +20,10 @@
|
|
20 |
.linkButton {
|
21 |
padding: 0;
|
22 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
.linkButton {
|
21 |
padding: 0;
|
22 |
}
|
23 |
+
|
24 |
+
.breadcrumbItemButton {
|
25 |
+
cursor: pointer;
|
26 |
+
color: #1677ff;
|
27 |
+
padding: 0;
|
28 |
+
height: auto;
|
29 |
+
}
|
web/src/pages/file-manager/index.tsx
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import { useSelectFileList } from '@/hooks/fileManagerHooks';
|
2 |
import { IFile } from '@/interfaces/database/file-manager';
|
3 |
import { formatDate } from '@/utils/date';
|
4 |
-
import { Button, Flex, Table } from 'antd';
|
5 |
import { ColumnsType } from 'antd/es/table';
|
6 |
import ActionCell from './action-cell';
|
7 |
import FileToolbar from './file-toolbar';
|
@@ -18,6 +18,8 @@ import {
|
|
18 |
|
19 |
import RenameModal from '@/components/rename-modal';
|
20 |
import SvgIcon from '@/components/svg-icon';
|
|
|
|
|
21 |
import { getExtension } from '@/utils/documentUtils';
|
22 |
import ConnectToKnowledgeModal from './connect-to-knowledge-modal';
|
23 |
import FileUploadModal from './file-upload-modal';
|
@@ -25,6 +27,7 @@ import FolderCreateModal from './folder-create-modal';
|
|
25 |
import styles from './index.less';
|
26 |
|
27 |
const FileManager = () => {
|
|
|
28 |
const fileList = useSelectFileList();
|
29 |
const { rowSelection, setSelectedRowKeys } = useGetRowSelection();
|
30 |
const loading = useSelectFileListLoading();
|
@@ -57,12 +60,13 @@ const FileManager = () => {
|
|
57 |
showConnectToKnowledgeModal,
|
58 |
onConnectToKnowledgeOk,
|
59 |
initialValue,
|
|
|
60 |
} = useHandleConnectToKnowledge();
|
61 |
const { pagination } = useGetFilesPagination();
|
62 |
|
63 |
const columns: ColumnsType<IFile> = [
|
64 |
{
|
65 |
-
title: '
|
66 |
dataIndex: 'name',
|
67 |
key: 'name',
|
68 |
render(value, record) {
|
@@ -88,7 +92,7 @@ const FileManager = () => {
|
|
88 |
},
|
89 |
},
|
90 |
{
|
91 |
-
title: '
|
92 |
dataIndex: 'create_date',
|
93 |
key: 'create_date',
|
94 |
render(text) {
|
@@ -96,22 +100,35 @@ const FileManager = () => {
|
|
96 |
},
|
97 |
},
|
98 |
{
|
99 |
-
title: '
|
100 |
-
dataIndex: '
|
101 |
-
key: '
|
102 |
render(value) {
|
103 |
-
return
|
104 |
-
|
105 |
-
|
106 |
},
|
107 |
},
|
108 |
{
|
109 |
-
title: '
|
110 |
-
dataIndex: '
|
111 |
-
key: '
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
},
|
113 |
{
|
114 |
-
title: '
|
115 |
dataIndex: 'action',
|
116 |
key: 'action',
|
117 |
render: (text, record) => (
|
@@ -168,6 +185,7 @@ const FileManager = () => {
|
|
168 |
visible={connectToKnowledgeVisible}
|
169 |
hideModal={hideConnectToKnowledgeModal}
|
170 |
onOk={onConnectToKnowledgeOk}
|
|
|
171 |
></ConnectToKnowledgeModal>
|
172 |
</section>
|
173 |
);
|
|
|
1 |
import { useSelectFileList } from '@/hooks/fileManagerHooks';
|
2 |
import { IFile } from '@/interfaces/database/file-manager';
|
3 |
import { formatDate } from '@/utils/date';
|
4 |
+
import { Button, Flex, Space, Table, Tag } from 'antd';
|
5 |
import { ColumnsType } from 'antd/es/table';
|
6 |
import ActionCell from './action-cell';
|
7 |
import FileToolbar from './file-toolbar';
|
|
|
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';
|
|
|
27 |
import styles from './index.less';
|
28 |
|
29 |
const FileManager = () => {
|
30 |
+
const { t } = useTranslate('fileManager');
|
31 |
const fileList = useSelectFileList();
|
32 |
const { rowSelection, setSelectedRowKeys } = useGetRowSelection();
|
33 |
const loading = useSelectFileListLoading();
|
|
|
60 |
showConnectToKnowledgeModal,
|
61 |
onConnectToKnowledgeOk,
|
62 |
initialValue,
|
63 |
+
connectToKnowledgeLoading,
|
64 |
} = useHandleConnectToKnowledge();
|
65 |
const { pagination } = useGetFilesPagination();
|
66 |
|
67 |
const columns: ColumnsType<IFile> = [
|
68 |
{
|
69 |
+
title: t('name'),
|
70 |
dataIndex: 'name',
|
71 |
key: 'name',
|
72 |
render(value, record) {
|
|
|
92 |
},
|
93 |
},
|
94 |
{
|
95 |
+
title: t('uploadDate'),
|
96 |
dataIndex: 'create_date',
|
97 |
key: 'create_date',
|
98 |
render(text) {
|
|
|
100 |
},
|
101 |
},
|
102 |
{
|
103 |
+
title: t('size'),
|
104 |
+
dataIndex: 'size',
|
105 |
+
key: 'size',
|
106 |
render(value) {
|
107 |
+
return (
|
108 |
+
formatNumberWithThousandsSeparator((value / 1024).toFixed(2)) + ' KB'
|
109 |
+
);
|
110 |
},
|
111 |
},
|
112 |
{
|
113 |
+
title: t('knowledgeBase'),
|
114 |
+
dataIndex: 'kbs_info',
|
115 |
+
key: 'kbs_info',
|
116 |
+
render(value) {
|
117 |
+
return Array.isArray(value) ? (
|
118 |
+
<Space wrap>
|
119 |
+
{value?.map((x) => (
|
120 |
+
<Tag color="blue" key={x.kb_id}>
|
121 |
+
{x.kb_name}
|
122 |
+
</Tag>
|
123 |
+
))}
|
124 |
+
</Space>
|
125 |
+
) : (
|
126 |
+
''
|
127 |
+
);
|
128 |
+
},
|
129 |
},
|
130 |
{
|
131 |
+
title: t('action'),
|
132 |
dataIndex: 'action',
|
133 |
key: 'action',
|
134 |
render: (text, record) => (
|
|
|
185 |
visible={connectToKnowledgeVisible}
|
186 |
hideModal={hideConnectToKnowledgeModal}
|
187 |
onOk={onConnectToKnowledgeOk}
|
188 |
+
loading={connectToKnowledgeLoading}
|
189 |
></ConnectToKnowledgeModal>
|
190 |
</section>
|
191 |
);
|
web/src/pages/file-manager/model.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1 |
import { paginationModel } from '@/base';
|
2 |
import { BaseState } from '@/interfaces/common';
|
3 |
import { IFile, IFolder } from '@/interfaces/database/file-manager';
|
|
|
4 |
import fileManagerService from '@/services/fileManagerService';
|
|
|
5 |
import omit from 'lodash/omit';
|
6 |
import { DvaModel } from 'umi';
|
7 |
|
@@ -33,6 +35,7 @@ const model: DvaModel<FileManagerModelState> = {
|
|
33 |
});
|
34 |
const { retcode } = data;
|
35 |
if (retcode === 0) {
|
|
|
36 |
yield put({
|
37 |
type: 'listFile',
|
38 |
payload: { parentId: payload.parentId },
|
@@ -69,6 +72,7 @@ const model: DvaModel<FileManagerModelState> = {
|
|
69 |
omit(payload, ['parentId']),
|
70 |
);
|
71 |
if (data.retcode === 0) {
|
|
|
72 |
yield put({
|
73 |
type: 'listFile',
|
74 |
payload: { parentId: payload.parentId },
|
@@ -89,6 +93,8 @@ const model: DvaModel<FileManagerModelState> = {
|
|
89 |
});
|
90 |
const { data } = yield call(fileManagerService.uploadFile, formData);
|
91 |
if (data.retcode === 0) {
|
|
|
|
|
92 |
yield put({
|
93 |
type: 'listFile',
|
94 |
payload: { parentId: payload.parentId },
|
@@ -99,6 +105,8 @@ const model: DvaModel<FileManagerModelState> = {
|
|
99 |
*createFolder({ payload = {} }, { call, put }) {
|
100 |
const { data } = yield call(fileManagerService.createFolder, payload);
|
101 |
if (data.retcode === 0) {
|
|
|
|
|
102 |
yield put({
|
103 |
type: 'listFile',
|
104 |
payload: { parentId: payload.parentId },
|
@@ -125,6 +133,7 @@ const model: DvaModel<FileManagerModelState> = {
|
|
125 |
omit(payload, 'parentId'),
|
126 |
);
|
127 |
if (data.retcode === 0) {
|
|
|
128 |
yield put({
|
129 |
type: 'listFile',
|
130 |
payload: { parentId: payload.parentId },
|
|
|
1 |
import { paginationModel } from '@/base';
|
2 |
import { BaseState } from '@/interfaces/common';
|
3 |
import { IFile, IFolder } from '@/interfaces/database/file-manager';
|
4 |
+
import i18n from '@/locales/config';
|
5 |
import fileManagerService from '@/services/fileManagerService';
|
6 |
+
import { message } from 'antd';
|
7 |
import omit from 'lodash/omit';
|
8 |
import { DvaModel } from 'umi';
|
9 |
|
|
|
35 |
});
|
36 |
const { retcode } = data;
|
37 |
if (retcode === 0) {
|
38 |
+
message.success(i18n.t('message.deleted'));
|
39 |
yield put({
|
40 |
type: 'listFile',
|
41 |
payload: { parentId: payload.parentId },
|
|
|
72 |
omit(payload, ['parentId']),
|
73 |
);
|
74 |
if (data.retcode === 0) {
|
75 |
+
message.success(i18n.t('message.renamed'));
|
76 |
yield put({
|
77 |
type: 'listFile',
|
78 |
payload: { parentId: payload.parentId },
|
|
|
93 |
});
|
94 |
const { data } = yield call(fileManagerService.uploadFile, formData);
|
95 |
if (data.retcode === 0) {
|
96 |
+
message.success(i18n.t('message.uploaded'));
|
97 |
+
|
98 |
yield put({
|
99 |
type: 'listFile',
|
100 |
payload: { parentId: payload.parentId },
|
|
|
105 |
*createFolder({ payload = {} }, { call, put }) {
|
106 |
const { data } = yield call(fileManagerService.createFolder, payload);
|
107 |
if (data.retcode === 0) {
|
108 |
+
message.success(i18n.t('message.created'));
|
109 |
+
|
110 |
yield put({
|
111 |
type: 'listFile',
|
112 |
payload: { parentId: payload.parentId },
|
|
|
133 |
omit(payload, 'parentId'),
|
134 |
);
|
135 |
if (data.retcode === 0) {
|
136 |
+
message.success(i18n.t('message.operated'));
|
137 |
yield put({
|
138 |
type: 'listFile',
|
139 |
payload: { parentId: payload.parentId },
|
web/src/utils/commonUtil.ts
CHANGED
@@ -27,3 +27,9 @@ export const getSearchValue = (key: string) => {
|
|
27 |
const params = new URL(document.location as any).searchParams;
|
28 |
return params.get(key);
|
29 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
const params = new URL(document.location as any).searchParams;
|
28 |
return params.get(key);
|
29 |
};
|
30 |
+
|
31 |
+
// Formatize numbers, add thousands of separators
|
32 |
+
export const formatNumberWithThousandsSeparator = (numberStr: string) => {
|
33 |
+
const formattedNumber = numberStr.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
34 |
+
return formattedNumber;
|
35 |
+
};
|