|
@@ -57,21 +57,34 @@ const useChunkUpload = ({
|
|
|
}: ChunkUploadOptions): UseUploadQueueResponse => {
|
|
}: ChunkUploadOptions): UseUploadQueueResponse => {
|
|
|
const config = getLastKnownConfig();
|
|
const config = getLastKnownConfig();
|
|
|
const chunkSize = config?.storage_browser?.file_upload_chunk_size ?? DEFAULT_CHUNK_SIZE;
|
|
const chunkSize = config?.storage_browser?.file_upload_chunk_size ?? DEFAULT_CHUNK_SIZE;
|
|
|
- const [pendingItems, setPendingItems] = useState<UploadItem[]>([]);
|
|
|
|
|
|
|
+ const [processingItem, setProcessingItem] = useState<UploadItem>();
|
|
|
|
|
+ const [pendingUploadItems, setPendingUploadItems] = useState<UploadItem[]>([]);
|
|
|
|
|
+ const [awaitingStatusItems, setAwaitingStatusItems] = useState<UploadItem[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+ const onError = () => {
|
|
|
|
|
+ if (processingItem) {
|
|
|
|
|
+ onStatusUpdate(processingItem, FileUploadStatus.Failed);
|
|
|
|
|
+ setProcessingItem(undefined);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const onSuccess = (item: UploadItem) => () => {
|
|
|
|
|
+ setAwaitingStatusItems(prev => [...prev, item]);
|
|
|
|
|
+ setProcessingItem(undefined);
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
const { save } = useSaveData(undefined, {
|
|
const { save } = useSaveData(undefined, {
|
|
|
postOptions: {
|
|
postOptions: {
|
|
|
qsEncodeData: false,
|
|
qsEncodeData: false,
|
|
|
- headers: {
|
|
|
|
|
- 'Content-Type': 'multipart/form-data'
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ headers: { 'Content-Type': 'multipart/form-data' }
|
|
|
|
|
+ },
|
|
|
|
|
+ onError
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const updateItemStatus = (serverResponse: TaskServerResponse[]) => {
|
|
const updateItemStatus = (serverResponse: TaskServerResponse[]) => {
|
|
|
const statusMap = getStatusHashMap(serverResponse);
|
|
const statusMap = getStatusHashMap(serverResponse);
|
|
|
|
|
|
|
|
- const remainingItems = pendingItems.filter(item => {
|
|
|
|
|
|
|
+ const remainingItems = awaitingStatusItems.filter(item => {
|
|
|
const status = statusMap[item.uuid];
|
|
const status = statusMap[item.uuid];
|
|
|
if (status === TaskStatus.Success || status === TaskStatus.Failure) {
|
|
if (status === TaskStatus.Success || status === TaskStatus.Failure) {
|
|
|
const ItemStatus =
|
|
const ItemStatus =
|
|
@@ -84,14 +97,14 @@ const useChunkUpload = ({
|
|
|
if (remainingItems.length === 0) {
|
|
if (remainingItems.length === 0) {
|
|
|
onComplete();
|
|
onComplete();
|
|
|
}
|
|
}
|
|
|
- setPendingItems(remainingItems);
|
|
|
|
|
|
|
+ setAwaitingStatusItems(remainingItems);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const { data: tasksStatus } = useLoadData<TaskServerResponse[]>(
|
|
const { data: tasksStatus } = useLoadData<TaskServerResponse[]>(
|
|
|
'/desktop/api2/taskserver/get_taskserver_tasks/',
|
|
'/desktop/api2/taskserver/get_taskserver_tasks/',
|
|
|
{
|
|
{
|
|
|
- pollInterval: pendingItems.length ? 5000 : undefined,
|
|
|
|
|
- skip: !pendingItems.length
|
|
|
|
|
|
|
+ pollInterval: awaitingStatusItems.length ? 5000 : undefined,
|
|
|
|
|
+ skip: !awaitingStatusItems.length
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
|
|
|
|
@@ -101,16 +114,14 @@ const useChunkUpload = ({
|
|
|
}
|
|
}
|
|
|
}, [tasksStatus]);
|
|
}, [tasksStatus]);
|
|
|
|
|
|
|
|
- const addItemToPending = (item: UploadItem) => {
|
|
|
|
|
- setPendingItems(prev => [...prev, item]);
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const onChunksUploadComplete = async (item: UploadItem) => {
|
|
|
|
|
- const { url, payload } = getChunksCompletePayload(item, chunkSize);
|
|
|
|
|
- return save(payload, {
|
|
|
|
|
- url,
|
|
|
|
|
- onSuccess: () => addItemToPending(item)
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const onChunksUploadComplete = async () => {
|
|
|
|
|
+ if (processingItem) {
|
|
|
|
|
+ const { url, payload } = getChunksCompletePayload(processingItem, chunkSize);
|
|
|
|
|
+ return save(payload, {
|
|
|
|
|
+ url,
|
|
|
|
|
+ onSuccess: onSuccess(processingItem)
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const uploadChunk = async (chunkItem: UploadChunkItem) => {
|
|
const uploadChunk = async (chunkItem: UploadChunkItem) => {
|
|
@@ -118,21 +129,21 @@ const useChunkUpload = ({
|
|
|
return save(payload, { url });
|
|
return save(payload, { url });
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const { enqueueAsync } = useQueueProcessor<UploadChunkItem>(uploadChunk, {
|
|
|
|
|
- concurrentProcess
|
|
|
|
|
|
|
+ const { enqueue } = useQueueProcessor<UploadChunkItem>(uploadChunk, {
|
|
|
|
|
+ concurrentProcess,
|
|
|
|
|
+ onSuccess: onChunksUploadComplete
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
- const uploadItemInChunks = async (item: UploadItem) => {
|
|
|
|
|
|
|
+ const uploadItemInChunks = (item: UploadItem) => {
|
|
|
const chunks = createChunks(item, chunkSize);
|
|
const chunks = createChunks(item, chunkSize);
|
|
|
- await enqueueAsync(chunks);
|
|
|
|
|
- return onChunksUploadComplete(item);
|
|
|
|
|
|
|
+ return enqueue(chunks);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const uploadItemInSingleChunk = (item: UploadItem) => {
|
|
|
|
|
|
|
+ const uploadItemInSingleChunk = async (item: UploadItem) => {
|
|
|
const { url, payload } = getChunkSinglePayload(item, chunkSize);
|
|
const { url, payload } = getChunkSinglePayload(item, chunkSize);
|
|
|
return save(payload, {
|
|
return save(payload, {
|
|
|
url,
|
|
url,
|
|
|
- onSuccess: () => addItemToPending(item)
|
|
|
|
|
|
|
+ onSuccess: onSuccess(item)
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -158,15 +169,25 @@ const useChunkUpload = ({
|
|
|
return uploadItemInChunks(item);
|
|
return uploadItemInChunks(item);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const {
|
|
|
|
|
- enqueue: addFiles,
|
|
|
|
|
- dequeue: removeFile,
|
|
|
|
|
- isLoading
|
|
|
|
|
- } = useQueueProcessor<UploadItem>(uploadItem, {
|
|
|
|
|
- concurrentProcess: 1 // This value must be 1 always
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ const addFiles = (newItems: UploadItem[]) => {
|
|
|
|
|
+ setPendingUploadItems(prev => [...prev, ...newItems]);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const removeFile = (item: UploadItem) => {
|
|
|
|
|
+ setPendingUploadItems(prev => prev.filter(i => i.uuid !== item.uuid));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ // Ensures one file is broken down in chunks and uploaded to the server
|
|
|
|
|
+ if (!processingItem && pendingUploadItems.length) {
|
|
|
|
|
+ const item = pendingUploadItems[0];
|
|
|
|
|
+ setProcessingItem(item);
|
|
|
|
|
+ setPendingUploadItems(prev => prev.slice(1));
|
|
|
|
|
+ uploadItem(item);
|
|
|
|
|
+ }
|
|
|
|
|
+ }, [pendingUploadItems, processingItem]);
|
|
|
|
|
|
|
|
- return { addFiles, removeFile, isLoading };
|
|
|
|
|
|
|
+ return { addFiles, removeFile, isLoading: !!processingItem || !!pendingUploadItems.length };
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
export default useChunkUpload;
|
|
export default useChunkUpload;
|