Skip to content
Snippets Groups Projects
Commit 72d26fa0 authored by Reiter, Christoph's avatar Reiter, Christoph :snake:
Browse files

Port to scoped elements

parent b6fd79b8
No related branches found
No related tags found
No related merge requests found
......@@ -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",
......
......@@ -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',
......
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 },
......
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
import './vpu-fileupload';
import {FileUpload} from './fileupload';
export {FileUpload};
\ No newline at end of file
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);
common @ 010b54fa
Subproject commit 4f1d5c504ad5935b8903ab37abcbaa2b588112bd
Subproject commit 010b54fa455829d732152b6794c7a92a874249aa
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment