From d239849cc548ac9df9ebd30e4a77f376be966eef Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 14 May 2025 10:47:43 +0200 Subject: [PATCH] Include property aliases in compatible composition check (#19277) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add method to get all property aliases * pass property aliases to composition modal * put in a box + adjust spacing * disable if doc type is not compatible for composing * compare with what is used for composition * add comment --------- Co-authored-by: Niels Lyngsø --- .../composition-picker-modal.element.ts | 19 +++++++++++++++++-- .../composition-picker-modal.token.ts | 1 + .../content-type-structure-manager.class.ts | 11 +++++++++++ .../content-type-design-editor.element.ts | 12 ++++++++++-- 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.element.ts index e0cf37273d..7ed7dddb7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.element.ts @@ -39,6 +39,9 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< @state() private _usedForInheritance: Array = []; + @state() + private _usedForComposition: Array = []; + override connectedCallback() { super.connectedCallback(); @@ -53,6 +56,7 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< this._selection = this.data?.selection ?? []; this._usedForInheritance = this.data?.usedForInheritance ?? []; + this._usedForComposition = this.data?.usedForComposition ?? []; this.modalContext?.setValue({ selection: this._selection }); const isNew = this.data!.isNew; @@ -131,7 +135,9 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< override render() { return html` - ${this._references.length ? this.#renderHasReference() : this.#renderAvailableCompositions()} + + ${this._references.length ? this.#renderHasReference() : this.#renderAvailableCompositions()} +
${!this._references.length @@ -213,11 +219,16 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< (compositions) => compositions.unique, (compositions) => { const usedForInheritance = this._usedForInheritance.includes(compositions.unique); + const usedForComposition = this._usedForComposition.includes(compositions.unique); + /* The server will return isCompatible as false if the Doc Type is currently being used in a composition. + Therefore, we need to account for this in the "isDisabled" check to ensure it remains enabled. + Otherwise, it would become disabled and couldn't be deselected by the user. */ + const isDisabled = usedForInheritance || (compositions.isCompatible === false && !usedForComposition); return html` this.#onSelectionAdd(compositions.unique)} @deselected=${() => this.#onSelectionRemove(compositions.unique)} ?selected=${this._selection.find((unique) => unique === compositions.unique)}> @@ -251,6 +262,10 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< align-items: center; gap: var(--uui-size-3); } + + .compositions-list { + margin-block: var(--uui-size-3); + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.token.ts index a711e4e4df..994d2d1912 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/modals/composition-picker/composition-picker-modal.token.ts @@ -5,6 +5,7 @@ export interface UmbCompositionPickerModalData { compositionRepositoryAlias: string; selection: Array; usedForInheritance: Array; + usedForComposition: Array; unique: string | null; isElement: boolean; currentPropertyAliases: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-structure-manager.class.ts index 8c0929539d..809be5a1b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-structure-manager.class.ts @@ -816,6 +816,17 @@ export class UmbContentTypeStructureManager< ); } + /** + * Get all property aliases for the content type including inherited and composed content types. + * @returns {Promise>} - A promise that will be resolved with the list of all content type property aliases. + */ + async getContentTypePropertyAliases() { + return this.#contentTypes + .getValue() + .flatMap((x) => x.properties?.map((y) => y.alias) ?? []) + .filter(UmbFilterDuplicateStrings); + } + #clear() { this.#contentTypeObservers.forEach((observer) => observer.destroy()); this.#contentTypeObservers = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts index e8eb09a220..34d0e5d3a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.element.ts @@ -389,17 +389,25 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements const currentOwnerCompositionCompositions = currentOwnerCompositions.filter( (composition) => composition.compositionType === CompositionTypeModel.COMPOSITION, ); + + const currentOwnerCompositionCompositionUniques = currentOwnerCompositionCompositions.map( + (composition) => composition.contentType.unique, + ); + const currentOwnerInheritanceCompositions = currentOwnerCompositions.filter( (composition) => composition.compositionType === CompositionTypeModel.INHERITANCE, ); + const currentPropertyAliases = await this.#workspaceContext.structure.getContentTypePropertyAliases(); + const compositionConfiguration = { compositionRepositoryAlias: this._compositionRepositoryAlias, unique: unique, - selection: currentOwnerCompositionCompositions.map((composition) => composition.contentType.unique), + selection: currentOwnerCompositionCompositionUniques, usedForInheritance: currentInheritanceCompositions.map((composition) => composition.contentType.unique), + usedForComposition: currentOwnerCompositionCompositionUniques, isElement: ownerContentType.isElement, - currentPropertyAliases: [], + currentPropertyAliases, isNew: this.#workspaceContext.getIsNew()!, };