From 7e4d372c42354fee9ecbebd8eb77f7da3bacd6a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 15 Nov 2023 21:35:24 +0100 Subject: [PATCH] fixed problem --- .../base-extension-initializer.controller.ts | 106 +++++++++++------- .../base-extensions-initializer.controller.ts | 7 +- ...tensions-element-initializer.controller.ts | 13 ++- .../core/section/section-default.element.ts | 4 +- 4 files changed, 81 insertions(+), 49 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts index 01c9c80f29..e2b8060604 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extension-initializer.controller.ts @@ -5,6 +5,7 @@ import { type ManifestWithDynamicConditions, type UmbExtensionRegistry, createExtensionApi, + UmbConditionConfigBase, } from '@umbraco-cms/backoffice/extension-api'; import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @@ -12,6 +13,7 @@ export abstract class UmbBaseExtensionInitializer< ManifestType extends ManifestWithDynamicConditions = ManifestWithDynamicConditions, SubClassType = never, > extends UmbBaseController { + // #promiseResolvers: Array<() => void> = []; #manifestObserver!: UmbObserverController; #extensionRegistry: UmbExtensionRegistry; @@ -74,7 +76,7 @@ export abstract class UmbBaseExtensionInitializer< this.#overwrites = extensionManifest.overwrites; } } - this.#gotConditions(); + this.#gotManifest(); } else { this.#overwrites = []; this.#cleanConditions(); @@ -90,16 +92,17 @@ export abstract class UmbBaseExtensionInitializer< } #cleanConditions() { + if (this.#conditionControllers.length === 0) return; this.#conditionControllers.forEach((controller) => controller.destroy()); this.#conditionControllers = []; this.removeControllerByAlias('_observeConditions'); } - #gotConditions() { + #gotManifest() { const conditionConfigs = this.#manifest?.conditions ?? []; // As conditionConfigs might have been configured as something else than an array, then we ignorer them. - if (conditionConfigs.length === undefined || conditionConfigs.length === 0) { + if (conditionConfigs.length === 0) { this.#cleanConditions(); this.#onConditionsChangedCallback(); return; @@ -131,41 +134,7 @@ export abstract class UmbBaseExtensionInitializer< // Observes the conditions and initialize as they come in. this.observe( this.#extensionRegistry.getByTypeAndAliases('condition', conditionAliases), - async (manifests) => { - const oldLength = this.#conditionControllers.length; - - // New comers: - manifests.forEach((conditionManifest) => { - const configsOfThisType = conditionConfigs.filter( - (conditionConfig) => conditionConfig.alias === conditionManifest.alias, - ); - - // Spin up conditions, based of condition configs: - configsOfThisType.forEach(async (conditionConfig) => { - // Check if we already have a controller for this config: - const existing = this.#conditionControllers.find((controller) => controller.config === conditionConfig); - if (!existing) { - const conditionController = await createExtensionApi(conditionManifest, [ - { - host: this, - manifest: conditionManifest, - config: conditionConfig, - onChange: this.#onConditionsChangedCallback, - }, - ]); - if (conditionController) { - // Some how listen to it? callback/event/onChange something. - this.#conditionControllers.push(conditionController); - } - } - }); - }); - - // If a change to amount of condition controllers, this will make sure that when new conditions are added, the callback is fired, so the extensions can be re-evaluated, starting out as bad. - if (oldLength !== this.#conditionControllers.length) { - this.#onConditionsChangedCallback(); - } - }, + this.#gotConditions, '_observeConditions', ); } else { @@ -178,6 +147,67 @@ export abstract class UmbBaseExtensionInitializer< } } + #gotConditions = (manifests: ManifestCondition[]) => { + manifests.forEach(this.#gotCondition); + }; + + #gotCondition = async (conditionManifest: ManifestCondition) => { + const conditionConfigs = this.#manifest?.conditions ?? []; + // + // Get just the conditions that uses this condition alias: + const configsOfThisType = conditionConfigs.filter( + (conditionConfig) => conditionConfig.alias === conditionManifest.alias, + ); + + // Create conditions, based of condition configs: + const newConditionControllers = await Promise.all( + configsOfThisType.map((conditionConfig) => this.#createConditionController(conditionManifest, conditionConfig)), + ); + + const oldLength = this.#conditionControllers.length; + + newConditionControllers + .filter((x) => x !== undefined) + .forEach((emerging) => { + // TODO: All of this could use a refactor at one point, when someone is fresh in their mind. + // Niels Notes: Current problem being that we are not aware about what is in the making, so we don't know if we end up creating the same condition multiple times. + // Because it took some time to create the conditions, it maybe have already gotten created by another cycle, so lets test again. + const existing = this.#conditionControllers.find((existing) => existing.config === emerging?.config); + if (!existing) { + this.#conditionControllers.push(emerging!); + } else { + emerging?.destroy(); + } + }); + + // If a change to amount of condition controllers, this will make sure that when new conditions are added, the callback is fired, so the extensions can be re-evaluated, starting out as bad. + if (oldLength !== this.#conditionControllers.length) { + this.#onConditionsChangedCallback(); + } + }; + + async #createConditionController( + conditionManifest: ManifestCondition, + conditionConfig: UmbConditionConfigBase, + ): Promise { + // Check if we already have a controller for this config: + const existing = this.#conditionControllers.find((controller) => controller.config === conditionConfig); + if (!existing) { + const conditionController = await createExtensionApi(conditionManifest, [ + { + host: this, + manifest: conditionManifest, + config: conditionConfig, + onChange: this.#onConditionsChangedCallback, + }, + ]); + if (conditionController) { + return conditionController; + } + } + return undefined; + } + #conditionsAreInitialized() { // Not good if we don't have a manifest. // Only good if conditions of manifest is equal to the amount of condition controllers (one for each condition). diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts index f84d87efd9..31dd2be80e 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts @@ -6,7 +6,6 @@ import type { UmbExtensionRegistry, } from '@umbraco-cms/backoffice/extension-api'; import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; export type PermittedControllerType = ControllerType & { manifest: Required>; @@ -70,9 +69,9 @@ export abstract class UmbBaseExtensionsInitializer< } // Clean up extensions that are no longer. - this._extensions = this._extensions.filter((controller) => { - if (!manifests.find((manifest) => manifest.alias === controller.alias)) { - controller.destroy(); + this._extensions = this._extensions.filter((extension) => { + if (!manifests.find((manifest) => manifest.alias === extension.alias)) { + extension.destroy(); // destroying the controller will, if permitted, make a last callback with isPermitted = false. This will also remove it from the _permittedExts array. return false; } diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts index 967db5f36f..d12714c73b 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts @@ -1,5 +1,8 @@ import type { ManifestTypeMap, SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; -import { type PermittedControllerType, UmbBaseExtensionsInitializer } from './base-extensions-initializer.controller.js'; +import { + type PermittedControllerType, + UmbBaseExtensionsInitializer, +} from './base-extensions-initializer.controller.js'; import { type ManifestBase, UmbExtensionElementInitializer, @@ -11,10 +14,10 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; */ export class UmbExtensionsElementInitializer< ManifestTypes extends ManifestBase, - ManifestTypeName extends keyof ManifestTypeMap | string = ManifestTypes["type"], + ManifestTypeName extends keyof ManifestTypeMap | string = ManifestTypes['type'], ManifestType extends ManifestBase = SpecificManifestTypeOrManifestBase, ControllerType extends UmbExtensionElementInitializer = UmbExtensionElementInitializer, - MyPermittedControllerType extends ControllerType = PermittedControllerType + MyPermittedControllerType extends ControllerType = PermittedControllerType, > extends UmbBaseExtensionsInitializer< ManifestTypes, ManifestTypeName, @@ -43,7 +46,7 @@ export class UmbExtensionsElementInitializer< type: ManifestTypeName | Array, filter: undefined | null | ((manifest: ManifestType) => boolean), onChange: (permittedManifests: Array) => void, - defaultElement?: string + defaultElement?: string, ) { super(host, extensionRegistry, type, filter, onChange); this.#extensionRegistry = extensionRegistry; @@ -57,7 +60,7 @@ export class UmbExtensionsElementInitializer< this.#extensionRegistry, manifest.alias, this._extensionChanged, - this._defaultElement + this._defaultElement, ) as ControllerType; extController.properties = this.#props; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-default.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-default.element.ts index e502cfacc8..fc54a88ad5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-default.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-default.element.ts @@ -1,6 +1,6 @@ import type { UmbWorkspaceElement } from '../workspace/workspace.element.js'; import type { UmbSectionMainViewElement } from './section-main-views/section-main-views.element.js'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { ManifestSection, @@ -82,7 +82,7 @@ export class UmbSectionDefaultElement extends UmbLitElement implements UmbSectio ${repeat( this._sidebarApps, (app) => app.alias, - (app) => app.component + (app) => app.component, )} `