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 1/5] 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', } From c3f61e9efc0d18cc20b5efbf55e5a534a42d06a7 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:39:12 +0100 Subject: [PATCH 2/5] redo of template section picker part 1 --- .../templating-item-menu.element.ts | 4 +- ...lating-page-field-builder-modal.element.ts | 21 +-- ...templating-section-picker-modal.element.ts | 132 +++++++++++++++++- .../src/packages/templating/types.ts | 6 + .../src/packages/templating/utils/index.ts | 2 +- 5 files changed, 144 insertions(+), 21 deletions(-) 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 4ffa8cae20..b21e364421 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 @@ -9,7 +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 { UmbModalManagerContext, UmbModalContext } from '@umbraco-cms/backoffice/modal'; +import type { UmbModalManagerContext } 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'; @@ -20,8 +20,6 @@ export class UmbTemplatingInsertMenuElement extends UmbLitElement { private _modalContext?: UmbModalManagerContext; - #openModal?: UmbModalContext; - #dictionaryDetailRepository = new UmbDictionaryDetailRepository(this); constructor() { 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 index fa026ffe32..e930c3b981 100644 --- 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 @@ -1,3 +1,4 @@ +import { getUmbracoFieldSnippet } from '../../utils/index.js'; import type { UmbTemplatingPageFieldBuilderModalData, UmbTemplatingPageFieldBuilderModalValue, @@ -16,7 +17,8 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme } private _submit() { - this.value = { output: this.#generateOutput() }; + if (!this._field) return; + this.value = { output: getUmbracoFieldSnippet(this._field, this._default, this._recursive) }; this.modalContext?.submit(); } @@ -32,19 +34,6 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme @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` @@ -74,7 +63,9 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme ?disabled=${this._field ? false : true}> Output sample - ${this.#generateOutput()} + ${this._field ? getUmbracoFieldSnippet(this._field, this._default, this._recursive) : ''}
{ + /* @queryAll('umb-insert-section-checkbox') checkboxes!: NodeListOf; @@ -22,7 +24,8 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement< @state() snippet = ''; - +*/ + /* #chooseSection(event: Event) { const target = event.target as UmbInsertSectionCheckboxElement; const checkboxes = Array.from(this.checkboxes); @@ -40,30 +43,129 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement< }); } } + */ + /* firstUpdated() { this.selectedCheckbox = this.checkboxes[0]; } + */ - snippetMethods = [getRenderBodySnippet, getRenderSectionSnippet, getAddSectionSnippet]; + //snippetMethods = [getRenderBodySnippet, getRenderSectionSnippet, getAddSectionSnippet]; + + @state() + private _pickedSection?: TemplatingSectionType; #close() { this.modalContext?.reject(); } #submit() { + /* const value = this.selectedCheckbox?.snippet; if (this.selectedCheckbox?.validate()) { this.value = { value: value ?? '' }; this.modalContext?.submit(); } + */ } + render() { + return html` + + +
+ ${this.#renderRenderChildTemplate()} ${this.#renderRenderANamedSection()} + ${this.#renderDefineANamedSection()} +
+
+ +
+ Close + Submit +
+
+ `; + } + + #renderRenderChildTemplate() { + return html` (this._pickedSection = TemplatingSectionType.renderChildTemplate)} + look="placeholder"> + ${this._pickedSection === TemplatingSectionType.renderChildTemplate + ? html`` + : ''} +

Render Child Template

+

+ + Renders the contents of a child template, by inserting a @RenderBody() placeholder. + +

+
`; + } + + #renderRenderANamedSection() { + return html` (this._pickedSection = TemplatingSectionType.renderANamedSection)} + look="placeholder"> + ${this._pickedSection === TemplatingSectionType.renderANamedSection + ? html`` + : ''} +

Render a named section

+

+ + Renders a named area of a child template, by inserting a + @RenderSection(name) placeholder. This renders an area of a child template which is wrapped in a + corresponding @section [name]{ ... } definition. + +

+ ${this._pickedSection === TemplatingSectionType.renderANamedSection + ? html`
+ Section Name + + + + + If mandatory, the child template must contain a @section definition, otherwise an error is + shown. + + +
` + : ''} +
`; + } + + #renderDefineANamedSection() { + return html` (this._pickedSection = TemplatingSectionType.defineANamedSection)} + look="placeholder"> + ${this._pickedSection === TemplatingSectionType.defineANamedSection + ? html`` + : ''} +

Define a named section

+

+ + Defines a part of your template as a named section by wrapping it in @section { ... }. This can + be rendered in a specific area of the parent of this template, by using @RenderSection. + +

+
`; + } + + /* render() { return html`
+ + +

Render Child Template

+ Renders the contents of a child template, by inserting a @RenderBody() placeholder. +
`; } + */ static styles = [ UmbTextStyles, css` + /* :host { display: block; color: var(--uui-color-text); @@ -133,11 +237,35 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement< #main umb-insert-section-checkbox:not(:last-of-type) { margin-bottom: var(--uui-size-space-5); } + */ + code { background-color: var(--uui-color-surface-alt); border: 1px solid var(--uui-color-border); border-radius: var(--uui-border-radius); } + + #main { + display: grid; + grid-gap: var(--uui-size-space-5); + } + + .section { + display: grid; + } + + uui-button { + text-align: left; + } + + uui-button p { + margin-top: 0; + } + + uui-input, + small { + margin-block: var(--uui-size-space-2) var(--uui-size-space-6); + } `, ]; } 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 30d70c464b..46069918b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/types.ts @@ -3,3 +3,9 @@ export enum CodeSnippetType { dictionaryItem = 'dictionaryItem', pageField = 'pageField', } + +export enum TemplatingSectionType { + renderChildTemplate = 'RenderChildTemplate', + renderANamedSection = 'RenderANamedSection', + defineANamedSection = 'DefineANamedSection', +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/utils/index.ts index 57c84ea4bf..43446d5e20 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/utils/index.ts @@ -45,7 +45,7 @@ export const getUmbracoFieldSnippet = (field: string, defaultValue: string | nul const value = `${field !== null ? `@Model.Value("${field}"` : ''}${ fallback !== null ? `, fallback: ${fallback}` : '' - }${defaultValue !== null ? `, defaultValue: new HtmlString("${defaultValue}")` : ''}${field ? ')' : ''}`; + }${defaultValue !== null ? `, defaultValue: new HtmlString("${defaultValue}")` : ''}${field ? ')' : ')'}`; return value; }; From 5149633865c12c16493d2623f05e8d145b14bf24 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:09:39 +0100 Subject: [PATCH 3/5] changes --- .../templating-item-picker-modal.element.ts | 2 +- ...lating-page-field-builder-modal.element.ts | 2 +- .../modals/templating-section-picker/index.ts | 2 +- ...templating-section-picker-input.element.ts | 150 --------------- ...templating-section-picker-modal.element.ts | 181 +++++------------- .../template-workspace-editor.element.ts | 1 + 6 files changed, 52 insertions(+), 286 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-input.element.ts 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 de6a71cf18..c535cf824c 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 @@ -96,7 +96,7 @@ export class UmbTemplatingItemPickerModalElement extends UmbModalBaseElement< @click=${this.#openTemplatingPageFieldModal} look="placeholder" label=${this.localize.term('template_insert')}> -

Value (Not implemented)

+

Value

Displays the value of a named field from the current page, with options to modify the value or fallback to 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 index e930c3b981..53f73c1416 100644 --- 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 @@ -78,7 +78,7 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme @click=${this._submit} color="positive" look="primary" - label=${this.localize.term('general_close')}> + label=${this.localize.term('general_submit')}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/index.ts index 5bb66c95b5..d5571f146d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/index.ts @@ -1,2 +1,2 @@ -export * from './templating-section-picker-input.element.js'; export * from './templating-section-picker-modal.element.js'; +export * from './templating-section-picker-modal.token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-input.element.ts deleted file mode 100644 index c8cf5632d1..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-input.element.ts +++ /dev/null @@ -1,150 +0,0 @@ -import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; -import { UUIBooleanInputElement } from '@umbraco-cms/backoffice/external/uui'; -import { css, html, customElement, property, query } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; - -@customElement('umb-insert-section-checkbox') -export class UmbInsertSectionCheckboxElement extends UUIBooleanInputElement { - renderCheckbox() { - return html``; - } - - @property({ type: Boolean, attribute: 'show-mandatory' }) - showMandatory = false; - - @property({ type: Boolean, attribute: 'show-input' }) - showInput = false; - - @query('uui-input') - input?: UUIInputElement; - - @query('form') - form?: HTMLFormElement; - - @query('uui-checkbox') - checkbox?: HTMLFormElement; - - get snippet() { - if (!this.snippetMethod) return ''; - const snippet = this.snippetMethod(this.inputValue as string, this.isMandatory) ?? ''; - return snippet; - } - - @property({ attribute: false }) - snippetMethod?: (value: string, isMandatory: boolean) => string; - - validate() { - if (!this.form) return true; - - this.form.requestSubmit(); - return this.form.checkValidity(); - } - - #preventDefault(event: Event) { - event.preventDefault(); - } - - get inputValue() { - return this.input?.value; - } - - get isMandatory() { - return this.checkbox?.checked; - } - - /* eslint-disable lit-a11y/click-events-have-key-events */ - render() { - return html` - ${super.render()} -

- ${this.checked ? html`` : ''}${this.label} -

-
-

here goes some description

-
- ${this.checked && this.showInput - ? html` -
- - Section name - ${this.showMandatory - ? html`

- Section is mandatory
- If mandatory, the child template must contain a @section definition, otherwise an - error is shown. -

` - : ''} -
-
` - : ''} - `; - } - /* eslint-enable lit-a11y/click-events-have-key-events */ - - static styles = [ - ...UUIBooleanInputElement.styles, - UmbTextStyles, - css` - :host { - display: block; - border-style: dashed; - background-color: transparent; - color: var(--uui-color-default-standalone, rgb(28, 35, 59)); - border-color: var(--uui-color-border-standalone, #c2c2c2); - border-radius: var(--uui-border-radius, 3px); - border-width: 1px; - line-height: normal; - padding: 6px 18px; - } - - :host(:hover), - :host(:focus), - :host(:focus-within) { - background-color: var(--uui-button-background-color-hover, transparent); - color: var(--uui-color-default-emphasis, #3544b1); - border-color: var(--uui-color-default-emphasis, #3544b1); - } - - uui-icon { - background-color: var(--uui-color-positive-emphasis); - border-radius: 50%; - padding: 0.2em; - margin-right: 1ch; - color: var(--uui-color-positive-contrast); - font-size: 0.7em; - } - - ::slotted(*) { - line-height: normal; - } - - .label { - display: none; - } - - h3, - p { - text-align: left; - } - - uui-input { - width: 100%; - } - `, - ]; -} - -export default UmbInsertSectionCheckboxElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-insert-section-input': UmbInsertSectionCheckboxElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-modal.element.ts index f85df1e65e..fd92e4c79c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-section-picker/templating-section-picker-modal.element.ts @@ -4,70 +4,50 @@ import type { UmbTemplatingSectionPickerModalData, UmbTemplatingSectionPickerModalValue, } from './templating-section-picker-modal.token.js'; -import type { UmbInsertSectionCheckboxElement } from './templating-section-picker-input.element.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement, queryAll, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; -import './templating-section-picker-input.element.js'; +import type { UUIBooleanInputElement, UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; @customElement('umb-templating-section-picker-modal') export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement< UmbTemplatingSectionPickerModalData, UmbTemplatingSectionPickerModalValue > { - /* - @queryAll('umb-insert-section-checkbox') - checkboxes!: NodeListOf; + @query('#render-named-section-name') + private _renderNamedSectionNameInput?: UUIInputElement; + + @query('#define-named-section-name') + private _defineNamedSectionNameInput?: UUIInputElement; + + @query('#render-named-section-is-mandatory') + private _renderNamedSectionIsMandatoryCheckbox?: UUIBooleanInputElement; @state() - selectedCheckbox?: UmbInsertSectionCheckboxElement | null = null; - - @state() - snippet = ''; -*/ - /* - #chooseSection(event: Event) { - const target = event.target as UmbInsertSectionCheckboxElement; - const checkboxes = Array.from(this.checkboxes); - if (checkboxes.every((checkbox) => checkbox.checked === false)) { - this.selectedCheckbox = null; - return; - } - if (target.checked) { - this.selectedCheckbox = target; - this.snippet = this.selectedCheckbox.snippet ?? ''; - checkboxes.forEach((checkbox) => { - if (checkbox !== target) { - checkbox.checked = false; - } - }); - } - } - */ - - /* - firstUpdated() { - this.selectedCheckbox = this.checkboxes[0]; - } - */ - - //snippetMethods = [getRenderBodySnippet, getRenderSectionSnippet, getAddSectionSnippet]; - - @state() - private _pickedSection?: TemplatingSectionType; + private _pickedSection: TemplatingSectionType = TemplatingSectionType.renderChildTemplate; #close() { this.modalContext?.reject(); } #submit() { - /* - const value = this.selectedCheckbox?.snippet; - if (this.selectedCheckbox?.validate()) { - this.value = { value: value ?? '' }; - this.modalContext?.submit(); + switch (this._pickedSection) { + case TemplatingSectionType.renderChildTemplate: + this.value = { value: getRenderBodySnippet() }; + break; + case TemplatingSectionType.renderANamedSection: + this.value = { + value: getRenderSectionSnippet( + this._renderNamedSectionNameInput?.value as string, + this._renderNamedSectionIsMandatoryCheckbox?.checked ?? false, + ), + }; + break; + case TemplatingSectionType.defineANamedSection: + this.value = { value: getAddSectionSnippet(this._defineNamedSectionNameInput?.value as string) }; + break; } - */ + this.modalContext?.submit(); } render() { @@ -81,8 +61,12 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement<
- Close - Submit + +
`; @@ -123,9 +107,13 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement<

${this._pickedSection === TemplatingSectionType.renderANamedSection ? html`
- Section Name - - + + Section Name + + + If mandatory, the child template must contain a @section definition, otherwise an error is @@ -152,93 +140,20 @@ export class UmbTemplatingSectionPickerModalElement extends UmbModalBaseElement< be rendered in a specific area of the parent of this template, by using @RenderSection.

+ ${this._pickedSection === TemplatingSectionType.defineANamedSection + ? html`
+ + Section Name + + +
` + : ''} `; } - /* - render() { - return html` - -
- - - -

Render Child Template

- Renders the contents of a child template, by inserting a @RenderBody() placeholder. -
- -

- - Renders the contents of a child template, by inserting a @RenderBody() placeholder. - -

-
- - -

- - Renders a named area of a child template, by inserting a - @RenderSection(name) placeholder. This renders an area of a child template which is - wrapped in a corresponding @section [name]{ ... } definition. - -

-
- - -

- - Renders a named area of a child template, by inserting a - @RenderSection(name) placeholder. This renders an area of a child template which is - wrapped in a corresponding @section [name]{ ... } definition. - -

-
-
-
-
- Close - Submit -
-
- `; - } - */ - static styles = [ UmbTextStyles, css` - /* - :host { - display: block; - color: var(--uui-color-text); - --umb-header-layout-height: 70px; - } - - #main { - box-sizing: border-box; - height: calc( - 100dvh - var(--umb-header-layout-height) - var(--umb-footer-layout-height) - 2 * var(--uui-size-layout-1) - ); - } - - #main umb-insert-section-checkbox:not(:last-of-type) { - margin-bottom: var(--uui-size-space-5); - } - */ - code { background-color: var(--uui-color-surface-alt); border: 1px solid var(--uui-color-border); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts index a10d9e5364..7cd94754b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts @@ -109,6 +109,7 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement { #openInsertSectionModal() { const sectionModal = this._modalContext?.open(UMB_TEMPLATING_SECTION_PICKER_MODAL); + sectionModal?.onSubmit().then((insertSectionModalValue) => { if (insertSectionModalValue?.value) { this._codeEditor?.insert(insertSectionModalValue.value); From 3f46db8f8941f7391ba250b1e041332ebc3867ed Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:16:54 +0100 Subject: [PATCH 4/5] remove console --- ...rty-editor-ui-collection-view-column-configuration.element.ts | 1 - 1 file changed, 1 deletion(-) 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 838f3fb4d3..4625960edb 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,7 +110,6 @@ export class UmbPropertyEditorUICollectionViewColumnConfigurationElement } render() { - console.log(this.config); return html`
From 9c4de36043a83305ab9c1327e6ecbf02689dd8dc Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 19 Feb 2024 13:32:38 +0100 Subject: [PATCH 5/5] add todo --- .../templating-page-field-builder-modal.element.ts | 2 ++ 1 file changed, 2 insertions(+) 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 index 53f73c1416..37afe148ca 100644 --- 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 @@ -34,6 +34,8 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme @state() private _recursive: boolean = false; + /** TODO: Implement "Choose field" */ + render() { return html`