From 4d67cfc8706acd4c18eb9142e22aea27f6357d83 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 16 Feb 2024 15:32:57 +0100 Subject: [PATCH] template page field modal beginning --- .../dictionary-item-picker-modal.token.ts | 1 + ...ction-view-column-configuration.element.ts | 1 + .../templating-item-menu.element.ts | 116 +++++++++--------- .../src/packages/templating/modals/index.ts | 1 + .../packages/templating/modals/manifests.ts | 6 + .../templating-item-picker-modal.element.ts | 70 +++++++---- .../templating-item-picker-modal.token.ts | 3 +- .../templating-page-field-builder/index.ts | 2 + ...lating-page-field-builder-modal.element.ts | 116 ++++++++++++++++++ ...mplating-page-field-builder-modal.token.ts | 17 +++ .../src/packages/templating/types.ts | 1 + 11 files changed, 247 insertions(+), 87 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/dictionary-item-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/dictionary-item-picker-modal.token.ts index 14c4f80d06..a537235eb5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/dictionary-item-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/token/dictionary-item-picker-modal.token.ts @@ -14,6 +14,7 @@ export const UMB_DICTIONARY_ITEM_PICKER_MODAL = new UmbModalToken< size: 'small', }, data: { + hideTreeRoot: true, treeAlias: 'Umb.Tree.Dictionary', }, }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/config/column-configuration/property-editor-ui-collection-view-column-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/config/column-configuration/property-editor-ui-collection-view-column-configuration.element.ts index 4625960edb..838f3fb4d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/config/column-configuration/property-editor-ui-collection-view-column-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/collection-view/config/column-configuration/property-editor-ui-collection-view-column-configuration.element.ts @@ -110,6 +110,7 @@ export class UmbPropertyEditorUICollectionViewColumnConfigurationElement } render() { + console.log(this.config); return html`
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/components/templating-item-menu/templating-item-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/components/templating-item-menu/templating-item-menu.element.ts index 59bb18f5b4..4ffa8cae20 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/components/templating-item-menu/templating-item-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/components/templating-item-menu/templating-item-menu.element.ts @@ -1,7 +1,5 @@ -import { - UMB_PARTIAL_VIEW_PICKER_MODAL, - type UmbPartialViewPickerModalValue, -} from '../../modals/partial-view-picker/partial-view-picker-modal.token.js'; +import { UMB_PARTIAL_VIEW_PICKER_MODAL } from '../../modals/partial-view-picker/partial-view-picker-modal.token.js'; +import { UMB_TEMPLATING_PAGE_FIELD_BUILDER_MODAL } from '../../modals/templating-page-field-builder/templating-page-field-builder-modal.token.js'; import { CodeSnippetType } from '../../types.js'; import { UMB_TEMPLATING_ITEM_PICKER_MODAL, @@ -11,11 +9,7 @@ import { getInsertDictionarySnippet, getInsertPartialSnippet } from '../../utils import { UmbDictionaryDetailRepository } from '@umbraco-cms/backoffice/dictionary'; import { customElement, property, css, html } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { - UmbDictionaryItemPickerModalValue, - UmbModalManagerContext, - UmbModalContext, -} from '@umbraco-cms/backoffice/modal'; +import type { UmbModalManagerContext, UmbModalContext } from '@umbraco-cms/backoffice/modal'; import { UMB_DICTIONARY_ITEM_PICKER_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -42,78 +36,82 @@ export class UmbTemplatingInsertMenuElement extends UmbLitElement { switch (type) { case CodeSnippetType.partialView: { - this.#getPartialViewSnippet(value as UmbPartialViewPickerModalValue); + this.value = getInsertPartialSnippet(value); + this.#dispatchInsertEvent(); break; } case CodeSnippetType.dictionaryItem: { - await this.#getDictionaryItemSnippet(value as UmbDictionaryItemPickerModalValue); + await this.#getDictionaryItemSnippet(value); + this.#dispatchInsertEvent(); + break; + } + case CodeSnippetType.pageField: { + this.value = value; this.#dispatchInsertEvent(); - break; } } } - #getDictionaryItemSnippet = async (modalValue: UmbDictionaryItemPickerModalValue) => { - const unique = modalValue.selection[0]; + async #getDictionaryItemSnippet(unique: string) { if (unique === null) return; const { data } = await this.#dictionaryDetailRepository.requestByUnique(unique); this.value = getInsertDictionarySnippet(data?.name ?? ''); - }; - - #getPartialViewSnippet = async (modalValue: UmbPartialViewPickerModalValue) => { - this.value = getInsertPartialSnippet(modalValue.selection?.[0] ?? ''); - }; - - #openChooseTypeModal = () => { - this.#openModal = this._modalContext?.open(UMB_TEMPLATING_ITEM_PICKER_MODAL, { - data: { - hidePartialViews: this.hidePartialView, - }, - }); - this.#openModal?.onSubmit().then((closedModal: UmbTemplatingItemPickerModalValue) => { - this.determineInsertValue(closedModal); - }); - }; - - #openInsertPageFieldSidebar() { - //this.#openModel = this._modalContext?.open(); } - #openInsertPartialViewSidebar() { - this.#openModal = this._modalContext?.open(UMB_PARTIAL_VIEW_PICKER_MODAL); - this.#openModal?.onSubmit().then((value) => { - this.#getPartialViewSnippet(value).then(() => { - this.#dispatchInsertEvent(); - }); - }); + async #openTemplatingItemPickerModal() { + const itemPickerContext = this._modalContext?.open(UMB_TEMPLATING_ITEM_PICKER_MODAL); + await itemPickerContext?.onSubmit(); + + const value = itemPickerContext?.getValue(); + if (!value) return; + + this.determineInsertValue(value); } - #openInsertDictionaryItemModal() { - this.#openModal = this._modalContext?.open(UMB_DICTIONARY_ITEM_PICKER_MODAL, { - data: { - hideTreeRoot: true, - pickableFilter: (item) => item.id !== null, - }, - }); - this.#openModal?.onSubmit().then((value) => { - this.#getDictionaryItemSnippet(value).then(() => { - this.#dispatchInsertEvent(); - }); - }); + async #openPartialViewPickerModal() { + const partialViewPickerContext = this._modalContext?.open(UMB_PARTIAL_VIEW_PICKER_MODAL); + await partialViewPickerContext?.onSubmit(); + + const path = partialViewPickerContext?.getValue().selection[0]; + if (!path) return; + + this.determineInsertValue({ type: CodeSnippetType.partialView, value: path }); + } + + async #openDictionaryItemPickerModal() { + const dictionaryItemPickerContext = this._modalContext?.open(UMB_DICTIONARY_ITEM_PICKER_MODAL); + await dictionaryItemPickerContext?.onSubmit(); + + const item = dictionaryItemPickerContext?.getValue().selection[0]; + if (!item) return; + + this.determineInsertValue({ type: CodeSnippetType.dictionaryItem, value: item }); + } + + async #openPageFieldBuilderModal() { + const pageFieldBuilderContext = this._modalContext?.open(UMB_TEMPLATING_PAGE_FIELD_BUILDER_MODAL); + await pageFieldBuilderContext?.onSubmit(); + + const output = pageFieldBuilderContext?.getValue().output; + if (!output) return; + + // The output is already built due to the preview in the modal. Can insert it directly now. + this.value = output; + this.#dispatchInsertEvent(); } #dispatchInsertEvent() { this.dispatchEvent(new CustomEvent('insert', { bubbles: false, cancelable: true, composed: false })); } - @property({ type: Boolean }) - hidePartialView = false; - render() { return html` - + ${this.localize.term('template_insert')} + @click=${this.#openPageFieldBuilderModal}> + @click=${this.#openPartialViewPickerModal}> + @click=${this.#openDictionaryItemPickerModal}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/index.ts index b95cabeeec..a3237a45c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/index.ts @@ -1,3 +1,4 @@ export * from './templating-section-picker/index.js'; export * from './templating-item-picker/index.js'; export * from './partial-view-picker/index.js'; +export * from './templating-page-field-builder/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/manifests.ts index fac1177afb..4270e4c145 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/manifests.ts @@ -13,6 +13,12 @@ const modals: Array = [ name: 'Templating Section Picker Modal', js: () => import('./templating-section-picker/templating-section-picker-modal.element.js'), }, + { + type: 'modal', + alias: 'Umb.Modal.TemplatingPageFieldBuilder', + name: 'Templating Page Field Builder Modal', + js: () => import('./templating-page-field-builder/templating-page-field-builder-modal.element.js'), + }, ]; export const manifests = [...modals]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.element.ts index 7450061be1..de6a71cf18 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.element.ts @@ -1,12 +1,13 @@ import { CodeSnippetType } from '../../types.js'; import { UMB_PARTIAL_VIEW_PICKER_MODAL } from '../partial-view-picker/partial-view-picker-modal.token.js'; +import { UMB_TEMPLATING_PAGE_FIELD_BUILDER_MODAL } from '../templating-page-field-builder/templating-page-field-builder-modal.token.js'; import type { UmbTemplatingItemPickerModalData, UmbTemplatingItemPickerModalValue, } from './templating-item-picker-modal.token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbModalManagerContext, UmbModalContext } from '@umbraco-cms/backoffice/modal'; +import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; import { UMB_MODAL_MANAGER_CONTEXT, UMB_DICTIONARY_ITEM_PICKER_MODAL, @@ -22,43 +23,58 @@ export class UmbTemplatingItemPickerModalElement extends UmbModalBaseElement< this.modalContext?.reject(); } - private _modalContext?: UmbModalManagerContext; + private _itemModalContext?: UmbModalManagerContext; constructor() { super(); this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { - this._modalContext = instance; + this._itemModalContext = instance; }); } - #openModal?: UmbModalContext; + async #openTemplatingPageFieldModal() { + const pageFieldBuilderContext = this._itemModalContext?.open(UMB_TEMPLATING_PAGE_FIELD_BUILDER_MODAL); + await pageFieldBuilderContext?.onSubmit(); - #openInsertPartialViewSidebar() { - this.#openModal = this._modalContext?.open(UMB_PARTIAL_VIEW_PICKER_MODAL); - this.#openModal?.onSubmit().then((partialViewPickerModalValue) => { - if (partialViewPickerModalValue) { - this.value = { - type: CodeSnippetType.partialView, - value: partialViewPickerModalValue.selection[0], - }; - this.modalContext?.submit(); - } - }); + const output = pageFieldBuilderContext?.getValue().output; + + if (output) { + this.value = { value: output, type: CodeSnippetType.pageField }; + this.modalContext?.submit(); + } } - #openInsertDictionaryItemModal() { - this.#openModal = this._modalContext?.open(UMB_DICTIONARY_ITEM_PICKER_MODAL, { + async #openPartialViewPickerModal() { + const partialViewPickerContext = this._itemModalContext?.open(UMB_PARTIAL_VIEW_PICKER_MODAL); + await partialViewPickerContext?.onSubmit(); + + const path = partialViewPickerContext?.getValue().selection[0]; + + if (path) { + const regex = /^%2F|%25dot%25cshtml$/g; + const prettyPath = path.replace(regex, '').replace(/%2F/g, '/'); + this.value = { + value: prettyPath, + type: CodeSnippetType.partialView, + }; + this.modalContext?.submit(); + } + } + + async #openDictionaryItemPickerModal() { + const dictionaryItemPickerModal = this._itemModalContext?.open(UMB_DICTIONARY_ITEM_PICKER_MODAL, { data: { - hideTreeRoot: true, pickableFilter: (item) => item.id !== null, }, }); - this.#openModal?.onSubmit().then((dictionaryItemPickerModalValue) => { - if (dictionaryItemPickerModalValue) { - this.value = { value: dictionaryItemPickerModalValue, type: CodeSnippetType.dictionaryItem }; - this.modalContext?.submit(); - } - }); + await dictionaryItemPickerModal?.onSubmit(); + + const dictionaryItem = dictionaryItemPickerModal?.getValue().selection[0]; + + if (dictionaryItem) { + this.value = { value: dictionaryItem, type: CodeSnippetType.dictionaryItem }; + this.modalContext?.submit(); + } } render() { @@ -77,7 +93,7 @@ export class UmbTemplatingItemPickerModalElement extends UmbModalBaseElement< #renderItems() { return html`
console.log('to be continued')} + @click=${this.#openTemplatingPageFieldModal} look="placeholder" label=${this.localize.term('template_insert')}>

Value (Not implemented)

@@ -89,7 +105,7 @@ export class UmbTemplatingItemPickerModalElement extends UmbModalBaseElement<

Partial view

@@ -101,7 +117,7 @@ export class UmbTemplatingItemPickerModalElement extends UmbModalBaseElement<

Dictionary Item

diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.token.ts index 79e593dae8..9a0a15e733 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-item-picker/templating-item-picker-modal.token.ts @@ -1,4 +1,5 @@ import type { CodeSnippetType } from '../../types.js'; +import type { UmbPartialViewPickerModalValue, UmbTemplatingPageFieldBuilderModalValue } from '../index.js'; import { type UmbDictionaryItemPickerModalValue, UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbTemplatingItemPickerModalData { @@ -6,7 +7,7 @@ export interface UmbTemplatingItemPickerModalData { } export type UmbTemplatingItemPickerModalValue = { - value: string | UmbDictionaryItemPickerModalValue; + value: string; type: CodeSnippetType; }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/index.ts new file mode 100644 index 0000000000..696a5c05e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/index.ts @@ -0,0 +1,2 @@ +export * from './templating-page-field-builder-modal.element.js'; +export * from './templating-page-field-builder-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts new file mode 100644 index 0000000000..fa026ffe32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts @@ -0,0 +1,116 @@ +import type { + UmbTemplatingPageFieldBuilderModalData, + UmbTemplatingPageFieldBuilderModalValue, +} from './templating-page-field-builder-modal.token.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; + +@customElement('umb-templating-page-field-builder-modal') +export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseElement< + UmbTemplatingPageFieldBuilderModalData, + UmbTemplatingPageFieldBuilderModalValue +> { + private _close() { + this.modalContext?.reject(); + } + + private _submit() { + this.value = { output: this.#generateOutput() }; + this.modalContext?.submit(); + } + + @state() + private _field?: string; + + @state() + private _haveDefault: boolean = false; + + @state() + private _default?: string; + + @state() + private _recursive: boolean = false; + + #generateOutput() { + if (!this._field) return ''; + if (this._default && !this._recursive) { + return `@Model.Value("${this._field}", fallback: Fallback.ToDefaultValue, defaultValue: new HtmlString("${this._default}"))`; + } else if (this._default && this._recursive) { + return `@Model.Value("${this._field}", fallback: Fallback.To(Fallback.Ancestors, Fallback.DefaultValue), defaultValue: new HtmlString("${this._default}"))`; + } else if (!this._default && this._recursive) { + return `@Model.Value("${this._field}", fallback: Fallback.ToAncestors)`; + } else { + return `@Model.Value("${this._field}")`; + } + } + + render() { + return html` + + +
+ + Choose field + + (Not implemented yet) + + + Default value + + ${!this._haveDefault + ? html` (this._haveDefault = true)}>` + : html``} + + Recursive + + + Output sample + ${this.#generateOutput()} +
+
+ + +
+ `; + } + + static styles = [ + UmbTextStyles, + css` + uui-box > div { + display: grid; + gap: var(--uui-size-space-2); + } + + uui-label:not(:first-child) { + margin-top: var(--uui-size-space-6); + } + `, + ]; +} + +export default UmbTemplatingPageFieldBuilderModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-templating-page-field-builder-modal': UmbTemplatingPageFieldBuilderModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.token.ts new file mode 100644 index 0000000000..ad621e61b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.token.ts @@ -0,0 +1,17 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbTemplatingPageFieldBuilderModalData {} + +export type UmbTemplatingPageFieldBuilderModalValue = { + output: string; +}; + +export const UMB_TEMPLATING_PAGE_FIELD_BUILDER_MODAL = new UmbModalToken< + UmbTemplatingPageFieldBuilderModalData, + UmbTemplatingPageFieldBuilderModalValue +>('Umb.Modal.TemplatingPageFieldBuilder', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts index 01a83f31b0..30d70c464b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts @@ -1,4 +1,5 @@ export enum CodeSnippetType { partialView = 'partialView', dictionaryItem = 'dictionaryItem', + pageField = 'pageField', }