From 951c89e255bf1f8cfa7cd787e9703c7992b45cf3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com>
Date: Fri, 13 Jan 2023 11:42:48 +0100
Subject: [PATCH] upload progress

---
 app/assets/javascripts/vue.js                 |  1 +
 .../vue/direct-upload-controller.js           | 52 +++++++++++++++++++
 .../admin/communication/blocks/edit.html.erb  | 39 +++++++++-----
 3 files changed, 79 insertions(+), 13 deletions(-)
 create mode 100644 app/assets/javascripts/vue/direct-upload-controller.js

diff --git a/app/assets/javascripts/vue.js b/app/assets/javascripts/vue.js
index f812291c6..503079155 100644
--- a/app/assets/javascripts/vue.js
+++ b/app/assets/javascripts/vue.js
@@ -1,2 +1,3 @@
 //= require vue/dist/vue.global.prod.js
 //= require vue-draggable-next/dist/vue-draggable-next.global.js
+//= require vue/direct-upload-controller
\ No newline at end of file
diff --git a/app/assets/javascripts/vue/direct-upload-controller.js b/app/assets/javascripts/vue/direct-upload-controller.js
new file mode 100644
index 000000000..b16af85fb
--- /dev/null
+++ b/app/assets/javascripts/vue/direct-upload-controller.js
@@ -0,0 +1,52 @@
+/*global Vue */
+Vue.DirectUploadController = function DirectUploadController (input, file, url) {
+    'use strict';
+    this.input = input;
+    this.file = file;
+    this.url = url;
+    this.directUpload = new ActiveStorage.DirectUpload(this.file, this.url, this)
+    this.dispatch("initialize");
+}
+
+Vue.DirectUploadController.prototype.start = function (callback) {
+    'use strict';
+    this.directUpload.create(function (error, blob) {
+        this.dispatch("end");
+        if (error) {
+            console.log(error);
+        } else {
+            callback(blob);
+        }
+    }.bind(this));
+}
+
+Vue.DirectUploadController.prototype.uploadRequestDidProgress = function (event) {
+    'use strict';
+    var progress = event.loaded / event.total * 100
+    if (progress) {
+        this.dispatch("progress", { "progress": progress });
+    }
+}
+
+Vue.DirectUploadController.prototype.dispatch = function (name, detail) {
+    var event = document.createEvent("Event"),
+        disabled = this.input.disabled;
+    detail = detail || {};
+    detail.file = this.file;
+    detail.id = this.directUpload.id;
+    event.initEvent(`direct-upload:${name}`, true, true);
+    event.detail = detail;
+
+    this.input.disabled = false;
+    this.input.dispatchEvent(event);
+    this.input.disabled = disabled;
+
+    return event;
+}
+
+// DirectUpload delegate
+
+Vue.DirectUploadController.prototype.directUploadWillStoreFileWithXHR = function (xhr) {
+    'use strict';
+    xhr.upload.addEventListener("progress", this.uploadRequestDidProgress.bind(this));
+}
\ No newline at end of file
diff --git a/app/views/admin/communication/blocks/edit.html.erb b/app/views/admin/communication/blocks/edit.html.erb
index 8dfdb9fb7..ff00edca2 100644
--- a/app/views/admin/communication/blocks/edit.html.erb
+++ b/app/views/admin/communication/blocks/edit.html.erb
@@ -65,27 +65,22 @@
         var files = event.target.files || event.dataTransfer.files;
         if (!files.length)
           return;
-        this.uploadFile(files[0], object, key);
+        this.uploadFile(event.target, files[0], object, key);
       },
-      uploadFile(file, object, key) {
-        var url = this.directUpload.url,
-            size = Math.round(file.size / 1024 / 1024);
+      uploadFile(input, file, object, key) {
+        var size = Math.round(file.size / 1024 / 1024);
+        var controller = new Vue.DirectUploadController(input, file, this.directUpload.url)
         if (file.size > <%= Communication::Block::IMAGE_MAX_SIZE %>) {
           alert("<%= t('admin.communication.blocks.alerts.image_is_too_big').html_safe %> (" + size + " Mo > <%= number_to_human_size Communication::Block::IMAGE_MAX_SIZE %>)");
           return;
         }
-        var upload = new ActiveStorage.DirectUpload(file, url);
-        upload.create(function (error, blob) {
-          if (error) {
-            console.log(error);
-          } else {
-            object[key] = {
+        controller.start(function (blob) {
+          object[key] = {
               id: blob.id,
               signed_id: blob.signed_id,
               filename: blob.filename
-            };
-          }
-        }.bind(this));
+          };
+        });
       },
       getFileUrl(signed_id, filename) {
         return this.directUpload.blobUrlTemplate
@@ -123,6 +118,24 @@
     }
   });
 
+  window.addEventListener('direct-upload:initialize', function (event) {
+    event.target.insertAdjacentHTML('afterend', `<progress value="0" max="100" style="width: 100%;"></progress>`)
+  });
+
+  window.addEventListener('direct-upload:progress', function (event) {
+    var progressBar = event.target.parentNode.querySelector('progress');
+    if (progressBar) {
+      progressBar.value = event.detail.progress;
+    }
+  });
+
+  window.addEventListener('direct-upload:end', function (event) {
+    var progressBar = event.target.parentNode.querySelector('progress');
+    if (progressBar) {
+      progressBar.parentNode.removeChild(progressBar);
+    }
+  });
+
   window.addEventListener('load', function(){
     setTimeout(function() {
       app.mount('#app');
-- 
GitLab