From c53eea0b429e66aa656ebaaa86a03eafca11ba39 Mon Sep 17 00:00:00 2001 From: Clemens Schwaighofer Date: Tue, 17 Sep 2024 15:50:39 +0900 Subject: [PATCH] All CSS used are prefixed with afus-, uuid v4 for each upload group Set uuid v4 for each upload group as ".uploadQueueUid" Add max upload files as ".uploadQueueMax" Change to upload files to ".uploadQueueOpen" (from ".uploadQueueMax") Extract retrun message from two types for messages that could come from the server --- jsconfig.json | 15 +++++++++++++++ src/ajaxFileUploadSimple.js | 36 ++++++++++++++++++++++++++++++++---- test/backend.php | 4 ++++ test/other.css | 22 ++++++++++++++++++++++ test/other.js | 13 +++++++++++++ 5 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 jsconfig.json diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..a1014d5 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "Bundler", + "target": "ES2020", + "jsx": "react", + "allowImportingTsExtensions": true, + "strictNullChecks": true, + "strictFunctionTypes": true + }, + "exclude": [ + "node_modules", + "**/node_modules/*" + ] +} diff --git a/src/ajaxFileUploadSimple.js b/src/ajaxFileUploadSimple.js index fad3681..d6ef622 100644 --- a/src/ajaxFileUploadSimple.js +++ b/src/ajaxFileUploadSimple.js @@ -2,7 +2,7 @@ // 'use strict'; -/* jshint esversion: 6 */ +/* jshint esversion: 11 */ /** * CUSTOM SUB CALL FUNCTIONS as passsd on in init call @@ -49,6 +49,16 @@ if (!String.prototype.format) { }; } +/** + * A very simple uuidv4 for grouping same uploads together + * @returns uuidv4 + */ +function afusUuidv4() { + return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => + (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16) + ); +} + /** * [from edit.js] * checks if a key exists in a given object @@ -691,16 +701,19 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit // add to upload status list el = document.createElement('div'); el.id = target_file + '-status-' + i; + el.classList.add('afus-status-row'); // file pos in queue? would need pos update on delete // file name el_sub = document.createElement('span'); el_sub.id = target_file + '-status-name-' + i; + el_sub.classList.add('afus-status-name'); el_sub.innerHTML = input_files.files[i].name; el.appendChild(el_sub); // progress info (just text) el_sub = document.createElement('span'); el_sub.id = target_file + '-status-progress-' + i; el_sub.setAttribute('style', 'display:none;margin-left:5px;'); + el_sub.classList.add('afus-status-progress'); el.appendChild(el_sub); // Toptional progress info as visual bar el_sub = document.createElement('span'); @@ -709,6 +722,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit // attach progress element into it el_sub_sub = document.createElement('progress'); el_sub_sub.id = target_file + '-status-progress-bar-' + i; + el_sub_sub.classList.add('afus-status-progress-bar'); el_sub_sub.max = 100; el_sub_sub.value = 0; el_sub.appendChild(el_sub_sub); @@ -719,7 +733,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit // if invalid types, show error if (valid_type === false || valid_size === false) { el_sub.setAttribute('style', 'margin-left:5px;'); - el_sub.classList.add('SubError'); + el_sub.classList.add('afus-status-error'); let error_list = []; if (valid_type === false) { error_list.push(AFUS_strings[target_file].invalid_type || 'Invalid file type'); @@ -731,6 +745,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit } else { // else show remove el_sub.setAttribute('style', 'margin-left:5px;'); + el_sub.classList.add('afus-status-delete'); // -W083 el_sub.addEventListener('click', function() { // jshint ignore:line AFUS_file_list[target_file].splice(i, 1); @@ -754,6 +769,7 @@ function afusPassThroughEvent(target_file, max_files, target_router, auto_submit el_sub = document.createElement('span'); el_sub.id = target_file + '-status-abort-' + i; el_sub.setAttribute('style', 'margin-left:5px;display:none;'); + el_sub.classList.add('afus-status-abort'); el_sub.innerHTML = AFUS_strings[target_file].cancel || 'Cancel'; el.appendChild(el_sub); // hidden info @@ -929,6 +945,8 @@ class afusAsyncUploader this.form_append[key] = value; } } + this.form_append.uploadQueueUid = afusUuidv4(); + this.form_append.uploadQueueMax = AFUS_file_list[target_file].length; // the function call (afusSendFile) with promise this.functionCall = function_call; // error flag for upload error @@ -1024,7 +1042,7 @@ function afusSendFile(target_file, file, form_append) } formData.append('action', AFUS_config[target_file].target_router); formData.append('uploadQueuePos', file_pos); - formData.append('uploadQueueMax', AFUS_file_list[target_file].length); + formData.append('uploadQueueOpen', AFUS_file_list[target_file].length); formData.append('uploadName', target_file + '-file'); // add file only (first file found) with target file name formData.append(target_file + '-file', file); @@ -1206,8 +1224,18 @@ function afusOnReadyStateChangeHandler(target_file, file_pos, target_router, evt afusRunningStop(target_file); // must set dynamic console.log('[AJAX Uploader ORSC: %s/%s] Running: %s, Uploader response: %s -> %o', target_file, file_pos, afusRunningGet(target_file), responseData.status, responseData); + // the return msg is normally on base level, but it can be in content too + msg = []; + if (afusKeyInObject('msg', responseData.content)) { + msg = responseData.content.msg; + } else if (afusKeyInObject('msg', responseData)) { + // we need to prep this one, these are default error mssages objects + for (let __message in responseData.msg) { + msg.append(__message.str); + } + } // then run status output - afusUploadError(target_file, file_pos, responseData.content.msg, responseData.status == 'success' ? false : true); + afusUploadError(target_file, file_pos, msg, responseData.status == 'success' ? false : true); // run post uploader if (responseData.status == 'success') { afusPostUpload(target_file, file_pos, target_router, { diff --git a/test/backend.php b/test/backend.php index deb408b..33c8373 100644 --- a/test/backend.php +++ b/test/backend.php @@ -243,6 +243,7 @@ if (isset($_POST['action'])) { $ajax_data = [ 'msg' => [], 'file_uid' => null, + 'file_crc' => null, 'file_url' => null, 'file_name' => null, 'file_size' => null, @@ -263,6 +264,7 @@ if (isset($_POST['action'])) { if ($status == 'success') { // basic file id data $file_uid = null; + $file_crc = null; $file_url = null; $file_name = null; $file_size = null; @@ -279,6 +281,7 @@ if (isset($_POST['action'])) { $file_name = $_FILES[$upload_name]['name']; $file_size = humanReadableByteFormat($_FILES[$upload_name]['size']); $file_size_raw = $_FILES[$upload_name]['size']; + $file_crc = hash('sha256', file_get_contents($folder . $file_uid) ?: ''); // correct the image rotation // $this->correctImageOrientation(BASE.TMP.$file_uid); // make a copy to layout/cache/images for file url @@ -289,6 +292,7 @@ if (isset($_POST['action'])) { $ajax_data = [ 'msg' => $file_upload_message, 'file_uid' => $file_uid, + 'file_crc' => $file_crc, 'file_url' => $file_url, 'file_name' => $file_name, 'file_size' => $file_size, diff --git a/test/other.css b/test/other.css index 4b2ac8b..74838e0 100644 --- a/test/other.css +++ b/test/other.css @@ -45,6 +45,28 @@ CSS Other .uploaded { margin-top: 20px; } .title { font-size: 1.5em; font-weight: bold; margin-bottom: 10px; } +.afus-status-delete { + color: orange; + font-weight: bold; +} +.afus-status-progress { + color: rgb(37, 140, 191); +} +.afus-status-progress-bar { + height: 10px; +} +.afus-status-progress-bar::slider-fill { + background-color: orange; +} +.afus-status-abort { + color: red; +} +.afus-status-error { + color: red; + font-weight: bold; + font-size: 1.2em; +} + .file-upload label div { text-align: center; color: #e60012; diff --git a/test/other.js b/test/other.js index 48486cb..a6f9c2f 100644 --- a/test/other.js +++ b/test/other.js @@ -93,6 +93,16 @@ function ajaxWrapper(call_id, queryString = {}, control = {}, url = 'backend.php }); } +/** + * uuid4 creator + * @returns {String} uuid4 + */ +function uuidv4() { + return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => + (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16) + ); +} + /** * FILE CHANGE: * helper call for ajax file upload on file selected @@ -331,6 +341,9 @@ $(document).ready(function () { form_parameters: {'parameter_a': 'Value 123'}, auto_submit: false, function_options: {action_box_id: 'actionBox-alt', 'other': 'free'}, + translation: { + remove: "REMOVE" + }, fileChange: fileChangeFunction, fileChangeAll: fileChangeFunctionAll, fileRemove: fileRemoveFunction,