refactor block workspace and co

This commit is contained in:
Niels Lyngsø
2024-10-11 10:35:18 +02:00
parent 7fef7ffcdb
commit c4d17a8d33
36 changed files with 733 additions and 490 deletions

View File

@@ -1,6 +1,6 @@
import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js';
import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js';
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
import type {
UmbInvariantDatasetWorkspaceContext,
@@ -12,9 +12,11 @@ import {
UmbInvariantWorkspacePropertyDatasetContext,
UmbWorkspaceIsNewRedirectController,
UmbWorkspaceIsNewRedirectControllerAlias,
umbObjectToPropertyValueArray,
} from '@umbraco-cms/backoffice/workspace';
import { UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeWithGroupKey = UmbBlockTypeWithGroupKey>
extends UmbSubmittableWorkspaceContextBase<BlockTypeData>
@@ -25,12 +27,18 @@ export class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlockTypeWith
#entityType: string;
#data = new UmbObjectState<BlockTypeData | undefined>(undefined);
//readonly data = this.#data.asObservable();
readonly data = this.#data.asObservable();
// TODO: Get the name of the contentElementType..
readonly name = this.#data.asObservablePart(() => 'block');
readonly name = this.#data.asObservablePart(() => 'block type');
readonly unique = this.#data.asObservablePart((data) => data?.contentElementTypeKey);
readonly values = this.#data.asObservablePart((data) => {
return umbObjectToPropertyValueArray(data);
});
async getValues(): Promise<Array<UmbPropertyValueData> | undefined> {
return umbObjectToPropertyValueArray(await firstValueFrom(this.data));
}
constructor(host: UmbControllerHost, args: { manifest: ManifestWorkspace }) {
super(host, args.manifest.alias);
const manifest = args.manifest;

View File

@@ -1,14 +1,14 @@
import type { UmbBlockDataValueModel, UmbBlockExposeModel, UmbBlockValueDataPropertiesBaseType } from '../types.js';
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbPropertyValueResolver } from '@umbraco-cms/backoffice/property';
export abstract class UmbBlockValueResolver<ValueType>
implements UmbPropertyValueResolver<UmbContentValueModel<ValueType>, UmbBlockDataValueModel, UmbBlockExposeModel>
implements UmbPropertyValueResolver<UmbElementValueModel<ValueType>, UmbBlockDataValueModel, UmbBlockExposeModel>
{
abstract processValues(
property: UmbContentValueModel<ValueType>,
property: UmbElementValueModel<ValueType>,
valuesCallback: (values: Array<UmbBlockDataValueModel>) => Promise<Array<UmbBlockDataValueModel> | undefined>,
): Promise<UmbContentValueModel<ValueType>>;
): Promise<UmbElementValueModel<ValueType>>;
protected async _processValueBlockData<ValueType extends UmbBlockValueDataPropertiesBaseType>(
value: ValueType,
@@ -30,9 +30,9 @@ export abstract class UmbBlockValueResolver<ValueType>
}
abstract processVariants(
property: UmbContentValueModel<ValueType>,
property: UmbElementValueModel<ValueType>,
variantsCallback: (values: Array<UmbBlockExposeModel>) => Promise<Array<UmbBlockExposeModel> | undefined>,
): Promise<UmbContentValueModel<ValueType>>;
): Promise<UmbElementValueModel<ValueType>>;
protected async _processVariantBlockData<ValueType extends UmbBlockValueDataPropertiesBaseType>(
value: ValueType,

View File

@@ -1,10 +1,10 @@
import type { UmbBlockDataValueModel, UmbBlockExposeModel, UmbBlockValueType } from '../types.js';
import { UmbBlockValueResolver } from './block-value-resolver.api.js';
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export class UmbStandardBlockValueResolver extends UmbBlockValueResolver<UmbBlockValueType> {
async processValues(
property: UmbContentValueModel<UmbBlockValueType>,
property: UmbElementValueModel<UmbBlockValueType>,
valuesCallback: (values: Array<UmbBlockDataValueModel>) => Promise<Array<UmbBlockDataValueModel> | undefined>,
) {
if (property.value) {
@@ -17,7 +17,7 @@ export class UmbStandardBlockValueResolver extends UmbBlockValueResolver<UmbBloc
}
async processVariants(
property: UmbContentValueModel<UmbBlockValueType>,
property: UmbElementValueModel<UmbBlockValueType>,
variantsCallback: (values: Array<UmbBlockExposeModel>) => Promise<Array<UmbBlockExposeModel> | undefined>,
) {
if (property.value) {

View File

@@ -1,4 +1,4 @@
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export interface UmbBlockLayoutBaseModel {
contentKey: string;
@@ -6,7 +6,7 @@ export interface UmbBlockLayoutBaseModel {
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbBlockDataValueModel<ValueType = unknown> extends UmbContentValueModel<ValueType> {}
export interface UmbBlockDataValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
export interface UmbBlockDataModel {
key: string;

View File

@@ -5,7 +5,6 @@ import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-
import {
type Observable,
UmbClassState,
UmbObjectState,
appendToFrozenArray,
mergeObservables,
} from '@umbraco-cms/backoffice/observable-api';
@@ -14,27 +13,41 @@ import { type UmbClassInterface, UmbControllerBase } from '@umbraco-cms/backoffi
import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbValidationController } from '@umbraco-cms/backoffice/validation';
import { UmbElementWorkspaceDataManager, type UmbElementPropertyDataOwner } from '@umbraco-cms/backoffice/content';
import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils';
export class UmbBlockElementManager extends UmbControllerBase {
import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type';
export class UmbBlockElementManager
extends UmbControllerBase
implements UmbElementPropertyDataOwner<UmbBlockDataModel, UmbContentTypeModel>
{
//
#data = new UmbObjectState<UmbBlockDataModel | undefined>(undefined);
readonly data = this.#data.asObservable();
readonly #data = new UmbElementWorkspaceDataManager<UmbBlockDataModel>(this);
//#data = new UmbObjectState<UmbBlockDataModel | undefined>(undefined);
readonly data = this.#data.current;
#getDataPromise = new Promise<void>((resolve) => {
this.#getDataResolver = resolve;
});
#getDataResolver!: () => void;
public readonly readOnlyState = new UmbReadOnlyVariantStateManager(this);
#variantId = new UmbClassState<UmbVariantId | undefined>(undefined);
readonly variantId = this.#variantId.asObservable();
readonly unique = this.#data.asObservablePart((data) => data?.key);
readonly contentTypeId = this.#data.asObservablePart((data) => data?.contentTypeKey);
readonly unique = this.#data.createObservablePartOfCurrent((data) => data?.key);
readonly contentTypeId = this.#data.createObservablePartOfCurrent((data) => data?.contentTypeKey);
readonly values = this.#data.asObservablePart((data) => data?.values);
readonly values = this.#data.createObservablePartOfCurrent((data) => data?.values);
getValues() {
return this.#data.getValue()?.values;
return this.#data.getCurrent()?.values;
}
readonly #dataTypeItemManager = new UmbDataTypeItemRepositoryManager(this);
#dataTypeSchemaAliasMap = new Map<string, string>();
readonly structure = new UmbContentTypeStructureManager<UmbContentTypeModel>(
this,
new UmbDocumentTypeDetailRepository(this),
@@ -51,10 +64,34 @@ export class UmbBlockElementManager extends UmbControllerBase {
this.validation.setDataPath('$.' + dataPathPropertyName + `[?(@.key = '${key}')]`);
}
});
this.observe(
this.structure.contentTypeDataTypeUniques,
(dataTypeUniques: Array<string>) => {
this.#dataTypeItemManager.setUniques(dataTypeUniques);
},
null,
);
this.observe(
this.#dataTypeItemManager.items,
(dataTypes) => {
// Make a map of the data type unique and editorAlias:
this.#dataTypeSchemaAliasMap = new Map(
dataTypes.map((dataType) => {
return [dataType.unique, dataType.propertyEditorSchemaAlias];
}),
);
},
null,
);
}
reset() {
this.#data.setValue(undefined);
public isLoaded() {
return this.#getDataPromise;
}
resetState() {
this.#data.clear();
}
setVariantId(variantId: UmbVariantId | undefined) {
@@ -66,12 +103,13 @@ export class UmbBlockElementManager extends UmbControllerBase {
// TODO: rename to currentData:
setData(data: UmbBlockDataModel | undefined) {
this.#data.setValue(data);
this.#data.setPersisted(data);
this.#data.setCurrent(data);
this.#getDataResolver();
}
getData() {
return this.#data.getValue();
return this.#data.getCurrent();
}
getUnique() {
@@ -105,100 +143,79 @@ export class UmbBlockElementManager extends UmbControllerBase {
/**
* @function propertyValueByAlias
* @param {string} propertyAlias - Property Alias to observe the value of.
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - Promise which resolves to an Observable
* @param {string} propertyAlias - The alias of the property
* @param {UmbVariantId} variantId - The variant
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - An observable for the value of the property
* @description Get an Observable for the value of this property.
*/
async propertyValueByAlias<PropertyValueType = unknown>(
propertyAlias: string,
variantId?: UmbVariantId,
): Promise<Observable<PropertyValueType | undefined> | undefined> {
await this.#getDataPromise;
return mergeObservables(
[
this.#data.asObservablePart((data) => data?.values?.filter((x) => x?.alias === propertyAlias)),
await this.propertyVariantId(propertyAlias),
],
([propertyValues, propertyVariantId]) => {
if (!propertyValues || !propertyVariantId) return;
return propertyValues.find((x) => propertyVariantId.compare(x))?.value as PropertyValueType;
},
return this.#data.createObservablePartOfCurrent(
(data) =>
data?.values?.find((x) => x?.alias === propertyAlias && (variantId ? variantId.compare(x) : true))
?.value as PropertyValueType,
);
}
/**
* Get the current value of the property with the given alias and variantId.
* @param {string} alias - The alias of the property
* @returns {ReturnType} The value or undefined if not set or found.
* @param {UmbVariantId | undefined} variantId - The variant id of the property
* @returns {ReturnType | undefined} The value or undefined if not set or found.
*/
async getPropertyValue<ReturnType = unknown>(alias: string) {
await this.#getDataPromise;
const managerVariantId = this.#variantId.getValue();
if (!managerVariantId) return;
const property = await this.structure.getPropertyStructureByAlias(alias);
if (!property) return;
const variantId = this.#createPropertyVariantId(property, managerVariantId);
const currentData = this.getData();
if (!currentData) return;
const newDataSet = currentData.values?.find((x) => x.alias === alias && (variantId ? variantId.compare(x) : true));
return newDataSet?.value as ReturnType;
getPropertyValue<ReturnType = unknown>(alias: string, variantId?: UmbVariantId) {
const currentData = this.#data.getCurrent();
if (currentData) {
const newDataSet = currentData.values?.find(
(x) => x.alias === alias && (variantId ? variantId.compare(x) : true),
);
return newDataSet?.value as ReturnType;
}
return undefined;
}
/**
* @function setPropertyValue
* @param {string} alias - The alias of the property
* @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self.
* @returns {Promise<void>}
* @description Set the value of this property.
*/
async setPropertyValue<ValueType = unknown>(alias: string, value: ValueType) {
async setPropertyValue<ValueType = unknown>(alias: string, value: ValueType, variantId?: UmbVariantId) {
this.initiatePropertyValueChange();
await this.#getDataPromise;
const managerVariantId = this.#variantId.getValue();
if (!managerVariantId) return;
variantId ??= UmbVariantId.CreateInvariant();
const property = await this.structure.getPropertyStructureByAlias(alias);
if (!property) return;
const variantId = this.#createPropertyVariantId(property, managerVariantId);
const entry = { ...variantId.toObject(), alias, value } as UmbBlockDataValueModel<ValueType>;
if (!property) {
throw new Error(`Property alias "${alias}" not found.`);
}
const editorAlias = this.#dataTypeSchemaAliasMap.get(property.dataType.unique);
if (!editorAlias) {
throw new Error(`Editor Alias of "${property.dataType.unique}" not found.`);
}
const entry = { ...variantId.toObject(), alias, editorAlias, value } as UmbBlockDataValueModel<ValueType>;
const currentData = this.getData();
if (currentData) {
const values = appendToFrozenArray(
currentData.values ?? [],
entry,
(x) => x.alias === alias && variantId.compare(x),
(x) => x.alias === alias && variantId!.compare(x),
);
this.#data.update({ values });
this.#data.updateCurrent({ values });
}
this.finishPropertyValueChange();
}
#updateLock = 0;
initiatePropertyValueChange() {
this.#updateLock++;
this.#data.mute();
// TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL]
/*return {
[Symbol.dispose]: this.finishPropertyValueChange,
};*/
this.#data.initiatePropertyValueChange();
}
finishPropertyValueChange = () => {
this.#updateLock--;
this.#triggerPropertyValueChanges();
this.#data.finishPropertyValueChange();
};
#triggerPropertyValueChanges() {
if (this.#updateLock === 0) {
this.#data.unmute();
}
public createPropertyDatasetContext(host: UmbControllerHost, variantId: UmbVariantId) {
return new UmbBlockElementPropertyDatasetContext(host, this, variantId);
}
public createPropertyDatasetContext(host: UmbControllerHost) {
return new UmbBlockElementPropertyDatasetContext(host, this, this.getVariantId());
}
public setup(host: UmbClassInterface) {
this.createPropertyDatasetContext(host);
public setup(host: UmbClassInterface, variantId: UmbVariantId) {
this.createPropertyDatasetContext(host, variantId);
// Provide Validation Context for this view:
this.validation.provideAt(host);

View File

@@ -1,89 +1,28 @@
import { UMB_BLOCK_ELEMENT_PROPERTY_DATASET_CONTEXT } from './block-element-property-dataset.context-token.js';
import type { UmbBlockElementManager } from './block-element-manager.js';
import { UMB_BLOCK_WORKSPACE_CONTEXT } from './block-workspace.context-token.js';
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbElementPropertyDatasetContext } from '@umbraco-cms/backoffice/content';
import { createObservablePart } from '@umbraco-cms/backoffice/observable-api';
export class UmbBlockElementPropertyDatasetContext extends UmbControllerBase implements UmbPropertyDatasetContext {
#elementManager: UmbBlockElementManager;
public getVariantId() {
return this.#elementManager.getVariantId();
export class UmbBlockElementPropertyDatasetContext
extends UmbElementPropertyDatasetContext
implements UmbPropertyDatasetContext
{
name;
culture;
segment;
getName(): string {
return 'Block';
}
#variantId: UmbVariantId;
#readOnly = new UmbBooleanState(false);
public readOnly = this.#readOnly.asObservable();
// default data:
getEntityType() {
return this.#elementManager.getEntityType();
}
getUnique() {
return this.#elementManager.getUnique();
}
getName(): string | undefined {
return 'TODO: get label';
}
readonly name: Observable<string | undefined> = 'TODO: get label observable' as any;
constructor(host: UmbControllerHost, elementManager: UmbBlockElementManager, variantId?: UmbVariantId) {
// The controller alias, is a very generic name cause we want only one of these for this controller host.
super(host, UMB_PROPERTY_DATASET_CONTEXT.toString());
this.#elementManager = elementManager;
this.#variantId = variantId ?? UmbVariantId.CreateInvariant();
super(host, elementManager, variantId);
this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspace) => {
this.observe(
workspace.readOnlyState.states,
(states) => {
const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId));
this.#readOnly.setValue(isReadOnly);
},
'umbObserveReadOnlyStates',
);
});
this.provideContext(UMB_BLOCK_ELEMENT_PROPERTY_DATASET_CONTEXT, this);
}
propertyVariantId?(propertyAlias: string): Promise<Observable<UmbVariantId | undefined>> {
return this.#elementManager.propertyVariantId(propertyAlias);
}
/**
* @function propertyValueByAlias
* @param {string} propertyAlias - The alias of the property
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - An observable of the property value.
* @description Get an Observable for the value of this property.
*/
async propertyValueByAlias<ReturnType = unknown>(propertyAlias: string) {
return await this.#elementManager.propertyValueByAlias<ReturnType>(propertyAlias);
}
/**
* @function setPropertyValue
* @param {string} alias - The alias of the property
* @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self.
* @returns {Promise<void>}
* @description Set the value of this property.
*/
async setPropertyValue(alias: string, value: PromiseLike<unknown>) {
this.#elementManager.setPropertyValue(alias, value);
}
/**
* Gets the read-only state of the current variant culture.
* @returns {*} {boolean}
* @memberof UmbBlockGridInlinePropertyDatasetContext
*/
getReadOnly(): boolean {
return this.#readOnly.getValue();
this.name = elementManager.name;
this.culture = createObservablePart(elementManager.variantId, (v) => v?.culture);
this.segment = createObservablePart(elementManager.variantId, (v) => v?.segment);
}
}

View File

@@ -204,8 +204,8 @@ export class UmbBlockWorkspaceContext<LayoutDataType extends UmbBlockLayoutBaseM
this.#initialLayout = undefined;
this.#initialContent = undefined;
this.#initialSettings = undefined;
this.content.reset();
this.settings.reset();
this.content.resetState();
this.settings.resetState();
this.removeUmbControllerByAlias(UmbWorkspaceIsNewRedirectControllerAlias);
}

View File

@@ -57,7 +57,6 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme
this.#blockWorkspace = context;
this.#tabsStructureHelper.setStructureManager(context.content.structure);
context.content.setup(this);
this.#observeRootGroups();
this.observe(
@@ -72,6 +71,7 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme
context.variantId,
async (variantId) => {
if (variantId) {
context.content.setup(this, variantId);
// TODO: Support segment name?
const culture = variantId.culture;
if (culture) {

View File

@@ -69,8 +69,16 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U
const blockManager = this.#blockWorkspace[this.#managerName];
this.#tabsStructureHelper.setStructureManager(blockManager.structure);
// Create Data Set & setup Validation Context:
blockManager.setup(this);
this.observe(
this.#blockWorkspace.variantId,
(variantId) => {
if (variantId) {
// Create Data Set & setup Validation Context:
blockManager.setup(this, variantId);
}
},
'observeVariantId',
);
this.observe(
await this.#blockWorkspace![this.#managerName!].structure.hasRootContainers('Group'),

View File

@@ -1,5 +1,5 @@
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { UmbContentDetailModel, UmbPotentialContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbContentLikeDetailModel, UmbPotentialContentValueModel } from '@umbraco-cms/backoffice/content';
import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry';
import { UmbVariantId, type UmbVariantDataModel } from '@umbraco-cms/backoffice/variant';
@@ -17,13 +17,13 @@ function defaultCompareVariantMethod(a: UmbVariantDataModel, b: UmbVariantDataMo
export class UmbMergeContentVariantDataController extends UmbControllerBase {
/**
* Merges content variant data based on selected variants and variants to store.
* @param {UmbContentDetailModel | undefined} persistedData - The persisted content variant data.
* @param {UmbContentDetailModel} currentData - The current content variant data.
* @param {UmbContentLikeDetailModel | undefined} persistedData - The persisted content variant data.
* @param {UmbContentLikeDetailModel} currentData - The current content variant data.
* @param {Array<UmbVariantId>} selectedVariants - The selected variants.
* @param {Array<UmbVariantId>} variantsToStore - The variants to store, we sometimes have additional variants that we like to process. This is typically the invariant variant, which we do not want to have as part of the variants data therefore a difference.
* @returns {Promise<UmbContentDetailModel>} - A promise that resolves to the merged content variant data.
* @returns {Promise<UmbContentLikeDetailModel>} - A promise that resolves to the merged content variant data.
*/
async process<ModelType extends UmbContentDetailModel>(
async process<ModelType extends UmbContentLikeDetailModel>(
persistedData: ModelType | undefined,
currentData: ModelType,
selectedVariants: Array<UmbVariantId>,
@@ -39,14 +39,17 @@ export class UmbMergeContentVariantDataController extends UmbControllerBase {
currentData.values,
variantsToStore,
),
};
if (currentData.variants) {
// Notice for variants we do not want to include all the variants that we are processing. but just the once selected for the process. (Not include invariant if we are in a variant document) [NL]
variants: this.#processVariants(
result.variants = this.#processVariants(
persistedData?.variants,
currentData.variants,
selectedVariants,
defaultCompareVariantMethod,
),
};
);
}
this.destroy();

View File

@@ -1,8 +1,8 @@
export { UMB_CONTENT_PROPERTY_CONTEXT } from './content-property.context-token.js';
export { UmbContentPropertyContext } from './content-property.context.js';
export * from './manager/content-data-manager.js';
export * from './controller/merge-content-variant-data.controller.js';
export * from './property-dataset-context/content-property-dataset.context.js';
export * from './workspace/index.js';
export * from './collection/index.js';
export * from './controller/merge-content-variant-data.controller.js';
export * from './manager/index.js';
export * from './property-dataset-context/index.js';
export * from './workspace/index.js';
export type * from './types.js';

View File

@@ -1,63 +1,24 @@
import { UmbMergeContentVariantDataController } from '../controller/merge-content-variant-data.controller.js';
import { UmbElementWorkspaceDataManager } from './element-data-manager.js';
import type { UmbContentDetailModel } from '@umbraco-cms/backoffice/content';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { appendToFrozenArray, jsonStringComparison } from '@umbraco-cms/backoffice/observable-api';
import { UmbVariantId, type UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant';
import { UmbEntityWorkspaceDataManager, type UmbWorkspaceDataManager } from '@umbraco-cms/backoffice/workspace';
export class UmbContentWorkspaceDataManager<
ModelType extends UmbContentDetailModel,
ModelVariantType extends UmbEntityVariantModel = ModelType extends { variants: UmbEntityVariantModel[] }
? ModelType['variants'][0]
: never,
>
extends UmbEntityWorkspaceDataManager<ModelType>
implements UmbWorkspaceDataManager<ModelType>
{
ModelType extends UmbContentDetailModel,
ModelVariantType extends UmbEntityVariantModel = ModelType extends { variants: UmbEntityVariantModel[] }
? ModelType['variants'][0]
: never,
> extends UmbElementWorkspaceDataManager<ModelType> {
//
//#repository;
#variantScaffold?: ModelVariantType;
#varies?: boolean;
//#variesByCulture?: boolean;
//#variesBySegment?: boolean;
constructor(host: UmbControllerHost, variantScaffold: ModelVariantType) {
super(host);
this.#variantScaffold = variantScaffold;
}
#updateLock = 0;
initiatePropertyValueChange() {
this.#updateLock++;
this._current.mute();
// TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL]
/*return {
[Symbol.dispose]: this.finishPropertyValueChange,
};*/
}
finishPropertyValueChange = () => {
this.#updateLock--;
this.#triggerPropertyValueChanges();
};
#triggerPropertyValueChanges() {
if (this.#updateLock === 0) {
this._current.unmute();
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setVariesByCulture(vary: boolean | undefined) {
//this.#variesByCulture = vary;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setVariesBySegment(vary: boolean | undefined) {
//this.#variesBySegment = vary;
}
setVaries(vary: boolean | undefined) {
this.#varies = vary;
}
ensureVariantData(variantId: UmbVariantId) {
this.updateVariantData(variantId);
}
@@ -66,7 +27,7 @@ export class UmbContentWorkspaceDataManager<
const currentData = this.getCurrent();
if (!currentData) throw new Error('Data is missing');
if (!this.#variantScaffold) throw new Error('Variant scaffold data is missing');
if (this.#varies === true) {
if (this._varies === true) {
// If variant Id is invariant, we don't to have the variant appended to our data.
if (variantId.isInvariant()) return;
const variant = currentData.variants.find((x) => variantId.compare(x));
@@ -82,7 +43,7 @@ export class UmbContentWorkspaceDataManager<
) as Array<ModelVariantType>;
// TODO: I have some trouble with TypeScript here, I does not look like me, but i had to give up. [NL]
this._current.update({ variants: newVariants } as any);
} else if (this.#varies === false) {
} else if (this._varies === false) {
// TODO: Beware about segments, in this case we need to also consider segments, if its allowed to vary by segments.
const invariantVariantId = UmbVariantId.CreateInvariant();
const variant = currentData.variants.find((x) => invariantVariantId.compare(x));
@@ -102,32 +63,6 @@ export class UmbContentWorkspaceDataManager<
}
}
async constructData(selectedVariants: Array<UmbVariantId>): Promise<ModelType> {
// Lets correct the selected variants, so invariant is included, or the only one if invariant.
// TODO: VDIVD: Could a document be set to invariant but hold variant data inside it?
const invariantVariantId = UmbVariantId.CreateInvariant();
let variantsToStore = [invariantVariantId];
if (this.#varies === false) {
// If we do not vary, we wil just pick the invariant variant id.
selectedVariants = [invariantVariantId];
} else {
variantsToStore = [...selectedVariants, invariantVariantId];
}
const data = this._current.getValue();
if (!data) throw new Error('Current data is missing');
if (!data.unique) throw new Error('Unique of current data is missing');
const persistedData = this.getPersisted();
return await new UmbMergeContentVariantDataController(this).process(
persistedData,
data,
selectedVariants,
variantsToStore,
);
}
getChangedVariants() {
const persisted = this.getPersisted();
const current = this.getCurrent();

View File

@@ -0,0 +1,70 @@
import { UmbMergeContentVariantDataController } from '../controller/merge-content-variant-data.controller.js';
import type { UmbElementDetailModel } from '@umbraco-cms/backoffice/content';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbEntityWorkspaceDataManager, type UmbWorkspaceDataManager } from '@umbraco-cms/backoffice/workspace';
export class UmbElementWorkspaceDataManager<ModelType extends UmbElementDetailModel>
extends UmbEntityWorkspaceDataManager<ModelType>
implements UmbWorkspaceDataManager<ModelType>
{
protected _varies?: boolean;
//#variesByCulture?: boolean;
//#variesBySegment?: boolean;
#updateLock = 0;
initiatePropertyValueChange() {
this.#updateLock++;
this._current.mute();
// TODO: When ready enable this code will enable handling a finish automatically by this implementation 'using myState.initiatePropertyValueChange()' (Relies on TS support of Using) [NL]
/*return {
[Symbol.dispose]: this.finishPropertyValueChange,
};*/
}
finishPropertyValueChange = () => {
this.#updateLock--;
this.#triggerPropertyValueChanges();
};
#triggerPropertyValueChanges() {
if (this.#updateLock === 0) {
this._current.unmute();
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setVariesByCulture(vary: boolean | undefined) {
//this.#variesByCulture = vary;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setVariesBySegment(vary: boolean | undefined) {
//this.#variesBySegment = vary;
}
setVaries(vary: boolean | undefined) {
this._varies = vary;
}
async constructData(selectedVariants: Array<UmbVariantId>): Promise<ModelType> {
// Lets correct the selected variants, so invariant is included, or the only one if invariant.
// TODO: VDIVD: Could a document be set to invariant but hold variant data inside it?
const invariantVariantId = UmbVariantId.CreateInvariant();
let variantsToStore = [invariantVariantId];
if (this._varies === false) {
// If we do not vary, we wil just pick the invariant variant id.
selectedVariants = [invariantVariantId];
} else {
variantsToStore = [...selectedVariants, invariantVariantId];
}
const data = this._current.getValue();
if (!data) throw new Error('Current data is missing');
//if (!data.unique) throw new Error('Unique of current data is missing');
const persistedData = this.getPersisted();
return await new UmbMergeContentVariantDataController(this).process(
persistedData,
data,
selectedVariants,
variantsToStore,
);
}
}

View File

@@ -0,0 +1,160 @@
import type { UmbElementPropertyDataOwner } from '../property-dataset-context/element-property-data-owner.interface.js';
import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import {
UmbBasicState,
classEqualMemoization,
createObservablePart,
mergeObservables,
} from '@umbraco-cms/backoffice/observable-api';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type';
type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>;
export class UmbElementDataPropertyManager<
ContentModel extends { values: Array<UmbPropertyValueData> },
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
> extends UmbControllerBase {
#dataOwner: UmbElementPropertyDataOwner<ContentModel, ContentTypeModel>;
#variantId: UmbVariantId;
// eslint-disable-next-line no-unused-private-class-members
#propertyVariantIdPromise?: Promise<never>;
#propertyVariantIdPromiseResolver?: () => void;
#propertyVariantIdMap = new UmbBasicState<UmbPropertyVariantIdMapType>([]);
private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable();
constructor(
host: UmbControllerHost,
dataOwner: UmbElementPropertyDataOwner<ContentModel, ContentTypeModel>,
variantId?: UmbVariantId,
) {
// The controller alias, is a very generic name cause we want only one of these for this controller host.
super(host);
this.#dataOwner = dataOwner;
this.#variantId = variantId ?? UmbVariantId.CreateInvariant();
this.observe(this.#dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => {
this.#propertyVariantIdPromise ??= new Promise((resolve) => {
this.#propertyVariantIdPromiseResolver = resolve as any;
});
const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) }));
this.#propertyVariantIdMap.setValue(map);
// Resolve promise, to let the once waiting on this know.
if (this.#propertyVariantIdPromiseResolver) {
this.#propertyVariantIdPromise = undefined;
this.#propertyVariantIdPromiseResolver();
this.#propertyVariantIdPromiseResolver = undefined;
}
});
}
#createPropertyVariantId(property: UmbPropertyTypeModel) {
return UmbVariantId.Create({
culture: property.variesByCulture ? this.#variantId.culture : null,
segment: property.variesBySegment ? this.#variantId.segment : null,
});
}
#propertiesObservable?: Observable<Array<UmbPropertyValueData>>;
// Should it be possible to get the properties as a list of property aliases?
get properties(): Observable<Array<UmbPropertyValueData>> {
if (!this.#propertiesObservable) {
this.#propertiesObservable = mergeObservables(
[this._propertyVariantIdMap, this.#dataOwner.values],
this.#mergeVariantIdsAndValues,
);
}
return this.#propertiesObservable;
}
#mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, Array<UmbPropertyValueData> | undefined]) {
const r: Array<UmbPropertyValueData> = [];
if (values) {
for (const prop of props) {
const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v));
if (f) {
r.push(f);
}
}
}
return r;
}
async getProperties(): Promise<Array<UmbPropertyValueData>> {
await this.#propertyVariantIdPromise;
return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#dataOwner.getValues()]);
}
/**
* @function propertyVariantId
* @param {string} propertyAlias - The property alias to observe the variantId of.
* @returns {Promise<Observable<UmbVariantId | undefined> | undefined>} - The observable for this properties variantId.
* @description Get an Observable for the variant id of this property.
*/
async propertyVariantId(propertyAlias: string) {
return createObservablePart(
this._propertyVariantIdMap,
(x) => x.find((v) => v.alias === propertyAlias)?.variantId,
classEqualMemoization,
);
}
/**
* @function propertyValueByAlias
* @param {string} propertyAlias The alias of the property
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - An observable of the property value
* @description Get an Observable for the value of this property.
*/
async propertyValueByAlias<ReturnType = unknown>(
propertyAlias: string,
): Promise<Observable<ReturnType | undefined> | undefined> {
await this.#dataOwner.isLoaded();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this.#dataOwner.propertyValueByAlias<ReturnType>(propertyAlias, propVariantId.variantId);
}
return;
}
async propertyValueByAliasAndVariantId<ReturnType = unknown>(
propertyAlias: string,
propertyVariantId: UmbVariantId,
): Promise<Observable<ReturnType | undefined> | undefined> {
return this.#dataOwner.propertyValueByAlias<ReturnType>(propertyAlias, propertyVariantId);
}
/**
* @function setPropertyValueByVariant
* @param {string} propertyAlias - The alias of the property
* @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self.
* @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for.
* @returns {Promise<unknown>} - A promise that resolves once the value has been set.
* @description Get the value of this property.
*/
setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise<void> {
return this.#dataOwner.setPropertyValue(propertyAlias, value, propertyVariantId);
}
/**
* @function setPropertyValue
* @param {string} propertyAlias - The alias for the value to be set
* @param {PromiseLike<unknown>} value - value can be a promise resolving into the actual value or the raw value it self.
* @returns {Promise<void>}
* @description Set the value of this property.
*/
async setPropertyValue(propertyAlias: string, value: PromiseLike<unknown>) {
this.#dataOwner.initiatePropertyValueChange();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this.#dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId);
}
this.#dataOwner.finishPropertyValueChange();
}
}

View File

@@ -0,0 +1,2 @@
export * from './content-data-manager.js';
export * from './element-data-manager.js';

View File

@@ -1,228 +1,57 @@
import type { UmbContentWorkspaceContext } from '../workspace/index.js';
import type { UmbContentDetailModel } from '../types.js';
import type { UmbNameablePropertyDatasetContext, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
import { UmbElementPropertyDatasetContext } from './element-property-dataset.context.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import { type Observable, map } from '@umbraco-cms/backoffice/external/rxjs';
import {
UmbBasicState,
UmbBooleanState,
UmbObjectState,
classEqualMemoization,
createObservablePart,
mergeObservables,
} from '@umbraco-cms/backoffice/observable-api';
import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type';
import type { UmbWorkspaceUniqueType } from '@umbraco-cms/backoffice/workspace';
type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>;
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbEntityVariantModel, UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type';
export class UmbContentPropertyDatasetContext<
ContentModel extends UmbContentDetailModel = UmbContentDetailModel,
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel,
>
extends UmbContextBase<UmbPropertyDatasetContext>
implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext
{
#workspace: UmbContentWorkspaceContext<ContentModel, ContentTypeModel, VariantModelType>;
#variantId: UmbVariantId;
public getVariantId() {
return this.#variantId;
}
#currentVariant = new UmbObjectState<UmbEntityVariantModel | undefined>(undefined);
ContentModel extends UmbContentDetailModel = UmbContentDetailModel,
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel,
> extends UmbElementPropertyDatasetContext<
ContentModel,
ContentTypeModel,
UmbContentWorkspaceContext<ContentModel, ContentTypeModel, VariantModelType>
> {
//
#currentVariant = new UmbObjectState<VariantModelType | undefined>(undefined);
currentVariant = this.#currentVariant.asObservable();
name = this.#currentVariant.asObservablePart((x) => x?.name);
culture = this.#currentVariant.asObservablePart((x) => x?.culture);
segment = this.#currentVariant.asObservablePart((x) => x?.segment);
// eslint-disable-next-line no-unused-private-class-members
#propertyVariantIdPromise?: Promise<never>;
#propertyVariantIdPromiseResolver?: () => void;
#propertyVariantIdMap = new UmbBasicState<UmbPropertyVariantIdMapType>([]);
private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable();
#readOnly = new UmbBooleanState(false);
public readOnly = this.#readOnly.asObservable();
getEntityType(): string {
return this.#workspace.getEntityType();
}
getUnique(): UmbWorkspaceUniqueType | undefined {
return this.#workspace.getUnique();
}
getName(): string | undefined {
return this.#workspace.getName(this.#variantId);
return this._dataOwner.getName(this.getVariantId());
}
setName(name: string) {
this.#workspace.setName(name, this.#variantId);
this._dataOwner.setName(name, this.getVariantId());
}
/**
* @deprecated Its not clear why we have this. We should either document the need better or get rid of it.
* @returns {UmbEntityVariantModel | undefined} - gives information about the current variant.
*/
getVariantInfo() {
return this.#workspace.getVariant(this.#variantId);
}
getReadOnly() {
return this.#readOnly.getValue();
return this._dataOwner.getVariant(this.getVariantId());
}
constructor(
host: UmbControllerHost,
workspace: UmbContentWorkspaceContext<ContentModel, ContentTypeModel, VariantModelType>,
dataOwner: UmbContentWorkspaceContext<ContentModel, ContentTypeModel, VariantModelType>,
variantId?: UmbVariantId,
) {
// The controller alias, is a very generic name cause we want only one of these for this controller host.
super(host, UMB_PROPERTY_DATASET_CONTEXT);
this.#workspace = workspace;
this.#variantId = variantId ?? UmbVariantId.CreateInvariant();
super(host, dataOwner, variantId);
this.observe(
this.#workspace.variantById(this.#variantId),
this._dataOwner.variantById(this.getVariantId()),
async (variantInfo) => {
if (!variantInfo) return;
this.#currentVariant.setValue(variantInfo);
},
'_observeActiveVariant',
);
this.observe(
this.#workspace.readOnlyState.states,
(states) => {
const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId));
this.#readOnly.setValue(isReadOnly);
},
'umbObserveReadOnlyStates',
);
// TODO: Refactor this into a separate manager/controller of some sort? [NL]
this.observe(this.#workspace.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => {
this.#propertyVariantIdPromise ??= new Promise((resolve) => {
this.#propertyVariantIdPromiseResolver = resolve as any;
});
const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) }));
this.#propertyVariantIdMap.setValue(map);
// Resolve promise, to let the once waiting on this know.
if (this.#propertyVariantIdPromiseResolver) {
this.#propertyVariantIdPromise = undefined;
this.#propertyVariantIdPromiseResolver();
this.#propertyVariantIdPromiseResolver = undefined;
}
});
}
#createPropertyVariantId(property: UmbPropertyTypeModel) {
return UmbVariantId.Create({
culture: property.variesByCulture ? this.#variantId.culture : null,
segment: property.variesBySegment ? this.#variantId.segment : null,
});
}
#propertiesObservable?: Observable<ContentModel['values']>;
// Should it be possible to get the properties as a list of property aliases?
get properties(): Observable<ContentModel['values']> {
if (!this.#propertiesObservable) {
this.#propertiesObservable = mergeObservables(
[this._propertyVariantIdMap, this.#workspace.values],
this.#mergeVariantIdsAndValues,
);
}
return this.#propertiesObservable;
}
#mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, ContentModel['values'] | undefined]) {
const r: ContentModel['values'] = [];
if (values) {
for (const prop of props) {
const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v));
if (f) {
r.push(f);
}
}
}
return r;
}
async getProperties(): Promise<ContentModel['values']> {
await this.#propertyVariantIdPromise;
return this.#mergeVariantIdsAndValues([this.#propertyVariantIdMap.getValue(), this.#workspace.getValues()]);
}
/**
* @function propertyVariantId
* @param {string} propertyAlias - The property alias to observe the variantId of.
* @returns {Promise<Observable<UmbVariantId | undefined> | undefined>} - The observable for this properties variantId.
* @description Get an Observable for the variant id of this property.
*/
async propertyVariantId(propertyAlias: string) {
/*
return (await this.#workspace.structure.propertyStructureByAlias(propertyAlias)).pipe(
map((property) => (property ? this.#createPropertyVariantId(property) : undefined)),
);
*/
return createObservablePart(
this._propertyVariantIdMap,
(x) => x.find((v) => v.alias === propertyAlias)?.variantId,
classEqualMemoization,
);
}
/**
* @function propertyValueByAlias
* @param {string} propertyAlias The alias of the property
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - An observable of the property value
* @description Get an Observable for the value of this property.
*/
async propertyValueByAlias<ReturnType = unknown>(
propertyAlias: string,
): Promise<Observable<ReturnType | undefined> | undefined> {
await this.#workspace.isLoaded();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this.#workspace.propertyValueByAlias<ReturnType>(propertyAlias, propVariantId.variantId);
}
return;
}
// TODO: Refactor: Not used currently, but should investigate if we can implement this, to spare some energy.
async propertyValueByAliasAndVariantId<ReturnType = unknown>(
propertyAlias: string,
propertyVariantId: UmbVariantId,
): Promise<Observable<ReturnType | undefined> | undefined> {
return this.#workspace.propertyValueByAlias<ReturnType>(propertyAlias, propertyVariantId);
}
/**
* @function setPropertyValueByVariant
* @param {string} propertyAlias - The alias of the property
* @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self.
* @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for.
* @returns {Promise<unknown>} - A promise that resolves once the value has been set.
* @description Get the value of this property.
*/
setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise<void> {
return this.#workspace.setPropertyValue(propertyAlias, value, propertyVariantId);
}
/**
* @function setPropertyValue
* @param {string} propertyAlias - The alias for the value to be set
* @param {PromiseLike<unknown>} value - value can be a promise resolving into the actual value or the raw value it self.
* @returns {Promise<void>}
* @description Set the value of this property.
*/
async setPropertyValue(propertyAlias: string, value: PromiseLike<unknown>) {
this.#workspace.initiatePropertyValueChange();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this.#workspace.setPropertyValue(propertyAlias, await value, propVariantId.variantId);
}
this.#workspace.finishPropertyValueChange();
}
}

View File

@@ -0,0 +1,36 @@
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
import type { UmbContentTypeModel, UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
import type { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils';
/**
* The data supplier for a Element Property Dataset
*/
export interface UmbElementPropertyDataOwner<
ContentModel extends { values: Array<UmbPropertyValueData> },
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
> extends UmbApi {
unique: Observable<UmbEntityUnique | undefined>;
getUnique(): UmbEntityUnique | undefined;
getEntityType(): string;
readonly structure: UmbContentTypeStructureManager<ContentTypeModel>;
readonly values: Observable<ContentModel['values'] | undefined>;
getValues(): ContentModel['values'] | undefined;
isLoaded(): Promise<unknown> | undefined;
readonly readOnlyState: UmbReadOnlyVariantStateManager;
// Same as from UmbVariantDatasetWorkspaceContext, could be refactored later [NL]
propertyValueByAlias<ReturnValue = unknown>(
alias: string,
variantId?: UmbVariantId,
): Promise<Observable<ReturnValue | undefined> | undefined>;
getPropertyValue<ReturnValue = unknown>(alias: string, variantId?: UmbVariantId): ReturnValue | undefined;
setPropertyValue(alias: string, value: unknown, variantId?: UmbVariantId): Promise<void>;
initiatePropertyValueChange(): void;
finishPropertyValueChange(): void;
}

View File

@@ -0,0 +1,208 @@
import type { UmbElementDetailModel } from '../types.js';
import type { UmbElementPropertyDataOwner } from './element-property-data-owner.interface.js';
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextBase } from '@umbraco-cms/backoffice/class-api';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import {
UmbBasicState,
UmbBooleanState,
classEqualMemoization,
createObservablePart,
mergeObservables,
} from '@umbraco-cms/backoffice/observable-api';
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type';
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
type UmbPropertyVariantIdMapType = Array<{ alias: string; variantId: UmbVariantId }>;
export abstract class UmbElementPropertyDatasetContext<
ContentModel extends UmbElementDetailModel = UmbElementDetailModel,
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
DataOwnerType extends UmbElementPropertyDataOwner<ContentModel, ContentTypeModel> = UmbElementPropertyDataOwner<
ContentModel,
ContentTypeModel
>,
>
extends UmbContextBase<UmbPropertyDatasetContext>
implements UmbPropertyDatasetContext
{
protected readonly _dataOwner: DataOwnerType;
#variantId: UmbVariantId;
public getVariantId() {
return this.#variantId;
}
abstract name: Observable<string | undefined>;
abstract culture: Observable<string | null | undefined>;
abstract segment: Observable<string | null | undefined>;
// eslint-disable-next-line no-unused-private-class-members
#propertyVariantIdPromise?: Promise<never>;
#propertyVariantIdPromiseResolver?: () => void;
#propertyVariantIdMap = new UmbBasicState<UmbPropertyVariantIdMapType>([]);
private readonly _propertyVariantIdMap = this.#propertyVariantIdMap.asObservable();
#readOnly = new UmbBooleanState(false);
public readOnly = this.#readOnly.asObservable();
getEntityType(): string {
return this._dataOwner.getEntityType();
}
getUnique(): UmbEntityUnique | undefined {
return this._dataOwner.getUnique();
}
abstract getName(): string | undefined;
getReadOnly() {
return this.#readOnly.getValue();
}
constructor(host: UmbControllerHost, dataOwner: DataOwnerType, variantId?: UmbVariantId) {
// The controller alias, is a very generic name cause we want only one of these for this controller host.
super(host, UMB_PROPERTY_DATASET_CONTEXT);
this._dataOwner = dataOwner;
this.#variantId = variantId ?? UmbVariantId.CreateInvariant();
this.observe(
this._dataOwner.readOnlyState.states,
(states) => {
const isReadOnly = states.some((state) => state.variantId.equal(this.#variantId));
this.#readOnly.setValue(isReadOnly);
},
'umbObserveReadOnlyStates',
);
// TODO: Refactor this into a separate manager/controller of some sort? [NL]
this.observe(this._dataOwner.structure.contentTypeProperties, (props: UmbPropertyTypeModel[]) => {
this.#propertyVariantIdPromise ??= new Promise((resolve) => {
this.#propertyVariantIdPromiseResolver = resolve as any;
});
const map = props.map((prop) => ({ alias: prop.alias, variantId: this.#createPropertyVariantId(prop) }));
this.#propertyVariantIdMap.setValue(map);
// Resolve promise, to let the once waiting on this know.
if (this.#propertyVariantIdPromiseResolver) {
this.#propertyVariantIdPromise = undefined;
this.#propertyVariantIdPromiseResolver();
this.#propertyVariantIdPromiseResolver = undefined;
}
});
}
#createPropertyVariantId(property: UmbPropertyTypeModel) {
return UmbVariantId.Create({
culture: property.variesByCulture ? this.#variantId.culture : null,
segment: property.variesBySegment ? this.#variantId.segment : null,
});
}
#propertiesObservable?: Observable<ContentModel['values']>;
// Should it be possible to get the properties as a list of property aliases?
get properties(): Observable<ContentModel['values']> {
if (!this.#propertiesObservable) {
this.#propertiesObservable = mergeObservables(
[this._propertyVariantIdMap, this._dataOwner.values],
this.#mergeVariantIdsAndValues,
);
}
return this.#propertiesObservable;
}
#mergeVariantIdsAndValues([props, values]: [UmbPropertyVariantIdMapType, ContentModel['values'] | undefined]) {
const r: ContentModel['values'] = [];
if (values) {
for (const prop of props) {
const f = values.find((v) => prop.alias === v.alias && prop.variantId.compare(v));
if (f) {
r.push(f);
}
}
}
return r as ContentModel['values'];
}
async getProperties(): Promise<ContentModel['values']> {
await this.#propertyVariantIdPromise;
return this.#mergeVariantIdsAndValues([
this.#propertyVariantIdMap.getValue(),
this._dataOwner.getValues(),
]) as ContentModel['values'];
}
/**
* @function propertyVariantId
* @param {string} propertyAlias - The property alias to observe the variantId of.
* @returns {Promise<Observable<UmbVariantId | undefined> | undefined>} - The observable for this properties variantId.
* @description Get an Observable for the variant id of this property.
*/
async propertyVariantId(propertyAlias: string) {
/*
return (await this.#workspace.structure.propertyStructureByAlias(propertyAlias)).pipe(
map((property) => (property ? this.#createPropertyVariantId(property) : undefined)),
);
*/
return createObservablePart(
this._propertyVariantIdMap,
(x) => x.find((v) => v.alias === propertyAlias)?.variantId,
classEqualMemoization,
);
}
/**
* @function propertyValueByAlias
* @param {string} propertyAlias The alias of the property
* @returns {Promise<Observable<ReturnType | undefined> | undefined>} - An observable of the property value
* @description Get an Observable for the value of this property.
*/
async propertyValueByAlias<ReturnType = unknown>(
propertyAlias: string,
): Promise<Observable<ReturnType | undefined> | undefined> {
await this._dataOwner.isLoaded();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this._dataOwner.propertyValueByAlias<ReturnType>(propertyAlias, propVariantId.variantId);
}
return;
}
// TODO: Refactor: Not used currently, but should investigate if we can implement this, to spare some energy.
async propertyValueByAliasAndVariantId<ReturnType = unknown>(
propertyAlias: string,
propertyVariantId: UmbVariantId,
): Promise<Observable<ReturnType | undefined> | undefined> {
return this._dataOwner.propertyValueByAlias<ReturnType>(propertyAlias, propertyVariantId);
}
/**
* @function setPropertyValueByVariant
* @param {string} propertyAlias - The alias of the property
* @param {unknown} value - value can be a promise resolving into the actual value or the raw value it self.
* @param {UmbVariantId} propertyVariantId - The variant id for the value to be set for.
* @returns {Promise<unknown>} - A promise that resolves once the value has been set.
* @description Get the value of this property.
*/
setPropertyValueByVariant(propertyAlias: string, value: unknown, propertyVariantId: UmbVariantId): Promise<void> {
return this._dataOwner.setPropertyValue(propertyAlias, value, propertyVariantId);
}
/**
* @function setPropertyValue
* @param {string} propertyAlias - The alias for the value to be set
* @param {PromiseLike<unknown>} value - value can be a promise resolving into the actual value or the raw value it self.
* @returns {Promise<void>}
* @description Set the value of this property.
*/
async setPropertyValue(propertyAlias: string, value: PromiseLike<unknown>) {
this._dataOwner.initiatePropertyValueChange();
await this.#propertyVariantIdPromise;
const propVariantId = this.#propertyVariantIdMap.getValue().find((x) => x.alias === propertyAlias);
if (propVariantId) {
return this._dataOwner.setPropertyValue(propertyAlias, await value, propVariantId.variantId);
}
this._dataOwner.finishPropertyValueChange();
}
}

View File

@@ -0,0 +1,3 @@
export * from './content-property-dataset.context.js';
export * from './element-property-data-owner.interface.js';
export * from './element-property-dataset.context.js';

View File

@@ -1,11 +1,17 @@
import type { UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
import type { UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant';
export interface UmbContentValueModel<ValueType = unknown> extends UmbPropertyValueData<ValueType> {
export interface UmbElementDetailModel {
values: Array<UmbElementValueModel>;
}
export interface UmbElementValueModel<ValueType = unknown> extends UmbPropertyValueData<ValueType> {
editorAlias: string;
culture: string | null;
segment: string | null;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbContentValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
export interface UmbPotentialContentValueModel<ValueType = unknown> extends UmbPropertyValueData<ValueType> {
editorAlias?: string;
@@ -13,9 +19,12 @@ export interface UmbPotentialContentValueModel<ValueType = unknown> extends UmbP
segment?: string | null;
}
export interface UmbContentDetailModel {
export interface UmbContentDetailModel extends UmbElementDetailModel {
unique: string;
entityType: string;
values: Array<UmbContentValueModel>;
variants: Array<UmbEntityVariantModel>;
}
export interface UmbContentLikeDetailModel
extends UmbElementDetailModel,
Partial<Pick<UmbContentDetailModel, 'variants'>> {}

View File

@@ -1,7 +1,6 @@
import type { UmbContentDetailModel } from '@umbraco-cms/backoffice/content';
import type { UmbContentDetailModel, UmbElementPropertyDataOwner } from '@umbraco-cms/backoffice/content';
import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import type { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils';
import type { UmbVariantId, UmbEntityVariantModel } from '@umbraco-cms/backoffice/variant';
import type {
UmbPropertyStructureWorkspaceContext,
@@ -13,13 +12,13 @@ export interface UmbContentWorkspaceContext<
ContentModel extends UmbContentDetailModel = UmbContentDetailModel,
ContentTypeModel extends UmbContentTypeModel = UmbContentTypeModel,
VariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel,
> extends UmbRoutableWorkspaceContext,
> extends UmbElementPropertyDataOwner<ContentModel, ContentTypeModel>,
UmbRoutableWorkspaceContext,
UmbVariantDatasetWorkspaceContext<VariantModelType>,
UmbPropertyStructureWorkspaceContext<ContentTypeModel> {
readonly IS_CONTENT_WORKSPACE_CONTEXT: true;
readonly readOnlyState: UmbReadOnlyVariantStateManager;
readonly values: Observable<ContentModel['values'] | undefined>;
getValues(): ContentModel['values'] | undefined;
//readonly values: Observable<ContentModel['values'] | undefined>;
//getValues(): ContentModel['values'] | undefined;
// Data:
getData(): ContentModel | undefined;
@@ -27,6 +26,6 @@ export interface UmbContentWorkspaceContext<
isLoaded(): Promise<unknown> | undefined;
variantById(variantId: UmbVariantId): Observable<VariantModelType | undefined>;
initiatePropertyValueChange(): void;
finishPropertyValueChange(): void;
//initiatePropertyValueChange(): void;
//finishPropertyValueChange(): void;
}

View File

@@ -1,6 +1,6 @@
import { UmbPropertyTypeWorkspaceEditorElement } from './property-type-workspace-editor.element.js';
import type { UmbPropertyTypeWorkspaceData } from './property-type-workspace.modal-token.js';
import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import type { UmbPropertyDatasetContext, UmbPropertyValueData } from '@umbraco-cms/backoffice/property';
import type {
UmbInvariantDatasetWorkspaceContext,
UmbRoutableWorkspaceContext,
@@ -11,6 +11,7 @@ import {
UmbInvariantWorkspacePropertyDatasetContext,
UmbWorkspaceIsNewRedirectController,
UmbWorkspaceIsNewRedirectControllerAlias,
umbObjectToPropertyValueArray,
} from '@umbraco-cms/backoffice/workspace';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
@@ -18,6 +19,7 @@ import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'
import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content-type';
import { UmbId } from '@umbraco-cms/backoffice/id';
import { UmbValidationContext } from '@umbraco-cms/backoffice/validation';
import { firstValueFrom } from '@umbraco-cms/backoffice/external/rxjs';
export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropertyTypeModel = UmbPropertyTypeModel>
extends UmbSubmittableWorkspaceContextBase<PropertyTypeData>
@@ -39,6 +41,13 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
readonly name = this.#data.asObservablePart((data) => data?.name);
readonly unique = this.#data.asObservablePart((data) => data?.id);
readonly values = this.#data.asObservablePart((data) => {
return umbObjectToPropertyValueArray(data);
});
async getValues(): Promise<Array<UmbPropertyValueData> | undefined> {
return umbObjectToPropertyValueArray(await firstValueFrom(this.data));
}
constructor(host: UmbControllerHost, args: { manifest: ManifestWorkspace }) {
super(host, args.manifest.alias);

View File

@@ -94,7 +94,7 @@ export class UmbPropertyDatasetContextBase
/**
* @returns {Array<UmbPropertyValueData>} - Array of properties as objects with alias and value properties.
*/
getProperties() {
async getProperties() {
return this.#properties.getValue();
}
/**

View File

@@ -1,16 +1,16 @@
import { UMB_ENTITY_WORKSPACE_CONTEXT } from '../../contexts/index.js';
import type { UmbWorkspaceUniqueType } from '../../types.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, customElement, state, nothing, query } from '@umbraco-cms/backoffice/external/lit';
import type { UmbActionExecutedEvent } from '@umbraco-cms/backoffice/event';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import type { UUIPopoverContainerElement } from '@umbraco-cms/backoffice/external/uui';
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
@customElement('umb-workspace-entity-action-menu')
export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement {
private _workspaceContext?: typeof UMB_ENTITY_WORKSPACE_CONTEXT.TYPE;
@state()
private _unique?: UmbWorkspaceUniqueType;
private _unique?: UmbEntityUnique;
@state()
private _entityType?: string;
@@ -39,14 +39,14 @@ export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement {
#onActionExecuted(event: UmbActionExecutedEvent) {
event.stopPropagation();
// TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
// TODO: This ignorer is just needed for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this._popover?.hidePopover();
}
#onPopoverToggle(event: ToggleEvent) {
// TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
// TODO: This ignorer is just needed for JSON SCHEMA TO WORK, As its not updated with latest TS jet.
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
this._popoverOpen = event.newState === 'open';

View File

@@ -1,8 +1,8 @@
import type { UmbWorkspaceContext } from '../../workspace-context.interface.js';
import type { UmbWorkspaceUniqueType } from './../../types.js';
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
export interface UmbEntityWorkspaceContext extends UmbWorkspaceContext {
unique: Observable<UmbWorkspaceUniqueType | undefined>;
getUnique(): UmbWorkspaceUniqueType | undefined;
unique: Observable<UmbEntityUnique | undefined>;
getUnique(): UmbEntityUnique | undefined;
}

View File

@@ -1,8 +1,7 @@
import type { UmbController } from '@umbraco-cms/backoffice/controller-api';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import type { MappingFunction, Observable } from '@umbraco-cms/backoffice/observable-api';
export interface UmbWorkspaceDataManager<ModelType extends UmbEntityModel> extends UmbController {
export interface UmbWorkspaceDataManager<ModelType> extends UmbController {
getPersisted(): ModelType | undefined;
getCurrent(): ModelType | undefined;

View File

@@ -1,6 +1,5 @@
import type { UmbWorkspaceDataManager } from '../data-manager/workspace-data-manager.interface.js';
import { jsonStringComparison, UmbObjectState, type MappingFunction } from '@umbraco-cms/backoffice/observable-api';
import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
/**
@@ -10,7 +9,7 @@ import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
* @implements {UmbWorkspaceDataManager<ModelType>}
* @template ModelType
*/
export class UmbEntityWorkspaceDataManager<ModelType extends UmbEntityModel>
export class UmbEntityWorkspaceDataManager<ModelType>
extends UmbControllerBase
implements UmbWorkspaceDataManager<ModelType>
{

View File

@@ -1,2 +1,7 @@
import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity';
export type * from './extensions/types.js';
export type UmbWorkspaceUniqueType = string | null;
/**
* @deprecated Use `UmbEntityUnique`instead.
*/
export type UmbWorkspaceUniqueType = UmbEntityUnique;

View File

@@ -49,6 +49,11 @@ export class UmbDataTypeWorkspaceContext
readonly propertyEditorUiAlias = this._data.createObservablePartOfCurrent((data) => data?.editorUiAlias);
readonly propertyEditorSchemaAlias = this._data.createObservablePartOfCurrent((data) => data?.editorAlias);
readonly values = this._data.createObservablePartOfCurrent((data) => data?.values);
async getValues() {
return this._data.getCurrent()?.values;
}
#properties = new UmbArrayState<PropertyEditorSettingsProperty>([], (x) => x.alias).sortBy(
(a, b) => (a.weight || 0) - (b.weight || 0),
);

View File

@@ -2,7 +2,7 @@ import type { UmbDocumentBlueprintEntityType } from './entity.js';
import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export { UmbDocumentBlueprintVariantState };
export interface UmbDocumentBlueprintDetailModel {
@@ -27,7 +27,7 @@ export interface UmbDocumentBlueprintUrlInfoModel {
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbDocumentBlueprintValueModel<ValueType = unknown> extends UmbContentValueModel<ValueType> {}
export interface UmbDocumentBlueprintValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbDocumentBlueprintVariantOptionModel

View File

@@ -6,7 +6,7 @@ import type {
} from '@umbraco-cms/backoffice/variant';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
import { DocumentVariantStateModel as UmbDocumentVariantState } from '@umbraco-cms/backoffice/external/backend-api';
import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export { UmbDocumentVariantState };
export interface UmbDocumentDetailModel extends UmbContentDetailModel {
@@ -34,7 +34,7 @@ export interface UmbDocumentUrlInfoModel {
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbDocumentValueModel<ValueType = unknown> extends UmbContentValueModel<ValueType> {}
export interface UmbDocumentValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbDocumentVariantOptionModel extends UmbEntityVariantOptionModel<UmbDocumentVariantModel> {}

View File

@@ -302,6 +302,7 @@ export class UmbDocumentWorkspaceContext
async load(unique: string) {
this.resetState();
this.#getDataPromise = this.repository.requestByUnique(unique);
type GetDataType = Awaited<ReturnType<UmbDocumentDetailRepository['requestByUnique']>>;
const { data, asObservable } = (await this.#getDataPromise) as GetDataType;

View File

@@ -1,7 +1,7 @@
import type { UmbMediaEntityType } from './entity.js';
import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant';
import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models';
import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export interface UmbMediaDetailModel extends UmbContentDetailModel {
mediaType: {
@@ -25,7 +25,7 @@ export interface UmbMediaUrlInfoModel {
export interface UmbMediaVariantModel extends UmbEntityVariantModel {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbMediaValueModel<ValueType = unknown> extends UmbContentValueModel<ValueType> {}
export interface UmbMediaValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbMediaVariantOptionModel extends UmbEntityVariantOptionModel<UmbEntityVariantModel> {}

View File

@@ -1,7 +1,7 @@
import type { UmbMemberEntityType } from './entity.js';
import type { UmbMemberKindType } from './utils/index.js';
import type { UmbEntityVariantModel, UmbEntityVariantOptionModel } from '@umbraco-cms/backoffice/variant';
import type { UmbContentDetailModel, UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbContentDetailModel, UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export interface UmbMemberDetailModel extends UmbContentDetailModel {
email: string;
@@ -28,7 +28,7 @@ export interface UmbMemberDetailModel extends UmbContentDetailModel {
export interface UmbMemberVariantModel extends UmbEntityVariantModel {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbMemberValueModel<ValueType = unknown> extends UmbContentValueModel<ValueType> {}
export interface UmbMemberValueModel<ValueType = unknown> extends UmbElementValueModel<ValueType> {}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbMemberVariantOptionModel extends UmbEntityVariantOptionModel<UmbMemberVariantModel> {}

View File

@@ -18,7 +18,6 @@ import {
UmbWorkspaceIsNewRedirectController,
UmbWorkspaceIsNewRedirectControllerAlias,
UmbWorkspaceSplitViewManager,
umbObjectToPropertyValueArray,
} from '@umbraco-cms/backoffice/workspace';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import {
@@ -35,7 +34,7 @@ import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
import { UmbContentWorkspaceDataManager, type UmbContentWorkspaceContext } from '@umbraco-cms/backoffice/content';
import { UmbReadOnlyVariantStateManager } from '@umbraco-cms/backoffice/utils';
import { UmbDataTypeItemRepositoryManager } from '@umbraco-cms/backoffice/data-type';
import { firstValueFrom, map } from '@umbraco-cms/backoffice/external/rxjs';
import { map } from '@umbraco-cms/backoffice/external/rxjs';
import { UmbEntityContext, type UmbEntityModel } from '@umbraco-cms/backoffice/entity';
import {
UmbRequestReloadChildrenOfEntityEvent,

View File

@@ -4,11 +4,11 @@ import {
type UmbBlockDataValueModel,
type UmbBlockExposeModel,
} from '@umbraco-cms/backoffice/block';
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbElementValueModel } from '@umbraco-cms/backoffice/content';
export class UmbRteBlockValueResolver extends UmbBlockValueResolver<UmbPropertyEditorUiValueType> {
async processValues(
property: UmbContentValueModel<UmbPropertyEditorUiValueType>,
property: UmbElementValueModel<UmbPropertyEditorUiValueType>,
valuesCallback: (values: Array<UmbBlockDataValueModel>) => Promise<Array<UmbBlockDataValueModel> | undefined>,
) {
if (property.value) {
@@ -24,7 +24,7 @@ export class UmbRteBlockValueResolver extends UmbBlockValueResolver<UmbPropertyE
}
async processVariants(
property: UmbContentValueModel<UmbPropertyEditorUiValueType>,
property: UmbElementValueModel<UmbPropertyEditorUiValueType>,
variantsCallback: (values: Array<UmbBlockExposeModel>) => Promise<Array<UmbBlockExposeModel> | undefined>,
) {
if (property.value) {