From 722ebeff34f0cfd8fec2c33fd5fedb96cf8b5718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 6 Feb 2024 17:16:13 +0100 Subject: [PATCH] mega commit tuesday --- .../block-grid-block.element.ts | 125 ++++++++++++++++ .../components/block-grid-block/index.ts | 1 + .../block/block-grid/components/index.ts | 0 .../block-grid-entries.context-token.ts | 5 + .../context/block-grid-entries.context.ts | 93 ++++++++++++ .../context/block-grid-entry.context-token.ts | 5 + ...context.ts => block-grid-entry.context.ts} | 13 +- .../context/block-grid.context-token.ts | 5 - .../block/block-grid/context/index.ts | 2 + .../src/packages/block/block-grid/index.ts | 3 +- .../manager/block-grid-manager.context.ts | 16 +- ...ty-editor-ui-block-grid-entries.element.ts | 109 ++++++++++++++ ...-ui-block-grid-layout-container.element.ts | 137 ------------------ .../property-editor-ui-block-grid.element.ts | 92 ++++++------ .../src/packages/block/block-grid/types.ts | 7 +- .../block-list-block.element.ts | 21 +-- .../inline-list-block.element.ts | 6 +- .../ref-list-block/ref-list-block.element.ts | 4 +- .../context/block-list-entry.context-token.ts | 5 + ...context.ts => block-list-entry.context.ts} | 2 +- .../context/block-list.context-token.ts | 5 - .../block/block-list/context/index.ts | 1 + .../src/packages/block/block-list/index.ts | 3 +- .../property-editor-ui-block-list.element.ts | 12 +- .../src/packages/block/block-list/types.ts | 4 +- .../block/context/block-entities.context.ts | 34 +++++ .../block/context/block-entity.context.ts | 34 ++++- .../block/manager/block-manager.context.ts | 33 ++++- .../workspace/block-workspace.context.ts | 1 + .../core/sorter/sorter.controller.test.ts | 18 --- 30 files changed, 536 insertions(+), 260 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context-token.ts rename src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/{block-grid.context.ts => block-grid-entry.context.ts} (69%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-entries.element.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-layout-container.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context-token.ts rename src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/{block-list.context.ts => block-list-entry.context.ts} (93%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entities.context.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/sorter/sorter.controller.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts new file mode 100644 index 0000000000..79fd25581d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -0,0 +1,125 @@ +import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; +import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import type { UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block'; +import '../ref-list-block/index.js'; +import '../inline-list-block/index.js'; + +/** + * @element umb-property-editor-ui-block-grid-block + */ +@customElement('umb-property-editor-ui-block-grid-block') +export class UmbPropertyEditorUIBlockGridBlockElement extends UmbLitElement implements UmbPropertyEditorUiElement { + // + @property({ attribute: false }) + public get layout(): UmbBlockGridLayoutModel | undefined { + return this._layout; + } + public set layout(value: UmbBlockGridLayoutModel | undefined) { + this._layout = value; + this.#context.setLayout(value); + } + private _layout?: UmbBlockGridLayoutModel | undefined; + + #context = new UmbBlockGridEntryContext(this); + + @state() + _contentUdi?: string; + + @state() + _hasSettings = false; + + @state() + _label = ''; + + @state() + _workspaceEditPath?: string; + + @state() + _inlineEditingMode?: boolean; + + // TODO: Move type for the Block Properties, and use it on the Element Interface for the Manifest. + @state() + _blockViewProps: { + label?: string; + } = {}; + + constructor() { + super(); + + this.observe(this.#context.workspaceEditPath, (workspaceEditPath) => { + this._workspaceEditPath = workspaceEditPath; + }); + this.observe(this.#context.contentUdi, (contentUdi) => { + this._contentUdi = contentUdi; + }); + this.observe(this.#context.blockTypeSettingsElementTypeKey, (blockTypeSettingsElementTypeKey) => { + this._hasSettings = !!blockTypeSettingsElementTypeKey; + }); + this.observe(this.#context.label, (label) => { + this._blockViewProps.label = label; + this._label = label; + }); + } + + #renderRefBlock() { + return html``; + } + + #renderBlock() { + return html` + ${this.#renderRefBlock()} + + ${this._workspaceEditPath + ? html` + + ` + : ''} + ${this._workspaceEditPath && this._hasSettings + ? html` + + ` + : ''} + + + + + `; + } + + render() { + return this.layout && this._contentUdi ? this.#renderBlock() : ''; + } + + static styles = [ + css` + :host { + position: relative; + display: block; + } + uui-action-bar { + position: absolute; + top: var(--uui-size-2); + right: var(--uui-size-2); + } + + :host([drag-placeholder]) { + opacity: 0.2; + } + `, + ]; +} + +export default UmbPropertyEditorUIBlockGridBlockElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-property-editor-ui-block-grid-block': UmbPropertyEditorUIBlockGridBlockElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/index.ts new file mode 100644 index 0000000000..8afd0511df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/index.ts @@ -0,0 +1 @@ +export * from './block-grid-block.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context-token.ts new file mode 100644 index 0000000000..6b05007c46 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context-token.ts @@ -0,0 +1,5 @@ +import type { UmbBlockGridEntriesContext } from './block-grid-entries.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +// TODO: Make discriminator method for this: +export const UMB_BLOCK_GRID_ENTRIES_CONTEXT = new UmbContextToken('UmbBlockEntriesContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts new file mode 100644 index 0000000000..8940fb7dc8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts @@ -0,0 +1,93 @@ +import { UMB_BLOCK_CATALOGUE_MODAL } from '../../block/index.js'; +import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from '../manager/block-grid-manager.context.js'; +import type { UmbBlockGridLayoutModel } from '../types.js'; +import { UMB_BLOCK_GRID_ENTRIES_CONTEXT } from './block-grid-entries.context-token.js'; +import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from './block-grid-entry.context-token.js'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { type UmbModalRouteBuilder, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; + +export class UmbBlockGridEntriesContext extends UmbContextBase { + // + #blockManager?: typeof UMB_BLOCK_GRID_MANAGER_CONTEXT.TYPE; + #catalogueModal: UmbModalRouteRegistrationController; + #catalogueRouteBuilder?: UmbModalRouteBuilder; + + #layoutEntries = new UmbArrayState([], (x) => x.contentUdi); + layoutEntries = this.#layoutEntries.asObservable(); + + setLayoutEntries(layoutEntries: Array) { + this.#layoutEntries.setValue(layoutEntries); + } + getLayoutEntries() { + return this.#layoutEntries.value; + } + + setParentKey(contentUdi: string) { + this.#catalogueModal.setUniquePathValue('parentUnique', contentUdi); + } + getParentKey() { + return ''; + } + + setAreaKey(areaKey: string) { + this.#catalogueModal.setUniquePathValue('areaKey', areaKey); + } + getAreaKey() { + return ''; + } + + constructor(host: UmbControllerHost) { + super(host, UMB_BLOCK_GRID_ENTRIES_CONTEXT.toString()); + + this.#catalogueModal = new UmbModalRouteRegistrationController(this, UMB_BLOCK_CATALOGUE_MODAL) + .addUniquePaths(['propertyAlias', 'parentUnique', 'areaKey']) + .addAdditionalPath(':view/:index') + .onSetup((routingInfo) => { + // Idea: Maybe on setup should be async, so it can retrieve the values when needed? [NL] + const index = routingInfo.index ? parseInt(routingInfo.index) : -1; + return { + data: { + blocks: [], + blockGroups: [], + openClipboard: routingInfo.view === 'clipboard', + blockOriginData: { index: index }, + }, + }; + }) + .observeRouteBuilder((routeBuilder) => { + this.#catalogueRouteBuilder = routeBuilder; + }); + + // TODO: Observe Blocks of the layout entries of this component. + this.consumeContext(UMB_BLOCK_GRID_MANAGER_CONTEXT, (blockGridManager) => { + this.#blockManager = blockGridManager; + this.#gotBlockManager(); + }); + } + + #gotBlockManager() { + if (!this.#blockManager) return; + + this.observe( + this.#blockManager.propertyAlias, + (alias) => { + this.#catalogueModal.setUniquePathValue('propertyAlias', alias); + }, + 'observePropertyAlias', + ); + } + + getPathForCreateBlock(index: number) { + return this.#catalogueRouteBuilder?.({ view: 'create', index: index }); + } + + getPathForClipboard(index: number) { + return this.#catalogueRouteBuilder?.({ view: 'clipboard', index: index }); + } + + // create Block? + + deleteBlock() {} +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context-token.ts new file mode 100644 index 0000000000..b5213a3c32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context-token.ts @@ -0,0 +1,5 @@ +import type { UmbBlockGridEntryContext } from './block-grid-entry.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +// TODO: Make discriminator method for this: +export const UMB_BLOCK_GRID_ENTRY_CONTEXT = new UmbContextToken('UmbBlockEntryContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts similarity index 69% rename from src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context.ts rename to src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts index 49a95d7aca..9fa8d9ad55 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts @@ -3,20 +3,25 @@ import { UmbBlockContext, type UmbBlockGridTypeModel, type UmbBlockGridLayoutModel, + type UmbBlockGridLayoutAreaItemModel, } from '@umbraco-cms/backoffice/block'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbBlockGridContext extends UmbBlockContext< +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +export class UmbBlockGridEntryContext extends UmbBlockContext< typeof UMB_BLOCK_GRID_MANAGER_CONTEXT, typeof UMB_BLOCK_GRID_MANAGER_CONTEXT.TYPE, UmbBlockGridTypeModel, UmbBlockGridLayoutModel > { - #inlineEditingMode = new UmbBooleanState(undefined); - inlineEditingMode = this.#inlineEditingMode.asObservable(); + #areas = new UmbArrayState([], (x) => x.key); + areas = this.#areas.asObservable(); constructor(host: UmbControllerHost) { super(host, UMB_BLOCK_GRID_MANAGER_CONTEXT); + + this.observe(this.layout, (layout) => { + this.#areas.setValue(layout?.areas ?? []); + }); } _gotManager() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context-token.ts deleted file mode 100644 index a8c429f977..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid.context-token.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { UmbBlockGridContext } from './block-grid.context.js'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; - -// TODO: Make discriminator method for this: -export const UMB_BLOCK_GRID_CONTEXT = new UmbContextToken('UmbBlockContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/index.ts new file mode 100644 index 0000000000..f652a039d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/index.ts @@ -0,0 +1,2 @@ +export * from './block-grid-entries.context-token.js'; +export * from './block-grid-entry.context-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts index 56ebdc81cc..577eea75f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/index.ts @@ -1,2 +1,3 @@ -export * from './workspace/index.js'; +export * from './context/index.js'; export * from './types.js'; +export * from './workspace/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/manager/block-grid-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/manager/block-grid-manager.context.ts index f0adca8e20..71087b2dd0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/manager/block-grid-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/manager/block-grid-manager.context.ts @@ -1,7 +1,9 @@ import type { UmbBlockGridLayoutModel, UmbBlockGridTypeModel } from '../types.js'; import { UmbBlockManagerContext } from '../../block/manager/block-manager.context.js'; import type { UmbBlockGridWorkspaceData } from '../index.js'; +import type { UmbBlockTypeGroup } from '../../block-type/types.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; /** * A implementation of the Block Manager specifically for the Block Grid Editor. @@ -10,14 +12,16 @@ export class UmbBlockGridManagerContext< BlockLayoutType extends UmbBlockGridLayoutModel = UmbBlockGridLayoutModel, > extends UmbBlockManagerContext { // - /* - #inlineEditingMode = new UmbBooleanState(undefined); - inlineEditingMode = this.#inlineEditingMode.asObservable(); + // + #blockGroups = new UmbArrayState(>[], (x) => x.key); + public readonly blockGroups = this.#blockGroups.asObservable(); - setInlineEditingMode(inlineEditingMode: boolean | undefined) { - this.#inlineEditingMode.setValue(inlineEditingMode ?? false); + setBlockGroups(blockGroups: Array) { + this.#blockGroups.setValue(blockGroups); + } + getBlockGroups() { + return this.#blockGroups.value; } - */ _createBlock(modalData: UmbBlockGridWorkspaceData, layoutEntry: BlockLayoutType, contentElementTypeKey: string) { // Here is room to append some extra layout properties if needed for this type. diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-entries.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-entries.element.ts new file mode 100644 index 0000000000..557bad244c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-entries.element.ts @@ -0,0 +1,109 @@ +import { UmbBlockGridEntriesContext } from '../../context/block-grid-entries.context.js'; +import type { UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block'; +import { html, customElement, state, repeat, css, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +/** + * @element umb-property-editor-ui-block-grid-entries + */ +@customElement('umb-property-editor-ui-block-grid-entries') +export class UmbPropertyEditorUIBlockGridEntriesElement extends UmbLitElement { + // + // TODO: Make sure Sorter callbacks handles columnSpan when retrieving a new entry. + + #context = new UmbBlockGridEntriesContext(this); + + @property({ attribute: false }) + public set layoutEntries(value: Array) { + this.#context.setLayoutEntries(value); + } + public get layoutEntries(): Array { + return this.#context.getLayoutEntries(); + } + + @property({ attribute: false }) + public set parentUnique(value: string) { + this.#context.setParentKey(value); + } + public get parentUnique(): string { + return this.#context.getParentKey(); + } + + @property({ attribute: false }) + public set areaKey(value: string) { + this.#context.setAreaKey(value); + } + public get areaKey(): string { + return this.#context.getAreaKey(); + } + + @state() + private _layoutEntries: Array = []; + + @state() + private _createButtonLabel = this.localize.term('blockEditor_addBlock'); + + constructor() { + super(); + this.observe(this.#context.layoutEntries, (layoutEntries) => { + this._layoutEntries = layoutEntries; + }); + } + + render() { + // TODO: Missing ability to jump directly to creating a Block, when there is only one Block Type. + return html` ${repeat( + this._layoutEntries, + (x) => x.contentUdi, + (layoutEntry, index) => + html` + + `, + )} + + + + + + `; + // + } + + static styles = [ + UmbTextStyles, + css` + :host { + display: grid; + gap: 1px; + } + > div { + display: flex; + flex-direction: column; + align-items: stretch; + } + + uui-button-group { + padding-top: 1px; + display: grid; + grid-template-columns: 1fr auto; + } + `, + ]; +} + +export default UmbPropertyEditorUIBlockGridEntriesElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-property-editor-ui-block-grid-entries': UmbPropertyEditorUIBlockGridEntriesElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-layout-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-layout-container.element.ts deleted file mode 100644 index afc0146d2e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid-layout-container.element.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { - UMB_BLOCK_CATALOGUE_MODAL, - type UmbBlockGridLayoutModel, - type UmbBlockTypeBaseModel, -} from '@umbraco-cms/backoffice/block'; -import { html, customElement, state, repeat, css, property } from '@umbraco-cms/backoffice/external/lit'; -import { type UmbModalRouteBuilder, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; -import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; - -/** - * @element umb-property-editor-ui-block-grid-entries - */ -@customElement('umb-property-editor-ui-block-grid-entries') -export class UmbPropertyEditorUIBlockGridEntriesElement extends UmbLitElement { - // TODO: Make sure Sorter handles columnSpan when retrieving a new entry. - #catalogueModal: UmbModalRouteRegistrationController; - - @state() - private _catalogueRouteBuilder?: UmbModalRouteBuilder; - - @state() - private _blocks?: Array; - - @property({ attribute: false }) - public set layoutEntries(value: Array) { - this._layoutEntries = value; - } - public get layoutEntries(): Array { - return this._layoutEntries; - } - private _layoutEntries: Array = []; - - @state() - private _createButtonLabel = this.localize.term('content_createEmpty'); - - constructor() { - super(); - - // TODO: Observe Blocks of the layout entries of this component. - - // TODO: Could this become part of the Block Manager Context? - this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { - this.observe( - propertyContext?.alias, - (alias) => { - this.#catalogueModal.setUniquePathValue('propertyAlias', alias); - }, - 'observePropertyAlias', - ); - }); - - // Maybe this can be moved to the Block Manager Context? As I don't want to know about groups here. Maybe just part of the onSetup method? - this.#catalogueModal = new UmbModalRouteRegistrationController(this, UMB_BLOCK_CATALOGUE_MODAL) - .addUniquePaths(['propertyAlias', 'parentUnique']) - .addAdditionalPath(':view/:index') - .onSetup((routingInfo) => { - const index = routingInfo.index ? parseInt(routingInfo.index) : -1; - return { - data: { - blocks: this._blocks ?? [], - //blockGroups: this._blockGroups ?? [], - blockGroups: [], - openClipboard: routingInfo.view === 'clipboard', - blockOriginData: { index: index }, - }, - }; - }) - .observeRouteBuilder((routeBuilder) => { - this._catalogueRouteBuilder = routeBuilder; - }); - } - - render() { - let createPath: string | undefined; - if (this._blocks?.length === 1) { - const elementKey = this._blocks[0].contentElementTypeKey; - createPath = - this._catalogueRouteBuilder?.({ view: 'create', index: -1 }) + 'modal/umb-modal-workspace/create/' + elementKey; - } else { - createPath = this._catalogueRouteBuilder?.({ view: 'create', index: -1 }); - } - return html` ${repeat( - this._layoutEntries, - (x) => x.contentUdi, - (layoutEntry, index) => - html` - - `, - )} - - - - - - `; - // - } - - static styles = [ - UmbTextStyles, - css` - :host { - display: grid; - gap: 1px; - } - > div { - display: flex; - flex-direction: column; - align-items: stretch; - } - - uui-button-group { - padding-top: 1px; - display: grid; - grid-template-columns: 1fr auto; - } - `, - ]; -} - -export default UmbPropertyEditorUIBlockGridEntriesElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-property-editor-ui-block-grid-entries': UmbPropertyEditorUIBlockGridEntriesElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts index 9e2141b81d..4d72d6cb1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts @@ -1,40 +1,31 @@ +import { UmbBlockGridManagerContext } from '../../manager/block-grid-manager.context.js'; +import { UMB_BLOCK_GRID_PROPERTY_EDITOR_ALIAS } from './manifests.js'; import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; -import type { UmbBlockGridLayoutModel, UmbBlockTypeBaseModel, UmbBlockTypeGroup } from '@umbraco-cms/backoffice/block'; +import type { + UmbBlockGridLayoutModel, + UmbBlockGridTypeModel, + UmbBlockGridValueModel, + UmbBlockTypeGroup, +} from '@umbraco-cms/backoffice/block'; import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UMB_BLOCK_GRID_PROPERTY_EDITOR_ALIAS } from './manifests'; /** * @element umb-property-editor-ui-block-grid */ @customElement('umb-property-editor-ui-block-grid') export class UmbPropertyEditorUIBlockGridElement extends UmbLitElement implements UmbPropertyEditorUiElement { - @property() - value = ''; - - @state() - private _limitMin?: number; - @state() - private _limitMax?: number; - - @state() - private _blocks?: Array; - - @state() - private _blockGroups?: Array; - - @state() - private _rootLayouts: Array = []; - - @state() - private _directRoute?: string; - - @state() - private _createButtonLabel = this.localize.term('blockEditor_addBlock'); + #context = new UmbBlockGridManagerContext(this); + // + private _value: UmbBlockGridValueModel = { + layout: {}, + contentData: [], + settingsData: [], + }; @property({ attribute: false }) public set config(config: UmbPropertyEditorConfigCollection | undefined) { @@ -45,28 +36,42 @@ export class UmbPropertyEditorUIBlockGridElement extends UmbLitElement implement this._limitMin = validationLimit?.min; this._limitMax = validationLimit?.max; - this._blocks = config.getValueByAlias>('blocks') ?? []; - this._blockGroups = config.getValueByAlias>('blockGroups') ?? []; + const blocks = config.getValueByAlias>('blocks') ?? []; + this.#context.setBlockTypes(blocks); - const customCreateButtonLabel = config.getValueByAlias('createLabel'); - if (customCreateButtonLabel) { - this._createButtonLabel = customCreateButtonLabel; - } else if (this._blocks.length === 1) { - this._createButtonLabel = this.localize.term('blockEditor_addThis', [this._blocks[0].label]); - } + const blockGroups = config.getValueByAlias>('blockGroups') ?? []; + this.#context.setBlockGroups(blockGroups); - //const useInlineEditingAsDefault = config.getValueByAlias('useInlineEditingAsDefault'); - - //this.#context.setInlineEditingMode(useInlineEditingAsDefault); - //config.useSingleBlockMode - //config.useLiveEditing - //config.useInlineEditingAsDefault this.style.maxWidth = config.getValueByAlias('maxPropertyWidth') ?? ''; - //this.#context.setEditorConfiguration(config); + //config.useLiveEditing, is covered by the EditorConfiguration of context. + this.#context.setEditorConfiguration(config); } - #context = new UmbBlockGridManagerContext(this); + // + @state() + private _limitMin?: number; + @state() + private _limitMax?: number; + + @property({ attribute: false }) + public get value(): UmbBlockGridValueModel { + return this._value; + } + public set value(value: UmbBlockGridValueModel | undefined) { + const buildUpValue: Partial = value ? { ...value } : {}; + buildUpValue.layout ??= {}; + buildUpValue.contentData ??= []; + buildUpValue.settingsData ??= []; + this._value = buildUpValue as UmbBlockGridValueModel; + + this.#context.setLayouts(this._value.layout[UMB_BLOCK_GRID_PROPERTY_EDITOR_ALIAS] ?? []); + this.#context.setContents(buildUpValue.contentData); + this.#context.setSettings(buildUpValue.settingsData); + } + + @state() + private _rootLayouts: Array = []; constructor() { super(); @@ -92,14 +97,13 @@ export class UmbPropertyEditorUIBlockGridElement extends UmbLitElement implement //console.log('settings changed', this._value); this.dispatchEvent(new UmbChangeEvent()); }); - this.observe(this.#context.blockTypes, (blockTypes) => { - this._blocks = blockTypes; - }); } render() { return html``; + .layoutEntries=${this._rootLayouts} + .parentUnique=${'root'} + .areaKey=${'root'}>`; } static styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts index 0a70b20f97..2c9368c59d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts @@ -1,8 +1,9 @@ import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../block-type/index.js'; -import type { UmbBlockLayoutBaseModel } from '../index.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '../index.js'; export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; +// Configuration models: export interface UmbBlockGridTypeModel extends UmbBlockTypeBaseModel { columnSpanOptions: Array; allowAtRoot: boolean; @@ -23,6 +24,10 @@ export interface UmbBlockGridGroupTypeConfiguration extends Partial; } +// Content models: + +export interface UmbBlockGridValueModel extends UmbBlockValueType {} + export interface UmbBlockGridLayoutModel extends UmbBlockLayoutBaseModel { columnSpan: number; rowSpan: number; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts index 897f888b4c..95b756a338 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts @@ -1,4 +1,4 @@ -import { UmbBlockListContext } from '../../context/block-list.context.js'; +import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -23,7 +23,7 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl } private _layout?: UmbBlockLayoutBaseModel | undefined; - #context = new UmbBlockListContext(this); + #context = new UmbBlockListEntryContext(this); @state() _contentUdi?: string; @@ -67,21 +67,6 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl }); } - #requestDelete() { - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, async (modalManager) => { - const modalContext = modalManager.open(UMB_CONFIRM_MODAL, { - data: { - headline: `Delete ${this._label}`, - content: 'Are you sure you want to delete this [INSERT BLOCK TYPE NAME]?', - confirmLabel: 'Delete', - color: 'danger', - }, - }); - await modalContext.onSubmit(); - this.#context.delete(); - }); - } - #renderRefBlock() { return html``; } @@ -109,7 +94,7 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl ` : ''} - + diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts index e177087318..714a3cc861 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts @@ -1,4 +1,4 @@ -import { UMB_BLOCK_LIST_CONTEXT } from '../../index.js'; +import { UMB_BLOCK_LIST_ENTRY_CONTEXT } from '../../index.js'; import type { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../../block/index.js'; import { UMB_BLOCK_WORKSPACE_ALIAS } from '../../../block/index.js'; import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; @@ -13,7 +13,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; */ @customElement('umb-inline-list-block') export class UmbInlineListBlockElement extends UmbLitElement { - #blockContext?: typeof UMB_BLOCK_LIST_CONTEXT.TYPE; + #blockContext?: typeof UMB_BLOCK_LIST_ENTRY_CONTEXT.TYPE; #workspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; #contentUdi?: string; @@ -26,7 +26,7 @@ export class UmbInlineListBlockElement extends UmbLitElement { constructor() { super(); - this.consumeContext(UMB_BLOCK_LIST_CONTEXT, (blockContext) => { + this.consumeContext(UMB_BLOCK_LIST_ENTRY_CONTEXT, (blockContext) => { this.#blockContext = blockContext; this.observe( this.#blockContext.contentUdi, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts index dce78e9855..56d52e4e0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts @@ -1,4 +1,4 @@ -import { UMB_BLOCK_LIST_CONTEXT } from '../../context/block-list.context-token.js'; +import { UMB_BLOCK_LIST_ENTRY_CONTEXT } from '../../context/block-list-entry.context-token.js'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -17,7 +17,7 @@ export class UmbRefListBlockElement extends UmbLitElement { constructor() { super(); - this.consumeContext(UMB_BLOCK_LIST_CONTEXT, (context) => { + this.consumeContext(UMB_BLOCK_LIST_ENTRY_CONTEXT, (context) => { this.observe( context.workspaceEditPath, (workspaceEditPath) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context-token.ts new file mode 100644 index 0000000000..d914fdf834 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context-token.ts @@ -0,0 +1,5 @@ +import type { UmbBlockListEntryContext } from './block-list-entry.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +// TODO: Make discriminator method for this: +export const UMB_BLOCK_LIST_ENTRY_CONTEXT = new UmbContextToken('UmbBlockEntryContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context.ts rename to src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context.ts index 60b2c3b4c3..718df6fa0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entry.context.ts @@ -2,7 +2,7 @@ import { UMB_BLOCK_LIST_MANAGER_CONTEXT } from '../manager/block-list-manager.co import { UmbBlockContext } from '@umbraco-cms/backoffice/block'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbBlockListContext extends UmbBlockContext< +export class UmbBlockListEntryContext extends UmbBlockContext< typeof UMB_BLOCK_LIST_MANAGER_CONTEXT, typeof UMB_BLOCK_LIST_MANAGER_CONTEXT.TYPE > { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context-token.ts deleted file mode 100644 index fb4f9c63fe..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list.context-token.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { UmbBlockListContext } from './block-list.context.js'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; - -// TODO: Make discriminator method for this: -export const UMB_BLOCK_LIST_CONTEXT = new UmbContextToken('UmbBlockContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/index.ts new file mode 100644 index 0000000000..235016411e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/index.ts @@ -0,0 +1 @@ +export * from './block-list-entry.context-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts index 06bff7c73b..577eea75f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/index.ts @@ -1,2 +1,3 @@ +export * from './context/index.js'; +export * from './types.js'; export * from './workspace/index.js'; -export * from './context/block-list.context-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index db0744379d..795467d4aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -1,6 +1,7 @@ import { UmbBlockListManagerContext } from '../../manager/block-list-manager.context.js'; import '../../components/block-list-block/index.js'; import type { UmbPropertyEditorUIBlockListBlockElement } from '../../components/block-list-block/index.js'; +import type { UmbBlockListLayoutModel, UmbBlockListValueModel } from '../../types.js'; import { UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS } from './manifests.js'; import { html, customElement, property, state, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -8,7 +9,7 @@ import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extensi import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UMB_BLOCK_CATALOGUE_MODAL } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockLayoutBaseModel, UmbBlockTypeBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockLayoutBaseModel, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block'; import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/modal'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; @@ -17,10 +18,6 @@ import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; -export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} - -export interface UmbBlockListValueModel extends UmbBlockValueType {} - const SORTER_CONFIG: UmbSorterConfig = { getUniqueOfElement: (element) => { return element.getAttribute('data-udi'); @@ -94,9 +91,8 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement const useInlineEditingAsDefault = config.getValueByAlias('useInlineEditingAsDefault'); this.#context.setInlineEditingMode(useInlineEditingAsDefault); - //config.useSingleBlockMode - //config.useLiveEditing - //config.useInlineEditingAsDefault + // TODO: + //config.useSingleBlockMode, not done jey this.style.maxWidth = config.getValueByAlias('maxPropertyWidth') ?? ''; this.#context.setEditorConfiguration(config); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts index bd1e8053c9..de8121d884 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts @@ -1,7 +1,9 @@ import type { UmbBlockTypeBaseModel } from '../block-type/index.js'; -import type { UmbBlockLayoutBaseModel } from '../index.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '../index.js'; export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {} export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} + +export interface UmbBlockListValueModel extends UmbBlockValueType {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entities.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entities.context.ts new file mode 100644 index 0000000000..51575f30fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entities.context.ts @@ -0,0 +1,34 @@ +import type { UmbBlockTypeBaseModel } from '../../block-type/types.js'; +import type { UmbBlockLayoutBaseModel } from '../types.js'; +import type { UMB_BLOCK_MANAGER_CONTEXT, UmbBlockManagerContext } from '../manager/index.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; + +export abstract class UmbBlockContext< + BlockManagerContextTokenType extends UmbContextToken, + BlockManagerContextType extends UmbBlockManagerContext, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, + BlockLayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, +> extends UmbContextBase< + UmbBlockContext +> { + // + _manager?: BlockManagerContextType; + + constructor(host: UmbControllerHost, blockManagerContextToken: BlockManagerContextTokenType) { + super(host, UMB_BLOCK_ENTITY_CONTEXT.toString()); + } + + // Public methods: + + //edit? + //editSettings + //requestDelete + //delete + //copy +} + +export const UMB_BLOCK_ENTITY_CONTEXT = new UmbContextToken< + UmbBlockContext +>('UmbBlockEntryContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entity.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entity.context.ts index 9f9d417e10..4a031d2a94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entity.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entity.context.ts @@ -6,6 +6,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { encodeFilePath } from '@umbraco-cms/backoffice/utils'; +import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export abstract class UmbBlockContext< BlockManagerContextTokenType extends UmbContextToken, @@ -21,6 +22,8 @@ export abstract class UmbBlockContext< #blockTypeName = new UmbStringState(undefined); public readonly blockTypeName = this.#blockTypeName.asObservable(); + // TODO: index state + observable? + #label = new UmbStringState(''); public readonly label = this.#label.asObservable(); @@ -59,6 +62,15 @@ export abstract class UmbBlockContext< this.#layout.setValue(layout); } + /** + * Get the current value of this Blocks label. + * @method getLabel + * @returns {string} + */ + getLabel() { + return this.#label.value; + } + constructor(host: UmbControllerHost, blockManagerContextToken: BlockManagerContextTokenType) { super(host, UMB_BLOCK_ENTITY_CONTEXT.toString()); @@ -190,14 +202,34 @@ export abstract class UmbBlockContext< // Public methods: + //activate + public edit() {} + //editSettings + + requestDelete() { + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, async (modalManager) => { + const modalContext = modalManager.open(UMB_CONFIRM_MODAL, { + data: { + headline: `Delete ${this.getLabel()}`, + content: 'Are you sure you want to delete this [INSERT BLOCK TYPE NAME]?', + confirmLabel: 'Delete', + color: 'danger', + }, + }); + await modalContext.onSubmit(); + this.delete(); + }); + } public delete() { if (!this._manager) return; const contentUdi = this.#layout.value?.contentUdi; if (!contentUdi) return; this._manager.deleteBlock(contentUdi); } + + //copy } export const UMB_BLOCK_ENTITY_CONTEXT = new UmbContextToken< UmbBlockContext ->('UmbBlockContext'); +>('UmbBlockEntryContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts index 0ab646f59a..c5faa4ce6d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts @@ -10,6 +10,7 @@ import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/mod import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; // TODO: We are using backend model here, I think we should get our own model: type ElementTypeModel = UmbContentTypeModel; @@ -20,10 +21,14 @@ export abstract class UmbBlockManagerContext< > extends UmbContextBase { // #contentTypeRepository = new UmbDocumentTypeDetailRepository(this); + #workspaceModal: UmbModalRouteRegistrationController; #workspacePath = new UmbStringState(undefined); workspacePath = this.#workspacePath.asObservable(); + #propertyAlias = new UmbStringState(undefined); + propertyAlias = this.#propertyAlias.asObservable(); + #contentTypes = new UmbArrayState(>[], (x) => x.unique); public readonly contentTypes = this.#contentTypes.asObservable(); @@ -42,6 +47,14 @@ export abstract class UmbBlockManagerContext< #settings = new UmbArrayState(>[], (x) => x.udi); public readonly settings = this.#settings.asObservable(); + setPropertyAlias(alias: string) { + this.#propertyAlias.setValue(alias); + this.#workspaceModal.setUniquePathValue('propertyAlias', alias); + } + getPropertyAlias() { + this.#propertyAlias.value; + } + setEditorConfiguration(configs: UmbPropertyEditorConfigCollection) { this.#editorConfiguration.setValue(configs); } @@ -67,9 +80,18 @@ export abstract class UmbBlockManagerContext< constructor(host: UmbControllerHost) { super(host, UMB_BLOCK_MANAGER_CONTEXT); - // TODO: This might will need the property alias as part of the URL, to avoid collision if multiple of these Editor on same Node. - // IDEA: Make a Workspace registration controller that can be used to register a workspace, which does both edit and create?. - new UmbModalRouteRegistrationController(this, UMB_BLOCK_WORKSPACE_MODAL) + this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { + this.observe( + propertyContext?.alias, + (alias) => { + this.#propertyAlias.setValue(alias); + }, + 'observePropertyAlias', + ); + }); + + this.#workspaceModal = new UmbModalRouteRegistrationController(this, UMB_BLOCK_WORKSPACE_MODAL) + .addUniquePaths(['propertyAlias']) .addAdditionalPath('block') .onSetup(() => { return { data: { entityType: 'block', preset: {} }, modal: { size: 'medium' } }; @@ -191,9 +213,12 @@ export abstract class UmbBlockManagerContext< return true; } + // Idea: should we return true if it was successful? deleteBlock(contentUdi: string) { const layout = this._layouts.value.find((x) => x.contentUdi === contentUdi); - if (!layout) return; + if (!layout) { + throw new Error(`Cannot delete block, missing layout for ${contentUdi}`); + } if (layout.settingsUdi) { this.#settings.removeOne(layout.settingsUdi); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 327498248a..3582efd244 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -76,6 +76,7 @@ export class UmbBlockWorkspaceContext< } this.observe( + // TODO: Make a general concept of Block Entries Context, use it to retrieve the layout: this.#blockManager.layoutOf(unique), (layoutData) => { this.#layout.setValue(layoutData as LayoutDataType); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/sorter/sorter.controller.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/sorter/sorter.controller.test.ts deleted file mode 100644 index 26e5f4b4ea..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/sorter/sorter.controller.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { expect, fixture, html } from '@open-wc/testing'; -import { UmbSorterConfig, UmbSorterController } from './sorter.controller.js'; -import type UmbTestSorterControllerElement from './stories/test-sorter-controller.element.js'; -import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { customElement } from '@umbraco-cms/backoffice/external/lit'; - -describe('UmbContextConsumer', () => { - let hostElement: UmbTestSorterControllerElement; - - beforeEach(async () => { - hostElement = await fixture(html` `); - }); - - // TODO: Testing ideas: - // - Test that the model is updated correctly? - // - Test that the DOM is updated correctly? - // - Use the controller to sort the DOM and test that the model is updated correctly... -});