invariant ID based on Element Type
This commit is contained in:
@@ -459,13 +459,30 @@ export abstract class UmbBlockEntryContext<
|
||||
|
||||
abstract _gotContentType(contentType: UmbContentTypeModel | undefined): void;
|
||||
|
||||
#observeVariantId() {
|
||||
async #observeVariantId() {
|
||||
if (!this._manager) return;
|
||||
await this.#contentStructurePromise;
|
||||
if (!this.#contentStructure) {
|
||||
throw new Error('No contentStructure found');
|
||||
}
|
||||
|
||||
// observe blockType:
|
||||
this.observe(
|
||||
this._manager.variantId,
|
||||
(variantId) => {
|
||||
observeMultiple([
|
||||
this._manager.variantId,
|
||||
this.#contentStructure?.ownerContentTypeObservablePart((x) => x?.variesByCulture),
|
||||
this.#contentStructure?.ownerContentTypeObservablePart((x) => x?.variesBySegment),
|
||||
]),
|
||||
([variantId, variesByCulture, variesBySegment]) => {
|
||||
if (!variantId || variesByCulture === undefined || variesBySegment === undefined) return;
|
||||
if (!variesBySegment && !variesByCulture) {
|
||||
variantId = UmbVariantId.CreateInvariant();
|
||||
} else if (!variesBySegment) {
|
||||
variantId = variantId.toSegmentInvariant();
|
||||
} else if (!variesByCulture) {
|
||||
variantId = variantId.toCultureInvariant();
|
||||
}
|
||||
|
||||
this.#variantId.setValue(variantId);
|
||||
this.#gotVariantId();
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
UmbWorkspaceIsNewRedirectController,
|
||||
type ManifestWorkspace,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import { UmbClassState, UmbObjectState, UmbStringState } from '@umbraco-cms/backoffice/observable-api';
|
||||
import { UmbClassState, UmbObjectState, UmbStringState, observeMultiple } from '@umbraco-cms/backoffice/observable-api';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UMB_MODAL_CONTEXT, type UmbModalContext } from '@umbraco-cms/backoffice/modal';
|
||||
import { decodeFilePath, UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils';
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
type UmbBlockWorkspaceData,
|
||||
} from '@umbraco-cms/backoffice/block';
|
||||
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
|
||||
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
|
||||
export type UmbBlockWorkspaceElementManagerNames = 'content' | 'settings';
|
||||
export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel>
|
||||
@@ -75,18 +75,37 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
|
||||
context.onSubmit().catch(this.#modalRejected);
|
||||
}).asPromise();
|
||||
|
||||
this.#retrieveBlockManager = this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (context) => {
|
||||
this.#blockManager = context;
|
||||
this.#retrieveBlockManager = this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (manager) => {
|
||||
this.#blockManager = manager;
|
||||
|
||||
this.observe(
|
||||
context.liveEditingMode,
|
||||
manager.liveEditingMode,
|
||||
(liveEditingMode) => {
|
||||
this.#liveEditingMode = liveEditingMode;
|
||||
},
|
||||
'observeLiveEditingMode',
|
||||
);
|
||||
this.observe(context.variantId, (variantId) => {
|
||||
this.#variantId.setValue(variantId);
|
||||
});
|
||||
|
||||
this.observe(
|
||||
observeMultiple([
|
||||
manager.variantId,
|
||||
this.content.structure.variesByCulture,
|
||||
this.content.structure.variesBySegment,
|
||||
]),
|
||||
([variantId, variesByCulture, variesBySegment]) => {
|
||||
if (!variantId || variesByCulture === undefined || variesBySegment === undefined) return;
|
||||
if (!variesBySegment && !variesByCulture) {
|
||||
variantId = UmbVariantId.CreateInvariant();
|
||||
} else if (!variesBySegment) {
|
||||
variantId = variantId.toSegmentInvariant();
|
||||
} else if (!variesByCulture) {
|
||||
variantId = variantId.toCultureInvariant();
|
||||
}
|
||||
|
||||
this.#variantId.setValue(variantId);
|
||||
},
|
||||
'observeBlockType',
|
||||
);
|
||||
}).asPromise();
|
||||
|
||||
this.#retrieveBlockEntries = this.consumeContext(UMB_BLOCK_ENTRIES_CONTEXT, (context) => {
|
||||
@@ -96,23 +115,27 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
|
||||
this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
|
||||
// TODO: Ideally we move this into the Block Manager [NL] To avoid binding the Block Manager to a Property...
|
||||
// If the current property is readonly all inner block content should also be readonly.
|
||||
this.observe(context.isReadOnly, (isReadOnly) => {
|
||||
const unique = 'UMB_PROPERTY_CONTEXT';
|
||||
const variantId = this.#variantId.getValue();
|
||||
if (variantId === undefined) return;
|
||||
this.observe(
|
||||
context.isReadOnly,
|
||||
(isReadOnly) => {
|
||||
const unique = 'UMB_PROPERTY_CONTEXT';
|
||||
const variantId = this.#variantId.getValue();
|
||||
if (variantId === undefined) return;
|
||||
|
||||
if (isReadOnly) {
|
||||
const state = {
|
||||
unique,
|
||||
variantId,
|
||||
message: '',
|
||||
};
|
||||
if (isReadOnly) {
|
||||
const state = {
|
||||
unique,
|
||||
variantId,
|
||||
message: '',
|
||||
};
|
||||
|
||||
this.readOnlyState?.addState(state);
|
||||
} else {
|
||||
this.readOnlyState?.removeState(unique);
|
||||
}
|
||||
});
|
||||
this.readOnlyState?.addState(state);
|
||||
} else {
|
||||
this.readOnlyState?.removeState(unique);
|
||||
}
|
||||
},
|
||||
'observeIsReadOnly',
|
||||
);
|
||||
});
|
||||
|
||||
this.observe(this.variantId, (variantId) => {
|
||||
@@ -189,11 +212,9 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
|
||||
await this.#retrieveModalContext;
|
||||
if (!this.#blockEntries) {
|
||||
throw new Error('Block Entries not found');
|
||||
return;
|
||||
}
|
||||
if (!this.#modalContext) {
|
||||
throw new Error('Modal Context not found');
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Missing some way to append more layout data... this could be part of modal data, (or context api?)
|
||||
@@ -303,21 +324,33 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
|
||||
* in the backoffice UI.
|
||||
*/
|
||||
establishLiveSync() {
|
||||
this.observe(this.layout, (layoutData) => {
|
||||
if (layoutData) {
|
||||
this.#blockManager?.setOneLayout(layoutData, this.#modalContext?.data as UmbBlockWorkspaceData);
|
||||
}
|
||||
});
|
||||
this.observe(this.content.data, (contentData) => {
|
||||
if (contentData) {
|
||||
this.#blockManager?.setOneContent(contentData);
|
||||
}
|
||||
});
|
||||
this.observe(this.settings.data, (settingsData) => {
|
||||
if (settingsData) {
|
||||
this.#blockManager?.setOneSettings(settingsData);
|
||||
}
|
||||
});
|
||||
this.observe(
|
||||
this.layout,
|
||||
(layoutData) => {
|
||||
if (layoutData) {
|
||||
this.#blockManager?.setOneLayout(layoutData, this.#modalContext?.data as UmbBlockWorkspaceData);
|
||||
}
|
||||
},
|
||||
'observeThisLayout',
|
||||
);
|
||||
this.observe(
|
||||
this.content.data,
|
||||
(contentData) => {
|
||||
if (contentData) {
|
||||
this.#blockManager?.setOneContent(contentData);
|
||||
}
|
||||
},
|
||||
'observeThisContent',
|
||||
);
|
||||
this.observe(
|
||||
this.settings.data,
|
||||
(settingsData) => {
|
||||
if (settingsData) {
|
||||
this.#blockManager?.setOneSettings(settingsData);
|
||||
}
|
||||
},
|
||||
'observeThisSettings',
|
||||
);
|
||||
}
|
||||
|
||||
getData() {
|
||||
|
||||
@@ -76,6 +76,9 @@ export class UmbContentTypeStructureManager<
|
||||
readonly contentTypeUniques = this.#contentTypes.asObservablePart((x) => x.map((y) => y.unique));
|
||||
readonly contentTypeAliases = this.#contentTypes.asObservablePart((x) => x.map((y) => y.alias));
|
||||
|
||||
readonly variesByCulture = createObservablePart(this.ownerContentType, (x) => x?.variesByCulture);
|
||||
readonly variesBySegment = createObservablePart(this.ownerContentType, (x) => x?.variesBySegment);
|
||||
|
||||
#containers: UmbArrayState<UmbPropertyTypeContainerModel> = new UmbArrayState<UmbPropertyTypeContainerModel>(
|
||||
[],
|
||||
(x) => x.id,
|
||||
@@ -91,7 +94,7 @@ export class UmbContentTypeStructureManager<
|
||||
// Observe owner content type compositions, as we only allow one level of compositions at this moment. [NL]
|
||||
// But, we could support more, we would just need to flatMap all compositions and make sure the entries are unique and then base the observation on that. [NL]
|
||||
this.observe(this.ownerContentTypeCompositions, (ownerContentTypeCompositions) => {
|
||||
this._loadContentTypeCompositions(ownerContentTypeCompositions);
|
||||
this.#loadContentTypeCompositions(ownerContentTypeCompositions);
|
||||
});
|
||||
this.observe(this.#contentTypeContainers, (contentTypeContainers) => {
|
||||
this.#containers.setValue(contentTypeContainers);
|
||||
@@ -109,7 +112,7 @@ export class UmbContentTypeStructureManager<
|
||||
|
||||
this.#ownerContentTypeUnique = unique;
|
||||
|
||||
const promise = this._loadType(unique);
|
||||
const promise = this.#loadType(unique);
|
||||
this.#init = promise;
|
||||
await this.#init;
|
||||
return promise;
|
||||
@@ -130,7 +133,7 @@ export class UmbContentTypeStructureManager<
|
||||
|
||||
/**
|
||||
* Save the owner content type. Notice this is for a Content Type that is already stored on the server.
|
||||
* @returns boolean
|
||||
* @returns {Promise} - A promise that will be resolved when the content type is saved.
|
||||
*/
|
||||
public async save() {
|
||||
const contentType = this.getOwnerContentType();
|
||||
@@ -149,8 +152,8 @@ export class UmbContentTypeStructureManager<
|
||||
|
||||
/**
|
||||
* Create the owner content type. Notice this is for a Content Type that is NOT already stored on the server.
|
||||
* @param parentUnique
|
||||
* @returns boolean
|
||||
* @param {string | null} parentUnique - The unique of the parent content type
|
||||
* @returns {Promise} - a promise that is resolved when the content type has been created.
|
||||
*/
|
||||
public async create(parentUnique: string | null) {
|
||||
const contentType = this.getOwnerContentType();
|
||||
@@ -165,10 +168,10 @@ export class UmbContentTypeStructureManager<
|
||||
this.#contentTypes.updateOne(contentType.unique, data);
|
||||
|
||||
// Start observe the new content type in the store, as we did not do that when it was a scaffold/local-version.
|
||||
this._observeContentType(data);
|
||||
this.#observeContentType(data);
|
||||
}
|
||||
|
||||
private async _loadContentTypeCompositions(ownerContentTypeCompositions: T['compositions'] | undefined) {
|
||||
async #loadContentTypeCompositions(ownerContentTypeCompositions: T['compositions'] | undefined) {
|
||||
if (!ownerContentTypeCompositions) {
|
||||
// Owner content type was undefined, so we can not load compositions. But at this point we neither offload existing compositions, this is most likely not a case that needs to be handled.
|
||||
return;
|
||||
@@ -186,28 +189,28 @@ export class UmbContentTypeStructureManager<
|
||||
}
|
||||
});
|
||||
ownerContentTypeCompositions.forEach((composition) => {
|
||||
this._ensureType(composition.contentType.unique);
|
||||
this.#ensureType(composition.contentType.unique);
|
||||
});
|
||||
}
|
||||
|
||||
private async _ensureType(unique?: string) {
|
||||
async #ensureType(unique?: string) {
|
||||
if (!unique) return;
|
||||
if (this.#contentTypes.getValue().find((x) => x.unique === unique)) return;
|
||||
await this._loadType(unique);
|
||||
await this.#loadType(unique);
|
||||
}
|
||||
|
||||
private async _loadType(unique?: string) {
|
||||
async #loadType(unique?: string) {
|
||||
if (!unique) return {};
|
||||
|
||||
// Lets initiate the content type:
|
||||
const { data, asObservable } = await this.#repository.requestByUnique(unique);
|
||||
if (!data) return {};
|
||||
|
||||
await this._observeContentType(data);
|
||||
await this.#observeContentType(data);
|
||||
return { data, asObservable };
|
||||
}
|
||||
|
||||
private async _observeContentType(data: T) {
|
||||
async #observeContentType(data: T) {
|
||||
if (!data.unique) return;
|
||||
|
||||
// Notice we do not store the content type in the store here, cause it will happen shortly after when the observations gets its first initial callback. [NL]
|
||||
@@ -611,7 +614,6 @@ export class UmbContentTypeStructureManager<
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
hasPropertyStructuresOf(containerId: string | null) {
|
||||
return this.#contentTypes.asObservablePart((docTypes) => {
|
||||
return (
|
||||
@@ -659,7 +661,7 @@ export class UmbContentTypeStructureManager<
|
||||
ownerContainersOf(containerType: UmbPropertyContainerTypes, parentId: string | null) {
|
||||
return this.ownerContentTypeObservablePart(
|
||||
(x) =>
|
||||
x.containers?.filter(
|
||||
x?.containers?.filter(
|
||||
(x) => (parentId ? x.parent?.id === parentId : x.parent === null) && x.type === containerType,
|
||||
) ?? [],
|
||||
);
|
||||
|
||||
@@ -83,6 +83,13 @@ export class UmbVariantId {
|
||||
return { culture: this.culture, segment: this.segment };
|
||||
}
|
||||
|
||||
public toSegmentInvariant(): UmbVariantId {
|
||||
return Object.freeze(new UmbVariantId(this.culture, null));
|
||||
}
|
||||
public toCultureInvariant(): UmbVariantId {
|
||||
return Object.freeze(new UmbVariantId(null, this.culture));
|
||||
}
|
||||
|
||||
// TODO: needs localization option:
|
||||
// TODO: Consider if this should be handled else where, it does not seem like the responsibility of this class, since it contains wordings:
|
||||
public toDifferencesString(
|
||||
|
||||
Reference in New Issue
Block a user