ensure variant property value resolver

This commit is contained in:
Niels Lyngsø
2024-09-25 09:48:58 +02:00
parent c0570344ab
commit c43df5c207
3 changed files with 93 additions and 39 deletions

View File

@@ -1,6 +1,9 @@
import type { UmbBlockDataValueModel, UmbBlockValueType } from '../types.js';
import type { UmbBlockDataValueModel, UmbBlockExposeModel, UmbBlockValueType } from '../types.js';
import type { UmbContentValueModel } from '@umbraco-cms/backoffice/content';
import type { UmbPropertyValueResolver } from '@umbraco-cms/backoffice/property';
import type {
UmbPropertyValueResolver,
UmbPropertyValueResolverEnsureVariantArgs,
} from '@umbraco-cms/backoffice/property';
export class UmbBlockValueResolver
implements UmbPropertyValueResolver<UmbContentValueModel<UmbBlockValueType>, UmbBlockDataValueModel>
@@ -35,5 +38,43 @@ export class UmbBlockValueResolver
return property;
}
async ensureVariants(
property: UmbContentValueModel<UmbBlockValueType>,
args: UmbPropertyValueResolverEnsureVariantArgs,
) {
if (property.value && args.selectedVariants) {
const currentExposes = property.value.expose ?? [];
const contentKeys = property.value.contentData.map((x) => x.key);
const newExposes = contentKeys.flatMap((contentKey) =>
args.selectedVariants.map((v) => ({
contentKey: contentKey,
culture: v.culture,
segment: v.segment,
})),
) as Array<UmbBlockExposeModel>;
// make exposes unique:
const expose = [
...currentExposes,
...newExposes.filter(
(n) =>
!currentExposes.some(
(p) => p.contentKey === n.contentKey && p.culture === n.culture && p.segment === n.segment,
),
),
];
return {
...property,
value: {
...property.value,
expose,
},
};
}
return property;
}
destroy(): void {}
}

View File

@@ -112,11 +112,12 @@ export class UmbContentWorkspaceDataManager<
// 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 {
selectedVariants = [...selectedVariants, invariantVariantId];
variantsToStore = [...selectedVariants, invariantVariantId];
}
const data = this.current.getValue();
@@ -134,6 +135,7 @@ export class UmbContentWorkspaceDataManager<
persistedData?.values,
data.values,
selectedVariants,
variantsToStore,
),
variants: this.#buildSaveVariants(persistedData?.variants, data.variants, selectedVariants),
};
@@ -145,57 +147,52 @@ export class UmbContentWorkspaceDataManager<
persistedValues: Array<T> | undefined,
draftValues: Array<T> | undefined,
selectedVariants: Array<UmbVariantId>,
variantsToStore: Array<UmbVariantId>,
): Promise<Array<T>> {
// Make array of unique values, based on persistedValues and draftValues. unique values are based upon alias culture and segment
const uniqueValues = [
...new Set(
[...(persistedValues ?? []), ...(draftValues ?? [])].map((x) => ({
alias: x.alias,
culture: x.culture,
segment: x.segment,
})),
),
];
// Make array of unique values, based on persistedValues and draftValues. Both alias, culture and segment has to be taken into account. [NL]
const uniqueValues = [...(persistedValues ?? []), ...(draftValues ?? [])].filter(
(n, i, self) =>
i === self.findIndex((v) => v.alias === n.alias && v.culture === n.culture && v.segment === n.segment),
);
// Map unique values to their respective draft values.
return await Promise.all(
uniqueValues
.map((value) => {
return (
await Promise.all(
uniqueValues.map((value) => {
const persistedValue = persistedValues?.find(
(x) => x.alias === value.alias && x.culture === value.culture && x.segment === value.segment,
);
// Should this value be saved?
if (selectedVariants.some((x) => x.equal(UmbVariantId.CreateFromPartial(value)))) {
if (variantsToStore.some((x) => x.equal(UmbVariantId.CreateFromPartial(value)))) {
const draftValue = draftValues?.find(
(x) => x.alias === value.alias && x.culture === value.culture && x.segment === value.segment,
);
return this.#buildSaveValue(persistedValue, draftValue, selectedVariants);
return this.#buildSaveValue(persistedValue, draftValue, selectedVariants, variantsToStore);
} else {
// TODO: Check if this promise is needed: [NL]
return Promise.resolve(persistedValue);
}
})
.filter((x) => x !== undefined) as Array<Promise<T>>,
);
}),
)
).filter((x) => x !== undefined) as Array<T>;
}
async #buildSaveValue(
persistedValue: UmbPotentialContentValueModel | undefined,
draftValue: UmbPotentialContentValueModel | undefined,
selectedVariants: Array<UmbVariantId>,
variantsToStore: Array<UmbVariantId>,
): Promise<UmbPotentialContentValueModel | undefined> {
const editorAlias = draftValue?.editorAlias ?? persistedValue?.editorAlias;
if (!editorAlias) {
console.error(`Editor alias not found for ${editorAlias}`);
return draftValue;
}
if (!persistedValue) {
// If the persisted value does not exists then no need to combine.
return draftValue;
}
if (!draftValue) {
// If the draft value does not exists then no need to combine.
// If the draft value does not exists then no need to process.
return undefined;
}
@@ -216,27 +213,41 @@ export class UmbContentWorkspaceDataManager<
return draftValue;
}
let newValue = draftValue;
if (api.processValues) {
// The a property values resolver resolves one value, we need to gather the persisted inner values first, and store them here:
const persistedValuesHolder: Array<Array<UmbPotentialContentValueModel>> = [];
await api.processValues(persistedValue, async (values) => {
persistedValuesHolder.push(values as unknown as Array<UmbPotentialContentValueModel>);
return undefined;
});
if (persistedValue) {
await api.processValues(persistedValue, async (values) => {
persistedValuesHolder.push(values as unknown as Array<UmbPotentialContentValueModel>);
return undefined;
});
}
let valuesIndex = 0;
return await api.processValues(draftValue, async (values) => {
newValue = await api.processValues(newValue, async (values) => {
// got some values (content and/or settings):
// but how to get the persisted and the draft of this.....
const persistedValues = persistedValuesHolder[valuesIndex++];
return await this.#buildSaveValues(persistedValues, values, selectedVariants);
return await this.#buildSaveValues(persistedValues, values, selectedVariants, variantsToStore);
});
}
if (api.ensureVariants) {
// The a property values resolver resolves one value, we need to gather the persisted inner values first, and store them here:
//const persistedVariants = newValue ? ((await api.readVariants(newValue)) ?? []) : [];
const args = {
selectedVariants,
};
newValue = await api.ensureVariants(newValue, args);
}
// the api did not provide a value processor, so we will return the draftValue:
return draftValue;
return newValue;
}
#buildSaveVariants(

View File

@@ -1,5 +1,5 @@
import type { UmbEntityVariantModel } from '../../variant/types.js';
import type { UmbPropertyValueData } from '../types/index.js';
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
export type * from './property-value-resolver.extension.js';
@@ -7,10 +7,9 @@ export type * from './property-value-resolver.extension.js';
export interface UmbPropertyValueResolver<
PropertyValueType extends UmbPropertyValueData = UmbPropertyValueData,
InnerPropertyValueType extends UmbPropertyValueData = PropertyValueType,
InnerVariantModelType extends UmbEntityVariantModel = UmbEntityVariantModel,
> extends UmbApi {
processValues?: UmbPropertyValueResolverValueProcessor<PropertyValueType, InnerPropertyValueType>;
processVariants?: UmbPropertyValueResolverVariantProcessor<PropertyValueType, InnerVariantModelType>;
ensureVariants?: UmbPropertyValueResolverEnsureVariants<PropertyValueType>;
}
export type UmbPropertyValueResolverValueProcessor<
@@ -21,10 +20,13 @@ export type UmbPropertyValueResolverValueProcessor<
valuesProcessor: (values: Array<InnerPropertyValueType>) => Promise<Array<InnerPropertyValueType> | undefined>,
) => PromiseLike<PropertyValueType | undefined>;
export type UmbPropertyValueResolverVariantProcessor<
export type UmbPropertyValueResolverEnsureVariants<
PropertyValueType extends UmbPropertyValueData = UmbPropertyValueData,
VariantType extends UmbEntityVariantModel = UmbEntityVariantModel,
> = (
value: PropertyValueType,
variantsProcessor: (variants: Array<VariantType>) => Promise<Array<VariantType> | undefined>,
args: UmbPropertyValueResolverEnsureVariantArgs,
) => PromiseLike<PropertyValueType | undefined>;
export type UmbPropertyValueResolverEnsureVariantArgs = {
selectedVariants: Array<UmbVariantId>;
};