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

@ -248,60 +248,27 @@ export const useUploadNextDocument = () => {
} = useMutation({
mutationKey: ['uploadDocument'],
mutationFn: async (fileList: UploadFile[]) => {
const partitionedFileList = fileList.reduce<UploadFile[][]>(
(acc, cur, index) => {
const partIndex = Math.floor(index / 20); // Uploads 20 documents at a time
if (!acc[partIndex]) {
acc[partIndex] = [];
}
acc[partIndex].push(cur);
return acc;
},
[],
);
const formData = new FormData();
formData.append('kb_id', knowledgeId);
fileList.forEach((file: any) => {
formData.append('file', file);
});
let allRet = [];
for (const listPart of partitionedFileList) {
const formData = new FormData();
formData.append('kb_id', knowledgeId);
listPart.forEach((file: any) => {
formData.append('file', file);
});
try {
const ret = await kbService.document_upload(formData);
const code = get(ret, 'data.code');
try {
const ret = await kbService.document_upload(formData);
allRet.push(ret);
} catch (error) {
allRet.push({ data: { code: 500 } });
const filenames = listPart.map((file: any) => file.name).join(', ');
console.warn(error);
console.warn('Error uploading files:', filenames);
if (code === 0 || code === 500) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
}
return ret?.data;
} catch (error) {
console.warn(error);
return {
code: 500,
message: error + '',
};
}
const succeed = allRet.every((ret) => get(ret, 'data.code') === 0);
const any500 = allRet.some((ret) => get(ret, 'data.code') === 500);
if (succeed) {
message.success(i18n.t('message.uploaded'));
}
if (succeed || any500) {
queryClient.invalidateQueries({ queryKey: ['fetchDocumentList'] });
}
const allData = {
code: any500
? 500
: succeed
? 0
: allRet.filter((ret) => get(ret, 'data.code') !== 0)[0]?.data
?.code,
data: succeed,
message: allRet.map((ret) => get(ret, 'data.message')).join('/n'),
};
return allData;
},
});