Skip to content

Commit bf1b02b

Browse files
committed
Merge remote-tracking branch 'origin' into v14/chore/implicit-overwrite
2 parents 96844e6 + b77c9dc commit bf1b02b

File tree

12 files changed

+131
-44
lines changed

12 files changed

+131
-44
lines changed

src/libs/context-api/consume/context-consumer.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('UmbContextConsumer', () => {
3939

4040
describe('events', () => {
4141
it('dispatches context request event when constructed', async () => {
42-
const listener = oneEvent(window, UMB_CONTENT_REQUEST_EVENT_TYPE);
42+
const listener = oneEvent(window, UMB_CONTENT_REQUEST_EVENT_TYPE, false);
4343

4444
consumer.hostConnected();
4545

src/packages/block/block-grid/components/block-grid-block-inline/block-grid-inline-property-dataset.context.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ export class UmbBlockGridInlinePropertyDatasetContext extends UmbControllerBase
3939
* TODO: Write proper JSDocs here.
4040
*/
4141
async propertyValueByAlias<ReturnType = unknown>(propertyAlias: string) {
42-
return await this.#entryContext.propertyValueByAlias<ReturnType>(propertyAlias);
42+
// TODO: Investigate how I do that with the workspaces..
43+
return await this.#entryContext.contentPropertyValueByAlias<ReturnType>(propertyAlias);
4344
}
4445

4546
/**
4647
* TODO: Write proper JSDocs here.
4748
*/
4849
async setPropertyValue(propertyAlias: string, value: unknown) {
49-
return this.#entryContext.setPropertyValue(propertyAlias, value);
50+
// TODO: Investigate how I do that with the workspaces..
51+
return this.#entryContext.setContentPropertyValue(propertyAlias, value);
5052
}
5153
}

src/packages/block/block/context/block-entries.context.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export abstract class UmbBlockEntriesContext<
6262
return this._layoutEntries.setValue(layouts);
6363
}
6464
setOneLayout(layoutData: BlockLayoutType) {
65+
console.log('setOneLayout', layoutData);
6566
return this._layoutEntries.appendOne(layoutData);
6667
}
6768

src/packages/block/block/context/block-entry.context.ts

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,22 @@ export abstract class UmbBlockEntryContext<
4343
getUnique() {
4444
return this.getContentUdi();
4545
}
46-
propertyValueByAlias<ReturnType>(propertyAlias: string) {
46+
47+
setContentPropertyValue(propertyAlias: string, value: unknown) {
48+
if (!this.#contentUdi) throw new Error('No content UDI set.');
49+
this._manager?.setOneContentProperty(this.#contentUdi, propertyAlias, value);
50+
}
51+
setSettingsPropertyValue(propertyAlias: string, value: unknown) {
52+
const settingsUdi = this._layout.getValue()?.settingsUdi;
53+
if (!settingsUdi) throw new Error('Settings UDI was not available.');
54+
this._manager?.setOneSettingsProperty(settingsUdi, propertyAlias, value);
55+
}
56+
57+
contentPropertyValueByAlias<ReturnType = unknown>(propertyAlias: string) {
4758
return this.#content.asObservablePart((x) => x?.[propertyAlias] as ReturnType | undefined);
4859
}
49-
setPropertyValue(propertyAlias: string, value: unknown) {
50-
this.#content.setValue({
51-
...this.#content.getValue()!,
52-
[propertyAlias]: value,
53-
});
60+
settingsPropertyValueByAlias<ReturnType = unknown>(propertyAlias: string) {
61+
return this.#settings.asObservablePart((x) => x?.[propertyAlias] as ReturnType | undefined);
5462
}
5563

5664
#index = new UmbNumberState(undefined);
@@ -76,14 +84,17 @@ export abstract class UmbBlockEntryContext<
7684
_blockType = new UmbObjectState<BlockType | undefined>(undefined);
7785
public readonly blockType = this._blockType.asObservable();
7886
public readonly contentElementTypeKey = this._blockType.asObservablePart((x) => x?.contentElementTypeKey);
79-
public readonly settingsElementTypeKey = this._blockType.asObservablePart((x) => x?.settingsElementTypeKey);
87+
public readonly settingsElementTypeKey = this._blockType.asObservablePart((x) =>
88+
x ? x.settingsElementTypeKey ?? undefined : null,
89+
);
8090

8191
_layout = new UmbObjectState<BlockLayoutType | undefined>(undefined);
8292
public readonly layout = this._layout.asObservable();
8393
/**
8494
* @obsolete Use `unique` instead. Cause we will most likely rename this in the future.
8595
*/
8696
public readonly contentUdi = this._layout.asObservablePart((x) => x?.contentUdi);
97+
public readonly settingsUdi = this._layout.asObservablePart((x) => x?.settingsUdi);
8798
public readonly unique = this._layout.asObservablePart((x) => x?.contentUdi);
8899

89100
#label = new UmbStringState('');
@@ -114,8 +125,12 @@ export abstract class UmbBlockEntryContext<
114125

115126
#settings = new UmbObjectState<UmbBlockDataType | undefined>(undefined);
116127
public readonly settings = this.#settings.asObservable();
128+
private readonly settingsDataContentTypeKey = this.#settings.asObservablePart((x) =>
129+
x ? x.contentTypeKey ?? undefined : null,
130+
);
117131

118132
abstract readonly showContentEdit: Observable<boolean>;
133+
119134
/**
120135
* Set the contentUdi of this entry.
121136
* @method setContentUdi
@@ -176,8 +191,39 @@ export abstract class UmbBlockEntryContext<
176191
this.#observeBlockTypeLabel();
177192
});
178193

179-
this.observe(this.index, () => {
180-
this.#updateCreatePaths();
194+
// Correct settings data, accordingly to configuration of the BlockType: [NL]
195+
this.observe(
196+
observeMultiple([this.settingsElementTypeKey, this.settingsDataContentTypeKey]),
197+
([settingsElementTypeKey, settingsDataContentTypeKey]) => {
198+
// Notice the values are only undefined while we are missing the source of these observables. [NL]
199+
if (settingsElementTypeKey === undefined || settingsDataContentTypeKey === undefined) return;
200+
// Is there a difference between configuration and actual data udi:
201+
if (settingsElementTypeKey !== settingsDataContentTypeKey) {
202+
// We need to update our udi for the settings data [NL]
203+
if (settingsElementTypeKey != null) {
204+
// Update the settings model with latest elementTypeKey, so data is up to date with configuration: [NL]
205+
const currentSettings = this.#settings.getValue();
206+
if (currentSettings) {
207+
this._manager?.setOneSettings({ ...currentSettings, contentTypeKey: settingsElementTypeKey });
208+
}
209+
}
210+
// We do not need to remove the settings if configuration is gone, cause another observation handles this. [NL]
211+
}
212+
},
213+
);
214+
215+
this.observe(observeMultiple([this.layout, this.blockType]), ([layout, blockType]) => {
216+
if (!this.#contentUdi || !layout || !blockType) return;
217+
if (layout.settingsUdi == null && blockType.settingsElementTypeKey) {
218+
// We have a settings ElementType in config but not in data, so lets create the scaffold for that: [NL]
219+
const settingsData = this._manager!.createBlockSettingsData(blockType.contentElementTypeKey); // Yes its on purpose we use the contentElementTypeKey here, as this is our identifier for a BlockType. [NL]
220+
this._manager?.setOneSettings(settingsData);
221+
this._layout.update({ settingsUdi: settingsData.udi } as Partial<BlockLayoutType>);
222+
} else if (layout.settingsUdi && blockType.settingsElementTypeKey === undefined) {
223+
// We no longer have settings ElementType in config. So we remove the settingsData and settings UDI from the layout. [NL]
224+
this._manager?.removeOneSettings(layout.settingsUdi);
225+
this._layout.update({ settingsUdi: undefined } as Partial<BlockLayoutType>);
226+
}
181227
});
182228
}
183229

@@ -275,21 +321,25 @@ export abstract class UmbBlockEntryContext<
275321
const settingsUdi = this._layout.value?.settingsUdi;
276322
if (settingsUdi) {
277323
this.observe(
278-
this._manager.contentOf(settingsUdi),
279-
(content) => {
280-
this.#settings.setValue(content);
324+
this._manager.settingsOf(settingsUdi),
325+
(settings) => {
326+
this.#settings.setValue(settings);
281327
},
282328
'observeSettings',
283329
);
330+
/*
331+
332+
This two way binding does not work well, might need to further investigate what the exact problem is.
284333
this.observe(
285334
this.settings,
286335
(settings) => {
287336
if (settings) {
337+
console.log('settings to be set', this.#contentUdi, settings);
288338
this._manager?.setOneSettings(settings);
289339
}
290340
},
291341
'observeInternalSettings',
292-
);
342+
);*/
293343
}
294344
}
295345

src/packages/block/block/context/block-manager.context.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,41 @@ export abstract class UmbBlockManagerContext<
184184
this.#settings.removeOne(settingsUdi);
185185
}
186186

187+
setOneContentProperty(udi: string, propertyAlias: string, value: unknown) {
188+
this.#contents.updateOne(udi, { [propertyAlias]: value });
189+
}
190+
setOneSettingsProperty(udi: string, propertyAlias: string, value: unknown) {
191+
this.#settings.updateOne(udi, { [propertyAlias]: value });
192+
}
193+
194+
contentProperty(udi: string, propertyAlias: string) {
195+
this.#contents.asObservablePart((source) => source.find((x) => x.udi === udi)?.[propertyAlias]);
196+
}
197+
settingsProperty(udi: string, propertyAlias: string) {
198+
this.#contents.asObservablePart((source) => source.find((x) => x.udi === udi)?.[propertyAlias]);
199+
}
200+
187201
abstract create(
188202
contentElementTypeKey: string,
189203
partialLayoutEntry?: Omit<BlockLayoutType, 'contentUdi'>,
190204
modalData?: UmbBlockWorkspaceData,
191205
): UmbBlockDataObjectModel<BlockLayoutType> | undefined;
192206

207+
public createBlockSettingsData(contentElementTypeKey: string) {
208+
const blockType = this.#blockTypes.value.find((x) => x.contentElementTypeKey === contentElementTypeKey);
209+
if (!blockType) {
210+
throw new Error(`Cannot create block settings, missing block type for ${contentElementTypeKey}`);
211+
}
212+
if (!blockType.settingsElementTypeKey) {
213+
throw new Error(`Cannot create block settings, missing settings element type for ${contentElementTypeKey}`);
214+
}
215+
216+
return {
217+
udi: buildUdi('element', UmbId.new()),
218+
contentTypeKey: blockType.settingsElementTypeKey,
219+
};
220+
}
221+
193222
protected createBlockData(contentElementTypeKey: string, partialLayoutEntry?: Omit<BlockLayoutType, 'contentUdi'>) {
194223
// Find block type.
195224
const blockType = this.#blockTypes.value.find((x) => x.contentElementTypeKey === contentElementTypeKey);

src/packages/block/block/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export interface UmbBlockLayoutBaseModel {
22
contentUdi: string;
3-
settingsUdi?: string;
3+
settingsUdi?: string | null;
44
}
55

66
export interface UmbBlockDataType {

src/packages/block/block/workspace/block-workspace.context.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -137,24 +137,26 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
137137

138138
// Content:
139139
const contentUdi = layoutData?.contentUdi;
140-
if (contentUdi) {
140+
if (!contentUdi) {
141+
return;
142+
}
143+
144+
this.observe(
145+
this.#blockManager!.contentOf(contentUdi),
146+
(contentData) => {
147+
this.content.setData(contentData);
148+
},
149+
'observeContent',
150+
);
151+
if (!this.#initialContent) {
141152
this.observe(
142153
this.#blockManager!.contentOf(contentUdi),
143154
(contentData) => {
144-
this.content.setData(contentData);
155+
this.#initialContent ??= contentData;
156+
this.removeUmbControllerByAlias('observeContentInitially');
145157
},
146-
'observeContent',
158+
'observeContentInitially',
147159
);
148-
if (!this.#initialContent) {
149-
this.observe(
150-
this.#blockManager!.contentOf(contentUdi),
151-
(contentData) => {
152-
this.#initialContent ??= contentData;
153-
this.removeUmbControllerByAlias('observeContentInitially');
154-
},
155-
'observeContentInitially',
156-
);
157-
}
158160
}
159161

160162
// Settings:
@@ -169,7 +171,7 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
169171
);
170172
if (!this.#initialSettings) {
171173
this.observe(
172-
this.#blockManager!.contentOf(settingsUdi),
174+
this.#blockManager!.settingsOf(settingsUdi),
173175
(settingsData) => {
174176
this.#initialSettings ??= settingsData;
175177
this.removeUmbControllerByAlias('observeSettingsInitially');

src/packages/core/property/property-dataset/property-dataset.element.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ describe('UmbBasicVariantElement', () => {
133133
});
134134

135135
it('fires change event', async () => {
136-
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE);
136+
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE, false);
137137

138138
expect(propertyEditor.alias).to.eq('testAlias');
139139
propertyEditor.setValue('testValue3');
@@ -153,7 +153,7 @@ describe('UmbBasicVariantElement', () => {
153153
adapterPropertyEditor.alias = 'testAdapterAlias';
154154
datasetElement.appendChild(adapterPropertyEditor);
155155

156-
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE);
156+
const listener = oneEvent(datasetElement, UmbChangeEvent.TYPE, false);
157157

158158
// The alias of the original property editor must be 'testAlias' for the adapter to set the value of it.
159159
expect(propertyEditor.alias).to.eq('testAlias');

src/packages/core/utils/pagination-manager/pagination.manager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ describe('UmbPaginationManager', () => {
141141
});
142142

143143
it('dispatches a change event', async () => {
144-
const listener = oneEvent(manager, UmbChangeEvent.TYPE);
144+
const listener = oneEvent(manager, UmbChangeEvent.TYPE, false);
145145
manager.setCurrentPageNumber(2);
146146
const event = (await listener) as unknown as UmbChangeEvent;
147147
const target = event.target as UmbPaginationManager;

src/packages/core/utils/string/split-string-to-array.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
* Splits a string into an array using a specified delimiter,
33
* trims whitespace from each element, and removes empty elements.
44
*
5-
* @param {string} string - The input string to be split and processed.
5+
* @param {string | undefined} string - The input string to be split and processed.
66
* @param {string} [split=','] - The delimiter used for splitting the string (default is comma).
7-
* @returns {string[]} An array of non-empty, trimmed strings.
7+
* @returns {Array<string>} An array of non-empty, trimmed strings.
88
*
99
* @example
1010
* const result = splitStringToArray('one, two, three, ,five');
@@ -14,7 +14,7 @@
1414
* const customDelimiterResult = splitStringToArray('apple | orange | banana', ' | ');
1515
* // customDelimiterResult: ['apple', 'orange', 'banana']
1616
*/
17-
export function splitStringToArray(string: string, split: string = ','): string[] {
17+
export function splitStringToArray(string: string | undefined, split: string = ','): string[] {
1818
if (!string) return [];
1919
return (
2020
string

0 commit comments

Comments
 (0)