From e57df8025c44234b426dcf86a6e44e80d6388aa5 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 11:10:48 +0000 Subject: [PATCH] Adds prependCondition and prependConditions so you can make sure your condition loads first, as order of conditions are important --- .../registry/extension.registry.test.ts | 89 +++++++++++++++++++ .../registry/extension.registry.ts | 48 ++++++++-- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts index f6add8c5c2..9add871f65 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.test.ts @@ -554,3 +554,92 @@ describe('Append Conditions', () => { expect(ext.conditions?.length).to.equal(3); }); }); + +describe('Prepend Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + it('allows an extension condition to be prepended', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); + + it('allows an extension to update with multiple prepended conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ]; + + extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); +}); diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts index e776d131f2..ed142671ac 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,9 @@ -import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestBase, + ManifestKind, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -434,7 +439,7 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } - + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -447,12 +452,12 @@ export class UmbExtensionRegistry< const allExtensions = this._extensions.getValue(); const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; - if(extensionToUpdate === undefined) { + if (extensionToUpdate === undefined) { console.error(`Extension with alias ${alias} not found`); } // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions){ + if (extensionToUpdate.conditions) { extensionToUpdate.conditions.push(newCondition); } else { extensionToUpdate.conditions = [newCondition]; @@ -467,7 +472,40 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array){ + appendConditions(alias: string, newConditions: Array) { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } + + /** + * Prepends a new condition to an existing extension + * @param alias {string} - The alias of the extension to prepend the condition to + * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. + */ + prependCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if (extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Prepend the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } + + /** + * Prepends a collection of conditions to an existing extension + * @param alias {string} - The alias of the extension to prepend the conditions to + * @param newConditions {Array} - A collection of conditions to prepend to an extension. + */ + prependConditions(alias: string, newConditions: Array) { + newConditions.forEach((condition) => this.prependCondition(alias, condition)); + } }