From 72d26fa019e835ba8f7c32ebc921495a5dd0a94c Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Mon, 20 Apr 2020 17:18:47 +0200
Subject: [PATCH] Port to scoped elements

---
 packages/file-handling/package.json          |   1 +
 packages/file-handling/rollup.config.js      |   2 +-
 packages/file-handling/src/demo.js           |  11 +-
 packages/file-handling/src/fileupload.js     | 243 +++++++++++++++++++
 packages/file-handling/src/index.js          |   4 +-
 packages/file-handling/src/vpu-fileupload.js | 238 +-----------------
 packages/file-handling/vendor/common         |   2 +-
 7 files changed, 260 insertions(+), 241 deletions(-)
 create mode 100644 packages/file-handling/src/fileupload.js

diff --git a/packages/file-handling/package.json b/packages/file-handling/package.json
index fd79b40a..5d40d4f6 100644
--- a/packages/file-handling/package.json
+++ b/packages/file-handling/package.json
@@ -24,6 +24,7 @@
     "vpu-common": "file:./vendor/common"
   },
   "dependencies": {
+    "@open-wc/scoped-elements": "^1.0.8",
     "i18next": "^19.4.2",
     "lit-element": "^2.1.0",
     "lit-html": "^1.1.1",
diff --git a/packages/file-handling/rollup.config.js b/packages/file-handling/rollup.config.js
index 036b7b8c..8fbc8e44 100644
--- a/packages/file-handling/rollup.config.js
+++ b/packages/file-handling/rollup.config.js
@@ -13,7 +13,7 @@ const build = (typeof process.env.BUILD !== 'undefined') ? process.env.BUILD : '
 console.log("build: " + build);
 
 export default {
-    input: (build !== 'test') ? 'src/demo.js' : glob.sync('test/**/*.js'),
+    input: (build !== 'test') ? ['src/demo.js', 'src/vpu-fileupload.js'] : glob.sync('test/**/*.js'),
     output: {
         dir: 'dist',
         entryFileNames: '[name].js',
diff --git a/packages/file-handling/src/demo.js b/packages/file-handling/src/demo.js
index 75fbaafb..cdbb663a 100644
--- a/packages/file-handling/src/demo.js
+++ b/packages/file-handling/src/demo.js
@@ -1,16 +1,23 @@
 import {i18n} from './i18n';
 import {html, LitElement} from 'lit-element';
 import {unsafeHTML} from 'lit-html/directives/unsafe-html.js';
-import './vpu-fileupload';
+import {ScopedElementsMixin} from '@open-wc/scoped-elements';
+import {FileUpload} from './fileupload.js';
 import * as commonUtils from 'vpu-common/utils';
 
-class FileUploadDemo extends LitElement {
+class FileUploadDemo extends ScopedElementsMixin(LitElement) {
     constructor() {
         super();
         this.lang = 'de';
         this.url = '';
     }
 
+    static get scopedElements() {
+        return {
+          'vpu-fileupload': FileUpload,
+        };
+    }
+
     static get properties() {
         return {
             lang: { type: String },
diff --git a/packages/file-handling/src/fileupload.js b/packages/file-handling/src/fileupload.js
new file mode 100644
index 00000000..f4073bcb
--- /dev/null
+++ b/packages/file-handling/src/fileupload.js
@@ -0,0 +1,243 @@
+import {i18n} from './i18n';
+import {css, html} from 'lit-element';
+import {ifDefined} from 'lit-html/directives/if-defined';
+import {ScopedElementsMixin} from '@open-wc/scoped-elements';
+// import JSONLD from 'vpu-common/jsonld';
+import VPULitElement from 'vpu-common/vpu-lit-element'
+import "vpu-common/vpu-mini-spinner.js";
+import * as commonUtils from "vpu-common/utils";
+import {Icon} from 'vpu-common';
+import * as commonStyles from 'vpu-common/styles';
+
+/**
+ * KnowledgeBaseWebPageElementView web component
+ */
+export class FileUpload extends ScopedElementsMixin(VPULitElement) {
+    constructor() {
+        super();
+        this.lang = 'de';
+        this.url = '';
+        this.dropArea = null;
+        this.accept = '';
+        this.text = '';
+        this.buttonLabel = '';
+        this.uploadInProgress = false;
+    }
+
+    static get scopedElements() {
+        return {
+          'vpu-icon': Icon,
+        };
+    }
+
+    /**
+     * See: https://lit-element.polymer-project.org/guide/properties#initialize
+     */
+    static get properties() {
+        return {
+            lang: { type: String },
+            url: { type: String },
+            accept: { type: String },
+            text: { type: String },
+            buttonLabel: { type: String, attribute: 'button-label'},
+            uploadInProgress: { type: Boolean, attribute: false},
+        };
+    }
+
+
+    update(changedProperties) {
+        changedProperties.forEach((oldValue, propName) => {
+            if (propName === "lang") {
+                i18n.changeLanguage(this.lang);
+            }
+        });
+
+        super.update(changedProperties);
+    }
+
+    connectedCallback() {
+        super.connectedCallback();
+
+        this.updateComplete.then(() => {
+            this.dropArea = this._('#dropArea');
+            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
+                this.dropArea.addEventListener(eventName, this.preventDefaults, false)
+            });
+            ['dragenter', 'dragover'].forEach(eventName => {
+                this.dropArea.addEventListener(eventName, this.highlight.bind(this), false)
+            });
+            ['dragleave', 'drop'].forEach(eventName => {
+                this.dropArea.addEventListener(eventName, this.unhighlight.bind(this), false)
+            });
+            this.dropArea.addEventListener('drop', this.handleDrop.bind(this), false);
+            this._('#fileElem').addEventListener('change', this.handleChange.bind(this));
+        });
+    }
+
+    preventDefaults (e) {
+        e.preventDefault();
+        e.stopPropagation();
+    }
+
+    highlight(e) {
+        if (this.uploadInProgress) {
+            return;
+        }
+
+        this.dropArea.classList.add('highlight')
+    }
+
+    unhighlight(e) {
+        this.dropArea.classList.remove('highlight')
+    }
+
+    handleDrop(e) {
+        if (this.uploadInProgress) {
+            return;
+        }
+
+        let dt = e.dataTransfer;
+        console.dir(dt);
+        let files = dt.files;
+
+        this.handleFiles(files);
+    }
+
+    async handleChange(e) {
+        let fileElem = this._('#fileElem');
+
+        if (fileElem.files.length === 0) {
+            return;
+        }
+
+        await this.handleFiles(fileElem.files);
+
+        // reset the element's value so the user can upload the same file(s) again
+        fileElem.value = '';
+    }
+
+    async handleFiles(files) {
+        console.log('handleFiles: files.length = ' + files.length);
+
+        this.dispatchEvent(new CustomEvent("vpu-fileupload-all-start",
+            { "detail": {}, bubbles: true, composed: true }));
+
+        // we need to wait for each upload until we start the next one
+        await commonUtils.asyncArrayForEach(files, async (file) => this.uploadFile(file));
+
+        this.dispatchEvent(new CustomEvent("vpu-fileupload-all-finished",
+            { "detail": {}, bubbles: true, composed: true }));
+    }
+
+    async sendFinishedEvent(response, file, sendFile = false) {
+        if (response === undefined) {
+            return;
+        }
+
+        let data =  {
+            fileName: file.name,
+            status: response.status,
+            json: {"hydra:description": ""}
+        };
+
+        try {
+            await response.json().then((json) => {
+                data.json = json;
+            });
+        } catch (e) {}
+
+        if (sendFile) {
+            data.file = file;
+        }
+
+        const event = new CustomEvent("vpu-fileupload-file-finished", { "detail": data, bubbles: true, composed: true });
+        this.dispatchEvent(event);
+    }
+
+    sendStartEvent(file) {
+        let data =  {
+            fileName: file.name,
+            fileSize: file.size,
+        };
+
+        this.dispatchEvent(new CustomEvent("vpu-fileupload-file-start",
+            { "detail": data, bubbles: true, composed: true }));
+    }
+
+    /**
+     * @param file
+     * @returns {Promise<void>}
+     */
+    async uploadFile(file) {
+        this.uploadInProgress = true;
+        this.sendStartEvent(file);
+        let url = this.url;
+        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);
+            })
+            .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`
+            ${commonStyles.getButtonCSS()}
+
+            #dropArea {
+                border: var(--FUBorderWidth, 2px) var(--FUBorderStyle, dashed) var(--FUBBorderColor, black);
+                border-radius: var(--FUBorderRadius, 0);
+                width: var(--FUWidth, auto);
+                margin: var(--FUMargin, 0px);
+                padding: var(--FUPadding, 20px);
+            }
+
+            #dropArea.highlight {
+                border-color: var(--FUBorderColorHighlight, purple);
+            }
+
+            p {
+                margin-top: 0;
+            }
+
+            .my-form {
+                margin-bottom: 10px;
+            }
+
+            #fileElem {
+                display: none;
+            }
+        `;
+    }
+
+    render() {
+        return html`
+            <div id="dropArea">
+                <div class="my-form" title="${this.uploadInProgress ? i18n.t('upload-disabled-title') : ''}">
+                    <p>${this.text || i18n.t('intro')}</p>
+                    <input ?disabled="${this.uploadInProgress}" type="file" id="fileElem" multiple accept="${ifDefined(this.accept)}" name='file'>
+                    <label class="button is-primary" for="fileElem"><vpu-icon style="display: ${this.uploadInProgress ? "inline-block" : "none"}" name="lock"></vpu-icon> ${this.buttonLabel || i18n.t('upload-label')}</label>
+                </div>
+            </div>
+        `;
+    }
+}
\ No newline at end of file
diff --git a/packages/file-handling/src/index.js b/packages/file-handling/src/index.js
index c986b9a9..a71fa7f9 100644
--- a/packages/file-handling/src/index.js
+++ b/packages/file-handling/src/index.js
@@ -1 +1,3 @@
-import './vpu-fileupload';
+import {FileUpload} from './fileupload';
+
+export {FileUpload};
\ No newline at end of file
diff --git a/packages/file-handling/src/vpu-fileupload.js b/packages/file-handling/src/vpu-fileupload.js
index 53b422c9..d1b82789 100644
--- a/packages/file-handling/src/vpu-fileupload.js
+++ b/packages/file-handling/src/vpu-fileupload.js
@@ -1,238 +1,4 @@
-import {i18n} from './i18n';
-import {css, html} from 'lit-element';
-import {ifDefined} from 'lit-html/directives/if-defined';
-// import JSONLD from 'vpu-common/jsonld';
-import VPULitElement from 'vpu-common/vpu-lit-element'
-import "vpu-common/vpu-mini-spinner.js";
 import * as commonUtils from "vpu-common/utils";
-import 'vpu-common/vpu-icon.js';
-import * as commonStyles from 'vpu-common/styles';
+import {FileUpload} from './fileupload';
 
-/**
- * KnowledgeBaseWebPageElementView web component
- */
-class VPUFileUpload extends VPULitElement {
-    constructor() {
-        super();
-        this.lang = 'de';
-        this.url = '';
-        this.dropArea = null;
-        this.accept = '';
-        this.text = '';
-        this.buttonLabel = '';
-        this.uploadInProgress = false;
-    }
-
-    /**
-     * See: https://lit-element.polymer-project.org/guide/properties#initialize
-     */
-    static get properties() {
-        return {
-            lang: { type: String },
-            url: { type: String },
-            accept: { type: String },
-            text: { type: String },
-            buttonLabel: { type: String, attribute: 'button-label'},
-            uploadInProgress: { type: Boolean, attribute: false},
-        };
-    }
-
-
-    update(changedProperties) {
-        changedProperties.forEach((oldValue, propName) => {
-            if (propName === "lang") {
-                i18n.changeLanguage(this.lang);
-            }
-        });
-
-        super.update(changedProperties);
-    }
-
-    connectedCallback() {
-        super.connectedCallback();
-
-        this.updateComplete.then(() => {
-            this.dropArea = this._('#dropArea');
-            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.preventDefaults, false)
-            });
-            ['dragenter', 'dragover'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.highlight.bind(this), false)
-            });
-            ['dragleave', 'drop'].forEach(eventName => {
-                this.dropArea.addEventListener(eventName, this.unhighlight.bind(this), false)
-            });
-            this.dropArea.addEventListener('drop', this.handleDrop.bind(this), false);
-            this._('#fileElem').addEventListener('change', this.handleChange.bind(this));
-        });
-    }
-
-    preventDefaults (e) {
-        e.preventDefault();
-        e.stopPropagation();
-    }
-
-    highlight(e) {
-        if (this.uploadInProgress) {
-            return;
-        }
-
-        this.dropArea.classList.add('highlight')
-    }
-
-    unhighlight(e) {
-        this.dropArea.classList.remove('highlight')
-    }
-
-    handleDrop(e) {
-        if (this.uploadInProgress) {
-            return;
-        }
-
-        let dt = e.dataTransfer;
-        console.dir(dt);
-        let files = dt.files;
-
-        this.handleFiles(files);
-    }
-
-    async handleChange(e) {
-        let fileElem = this._('#fileElem');
-
-        if (fileElem.files.length === 0) {
-            return;
-        }
-
-        await this.handleFiles(fileElem.files);
-
-        // reset the element's value so the user can upload the same file(s) again
-        fileElem.value = '';
-    }
-
-    async handleFiles(files) {
-        console.log('handleFiles: files.length = ' + files.length);
-
-        this.dispatchEvent(new CustomEvent("vpu-fileupload-all-start",
-            { "detail": {}, bubbles: true, composed: true }));
-
-        // we need to wait for each upload until we start the next one
-        await commonUtils.asyncArrayForEach(files, async (file) => this.uploadFile(file));
-
-        this.dispatchEvent(new CustomEvent("vpu-fileupload-all-finished",
-            { "detail": {}, bubbles: true, composed: true }));
-    }
-
-    async sendFinishedEvent(response, file, sendFile = false) {
-        if (response === undefined) {
-            return;
-        }
-
-        let data =  {
-            fileName: file.name,
-            status: response.status,
-            json: {"hydra:description": ""}
-        };
-
-        try {
-            await response.json().then((json) => {
-                data.json = json;
-            });
-        } catch (e) {}
-
-        if (sendFile) {
-            data.file = file;
-        }
-
-        const event = new CustomEvent("vpu-fileupload-file-finished", { "detail": data, bubbles: true, composed: true });
-        this.dispatchEvent(event);
-    }
-
-    sendStartEvent(file) {
-        let data =  {
-            fileName: file.name,
-            fileSize: file.size,
-        };
-
-        this.dispatchEvent(new CustomEvent("vpu-fileupload-file-start",
-            { "detail": data, bubbles: true, composed: true }));
-    }
-
-    /**
-     * @param file
-     * @returns {Promise<void>}
-     */
-    async uploadFile(file) {
-        this.uploadInProgress = true;
-        this.sendStartEvent(file);
-        let url = this.url;
-        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);
-            })
-            .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`
-            ${commonStyles.getButtonCSS()}
-
-            #dropArea {
-                border: var(--FUBorderWidth, 2px) var(--FUBorderStyle, dashed) var(--FUBBorderColor, black);
-                border-radius: var(--FUBorderRadius, 0);
-                width: var(--FUWidth, auto);
-                margin: var(--FUMargin, 0px);
-                padding: var(--FUPadding, 20px);
-            }
-
-            #dropArea.highlight {
-                border-color: var(--FUBorderColorHighlight, purple);
-            }
-
-            p {
-                margin-top: 0;
-            }
-
-            .my-form {
-                margin-bottom: 10px;
-            }
-
-            #fileElem {
-                display: none;
-            }
-        `;
-    }
-
-    render() {
-        return html`
-            <div id="dropArea">
-                <div class="my-form" title="${this.uploadInProgress ? i18n.t('upload-disabled-title') : ''}">
-                    <p>${this.text || i18n.t('intro')}</p>
-                    <input ?disabled="${this.uploadInProgress}" type="file" id="fileElem" multiple accept="${ifDefined(this.accept)}" name='file'>
-                    <label class="button is-primary" for="fileElem"><vpu-icon style="display: ${this.uploadInProgress ? "inline-block" : "none"}" name="lock"></vpu-icon> ${this.buttonLabel || i18n.t('upload-label')}</label>
-                </div>
-            </div>
-        `;
-    }
-}
-
-commonUtils.defineCustomElement('vpu-fileupload', VPUFileUpload);
+commonUtils.defineCustomElement('vpu-fileupload', FileUpload);
diff --git a/packages/file-handling/vendor/common b/packages/file-handling/vendor/common
index 4f1d5c50..010b54fa 160000
--- a/packages/file-handling/vendor/common
+++ b/packages/file-handling/vendor/common
@@ -1 +1 @@
-Subproject commit 4f1d5c504ad5935b8903ab37abcbaa2b588112bd
+Subproject commit 010b54fa455829d732152b6794c7a92a874249aa
-- 
GitLab