Merge pull request #1192 from umbraco/bugfix/modals

Bugfix/modals
This commit is contained in:
Jacob Overgaard
2024-02-06 16:50:08 +01:00
committed by GitHub
2 changed files with 43 additions and 21 deletions

View File

@@ -1,13 +1,8 @@
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { CSSResultGroup} from '@umbraco-cms/backoffice/external/lit';
import { css, html, repeat, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type {
UmbModalManagerContext,
UmbModalContext} from '@umbraco-cms/backoffice/modal';
import {
UMB_MODAL_MANAGER_CONTEXT,
UmbModalElement
} from '@umbraco-cms/backoffice/modal';
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
import { css, html, repeat, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit';
import type { UmbModalManagerContext, UmbModalContext } from '@umbraco-cms/backoffice/modal';
import { UMB_MODAL_MANAGER_CONTEXT, UmbModalElement } from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@customElement('umb-backoffice-modal-container')
@@ -24,6 +19,7 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
super();
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => {
//TODO: This is being called way to many times if first page load includes an open modal.
this._modalManager = instance;
this._observeModals();
});
@@ -31,14 +27,24 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
private _observeModals() {
if (!this._modalManager) return;
this.observe(this._modalManager.modals, (modals) => this.#createModalElements(modals));
this.observe(this._modalManager.modals, (modals) => {
this.#createModalElements(modals);
});
}
/** We cannot render the umb-modal element directly in the uui-modal-container because it wont get recognized by UUI.
* We therefore have a helper class which creates the uui-modal element and returns it. */
#createModalElements(modals: Array<UmbModalContext>) {
const oldValue = this._modals;
this._modals = modals;
const oldModals = oldValue.filter((oldModal) => !modals.some((modal) => modal.key === oldModal.key));
oldModals.forEach((modal) => {
this._modalElementMap.get(modal.key)?.removeEventListener('close-end', this.#onCloseEnd.bind(this, modal.key));
this._modalElementMap.delete(modal.key);
});
if (this._modals.length === 0) {
this._modalElementMap.clear();
return;
@@ -50,15 +56,21 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
const modalElement = new UmbModalElement();
modalElement.modalContext = modal;
modalElement.element?.addEventListener('close-end', () => this._modalManager?.remove(modal.key));
modalElement.element?.addEventListener('close-end', this.#onCloseEnd.bind(this, modal.key));
this._modalElementMap.set(modal.key, modalElement);
this.requestUpdate();
});
}
#onCloseEnd(key: string) {
this._modalManager?.remove(key);
}
#renderModal(key: string) {
const modalElement = this._modalElementMap.get(key);
if (!modalElement) return;
if (!modalElement) return nothing;
return modalElement.render();
}

View File

@@ -1,22 +1,23 @@
import type { UmbModalContext } from './modal.context.js';
import { UMB_MODAL_CONTEXT } from './modal.context.js';
import type { ManifestModal} from '@umbraco-cms/backoffice/extension-registry';
import type { ManifestModal } from '@umbraco-cms/backoffice/extension-registry';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import type { CSSResultGroup} from '@umbraco-cms/backoffice/external/lit';
import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit';
import { html, customElement } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { BehaviorSubject } from '@umbraco-cms/backoffice/external/rxjs';
import type { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import type { UUIDialogElement, UUIModalDialogElement, UUIModalSidebarElement } from '@umbraco-cms/backoffice/external/uui';
import {
UUIModalCloseEvent,
type UUIDialogElement,
type UUIModalDialogElement,
type UUIModalSidebarElement,
} from '@umbraco-cms/backoffice/external/uui';
import type { UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
import type {
UmbContextRequestEvent} from '@umbraco-cms/backoffice/context-api';
import {
UMB_CONTENT_REQUEST_EVENT_TYPE,
UmbContextProvider
} from '@umbraco-cms/backoffice/context-api';
import type { UmbContextRequestEvent } from '@umbraco-cms/backoffice/context-api';
import { UMB_CONTENT_REQUEST_EVENT_TYPE, UmbContextProvider } from '@umbraco-cms/backoffice/context-api';
@customElement('umb-modal')
export class UmbModalElement extends UmbLitElement {
@@ -42,10 +43,19 @@ export class UmbModalElement extends UmbLitElement {
#modalExtensionObserver?: UmbObserverController<ManifestModal | undefined>;
#modalRouterElement: UmbRouterSlotElement = document.createElement('umb-router-slot');
#onClose = () => {
this.element?.removeEventListener(UUIModalCloseEvent, this.#onClose);
this.#modalContext?.reject({ type: 'close' });
};
#createModalElement() {
if (!this.#modalContext) return;
this.element = this.#createContainerElement();
// Makes sure that the modal triggers the reject of the context promise when it is closed by pressing escape.
this.element.addEventListener(UUIModalCloseEvent, this.#onClose);
if (this.#modalContext.originTarget) {
// The following code is the context api proxy.
// It re-dispatches the context api request event to the origin target of this modal, in other words the element that initiated the modal.