From 1a8438f57e6c86d5855b96ff97b3109f9eb2d4d8 Mon Sep 17 00:00:00 2001
From: Patrizio Bekerle <patrizio@bekerle.com>
Date: Thu, 25 Jun 2020 13:29:05 +0200
Subject: [PATCH] Implement FileSource component (VPU/Apps/Signature#28)

---
 packages/file-handling/src/file-source.js | 169 +++-------------------
 1 file changed, 20 insertions(+), 149 deletions(-)

diff --git a/packages/file-handling/src/file-source.js b/packages/file-handling/src/file-source.js
index 12b0fae1..b9982659 100644
--- a/packages/file-handling/src/file-source.js
+++ b/packages/file-handling/src/file-source.js
@@ -42,12 +42,6 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
         this.allowedMimeTypes = '*/*';
         this.text = '';
         this.buttonLabel = '';
-        this.uploadInProgress = false;
-        this.multipleUploadInProgress = false;
-        this.alwaysSendFile = false;
-        this.isDeferred = false;
-        this.queuedFiles = [];
-        this.queuedFilesCount = 0;
         this.disabled = false;
         this.decompressZip = false;
         this._queueKey = 0;
@@ -73,11 +67,6 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
             nextcloudWebDavUrl: { type: String, attribute: 'nextcloud-web-dav-url' },
             text: { type: String },
             buttonLabel: { type: String, attribute: 'button-label' },
-            uploadInProgress: { type: Boolean, attribute: false },
-            multipleUploadInProgress: { type: Boolean, attribute: false },
-            alwaysSendFile: { type: Boolean, attribute: 'always-send-file' },
-            isDeferred: { type: Boolean, attribute: 'deferred' },
-            queuedFilesCount: { type: Number, attribute: false },
             disabled: { type: Boolean },
             decompressZip: { type: Boolean, attribute: 'decompress-zip' },
         };
@@ -90,12 +79,6 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
                 case "lang":
                     i18n.changeLanguage(this.lang);
                     break;
-                case "queuedFilesCount":
-                    const data = { "queuedFilesCount": this.queuedFilesCount, "queuedFiles": this.queuedFiles };
-                    const event = new CustomEvent("vpu-file-source-queued-files-changed",
-                        { "detail": data, bubbles: true, composed: true });
-                    this.dispatchEvent(event);
-                    break;
             }
         });
 
@@ -127,10 +110,6 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
     }
 
     highlight(e) {
-        if (this.uploadInProgress) {
-            return;
-        }
-
         this.dropArea.classList.add('highlight')
     }
 
@@ -139,7 +118,7 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
     }
 
     handleDrop(e) {
-        if (this.uploadInProgress || this.disabled) {
+        if (this.disabled) {
             return;
         }
 
@@ -171,13 +150,9 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
      */
     async handleFiles(files) {
         console.log('handleFiles: files.length = ' + files.length);
-        this.multipleUploadInProgress = true;
+        // this.dispatchEvent(new CustomEvent("vpu-file-source-selection-start",
+        //     { "detail": {}, bubbles: true, composed: true }));
 
-        this.dispatchEvent(new CustomEvent("vpu-file-source-all-start",
-            { "detail": {}, bubbles: true, composed: true }));
-
-        // we need to copy the files to another array or else they will be gone in the setTimeout function!
-        let tempFilesToHandle = [];
         await commonUtils.asyncArrayForEach(files, async (file) => {
             if (file.size === 0) {
                 console.log('file \'' + file.name + '\' has size=0 and is denied!')
@@ -187,28 +162,28 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
             // check if we want to decompress the zip and queue the contained files
             if (this.decompressZip && file.type === "application/zip") {
                 // add decompressed files to tempFilesToHandle
-                tempFilesToHandle = tempFilesToHandle.concat(await this.decompressZIP(file));
+                await commonUtils.asyncArrayForEach(
+                    await this.decompressZIP(file), (file) => this.sendFileEvent(file));
 
                 return;
             } else if (this.allowedMimeTypes && !this.checkFileType(file)) {
                 return;
             }
 
-            tempFilesToHandle.push(file);
+            await this.sendFileEvent(file);
         });
 
-        // the browsers don't render updates to the dom while these files are handled!
-        // if we set a small delay the dom changes will be rendered
-        setTimeout(async () => {
-            // we need to wait for each upload until we start the next one
-            await commonUtils.asyncArrayForEach(tempFilesToHandle, async (file) =>
-                this.isDeferred ? this.queueFile(file) : this.uploadFile(file));
-
-            this.multipleUploadInProgress = false;
+        // this.dispatchEvent(new CustomEvent("vpu-file-source-selection-finished",
+        //     { "detail": {}, bubbles: true, composed: true }));
+    }
 
-            this.dispatchEvent(new CustomEvent("vpu-file-source-all-finished",
-                { "detail": {}, bubbles: true, composed: true }));
-        }, 100);
+    /**
+     * @param file
+     */
+    sendFileEvent(file) {
+        const data = {"file": file};
+        const event = new CustomEvent("vpu-file-source-file-selected", { "detail": data, bubbles: true, composed: true });
+        this.dispatchEvent(event);
     }
 
     checkFileType(file) {
@@ -306,108 +281,6 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
         this.dispatchEvent(event);
     }
 
-    sendStartEvent(file) {
-        let data =  {
-            fileName: file.name,
-            fileSize: file.size,
-        };
-
-        this.dispatchEvent(new CustomEvent("vpu-file-source-file-start",
-            { "detail": data, bubbles: true, composed: true }));
-    }
-
-    /**
-     * @param file
-     * @returns {Promise<number>} key of the queued item
-     */
-    async queueFile(file) {
-        this._queueKey++;
-        const key = this._queueKey;
-        this.queuedFiles[key] = file;
-        this.updateQueuedFilesCount();
-
-        const data = {"file": file};
-        const event = new CustomEvent("vpu-file-source-file-queued", { "detail": data, bubbles: true, composed: true });
-        this.dispatchEvent(event);
-
-        return key;
-    }
-
-    /**
-     * Takes a file off of the queue
-     *
-     * @param key
-     */
-    takeFileFromQueue(key) {
-        const file = this.queuedFiles[key];
-        delete this.queuedFiles[key];
-        this.updateQueuedFilesCount();
-
-        return file;
-    }
-
-    uploadOneQueuedFile() {
-        const file = this.takeFileFromQueue();
-
-        return this.uploadFile(file);
-    }
-
-    getQueuedFile(key) {
-        return this.queuedFiles[key];
-    }
-
-    getQueuedFiles() {
-        return this.queuedFiles;
-    }
-
-    clearQueuedFiles() {
-        this.queuedFiles = [];
-        this.queuedFilesCount = 0;
-    }
-
-    updateQueuedFilesCount() {
-        return this.queuedFilesCount = Object.keys(this.queuedFiles).length;
-    }
-
-    getQueuedFilesCount() {
-        return this.queuedFilesCount;
-    }
-
-    /**
-     * @param file
-     * @param params
-     * @returns {Promise<void>}
-     */
-    async uploadFile(file, params = {}) {
-        this.uploadInProgress = true;
-        this.sendStartEvent(file);
-        let url = new URL(this.url)
-        url.search = new URLSearchParams(params).toString();
-        let formData = new FormData();
-        formData.append('file', file);
-
-        // I got a 60s timeout in Google Chrome and found no way to increase that
-        await fetch(url, {
-            method: 'POST',
-            headers: {
-                'Authorization': 'Bearer ' + window.VPUAuthToken,
-            },
-            body: formData
-        })
-            .then((response) => {
-                /* Done. Inform the user */
-                console.log(`Status: ${response.status} for file ${file.name}`);
-                this.sendFinishedEvent(response, file, response.status !== 201 || this.alwaysSendFile);
-            })
-            .catch((response) => {
-                /* Error. Inform the user */
-                console.log(`Error status: ${response.status} for file ${file.name}`);
-                this.sendFinishedEvent(response, file, true);
-            });
-
-        this.uploadInProgress = false;
-    }
-
     static get styles() {
         // language=css
         return css`
@@ -458,30 +331,28 @@ export class FileSource extends ScopedElementsMixin(VPULitElement) {
 
         return html`
             <div id="dropArea">
-                <div title="${this.uploadInProgress ? i18n.t('upload-disabled-title') : ''}">
+                <div>
                     <div class="block">
                         ${this.text || i18n.t('intro')}
                     </div>
-                    <input ?disabled="${this.uploadInProgress || this.disabled}"
+                    <input ?disabled="${this.disabled}"
                            type="file"
                            id="fileElem"
                            multiple
                            accept="${mimeTypesToAccept(allowedMimeTypes)}"
                            name='file'>
                     <label class="button is-primary" for="fileElem" ?disabled="${this.disabled}">
-                        <vpu-icon style="display: ${this.uploadInProgress ? "inline-block" : "none"}" name="lock"></vpu-icon>
                         ${this.buttonLabel || i18n.t('upload-label')}
                     </label>
                     <vpu-nextcloud-file-picker id="nextcloud-file-picker"
                                                class="${classMap({hidden: this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"
-                                               ?disabled="${this.uploadInProgress || this.disabled}"
+                                               ?disabled="${this.disabled}"
                                                lang="${this.lang}"
                                                auth-url="${this.nextcloudAuthUrl}"
                                                web-dav-url="${this.nextcloudWebDavUrl}"
                                                @vpu-nextcloud-file-picker-file-downloaded="${(event) => {
-                                                   this.queueFile(event.detail.file);
+                                                   this.sendFileEvent(event.detail.file);
                                                }}"></vpu-nextcloud-file-picker>
-                    <vpu-mini-spinner style="display: ${this.multipleUploadInProgress ? "inline-block" : "none"}"></vpu-mini-spinner>
                 </div>
             </div>
         `;
-- 
GitLab