From e3594e1de8d3ed44c88b2d7afa5316a91933a001 Mon Sep 17 00:00:00 2001 From: Patrizio Bekerle <patrizio@bekerle.com> Date: Tue, 22 Jun 2021 10:35:32 +0200 Subject: [PATCH] Allow globally overriding slots in the light dom of components and use it to override the auth-info slot in the Nextcloud file picker --- packages/common/dbp-lit-element.js | 85 ++++++++++++++++--- .../src/dbp-nextcloud-file-picker.js | 3 +- packages/file-handling/src/file-sink.js | 1 + packages/file-handling/src/file-source.js | 1 + 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/packages/common/dbp-lit-element.js b/packages/common/dbp-lit-element.js index 5b0af19e..2112ab56 100644 --- a/packages/common/dbp-lit-element.js +++ b/packages/common/dbp-lit-element.js @@ -1,30 +1,58 @@ import {AdapterLitElement} from "./src/adapter-lit-element"; export default class DBPLitElement extends AdapterLitElement { - _(selector) { - return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector); + constructor() { + super(); + this.htmlOverrides = ''; + } + + /** + * See: https://lit-element.polymer-project.org/guide/properties#initialize + */ + static get properties() { + return { + ...super.properties, + htmlOverrides: { type: String, attribute: 'html-overrides' }, + }; + } connectedCallback() { this.updateComplete.then(() => { - // transform all named template slots in the light DOM to named div slots - this.transformTemplateSlots(); + // transform all global override templates or named template slots in the light DOM to named div slots + this.transformSlots(); }); super.connectedCallback(); } + _(selector) { + return this.shadowRoot === null ? this.querySelector(selector) : this.shadowRoot.querySelector(selector); + } + + getTagName() { + const tagName = this.dataset ? (this.dataset.tagName || '') : ''; + + return tagName !== '' ? tagName : this.tagName.toLowerCase(); + } + /** - * Transforms all named template slots in the light DOM to named div slots + * Transforms all global override templates or named template slots in the light DOM to named div slots */ - transformTemplateSlots() { + transformSlots() { // query all named slots of the component const slots = this.shadowRoot.querySelectorAll("slot[name]"); + // if there are no slots we can exit + if (slots.length === 0) { + return; + } + slots.forEach((slot) => { - const name = slot.name; + const slotName = slot.name; + // search if there is a template with the name of the slot in the light DOM of the component - const templateElem = this.querySelector("template[slot=" + name + "]"); + const templateElem = this.querySelector("template[slot=" + slotName + "]"); if (!templateElem) { return; @@ -32,14 +60,51 @@ export default class DBPLitElement extends AdapterLitElement { // create a slot div container to put in the cloned template content const divElem = document.createElement('div'); - divElem.slot = name; + divElem.slot = slotName; divElem.appendChild(templateElem.content.cloneNode(true)); - // remove the old template with slot attribute + // remove the old template templateElem.remove(); // put the slot div container with the cloned template in the light DOM this.appendChild(divElem); }); + + // check if we have an "html-override" attribute set so we need to check for the global override template + if (this.htmlOverrides !== '') { + const globalOverrideTemplateElem = document.querySelector('template#' + this.htmlOverrides); + + if (globalOverrideTemplateElem) { + // we need to clone the element so we can access the content + const overrideTemplateElemClone = globalOverrideTemplateElem.content.cloneNode(true); + const tagName = this.getTagName(); + + // then we will look if there is an override for the current tag + const templateOverrideElem = overrideTemplateElemClone.querySelector('template#' + tagName); + + if (templateOverrideElem) { + // if there is an override we again need to clone that template so we can access the content + const templateOverrideElemClone = templateOverrideElem.content.cloneNode(true); + + // now we need to look for slots in the override + slots.forEach((slot) => { + const slotName = slot.name; + + // if a slot is found we need to remove the current slot in the light DOM + // so we are not showing the old and new content at the same time + if (templateOverrideElemClone.querySelector('[slot="' + slotName + '"]')) { + const currentSlotElement = this.querySelector('[slot="' + slotName + '"]'); + + if (currentSlotElement) { + currentSlotElement.remove(); + } + } + }); + + // append the cloned template to the light DOM + this.appendChild(templateOverrideElemClone); + } + } + } } } diff --git a/packages/file-handling/src/dbp-nextcloud-file-picker.js b/packages/file-handling/src/dbp-nextcloud-file-picker.js index d352f07f..23506dd4 100644 --- a/packages/file-handling/src/dbp-nextcloud-file-picker.js +++ b/packages/file-handling/src/dbp-nextcloud-file-picker.js @@ -1508,7 +1508,8 @@ export class NextcloudFilePicker extends ScopedElementsMixin(DBPLitElement) { </div> <div class="block text-center m-inherit ${classMap({hidden: this.isPickerActive})}"> <p class="m-inherit"><br> - ${i18n.t('nextcloud-file-picker.auth-info')}<br>${this.authInfo} + ${i18n.t('nextcloud-file-picker.auth-info')} + <slot name="auth-info"><br />${this.authInfo}</slot> </p> </div> </div> diff --git a/packages/file-handling/src/file-sink.js b/packages/file-handling/src/file-sink.js index adae346b..e9a48d19 100644 --- a/packages/file-handling/src/file-sink.js +++ b/packages/file-handling/src/file-sink.js @@ -268,6 +268,7 @@ export class FileSink extends ScopedElementsMixin(DBPLitElement) { select-button-text="${i18n.t('file-sink.select-directory')}" ?disabled="${this.disabled}" lang="${this.lang}" + subscribe="html-overrides" auth-url="${this.nextcloudAuthUrl}" web-dav-url="${this.nextcloudWebDavUrl}" nextcloud-name="${this.nextcloudName}" diff --git a/packages/file-handling/src/file-source.js b/packages/file-handling/src/file-source.js index 9c7bf2d8..e1e2376b 100644 --- a/packages/file-handling/src/file-source.js +++ b/packages/file-handling/src/file-source.js @@ -464,6 +464,7 @@ export class FileSource extends ScopedElementsMixin(DBPLitElement) { class="${classMap({hidden: this.nextcloudWebDavUrl === "" || this.nextcloudAuthUrl === ""})}" ?disabled="${this.disabled}" lang="${this.lang}" + subscribe="html-overrides" auth-url="${this.nextcloudAuthUrl}" web-dav-url="${this.nextcloudWebDavUrl}" nextcloud-name="${this.nextcloudName}" -- GitLab