Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,11 @@ export abstract class UmbBlockManagerContext<
if (segments) {
controller.setSegments(segments);
}
const values = await controller.create(valueDefinitions);
const values = await controller.create(valueDefinitions, {
entityType: 'block',
entityUnique: key,
entityTypeUnique: contentTypeKey,
});

// Set culture and segment for all values:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,57 +382,66 @@
}

protected override async _scaffoldProcessData(data: DetailModelType): Promise<DetailModelType> {
const contentTypeUnique: string | undefined = (data as any)[this.#contentTypePropertyName].unique;
if (!contentTypeUnique) {
throw new Error(`Could not find content type unique on property '${this.#contentTypePropertyName}'`);
}
// Load the content type structure, usually this comes from the data, but in this case we are making the data, and we need this to be able to complete the data. [NL]
await this.structure.loadType((data as any)[this.#contentTypePropertyName].unique);
await this.structure.loadType(contentTypeUnique);

/**
* TODO: Should we also set Preset Values when loading Content, because maybe content contains uncreated Cultures or Segments.
*/

// Set culture and segment for all values:
const cultures = this.#languages.getValue().map((x) => x.unique);

if (this.structure.variesBySegment) {
// TODO: v.17 Engage please note we have not implemented support for segments yet. [NL]
console.warn('Segments are not yet implemented for preset');
}
// TODO: Add Segments for Presets:
const segments: Array<string> | undefined = this.structure.variesBySegment ? [] : undefined;

const repo = new UmbDataTypeDetailRepository(this);

const propertyTypes = await this.structure.getContentTypeProperties();
const valueDefinitions = await Promise.all(
propertyTypes.map(async (property) => {
// TODO: Implement caching for data-type requests. [NL]
const dataType = (await repo.requestByUnique(property.dataType.unique)).data;
// This means if its not loaded this will never resolve and the error below will never happen.
if (!dataType) {
throw new Error(`DataType of "${property.dataType.unique}" not found.`);
}
if (!dataType.editorUiAlias) {
throw new Error(`DataType of "${property.dataType.unique}" did not have a editorUiAlias.`);
}

return {
alias: property.alias,
propertyEditorUiAlias: dataType.editorUiAlias,
propertyEditorSchemaAlias: dataType.editorAlias,
config: dataType.values,
typeArgs: {
variesByCulture: property.variesByCulture,
variesBySegment: property.variesBySegment,
} as UmbPropertyTypePresetModelTypeModel,
} as UmbPropertyTypePresetModel;
}),
);

const controller = new UmbPropertyValuePresetVariantBuilderController(this);
controller.setCultures(cultures);
if (segments) {
controller.setSegments(segments);
}

const presetValues = await controller.create(valueDefinitions);
const presetValues = await controller.create(valueDefinitions, {
entityType: this.getEntityType(),
entityUnique: data.unique,
entityTypeUnique: contentTypeUnique,
});

Check warning on line 444 in src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/content-detail-workspace-base.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (main)

❌ Getting worse: Complex Method

_scaffoldProcessData increases in cyclomatic complexity from 11 to 13, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

// Don't just set the values, as we could have some already populated from a blueprint.
// If we have a value from both a blueprint and a preset, use the latter as priority.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ describe('UmbPropertyValuePresetBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityUnique: 'test-unique',
entityType: 'test',
});

expect(result.length).to.be.equal(1);
expect(result[0]?.value).to.be.equal('first');
Expand Down Expand Up @@ -120,7 +123,10 @@ describe('UmbPropertyValuePresetBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityUnique: 'test-unique',
entityType: 'test',
});

expect(result.length).to.be.equal(1);
expect(result[0]?.value).to.be.equal('first_second');
Expand Down Expand Up @@ -168,7 +174,10 @@ describe('UmbPropertyValuePresetBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityUnique: 'test-unique',
entityType: 'test',
});

expect(result.length).to.be.equal(1);
expect(result[0]?.value).to.be.equal('second_first');
Expand Down Expand Up @@ -233,7 +242,10 @@ describe('UmbPropertyValuePresetBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityUnique: 'test-unique',
entityType: 'test',
});

expect(result.length).to.be.equal(2);
expect(result[0]?.alias).to.be.equal('test');
Expand Down Expand Up @@ -310,7 +322,10 @@ describe('UmbPropertyValuePresetBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityUnique: 'test-unique',
entityType: 'test',
});

// Test that only the right presets are used:
expect(result.length).to.be.equal(3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
UmbPropertyTypePresetWithSchemaAliasModel,
UmbPropertyValuePreset,
UmbPropertyValuePresetApiCallArgs,
UmbPropertyValuePresetApiCallArgsEntityBase,
} from './types.js';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { createExtensionApi } from '@umbraco-cms/backoffice/extension-api';
Expand All @@ -15,14 +16,37 @@ const EMPTY_CALL_ARGS = Object.freeze({});
export class UmbPropertyValuePresetBuilderController<
ReturnType = UmbPropertyValueData | UmbPropertyValueDataPotentiallyWithEditorAlias,
> extends UmbControllerBase {
#baseCreateArgs?: UmbPropertyValuePresetApiCallArgsEntityBase;

/**
* Clones the property data.
* @param {UmbPropertyValueDataPotentiallyWithEditorAlias} propertyTypes - Data about the properties to make a preset for.
* @param createArgs
* @returns {Promise<UmbPropertyValueDataPotentiallyWithEditorAlias>} - A promise that resolves to the cloned property data.
*/
async create<GivenPropertyTypesType extends UmbPropertyTypePresetModel>(
propertyTypes: Array<GivenPropertyTypesType>,
// TODO: Remove Option argument and Partial<> in v.17.0 [NL]
createArgs?: Partial<UmbPropertyValuePresetApiCallArgsEntityBase>,
): Promise<Array<ReturnType>> {
//
// TODO: Clean up warnings in v.17.0 [NL]
this.#baseCreateArgs = {
entityType:
createArgs?.entityType ??
'needs to be parsed to the UmbPropertyValuePresetBuilderController, this is not present because of a custom legacy implementation',
entityUnique:
createArgs?.entityUnique ??
'needs to be parsed to the UmbPropertyValuePresetBuilderController, this is not present because of a custom legacy implementation',
entityTypeUnique: createArgs?.entityTypeUnique,
};

if (!createArgs?.entityUnique || !createArgs?.entityType) {
console.warn(
`entityUnique or entityType was not provided for UmbPropertyValuePresetBuilderController.create in the second argument. This will be required in v.17.0 and must be provided when calling create().`,
);
}

const result = await Promise.all(propertyTypes.map(this.#createPropertyPreset));

//Merge all the values into a single array:
Expand Down Expand Up @@ -87,9 +111,17 @@ export class UmbPropertyValuePresetBuilderController<
protected async _generatePropertyValue(
apis: Array<UmbPropertyValuePreset>,
propertyType: UmbPropertyTypePresetModel | UmbPropertyTypePresetWithSchemaAliasModel,
callArgs: UmbPropertyValuePresetApiCallArgs,
incomingCallArgs: Partial<UmbPropertyValuePresetApiCallArgs>,
): Promise<ReturnType | undefined> {
let value: unknown = undefined;

const callArgs: UmbPropertyValuePresetApiCallArgs = {
...this.#baseCreateArgs!,
alias: propertyType.alias,
propertyEditorUiAlias: propertyType.propertyEditorUiAlias,
propertyEditorSchemaAlias: (propertyType as UmbPropertyTypePresetWithSchemaAliasModel).propertyEditorSchemaAlias,
...incomingCallArgs,
};
// Important to use a inline for loop, to secure that each entry is processed(asynchronously) in order
for (const api of apis) {
if (!api.processValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ describe('UmbPropertyValuePresetVariantBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityType: 'test',
entityUnique: 'some-unique',
});

expect(result.length).to.be.equal(2);
expect(result[0]?.value).to.be.equal('value for culture cultureA');
Expand All @@ -86,7 +89,10 @@ describe('UmbPropertyValuePresetVariantBuilderController', () => {
];

try {
await ctrl.create(propertyTypes);
await ctrl.create(propertyTypes, {
entityType: 'test',
entityUnique: 'some-unique',
});
expect.fail('Expected to fail');
} catch (e) {}
});
Expand All @@ -105,7 +111,10 @@ describe('UmbPropertyValuePresetVariantBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityType: 'test',
entityUnique: 'some-unique',
});

expect(result.length).to.be.equal(3);
expect(result[0]?.value).to.be.equal('value for culture invariant');
Expand All @@ -132,7 +141,10 @@ describe('UmbPropertyValuePresetVariantBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityType: 'test',
entityUnique: 'some-unique',
});

expect(result.length).to.be.equal(1);
expect(result[0]?.value).to.be.equal('value for culture invariant');
Expand All @@ -155,7 +167,10 @@ describe('UmbPropertyValuePresetVariantBuilderController', () => {
},
];

const result = await ctrl.create(propertyTypes);
const result = await ctrl.create(propertyTypes, {
entityType: 'test',
entityUnique: 'some-unique',
});

expect(result.length).to.be.equal(6);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export class UmbPropertyValuePresetVariantBuilderController extends UmbPropertyV
// Always declare the default segment (null)
#segments: Array<null | string> = [null];

// TODO: We properly need to break this, as Engage needs to control which Segments are available for each culture, maybe investigate the option to go about a new option to just parse options.? Break in v.17.0 [NL]

setCultures(cultures: Array<string>): void {
this.#cultures = cultures;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@ export interface UmbPropertyTypePresetModelTypeModel {
variesByCulture?: boolean;
variesBySegment?: boolean;
}
export interface UmbPropertyValuePresetApiCallArgs {

export interface UmbPropertyValuePresetApiCallArgsEntityBase {
entityType: string;
entityUnique: string;
entityTypeUnique?: string;
}

export interface UmbPropertyValuePresetApiCallArgs extends UmbPropertyValuePresetApiCallArgsEntityBase {
alias: string;
propertyEditorUiAlias: string;
propertyEditorSchemaAlias?: string;
variantId?: UmbVariantId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ import { Italic } from '@umbraco-cms/backoffice/external/tiptap';
export default class UmbTiptapItalicExtensionApi extends UmbTiptapExtensionApiBase {
getTiptapExtensions = () => [Italic];
}

Loading