register property settings modal
This commit is contained in:
@@ -25,6 +25,12 @@ const modals: Array<ManifestModal> = [
|
||||
name: 'Link Picker Modal',
|
||||
loader: () => import('./link-picker/link-picker-modal.element'),
|
||||
},
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.PropertySettings',
|
||||
name: 'Property Settings Modal',
|
||||
loader: () => import('./property-settings/property-settings-modal.element'),
|
||||
},
|
||||
{
|
||||
type: 'modal',
|
||||
alias: 'Umb.Modal.SectionPicker',
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { UmbModalToken } from 'libs/modal';
|
||||
|
||||
// TODO: add interface for data
|
||||
// PropertyTypeViewModelBaseModel
|
||||
|
||||
export const UMB_PROPERTY_SETTINGS_MODAL_TOKEN = new UmbModalToken('Umb.Modal.PropertySettings', {
|
||||
type: 'sidebar',
|
||||
size: 'small',
|
||||
});
|
||||
@@ -3,11 +3,12 @@ import { UUITextStyles } from '@umbraco-ui/uui-css';
|
||||
import { css, html, nothing } from 'lit';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { UmbModalContext, UmbModalLayoutElement, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal';
|
||||
import { UMB_PROPERTY_EDITOR_UI_PICKER_MODAL_TOKEN } from '../../property-editors/modals/property-editor-ui-picker';
|
||||
import { ManifestPropertyEditorUI } from '@umbraco-cms/extensions-registry';
|
||||
import { umbExtensionsRegistry } from '@umbraco-cms/extensions-api';
|
||||
|
||||
@customElement('umb-modal-layout-property-settings')
|
||||
export class UmbModalLayoutPropertySettingsElement extends UmbModalLayoutElement {
|
||||
@customElement('umb-property-settings-modal')
|
||||
export class UmbPropertySettingsModalElement extends UmbModalLayoutElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
@@ -229,6 +230,7 @@ export class UmbModalLayoutPropertySettingsElement extends UmbModalLayoutElement
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move this to a helper so we can reuse it across the app
|
||||
#generateAlias(text: string) {
|
||||
//replace all spaces characters with a dash and remove all non-alphanumeric characters, except underscore. Allow a maximum of 1 dashes or underscores in a row.
|
||||
return text
|
||||
@@ -257,7 +259,7 @@ export class UmbModalLayoutPropertySettingsElement extends UmbModalLayoutElement
|
||||
}
|
||||
|
||||
#onOpenPropertyEditorUIPicker() {
|
||||
const modalHandler = this.#modalContext?.propertyEditorUIPicker({
|
||||
const modalHandler = this.#modalContext?.open(UMB_PROPERTY_EDITOR_UI_PICKER_MODAL_TOKEN, {
|
||||
selection: [],
|
||||
});
|
||||
|
||||
@@ -423,8 +425,10 @@ export class UmbModalLayoutPropertySettingsElement extends UmbModalLayoutElement
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbPropertySettingsModalElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-modal-layout-property-settings': UmbModalLayoutPropertySettingsElement;
|
||||
'umb-property-settings-modal': UmbPropertySettingsModalElement;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css';
|
||||
import { css, html } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/modal';
|
||||
import { UMB_PROPERTY_SETTINGS_MODAL_TOKEN } from '../modals/property-settings';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
@customElement('umb-property-creator')
|
||||
export class UmbPropertyCreatorElement extends UmbLitElement {
|
||||
@@ -17,13 +18,11 @@ export class UmbPropertyCreatorElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
#onAddProperty() {
|
||||
const modalHandler = this.#modalContext?.propertySettings();
|
||||
const modalHandler = this.#modalContext?.open(UMB_PROPERTY_SETTINGS_MODAL_TOKEN);
|
||||
|
||||
if (modalHandler) {
|
||||
modalHandler.onClose().then((result) => {
|
||||
console.log('result', result);
|
||||
});
|
||||
}
|
||||
modalHandler?.onClose().then((result) => {
|
||||
console.log('result', result);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
import type { UUIDialogElement } from '@umbraco-ui/uui';
|
||||
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 { UmbModalOptions } from './modal.context';
|
||||
|
||||
//TODO consider splitting this into two separate handlers
|
||||
export class UmbModalHandler {
|
||||
private _closeResolver: any;
|
||||
private _closePromise: any;
|
||||
|
||||
public element: UUIModalDialogElement | UUIModalSidebarElement;
|
||||
public key: string;
|
||||
public type: string;
|
||||
public size: UUIModalSidebarSize;
|
||||
|
||||
constructor(element: string | HTMLElement, options?: UmbModalOptions<unknown>) {
|
||||
this.key = uuidv4();
|
||||
|
||||
this.type = options?.type || 'dialog';
|
||||
this.size = options?.size || 'small';
|
||||
this.element = this._createElement(element, options);
|
||||
|
||||
// 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) => {
|
||||
this._closeResolver = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
private _createElement(element: string | HTMLElement, options?: UmbModalOptions<unknown>) {
|
||||
const layoutElement = this._createInsideElement(element, options?.data);
|
||||
return this.type === 'sidebar'
|
||||
? this._createSidebarElement(layoutElement)
|
||||
: this._createDialogElement(layoutElement);
|
||||
}
|
||||
|
||||
private _createSidebarElement(insideElement: HTMLElement) {
|
||||
const sidebarElement = document.createElement('uui-modal-sidebar');
|
||||
sidebarElement.appendChild(insideElement);
|
||||
sidebarElement.size = this.size;
|
||||
return sidebarElement;
|
||||
}
|
||||
|
||||
private _createDialogElement(insideElement: HTMLElement) {
|
||||
const modalDialogElement = document.createElement('uui-modal-dialog');
|
||||
const dialogElement: UUIDialogElement = document.createElement('uui-dialog');
|
||||
modalDialogElement.appendChild(dialogElement);
|
||||
dialogElement.appendChild(insideElement);
|
||||
return modalDialogElement;
|
||||
}
|
||||
|
||||
private _createInsideElement(element: string | HTMLElement, data: unknown) {
|
||||
const insideElement: any = element instanceof HTMLElement ? element : document.createElement(element);
|
||||
insideElement.data = data;
|
||||
insideElement.modalHandler = this;
|
||||
return insideElement;
|
||||
}
|
||||
|
||||
public close(...args: any) {
|
||||
this._closeResolver(...args);
|
||||
this.element.close();
|
||||
}
|
||||
|
||||
public onClose(): Promise<any> {
|
||||
return this._closePromise;
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
// TODO: lazy load
|
||||
import './layouts/confirm/modal-layout-confirm.element';
|
||||
import './layouts/content-picker/modal-layout-content-picker.element';
|
||||
import './layouts/media-picker/modal-layout-media-picker.element';
|
||||
import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element';
|
||||
import './layouts/property-settings/modal-layout-property-settings.element';
|
||||
import './layouts/modal-layout-current-user.element';
|
||||
import './layouts/icon-picker/modal-layout-icon-picker.element';
|
||||
import '../../backoffice/settings/languages/language-picker/language-picker-modal-layout.element';
|
||||
import './layouts/link-picker/modal-layout-link-picker.element';
|
||||
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 { 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 './layouts/content-picker/modal-layout-content-picker.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 { UmbPickerModalData } from './layouts/modal-layout-picker-base';
|
||||
import { UmbContextToken } from '@umbraco-cms/context-api';
|
||||
import { LanguageModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
export type UmbModalType = 'dialog' | 'sidebar';
|
||||
|
||||
export interface UmbModalOptions<UmbModalData> {
|
||||
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.
|
||||
// TODO: move all layouts into their correct "silo" folders. User picker should live with users etc.
|
||||
export class UmbModalContext {
|
||||
// TODO: Investigate if we can get rid of HTML elements in our store, so we can use one of our states.
|
||||
#modals = new BehaviorSubject(<Array<UmbModalHandler>>[]);
|
||||
public readonly modals = this.#modals.asObservable();
|
||||
|
||||
/**
|
||||
* Opens a Confirm modal
|
||||
* @public
|
||||
* @param {UmbModalConfirmData} data
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public confirm(data: UmbModalConfirmData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-confirm', { data, type: 'dialog' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a Content Picker sidebar modal
|
||||
* @public
|
||||
* @param {UmbModalContentPickerData} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public contentPicker(data?: UmbModalContentPickerData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-content-picker', { data, type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a Media Picker sidebar modal
|
||||
* @public
|
||||
* @param {UmbModalMediaPickerData} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public mediaPicker(data?: UmbModalMediaPickerData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-media-picker', { data, type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a Property Editor UI sidebar modal
|
||||
* @public
|
||||
* @param {UmbModalPropertyEditorUIPickerData} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public propertyEditorUIPicker(data?: UmbModalPropertyEditorUIPickerData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-property-editor-ui-picker', { data, type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an Icon Picker sidebar modal
|
||||
* @public
|
||||
* @param {UmbModalIconPickerData} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public iconPicker(data?: UmbModalIconPickerData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-icon-picker', { data, type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an Link Picker sidebar modal
|
||||
* @public
|
||||
* @param {(LinkPickerData & LinkPickerConfig)} [data]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public linkPicker(data?: UmbModalLinkPickerData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-link-picker', {
|
||||
data,
|
||||
type: 'sidebar',
|
||||
size: data?.config?.overlaySize || 'small',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the user settings sidebar modal
|
||||
* @public
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public userSettings(): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-current-user', { type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the property settings sidebar modal
|
||||
* @public
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalService
|
||||
*/
|
||||
public propertySettings(): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-property-settings', { type: 'sidebar', size: 'small' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the user settings sidebar modal
|
||||
* @public
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public changePassword(data: UmbModalChangePasswordData): UmbModalHandler {
|
||||
return this.open('umb-modal-layout-change-password', { data, type: 'dialog' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a language picker sidebar modal
|
||||
* @public
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public languagePicker(data: UmbPickerModalData<LanguageModel>): UmbModalHandler {
|
||||
return this.open('umb-language-picker-modal-layout', { data, type: 'sidebar' });
|
||||
}
|
||||
|
||||
public search(): UmbModalHandler {
|
||||
const modalHandler = new UmbModalHandler('umb-modal-layout-search');
|
||||
|
||||
//TODO START: This is a hack to get the search modal layout to look like i want it to.
|
||||
//TODO: Remove from here to END when the modal system is more flexible
|
||||
const topDistance = '50%';
|
||||
const margin = '16px';
|
||||
const maxHeight = '600px';
|
||||
const maxWidth = '500px';
|
||||
const dialog = document.createElement('dialog') as HTMLDialogElement;
|
||||
dialog.style.top = `max(${margin}, calc(${topDistance} - ${maxHeight} / 2))`;
|
||||
dialog.style.margin = '0 auto';
|
||||
dialog.style.transform = `translateY(${-maxHeight})`;
|
||||
dialog.style.maxHeight = `min(${maxHeight}, calc(100% - ${margin}px * 2))`;
|
||||
dialog.style.width = `min(${maxWidth}, calc(100vw - ${margin}))`;
|
||||
dialog.style.boxSizing = 'border-box';
|
||||
dialog.style.background = 'none';
|
||||
dialog.style.border = 'none';
|
||||
dialog.style.padding = '0';
|
||||
dialog.style.boxShadow = 'var(--uui-shadow-depth-5)';
|
||||
dialog.style.borderRadius = '9px';
|
||||
const search = document.createElement('umb-modal-layout-search');
|
||||
dialog.appendChild(search);
|
||||
requestAnimationFrame(() => {
|
||||
dialog.showModal();
|
||||
});
|
||||
modalHandler.element = dialog as unknown as UUIModalDialogElement;
|
||||
//TODO END
|
||||
|
||||
modalHandler.element.addEventListener('close-end', () => this._handleCloseEnd(modalHandler));
|
||||
|
||||
this.#modals.next([...this.#modals.getValue(), modalHandler]);
|
||||
return modalHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a modal or sidebar modal
|
||||
* @public
|
||||
* @param {(string | HTMLElement)} element
|
||||
* @param {UmbModalOptions<unknown>} [options]
|
||||
* @return {*} {UmbModalHandler}
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
public open(element: string | HTMLElement, options?: UmbModalOptions<unknown>): UmbModalHandler {
|
||||
const modalHandler = new UmbModalHandler(element, options);
|
||||
|
||||
modalHandler.element.addEventListener('close-end', () => this._handleCloseEnd(modalHandler));
|
||||
|
||||
this.#modals.next([...this.#modals.getValue(), modalHandler]);
|
||||
return modalHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a modal or sidebar modal
|
||||
* @private
|
||||
* @param {string} key
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
private _close(key: string) {
|
||||
this.#modals.next(this.#modals.getValue().filter((modal) => modal.key !== key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the close-end event
|
||||
* @private
|
||||
* @param {UmbModalHandler} modalHandler
|
||||
* @memberof UmbModalContext
|
||||
*/
|
||||
private _handleCloseEnd(modalHandler: UmbModalHandler) {
|
||||
modalHandler.element.removeEventListener('close-end', () => this._handleCloseEnd(modalHandler));
|
||||
this._close(modalHandler.key);
|
||||
}
|
||||
}
|
||||
|
||||
export const UMB_MODAL_CONTEXT_TOKEN = new UmbContextToken<UmbModalContext>('UmbModalContext');
|
||||
Reference in New Issue
Block a user