diff --git a/packages/file-handling/src/clipboard.js b/packages/file-handling/src/clipboard.js index 57c45cac1b176784f1199f8bf6b8835ed07d1f7e..0526c4164f54c3b9cd1eda92fac03400454e395c 100644 --- a/packages/file-handling/src/clipboard.js +++ b/packages/file-handling/src/clipboard.js @@ -78,6 +78,10 @@ export class Clipboard extends ScopedElementsMixin(AdapterLitElement) { return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector); } + _a(selector) { + return this.shadowRoot === null ? this.querySelectorAll(selector) : this.shadowRoot.querySelectorAll(selector); + } + update(changedProperties) { changedProperties.forEach((oldValue, propName) => { switch (propName) { @@ -100,8 +104,18 @@ export class Clipboard extends ScopedElementsMixin(AdapterLitElement) { let boundSelectHandler = this.selectAllFiles.bind(this); this._("#select_all").addEventListener('click', boundSelectHandler); } + + + + } + toggleCollapse(e) { + const table = this.tabulatorTable; + setTimeout(function() { + table.redraw(); + }, 0); + } connectedCallback() { @@ -111,8 +125,6 @@ export class Clipboard extends ScopedElementsMixin(AdapterLitElement) { // see: http://tabulator.info/docs/4.7 this.tabulatorTable = new Tabulator(this._("#clipboard-content-table"), {//if you delete the wrapper around the table you need to set a heigh here - maxHeight:"100%", - height:"100%", layout: "fitColumns", selectable: true, selectableRangeMode: "drag", @@ -324,6 +336,15 @@ export class Clipboard extends ScopedElementsMixin(AdapterLitElement) { if (this.tabulatorTable !== null) { this.tabulatorTable.clearData(); this.tabulatorTable.setData(data); + + console.log("add"); + if (this._('.tabulator-responsive-collapse-toggle-open')) { + this._a('.tabulator-responsive-collapse-toggle-open').forEach(element => element.addEventListener("click", this.toggleCollapse.bind(this))); + } + + if (this._('.tabulator-responsive-collapse-toggle-close')) { + this._a('.tabulator-responsive-collapse-toggle-close').forEach(element => element.addEventListener("click", this.toggleCollapse.bind(this))); + } } } if (this._("#select_all")) { diff --git a/packages/file-handling/src/dbp-file-handling-lit-element.js b/packages/file-handling/src/dbp-file-handling-lit-element.js new file mode 100644 index 0000000000000000000000000000000000000000..4806d35cd7dc9e878be9856442a0453c6e3029a4 --- /dev/null +++ b/packages/file-handling/src/dbp-file-handling-lit-element.js @@ -0,0 +1,79 @@ +import {ScopedElementsMixin} from '@open-wc/scoped-elements'; +import DBPLitElement from "../../common/dbp-lit-element"; + +export default class DbpFileHandlingLitElement extends ScopedElementsMixin(DBPLitElement) { + constructor() { + super(); + + } + + static get properties() { + return { + ...super.properties, + }; + } + + /** + * handles the scroll of the current element and displays the right and/or the left paddle + * to match the scrolling position + * + * @param e + */ + handleScroll(e) { + if (!this._(".right-paddle") || !this._(".left-paddle")) + return; + let horizontal = e.currentTarget.scrollLeft; + let scrollWidth = e.currentTarget.scrollWidth - e.currentTarget.clientWidth; //e.currentTarget.scrollLeftMax isn't support except firefox + if(horizontal > 0) { + this._(".left-paddle").classList.remove("hidden"); + } + if (horizontal < scrollWidth) { + this._(".right-paddle").classList.remove("hidden"); + } + + if (horizontal >= scrollWidth) { + this._(".right-paddle").classList.add("hidden"); + } + + if (horizontal <= 0) { + this._(".left-paddle").classList.add("hidden"); + } + } + + /** + * Scrolls smooth to the maximum right of an given element + * + * @param element + */ + handleScrollRight(element) { + const maxwidth = element.scrollWidth - element.clientWidth; + let container = element; + let scrollAmount = 0; + let slideTimer = setInterval(function(){ + container.scrollLeft += 10; + scrollAmount += 10; + if(scrollAmount >= maxwidth){ + window.clearInterval(slideTimer); + } + }, 25); + } + + /** + * Scrolls smooth to the min left of an given element + * + * @param element + */ + handleScrollLeft(element) { + const minwidth = 0; + let container = element; + let scrollAmount = element.scrollWidth - element.clientWidth;; + let slideTimer = setInterval(function(){ + container.scrollLeft -= 10; + scrollAmount -= 10; + if(scrollAmount <= minwidth){ + window.clearInterval(slideTimer); + } + }, 25); + } + +} \ No newline at end of file diff --git a/packages/file-handling/src/file-sink.js b/packages/file-handling/src/file-sink.js index 16b8631639850a96eef0169b21e093ae6af6db07..b71f6b2c711cc7ae7c02b025cad74ee3f3d13003 100644 --- a/packages/file-handling/src/file-sink.js +++ b/packages/file-handling/src/file-sink.js @@ -12,12 +12,13 @@ import MicroModal from "./micromodal.es"; import * as fileHandlingStyles from './styles'; import { send } from '@dbp-toolkit/common/notification'; import {Clipboard} from "@dbp-toolkit/file-handling/src/clipboard"; +import DbpFileHandlingLitElement from "./dbp-file-handling-lit-element"; /** * FileSink web component */ -export class FileSink extends ScopedElementsMixin(DBPLitElement) { +export class FileSink extends ScopedElementsMixin(DbpFileHandlingLitElement) { constructor() { super(); this.context = ''; @@ -78,8 +79,12 @@ export class FileSink extends ScopedElementsMixin(DBPLitElement) { connectedCallback() { super.connectedCallback(); - this.updateComplete.then(() => { + this._('nav.modal-nav').addEventListener("scroll", this.handleScroll.bind(this)); + + this._('.right-paddle').addEventListener("click", this.handleScrollRight.bind(this, this._('nav.modal-nav'))); + + this._('.left-paddle').addEventListener("click", this.handleScrollLeft.bind(this, this._('nav.modal-nav'))); }); } @@ -330,6 +335,48 @@ export class FileSink extends ScopedElementsMixin(DBPLitElement) { width: 100%; height: 100%; } + + .paddle { + position: absolute; + background-color: #ffffffd1; + top: 0px; + padding: 0px 5px; + box-sizing: content-box; + height: 100%; + } + + .right-paddle{ + right: 0px; + } + + .left-paddle{ + left: 0px; + } + + .nav-wrapper{ + position: relative; + display: block; + overflow-x: auto; + border:none; + } + + .paddles{ + display: none; + } + + .modal-nav{ + height: 100%; + } + + @media only screen + and (orientation: portrait) + and (max-width: 768px) { + + .paddles{ + display: inherit; + } + + } `; @@ -342,26 +389,33 @@ export class FileSink extends ScopedElementsMixin(DBPLitElement) { <div class="modal micromodal-slide" id="modal-picker" aria-hidden="true"> <div class="modal-overlay" tabindex="-1"> <div class="modal-container ${classMap({"modal-container-full-size": this.fullsizeModal})}" role="dialog" aria-modal="true" aria-labelledby="modal-picker-title"> - <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> - <p>${i18n.t('file-source.nav-local')}</p> - </div> - <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> - <p> ${this.nextcloudName} </p> - </div> - <div title="${i18n.t('file-sink.clipboard')}" - @click="${() => { this.activeTarget = "clipboard"; }}" - class="${classMap({"active": this.activeTarget === "clipboard", hidden: (!this.hasEnabledDestination("clipboard")) })}"> - <dbp-icon class="nav-icon" name="clipboard"></dbp-icon> - <p>${i18n.t('file-sink.clipboard')}</p> + <div class="nav-wrapper modal-nav"> + <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> + <p>${i18n.t('file-source.nav-local')}</p> + </div> + <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> + <p> ${this.nextcloudName} </p> + </div> + <div title="${i18n.t('file-sink.clipboard')}" + @click="${() => { this.activeTarget = "clipboard"; }}" + class="${classMap({"active": this.activeTarget === "clipboard", hidden: (!this.hasEnabledDestination("clipboard")) })}"> + <dbp-icon class="nav-icon" name="clipboard"></dbp-icon> + <p>${i18n.t('file-sink.clipboard')}</p> + </div> + </nav> + <div class="paddles"> + <dbp-icon class="left-paddle paddle hidden" name="chevron-left" class="close-icon"></dbp-icon> + <dbp-icon class="right-paddle paddle" name="chevron-right" class="close-icon"></dbp-icon> </div> - </nav> + </div> + <div class="modal-header"> <button title="${i18n.t('file-sink.modal-close')}" class="modal-close" aria-label="Close modal" @click="${() => { this.closeDialog();}}"> <dbp-icon title="${i18n.t('file-sink.modal-close')}" name="close" class="close-icon"></dbp-icon> diff --git a/packages/file-handling/src/file-source.js b/packages/file-handling/src/file-source.js index 0a564b41eb71b7193f2913e6d9efafaf8d3b6a39..7992983c3a2ca3613b2dfe57634cf69f89446131 100644 --- a/packages/file-handling/src/file-source.js +++ b/packages/file-handling/src/file-source.js @@ -11,6 +11,7 @@ import {classMap} from 'lit-html/directives/class-map.js'; import MicroModal from './micromodal.es'; import * as fileHandlingStyles from './styles'; import {Clipboard} from "@dbp-toolkit/file-handling/src/clipboard"; +import DbpFileHandlingLitElement from "./dbp-file-handling-lit-element"; function mimeTypesToAccept(mimeTypes) { // Some operating systems can't handle mime types and @@ -33,7 +34,7 @@ function mimeTypesToAccept(mimeTypes) { /** * FileSource web component */ -export class FileSource extends ScopedElementsMixin(DBPLitElement) { +export class FileSource extends ScopedElementsMixin(DbpFileHandlingLitElement) { constructor() { super(); this.context = ''; @@ -139,6 +140,12 @@ export class FileSource extends ScopedElementsMixin(DBPLitElement) { }); this.dropArea.addEventListener('drop', this.handleDrop.bind(this), false); this._('#fileElem').addEventListener('change', this.handleChange.bind(this)); + + this._('nav.modal-nav').addEventListener("scroll", this.handleScroll.bind(this)); + + this._('.right-paddle').addEventListener("click", this.handleScrollRight.bind(this, this._('nav.modal-nav'))); + + this._('.left-paddle').addEventListener("click", this.handleScrollLeft.bind(this, this._('nav.modal-nav'))); }); } @@ -529,12 +536,49 @@ export class FileSource extends ScopedElementsMixin(DBPLitElement) { height: 100%; } + .paddle { + position: absolute; + background-color: #ffffffd1; + top: 0px; + padding: 0px 5px; + box-sizing: content-box; + height: 100%; + } + + .right-paddle{ + right: 0px; + } + + .left-paddle{ + left: 0px; + } + + .nav-wrapper{ + position: relative; + display: block; + overflow-x: auto; + border:none; + } + + .paddles{ + display: none; + } + + .modal-nav{ + height: 100%; + } + + @media only screen and (orientation: portrait) and (max-width: 768px) { #dropArea{ height: 100%; } + + .paddles{ + display: inherit; + } } `; @@ -557,27 +601,32 @@ export class FileSource extends ScopedElementsMixin(DBPLitElement) { <div class="modal micromodal-slide" id="modal-picker" aria-hidden="true"> <div class="modal-overlay" tabindex="-1" data-micromodal-close> <div class="modal-container" role="dialog" aria-modal="true" aria-labelledby="modal-picker-title"> - <nav class="modal-nav"> - <div title="${i18n.t('file-source.nav-local')}" - @click="${() => { this.activeTarget = "local"; }}" - class="${classMap({"active": this.activeTarget === "local", hidden: !this.hasEnabledSource("local")})}"> - <dbp-icon class="nav-icon" name="laptop"></dbp-icon> - <p>${i18n.t('file-source.nav-local')}</p> - </div> - <div title="Nextcloud" - @click="${() => { this.activeTarget = "nextcloud";}}" - class="${classMap({"active": this.activeTarget === "nextcloud", hidden: !this.hasEnabledSource("nextcloud") || this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"> - <dbp-icon class="nav-icon" name="cloud"></dbp-icon> - <p> ${this.nextcloudName} </p> - </div> - <div title="${i18n.t('file-source.clipboard')}" - @click="${() => { this.activeTarget = "clipboard"; }}" - class="${classMap({"active": this.activeTarget === "clipboard", hidden: !this.hasEnabledSource("clipboard") })}"> - <dbp-icon class="nav-icon" name="clipboard"></dbp-icon> - <p>${i18n.t('file-source.clipboard')}</p> + <div class="nav-wrapper modal-nav"> + <nav class="modal-nav"> + <div title="${i18n.t('file-source.nav-local')}" + @click="${() => { this.activeTarget = "local"; }}" + class="${classMap({"active": this.activeTarget === "local", hidden: !this.hasEnabledSource("local")})}"> + <dbp-icon class="nav-icon" name="laptop"></dbp-icon> + <p>${i18n.t('file-source.nav-local')}</p> + </div> + <div title="Nextcloud" + @click="${() => { this.activeTarget = "nextcloud";}}" + class="${classMap({"active": this.activeTarget === "nextcloud", hidden: !this.hasEnabledSource("nextcloud") || this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}"> + <dbp-icon class="nav-icon" name="cloud"></dbp-icon> + <p> ${this.nextcloudName} </p> + </div> + <div title="${i18n.t('file-source.clipboard')}" + @click="${() => { this.activeTarget = "clipboard"; }}" + class="${classMap({"active": this.activeTarget === "clipboard", hidden: !this.hasEnabledSource("clipboard") })}"> + <dbp-icon class="nav-icon" name="clipboard"></dbp-icon> + <p>${i18n.t('file-source.clipboard')}</p> + </div> + </nav> + <div class="paddles"> + <dbp-icon class="left-paddle paddle hidden" name="chevron-left" class="close-icon"></dbp-icon> + <dbp-icon class="right-paddle paddle" name="chevron-right" class="close-icon"></dbp-icon> </div> - - </nav> + </div> <div class="modal-header"> <button title="${i18n.t('file-source.modal-close')}" class="modal-close" aria-label="Close modal" @click="${() => {this.closeDialog();}}"> <dbp-icon name="close" class="close-icon"></dbp-icon> diff --git a/packages/file-handling/src/i18n/de/translation.json b/packages/file-handling/src/i18n/de/translation.json index ee20bbccc760c9497e2130721f36ddae93c54df5..62374158320ed90e1d1513a4b853249f82e326bf 100644 --- a/packages/file-handling/src/i18n/de/translation.json +++ b/packages/file-handling/src/i18n/de/translation.json @@ -84,7 +84,8 @@ "select-nothing": "Nichts auswählen", "select-nothing-title": "Alle gewählten Dateien nicht mehr selektieren", "abort": "Vorgang abbrechen", - "abort-message": "Vorgang wurde abgebrochen." + "abort-message": "Vorgang wurde abgebrochen.", + "remember-me": "Angemeldet bleiben" }, "clipboard": { "add-files": "Dateien der Zwischenablage hinzufügen", diff --git a/packages/file-handling/src/i18n/en/translation.json b/packages/file-handling/src/i18n/en/translation.json index 7639e448011b5881359a41d77d155f99ff951800..f3f1bb29246f37809a8d3a47bbb5a5e35ad7c926 100644 --- a/packages/file-handling/src/i18n/en/translation.json +++ b/packages/file-handling/src/i18n/en/translation.json @@ -98,7 +98,8 @@ "select-nothing": "Select none", "select-nothing-title": "Select no files", "abort": "Cancel process", - "abort-message": "The process was canceled." + "abort-message": "The process was canceled.", + "remember-me": "Remember me" }, "clipboard": { "add-files": "Add files to clipboard", diff --git a/packages/file-handling/src/nextcloud-file-picker.js b/packages/file-handling/src/nextcloud-file-picker.js index c8b2c88691b9d27d8fe51dc091f9d14371984b7d..46c3ecb4d30521a712fe0d9bdd280f33b272c82a 100644 --- a/packages/file-handling/src/nextcloud-file-picker.js +++ b/packages/file-handling/src/nextcloud-file-picker.js @@ -347,8 +347,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { password: sessionStorage.getItem("nextcloud-webdav-password") } ); - console.log("check"); - this.loadDirectory(this.directoryPath); } @@ -391,7 +389,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { } onReceiveWindowMessage(event) { - console.log("hui"); if (this.webDavClient === null) { const data = event.data; @@ -399,7 +396,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { if (this.loginWindow !== null) { this.loginWindow.close(); } - console.log("lala"); // see https://github.com/perry-mitchell/webdav-client/blob/master/API.md#module_WebDAV.createClient this.webDavClient = createClient( @@ -409,7 +405,6 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { password: data.token } ); - console.log("tada"); if (this._("#remember-checkbox") && this._("#remember-checkbox").checked) { sessionStorage.setItem('nextcloud-webdav-username', data.loginName); @@ -1630,7 +1625,7 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { </div> <div class="block text-center m-inherit ${classMap({hidden: this.isPickerActive})}"> <label class="button-container remember-container"> - Remember me + ${i18n.t('nextcloud-file-picker.remember-me')} <input type="checkbox" id="remember-checkbox" name="remember"> <span class="checkmark"></span> </label> diff --git a/packages/file-handling/src/styles.js b/packages/file-handling/src/styles.js index 3f7bcd14d060db8fe104e58e1a8ee046652dcf3e..180643c959c5acc62be18f274f341338304c64d0 100644 --- a/packages/file-handling/src/styles.js +++ b/packages/file-handling/src/styles.js @@ -211,7 +211,7 @@ export function getFileHandlingCss() { } .tabulator .tabulator-tableHolder { - height: unset !important; /*TODO find a better way to do this*/ + /* height: unset !important; /*TODO find a better way to do this*/ } .tabulator-row .tabulator-responsive-collapse{ @@ -226,6 +226,15 @@ export function getFileHandlingCss() { font-size: 1.3em; margin-top: -8px; } + + .tabulator-responsive-collapse-toggle-open, .tabulator-responsive-collapse-toggle-close{ + width: 100%; + height: 100%; + } + + .tabulator-row-handle{ + padding: 0px !important; + } @media only screen and (orientation: portrait)