From 35113f797ca3e48215529c4dd32e88f93e4d96a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 21 May 2024 23:24:58 +0200 Subject: [PATCH] re-introduce two-way-binding --- .../block-grid-entries.element.ts | 2 - .../context/block-grid-entries.context.ts | 21 +++ .../context/block-grid-entry.context.ts | 48 ++++-- .../context/block-grid-manager.context.ts | 144 ------------------ .../context/block-list-entries.context.ts | 7 + .../context/block-list-manager.context.ts | 5 - .../block/context/block-entries.context.ts | 7 +- .../block/context/block-entry.context.ts | 9 ++ .../block/context/block-manager.context.ts | 9 +- .../workspace/block-workspace.context.ts | 6 +- 10 files changed, 83 insertions(+), 175 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts index 3eb864d549..fe7917928c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts @@ -112,8 +112,6 @@ export class UmbBlockGridEntriesElement extends UmbLitElement { this.#context.onDragEnd(); }, onChange: ({ model }) => { - // TODO: There is some problem with sorting.. - console.log('sort change'); this.#context.setLayouts(model); }, onRequestMove: ({ item }) => { 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 index 4f944c690c..7b24b49f4d 100644 --- 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 @@ -163,6 +163,15 @@ export class UmbBlockGridEntriesContext }, 'observeParentLayouts', ); + this.observe( + this.layoutEntries, + (layouts) => { + this._manager?.setLayouts(layouts); + }, + 'observeThisLayouts', + ); + + this.removeUmbControllerByAlias('observeAreaType'); const hostEl = this.getHostElement() as HTMLElement | undefined; if (hostEl) { @@ -196,6 +205,16 @@ export class UmbBlockGridEntriesContext 'observeParentLayouts', ); + this.observe( + this.layoutEntries, + (layouts) => { + if (this.#areaKey) { + this.#parentEntry?.setLayoutsOfArea(this.#areaKey, layouts); + } + }, + 'observeThisLayouts', + ); + this.observe( this.#parentEntry.areaType(this.#areaKey), (areaType) => { @@ -229,6 +248,7 @@ export class UmbBlockGridEntriesContext return this._catalogueRouteBuilderState.getValue()?.({ view: 'clipboard', index: index }); } + /* async setLayouts(layouts: Array) { await this._retrieveManager; if (this.#areaKey === null) { @@ -240,6 +260,7 @@ export class UmbBlockGridEntriesContext this._manager?.setLayoutsOfArea(this.#parentUnique, this.#areaKey, layouts); } } + */ async create( contentElementTypeKey: string, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts index 6f7216e83e..7eeb562cd1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts @@ -14,6 +14,7 @@ import { UmbBooleanState, UmbNumberState, UmbObjectState, + appendToFrozenArray, observeMultiple, } from '@umbraco-cms/backoffice/observable-api'; @@ -76,6 +77,20 @@ export class UmbBlockGridEntryContext return this._blockType.asObservablePart((x) => x?.areas?.find((x) => x.key === areaKey)); } + setLayoutsOfArea(areaKey: string, layouts: UmbBlockGridLayoutModel[]) { + const frozenValue = this._layout.value; + if (!frozenValue) return; + const areas = appendToFrozenArray( + frozenValue?.areas ?? [], + { + key: areaKey, + items: layouts, + }, + (x) => x.key, + ); + this._layout.update({ areas }); + } + /** * Set the column span of this entry. * @param columnSpan {number} The new column span. @@ -88,9 +103,10 @@ export class UmbBlockGridEntryContext columnSpan = this.#calcColumnSpan(columnSpan, this.getRelevantColumnSpanOptions(), layoutColumns); if (columnSpan === this.getColumnSpan()) return; //this._layout.update({ columnSpan }); - const contentUdi = this.getContentUdi(); - if (!contentUdi) return; - this._manager?.updateLayout({ contentUdi, columnSpan }); + //const contentUdi = this.getContentUdi(); + //if (!contentUdi) return; + //this._manager?.updateLayout({ contentUdi, columnSpan }); + this._layout.update({ columnSpan }); } /** * Get the column span of this entry. @@ -110,9 +126,10 @@ export class UmbBlockGridEntryContext rowSpan = Math.max(minMax[0], Math.min(rowSpan, minMax[1])); if (rowSpan === this.getRowSpan()) return; //this._layout.update({ rowSpan }); - const contentUdi = this.getContentUdi(); - if (!contentUdi) return; - this._manager?.updateLayout({ contentUdi, rowSpan }); + //const contentUdi = this.getContentUdi(); + //if (!contentUdi) return; + //this._manager?.updateLayout({ contentUdi, rowSpan }); + this._layout.update({ rowSpan }); } /** * Get the row span of this entry. @@ -176,12 +193,17 @@ export class UmbBlockGridEntryContext const areasAreIdentical = areas.length === layoutAreas.length && areas.every((area) => layoutAreas.some((y) => y.key === area.key)); if (areasAreIdentical === false) { + /* const contentUdi = this.getContentUdi(); if (!contentUdi) return; this._manager?.updateLayout({ contentUdi, areas: layoutAreas.map((x) => (areas.find((y) => y.key === x.key) ? x : { key: x.key, items: [] })), }); + */ + this._layout.update({ + areas: layoutAreas.map((x) => (areas.find((y) => y.key === x.key) ? x : { key: x.key, items: [] })), + }); } }, 'observeAreaValidation', @@ -199,9 +221,10 @@ export class UmbBlockGridEntryContext layoutColumns, ); if (newColumnSpan !== columnSpan) { - const contentUdi = this.getContentUdi(); - if (!contentUdi) return; - this._manager?.updateLayout({ contentUdi, columnSpan: newColumnSpan }); + //const contentUdi = this.getContentUdi(); + //if (!contentUdi) return; + //this._manager?.updateLayout({ contentUdi, columnSpan: newColumnSpan }); + this._layout.update({ columnSpan: newColumnSpan }); } }, 'observeColumnSpanValidation', @@ -215,9 +238,10 @@ export class UmbBlockGridEntryContext if (minMax) { const newRowSpan = Math.max(minMax[0], Math.min(rowSpan ?? 1, minMax[1])); if (newRowSpan !== rowSpan) { - const contentUdi = this.getContentUdi(); - if (!contentUdi) return; - this._manager!.updateLayout({ contentUdi, rowSpan: newRowSpan }); + //const contentUdi = this.getContentUdi(); + //if (!contentUdi) return; + //this._manager!.updateLayout({ contentUdi, rowSpan: newRowSpan }); + this._layout.update({ rowSpan: newRowSpan }); } } }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts index d6e042d27f..a2d7737ec8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-manager.context.ts @@ -32,83 +32,6 @@ export class UmbBlockGridManagerContext< return this.#blockGroups.value; } - /** - * Inserts a layout entry into an area of a layout entry. - * @param newEntries The layout entry to insert. - * @param entries The layout entries to search within. - * @param parentUnique The parentUnique to search for. - * @param areaKey The areaKey to insert the layout entry into. - * @returns a updated layout entries array if the insert was successful. - * - * @remarks - * This method is recursive and will search for the parentUnique in the layout entries. - * If the parentUnique is found, the layout entry will be inserted into the items of the area that matches the areaKey. - * This returns a new array of layout entries with the updated layout entry inserted. - * Because the layout entries are frozen, the affected parts is replaced with a new. Only updating/unfreezing the affected part of the structure. - */ - #setLayoutsToArea( - newEntries: Array, - entries: Array, - parentUnique: string, - areaKey: string, - ): Array | undefined { - // I'm sorry, this code is not easy to read or maintain [NL] - let i: number = entries.length; - while (i--) { - const currentEntry = entries[i]; - // Lets check if we found the right parent layout entry: - if (currentEntry.contentUdi === parentUnique) { - // Append the layout entry to be inserted and unfreeze the rest of the data: - const areas = currentEntry.areas.map((x) => (x.key === areaKey ? { ...x, items: newEntries } : x)); - return appendToFrozenArray( - entries, - { - ...currentEntry, - areas, - }, - (x) => x.contentUdi === currentEntry.contentUdi, - ); - } - // Otherwise check if any items of the areas are the parent layout entry we are looking for. We do so based on parentId, recursively: - let y: number = currentEntry.areas?.length; - while (y--) { - // Recursively ask the items of this area to insert the layout entry, if something returns there was a match in this branch. [NL] - const correctedAreaItems = this.#setLayoutsToArea( - newEntries, - currentEntry.areas[y].items, - parentUnique, - areaKey, - ); - if (correctedAreaItems) { - // This area got a corrected set of items, lets append those to the area and unfreeze the surrounding data: - const area = currentEntry.areas[y]; - return appendToFrozenArray( - entries, - { - ...currentEntry, - areas: appendToFrozenArray( - currentEntry.areas, - { ...area, items: correctedAreaItems }, - (z) => z.key === area.key, - ), - }, - (x) => x.contentUdi === currentEntry.contentUdi, - ); - } - } - } - return undefined; - } - - setLayoutsOfArea(parentUnique: string, areaKey: string, layouts: Array) { - const frozenValue = this._layouts.value; - if (!frozenValue) return; - const layoutEntries = this.#setLayoutsToArea(layouts, this._layouts.getValue(), parentUnique, areaKey); - if (layoutEntries) { - this._layouts.setValue(layoutEntries); - } - } - create( contentElementTypeKey: string, partialLayoutEntry?: Omit, @@ -224,73 +147,6 @@ export class UmbBlockGridManagerContext< return true; } - /** - * Updates a layout entry of an area of a layout entry. - * @param entryUpdate The partial object of the layout entry to update. - * @param entries The current array of entries to search and eventually update in. - * @returns a updated layout entries array if the update was successful. - * - * @remarks - * This method is recursive and will search for the contentUdi in the layout entries. - * If entry with the contentUdi is found, the layout entry will be updated. - * This returns a new array of layout entries with the updated layout entry. - * Because the layout entries are frozen, the affected parts is replaced with a new. Only updating/unfreezing the affected part of the structure. - */ - #updateLayoutEntry( - entryUpdate: Partial & Pick, - entries: Array, - ): Array | undefined { - // I'm sorry, this code is not easy to read or maintain [NL] - let i: number = entries.length; - while (i--) { - const entry = entries[i]; - // Check if the item we are looking for is this entry: - if (entry.contentUdi === entryUpdate.contentUdi) { - // Append the layout entry to be inserted and unfreeze the rest of the data: - /*return appendToFrozenArray( - entries, - { - ...entryUpdate, - }, - (x) => x.contentUdi === entry.contentUdi, - );*/ - return partialUpdateFrozenArray(entries, entryUpdate, (x) => x.contentUdi === entryUpdate.contentUdi); - } - // Otherwise check if any items of the areas are the parent layout entry we are looking for. We do so based on parentId, recursively: - let y: number = entry.areas?.length; - while (y--) { - // Recursively ask the items of this area to insert the layout entry, if something returns there was a match in this branch. [NL] - const correctedAreaItems = this.#updateLayoutEntry(entryUpdate, entry.areas[y].items); - if (correctedAreaItems) { - // This area got a corrected set of items, lets append those to the area and unfreeze the surrounding data: - const area = entry.areas[y]; - return appendToFrozenArray( - entries, - { - ...entry, - areas: appendToFrozenArray( - entry.areas, - { ...area, items: correctedAreaItems }, - (z) => z.key === area.key, - ), - }, - (x) => x.contentUdi === entry.contentUdi, - ); - } - } - } - return undefined; - } - - updateLayout(layoutEntry: Partial & Pick) { - const layoutEntries = this.#updateLayoutEntry(layoutEntry, this._layouts.getValue()); - if (layoutEntries) { - this._layouts.setValue(layoutEntries); - return true; - } - return false; - } - onDragStart() { (this.getHostElement() as HTMLElement).style.setProperty('--umb-block-grid--is-dragging', ' '); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts index 3fa70a0c1f..f3c7ea6b97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-entries.context.ts @@ -52,6 +52,13 @@ export class UmbBlockListEntriesContext extends UmbBlockEntriesContext< }, 'observeParentLayouts', ); + this.observe( + this.layoutEntries, + (layouts) => { + this._manager?.setLayouts(layouts); + }, + 'observeThisLayouts', + ); this.observe( this._manager.propertyAlias, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts index 9bc8080b57..cf7b2a3130 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/context/block-list-manager.context.ts @@ -39,11 +39,6 @@ export class UmbBlockListManagerContext< return true; } - - updateLayout(layoutEntry: Partial & Pick): boolean { - this._layouts.updateOne(layoutEntry.contentUdi, layoutEntry); - return true; // Should have returned false if it did not find the one to update.. but in this case we just insert it if it does not exist. [NL] - } } // TODO: Make discriminator method for this: diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts index dd21f240c3..0e375270b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts @@ -87,7 +87,12 @@ export abstract class UmbBlockEntriesContext< getLayoutOf(contentUdi: string) { return this._layoutEntries.getValue().find((x) => x.contentUdi === contentUdi); } - abstract setLayouts(layouts: Array): Promise; + setLayouts(layouts: Array) { + return this._layoutEntries.setValue(layouts); + } + setOneLayout(layoutData: BlockLayoutType) { + return this._layoutEntries.appendOne(layoutData); + } public abstract getPathForCreateBlock(index: number): string | undefined; public abstract getPathForClipboard(index: number): string | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index 29000cc365..ad79fc4d13 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -208,6 +208,15 @@ export abstract class UmbBlockEntryContext< }, 'observeParentLayout', ); + this.observe( + this.layout, + (layout) => { + if (layout) { + this._entries?.setOneLayout(layout); + } + }, + 'observeThisLayout', + ); } #gotManager() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index 471f5c7b5c..4f86a9475e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -79,10 +79,6 @@ export abstract class UmbBlockManagerContext< setLayouts(layouts: Array) { this._layouts.setValue(layouts); } - // TODO: Remove this as it is just for debug purpose...? - getLayouts(): Array { - return this._layouts.getValue(); - } setContents(contents: Array) { this.#contents.setValue(contents); } @@ -169,8 +165,7 @@ export abstract class UmbBlockManagerContext< } setOneLayout(layoutData: BlockLayoutType) { - //return this._layouts.appendOne(layoutData); - this.updateLayout(layoutData); + this._layouts.appendOne(layoutData); } setOneContent(contentData: UmbBlockDataType) { this.#contents.appendOne(contentData); @@ -236,8 +231,6 @@ export abstract class UmbBlockManagerContext< modalData: UmbBlockWorkspaceData, ): boolean; - abstract updateLayout(layoutEntry: Partial & Pick): boolean; - protected insertBlockData( layoutEntry: BlockLayoutType, content: UmbBlockDataType, 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 12335edf35..624e93d557 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 @@ -242,7 +242,7 @@ export class UmbBlockWorkspaceContext { if (layoutData) { - this.#blockManager?.updateLayout(layoutData); + this.#blockManager?.setOneLayout(layoutData); } }); this.observe(this.content.data, (contentData) => { @@ -324,7 +324,7 @@ export class UmbBlockWorkspaceContext