re-introduce two-way-binding

This commit is contained in:
Niels Lyngsø
2024-05-21 23:24:58 +02:00
parent 2dab1b8a8d
commit 35113f797c
10 changed files with 83 additions and 175 deletions

View File

@@ -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 }) => {

View File

@@ -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<UmbBlockGridLayoutModel>) {
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,

View File

@@ -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 });
}
}
},

View File

@@ -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<UmbBlockGridLayoutModel>,
entries: Array<UmbBlockGridLayoutModel>,
parentUnique: string,
areaKey: string,
): Array<UmbBlockGridLayoutModel> | 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<BlockLayoutType>) {
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<BlockLayoutType, 'contentUdi'>,
@@ -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<BlockLayoutType> & Pick<BlockLayoutType, 'contentUdi'>,
entries: Array<UmbBlockGridLayoutModel>,
): Array<UmbBlockGridLayoutModel> | 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<BlockLayoutType> & Pick<BlockLayoutType, 'contentUdi'>) {
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', ' ');
}

View File

@@ -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,

View File

@@ -39,11 +39,6 @@ export class UmbBlockListManagerContext<
return true;
}
updateLayout(layoutEntry: Partial<BlockLayoutType> & Pick<BlockLayoutType, 'contentUdi'>): 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:

View File

@@ -87,7 +87,12 @@ export abstract class UmbBlockEntriesContext<
getLayoutOf(contentUdi: string) {
return this._layoutEntries.getValue().find((x) => x.contentUdi === contentUdi);
}
abstract setLayouts(layouts: Array<BlockLayoutType>): Promise<void>;
setLayouts(layouts: Array<BlockLayoutType>) {
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;

View File

@@ -208,6 +208,15 @@ export abstract class UmbBlockEntryContext<
},
'observeParentLayout',
);
this.observe(
this.layout,
(layout) => {
if (layout) {
this._entries?.setOneLayout(layout);
}
},
'observeThisLayout',
);
}
#gotManager() {

View File

@@ -79,10 +79,6 @@ export abstract class UmbBlockManagerContext<
setLayouts(layouts: Array<BlockLayoutType>) {
this._layouts.setValue(layouts);
}
// TODO: Remove this as it is just for debug purpose...?
getLayouts(): Array<BlockLayoutType> {
return this._layouts.getValue();
}
setContents(contents: Array<UmbBlockDataType>) {
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<BlockLayoutType> & Pick<BlockLayoutType, 'contentUdi'>): boolean;
protected insertBlockData<ModalDataType extends UmbBlockWorkspaceData>(
layoutEntry: BlockLayoutType,
content: UmbBlockDataType,

View File

@@ -242,7 +242,7 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
#establishLiveSync() {
this.observe(this.layout, (layoutData) => {
if (layoutData) {
this.#blockManager?.updateLayout(layoutData);
this.#blockManager?.setOneLayout(layoutData);
}
});
this.observe(this.content.data, (contentData) => {
@@ -324,7 +324,7 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
} else {
// Update data:
this.#blockManager.updateLayout(layoutData);
this.#blockManager.setOneLayout(layoutData);
if (contentData) {
this.#blockManager.setOneContent(contentData);
}
@@ -350,7 +350,7 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
} else {
// TODO: Revert the layout, content & settings data to the original state.
if (this.#initialLayout) {
this.#blockManager?.updateLayout(this.#initialLayout);
this.#blockManager?.setOneLayout(this.#initialLayout);
}
if (this.#initialContent) {
this.#blockManager?.setOneContent(this.#initialContent);