diff --git a/frappe/public/js/frappe/file_uploader/FileUploader.vue b/frappe/public/js/frappe/file_uploader/FileUploader.vue index 2420cc1bf5..10012c82ad 100644 --- a/frappe/public/js/frappe/file_uploader/FileUploader.vue +++ b/frappe/public/js/frappe/file_uploader/FileUploader.vue @@ -513,25 +513,36 @@ function check_restrictions(file) { return is_correct_type && valid_file_size; } + +function set_loading_state(dialog, loading) { + let $btn = dialog?.get_primary_btn(); + if (loading) { + $btn?.css("width", $btn.outerWidth()); + $btn?.html(``); + $btn?.prop("disabled", true); + dialog?.get_secondary_btn().prop("disabled", true); + } else { + $btn?.css("width", ""); + $btn?.html(__("Upload")); + $btn?.prop("disabled", false); + dialog?.get_secondary_btn().prop("disabled", false); + } +} function upload_files(dialog) { + set_loading_state(dialog, true); if (show_file_browser.value) { - return upload_via_file_browser(); - } - if (show_web_link.value) { - return upload_via_web_link(); - } - if (props.as_dataurl) { - return return_as_dataurl(); - } - if (!files.value.length) { + promise = upload_via_file_browser(); + } else if (show_web_link.value) { + promise = upload_via_web_link(); + } else if (props.as_dataurl) { + promise = return_as_dataurl(); + } else if (!files.value.length) { frappe.msgprint(__("Please select a file first.")); - return Promise.reject(); + promise = Promise.reject(); + } else { + promise = frappe.run_serially(files.value.map((file, i) => () => upload_file(file, i))); } - - dialog?.get_primary_btn().prop("disabled", true); - dialog?.get_secondary_btn().prop("disabled", true); - - return frappe.run_serially(files.value.map((file, i) => () => upload_file(file, i))); + return promise.finally(() => set_loading_state(dialog, false)); } function upload_via_file_browser() { let selected_file = file_browser.value.selected_node; @@ -548,12 +559,16 @@ function upload_via_file_browser() { function upload_via_web_link() { let file_url = web_link.value.url; if (!file_url) { - frappe.msgprint(__("Invalid URL")); - close_dialog.value = true; + web_link.value.invalid_input(__("Please enter a valid URL")); + return Promise.reject(); + } + try { + file_url = decodeURI(file_url); + } catch (error) { + var error_message = error.message; + web_link.value.invalid_input(__(error_message)); return Promise.reject(); } - file_url = decodeURI(file_url); - close_dialog.value = true; return upload_file({ file_url, }); @@ -584,7 +599,6 @@ function upload_file(file, i) { }); xhr.upload.addEventListener("load", (e) => { file.uploading = false; - resolve(); }); xhr.addEventListener("error", (e) => { file.failed = true; @@ -593,6 +607,7 @@ function upload_file(file, i) { xhr.onreadystatechange = () => { if (xhr.readyState == XMLHttpRequest.DONE) { if (xhr.status === 200) { + resolve(); file.request_succeeded = true; let r = null; let file_doc = null; @@ -617,7 +632,11 @@ function upload_file(file, i) { ) { close_dialog.value = true; } + if (show_web_link.value && file.file_url) { + close_dialog.value = true; + } } else if (xhr.status === 403) { + reject(); file.failed = true; let response = parse_error_response(xhr.responseText); file.error_message = __("Not permitted. {0}.", [response.error_message || ""]); @@ -625,16 +644,29 @@ function upload_file(file, i) { file.error_message += `\n${response.server_messages.join("\n")}`; } } else if (xhr.status === 413) { + reject(); file.failed = true; file.error_message = __("Size exceeds the maximum allowed file size."); } else if (xhr.status === 417) { + reject(); // regular frappe.throw() in backend file.failed = true; let response = parse_error_response(xhr.responseText); file.error_message = response.server_messages.length ? response.server_messages.join("\n") : __("File upload failed."); + + if (show_web_link.value && web_link.value && file.file_url) { + web_link.value.invalid_input(__(file.error_message)); + } else if (!files.value.includes(file)) { + frappe.msgprint({ + title: __("Upload Failed"), + message: __(file.error_message), + indicator: "red", + }); + } } else { + reject(); file.failed = true; let detail = xhr.statusText || diff --git a/frappe/public/js/frappe/file_uploader/WebLink.vue b/frappe/public/js/frappe/file_uploader/WebLink.vue index 7e731f0dc8..ef601a7796 100644 --- a/frappe/public/js/frappe/file_uploader/WebLink.vue +++ b/frappe/public/js/frappe/file_uploader/WebLink.vue @@ -1,28 +1,42 @@