diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.interface.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.interface.ts index b7f7cc9dcd..9e5de261c0 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.interface.ts @@ -16,8 +16,8 @@ export interface UmbClassMixinInterface extends UmbControllerHost, UmbController unique?: string ): UmbObserverController; provideContext(alias: string | UmbContextToken, instance: R): UmbContextProviderController; - consumeContext( - alias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController; + consumeContext( + alias: string | UmbContextToken, + callback: UmbContextCallback + ): UmbContextConsumerController; } diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts index 8d8364766d..b870354492 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts @@ -28,10 +28,10 @@ declare class UmbClassMixinDeclaration implements UmbClassMixinInterface { controllerAlias?: UmbControllerAlias ): UmbObserverController; provideContext(alias: string | UmbContextToken, instance: R): UmbContextProviderController; - consumeContext( - alias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController; + consumeContext( + alias: string | UmbContextToken, + callback: UmbContextCallback + ): UmbContextConsumerController; hasController(controller: UmbController): boolean; getControllers(filterMethod: (ctrl: UmbController) => boolean): UmbController[]; addController(controller: UmbController): void; @@ -96,10 +96,10 @@ export const UmbClassMixin = (superClass: T) => { * @return {UmbContextConsumerController} Reference to a Context Consumer Controller instance * @memberof UmbElementMixin */ - consumeContext( - contextAlias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController { + consumeContext( + contextAlias: string | UmbContextToken, + callback: UmbContextCallback + ): UmbContextConsumerController { return new UmbContextConsumerController(this, contextAlias, callback); } } diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.controller.ts index 69d9737250..2194903148 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.controller.ts @@ -3,7 +3,12 @@ import { UmbContextConsumer } from './context-consumer.js'; import { UmbContextCallback } from './context-request.event.js'; import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api'; -export class UmbContextConsumerController extends UmbContextConsumer implements UmbController { + +export class UmbContextConsumerController< + BaseType = unknown, + DiscriminatedType extends BaseType = never, + ResultType extends BaseType = keyof DiscriminatedType extends BaseType ? DiscriminatedType : BaseType +> extends UmbContextConsumer implements UmbController { #controllerAlias = Symbol(); #host: UmbControllerHost; @@ -11,7 +16,7 @@ export class UmbContextConsumerController extends UmbContextConsume return this.#controllerAlias; } - constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken, callback: UmbContextCallback) { + constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken, callback: UmbContextCallback) { super(host.getHostElement(), contextAlias, callback); this.#host = host; host.addController(this); diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts index f671be1a38..b50fe5ecfe 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts @@ -11,12 +11,15 @@ import { UmbContextRequestEventImplementation, UmbContextCallback } from './cont * @export * @class UmbContextConsumer */ -export class UmbContextConsumer { - #callback?: UmbContextCallback; - #promise?: Promise; - #promiseResolver?: (instance: DiscriminatedType) => void; +export class UmbContextConsumer< +BaseType = unknown, +DiscriminatedType extends BaseType = never, +ResultType extends BaseType = keyof DiscriminatedType extends BaseType ? DiscriminatedType : BaseType> { + #callback?: UmbContextCallback; + #promise?: Promise; + #promiseResolver?: (instance: ResultType) => void; - #instance?: DiscriminatedType; + #instance?: ResultType; get instance() { return this.#instance; } @@ -34,8 +37,8 @@ export class UmbContextConsumer, - callback?: UmbContextCallback + contextAlias: string | UmbContextToken, + callback?: UmbContextCallback ) { this.#contextAlias = contextAlias.toString(); this.#callback = callback; @@ -55,14 +58,14 @@ export class UmbContextConsumer((resolve) => { + (this.#promise = new Promise((resolve) => { this.#instance ? resolve(this.#instance) : (this.#promiseResolver = resolve); })) ); diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.ts index 25b473e58c..afd0e772bc 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.ts @@ -9,9 +9,9 @@ export type UmbContextCallback = (instance: T) => void; * @export * @interface UmbContextRequestEvent */ -export interface UmbContextRequestEvent extends Event { - readonly contextAlias: string | UmbContextToken; - readonly callback: UmbContextCallback; +export interface UmbContextRequestEvent extends Event { + readonly contextAlias: string | UmbContextToken; + readonly callback: UmbContextCallback; } /** @@ -20,10 +20,10 @@ export interface UmbContextRequestEvent extends Event { * @extends {Event} * @implements {UmbContextRequestEvent} */ -export class UmbContextRequestEventImplementation extends Event implements UmbContextRequestEvent { +export class UmbContextRequestEventImplementation extends Event implements UmbContextRequestEvent { public constructor( - public readonly contextAlias: string | UmbContextToken, - public readonly callback: UmbContextCallback + public readonly contextAlias: string | UmbContextToken, + public readonly callback: UmbContextCallback ) { super(umbContextRequestEventType, { bubbles: true, composed: true, cancelable: true }); } diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.ts index f3db2560b3..6734d971e6 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.ts @@ -2,14 +2,18 @@ import { UmbContextToken } from '../token/context-token.js'; import { UmbContextProvider } from './context-provider.js'; import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api'; -export class UmbContextProviderController extends UmbContextProvider implements UmbController { +export class UmbContextProviderController< + BaseType = unknown, + DiscriminatorType extends BaseType = never, + ResultType extends BaseType = keyof DiscriminatorType extends BaseType ? DiscriminatorType : BaseType +> extends UmbContextProvider implements UmbController { #host: UmbControllerHost; public get controllerAlias() { return this._contextAlias.toString(); } - constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken, instance: T) { + constructor(host: UmbControllerHost, contextAlias: string | UmbContextToken, instance: ResultType) { super(host.getHostElement(), contextAlias, instance); this.#host = host; diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts index 90418bcab7..162a9cdd99 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts @@ -13,7 +13,7 @@ import { * @export * @class UmbContextProvider */ -export class UmbContextProvider { +export class UmbContextProvider { protected hostElement: EventTarget; protected _contextAlias: string; @@ -35,7 +35,7 @@ export class UmbContextProvider { * @param {*} instance * @memberof UmbContextProvider */ - constructor(hostElement: EventTarget, contextAlias: string | UmbContextToken, instance: unknown) { + constructor(hostElement: EventTarget, contextAlias: string | UmbContextToken, instance: ResultType) { this.hostElement = hostElement; this._contextAlias = contextAlias.toString(); this.#instance = instance; diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.ts index 826d1ca066..e90e74cd72 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.ts @@ -1,7 +1,7 @@ -export type UmbContextDiscriminator = (instance: BaseType) => instance is DiscriminatorResult; +export type UmbContextDiscriminator = (instance: BaseType) => instance is DiscriminatorResult; -export class UmbContextToken { +export class UmbContextToken { #discriminator: UmbContextDiscriminator | undefined; /** @@ -13,7 +13,7 @@ export class UmbContextToken; provideContext(alias: string | UmbContextToken, instance: R): UmbContextProviderController; - consumeContext( - alias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController; + consumeContext( + alias: string | UmbContextToken, + callback: UmbContextCallback + ): UmbContextConsumerController; } export const UmbElementMixin = (superClass: T) => { @@ -64,10 +64,10 @@ export const UmbElementMixin = (superClass: T) * @return {UmbContextConsumerController} Reference to a Context Consumer Controller instance * @memberof UmbElementMixin */ - consumeContext( - alias: string | UmbContextToken, - callback: UmbContextCallback - ): UmbContextConsumerController { + consumeContext( + alias: string | UmbContextToken, + callback: UmbContextCallback + ): UmbContextConsumerController { return new UmbContextConsumerController(this, alias, callback); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/data-type-workspace.context.ts index 4c2e250cb5..4019f99469 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/data-type-workspace.context.ts @@ -3,6 +3,7 @@ import { UmbEntityWorkspaceContextInterface, UmbWorkspaceContext } from '@umbrac import type { DataTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { appendToFrozenArray, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export class UmbDataTypeWorkspaceContext extends UmbWorkspaceContext @@ -95,3 +96,8 @@ export class UmbDataTypeWorkspaceContext this.#data.complete(); } } + +export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken( + 'UmbWorkspaceContext', + (context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type' +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts index d8ef6db802..f08a2a72d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts @@ -1,7 +1,6 @@ -import { UmbDataTypeWorkspaceContext } from '../../data-type-workspace.context.js'; +import { UMB_DATA_TYPE_WORKSPACE_CONTEXT, UmbDataTypeWorkspaceContext } from '../../data-type-workspace.context.js'; import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN, @@ -47,9 +46,8 @@ export class UmbDataTypeDetailsWorkspaceViewEditElement this._modalContext = instance; }); - // TODO: Figure out if this is the best way to consume a context or if it could be strongly typed using UmbContextToken - this.consumeContext(UMB_WORKSPACE_CONTEXT, (_instance) => { - this._workspaceContext = _instance as UmbDataTypeWorkspaceContext; + this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (_instance) => { + this._workspaceContext = _instance; this._observeDataType(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.token.ts b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.token.ts index 36a5862575..831ead587c 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/auth/auth.token.ts +++ b/src/Umbraco.Web.UI.Client/src/shared/auth/auth.token.ts @@ -2,6 +2,5 @@ import { IUmbAuth } from './auth.interface.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_AUTH = new UmbContextToken( - 'UmbAuth', - 'An instance of UmbAuthFlow that should be shared across the app.' + 'UmbAuth' );