Newer
Older
import {i18n} from './i18n';
import {css, html} from 'lit-element';
import {ScopedElementsMixin} from '@open-wc/scoped-elements';
import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element';
import * as commonUtils from "@dbp-toolkit/common/utils";
import {Icon, MiniSpinner} from '@dbp-toolkit/common';
import * as commonStyles from '@dbp-toolkit/common/styles';
import {NextcloudFilePicker} from "./dbp-nextcloud-file-picker";
import {classMap} from 'lit-html/directives/class-map.js';
import FileSaver from 'file-saver';
Bekerle, Patrizio
committed
import MicroModal from "./micromodal.es";
Steinwender, Tamara
committed
import * as fileHandlingStyles from './styles';
import { send } from '@dbp-toolkit/common/notification';
import {Clipboard} from "@dbp-toolkit/file-handling/src/clipboard";
/**
* FileSink web component
*/
export class FileSink extends ScopedElementsMixin(DBPLitElement) {
constructor() {
super();
Steinwender, Tamara
committed
this.context = '';
this.lang = 'de';
this.nextcloudAuthUrl = '';
this.nextcloudWebDavUrl = '';
Steinwender, Tamara
committed
this.nextcloudName ='Nextcloud';
this.nextcloudFileURL = '';
Bekerle, Patrizio
committed
this.buttonLabel = '';
this.filename = "files.zip";
this.files = [];
this.activeTarget = 'local';
Bekerle, Patrizio
committed
this.isDialogOpen = false;
this.enabledTargets = 'local';
this.fullsizeModal = false;
this.nextcloudAuthInfo = '';
this.initialFileHandlingState = {target: '', path: ''};
}
static get scopedElements() {
return {
'dbp-icon': Icon,
'dbp-mini-spinner': MiniSpinner,
'dbp-nextcloud-file-picker': NextcloudFilePicker,
};
}
/**
* See: https://lit-element.polymer-project.org/guide/properties#initialize
*/
static get properties() {
context: {type: String, attribute: 'context'},
lang: {type: String},
filename: {type: String},
files: {type: Array, attribute: false},
enabledTargets: {type: String, attribute: 'enabled-targets'},
nextcloudAuthUrl: {type: String, attribute: 'nextcloud-auth-url'},
nextcloudWebDavUrl: {type: String, attribute: 'nextcloud-web-dav-url'},
nextcloudName: {type: String, attribute: 'nextcloud-name'},
nextcloudFileURL: {type: String, attribute: 'nextcloud-file-url'},
nextcloudAuthInfo: {type: String, attribute: 'nextcloud-auth-info'},
buttonLabel: {type: String, attribute: 'button-label'},
isDialogOpen: {type: Boolean, attribute: false},
activeTarget: {type: String, attribute: 'active-target'},
nextcloudPath: {type: String, attribute: false},
fullsizeModal: { type: Boolean, attribute: 'fullsize-modal' },
initialFileHandlingState: {type: Object, attribute: 'initial-file-handling-state'},
connectedCallback() {
super.connectedCallback();
this.updateComplete.then(() => {
});
}
Bekerle, Patrizio
committed
async downloadCompressedFiles() {
// see: https://stuk.github.io/jszip/
let JSZip = (await import('jszip/dist/jszip.js')).default;
let zip = new JSZip();
let fileNames = [];
// download one file not compressed!
FileSaver.saveAs(this.files[0], this.files[0].filename);
return;
}
// download all files compressed
Bekerle, Patrizio
committed
this.files.forEach((file) => {
let fileName = file.name;
// add pseudo-random string on duplicate file name
if (fileNames.indexOf(fileName) !== -1) {
fileName = commonUtils.getBaseName(fileName) + "-" + Math.random().toString(36).substring(7) + "." +
commonUtils.getFileExtension(fileName);
}
fileNames.push(fileName);
zip.file(fileName, file);
});
let content = await zip.generateAsync({type:"blob"});
// see: https://github.com/eligrey/FileSaver.js#readme
Bekerle, Patrizio
committed
FileSaver.saveAs(content, this.filename || "files.zip");
}
update(changedProperties) {
changedProperties.forEach((oldValue, propName) => {
switch (propName) {
case "lang":
i18n.changeLanguage(this.lang);
break;
case "enabledTargets":
if (!this.hasEnabledDestination(this.activeTargets)) {
this.activeTargets = this.enabledTargets.split(",")[0];
Bekerle, Patrizio
committed
}
break;
case "files":
Bekerle, Patrizio
committed
this.openDialog();
if (this.enabledTargets.includes("clipboard")) {
const clipboardSink = this._("#clipboard-file-picker");
if (clipboardSink) {
this._("#clipboard-file-picker").filesToSave = [...this.files];
Bekerle, Patrizio
committed
}
break;
case "initialFileHandlingState":
//check if default destination is set
if (this.firstOpen) {
this.nextcloudPath = this.initialFileHandlingState.path;
}
});
super.update(changedProperties);
}
Bekerle, Patrizio
committed
hasEnabledDestination(source) {
return this.enabledTargets.split(',').includes(source);
async uploadToNextcloud(directory) {
let that = this;
const element = that._('#nextcloud-file-picker');
await element.uploadFiles(that.files, directory);
Steinwender, Tamara
committed
finishedFileUpload(event) {
Steinwender, Tamara
committed
MicroModal.close(this._('#modal-picker'));
Steinwender, Tamara
committed
send({
"summary": i18n.t('file-sink.upload-success-title'),
"body": i18n.t('file-sink.upload-success-body', {name: this.nextcloudName, count: event.detail}),
"type": "success",
"timeout": 5,
});
}
sendDestination() {
let data = {};
data = {"target": this.activeTarget, "path": this._("#nextcloud-file-picker").directoryPath};
data = {"target": this.activeTarget};
this.sendSetPropertyEvent('initial-file-handling-state', data);
preventDefaults (e) {
e.preventDefault();
e.stopPropagation();
}
Bekerle, Patrizio
committed
const filePicker = this._('#nextcloud-file-picker');
Steinwender, Tamara
committed
if (filePicker) {
filePicker.checkSessionStorage().then(contents => {
if (filePicker.webDavClient !== null) {
filePicker.loadDirectory(filePicker.directoryPath);
}
});
Bekerle, Patrizio
committed
openDialog() {
if (this.enabledTargets.includes('nextcloud')) {
this.loadWebdavDirectory();
}
Steinwender, Tamara
committed
if (this.enabledTargets.includes('clipboard')) {
if (this._('#clipboard-file-picker')._("#select_all")) {
this._('#clipboard-file-picker')._("#select_all").checked = false;
}
}
const filePicker = this._('#modal-picker');
if (filePicker) {
MicroModal.show(filePicker, {
disableScroll: true,
onClose: modal => { this.isDialogOpen = false; },
});
}
//check if default destination is set
if (this.initialFileHandlingState.target !== '' && typeof this.initialFileHandlingState.target !== 'undefined' && this.firstOpen) {
this.activeTarget = this.initialFileHandlingState.target;
this.nextcloudPath = this.initialFileHandlingState.path;
Bekerle, Patrizio
committed
const filePicker = this._('#nextcloud-file-picker');
if (filePicker && filePicker.webDavClient !== null) {
filePicker.loadDirectory(this.initialFileHandlingState.path);
Bekerle, Patrizio
committed
Steinwender, Tamara
committed
closeDialog(e) {
this.sendDestination();
MicroModal.close(this._('#modal-picker'));
Steinwender, Tamara
committed
getClipboardHtml() {
if (this.enabledTargets.includes('clipboard')) {
Steinwender, Tamara
committed
return html`
<dbp-clipboard
Steinwender, Tamara
committed
subscribe="clipboard-files:clipboard-files"
Steinwender, Tamara
committed
lang="${this.lang}"
auth-url="${this.nextcloudAuthUrl}"
enabled-targets="${this.enabledTargets}"
nextcloud-auth-url="${this.nextcloudAuthUrl}"
nextcloud-web-dav-url="${this.nextcloudWebDavUrl}"
nextcloud-name="${this.nextcloudName}"
nextcloud-file-url="${this.nextcloudFileURL}"
@dbp-clipboard-file-picker-file-uploaded="${(event) => {
this.closeDialog(event);}}">
Steinwender, Tamara
committed
</dbp-clipboard>`;
Steinwender, Tamara
committed
return html``;
Steinwender, Tamara
committed
getNextcloudHtml() {
if (this.enabledTargets.includes('nextcloud') && this.nextcloudWebDavUrl !== "" && this.nextcloudAuthUrl !== "") {
return html`
<dbp-nextcloud-file-picker id="nextcloud-file-picker"
class="${classMap({hidden: this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"
directories-only
max-selected-items="1"
select-button-text="${i18n.t('file-sink.select-directory')}"
?disabled="${this.disabled}"
lang="${this.lang}"
Bekerle, Patrizio
committed
subscribe="html-overrides"
Steinwender, Tamara
committed
auth-url="${this.nextcloudAuthUrl}"
web-dav-url="${this.nextcloudWebDavUrl}"
nextcloud-name="${this.nextcloudName}"
auth-info="${this.nextcloudAuthInfo}"
Steinwender, Tamara
committed
directory-path="${this.nextcloudPath}"
nextcloud-file-url="${this.nextcloudFileURL}"
@dbp-nextcloud-file-picker-file-uploaded="${(event) => {
this.uploadToNextcloud(event.detail);
}}"
@dbp-nextcloud-file-picker-file-uploaded-finished="${(event) => {
this.finishedFileUpload(event);
}}">
</dbp-nextcloud-file-picker>`;
}
return html``;
Bekerle, Patrizio
committed
}
Steinwender, Tamara
committed
static get styles() {
// language=css
return css`
${commonStyles.getThemeCSS()}
${commonStyles.getGeneralCSS()}
${commonStyles.getButtonCSS()}
Bekerle, Patrizio
committed
${commonStyles.getModalDialogCSS()}
Steinwender, Tamara
committed
${fileHandlingStyles.getFileHandlingCss()}
Bekerle, Patrizio
committed
.modal-container-full-size{
min-width: 100%;
min-height: 100%;
}
Bekerle, Patrizio
committed
#zip-download-block {
height: 100%;
Steinwender, Tamara
committed
width: 100%;
Bekerle, Patrizio
committed
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.block {
margin-bottom: 10px;
}
Steinwender, Tamara
committed
#clipboard-file-sink{
Steinwender, Tamara
committed
width: 100%;
Steinwender, Tamara
committed
height: 100%;
`;
}
render() {
return html`
<vpu-notification lang="de" client-id="my-client-id"></vpu-notification>
Bekerle, Patrizio
committed
<div class="modal micromodal-slide" id="modal-picker" aria-hidden="true">
<div class="modal-container ${classMap({"modal-container-full-size": this.fullsizeModal})}" role="dialog" aria-modal="true" aria-labelledby="modal-picker-title">
Bekerle, Patrizio
committed
<nav class="modal-nav">
<div title="${i18n.t('file-sink.nav-local')}"
@click="${() => { this.activeTarget = "local"; }}"
class="${classMap({"active": this.activeTarget === "local", hidden: !this.hasEnabledDestination("local")})}">
<dbp-icon class="nav-icon" name="laptop"></dbp-icon>
Steinwender, Tamara
committed
<p>${i18n.t('file-source.nav-local')}</p>
Bekerle, Patrizio
committed
</div>
Steinwender, Tamara
committed
<div title="${this.nextcloudName}"
@click="${() => { this.activeTarget = "nextcloud"; this.loadWebdavDirectory();}}"
class="${classMap({"active": this.activeTarget === "nextcloud", hidden: !this.hasEnabledDestination("nextcloud") || this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}">
<dbp-icon class="nav-icon" name="cloud"></dbp-icon>
Steinwender, Tamara
committed
<p> ${this.nextcloudName} </p>
Bekerle, Patrizio
committed
</div>
@click="${() => { this.activeTarget = "clipboard"; }}"
class="${classMap({"active": this.activeTarget === "clipboard", hidden: (!this.hasEnabledDestination("clipboard")) })}">
<dbp-icon class="nav-icon" name="clipboard"></dbp-icon>
Bekerle, Patrizio
committed
</nav>
Steinwender, Tamara
committed
<div class="modal-header">
<button title="${i18n.t('file-sink.modal-close')}" class="modal-close" aria-label="Close modal" @click="${() => { this.closeDialog();}}">
Steinwender, Tamara
committed
<dbp-icon title="${i18n.t('file-sink.modal-close')}" name="close" class="close-icon"></dbp-icon>
</button>
<p class="modal-context"> ${this.context}</p>
</div>
Bekerle, Patrizio
committed
<main class="modal-content" id="modal-picker-content">
<div class="source-main ${classMap({"hidden": this.activeTarget !== "local"})}">
Bekerle, Patrizio
committed
<div id="zip-download-block">
<div class="block">
${i18n.t('file-sink.local-intro', {'count': this.files.length})}
Bekerle, Patrizio
committed
</div>
<button class="button is-primary"
?disabled="${this.disabled}"
@click="${() => { this.downloadCompressedFiles(); }}">
${i18n.t('file-sink.local-button', {'count': this.files.length})}
Bekerle, Patrizio
committed
</button>
</div>
</div>
<div class="source-main ${classMap({"hidden": this.activeTarget !== "nextcloud" || this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}">
Steinwender, Tamara
committed
${this.getNextcloudHtml()}
Bekerle, Patrizio
committed
</div>
<div class="source-main ${classMap({"hidden": this.activeTarget !== "clipboard"})}">
Steinwender, Tamara
committed
${this.getClipboardHtml()}
Bekerle, Patrizio
committed
</main>
</div>
</div>
</div>