diff --git a/src/api-client/dataset.js b/src/api-client/dataset.js index 5707f8786c..deaa8dd1cd 100644 --- a/src/api-client/dataset.js +++ b/src/api-client/dataset.js @@ -11,7 +11,7 @@ export default function addDatasetMethods(client) { }); }; - client.uploadFile = (file) => { + client.uploadFile = (file, controller) => { const data = new FormData(); data.append("file", file); data.append("file_name", file.name); @@ -22,27 +22,40 @@ export default function addDatasetMethods(client) { "Accept": "application/json" }); - return fetch(`${client.baseUrl}/renku/cache.files_upload?override_existing=true`, { + let queryParams = { method: "POST", headers: headers, body: data, processData: false + }; + + if (controller) queryParams.signal = controller.signal; + + return fetch(`${client.baseUrl}/renku/cache.files_upload?override_existing=true`, queryParams) + .then(response => { + if (controller !== undefined) + response.controller = controller; + return response; }); }; - client.addFilesToDataset = (projectUrl, datasetName, filesList) => { + client.addFilesToDataset = (projectUrl, datasetName, filesList, signal) => { let headers = client.getBasicHeaders(); headers.append("Content-Type", "application/json"); headers.append("X-Requested-With", "XMLHttpRequest"); - return client.clientFetch(`${client.baseUrl}/renku/cache.project_clone`, { + let queryParams = { method: "POST", headers: headers, body: JSON.stringify({ depth: 1, git_url: projectUrl - }) - }).then(response => { + }), + }; + + return client.clientFetch(`${client.baseUrl}/renku/cache.project_clone`, + queryParams + ).then(response => { if (response.data.error) { return response; } else if (filesList.length > 0) { @@ -53,7 +66,6 @@ export default function addDatasetMethods(client) { "dataset_name": datasetName, "files": filesList, "project_id": response.data.result.project_id - }) }); } return response; diff --git a/src/utils/formgenerator/fields/FileUploaderInput.js b/src/utils/formgenerator/fields/FileUploaderInput.js index 73b6967173..0b6848022a 100644 --- a/src/utils/formgenerator/fields/FileUploaderInput.js +++ b/src/utils/formgenerator/fields/FileUploaderInput.js @@ -61,14 +61,15 @@ function getFileStatus(id, error, status) { return FILE_STATUS.UPLOADING; } -function getFileObject(name, size, id, error, alias, status) { +function getFileObject(name, size, id, error, alias, controller, status) { return { file_name: name, file_size: size, file_id: id, file_error: error, file_alias: alias, - file_status: getFileStatus(id, error, status) + file_status: getFileStatus(id, error, status), + file_controller: controller }; } @@ -84,7 +85,7 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable useEffect(() => { if (value !== undefined && !initialized) { setDisplayFiles(value.map(file => getFileObject( - file.name, null, undefined, undefined, undefined, FILE_STATUS.ADDED))); + file.name, null, undefined, undefined, undefined, undefined, FILE_STATUS.ADDED))); } setInitialized(true); }, [value, initialized]); @@ -104,7 +105,8 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable uploadingFile.file_size, uploadingFile.file_id, filesErrors.find(file => file.file_name === uploadingFile.file_name), - uploadingFile.file_alias); + uploadingFile.file_alias, + uploadingFile.file_controller); } return dFile; }) @@ -119,7 +121,8 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable let errorFile = filesErrors.find(eFile => eFile.file_name === dFile.file_name); if (errorFile !== undefined) { return getFileObject( - errorFile.file_name, errorFile.file_size, null, errorFile.file_error, errorFile.file_alias); + errorFile.file_name, errorFile.file_size, null, errorFile.file_error, errorFile.file_alias, + errorFile.file_controller); } return dFile; }) @@ -127,28 +130,32 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable }, [filesErrors]); let uploadFile = (file) => { - uploadFileFunction(file).then((response) => { + uploadFileFunction(file, file.file_controller).then((response) => { if (response.status >= 400) throw new Error(); response.json().then((body) => { if (body.error) { setFilesErrors(prevFilesErrors => [...prevFilesErrors, - getFileObject(file.name, file.size, undefined, body.error.reason, undefined)] + getFileObject(file.name, file.size, undefined, body.error.reason, undefined, file.file_controller)] ); return []; } let newFileObj = body.result.files[0]; if (newFileObj.file_name !== undefined && newFileObj.file_name !== file.name) { newFileObj = getFileObject( - file.name, newFileObj.file_size, newFileObj.file_id, undefined, newFileObj.file_name); + file.name, newFileObj.file_size, newFileObj.file_id, undefined, newFileObj.file_name, + response.controller); } setUploadedFiles(prevUploadedFiles => [...prevUploadedFiles, newFileObj]); return newFileObj; }); }).catch((error) => { - setFilesErrors(prevFilesErrors => [...prevFilesErrors, - getFileObject(file.name, file.size, undefined, "Error uploading the file", undefined)]); - return []; + if (error.code !== DOMException.ABORT_ERR) { + setFilesErrors(prevFilesErrors => [...prevFilesErrors, + getFileObject(file.name, file.size, undefined, "Error uploading the file", undefined, + file.file_controller)]); + return []; + } }); }; @@ -158,19 +165,32 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable if (!disabled) { let eventFiles = e.dataTransfer ? e.dataTransfer.files : e.target.files; let droppedFiles = getFilteredFiles(Array.from(eventFiles)); - droppedFiles.map(file => uploadFile(file)); + + droppedFiles = "signal" in new Request("") ? + droppedFiles.map(file => { + file.file_controller = new AbortController(); + return file; + }) + : droppedFiles; + + droppedFiles.map(file => uploadFile(file, file.file_controller)); setFiles([...files, ...droppedFiles]); const newDisplayFiles = droppedFiles - .map(file => getFileObject(file.name, file.size, null, undefined, undefined)); + .map(file => getFileObject(file.name, file.size, null, undefined, undefined, file.file_controller)); + setDisplayFiles([...displayFiles, ...newDisplayFiles]); } }; - let deleteFile = (file_name) => { + let deleteFile = (file_name, file_controller) => { if (!disabled) { setFilesErrors(prevfilesErrors => prevfilesErrors.filter(file => file.file_name !== file_name)); setDisplayFiles(prevDisplayFiles => prevDisplayFiles.filter(file => file.file_name !== file_name)); setUploadedFiles(prevUploadedFiles => prevUploadedFiles.filter(file => file.file_name !== file_name)); + const filteredFiles = files.filter(file => file.name !== file_name); + setFiles([...filteredFiles]); + $input.current.value = ""; + if (file_controller) file_controller.abort(); } }; @@ -179,13 +199,15 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable let retryFile = files.find(file => file.name === file_name); if (retryFile !== undefined) { const displayFilesFiltered = displayFiles.map(file => { - if (file.file_name === file_name) - return getFileObject(retryFile.name, retryFile.size, null, undefined, undefined); + if (file.file_name === file_name) { + return getFileObject(retryFile.name, retryFile.size, null, undefined, retryFile.file_alias, + retryFile.file_controller); + } return file; }); setDisplayFiles([...displayFilesFiltered]); setFilesErrors(prevfilesErrors => prevfilesErrors.filter(file => file.file_name !== file_name)); - uploadFile(retryFile); + uploadFile(retryFile, retryFile.file_controller); } } }; @@ -198,7 +220,7 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable dropErrorMessage = dropErrorMessage === "" ? "Files can't have the same name (This file(s) alredy exist(s): " + file.name - : ", " + file.name; + : dropErrorMessage + ", " + file.name; return false; }); @@ -271,10 +293,13 @@ function FileuploaderInput({ name, label, alert, value, setInputs, help, disable