diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts index 86525593be..fb1d017015 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.ts @@ -1,17 +1,19 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; // The Example Workspace Context Controller: -export class WorkspaceContextCounter extends UmbControllerBase { +export class WorkspaceContextCounterElement extends UmbContextBase< + WorkspaceContextCounterElement, + typeof EXAMPLE_COUNTER_CONTEXT +> { // We always keep our states private, and expose the values as observables: #counter = new UmbNumberState(0); readonly counter = this.#counter.asObservable(); constructor(host: UmbControllerHost) { - super(host, EXAMPLE_COUNTER_CONTEXT.toString()); - this.provideContext(EXAMPLE_COUNTER_CONTEXT, this); + super(host, EXAMPLE_COUNTER_CONTEXT); } // Lets expose methods to update the state: @@ -21,10 +23,10 @@ export class WorkspaceContextCounter extends UmbControllerBase { } // Declare a api export, so Extension Registry can initialize this class: -export const api = WorkspaceContextCounter; +export const api = WorkspaceContextCounterElement; // Declare a Context Token that other elements can use to request the WorkspaceContextCounter: -export const EXAMPLE_COUNTER_CONTEXT = new UmbContextToken( +export const EXAMPLE_COUNTER_CONTEXT = new UmbContextToken( 'UmbWorkspaceContext', 'example.workspaceContext.counter', ); diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts index 717a07f654..87081f11b1 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-main.element.ts @@ -95,7 +95,7 @@ export class UmbBackofficeMainElement extends UmbLitElement { private _provideSectionContext(sectionManifest: ManifestSection) { if (!this._sectionContext) { - this._sectionContext = new UmbSectionContext(sectionManifest); + this._sectionContext = new UmbSectionContext(this, sectionManifest); this.provideContext(UMB_SECTION_CONTEXT, this._sectionContext); } else { this._sectionContext.setManifest(sectionManifest); diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts index 6008563367..d60a58df9f 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts @@ -5,6 +5,7 @@ import type { Meta, StoryFn } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; import './installer-error.element.js'; +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; const error = { type: 'validation', @@ -20,14 +21,17 @@ const error = { }, }; -const installerContext = new UmbInstallerContext(); -installerContext.setInstallStatus(error); +const installerContextMethod = (host: UmbControllerHostElement) => { + const installerContext = new UmbInstallerContext(host); + installerContext.setInstallStatus(error); + return installerContext; +}; export default { title: 'Apps/Installer/Steps', component: 'umb-installer-error', id: 'umb-installer-error', - decorators: [(story) => installerContextProvider(story, installerContext)], + decorators: [(story) => installerContextProvider(story, installerContextMethod)], } as Meta; export const Step5Error: StoryFn = () => html``; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts index ad203dbf29..0193999416 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.context.ts @@ -8,12 +8,14 @@ import { InstallService, TelemetryLevelModel } from '@umbraco-cms/backoffice/ext import { tryExecute } from '@umbraco-cms/backoffice/resources'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbObjectState, UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; /** * Context API for the installer * @class UmbInstallerContext */ -export class UmbInstallerContext { +export class UmbInstallerContext extends UmbContextBase { private _data = new UmbObjectState({ user: { name: '', email: '', password: '', subscribeToNewsletter: false }, database: { id: '', providerName: '', useIntegratedAuthentication: false, trustServerCertificate: false }, @@ -30,7 +32,8 @@ export class UmbInstallerContext { private _installStatus = new UmbObjectState(null); public readonly installStatus = this._installStatus.asObservable(); - constructor() { + constructor(host: UmbControllerHost) { + super(host, UMB_INSTALLER_CONTEXT); this._loadInstallerSettings(); } diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.element.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.element.ts index bbd49dbcc0..7de17887b0 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.element.ts @@ -1,4 +1,4 @@ -import { UmbInstallerContext, UMB_INSTALLER_CONTEXT } from './installer.context.js'; +import { UmbInstallerContext } from './installer.context.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @@ -14,12 +14,7 @@ export class UmbInstallerElement extends UmbLitElement { @state() step = 1; - private _umbInstallerContext = new UmbInstallerContext(); - - constructor() { - super(); - this.provideContext(UMB_INSTALLER_CONTEXT, this._umbInstallerContext); - } + private _umbInstallerContext = new UmbInstallerContext(this); override connectedCallback(): void { super.connectedCallback(); diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/shared/utils.story-helpers.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/shared/utils.story-helpers.ts index e22e315b24..2828cb638d 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/shared/utils.story-helpers.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/installer/shared/utils.story-helpers.ts @@ -1,14 +1,16 @@ import { UmbInstallerContext } from '../installer.context.js'; +import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { html, type TemplateResult } from '@umbraco-cms/backoffice/external/lit'; export const installerContextProvider = ( story: () => Node | string | TemplateResult, - installerContext = new UmbInstallerContext(), + createContextMethod = (host: UmbControllerHostElement) => { + return new UmbInstallerContext(host); + }, ) => html` - + .create=${createContextMethod}> ${story()} - + `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts index 61cd3892a0..1295413273 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/backoffice-modal-container/backoffice-modal-container.element.ts @@ -49,8 +49,11 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement { oldModals.forEach((modal) => { // TODO: I would not think this works as expected, the callback method has to be the exact same instance as the one added: [NL] - this._modalElementMap.get(modal.key)?.removeEventListener('close-end', this.#onCloseEnd.bind(this, modal.key)); + const modalElement = this._modalElementMap.get(modal.key); + modalElement?.removeEventListener('close-end', this.#onCloseEnd.bind(this, modal.key)); + modalElement?.destroy(); this._modalElementMap.delete(modal.key); + modal.destroy(); }); if (this._modals.length === 0) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/index.ts index ed60e33603..242a263f7a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/index.ts @@ -1,2 +1 @@ export * from './menu.element.js'; -export * from './menu.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.context.ts deleted file mode 100644 index c96cdbb94e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.context.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { ManifestMenu } from '../../menu.extension.js'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbDeepState } from '@umbraco-cms/backoffice/observable-api'; - -export class UmbMenuContext { - #manifest = new UmbDeepState(undefined); - public readonly manifest = this.#manifest.asObservable(); - public readonly alias = this.#manifest.asObservablePart((x) => x?.alias); - - public setManifest(manifest: ManifestMenu | undefined) { - this.#manifest.setValue(manifest); - } -} - -export const UMB_MENU_CONTEXT = new UmbContextToken('UMB_MENU_CONTEXT'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.element.ts index 026a6277f3..7e051db0e0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/components/menu/menu.element.ts @@ -10,11 +10,6 @@ export class UmbMenuElement extends UmbLitElement { @property({ attribute: false }) manifest?: ManifestMenu; - constructor() { - super(); - //this.provideContext(UMB_MENU_CONTEXT, new UmbMenuContext()); - } - override render() { return html` ) { super(host, args); + console.error( + 'Condition of alias `Umb.Condition.MenuAlias` is not implemented. Please report this issue if you where expecting this condition to work.', + ); + /* this.consumeContext(UMB_MENU_CONTEXT, (context) => { this.observe( context.alias, @@ -21,6 +24,7 @@ export class UmbMenuAliasCondition extends UmbConditionBase { #manifestAlias = new UmbStringState(undefined); #manifestPathname = new UmbStringState(undefined); #manifestLabel = new UmbStringState(undefined); @@ -10,7 +12,8 @@ export class UmbSectionContext { public readonly pathname = this.#manifestPathname.asObservable(); public readonly label = this.#manifestLabel.asObservable(); - constructor(manifest: ManifestSection) { + constructor(host: UmbControllerHost, manifest: ManifestSection) { + super(host, UMB_SECTION_CONTEXT); this.setManifest(manifest); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts index b69994d8a9..8829599ee0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/global-contexts/document-configuration.context.ts @@ -1,4 +1,4 @@ -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; @@ -10,15 +10,17 @@ import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; * A context for fetching and caching the document configuration. * @deprecated Do not use this one, it will have ot change in near future. */ -export class UmbDocumentConfigurationContext extends UmbControllerBase implements UmbApi { +export class UmbDocumentConfigurationContext + extends UmbContextBase + implements UmbApi +{ /** * The cached document configuration. */ static #DocumentConfiguration: Promise; constructor(host: UmbControllerHost) { - super(host); - this.provideContext(UMB_DOCUMENT_CONFIGURATION_CONTEXT, this); + super(host, UMB_DOCUMENT_CONFIGURATION_CONTEXT); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts index cb468209f7..fd5e06405f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.element.ts @@ -1,7 +1,7 @@ import type { UmbDashboardHealthCheckGroupElement } from './views/health-check-group.element.js'; -import { UmbHealthCheckDashboardContext, UMB_HEALTHCHECK_DASHBOARD_CONTEXT } from './health-check-dashboard.context.js'; +import { UmbHealthCheckDashboardContext } from './health-check-dashboard.context.js'; import type { ManifestHealthCheck } from './health-check.extension.js'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, state, type PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import type { HealthCheckGroupResponseModel } from '@umbraco-cms/backoffice/external/backend-api'; import { HealthCheckService } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; @@ -35,14 +35,14 @@ export class UmbDashboardHealthCheckElement extends UmbLitElement { constructor() { super(); - this.provideContext(UMB_HEALTHCHECK_DASHBOARD_CONTEXT, this._healthCheckDashboardContext); this.observe(umbExtensionsRegistry.byType('healthCheck'), (healthCheckManifests) => { this._healthCheckDashboardContext.manifests = healthCheckManifests; }); } - protected override firstUpdated() { + protected override firstUpdated(_changedProperties: PropertyValueMap | Map) { + super.firstUpdated(_changedProperties); this.#registerHealthChecks(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check-dashboard.context.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check-dashboard.context.ts index 2801a13365..516bf4b191 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check-dashboard.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/health-check-dashboard.context.ts @@ -1,9 +1,14 @@ +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbHealthCheckContext } from './health-check.context.js'; import type { ManifestHealthCheck } from './health-check.extension.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { loadManifestApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbHealthCheckDashboardContext { +export class UmbHealthCheckDashboardContext extends UmbContextBase< + UmbHealthCheckDashboardContext, + typeof UMB_HEALTHCHECK_DASHBOARD_CONTEXT +> { #manifests: ManifestHealthCheck[] = []; set manifests(value: ManifestHealthCheck[]) { this.#manifests = value; @@ -14,10 +19,9 @@ export class UmbHealthCheckDashboardContext { } public apis = new Map(); - public host: HTMLElement; - constructor(host: HTMLElement) { - this.host = host; + constructor(host: UmbControllerHost) { + super(host, UMB_HEALTHCHECK_DASHBOARD_CONTEXT); } async checkAll() { @@ -32,7 +36,7 @@ export class UmbHealthCheckDashboardContext { if (!manifest.api) return; const api = await loadManifestApi(manifest.api); if (!api) return; - const apiInstance = new api(this.host); + const apiInstance = new api(this); if (api && UmbHealthCheckContext.isInstanceLike(apiInstance)) this.apis.set(manifest.meta.label, apiInstance); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context.ts index 0c1f7c84f2..664927d4a6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context.ts @@ -11,7 +11,7 @@ import type { } from '@umbraco-cms/backoffice/external/backend-api'; import { DirectionModel, LogLevelModel } from '@umbraco-cms/backoffice/external/backend-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { query } from '@umbraco-cms/backoffice/router'; import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @@ -27,7 +27,10 @@ export interface LogViewerDateRange { } // TODO: Revisit usage of workspace for this case... -export class UmbLogViewerWorkspaceContext extends UmbControllerBase implements UmbWorkspaceContext { +export class UmbLogViewerWorkspaceContext + extends UmbContextBase + implements UmbWorkspaceContext +{ public readonly workspaceAlias: string = 'Umb.Workspace.LogViewer'; #repository: UmbLogViewerRepository; @@ -104,10 +107,9 @@ export class UmbLogViewerWorkspaceContext extends UmbControllerBase implements U currentPage = 1; constructor(host: UmbControllerHost) { - super(host); + super(host, UMB_APP_LOG_VIEWER_CONTEXT); + // TODO: Revisit usage of workspace for this case... currently no other workspace context provides them self with their own token, we need to update UMB_APP_LOG_VIEWER_CONTEXT to become a workspace context. [NL] this.provideContext(UMB_WORKSPACE_CONTEXT, this); - // TODO: Revisit usage of workspace for this case... currently no other workspace context provides them self with their own token. - this.provideContext(UMB_APP_LOG_VIEWER_CONTEXT, this); this.#repository = new UmbLogViewerRepository(host); }