balibabu
commited on
Commit
·
ba91369
1
Parent(s):
0a4eab6
feat: Move files in file manager #1826 (#1837)
Browse files### What problem does this PR solve?
feat: Move files in file manager #1826
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/src/assets/svg/move.svg +6 -0
- web/src/hooks/file-manager-hooks.ts +45 -0
- web/src/locales/en.ts +2 -0
- web/src/locales/zh-traditional.ts +2 -0
- web/src/locales/zh.ts +2 -0
- web/src/pages/file-manager/action-cell/index.tsx +24 -6
- web/src/pages/file-manager/file-toolbar.tsx +21 -2
- web/src/pages/file-manager/folder-create-modal/index.tsx +1 -15
- web/src/pages/file-manager/hooks.ts +46 -0
- web/src/pages/file-manager/index.tsx +19 -1
- web/src/pages/file-manager/move-file-modal/async-tree-select.tsx +64 -0
- web/src/pages/file-manager/move-file-modal/index.tsx +54 -0
- web/src/services/file-manager-service.ts +5 -0
- web/src/utils/api.ts +1 -0
web/src/assets/svg/move.svg
ADDED
|
|
web/src/hooks/file-manager-hooks.ts
CHANGED
|
@@ -28,6 +28,23 @@ export interface IListResult {
|
|
| 28 |
loading: boolean;
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
export const useFetchFileList = (): ResponseType<any> & IListResult => {
|
| 32 |
const { searchString, handleInputChange } = useHandleSearchChange();
|
| 33 |
const { pagination, setPagination } = useGetPaginationWithRouter();
|
|
@@ -225,3 +242,31 @@ export const useConnectToKnowledge = () => {
|
|
| 225 |
|
| 226 |
return { data, loading, connectFileToKnowledge: mutateAsync };
|
| 227 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
loading: boolean;
|
| 29 |
}
|
| 30 |
|
| 31 |
+
export const useFetchPureFileList = () => {
|
| 32 |
+
const { mutateAsync, isPending: loading } = useMutation({
|
| 33 |
+
mutationKey: ['fetchPureFileList'],
|
| 34 |
+
gcTime: 0,
|
| 35 |
+
|
| 36 |
+
mutationFn: async (parentId: string) => {
|
| 37 |
+
const { data } = await fileManagerService.listFile({
|
| 38 |
+
parent_id: parentId,
|
| 39 |
+
});
|
| 40 |
+
|
| 41 |
+
return data;
|
| 42 |
+
},
|
| 43 |
+
});
|
| 44 |
+
|
| 45 |
+
return { loading, fetchList: mutateAsync };
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
export const useFetchFileList = (): ResponseType<any> & IListResult => {
|
| 49 |
const { searchString, handleInputChange } = useHandleSearchChange();
|
| 50 |
const { pagination, setPagination } = useGetPaginationWithRouter();
|
|
|
|
| 242 |
|
| 243 |
return { data, loading, connectFileToKnowledge: mutateAsync };
|
| 244 |
};
|
| 245 |
+
|
| 246 |
+
export interface IMoveFileBody {
|
| 247 |
+
src_file_ids: string[];
|
| 248 |
+
dest_file_id: string; // target folder id
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
export const useMoveFile = () => {
|
| 252 |
+
const queryClient = useQueryClient();
|
| 253 |
+
const { t } = useTranslation();
|
| 254 |
+
|
| 255 |
+
const {
|
| 256 |
+
data,
|
| 257 |
+
isPending: loading,
|
| 258 |
+
mutateAsync,
|
| 259 |
+
} = useMutation({
|
| 260 |
+
mutationKey: ['moveFile'],
|
| 261 |
+
mutationFn: async (params: IMoveFileBody) => {
|
| 262 |
+
const { data } = await fileManagerService.moveFile(params);
|
| 263 |
+
if (data.retcode === 0) {
|
| 264 |
+
message.success(t('message.operated'));
|
| 265 |
+
queryClient.invalidateQueries({ queryKey: ['fetchFileList'] });
|
| 266 |
+
}
|
| 267 |
+
return data.retcode;
|
| 268 |
+
},
|
| 269 |
+
});
|
| 270 |
+
|
| 271 |
+
return { data, loading, moveFile: mutateAsync };
|
| 272 |
+
};
|
web/src/locales/en.ts
CHANGED
|
@@ -26,6 +26,7 @@ export default {
|
|
| 26 |
download: 'Download',
|
| 27 |
close: 'Close',
|
| 28 |
preview: 'Preview',
|
|
|
|
| 29 |
},
|
| 30 |
login: {
|
| 31 |
login: 'Sign in',
|
|
@@ -564,6 +565,7 @@ The above is the content you need to summarize.`,
|
|
| 564 |
fileError: 'File error',
|
| 565 |
uploadLimit:
|
| 566 |
'The file size cannot exceed 10M, and the total number of files cannot exceed 128',
|
|
|
|
| 567 |
},
|
| 568 |
flow: {
|
| 569 |
cite: 'Cite',
|
|
|
|
| 26 |
download: 'Download',
|
| 27 |
close: 'Close',
|
| 28 |
preview: 'Preview',
|
| 29 |
+
move: 'Move',
|
| 30 |
},
|
| 31 |
login: {
|
| 32 |
login: 'Sign in',
|
|
|
|
| 565 |
fileError: 'File error',
|
| 566 |
uploadLimit:
|
| 567 |
'The file size cannot exceed 10M, and the total number of files cannot exceed 128',
|
| 568 |
+
destinationFolder: 'Destination folder',
|
| 569 |
},
|
| 570 |
flow: {
|
| 571 |
cite: 'Cite',
|
web/src/locales/zh-traditional.ts
CHANGED
|
@@ -26,6 +26,7 @@ export default {
|
|
| 26 |
download: '下載',
|
| 27 |
close: '關閉',
|
| 28 |
preview: '預覽',
|
|
|
|
| 29 |
},
|
| 30 |
login: {
|
| 31 |
login: '登入',
|
|
@@ -524,6 +525,7 @@ export default {
|
|
| 524 |
preview: '預覽',
|
| 525 |
fileError: '文件錯誤',
|
| 526 |
uploadLimit: '文件大小不能超過10M,文件總數不超過128個',
|
|
|
|
| 527 |
},
|
| 528 |
flow: {
|
| 529 |
cite: '引用',
|
|
|
|
| 26 |
download: '下載',
|
| 27 |
close: '關閉',
|
| 28 |
preview: '預覽',
|
| 29 |
+
move: '移動',
|
| 30 |
},
|
| 31 |
login: {
|
| 32 |
login: '登入',
|
|
|
|
| 525 |
preview: '預覽',
|
| 526 |
fileError: '文件錯誤',
|
| 527 |
uploadLimit: '文件大小不能超過10M,文件總數不超過128個',
|
| 528 |
+
destinationFolder: '目標資料夾',
|
| 529 |
},
|
| 530 |
flow: {
|
| 531 |
cite: '引用',
|
web/src/locales/zh.ts
CHANGED
|
@@ -26,6 +26,7 @@ export default {
|
|
| 26 |
download: '下载',
|
| 27 |
close: '关闭',
|
| 28 |
preview: '预览',
|
|
|
|
| 29 |
},
|
| 30 |
login: {
|
| 31 |
login: '登录',
|
|
@@ -542,6 +543,7 @@ export default {
|
|
| 542 |
preview: '预览',
|
| 543 |
fileError: '文件错误',
|
| 544 |
uploadLimit: '文件大小不能超过10M,文件总数不超过128个',
|
|
|
|
| 545 |
},
|
| 546 |
flow: {
|
| 547 |
flow: '工作流',
|
|
|
|
| 26 |
download: '下载',
|
| 27 |
close: '关闭',
|
| 28 |
preview: '预览',
|
| 29 |
+
move: '移动',
|
| 30 |
},
|
| 31 |
login: {
|
| 32 |
login: '登录',
|
|
|
|
| 543 |
preview: '预览',
|
| 544 |
fileError: '文件错误',
|
| 545 |
uploadLimit: '文件大小不能超过10M,文件总数不超过128个',
|
| 546 |
+
destinationFolder: '目标文件夹',
|
| 547 |
},
|
| 548 |
flow: {
|
| 549 |
flow: '工作流',
|
web/src/pages/file-manager/action-cell/index.tsx
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
|
|
|
|
|
| 1 |
import { useTranslate } from '@/hooks/common-hooks';
|
| 2 |
import { IFile } from '@/interfaces/database/file-manager';
|
| 3 |
import { api_host } from '@/utils/api';
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
import { downloadFile } from '@/utils/file-util';
|
| 5 |
import {
|
| 6 |
DeleteOutlined,
|
|
@@ -11,18 +17,13 @@ import {
|
|
| 11 |
} from '@ant-design/icons';
|
| 12 |
import { Button, Space, Tooltip } from 'antd';
|
| 13 |
import { useHandleDeleteFile } from '../hooks';
|
| 14 |
-
|
| 15 |
-
import NewDocumentLink from '@/components/new-document-link';
|
| 16 |
-
import {
|
| 17 |
-
getExtension,
|
| 18 |
-
isSupportedPreviewDocumentType,
|
| 19 |
-
} from '@/utils/document-util';
|
| 20 |
import styles from './index.less';
|
| 21 |
|
| 22 |
interface IProps {
|
| 23 |
record: IFile;
|
| 24 |
setCurrentRecord: (record: any) => void;
|
| 25 |
showRenameModal: (record: IFile) => void;
|
|
|
|
| 26 |
showConnectToKnowledgeModal: (record: IFile) => void;
|
| 27 |
setSelectedRowKeys(keys: string[]): void;
|
| 28 |
}
|
|
@@ -33,6 +34,7 @@ const ActionCell = ({
|
|
| 33 |
showRenameModal,
|
| 34 |
showConnectToKnowledgeModal,
|
| 35 |
setSelectedRowKeys,
|
|
|
|
| 36 |
}: IProps) => {
|
| 37 |
const documentId = record.id;
|
| 38 |
const beingUsed = false;
|
|
@@ -64,6 +66,10 @@ const ActionCell = ({
|
|
| 64 |
showConnectToKnowledgeModal(record);
|
| 65 |
};
|
| 66 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
return (
|
| 68 |
<Space size={0}>
|
| 69 |
{isKnowledgeBase || (
|
|
@@ -90,6 +96,18 @@ const ActionCell = ({
|
|
| 90 |
</Button>
|
| 91 |
</Tooltip>
|
| 92 |
)}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
{isKnowledgeBase || (
|
| 94 |
<Tooltip title={t('delete', { keyPrefix: 'common' })}>
|
| 95 |
<Button
|
|
|
|
| 1 |
+
import NewDocumentLink from '@/components/new-document-link';
|
| 2 |
+
import SvgIcon from '@/components/svg-icon';
|
| 3 |
import { useTranslate } from '@/hooks/common-hooks';
|
| 4 |
import { IFile } from '@/interfaces/database/file-manager';
|
| 5 |
import { api_host } from '@/utils/api';
|
| 6 |
+
import {
|
| 7 |
+
getExtension,
|
| 8 |
+
isSupportedPreviewDocumentType,
|
| 9 |
+
} from '@/utils/document-util';
|
| 10 |
import { downloadFile } from '@/utils/file-util';
|
| 11 |
import {
|
| 12 |
DeleteOutlined,
|
|
|
|
| 17 |
} from '@ant-design/icons';
|
| 18 |
import { Button, Space, Tooltip } from 'antd';
|
| 19 |
import { useHandleDeleteFile } from '../hooks';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
import styles from './index.less';
|
| 21 |
|
| 22 |
interface IProps {
|
| 23 |
record: IFile;
|
| 24 |
setCurrentRecord: (record: any) => void;
|
| 25 |
showRenameModal: (record: IFile) => void;
|
| 26 |
+
showMoveFileModal: (ids: string[]) => void;
|
| 27 |
showConnectToKnowledgeModal: (record: IFile) => void;
|
| 28 |
setSelectedRowKeys(keys: string[]): void;
|
| 29 |
}
|
|
|
|
| 34 |
showRenameModal,
|
| 35 |
showConnectToKnowledgeModal,
|
| 36 |
setSelectedRowKeys,
|
| 37 |
+
showMoveFileModal,
|
| 38 |
}: IProps) => {
|
| 39 |
const documentId = record.id;
|
| 40 |
const beingUsed = false;
|
|
|
|
| 66 |
showConnectToKnowledgeModal(record);
|
| 67 |
};
|
| 68 |
|
| 69 |
+
const onShowMoveFileModal = () => {
|
| 70 |
+
showMoveFileModal([documentId]);
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
return (
|
| 74 |
<Space size={0}>
|
| 75 |
{isKnowledgeBase || (
|
|
|
|
| 96 |
</Button>
|
| 97 |
</Tooltip>
|
| 98 |
)}
|
| 99 |
+
{isKnowledgeBase || (
|
| 100 |
+
<Tooltip title={t('move', { keyPrefix: 'common' })}>
|
| 101 |
+
<Button
|
| 102 |
+
type="text"
|
| 103 |
+
disabled={beingUsed}
|
| 104 |
+
onClick={onShowMoveFileModal}
|
| 105 |
+
className={styles.iconButton}
|
| 106 |
+
>
|
| 107 |
+
<SvgIcon name={`move`} width={16}></SvgIcon>
|
| 108 |
+
</Button>
|
| 109 |
+
</Tooltip>
|
| 110 |
+
)}
|
| 111 |
{isKnowledgeBase || (
|
| 112 |
<Tooltip title={t('delete', { keyPrefix: 'common' })}>
|
| 113 |
<Button
|
web/src/pages/file-manager/file-toolbar.tsx
CHANGED
|
@@ -17,13 +17,14 @@ import {
|
|
| 17 |
MenuProps,
|
| 18 |
Space,
|
| 19 |
} from 'antd';
|
| 20 |
-
import { useMemo } from 'react';
|
| 21 |
import {
|
| 22 |
useHandleBreadcrumbClick,
|
| 23 |
useHandleDeleteFile,
|
| 24 |
useSelectBreadcrumbItems,
|
| 25 |
} from './hooks';
|
| 26 |
|
|
|
|
| 27 |
import {
|
| 28 |
IListResult,
|
| 29 |
useFetchParentFolderList,
|
|
@@ -36,6 +37,7 @@ interface IProps
|
|
| 36 |
showFolderCreateModal: () => void;
|
| 37 |
showFileUploadModal: () => void;
|
| 38 |
setSelectedRowKeys: (keys: string[]) => void;
|
|
|
|
| 39 |
}
|
| 40 |
|
| 41 |
const FileToolbar = ({
|
|
@@ -45,6 +47,7 @@ const FileToolbar = ({
|
|
| 45 |
setSelectedRowKeys,
|
| 46 |
searchString,
|
| 47 |
handleInputChange,
|
|
|
|
| 48 |
}: IProps) => {
|
| 49 |
const { t } = useTranslate('knowledgeDetails');
|
| 50 |
const breadcrumbItems = useSelectBreadcrumbItems();
|
|
@@ -111,6 +114,10 @@ const FileToolbar = ({
|
|
| 111 |
setSelectedRowKeys,
|
| 112 |
);
|
| 113 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
const disabled = selectedRowKeys.length === 0;
|
| 115 |
|
| 116 |
const items: MenuProps['items'] = useMemo(() => {
|
|
@@ -127,8 +134,20 @@ const FileToolbar = ({
|
|
| 127 |
</Flex>
|
| 128 |
),
|
| 129 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
];
|
| 131 |
-
}, [
|
| 132 |
|
| 133 |
return (
|
| 134 |
<div className={styles.filter}>
|
|
|
|
| 17 |
MenuProps,
|
| 18 |
Space,
|
| 19 |
} from 'antd';
|
| 20 |
+
import { useCallback, useMemo } from 'react';
|
| 21 |
import {
|
| 22 |
useHandleBreadcrumbClick,
|
| 23 |
useHandleDeleteFile,
|
| 24 |
useSelectBreadcrumbItems,
|
| 25 |
} from './hooks';
|
| 26 |
|
| 27 |
+
import SvgIcon from '@/components/svg-icon';
|
| 28 |
import {
|
| 29 |
IListResult,
|
| 30 |
useFetchParentFolderList,
|
|
|
|
| 37 |
showFolderCreateModal: () => void;
|
| 38 |
showFileUploadModal: () => void;
|
| 39 |
setSelectedRowKeys: (keys: string[]) => void;
|
| 40 |
+
showMoveFileModal: (ids: string[]) => void;
|
| 41 |
}
|
| 42 |
|
| 43 |
const FileToolbar = ({
|
|
|
|
| 47 |
setSelectedRowKeys,
|
| 48 |
searchString,
|
| 49 |
handleInputChange,
|
| 50 |
+
showMoveFileModal,
|
| 51 |
}: IProps) => {
|
| 52 |
const { t } = useTranslate('knowledgeDetails');
|
| 53 |
const breadcrumbItems = useSelectBreadcrumbItems();
|
|
|
|
| 114 |
setSelectedRowKeys,
|
| 115 |
);
|
| 116 |
|
| 117 |
+
const handleShowMoveFileModal = useCallback(() => {
|
| 118 |
+
showMoveFileModal(selectedRowKeys);
|
| 119 |
+
}, [selectedRowKeys, showMoveFileModal]);
|
| 120 |
+
|
| 121 |
const disabled = selectedRowKeys.length === 0;
|
| 122 |
|
| 123 |
const items: MenuProps['items'] = useMemo(() => {
|
|
|
|
| 134 |
</Flex>
|
| 135 |
),
|
| 136 |
},
|
| 137 |
+
{
|
| 138 |
+
key: '5',
|
| 139 |
+
onClick: handleShowMoveFileModal,
|
| 140 |
+
label: (
|
| 141 |
+
<Flex gap={10}>
|
| 142 |
+
<span className={styles.deleteIconWrapper}>
|
| 143 |
+
<SvgIcon name={`move`} width={18}></SvgIcon>
|
| 144 |
+
</span>
|
| 145 |
+
<b>{t('move', { keyPrefix: 'common' })}</b>
|
| 146 |
+
</Flex>
|
| 147 |
+
),
|
| 148 |
+
},
|
| 149 |
];
|
| 150 |
+
}, [handleShowMoveFileModal, t, handleRemoveFile]);
|
| 151 |
|
| 152 |
return (
|
| 153 |
<div className={styles.filter}>
|
web/src/pages/file-manager/folder-create-modal/index.tsx
CHANGED
|
@@ -21,24 +21,12 @@ const FolderCreateModal = ({ visible, hideModal, loading, onOk }: IProps) => {
|
|
| 21 |
return onOk(ret.name);
|
| 22 |
};
|
| 23 |
|
| 24 |
-
const handleCancel = () => {
|
| 25 |
-
hideModal();
|
| 26 |
-
};
|
| 27 |
-
|
| 28 |
-
const onFinish = (values: any) => {
|
| 29 |
-
console.log('Success:', values);
|
| 30 |
-
};
|
| 31 |
-
|
| 32 |
-
const onFinishFailed = (errorInfo: any) => {
|
| 33 |
-
console.log('Failed:', errorInfo);
|
| 34 |
-
};
|
| 35 |
-
|
| 36 |
return (
|
| 37 |
<Modal
|
| 38 |
title={t('newFolder', { keyPrefix: 'fileManager' })}
|
| 39 |
open={visible}
|
| 40 |
onOk={handleOk}
|
| 41 |
-
onCancel={
|
| 42 |
okButtonProps={{ loading }}
|
| 43 |
confirmLoading={loading}
|
| 44 |
>
|
|
@@ -47,8 +35,6 @@ const FolderCreateModal = ({ visible, hideModal, loading, onOk }: IProps) => {
|
|
| 47 |
labelCol={{ span: 4 }}
|
| 48 |
wrapperCol={{ span: 20 }}
|
| 49 |
style={{ maxWidth: 600 }}
|
| 50 |
-
onFinish={onFinish}
|
| 51 |
-
onFinishFailed={onFinishFailed}
|
| 52 |
autoComplete="off"
|
| 53 |
form={form}
|
| 54 |
>
|
|
|
|
| 21 |
return onOk(ret.name);
|
| 22 |
};
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
return (
|
| 25 |
<Modal
|
| 26 |
title={t('newFolder', { keyPrefix: 'fileManager' })}
|
| 27 |
open={visible}
|
| 28 |
onOk={handleOk}
|
| 29 |
+
onCancel={hideModal}
|
| 30 |
okButtonProps={{ loading }}
|
| 31 |
confirmLoading={loading}
|
| 32 |
>
|
|
|
|
| 35 |
labelCol={{ span: 4 }}
|
| 36 |
wrapperCol={{ span: 20 }}
|
| 37 |
style={{ maxWidth: 600 }}
|
|
|
|
|
|
|
| 38 |
autoComplete="off"
|
| 39 |
form={form}
|
| 40 |
>
|
web/src/pages/file-manager/hooks.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
| 4 |
useCreateFolder,
|
| 5 |
useDeleteFile,
|
| 6 |
useFetchParentFolderList,
|
|
|
|
| 7 |
useRenameFile,
|
| 8 |
useUploadFile,
|
| 9 |
} from '@/hooks/file-manager-hooks';
|
|
@@ -246,3 +247,48 @@ export const useHandleBreadcrumbClick = () => {
|
|
| 246 |
|
| 247 |
return { handleBreadcrumbClick };
|
| 248 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
useCreateFolder,
|
| 5 |
useDeleteFile,
|
| 6 |
useFetchParentFolderList,
|
| 7 |
+
useMoveFile,
|
| 8 |
useRenameFile,
|
| 9 |
useUploadFile,
|
| 10 |
} from '@/hooks/file-manager-hooks';
|
|
|
|
| 247 |
|
| 248 |
return { handleBreadcrumbClick };
|
| 249 |
};
|
| 250 |
+
|
| 251 |
+
export const useHandleMoveFile = (
|
| 252 |
+
setSelectedRowKeys: (keys: string[]) => void,
|
| 253 |
+
) => {
|
| 254 |
+
const {
|
| 255 |
+
visible: moveFileVisible,
|
| 256 |
+
hideModal: hideMoveFileModal,
|
| 257 |
+
showModal: showMoveFileModal,
|
| 258 |
+
} = useSetModalState();
|
| 259 |
+
const { moveFile, loading } = useMoveFile();
|
| 260 |
+
const [sourceFileIds, setSourceFileIds] = useState<string[]>([]);
|
| 261 |
+
|
| 262 |
+
const onMoveFileOk = useCallback(
|
| 263 |
+
async (targetFolderId: string) => {
|
| 264 |
+
const ret = await moveFile({
|
| 265 |
+
src_file_ids: sourceFileIds,
|
| 266 |
+
dest_file_id: targetFolderId,
|
| 267 |
+
});
|
| 268 |
+
|
| 269 |
+
if (ret === 0) {
|
| 270 |
+
setSelectedRowKeys([]);
|
| 271 |
+
hideMoveFileModal();
|
| 272 |
+
}
|
| 273 |
+
return ret;
|
| 274 |
+
},
|
| 275 |
+
[moveFile, hideMoveFileModal, sourceFileIds, setSelectedRowKeys],
|
| 276 |
+
);
|
| 277 |
+
|
| 278 |
+
const handleShowMoveFileModal = useCallback(
|
| 279 |
+
(ids: string[]) => {
|
| 280 |
+
setSourceFileIds(ids);
|
| 281 |
+
showMoveFileModal();
|
| 282 |
+
},
|
| 283 |
+
[showMoveFileModal],
|
| 284 |
+
);
|
| 285 |
+
|
| 286 |
+
return {
|
| 287 |
+
initialValue: '',
|
| 288 |
+
moveFileLoading: loading,
|
| 289 |
+
onMoveFileOk,
|
| 290 |
+
moveFileVisible,
|
| 291 |
+
hideMoveFileModal,
|
| 292 |
+
showMoveFileModal: handleShowMoveFileModal,
|
| 293 |
+
};
|
| 294 |
+
};
|
web/src/pages/file-manager/index.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
| 9 |
useGetRowSelection,
|
| 10 |
useHandleConnectToKnowledge,
|
| 11 |
useHandleCreateFolder,
|
|
|
|
| 12 |
useHandleUploadFile,
|
| 13 |
useNavigateToOtherFolder,
|
| 14 |
useRenameCurrentFile,
|
|
@@ -23,6 +24,7 @@ import { getExtension } from '@/utils/document-util';
|
|
| 23 |
import ConnectToKnowledgeModal from './connect-to-knowledge-modal';
|
| 24 |
import FolderCreateModal from './folder-create-modal';
|
| 25 |
import styles from './index.less';
|
|
|
|
| 26 |
|
| 27 |
const { Text } = Typography;
|
| 28 |
|
|
@@ -61,7 +63,13 @@ const FileManager = () => {
|
|
| 61 |
initialValue,
|
| 62 |
connectToKnowledgeLoading,
|
| 63 |
} = useHandleConnectToKnowledge();
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
const { pagination, data, searchString, handleInputChange, loading } =
|
| 66 |
useFetchFileList();
|
| 67 |
const columns: ColumnsType<IFile> = [
|
|
@@ -139,6 +147,7 @@ const FileManager = () => {
|
|
| 139 |
console.info(record);
|
| 140 |
}}
|
| 141 |
showRenameModal={showFileRenameModal}
|
|
|
|
| 142 |
showConnectToKnowledgeModal={showConnectToKnowledgeModal}
|
| 143 |
setSelectedRowKeys={setSelectedRowKeys}
|
| 144 |
></ActionCell>
|
|
@@ -155,6 +164,7 @@ const FileManager = () => {
|
|
| 155 |
showFolderCreateModal={showFolderCreateModal}
|
| 156 |
showFileUploadModal={showFileUploadModal}
|
| 157 |
setSelectedRowKeys={setSelectedRowKeys}
|
|
|
|
| 158 |
></FileToolbar>
|
| 159 |
<Table
|
| 160 |
dataSource={data?.files}
|
|
@@ -191,6 +201,14 @@ const FileManager = () => {
|
|
| 191 |
onOk={onConnectToKnowledgeOk}
|
| 192 |
loading={connectToKnowledgeLoading}
|
| 193 |
></ConnectToKnowledgeModal>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
</section>
|
| 195 |
);
|
| 196 |
};
|
|
|
|
| 9 |
useGetRowSelection,
|
| 10 |
useHandleConnectToKnowledge,
|
| 11 |
useHandleCreateFolder,
|
| 12 |
+
useHandleMoveFile,
|
| 13 |
useHandleUploadFile,
|
| 14 |
useNavigateToOtherFolder,
|
| 15 |
useRenameCurrentFile,
|
|
|
|
| 24 |
import ConnectToKnowledgeModal from './connect-to-knowledge-modal';
|
| 25 |
import FolderCreateModal from './folder-create-modal';
|
| 26 |
import styles from './index.less';
|
| 27 |
+
import FileMovingModal from './move-file-modal';
|
| 28 |
|
| 29 |
const { Text } = Typography;
|
| 30 |
|
|
|
|
| 63 |
initialValue,
|
| 64 |
connectToKnowledgeLoading,
|
| 65 |
} = useHandleConnectToKnowledge();
|
| 66 |
+
const {
|
| 67 |
+
showMoveFileModal,
|
| 68 |
+
moveFileVisible,
|
| 69 |
+
onMoveFileOk,
|
| 70 |
+
hideMoveFileModal,
|
| 71 |
+
moveFileLoading,
|
| 72 |
+
} = useHandleMoveFile(setSelectedRowKeys);
|
| 73 |
const { pagination, data, searchString, handleInputChange, loading } =
|
| 74 |
useFetchFileList();
|
| 75 |
const columns: ColumnsType<IFile> = [
|
|
|
|
| 147 |
console.info(record);
|
| 148 |
}}
|
| 149 |
showRenameModal={showFileRenameModal}
|
| 150 |
+
showMoveFileModal={showMoveFileModal}
|
| 151 |
showConnectToKnowledgeModal={showConnectToKnowledgeModal}
|
| 152 |
setSelectedRowKeys={setSelectedRowKeys}
|
| 153 |
></ActionCell>
|
|
|
|
| 164 |
showFolderCreateModal={showFolderCreateModal}
|
| 165 |
showFileUploadModal={showFileUploadModal}
|
| 166 |
setSelectedRowKeys={setSelectedRowKeys}
|
| 167 |
+
showMoveFileModal={showMoveFileModal}
|
| 168 |
></FileToolbar>
|
| 169 |
<Table
|
| 170 |
dataSource={data?.files}
|
|
|
|
| 201 |
onOk={onConnectToKnowledgeOk}
|
| 202 |
loading={connectToKnowledgeLoading}
|
| 203 |
></ConnectToKnowledgeModal>
|
| 204 |
+
{moveFileVisible && (
|
| 205 |
+
<FileMovingModal
|
| 206 |
+
visible={moveFileVisible}
|
| 207 |
+
hideModal={hideMoveFileModal}
|
| 208 |
+
onOk={onMoveFileOk}
|
| 209 |
+
loading={moveFileLoading}
|
| 210 |
+
></FileMovingModal>
|
| 211 |
+
)}
|
| 212 |
</section>
|
| 213 |
);
|
| 214 |
};
|
web/src/pages/file-manager/move-file-modal/async-tree-select.tsx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useFetchPureFileList } from '@/hooks/file-manager-hooks';
|
| 2 |
+
import { IFile } from '@/interfaces/database/file-manager';
|
| 3 |
+
import type { GetProp, TreeSelectProps } from 'antd';
|
| 4 |
+
import { TreeSelect } from 'antd';
|
| 5 |
+
import { useCallback, useEffect, useState } from 'react';
|
| 6 |
+
|
| 7 |
+
type DefaultOptionType = GetProp<TreeSelectProps, 'treeData'>[number];
|
| 8 |
+
|
| 9 |
+
interface IProps {
|
| 10 |
+
value?: string;
|
| 11 |
+
onChange?: (value: string) => void;
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
const AsyncTreeSelect = ({ value, onChange }: IProps) => {
|
| 15 |
+
const { fetchList } = useFetchPureFileList();
|
| 16 |
+
const [treeData, setTreeData] = useState<Omit<DefaultOptionType, 'label'>[]>(
|
| 17 |
+
[],
|
| 18 |
+
);
|
| 19 |
+
|
| 20 |
+
const onLoadData: TreeSelectProps['loadData'] = useCallback(
|
| 21 |
+
async ({ id }) => {
|
| 22 |
+
const ret = await fetchList(id);
|
| 23 |
+
if (ret.retcode === 0) {
|
| 24 |
+
setTreeData((tree) => {
|
| 25 |
+
return tree.concat(
|
| 26 |
+
ret.data.files
|
| 27 |
+
.filter((x: IFile) => x.type === 'folder')
|
| 28 |
+
.map((x: IFile) => ({
|
| 29 |
+
id: x.id,
|
| 30 |
+
pId: x.parent_id,
|
| 31 |
+
value: x.id,
|
| 32 |
+
title: x.name,
|
| 33 |
+
isLeaf: false,
|
| 34 |
+
})),
|
| 35 |
+
);
|
| 36 |
+
});
|
| 37 |
+
}
|
| 38 |
+
},
|
| 39 |
+
[fetchList],
|
| 40 |
+
);
|
| 41 |
+
|
| 42 |
+
const handleChange = (newValue: string) => {
|
| 43 |
+
onChange?.(newValue);
|
| 44 |
+
};
|
| 45 |
+
|
| 46 |
+
useEffect(() => {
|
| 47 |
+
onLoadData?.({ id: '', props: '' });
|
| 48 |
+
}, [onLoadData]);
|
| 49 |
+
|
| 50 |
+
return (
|
| 51 |
+
<TreeSelect
|
| 52 |
+
treeDataSimpleMode
|
| 53 |
+
style={{ width: '100%' }}
|
| 54 |
+
value={value}
|
| 55 |
+
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
|
| 56 |
+
placeholder="Please select"
|
| 57 |
+
onChange={handleChange}
|
| 58 |
+
loadData={onLoadData}
|
| 59 |
+
treeData={treeData}
|
| 60 |
+
/>
|
| 61 |
+
);
|
| 62 |
+
};
|
| 63 |
+
|
| 64 |
+
export default AsyncTreeSelect;
|
web/src/pages/file-manager/move-file-modal/index.tsx
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { IModalManagerChildrenProps } from '@/components/modal-manager';
|
| 2 |
+
import { useTranslate } from '@/hooks/common-hooks';
|
| 3 |
+
import { Form, Modal } from 'antd';
|
| 4 |
+
import AsyncTreeSelect from './async-tree-select';
|
| 5 |
+
|
| 6 |
+
interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
|
| 7 |
+
loading: boolean;
|
| 8 |
+
onOk: (id: string) => void;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
const FileMovingModal = ({ visible, hideModal, loading, onOk }: IProps) => {
|
| 12 |
+
const [form] = Form.useForm();
|
| 13 |
+
const { t } = useTranslate('fileManager');
|
| 14 |
+
|
| 15 |
+
type FieldType = {
|
| 16 |
+
name?: string;
|
| 17 |
+
};
|
| 18 |
+
|
| 19 |
+
const handleOk = async () => {
|
| 20 |
+
const ret = await form.validateFields();
|
| 21 |
+
|
| 22 |
+
return onOk(ret.name);
|
| 23 |
+
};
|
| 24 |
+
|
| 25 |
+
return (
|
| 26 |
+
<Modal
|
| 27 |
+
title={t('move', { keyPrefix: 'common' })}
|
| 28 |
+
open={visible}
|
| 29 |
+
onOk={handleOk}
|
| 30 |
+
onCancel={hideModal}
|
| 31 |
+
okButtonProps={{ loading }}
|
| 32 |
+
confirmLoading={loading}
|
| 33 |
+
width={600}
|
| 34 |
+
>
|
| 35 |
+
<Form
|
| 36 |
+
name="basic"
|
| 37 |
+
labelCol={{ span: 6 }}
|
| 38 |
+
wrapperCol={{ span: 18 }}
|
| 39 |
+
autoComplete="off"
|
| 40 |
+
form={form}
|
| 41 |
+
>
|
| 42 |
+
<Form.Item<FieldType>
|
| 43 |
+
label={t('destinationFolder')}
|
| 44 |
+
name="name"
|
| 45 |
+
rules={[{ required: true, message: t('pleaseSelect') }]}
|
| 46 |
+
>
|
| 47 |
+
<AsyncTreeSelect></AsyncTreeSelect>
|
| 48 |
+
</Form.Item>
|
| 49 |
+
</Form>
|
| 50 |
+
</Modal>
|
| 51 |
+
);
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
export default FileMovingModal;
|
web/src/services/file-manager-service.ts
CHANGED
|
@@ -13,6 +13,7 @@ const {
|
|
| 13 |
connectFileToKnowledge,
|
| 14 |
get_document_file,
|
| 15 |
getFile,
|
|
|
|
| 16 |
} = api;
|
| 17 |
|
| 18 |
const methods = {
|
|
@@ -49,6 +50,10 @@ const methods = {
|
|
| 49 |
method: 'get',
|
| 50 |
responseType: 'blob',
|
| 51 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
} as const;
|
| 53 |
|
| 54 |
const fileManagerService = registerServer<keyof typeof methods>(
|
|
|
|
| 13 |
connectFileToKnowledge,
|
| 14 |
get_document_file,
|
| 15 |
getFile,
|
| 16 |
+
moveFile,
|
| 17 |
} = api;
|
| 18 |
|
| 19 |
const methods = {
|
|
|
|
| 50 |
method: 'get',
|
| 51 |
responseType: 'blob',
|
| 52 |
},
|
| 53 |
+
moveFile: {
|
| 54 |
+
url: moveFile,
|
| 55 |
+
method: 'post',
|
| 56 |
+
},
|
| 57 |
} as const;
|
| 58 |
|
| 59 |
const fileManagerService = registerServer<keyof typeof methods>(
|
web/src/utils/api.ts
CHANGED
|
@@ -79,6 +79,7 @@ export default {
|
|
| 79 |
createFolder: `${api_host}/file/create`,
|
| 80 |
connectFileToKnowledge: `${api_host}/file2document/convert`,
|
| 81 |
getFile: `${api_host}/file/get`,
|
|
|
|
| 82 |
|
| 83 |
// system
|
| 84 |
getSystemVersion: `${api_host}/system/version`,
|
|
|
|
| 79 |
createFolder: `${api_host}/file/create`,
|
| 80 |
connectFileToKnowledge: `${api_host}/file2document/convert`,
|
| 81 |
getFile: `${api_host}/file/get`,
|
| 82 |
+
moveFile: `${api_host}/file/mv`,
|
| 83 |
|
| 84 |
// system
|
| 85 |
getSystemVersion: `${api_host}/system/version`,
|