mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-09-26 08:34:02 +00:00

### What problem does this PR solve? Fix: Knowledge base page cannot upload folders #6062 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
192 lines
4.5 KiB
TypeScript
192 lines
4.5 KiB
TypeScript
import { useTranslate } from '@/hooks/common-hooks';
|
|
import { IModalProps } from '@/interfaces/common';
|
|
import { InboxOutlined } from '@ant-design/icons';
|
|
import {
|
|
Checkbox,
|
|
Flex,
|
|
Modal,
|
|
Progress,
|
|
Segmented,
|
|
Tabs,
|
|
TabsProps,
|
|
Upload,
|
|
UploadFile,
|
|
UploadProps,
|
|
} from 'antd';
|
|
import { Dispatch, SetStateAction, useState } from 'react';
|
|
|
|
import styles from './index.less';
|
|
|
|
const { Dragger } = Upload;
|
|
|
|
const FileUpload = ({
|
|
directory,
|
|
fileList,
|
|
setFileList,
|
|
uploadProgress,
|
|
}: {
|
|
directory: boolean;
|
|
fileList: UploadFile[];
|
|
setFileList: Dispatch<SetStateAction<UploadFile[]>>;
|
|
uploadProgress?: number;
|
|
}) => {
|
|
const { t } = useTranslate('fileManager');
|
|
const props: UploadProps = {
|
|
multiple: true,
|
|
onRemove: (file) => {
|
|
const index = fileList.indexOf(file);
|
|
const newFileList = fileList.slice();
|
|
newFileList.splice(index, 1);
|
|
setFileList(newFileList);
|
|
},
|
|
beforeUpload: (file: UploadFile) => {
|
|
setFileList((pre) => {
|
|
return [...pre, file];
|
|
});
|
|
|
|
return false;
|
|
},
|
|
directory,
|
|
fileList,
|
|
progress: {
|
|
strokeWidth: 2,
|
|
},
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Progress percent={uploadProgress} showInfo={false} />
|
|
<Dragger {...props} className={styles.uploader}>
|
|
<p className="ant-upload-drag-icon">
|
|
<InboxOutlined />
|
|
</p>
|
|
<p className="ant-upload-text">{t('uploadTitle')}</p>
|
|
<p className="ant-upload-hint">{t('uploadDescription')}</p>
|
|
{false && <p className={styles.uploadLimit}>{t('uploadLimit')}</p>}
|
|
</Dragger>
|
|
</>
|
|
);
|
|
};
|
|
|
|
interface IFileUploadModalProps
|
|
extends IModalProps<
|
|
{ parseOnCreation: boolean; directoryFileList: UploadFile[] } | UploadFile[]
|
|
> {
|
|
uploadFileList?: UploadFile[];
|
|
setUploadFileList?: Dispatch<SetStateAction<UploadFile[]>>;
|
|
uploadProgress?: number;
|
|
setUploadProgress?: Dispatch<SetStateAction<number>>;
|
|
}
|
|
|
|
const FileUploadModal = ({
|
|
visible,
|
|
hideModal,
|
|
loading,
|
|
onOk: onFileUploadOk,
|
|
uploadFileList: fileList,
|
|
setUploadFileList: setFileList,
|
|
uploadProgress,
|
|
setUploadProgress,
|
|
}: IFileUploadModalProps) => {
|
|
const { t } = useTranslate('fileManager');
|
|
const [value, setValue] = useState<string | number>('local');
|
|
const [parseOnCreation, setParseOnCreation] = useState(false);
|
|
const [currentFileList, setCurrentFileList] = useState<UploadFile[]>([]);
|
|
const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
|
|
|
|
const clearFileList = () => {
|
|
if (setFileList) {
|
|
setFileList([]);
|
|
setUploadProgress?.(0);
|
|
} else {
|
|
setCurrentFileList([]);
|
|
}
|
|
setDirectoryFileList([]);
|
|
};
|
|
|
|
const onOk = async () => {
|
|
if (uploadProgress === 100) {
|
|
hideModal?.();
|
|
return;
|
|
}
|
|
|
|
const ret = await onFileUploadOk?.(
|
|
fileList
|
|
? { parseOnCreation, directoryFileList }
|
|
: [...currentFileList, ...directoryFileList],
|
|
);
|
|
return ret;
|
|
};
|
|
|
|
const afterClose = () => {
|
|
clearFileList();
|
|
};
|
|
|
|
const items: TabsProps['items'] = [
|
|
{
|
|
key: '1',
|
|
label: t('file'),
|
|
children: (
|
|
<FileUpload
|
|
directory={false}
|
|
fileList={fileList ? fileList : currentFileList}
|
|
setFileList={setFileList ? setFileList : setCurrentFileList}
|
|
uploadProgress={uploadProgress}
|
|
></FileUpload>
|
|
),
|
|
},
|
|
{
|
|
key: '2',
|
|
label: t('directory'),
|
|
children: (
|
|
<FileUpload
|
|
directory
|
|
fileList={directoryFileList}
|
|
setFileList={setDirectoryFileList}
|
|
uploadProgress={uploadProgress}
|
|
></FileUpload>
|
|
),
|
|
},
|
|
];
|
|
|
|
return (
|
|
<>
|
|
<Modal
|
|
title={t('uploadFile')}
|
|
open={visible}
|
|
onOk={onOk}
|
|
onCancel={hideModal}
|
|
confirmLoading={loading}
|
|
afterClose={afterClose}
|
|
>
|
|
<Flex gap={'large'} vertical>
|
|
<Segmented
|
|
options={[
|
|
{ label: t('local'), value: 'local' },
|
|
{ label: t('s3'), value: 's3' },
|
|
]}
|
|
block
|
|
value={value}
|
|
onChange={setValue}
|
|
/>
|
|
{value === 'local' ? (
|
|
<>
|
|
<Checkbox
|
|
checked={parseOnCreation}
|
|
onChange={(e) => setParseOnCreation(e.target.checked)}
|
|
>
|
|
{t('parseOnCreation')}
|
|
</Checkbox>
|
|
<Tabs defaultActiveKey="1" items={items} />
|
|
</>
|
|
) : (
|
|
t('comingSoon', { keyPrefix: 'common' })
|
|
)}
|
|
</Flex>
|
|
</Modal>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default FileUploadModal;
|