Feat: Upload file UI/UX enhancements (#5359)

### What problem does this PR solve?

Modifies the UX for uploading process on the website.

- Adds option to parse on creation the files
- Adds progress bar to display progress of chunk
- Adds per file feedback on uploading operation

#### Screenshots:

- Show files uploading:

![image](https://github.com/user-attachments/assets/a5693f42-8232-4d5c-a240-20ed343634a5)

- Errors on specific files

![image](https://github.com/user-attachments/assets/986a7f54-ab32-4634-89ab-a098fe1954aa)


### Type of change

- [X] New Feature (non-breaking change which adds functionality)
This commit is contained in:
Omar Leonardo Sanchez Granados
2025-03-05 02:20:32 -05:00
committed by GitHub
parent f65c3ae62b
commit 11e3f5e8b2
13 changed files with 189 additions and 92 deletions

View File

@ -2,8 +2,10 @@ 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,
@ -21,10 +23,12 @@ const FileUpload = ({
directory,
fileList,
setFileList,
uploadProgress,
}: {
directory: boolean;
fileList: UploadFile[];
setFileList: Dispatch<SetStateAction<UploadFile[]>>;
uploadProgress: number;
}) => {
const { t } = useTranslate('fileManager');
const props: UploadProps = {
@ -35,7 +39,7 @@ const FileUpload = ({
newFileList.splice(index, 1);
setFileList(newFileList);
},
beforeUpload: (file) => {
beforeUpload: (file: UploadFile) => {
setFileList((pre) => {
return [...pre, file];
});
@ -44,38 +48,59 @@ const FileUpload = ({
},
directory,
fileList,
progress: {
strokeWidth: 2,
},
};
return (
<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>
<>
<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<boolean> {
uploadFileList: UploadFile[];
setUploadFileList: Dispatch<SetStateAction<UploadFile[]>>;
uploadProgress: number;
setUploadProgress: Dispatch<SetStateAction<number>>;
}
const FileUploadModal = ({
visible,
hideModal,
loading,
onOk: onFileUploadOk,
}: IModalProps<UploadFile[]>) => {
uploadFileList: fileList,
setUploadFileList: setFileList,
uploadProgress,
setUploadProgress,
}: IFileUploadModalProps) => {
const { t } = useTranslate('fileManager');
const [value, setValue] = useState<string | number>('local');
const [fileList, setFileList] = useState<UploadFile[]>([]);
const [directoryFileList, setDirectoryFileList] = useState<UploadFile[]>([]);
const [parseOnCreation, setParseOnCreation] = useState(false);
const clearFileList = () => {
setFileList([]);
setDirectoryFileList([]);
setUploadProgress(0);
};
const onOk = async () => {
const ret = await onFileUploadOk?.([...fileList, ...directoryFileList]);
if (uploadProgress === 100) {
hideModal?.();
return;
}
const ret = await onFileUploadOk?.(parseOnCreation);
return ret;
};
@ -92,6 +117,7 @@ const FileUploadModal = ({
directory={false}
fileList={fileList}
setFileList={setFileList}
uploadProgress={uploadProgress}
></FileUpload>
),
},
@ -101,8 +127,9 @@ const FileUploadModal = ({
children: (
<FileUpload
directory
fileList={directoryFileList}
setFileList={setDirectoryFileList}
fileList={fileList}
setFileList={setFileList}
uploadProgress={uploadProgress}
></FileUpload>
),
},
@ -129,7 +156,15 @@ const FileUploadModal = ({
onChange={setValue}
/>
{value === 'local' ? (
<Tabs defaultActiveKey="1" items={items} />
<>
<Checkbox
checked={parseOnCreation}
onChange={(e) => setParseOnCreation(e.target.checked)}
>
{t('parseOnCreation')}
</Checkbox>
<Tabs defaultActiveKey="1" items={items} />
</>
) : (
t('comingSoon', { keyPrefix: 'common' })
)}