diff --git a/packages/common/dbp-lit-element.js b/packages/common/dbp-lit-element.js index 5b0af19e314548d0e903d3c81b050242e4492377..2112ab566c72fa4b7bcd80818022b1b22258e3b3 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 d352f07f8e7ebbe1b220dfb0f504bb22f9bdf541..23506dd408573ccfb2b70f24c2fc86dbc7b906f5 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 adae346b932e3105128146e7ee739639f6602012..e9a48d19748ccb3887390e5be70d7a4aeea9652a 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 9c7bf2d80cafb2829a36ce1200d3208f90ac046d..e1e2376b5c8c61a74d9ba85cbb134a040356806d 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}"