introduce modal tokens
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
export * from './modal.context';
|
||||
export * from './modal-handler';
|
||||
export * from './layouts/modal-layout.element';
|
||||
export * from './token/modal-token';
|
||||
|
||||
@@ -3,7 +3,8 @@ import type { UUIModalDialogElement } from '@umbraco-ui/uui-modal-dialog';
|
||||
import type { UUIModalSidebarElement, UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { UmbModalOptions } from './modal.context';
|
||||
import { UmbModalConfig, UmbModalType } from './modal.context';
|
||||
import { UmbModalToken } from './token/modal-token';
|
||||
import { createExtensionElement, umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
import { UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
@@ -21,15 +22,25 @@ export class UmbModalHandler {
|
||||
public readonly element = this.#element.asObservable();
|
||||
|
||||
public key: string;
|
||||
public type: string;
|
||||
public size: UUIModalSidebarSize;
|
||||
public type: UmbModalType = 'dialog';
|
||||
public size: UUIModalSidebarSize = 'small';
|
||||
|
||||
constructor(host: UmbControllerHostInterface, modalAlias: string, options?: UmbModalOptions<unknown>) {
|
||||
constructor(
|
||||
host: UmbControllerHostInterface,
|
||||
modalAlias: string | UmbModalToken,
|
||||
data: unknown,
|
||||
config?: UmbModalConfig
|
||||
) {
|
||||
this.#host = host;
|
||||
this.key = uuidv4();
|
||||
|
||||
this.type = options?.type || 'dialog';
|
||||
this.size = options?.size || 'small';
|
||||
if (modalAlias instanceof UmbModalToken) {
|
||||
this.type = modalAlias.getDefaultConfig().type || this.type;
|
||||
this.size = modalAlias.getDefaultConfig().size || this.size;
|
||||
}
|
||||
|
||||
this.type = config?.type || this.type;
|
||||
this.size = config?.size || this.size;
|
||||
|
||||
// TODO: Consider if its right to use Promises, or use another event based system? Would we need to be able to cancel an event, to then prevent the closing..?
|
||||
this._closePromise = new Promise((resolve) => {
|
||||
@@ -37,7 +48,7 @@ export class UmbModalHandler {
|
||||
});
|
||||
|
||||
this.containerElement = this.#createContainerElement();
|
||||
this.#observeModal(modalAlias, options?.data);
|
||||
this.#observeModal(modalAlias.toString(), data);
|
||||
}
|
||||
|
||||
#createContainerElement() {
|
||||
|
||||
@@ -13,26 +13,26 @@ import './layouts/search/modal-layout-search.element.ts';
|
||||
import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import type { UUIModalDialogElement } from '@umbraco-ui/uui-modal-dialog';
|
||||
import type { UmbModalDocumentPickerData } from '../../src/backoffice/documents/documents/modals/document-picker';
|
||||
import { UmbModalChangePasswordData } from './layouts/modal-layout-change-password.element';
|
||||
import type { UmbModalIconPickerData } from './layouts/icon-picker/modal-layout-icon-picker.element';
|
||||
import type { UmbModalConfirmData } from './layouts/confirm/modal-layout-confirm.element';
|
||||
import type { UmbModalContentPickerData } from '../../src/backoffice/documents/documents/modals/document-picker/document-picker-modal.element';
|
||||
import type { UmbModalPropertyEditorUIPickerData } from './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element';
|
||||
import type { UmbModalMediaPickerData } from './layouts/media-picker/modal-layout-media-picker.element';
|
||||
import type { UmbModalLinkPickerData } from './layouts/link-picker/modal-layout-link-picker.element';
|
||||
import { UmbModalHandler } from './modal-handler';
|
||||
import type { UmbBasicModalData } from './layouts/basic/modal-layout-basic.element';
|
||||
import { UmbPickerModalData } from './layouts/modal-layout-picker-base';
|
||||
import { UmbModalToken } from './token/modal-token';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { LanguageModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
export type UmbModalType = 'dialog' | 'sidebar';
|
||||
|
||||
export interface UmbModalOptions<UmbModalData> {
|
||||
export interface UmbModalConfig {
|
||||
type?: UmbModalType;
|
||||
size?: UUIModalSidebarSize;
|
||||
data?: UmbModalData;
|
||||
}
|
||||
|
||||
// TODO: we should find a way to easily open a modal without adding custom methods to this context. It would result in a better separation of concerns.
|
||||
@@ -61,11 +61,11 @@ export class UmbModalContext {
|
||||
/**
|
||||
* Opens a Content Picker sidebar modal
|
||||
* @public
|
||||
* @param {UmbModalContentPickerData} [data]
|
||||
* @param {UmbModalDocumentPickerData} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public documentPicker(data?: UmbModalContentPickerData): UmbModalHandler {
|
||||
public documentPicker(data?: UmbModalDocumentPickerData): UmbModalHandler {
|
||||
return this.open('umb-document-picker-modal', { data, type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
@@ -204,8 +204,8 @@ export class UmbModalContext {
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public open(modalAlias: string, options?: UmbModalOptions<unknown>): UmbModalHandler {
|
||||
const modalHandler = new UmbModalHandler(this.host, modalAlias, options);
|
||||
public open<T = unknown>(modalAlias: string | UmbModalToken<T>, data: T, config?: UmbModalConfig): UmbModalHandler {
|
||||
const modalHandler = new UmbModalHandler(this.host, modalAlias, data, config);
|
||||
|
||||
modalHandler.containerElement.addEventListener('close-end', () => this.#onCloseEnd(modalHandler));
|
||||
|
||||
|
||||
37
src/Umbraco.Web.UI.Client/libs/modal/token/modal-token.ts
Normal file
37
src/Umbraco.Web.UI.Client/libs/modal/token/modal-token.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { UmbModalConfig } from '../modal.context';
|
||||
|
||||
export class UmbModalToken<T = unknown> {
|
||||
/**
|
||||
* Get the type of the token
|
||||
*
|
||||
* @public
|
||||
* @type {T}
|
||||
* @memberOf UmbModalToken
|
||||
* @example `typeof MyToken.TYPE`
|
||||
* @returns undefined
|
||||
*/
|
||||
readonly TYPE: T = undefined as never;
|
||||
|
||||
/**
|
||||
* @param alias Unique identifier for the token,
|
||||
* @param defaultConfig Default configuration for the modal,
|
||||
* @param _desc Description for the token,
|
||||
* used only for debugging purposes,
|
||||
* it should but does not need to be unique
|
||||
*/
|
||||
constructor(protected alias: string, protected defaultConfig: UmbModalConfig, protected _desc?: string) {}
|
||||
|
||||
/**
|
||||
* This method must always return the unique alias of the token since that
|
||||
* will be used to look up the token in the injector.
|
||||
*
|
||||
* @returns the unique alias of the token
|
||||
*/
|
||||
toString(): string {
|
||||
return this.alias;
|
||||
}
|
||||
|
||||
public getDefaultConfig(): UmbModalConfig {
|
||||
return this.defaultConfig;
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,12 @@ import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbModalLayoutElement } from '../../../../../../libs/modal/layouts/modal-layout.element';
|
||||
import { UmbModalDocumentPickerData } from '.';
|
||||
import type { UmbTreeElement } from 'src/backoffice/shared/components/tree/tree.element';
|
||||
|
||||
export interface UmbModalContentPickerData {
|
||||
multiple?: boolean;
|
||||
selection?: Array<string>;
|
||||
}
|
||||
|
||||
// TODO: make use of UmbPickerLayoutBase
|
||||
@customElement('umb-document-picker-modal')
|
||||
export class UmbDocumentPickerModalElement extends UmbModalLayoutElement<UmbModalContentPickerData> {
|
||||
export class UmbDocumentPickerModalElement extends UmbModalLayoutElement<UmbModalDocumentPickerData> {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
|
||||
@@ -4,7 +4,8 @@ import './document-picker-modal.element';
|
||||
import { Meta, Story } from '@storybook/web-components';
|
||||
import { html } from 'lit';
|
||||
|
||||
import type { UmbDocumentPickerModalElement, UmbModalContentPickerData } from './document-picker-modal.element';
|
||||
import type { UmbDocumentPickerModalElement } from './document-picker-modal.element';
|
||||
import type { UmbModalDocumentPickerData } from './index';
|
||||
|
||||
export default {
|
||||
title: 'API/Modals/Layouts/Content Picker',
|
||||
@@ -12,7 +13,7 @@ export default {
|
||||
id: 'umb-document-picker-modal',
|
||||
} as Meta;
|
||||
|
||||
const data: UmbModalContentPickerData = {
|
||||
const data: UmbModalDocumentPickerData = {
|
||||
multiple: true,
|
||||
selection: [],
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { UmbModalToken } from 'libs/modal';
|
||||
|
||||
export interface UmbModalDocumentPickerData {
|
||||
multiple?: boolean;
|
||||
selection?: Array<string>;
|
||||
}
|
||||
|
||||
export interface UmbModalDocumentPickerResponse {
|
||||
selection: Array<string>;
|
||||
}
|
||||
|
||||
export const UMB_DOCUMENT_PICKER_MODAL_TOKEN = new UmbModalToken<UmbModalDocumentPickerData>(
|
||||
'Umb.Modal.DocumentPicker',
|
||||
{
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
}
|
||||
);
|
||||
@@ -9,6 +9,7 @@ import type { UmbDocumentTreeStore } from '../../../documents/documents/reposito
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import type { DocumentTreeItemModel, FolderTreeItemModel } from '@umbraco-cms/backend-api';
|
||||
import type { UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
import { UMB_DOCUMENT_PICKER_MODAL_TOKEN } from 'src/backoffice/documents/documents/modals/document-picker';
|
||||
|
||||
@customElement('umb-input-document-picker')
|
||||
export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElement) {
|
||||
@@ -121,13 +122,9 @@ export class UmbInputDocumentPickerElement extends FormControlMixin(UmbLitElemen
|
||||
|
||||
private _openPicker() {
|
||||
// We send a shallow copy(good enough as its just an array of keys) of our this._selectedKeys, as we don't want the modal to manipulate our data:
|
||||
const modalHandler = this._modalContext?.open('Umb.Modal.DocumentPicker', {
|
||||
data: {
|
||||
multiple: this.max === 1 ? false : true,
|
||||
selection: [...this._selectedKeys],
|
||||
},
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
const modalHandler = this._modalContext?.open(UMB_DOCUMENT_PICKER_MODAL_TOKEN, {
|
||||
multiple: this.max === 1 ? false : true,
|
||||
selection: [...this._selectedKeys],
|
||||
});
|
||||
|
||||
modalHandler?.onClose().then(({ selection }: any) => {
|
||||
|
||||
Reference in New Issue
Block a user