diff --git a/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-validator.ts b/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-validator.ts index d76ee61636c0..a97f54b44712 100644 --- a/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-validator.ts +++ b/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-validator.ts @@ -40,7 +40,7 @@ export class CustomValidationValidator extends UmbControllerBase implements UmbV this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, async (context) => { this.#workspaceContext = context; this.observe( - await context.propertyValueByAlias(propertyAlias, this.#variantId), + await context?.propertyValueByAlias(propertyAlias, this.#variantId), (value) => { this.#value = value; this.#checkValidation(); diff --git a/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-workspace-context.ts b/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-workspace-context.ts index df923540cee0..e7f071985523 100644 --- a/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/examples/custom-validation-workspace-context/custom-validation-workspace-context.ts @@ -8,10 +8,7 @@ import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; const EXAMPLE_CUSTOM_VALIDATION_PROPERTY_ALIAS = 'tiptap'; // The Example Workspace Context Controller: -export class CustomValidationWorkspaceContext extends UmbContextBase< - CustomValidationWorkspaceContext, - typeof EXAMPLE_CUSTOM_VALIDATION_CONTEXT -> { +export class CustomValidationWorkspaceContext extends UmbContextBase { #validators?: Array; constructor(host: UmbControllerHost) { @@ -30,12 +27,12 @@ export class CustomValidationWorkspaceContext extends UmbContextBase< if (propertyType.variesByCulture) { // Because this property exists in multiple cultures we should observe cultures an create a custom validator for each culture value: this.observe( - context.variantOptions, + context?.variantOptions, (variantOptions) => { // clean up old validators: this.#validators?.forEach((x) => x.destroy()); - this.#validators = variantOptions.map((option) => { + this.#validators = variantOptions?.map((option) => { return new CustomValidationValidator( this, EXAMPLE_CUSTOM_VALIDATION_PROPERTY_ALIAS, diff --git a/src/Umbraco.Web.UI.Client/examples/validation-context/validation-context-dashboard.ts b/src/Umbraco.Web.UI.Client/examples/validation-context/validation-context-dashboard.ts index e328d10067ab..cf50893f3061 100644 --- a/src/Umbraco.Web.UI.Client/examples/validation-context/validation-context-dashboard.ts +++ b/src/Umbraco.Web.UI.Client/examples/validation-context/validation-context-dashboard.ts @@ -39,7 +39,7 @@ export class UmbExampleValidationContextDashboardElement extends UmbLitElement { this.consumeContext(UMB_VALIDATION_CONTEXT, (validationContext) => { this.observe( - validationContext.messages.messages, + validationContext?.messages.messages, (messages) => { this.messages = messages; }, 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 fb1d01701579..5f3d813f542e 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 @@ -4,10 +4,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbNumberState } from '@umbraco-cms/backoffice/observable-api'; // The Example Workspace Context Controller: -export class WorkspaceContextCounterElement extends UmbContextBase< - WorkspaceContextCounterElement, - typeof EXAMPLE_COUNTER_CONTEXT -> { +export class WorkspaceContextCounterElement extends UmbContextBase { // We always keep our states private, and expose the values as observables: #counter = new UmbNumberState(0); readonly counter = this.#counter.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts index 69b1b2381a4d..ea7e2b88136f 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-view.ts @@ -1,7 +1,7 @@ +import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state, LitElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context'; @customElement('example-counter-workspace-view') export class ExampleCounterWorkspaceView extends UmbElementMixin(LitElement) { diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts index 93f1f6de1d2e..69cfb190f9fa 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts @@ -19,7 +19,7 @@ export class UmbAppAuthController extends UmbControllerBase { // Observe the user's authorization state and start the authorization flow if the user is not authorized this.observe( - context.timeoutSignal, + context?.timeoutSignal, () => { this.makeAuthorizationRequest('timedOut'); }, diff --git a/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts b/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts index b1b160309e5e..802c3c947fa3 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/app/app-logo.element.ts @@ -43,12 +43,12 @@ export class UmbAppLogoElement extends UmbLitElement { super(); this.consumeContext(UMB_SERVER_CONTEXT, (instance) => { - this._serverUrl = instance.getServerUrl(); + this._serverUrl = instance?.getServerUrl(); }); this.consumeContext(UMB_THEME_CONTEXT, (context) => { this.observe( - context.theme, + context?.theme, (theme) => { this._theme = theme; }, diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts index ee79a30bff74..db4951ef64a0 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts @@ -12,7 +12,7 @@ import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; import { UmbSysinfoRepository } from '@umbraco-cms/backoffice/sysinfo'; -export class UmbBackofficeContext extends UmbContextBase { +export class UmbBackofficeContext extends UmbContextBase { #activeSectionAlias = new UmbStringState(undefined); public readonly activeSectionAlias = this.#activeSectionAlias.asObservable(); @@ -28,7 +28,7 @@ export class UmbBackofficeContext extends UmbContextBase { // TODO: We need to ensure this request is called every time the user logs in, but this should be done somewhere across the app and not here [JOV] this.consumeContext(UMB_AUTH_CONTEXT, (authContext) => { - this.observe(authContext.isAuthorized, (isAuthorized) => { + this.observe(authContext?.isAuthorized, (isAuthorized) => { if (!isAuthorized) return; this.#getVersion(); }); @@ -36,7 +36,7 @@ export class UmbBackofficeContext extends UmbContextBase { this.consumeContext(UMB_CURRENT_USER_CONTEXT, (userContext) => { this.observe( - userContext.allowedSections, + userContext?.allowedSections, (allowedSections) => { if (!allowedSections) return; // TODO: Please be aware that we re-initialize this initializer based on user permissions. I suggest we should solve this specific case should be improved by the ability to change the filter [NL] diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts index c95a3af0b5f8..1a6523e7b043 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts @@ -77,7 +77,7 @@ export class UmbBackofficeElement extends UmbLitElement { // TODO: We need to ensure this request is called every time the user logs in, but this should be done somewhere across the app and not here [JOV] this.consumeContext(UMB_AUTH_CONTEXT, (authContext) => { - this.observe(authContext.isAuthorized, (isAuthorized) => { + this.observe(authContext?.isAuthorized, (isAuthorized) => { if (!isAuthorized) return; serverExtensions.registerPrivateExtensions(); }); diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts index 5c7cbe4484d9..abc12ce0cf6d 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/components/backoffice-header-logo.element.ts @@ -35,7 +35,7 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement { this.consumeContext(UMB_BACKOFFICE_CONTEXT, (context) => { this.observe( - context.version, + context?.version, (version) => { if (!version) return; this._version = version; 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 bc77b8dcffd5..b638c1d94eb6 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 @@ -14,7 +14,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; * Context API for the installer * @class UmbInstallerContext */ -export class UmbInstallerContext extends UmbContextBase { +export class UmbInstallerContext extends UmbContextBase { private _data = new UmbObjectState({ user: { name: '', email: '', password: '', subscribeToNewsletter: false }, database: { id: '', providerName: '', useIntegratedAuthentication: false, trustServerCertificate: false }, diff --git a/src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts b/src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts index 9fac3a4f4a6d..014ed0cc3125 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts @@ -8,7 +8,7 @@ import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server'; const UMB_LOCALSTORAGE_SESSION_KEY = 'umb:previewSessions'; -export class UmbPreviewContext extends UmbContextBase { +export class UmbPreviewContext extends UmbContextBase { #culture?: string | null; #serverUrl: string = ''; #webSocket?: WebSocket; @@ -26,7 +26,7 @@ export class UmbPreviewContext extends UmbContextBase { super(host, UMB_PREVIEW_CONTEXT); this.consumeContext(UMB_SERVER_CONTEXT, (instance) => { - this.#serverUrl = instance.getServerUrl(); + this.#serverUrl = instance?.getServerUrl() ?? ''; const params = new URLSearchParams(window.location.search); 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 e25e08831ca4..326ad68d593b 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 @@ -2,6 +2,7 @@ import type { UmbContextCallback, UmbContextConsumerAsPromiseOptionsType, UmbContextConsumerController, + UmbContextMinimal, UmbContextProviderController, UmbContextToken, } from '@umbraco-cms/backoffice/context-api'; @@ -48,7 +49,10 @@ export interface UmbClassInterface extends UmbControllerHost { * @returns {UmbContextProviderController} Reference to the created Context Provider Controller instance * @memberof UmbClassInterface */ - provideContext(alias: string | UmbContextToken, instance: R): UmbContextProviderController; + provideContext( + alias: string | UmbContextToken, + instance: R, + ): UmbContextProviderController; /** * @description Setup a subscription for a context. The callback is called when the context is resolved. @@ -57,7 +61,7 @@ export interface UmbClassInterface extends UmbControllerHost { * @returns {UmbContextConsumerController} Reference to the created Context Consumer Controller instance * @memberof UmbClassInterface */ - consumeContext( + consumeContext( alias: string | UmbContextToken, callback: UmbContextCallback, ): UmbContextConsumerController; @@ -68,7 +72,7 @@ export interface UmbClassInterface extends UmbControllerHost { * @returns {Promise} A Promise with the reference to the Context Api Instance * @memberof UmbClassInterface */ - getContext( + getContext( alias: string | UmbContextToken, options?: UmbClassGetContextOptions, ): Promise; 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 4f4b11b37834..7d51a9c4005a 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 @@ -12,6 +12,7 @@ import { type UmbContextCallback, UmbContextConsumerController, UmbContextProviderController, + type UmbContextMinimal, } from '@umbraco-cms/backoffice/context-api'; import { type ObserverCallback, UmbObserverController, simpleHashCode } from '@umbraco-cms/backoffice/observable-api'; @@ -80,7 +81,7 @@ export const UmbClassMixin = >(superClas } provideContext< - BaseType = unknown, + BaseType extends UmbContextMinimal = UmbContextMinimal, ResultType extends BaseType = BaseType, InstanceType extends ResultType = ResultType, >( @@ -90,14 +91,14 @@ export const UmbClassMixin = >(superClas return new UmbContextProviderController(this, contextAlias, instance); } - consumeContext( + consumeContext( contextAlias: string | UmbContextToken, callback: UmbContextCallback, ): UmbContextConsumerController { return new UmbContextConsumerController(this, contextAlias, callback); } - async getContext( + async getContext( contextAlias: string | UmbContextToken, options?: UmbClassGetContextOptions, ): Promise { @@ -116,9 +117,11 @@ export const UmbClassMixin = >(superClas public override destroy(): void { if (this._host) { this._host.removeUmbController(this); - this._host = undefined as never; } super.destroy(); + if (this._host) { + this._host = undefined as never; + } } } diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/context-base.class.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/context-base.class.ts index 17739ff1fd59..a8b23491326e 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/context-base.class.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/context-base.class.ts @@ -7,15 +7,9 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; * This base provides the necessary for a class to become a context-api controller. * */ -export abstract class UmbContextBase< - ContextType, - GivenContextToken extends UmbContextToken = UmbContextToken, - > - extends UmbControllerBase - implements UmbContext -{ - constructor(host: UmbControllerHost, contextToken: GivenContextToken | string) { +export abstract class UmbContextBase extends UmbControllerBase implements UmbContext { + constructor(host: UmbControllerHost, contextToken: UmbContextToken | string) { super(host, contextToken.toString()); - this.provideContext(contextToken, this as unknown as ContextType); + this.provideContext(contextToken, this as any); } } diff --git a/src/Umbraco.Web.UI.Client/src/libs/class-api/context.interface.ts b/src/Umbraco.Web.UI.Client/src/libs/class-api/context.interface.ts index 66ae6e623eb4..17457241b6de 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/class-api/context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/class-api/context.interface.ts @@ -1,4 +1,6 @@ import type { UmbController } from '@umbraco-cms/backoffice/controller-api'; // eslint-disable-next-line @typescript-eslint/no-empty-object-type -export interface UmbContext extends UmbController {} +export interface UmbContext extends UmbController { + getHostElement(): Element; +} 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 573cb5aaddd3..0173ed09d5f3 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 @@ -1,9 +1,13 @@ import type { UmbContextToken } from '../token/context-token.js'; +import type { UmbContextMinimal } from '../types.js'; import { UmbContextConsumer } from './context-consumer.js'; import type { UmbContextCallback } from './context-request.event.js'; import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api'; -export class UmbContextConsumerController +export class UmbContextConsumerController< + BaseType extends UmbContextMinimal = UmbContextMinimal, + ResultType extends BaseType = BaseType, + > extends UmbContextConsumer implements UmbController { diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts index bd3115eab302..11a35bd31e24 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts @@ -1,9 +1,10 @@ import { UmbContextProvider } from '../provide/context-provider.js'; import { UmbContextToken } from '../token/context-token.js'; +import type { UmbContextMinimal } from '../types.js'; import { UmbContextConsumer } from './context-consumer.js'; import type { UmbContextRequestEventImplementation } from './context-request.event.js'; import { UMB_CONTEXT_REQUEST_EVENT_TYPE } from './context-request.event.js'; -import { expect, oneEvent } from '@open-wc/testing'; +import { assert, expect, oneEvent } from '@open-wc/testing'; const testContextAlias = 'my-test-context'; const testContextAliasAndApiAlias = 'my-test-context#testApi'; @@ -11,10 +12,16 @@ const testContextAliasAndNotExistingApiAlias = 'my-test-context#notExistingTestA class UmbTestContextConsumerClass { public prop: string = 'value from provider'; + getHostElement() { + return document.body; + } } class UmbTestAlternativeContextConsumerClass { public alternativeProp: string = 'value from alternative provider'; + getHostElement() { + return document.body; + } } describe('UmbContextConsumer', () => { @@ -180,7 +187,7 @@ describe('UmbContextConsumer', () => { }); it('works with host method returning undefined', async () => { - const notExistingElement = undefined; + const notExistingElement = undefined as unknown as Element; const localConsumer = new UmbContextConsumer( () => notExistingElement, @@ -198,8 +205,6 @@ describe('UmbContextConsumer', () => { localConsumer.hostDisconnected(); }); - /* - Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure. it('acts to Context API disconnected', (done) => { const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); provider.hostConnected(); @@ -222,11 +227,10 @@ describe('UmbContextConsumer', () => { expect(_instance?.prop).to.be.undefined; done(); } - } + }, ); localConsumer.hostConnected(); }); - */ }); describe('Implementation with Api Alias', () => { @@ -270,8 +274,16 @@ describe('UmbContextConsumer', () => { ); provider.hostConnected(); - const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExistingApiAlias, () => { - expect(false).to.be.true; + let callbackCount = 0; + + const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExistingApiAlias, (context) => { + callbackCount++; + if (callbackCount === 1) { + expect(context).to.be.undefined; + done(); + } else { + assert.fail('Callback should not be called more than once'); + } }); localConsumer.hostConnected(); @@ -279,7 +291,6 @@ describe('UmbContextConsumer', () => { Promise.resolve().then(() => { localConsumer.hostDisconnected(); provider.hostDisconnected(); - done(); }); }); }); @@ -294,7 +305,9 @@ describe('UmbContextConsumer', () => { document.body.removeChild(element); }); - type A = { prop: string }; + interface A extends UmbContextMinimal { + prop: string; + } function discriminator(instance: unknown): instance is A { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -309,14 +322,19 @@ describe('UmbContextConsumer', () => { it('discriminator determines the instance type', (done) => { const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, new UmbContextToken(testContextAlias, undefined, discriminator), - (instance: A) => { - expect(instance.prop).to.eq('value from provider'); - provider.destroy(); - localConsumer.destroy(); - done(); + (instance: A | undefined) => { + callbackCount++; + if (callbackCount === 1) { + expect(instance?.prop).to.eq('value from provider'); + provider.destroy(); + localConsumer.destroy(); + done(); + } }, ); localConsumer.hostConnected(); @@ -332,14 +350,19 @@ describe('UmbContextConsumer', () => { const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); provider.hostConnected(); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, new UmbContextToken(testContextAlias, undefined, discriminator), (_instance) => { - expect(_instance.prop).to.eq('value from provider'); - localConsumer.hostDisconnected(); - provider.hostDisconnected(); - done(); + callbackCount++; + if (callbackCount === 1) { + expect(_instance?.prop).to.eq('value from provider'); + localConsumer.hostDisconnected(); + provider.hostDisconnected(); + done(); + } }, ); localConsumer.hostConnected(); @@ -349,11 +372,19 @@ describe('UmbContextConsumer', () => { const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); provider.hostConnected(); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, new UmbContextToken(testContextAlias, undefined, badDiscriminator), (_instance) => { - expect(_instance.prop).to.eq('this must not happen!'); + callbackCount++; + if (callbackCount === 1) { + expect(_instance).to.be.undefined; + done(); + } else { + assert.fail('Callback should not be called more than once'); + } }, ); localConsumer.hostConnected(); @@ -362,7 +393,6 @@ describe('UmbContextConsumer', () => { Promise.resolve().then(() => { localConsumer.hostDisconnected(); provider.hostDisconnected(); - done(); }); }); @@ -377,11 +407,17 @@ describe('UmbContextConsumer', () => { ); alternativeProvider.hostConnected(); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, new UmbContextToken(testContextAlias, undefined, discriminator), (_instance) => { - expect(_instance.prop).to.eq('this must not happen!'); + callbackCount++; + if (callbackCount === 1) { + expect(_instance).to.be.undefined; + done(); + } }, ); localConsumer.hostConnected(); @@ -390,7 +426,6 @@ describe('UmbContextConsumer', () => { Promise.resolve().then(() => { localConsumer.hostDisconnected(); provider.hostDisconnected(); - done(); }); }); @@ -405,14 +440,21 @@ describe('UmbContextConsumer', () => { ); alternativeProvider.hostConnected(); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, new UmbContextToken(testContextAlias, undefined, discriminator), (_instance) => { - expect(_instance.prop).to.eq('value from provider'); - localConsumer.hostDisconnected(); - provider.hostDisconnected(); - done(); + callbackCount++; + if (callbackCount === 1) { + expect(_instance?.prop).to.eq('value from provider'); + localConsumer.hostDisconnected(); + provider.hostDisconnected(); + } else { + expect(_instance).to.be.undefined; + done(); + } }, ); localConsumer.passContextAliasMatches(); 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 1f3682098e40..5334cc6a222a 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 @@ -1,9 +1,15 @@ import type { UmbContextDiscriminator, UmbContextToken } from '../token/context-token.js'; -import { isUmbContextProvideEventType, UMB_CONTEXT_PROVIDE_EVENT_TYPE } from '../provide/context-provide.event.js'; +import { + isUmbContextProvideEventType, + isUmbContextUnprovidedEventType, + UMB_CONTEXT_PROVIDE_EVENT_TYPE, + UMB_CONTEXT_UNPROVIDED_EVENT_TYPE, +} from '../provide/context-provide.event.js'; +import type { UmbContextMinimal } from '../types.js'; import type { UmbContextCallback } from './context-request.event.js'; import { UmbContextRequestEventImplementation } from './context-request.event.js'; -type HostElementMethod = () => Element | undefined; +type HostElementMethod = () => Element; export type UmbContextConsumerAsPromiseOptionsType = { preventTimeout?: boolean; @@ -15,7 +21,10 @@ export type UmbContextConsumerAsPromiseOptionsType = { * Notice it is not recommended to use this class directly, but rather use the `consumeContext` method from a `UmbElement` or `UmbElementMixin` or `UmbControllerBase` or `UmbClassMixin`. * Alternatively, you can use the `UmbContextConsumerController` to consume a context from a host element. But this does require that you can implement one of the Class Mixins mentioned above. */ -export class UmbContextConsumer { +export class UmbContextConsumer< + BaseType extends UmbContextMinimal = UmbContextMinimal, + ResultType extends BaseType = BaseType, +> { protected _retrieveHost: HostElementMethod; #raf?: number; @@ -61,6 +70,10 @@ export class UmbContextConsumer).getDiscriminator?.(); } + getHostElement(): Element { + return this._retrieveHost(); + } + /** * @public * @memberof UmbContextConsumer @@ -108,6 +121,7 @@ export class UmbContextConsumer { this.#instance = instance; + this.#setCurrentTarget(instance.getHostElement()); await this.#callback?.(instance); // Resolve callback first as it might perform something you like completed before resolving the promise, as the promise might be used to determine when things are ready/initiated [NL] this.#resolvePromise(); } @@ -185,13 +199,6 @@ export class UmbContextConsumer 0 && this.#promiseRejecter) { - await new Promise((resolve) => requestAnimationFrame(resolve)); - } - */ - if (this.#promiseResolver && this.#promiseOptions?.preventTimeout !== true) { this.#raf = requestAnimationFrame(() => { // For unproviding, then setInstance to undefined here. [NL] @@ -202,9 +209,7 @@ export class UmbContextConsumer { + #onProvide = (event: Event): void => { // Does seem a bit unnecessary, we could just assume the type via type casting... if (!isUmbContextProvideEventType(event)) return; @@ -239,24 +265,21 @@ export class UmbContextConsumer { + #onUnprovided = (event: Event) => { // Does seem a bit unnecessary, we could just assume the type via type casting... if (!isUmbContextUnprovidedEventType(event)) return; if (this.#contextAlias === event.contextAlias && event.instance === this.#instance) { - this.#unProvide(); + this.#unprovide(); } }; - #unProvide() { + #unprovide() { if (this.#instance !== undefined) { this.#instance = undefined; this.#callback?.(undefined); } } - */ public destroy(): void { this.hostDisconnected(); 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 a2fa4d99753e..b22f4fda8bdd 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 @@ -6,7 +6,7 @@ export const UMB_CONTEXT_REQUEST_EVENT_TYPE = 'umb:context-request'; export const UMB_CONTENT_REQUEST_EVENT_TYPE = UMB_CONTEXT_REQUEST_EVENT_TYPE; export const UMB_DEBUG_CONTEXT_EVENT_TYPE = 'umb:debug-contexts'; -export type UmbContextCallback = (instance: T) => void; +export type UmbContextCallback = (instance: T | undefined) => void; /** * @interface UmbContextRequestEvent diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/index.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/index.ts index 4fa53c1c03dd..ace5237d3da6 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/index.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/index.ts @@ -2,3 +2,4 @@ export * from './consume/index.js'; export * from './debug/context-data.function.js'; export * from './provide/index.js'; export * from './token/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provide.event.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provide.event.ts index 34de1e829ba2..4b56b6bb08f8 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provide.event.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provide.event.ts @@ -39,17 +39,15 @@ export interface UmbContextUnprovidedEvent extends Event { * @augments {Event} * @implements {UmbContextUnprovidedEvent} */ -/* - export class UmbContextUnprovidedEventImplementation extends Event implements UmbContextUnprovidedEvent { - public constructor( - public readonly contextAlias: string | UmbContextToken, - public readonly instance: unknown, - ) { - super(UMB_CONTEXT_UNPROVIDED_EVENT_TYPE, { bubbles: true, composed: true }); - } +export class UmbContextUnprovidedEventImplementation extends Event implements UmbContextUnprovidedEvent { + public constructor( + public readonly contextAlias: string | UmbContextToken, + public readonly instance: unknown, + ) { + super(UMB_CONTEXT_UNPROVIDED_EVENT_TYPE, { bubbles: true, composed: true }); } +} - export const isUmbContextUnprovidedEventType = (event: Event): event is UmbContextUnprovidedEventImplementation => { - return event.type === UMB_CONTEXT_UNPROVIDED_EVENT_TYPE; - }; -*/ +export const isUmbContextUnprovidedEventType = (event: Event): event is UmbContextUnprovidedEventImplementation => { + return event.type === UMB_CONTEXT_UNPROVIDED_EVENT_TYPE; +}; diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.test.ts index a33ae354f0cc..5dea5e6dd42a 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.controller.test.ts @@ -5,6 +5,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; class UmbTestContextProviderControllerClass { prop = 'value from provider'; + getHostElement() { + return undefined as unknown as Element; + } } class UmbTestControllerHostElement extends UmbLitElement {} @@ -39,13 +42,20 @@ describe('UmbContextProviderController', () => { }); it('works with UmbContextConsumer', (done) => { + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, 'my-test-context', (_instance: UmbTestContextProviderControllerClass | undefined) => { - expect(_instance?.prop).to.eq('value from provider'); - done(); - localConsumer.hostDisconnected(); + callbackCount++; + if (callbackCount === 1) { + expect(_instance?.prop).to.eq('value from provider'); + localConsumer.hostDisconnected(); + } else { + expect(_instance).to.be.undefined; + done(); + } }, ); localConsumer.hostConnected(); 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 a1305887490d..7700f6fedc61 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 @@ -1,9 +1,10 @@ import type { UmbContextToken } from '../token/index.js'; +import type { UmbContextMinimal } from '../types.js'; import { UmbContextProvider } from './context-provider.js'; import type { UmbControllerHost, UmbController } from '@umbraco-cms/backoffice/controller-api'; export class UmbContextProviderController< - BaseType = unknown, + BaseType extends UmbContextMinimal = UmbContextMinimal, ResultType extends BaseType = BaseType, InstanceType extends ResultType = ResultType, > diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.test.ts index 045e53546c62..ee19d05e9d99 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.test.ts @@ -4,14 +4,21 @@ import { expect, fixture, html } from '@open-wc/testing'; import { customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controller-api'; +class UmbTestContextProviderControllerClass { + prop = 'value from provider'; + getHostElement() { + return undefined as unknown as Element; + } +} + @customElement('umb-test-context') export class UmbTestContextElement extends UmbControllerHostElementMixin(HTMLElement) { - public value: string | null = null; + public value?: string; constructor() { super(); - new UmbContextConsumerController(this, 'test-context', (value) => { - this.value = value; + new UmbContextConsumerController(this, 'test-context', (context) => { + this.value = context?.prop; }); } } @@ -19,22 +26,27 @@ export class UmbTestContextElement extends UmbControllerHostElementMixin(HTMLEle describe('UmbContextProvider', () => { let element: HTMLElement; let consumer: UmbTestContextElement; - const contextValue = 'test-value'; + let context: UmbTestContextProviderControllerClass; beforeEach(async () => { + const context = new UmbTestContextProviderControllerClass(); element = await fixture( - html` + html` `, ); consumer = element.getElementsByTagName('umb-test-context')[0] as unknown as UmbTestContextElement; }); + afterEach(() => { + element.remove(); + }); + it('is defined with its own instance', () => { expect(element).to.be.instanceOf(UmbContextProviderElement); }); it('provides the context', () => { - expect(consumer.value).to.equal(contextValue); + expect(consumer.value).to.equal('value from provider'); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.ts index 5ac97278bc74..f9e75e040b91 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.element.ts @@ -1,4 +1,5 @@ import type { UmbContextToken } from '../token/index.js'; +import type { UmbContextMinimal } from '../types.js'; import { UmbContextProviderController } from './context-provider.controller.js'; import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controller-api'; @@ -15,13 +16,13 @@ export class UmbContextProviderElement extends UmbControllerHostElementMixin(HTM * The value to provide to the context. * @optional */ - public create?: (host: UmbControllerHostElement) => unknown; + public create?: (host: UmbControllerHostElement) => UmbContextMinimal; /** * The value to provide to the context. * @required */ - public value: unknown; + public value?: UmbContextMinimal; /** * The key to provide to the context. @@ -33,9 +34,12 @@ export class UmbContextProviderElement extends UmbControllerHostElementMixin(HTM return ['value', 'key']; } - attributeChangedCallback(name: string, _oldValue: string | UmbContextToken, newValue: string | UmbContextToken) { - if (name === 'key') this.key = newValue; - if (name === 'value') this.value = newValue; + attributeChangedCallback(name: string, _oldValue: unknown, newValue: unknown) { + if (name === 'key') { + this.key = newValue as string | UmbContextToken; + } else if (name === 'value') { + this.value = newValue as UmbContextMinimal; + } } constructor() { diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts index 31a3bf66458b..71606a508e9f 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts @@ -5,6 +5,9 @@ import { expect } from '@open-wc/testing'; class UmbTestContextProviderClass { prop = 'value from provider'; + getHostElement() { + return undefined as unknown as Element; + } } describe('UmbContextProvider', () => { @@ -51,13 +54,18 @@ describe('UmbContextProvider', () => { const element = document.createElement('div'); document.body.appendChild(element); + let callbackCount = 0; + const localConsumer = new UmbContextConsumer( element, 'my-test-context', (_instance: UmbTestContextProviderClass | undefined) => { - expect(_instance?.prop).to.eq('value from provider'); - done(); - localConsumer.hostDisconnected(); + callbackCount++; + if (callbackCount === 1) { + expect(_instance?.prop).to.eq('value from provider'); + done(); + localConsumer.hostDisconnected(); + } }, ); localConsumer.hostConnected(); 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 9c729080e21f..dd7c44e7cca6 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 @@ -1,12 +1,19 @@ +import type { UmbContextMinimal } from '../types.js'; import type { UmbContextRequestEvent } from '../consume/context-request.event.js'; import type { UmbContextToken } from '../token/index.js'; import { UMB_CONTEXT_REQUEST_EVENT_TYPE, UMB_DEBUG_CONTEXT_EVENT_TYPE } from '../consume/context-request.event.js'; -import { UmbContextProvideEventImplementation } from './context-provide.event.js'; +import { + UmbContextProvideEventImplementation, + UmbContextUnprovidedEventImplementation, +} from './context-provide.event.js'; /** * @class UmbContextProvider */ -export class UmbContextProvider { +export class UmbContextProvider< + BaseType extends UmbContextMinimal = UmbContextMinimal, + ResultType extends BaseType = BaseType, +> { #eventTarget: EventTarget; #contextAlias: string; @@ -58,8 +65,8 @@ export class UmbContextProvider { 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 19c7ddb49d98..2b545ab2a091 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,3 +1,5 @@ +import type { UmbContextMinimal } from '../types.js'; + export type UmbContextDiscriminator = ( instance: BaseType, ) => instance is DiscriminatorResult; @@ -7,7 +9,10 @@ export type UmbContextDiscriminator { +export class UmbContextToken< + BaseType extends UmbContextMinimal = UmbContextMinimal, + ResultType extends BaseType = BaseType, +> { #discriminator: UmbContextDiscriminator | undefined; /** * Get the type of the token diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/types.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/types.ts new file mode 100644 index 000000000000..f8ed61a1817c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/types.ts @@ -0,0 +1,3 @@ +export interface UmbContextMinimal { + getHostElement(): Element; +} diff --git a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts index 34802081e5ee..18ebd9d1764f 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-element.mixin.ts @@ -7,6 +7,7 @@ import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-a * This enables controllers to be added to the life cycle of this element. * @param {object} superClass - superclass to be extended. * @mixin + * @returns {UmbControllerHostElement} - The class that extends the superClass and implements the UmbControllerHostElement interface. */ export const UmbControllerHostElementMixin = (superClass: T) => { class UmbControllerHostElementClass diff --git a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-provider.test.ts b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-provider.test.ts index 67fdb1f9db40..9c54b8f2ece9 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-provider.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/controller-api/controller-host-provider.test.ts @@ -5,28 +5,39 @@ import { expect, fixture, html } from '@open-wc/testing'; import { customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbContextConsumerController, UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; +class UmbTestContextProviderControllerClass { + prop = 'value from provider'; + getHostElement() { + return undefined as unknown as Element; + } +} + @customElement('umb-test-controller-host-initializer-consumer') export class UmbTestControllerHostInitializerConsumerElement extends UmbControllerHostElementMixin(HTMLElement) { - public value: string | null = null; + public value?: string; constructor() { super(); - new UmbContextConsumerController(this, 'my-test-context-alias', (value) => { - this.value = value; - }); + new UmbContextConsumerController( + this, + 'my-test-context-alias', + (context) => { + this.value = context?.prop; + }, + ); } } describe('UmbControllerHostTestElement', () => { let element: UmbControllerHostProviderElement; let consumer: UmbTestControllerHostInitializerConsumerElement; - const contextValue = 'test-value'; beforeEach(async () => { element = await fixture( html` - new UmbContextProviderController(host, 'my-test-context-alias', contextValue)}> + .create=${(host: UmbControllerHostElement): void => { + new UmbContextProviderController(host, 'my-test-context-alias', new UmbTestContextProviderControllerClass()); + }}> `, ); @@ -44,6 +55,6 @@ describe('UmbControllerHostTestElement', () => { // Potentially we need to wait a bit here, cause the value might not be set already? as of the context consumption... expect(consumer).to.be.instanceOf(UmbTestControllerHostInitializerConsumerElement); expect(consumer.value).to.not.be.null; - expect(consumer.value).to.equal(contextValue); + expect(consumer.value).to.equal('value from provider'); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts index 9297bb7f9921..3859b30a0d70 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/element-api/element.mixin.ts @@ -3,7 +3,7 @@ import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization- import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { HTMLElementConstructor } from '@umbraco-cms/backoffice/extension-api'; import { type UmbControllerAlias, UmbControllerHostElementMixin } from '@umbraco-cms/backoffice/controller-api'; -import type { UmbContextToken, UmbContextCallback } from '@umbraco-cms/backoffice/context-api'; +import type { UmbContextToken, UmbContextCallback, UmbContextMinimal } from '@umbraco-cms/backoffice/context-api'; import { UmbContextConsumerController, UmbContextProviderController } from '@umbraco-cms/backoffice/context-api'; import type { ObserverCallback } from '@umbraco-cms/backoffice/observable-api'; import { UmbObserverController, simpleHashCode } from '@umbraco-cms/backoffice/observable-api'; @@ -56,7 +56,7 @@ export const UmbElementMixin = (superClass: T) } provideContext< - BaseType = unknown, + BaseType extends UmbContextMinimal = UmbContextMinimal, ResultType extends BaseType = BaseType, InstanceType extends ResultType = ResultType, >( @@ -66,14 +66,14 @@ export const UmbElementMixin = (superClass: T) return new UmbContextProviderController(this, alias, instance); } - consumeContext( + consumeContext( alias: string | UmbContextToken, callback: UmbContextCallback, ): UmbContextConsumerController { return new UmbContextConsumerController(this, alias, callback); } - async getContext( + async getContext( contextAlias: string | UmbContextToken, options?: UmbClassGetContextOptions, ): Promise { diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/condition/condition-controller-arguments.type.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/condition/condition-controller-arguments.type.ts index 795b1e490754..78b92618f2bb 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/condition/condition-controller-arguments.type.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/condition/condition-controller-arguments.type.ts @@ -3,7 +3,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; export type UmbConditionControllerArguments< ConditionConfigType extends UmbConditionConfigBase = UmbConditionConfigBase, - ConditionOnChangeCallbackType = () => void, + ConditionOnChangeCallbackType = (permitted: boolean) => void, > = { host: UmbControllerHost; config: ConditionConfigType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/block-grid-manager/block-grid-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/block-grid-manager/block-grid-manager.context.ts index f46d4058c6fd..4ed978fc1174 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/block-grid-manager/block-grid-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/block-grid-manager/block-grid-manager.context.ts @@ -88,7 +88,7 @@ export class UmbBlockGridManagerContext< super(host); this.#initAppUrl = this.consumeContext(UMB_SERVER_CONTEXT, (instance) => { - this.#serverUrl = instance.getServerUrl(); + this.#serverUrl = instance?.getServerUrl(); }).asPromise({ preventTimeout: true }); } /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.context.ts index dca1a8bb0490..597b6b36f0d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.context.ts @@ -10,10 +10,7 @@ import { UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/obs import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; -export class UmbBlockGridAreaConfigEntryContext - extends UmbContextBase - implements UmbBlockGridScalableContext -{ +export class UmbBlockGridAreaConfigEntryContext extends UmbContextBase implements UmbBlockGridScalableContext { // #entriesContext?: typeof UMB_BLOCK_GRID_AREA_TYPE_ENTRIES_CONTEXT.TYPE; // diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts index 0a773ae41eb4..7383ed3f5e5c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts @@ -15,7 +15,7 @@ export class UmbBlockGridAreaTypeWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; - this.observe(this.#workspaceContext.name, (name) => { + this.observe(this.#workspaceContext?.name, (name) => { this._name = name; }); this.#workspaceContext?.createPropertyDatasetContext(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts index 9cb21959c37e..fd4f1cdb5013 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts @@ -82,7 +82,7 @@ export class UmbBlockGridAreaTypeWorkspaceContext this.resetState(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { this.observe( - context.value, + context?.value, (value) => { if (value) { const blockTypeData = value.find((x: UmbBlockGridTypeAreaType) => x.key === unique); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/settings.element.ts index e77af60a5e9a..a29ce7fc8907 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/views/settings.element.ts @@ -22,12 +22,20 @@ export class UmbBlockGridAreaTypeWorkspaceViewSettingsElement extends UmbLitElem super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { this.#dataset = context; - this.observe(await this.#dataset.propertyValueByAlias('minAllowed'), (min) => { - this._minValue = min ?? 0; - }); - this.observe(await this.#dataset.propertyValueByAlias('maxAllowed'), (max) => { - this._maxValue = max ?? Infinity; - }); + this.observe( + await this.#dataset?.propertyValueByAlias('minAllowed'), + (min) => { + this._minValue = min ?? 0; + }, + 'observeMinAllowed', + ); + this.observe( + await this.#dataset?.propertyValueByAlias('maxAllowed'), + (max) => { + this._maxValue = max ?? Infinity; + }, + 'observeMaxAllowed', + ); }); } #onAllowedRangeChange = (e: UmbChangeEvent) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area/block-grid-area.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area/block-grid-area.element.ts index a0087d9d2081..32d11d3af58c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area/block-grid-area.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area/block-grid-area.element.ts @@ -14,7 +14,7 @@ export class UmbBlockGridAreasContainerElement extends UmbBlockGridEntriesElemen this.consumeContext(UMB_BLOCK_GRID_ENTRIES_CONTEXT, (context) => { this.observe( - context.layoutColumns, + context?.layoutColumns, (layoutColumns) => { this.layoutColumns = layoutColumns; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts index c99c89e15712..d38ee79c25d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts @@ -25,14 +25,14 @@ export class UmbBlockGridAreasContainerElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_GRID_ENTRY_CONTEXT, (context) => { this.observe( - context.areas, + context?.areas, (areas) => { this._areas = areas; }, 'observeAreas', ); this.observe( - context.areaGridColumns, + context?.areaGridColumns, (areaGridColumns) => { this._areaGridColumns = areaGridColumns; //this.requestUpdate('_areaGridColumns'); @@ -42,7 +42,7 @@ export class UmbBlockGridAreasContainerElement extends UmbLitElement { }); this.consumeContext(UMB_BLOCK_GRID_MANAGER_CONTEXT, (manager) => { this.observe( - manager.layoutStylesheet, + manager?.layoutStylesheet, (stylesheet) => { // Do not re-render stylesheet if its the same href. if (!stylesheet || this._styleElement?.href === stylesheet) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index ba4745337a40..c8a4d24f14c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -68,7 +68,7 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_GRID_ENTRY_CONTEXT, (blockContext) => { this.#blockContext = blockContext; this.observe( - this.#blockContext.unique, + this.#blockContext?.unique, (contentKey) => { this.#contentKey = contentKey; this.#load(); @@ -77,8 +77,8 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { ); }); this.consumeContext(UMB_BLOCK_GRID_ENTRIES_CONTEXT, (entriesContext) => { - this.#parentUnique = entriesContext.getParentUnique(); - this.#areaKey = entriesContext.getAreaKey(); + this.#parentUnique = entriesContext?.getParentUnique(); + this.#areaKey = entriesContext?.getAreaKey(); }); new UmbExtensionApiInitializer( this, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts index 62c9e7408c7b..4db70b0ef44f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts @@ -59,15 +59,15 @@ export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias>('blocks'), + await context?.propertyValueByAlias>('blocks'), (blockTypes) => { this._blockTypes = blockTypes ?? []; - this.#itemsManager.setUniques(blockTypes.map((block) => block.contentElementTypeKey)); + this.#itemsManager.setUniques(this._blockTypes.map((block) => block.contentElementTypeKey)); }, 'observeBlockType', ); this.observe( - await context.propertyValueByAlias>('blockGroups'), + await context?.propertyValueByAlias>('blockGroups'), (blockGroups) => { this._blockGroups = blockGroups ?? []; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/block-grid-area-type-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/block-grid-area-type-entries.context.ts index e576586509dd..2922f3bdbd9a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/block-grid-area-type-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/block-grid-area-type-entries.context.ts @@ -3,10 +3,7 @@ import { UMB_BLOCK_GRID_AREA_TYPE_ENTRIES_CONTEXT } from './block-grid-area-type import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbBlockGridAreaTypeEntriesContext - extends UmbContextBase - implements UmbBlockGridScalableContainerContext -{ +export class UmbBlockGridAreaTypeEntriesContext extends UmbContextBase implements UmbBlockGridScalableContainerContext { #layoutColumns?: number; setLayoutColumns(layoutColumns: number) { this.#layoutColumns = layoutColumns; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts index 93d2fd7b05b4..78e52ed1476c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts @@ -77,7 +77,7 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias('areaGridColumns'), + await context?.propertyValueByAlias('areaGridColumns'), (value) => { // Value can be undefined, but 'undefined > 0' is still valid JS and will return false. [NL] this.#valueOfAreaGridColumns = (value as number) > 0 ? value : null; @@ -87,7 +87,7 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement ); this.observe( - await context.propertyValueByAlias('layoutStylesheet'), + await context?.propertyValueByAlias('layoutStylesheet'), (stylesheet) => { if (this._styleElement && this._styleElement.href === stylesheet) return; this._styleElement = document.createElement('link'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts index 06d94b2dd031..2549a7f18489 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts @@ -1,4 +1,5 @@ import { UmbBlockGridManagerContext } from '../../block-grid-manager/index.js'; +import type { UmbBlockGridTypeModel, UmbBlockGridValueModel } from '../../types.js'; import { UMB_BLOCK_GRID_PROPERTY_EDITOR_SCHEMA_ALIAS } from './constants.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { @@ -25,7 +26,6 @@ import { debounceTime } from '@umbraco-cms/backoffice/external/rxjs'; // TODO: consider moving the components to the property editor folder as they are only used here import '../../local-components.js'; import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; -import type { UmbBlockGridTypeModel, UmbBlockGridValueModel } from '../../types.js'; /** * @element umb-property-editor-ui-block-grid @@ -113,47 +113,52 @@ export class UmbPropertyEditorUIBlockGridElement super(); this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { - this.observe( - observeMultiple([ - this.#managerContext.blockTypes, - context.structure.variesByCulture, - context.structure.variesBySegment, - ]), - async ([blockTypes, variesByCulture, variesBySegment]) => { - if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { - // check if any of the Blocks varyByCulture or Segment and then display a warning. - const promises = await Promise.all( - blockTypes.map(async (blockType) => { - const elementType = blockType.contentElementTypeKey; - await this.#managerContext.contentTypesLoaded; - const structure = await this.#managerContext.getStructure(elementType); - if (variesByCulture === false && structure?.getVariesByCulture() === true) { - // If block varies by culture but document does not. - return true; - } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { - // If block varies by segment but document does not. - return true; - } - return false; - }), - ); - this._notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; - - if (this._notSupportedVariantSetting) { - this.#validationContext.messages.addMessage( - 'config', - '$', - '#blockEditor_blockVariantConfigurationNotSupported', + if (context) { + this.observe( + observeMultiple([ + this.#managerContext.blockTypes, + context.structure.variesByCulture, + context.structure.variesBySegment, + ]), + async ([blockTypes, variesByCulture, variesBySegment]) => { + if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { + // check if any of the Blocks varyByCulture or Segment and then display a warning. + const promises = await Promise.all( + blockTypes.map(async (blockType) => { + const elementType = blockType.contentElementTypeKey; + await this.#managerContext.contentTypesLoaded; + const structure = await this.#managerContext.getStructure(elementType); + if (variesByCulture === false && structure?.getVariesByCulture() === true) { + // If block varies by culture but document does not. + return true; + } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { + // If block varies by segment but document does not. + return true; + } + return false; + }), ); + this._notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; + + if (this._notSupportedVariantSetting) { + this.#validationContext.messages.addMessage( + 'config', + '$', + '#blockEditor_blockVariantConfigurationNotSupported', + ); + } } - } - }, - ); + }, + 'observeBlockTypes', + ); + } else { + this.removeUmbControllerByAlias('observeBlockTypes'); + } }).passContextAliasMatches(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { this.observe( - context.dataPath, + context?.dataPath, (dataPath) => { if (dataPath) { // Set the data path for the local validation context: @@ -193,7 +198,7 @@ export class UmbPropertyEditorUIBlockGridElement return; } - propertyContext.setValue(super.value); + propertyContext?.setValue(super.value); }, 'motherObserver', ); @@ -208,7 +213,7 @@ export class UmbPropertyEditorUIBlockGridElement }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => { - this.#managerContext.setVariantId(context.getVariantId()); + this.#managerContext.setVariantId(context?.getVariantId()); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts index 0955813e9411..883aa25d7846 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.element.ts @@ -96,13 +96,13 @@ export class UmbPropertyEditorUIBlockGridTypeConfigurationElement super(); this.consumeContext(UMB_PROPERTY_CONTEXT, async (context) => { - this._alias = context.getAlias(); + this._alias = context?.getAlias(); }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { this.#datasetContext = context; this.observe( - await this.#datasetContext.propertyValueByAlias('blockGroups'), + await this.#datasetContext?.propertyValueByAlias('blockGroups'), (value) => { this.#blockGroups = (value as Array) ?? []; this.#mapValuesToBlockGroups(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-areas.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-areas.element.ts index b8c5f11fcc3e..d0ecf50f9781 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-areas.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-areas.element.ts @@ -19,7 +19,7 @@ export class UmbBlockGridTypeWorkspaceViewAreasElement extends UmbLitElement imp this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias('gridColumns'), + await context?.propertyValueByAlias('gridColumns'), (value) => { const dataTypeGridColumns = value ? parseInt(value, 10) : 12; this._areaColumnsConfigurationObject = [{ alias: 'placeholder', value: dataTypeGridColumns }]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-settings.element.ts index d02fec7982ac..bd6d2644a644 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/views/block-grid-type-workspace-view-settings.element.ts @@ -29,7 +29,7 @@ export class UmbBlockGridTypeWorkspaceViewSettingsElement extends UmbLitElement this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias('gridColumns'), + await context?.propertyValueByAlias('gridColumns'), (value) => { this._dataTypeGridColumns = value ? parseInt(value, 10) : undefined; }, @@ -43,7 +43,7 @@ export class UmbBlockGridTypeWorkspaceViewSettingsElement extends UmbLitElement // TODO set showSizeOption to true when rowMinSpan or rowMaxSpan is set this.observe( - await context.propertyValueByAlias('columnSpanOptions'), + await context?.propertyValueByAlias('columnSpanOptions'), (value) => { if (Array.isArray(value) && value.length > 0) { this._showSizeOptions = true; @@ -54,7 +54,7 @@ export class UmbBlockGridTypeWorkspaceViewSettingsElement extends UmbLitElement ); this.observe( - await context.propertyValueByAlias('rowMinSpan'), + await context?.propertyValueByAlias('rowMinSpan'), (value) => { this._rowMinSpan = value; }, @@ -62,7 +62,7 @@ export class UmbBlockGridTypeWorkspaceViewSettingsElement extends UmbLitElement ); this.observe( - await context.propertyValueByAlias('rowMaxSpan'), + await context?.propertyValueByAlias('rowMaxSpan'), (value) => { this._rowMaxSpan = value; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts index ebccf9b775ea..d15e7cf852a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts @@ -60,7 +60,7 @@ export class UmbInlineListBlockElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_LIST_ENTRY_CONTEXT, (blockContext) => { this.#blockContext = blockContext; this.observe( - this.#blockContext.unique, + this.#blockContext?.unique, (contentKey) => { this.#contentKey = contentKey; this.#load(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index f905bb8f4251..e8b4b4ed8d36 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -168,43 +168,48 @@ export class UmbPropertyEditorUIBlockListElement super(); this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { - this.observe( - observeMultiple([ - this.#managerContext.blockTypes, - context.structure.variesByCulture, - context.structure.variesBySegment, - ]), - async ([blockTypes, variesByCulture, variesBySegment]) => { - if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { - // check if any of the Blocks varyByCulture or Segment and then display a warning. - const promises = await Promise.all( - blockTypes.map(async (blockType) => { - const elementType = blockType.contentElementTypeKey; - await this.#managerContext.contentTypesLoaded; - const structure = await this.#managerContext.getStructure(elementType); - if (variesByCulture === false && structure?.getVariesByCulture() === true) { - // If block varies by culture but document does not. - return true; - } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { - // If block varies by segment but document does not. - return true; - } - return false; - }), - ); - this._notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; - - if (this._notSupportedVariantSetting) { - this.#validationContext.messages.addMessage( - 'config', - '$', - '#blockEditor_blockVariantConfigurationNotSupported', - 'blockConfigurationNotSupported', + if (context) { + this.observe( + observeMultiple([ + this.#managerContext.blockTypes, + context.structure.variesByCulture, + context.structure.variesBySegment, + ]), + async ([blockTypes, variesByCulture, variesBySegment]) => { + if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { + // check if any of the Blocks varyByCulture or Segment and then display a warning. + const promises = await Promise.all( + blockTypes.map(async (blockType) => { + const elementType = blockType.contentElementTypeKey; + await this.#managerContext.contentTypesLoaded; + const structure = await this.#managerContext.getStructure(elementType); + if (variesByCulture === false && structure?.getVariesByCulture() === true) { + // If block varies by culture but document does not. + return true; + } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { + // If block varies by segment but document does not. + return true; + } + return false; + }), ); + this._notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; + + if (this._notSupportedVariantSetting) { + this.#validationContext.messages.addMessage( + 'config', + '$', + '#blockEditor_blockVariantConfigurationNotSupported', + 'blockConfigurationNotSupported', + ); + } } - } - }, - ); + }, + 'blockTypeConfigurationCheck', + ); + } else { + this.removeUmbControllerByAlias('blockTypeConfigurationCheck'); + } }).passContextAliasMatches(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { @@ -241,7 +246,7 @@ export class UmbPropertyEditorUIBlockListElement ); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { - this.#managerContext.setVariantId(context.getVariantId()); + this.#managerContext.setVariantId(context?.getVariantId()); }); this.addValidator( @@ -301,9 +306,9 @@ export class UmbPropertyEditorUIBlockListElement ); } - #gotPropertyContext(context: typeof UMB_PROPERTY_CONTEXT.TYPE) { + #gotPropertyContext(context: typeof UMB_PROPERTY_CONTEXT.TYPE | undefined) { this.observe( - context.dataPath, + context?.dataPath, (dataPath) => { if (dataPath) { // Set the data path for the local validation context: @@ -348,7 +353,7 @@ export class UmbPropertyEditorUIBlockListElement return; } - context.setValue(super.value); + context?.setValue(super.value); }, 'motherObserver', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts index a95c3b3030bb..183fb365dfd9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts @@ -28,7 +28,7 @@ export class UmbRefRteBlockElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_ENTRY_CONTEXT, (context) => { this.observe( - context.workspaceEditContentPath, + context?.workspaceEditContentPath, (workspaceEditPath) => { this._workspaceEditPath = workspaceEditPath; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts index ce2a4b906cd1..d97744471b0d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-card/block-type-card.element.ts @@ -77,7 +77,7 @@ export class UmbBlockTypeCardElement extends UmbLitElement { super(); this.#init = this.consumeContext(UMB_SERVER_CONTEXT, (instance) => { - this.#serverUrl = instance.getServerUrl(); + this.#serverUrl = instance?.getServerUrl() ?? ''; }).asPromise({ preventTimeout: true }); this.observe(this.#itemManager.statuses, async (statuses) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index 5d54f25b417c..40cc20ba8c28 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -34,7 +34,7 @@ export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias('contentElementTypeKey'), + await context?.propertyValueByAlias('contentElementTypeKey'), async (value) => { if (!value) return; const { asObservable } = await this.#repository.requestByUnique(value); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace-editor.element.ts index 05d2407e78b5..1bbecd25353a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace-editor.element.ts @@ -21,7 +21,7 @@ export class UmbBlockTypeWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_TYPE_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; this.#workspaceContext?.createPropertyDatasetContext(this); - this.observe(this.#workspaceContext.unique, (unique) => { + this.observe(this.#workspaceContext?.unique, (unique) => { if (unique) { this.#itemManager.setUniques([unique]); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-entry-show-content-edit.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-entry-show-content-edit.condition.ts index 31168a794484..c639cf8c8f1c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-entry-show-content-edit.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-entry-show-content-edit.condition.ts @@ -4,6 +4,7 @@ import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +const ObserveSymbol = Symbol(); export class UmbBlockEntryShowContentEditCondition extends UmbConditionBase implements UmbExtensionCondition @@ -16,11 +17,11 @@ export class UmbBlockEntryShowContentEditCondition this.consumeContext(UMB_BLOCK_ENTRY_CONTEXT, (context) => { this.observe( - context.showContentEdit, + context?.showContentEdit, (showContentEdit) => { this.permitted = !!showContentEdit; }, - 'observeEntryShowContentEdit', + ObserveSymbol, ); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts index d5d495203d5c..176afd3e1d34 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts @@ -16,7 +16,7 @@ export class UmbBlockWorkspaceHasSettingsCondition this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => { this.observe( - context.settings.contentTypeId, + context?.settings.contentTypeId, (settingsContentTypeId) => { this.permitted = settingsContentTypeId !== undefined; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-is-exposed.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-is-exposed.condition.ts index 685a93399472..275eb6e79631 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-is-exposed.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-is-exposed.condition.ts @@ -13,7 +13,7 @@ export class UmbBlockEntryIsExposedCondition this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => { this.observe( - context.exposed, + context?.exposed, (exposed) => { if (exposed !== undefined) { // Check if equal to match, if match not set it defaults to true. diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts index 5d959e088a1c..c3892ab1e8f8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts @@ -15,15 +15,7 @@ export abstract class UmbBlockEntriesContext< BlockType extends UmbBlockTypeBaseModel, BlockLayoutType extends UmbBlockLayoutBaseModel, BlockOriginData extends UmbBlockWorkspaceOriginData, -> extends UmbContextBase< - UmbBlockEntriesContext< - BlockManagerContextTokenType, - BlockManagerContextType, - BlockType, - BlockLayoutType, - BlockOriginData - > -> { +> extends UmbContextBase { // _manager?: BlockManagerContextType; _retrieveManager; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index 8ecb1ab0bb2b..f12767755e09 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -47,7 +47,7 @@ export abstract class UmbBlockEntryContext< BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, BlockLayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, BlockOriginData extends UmbBlockWorkspaceOriginData = UmbBlockWorkspaceOriginData, -> extends UmbContextBase { +> extends UmbContextBase { // _manager?: BlockManagerContextType; _entries?: BlockEntriesContextType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index 8da44ce1e76c..a54d1190c416 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -35,7 +35,7 @@ export abstract class UmbBlockManagerContext< BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, BlockLayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, BlockOriginDataType extends UmbBlockWorkspaceOriginData = UmbBlockWorkspaceOriginData, -> extends UmbContextBase { +> extends UmbContextBase { get contentTypesLoaded() { return Promise.all(this.#contentTypeRequests); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts index 8c73456e4320..92e8cc60baa5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.element.ts @@ -36,7 +36,7 @@ export class UmbBlockCatalogueModalElement extends UmbModalBaseElement< super(); this.consumeContext(UMB_MODAL_CONTEXT, (modalContext) => { - if (modalContext.data.createBlockInWorkspace) { + if (modalContext?.data.createBlockInWorkspace) { new UmbModalRouteRegistrationController(this, UMB_BLOCK_WORKSPACE_MODAL) //.addAdditionalPath('block') // No need for additional path specification in this context as this is for sure the only workspace we want to open here. .onSetup(() => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts index 0476624a8f0e..4727d3a028e9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-element-property-dataset.context.ts @@ -27,9 +27,9 @@ export class UmbBlockElementPropertyDatasetContext this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspace) => { this.observe( - workspace.readOnlyGuard.isPermittedForVariant(elementManager.getVariantId()), + workspace?.readOnlyGuard.isPermittedForVariant(elementManager.getVariantId()), (isReadOnly) => { - this._readOnly.setValue(isReadOnly); + this._readOnly.setValue(isReadOnly ?? false); }, 'umbObserveReadOnlyStates', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace-editor.element.ts index 1b93118d2ba4..282755fff584 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace-editor.element.ts @@ -9,17 +9,21 @@ export class UmbBlockWorkspaceEditorElement extends UmbLitElement { constructor() { super(); this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => { - this.observe( - observeMultiple([ - context.isNew, - context.content.structure.ownerContentTypeObservablePart((contentType) => contentType?.name), - ]), - ([isNew, name]) => { - this._headline = - this.localize.term(isNew ? 'general_add' : 'general_edit') + ' ' + this.localize.string(name); - }, - 'observeOwnerContentElementTypeName', - ); + if (context) { + this.observe( + observeMultiple([ + context.isNew, + context.content.structure.ownerContentTypeObservablePart((contentType) => contentType?.name), + ]), + ([isNew, name]) => { + this._headline = + this.localize.term(isNew ? 'general_add' : 'general_edit') + ' ' + this.localize.string(name); + }, + 'observeOwnerContentElementTypeName', + ); + } else { + this.removeUmbControllerByAlias('observeOwnerContentElementTypeName'); + } }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 72a008cb2af0..cce733ccf951 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -86,7 +86,7 @@ export class UmbBlockWorkspaceContext { this.#modalContext = context; this.#originData = context?.data.originData; - context.onSubmit().catch(this.#modalRejected); + context?.onSubmit().catch(this.#modalRejected); }).asPromise({ preventTimeout: true }); this.#retrieveBlockManager = this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (manager) => { @@ -99,7 +99,7 @@ export class UmbBlockWorkspaceContext { - this.#name.setValue(context.getName()); + this.#name.setValue(context?.getName()); }); this.observe(this.variantId, (variantId) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts index 652400020c25..e35d81977188 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-content-no-router.element.ts @@ -45,7 +45,7 @@ export class UmbBlockWorkspaceViewEditContentNoRouterElement extends UmbLitEleme this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => { this.#blockWorkspace = context; - this.#tabsStructureHelper.setStructureManager(context.content.structure); + this.#tabsStructureHelper.setStructureManager(context?.content.structure); this.#observeRootGroups(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index 4afecc7639f9..801babf6520e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -1,4 +1,5 @@ import type { UmbBlockWorkspaceElementManagerNames } from '../../block-workspace.context.js'; +import type UmbBlockElementManager from '../../block-element-manager.js'; import { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../block-workspace.context-token.js'; import { css, html, customElement, property, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -8,7 +9,6 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import './block-workspace-view-edit-property.element.js'; -import type UmbBlockElementManager from '../../block-element-manager.js'; @customElement('umb-block-workspace-view-edit-properties') export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { @@ -52,9 +52,9 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { this.#workspaceContext = workspaceContext; - this._ownerEntityType = this.#workspaceContext.getEntityType(); + this._ownerEntityType = this.#workspaceContext?.getEntityType(); this.observe( - workspaceContext.variantId, + workspaceContext?.variantId, (variantId) => { this._variantId = variantId; this.#processPropertyStructure(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/clipboard/context/clipboard.context.ts b/src/Umbraco.Web.UI.Client/src/packages/clipboard/context/clipboard.context.ts index dc7b1de71919..8df034787f74 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/clipboard/context/clipboard.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/clipboard/context/clipboard.context.ts @@ -7,9 +7,9 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; * Clipboard context for managing clipboard entries * @export * @class UmbClipboardContext - * @augments {UmbContextBase} + * @augments {UmbContextBase} */ -export class UmbClipboardContext extends UmbContextBase { +export class UmbClipboardContext extends UmbContextBase { #clipboardDetailRepository = new UmbClipboardEntryDetailRepository(this); constructor(host: UmbControllerHost) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/clipboard/property/context/clipboard.property-context.ts b/src/Umbraco.Web.UI.Client/src/packages/clipboard/property/context/clipboard.property-context.ts index d5ce88ce2018..86c63fe6cfef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/clipboard/property/context/clipboard.property-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/clipboard/property/context/clipboard.property-context.ts @@ -22,9 +22,9 @@ import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; * Clipboard context for managing clipboard entries for property values * @export * @class UmbClipboardPropertyContext - * @augments {UmbContextBase} + * @augments {UmbContextBase} */ -export class UmbClipboardPropertyContext extends UmbContextBase { +export class UmbClipboardPropertyContext extends UmbContextBase { #init?: Promise; constructor(host: UmbControllerHost) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.element.ts index 2d90d2abc36a..862464334455 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.element.ts @@ -142,7 +142,7 @@ export class UmbCodeEditorElement extends UmbLitElement implements UmbCodeEditor this.consumeContext(UMB_THEME_CONTEXT, (instance) => { this.observe( - instance.theme, + instance?.theme, (themeAlias) => { this.theme = themeAlias ? this.#translateTheme(themeAlias) : CodeEditorTheme.Light; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts index b21189980d86..532489b6255b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts @@ -30,7 +30,7 @@ export class UmbWorkspaceContentTypeAliasCondition if (permissionCheck !== undefined) { this.consumeContext(UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT, (context) => { this.observe( - context.structure.contentTypeAliases, + context?.structure.contentTypeAliases, (contentTypeAliases) => { this.permitted = contentTypeAliases ? permissionCheck!(contentTypeAliases) : false; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-container-structure-helper.class.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-container-structure-helper.class.ts index 7f98ef7b3735..2dbe7595c0ee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-container-structure-helper.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-container-structure-helper.class.ts @@ -43,9 +43,9 @@ export class UmbContentTypeContainerStructureHelper) { - if (this.#structure === structure) return; - if (this.#structure) { + public setStructureManager(structure: UmbContentTypeStructureManager | undefined) { + if (this.#structure === structure || !structure) return; + if (this.#structure && !structure) { throw new Error( 'Structure manager is already set, the helpers are not designed to be re-setup with new managers', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-property-structure-helper.class.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-property-structure-helper.class.ts index 6ff9acab953c..5a03b13c6ef3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-property-structure-helper.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/structure/content-type-property-structure-helper.class.ts @@ -42,8 +42,8 @@ export class UmbContentTypePropertyStructureHelper) { - if (this.#structure === structure) return; - if (this.#structure) { + if (this.#structure === structure || !structure) return; + if (this.#structure && !structure) { throw new Error( 'Structure manager is already set, the helpers are not designed to be re-setup with new managers', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-properties.element.ts index 22c705d91a39..0f92a8e7a605 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-properties.element.ts @@ -156,7 +156,7 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement { this.consumeContext(UMB_CONTENT_TYPE_DESIGN_EDITOR_CONTEXT, (context) => { this.observe( - context.isSorting, + context?.isSorting, (isSorting) => { this._sortModeActive = isSorting; if (isSorting) { @@ -170,20 +170,22 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement { }); this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, async (workspaceContext) => { - this.#propertyStructureHelper.setStructureManager(workspaceContext.structure); + if (workspaceContext) { + this.#propertyStructureHelper.setStructureManager(workspaceContext.structure); + } - this._ownerContentTypeUnique = workspaceContext.structure.getOwnerContentTypeUnique(); + this._ownerContentTypeUnique = workspaceContext?.structure.getOwnerContentTypeUnique(); this.createPropertyTypeWorkspaceRoutes(); this.observe( - workspaceContext.variesByCulture, + workspaceContext?.variesByCulture, (variesByCulture) => { this._ownerContentTypeVariesByCulture = variesByCulture; }, 'observeOwnerVariesByCulture', ); this.observe( - workspaceContext.variesBySegment, + workspaceContext?.variesBySegment, (variesBySegment) => { this._ownerContentTypeVariesBySegment = variesBySegment; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-property.context.ts index c4f88beef996..ed20f04f701f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-property.context.ts @@ -3,7 +3,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbPropertyTypeContext extends UmbContextBase { +export class UmbPropertyTypeContext extends UmbContextBase { #alias = new UmbStringState(undefined); public readonly alias = this.#alias.asObservable(); #label = new UmbStringState(undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-tab.element.ts index 73a923bd4aae..7494c47cf688 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor-tab.element.ts @@ -110,13 +110,13 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement { super(); this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (context) => { - this.#groupStructureHelper.setStructureManager(context.structure); + this.#groupStructureHelper.setStructureManager(context?.structure); - const entityType = context.getEntityType(); + const entityType = context?.getEntityType(); this.#workspaceModal?.destroy(); this.#workspaceModal = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) - .addAdditionalPath(entityType) + .addAdditionalPath(entityType ?? 'unknown') .onSetup(async () => { return { data: { entityType: entityType, preset: {} } }; }) @@ -127,7 +127,7 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement { this.consumeContext(UMB_CONTENT_TYPE_DESIGN_EDITOR_CONTEXT, (context) => { this.observe( - context.isSorting, + context?.isSorting, (isSorting) => { this._sortModeActive = isSorting; if (isSorting) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.context.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.context.ts index 866b83ec84d3..33fe4adbc550 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/workspace/views/design/content-type-design-editor.context.ts @@ -3,7 +3,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbContentTypeDesignEditorContext extends UmbContextBase { +export class UmbContentTypeDesignEditorContext extends UmbContextBase { #isSorting = new UmbBooleanState(false); readonly isSorting = this.#isSorting.asObservable(); 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 35bf37453c4a..909af69582c8 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 @@ -146,7 +146,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => { this.#workspaceContext = workspaceContext; - this.#tabsStructureHelper.setStructureManager(workspaceContext.structure); + this.#tabsStructureHelper.setStructureManager(workspaceContext?.structure); this.#observeRootGroups(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/content-collection-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/content-collection-workspace-view.element.ts index 88b351890daa..55fe2cf3743f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/content-collection-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/content-collection-workspace-view.element.ts @@ -31,11 +31,11 @@ export class UmbContentCollectionWorkspaceViewElement extends UmbLitElement impl async #observeConfig() { this.consumeContext(UMB_CONTENT_COLLECTION_WORKSPACE_CONTEXT, (workspaceContext) => { - this._collectionAlias = workspaceContext.getCollectionAlias(); - this._documentUnique = workspaceContext.getUnique() ?? ''; + this._collectionAlias = workspaceContext?.getCollectionAlias(); + this._documentUnique = workspaceContext?.getUnique() ?? ''; this.observe( - workspaceContext.structure.ownerContentType, + workspaceContext?.structure.ownerContentType, async (contentType) => { if (!contentType || !contentType.collection) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/workspace-has-content-collection/workspace-has-content-collection.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/workspace-has-content-collection/workspace-has-content-collection.condition.ts index 579df46456ae..9cb170922e0a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/workspace-has-content-collection/workspace-has-content-collection.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/collection/workspace-has-content-collection/workspace-has-content-collection.condition.ts @@ -18,9 +18,9 @@ export class UmbWorkspaceHasContentCollectionCondition this.consumeContext(UMB_CONTENT_COLLECTION_WORKSPACE_CONTEXT, (context) => { this.observe( - context.contentTypeHasCollection, + context?.contentTypeHasCollection, (hasCollection) => { - this.permitted = hasCollection; + this.permitted = hasCollection ?? false; }, ObserveSymbol, ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/conditions/has-properties/content-has-properties.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/conditions/has-properties/content-has-properties.condition.ts index 8e2e65ba0195..6063ab12e322 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/conditions/has-properties/content-has-properties.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/conditions/has-properties/content-has-properties.condition.ts @@ -16,9 +16,9 @@ export class UmbContentHasPropertiesWorkspaceCondition this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { this.observe( - context.structure.contentTypeHasProperties, + context?.structure.contentTypeHasProperties, (hasProperties) => { - this.permitted = hasProperties; + this.permitted = hasProperties ?? false; }, 'hasPropertiesObserver', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/content-property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/content-property.context.ts index caefd7669024..b5380a092367 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/content-property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/content-property.context.ts @@ -4,7 +4,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -export class UmbContentPropertyContext extends UmbContextBase { +export class UmbContentPropertyContext extends UmbContextBase { #dataType = new UmbObjectState(undefined); dataType = this.#dataType.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/property-dataset-context/element-property-dataset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/property-dataset-context/element-property-dataset.context.ts index 22f434e2ca73..96381eb39fcf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/property-dataset-context/element-property-dataset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/property-dataset-context/element-property-dataset.context.ts @@ -26,7 +26,7 @@ export abstract class UmbElementPropertyDatasetContext< ContentTypeModel >, > - extends UmbContextBase + extends UmbContextBase implements UmbPropertyDatasetContext { protected readonly _dataOwner: DataOwnerType; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/content-detail-workspace-base.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/content-detail-workspace-base.ts index 2145e7dbb65a..bbfa248cd6a5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/content-detail-workspace-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/content-detail-workspace-base.ts @@ -124,7 +124,7 @@ export abstract class UmbContentDetailWorkspaceContextBase< /* Data Type */ // This dataTypeItemManager is used to load the data type items for this content type, so we have all data-types for this content type up front. [NL] - // But once we have a propert application cache this could be solved in a way where we ask the cache for the data type items. [NL] + // But once we have a proper application cache this could be solved in a way where we ask the cache for the data type items. [NL] // And then we do not need to store them here in a local manager, but instead just request them here up-front and then again needed(which would get them from the cache, which as well could be update while this runs) [NL] readonly #dataTypeItemManager = new UmbDataTypeItemRepositoryManager(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-properties.element.ts index acf627ffadce..0e5fc652a969 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-properties.element.ts @@ -38,16 +38,15 @@ export class UmbContentWorkspaceViewEditPropertiesElement extends UmbLitElement super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (datasetContext) => { - this._variantId = datasetContext.getVariantId(); + this._variantId = datasetContext?.getVariantId(); this.#processPropertyStructure(); }); this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (workspaceContext) => { this.#workspaceContext = workspaceContext; - this.#propertyStructureHelper.setStructureManager( // Assuming its the same content model type that we are working with here... [NL] - workspaceContext.structure as unknown as UmbContentTypeStructureManager, + workspaceContext?.structure as unknown as UmbContentTypeStructureManager, ); this.observe( diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-tab.element.ts index 91850508d5ef..c9d011257d9d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor-tab.element.ts @@ -39,7 +39,7 @@ export class UmbContentWorkspaceViewEditTabElement extends UmbLitElement { this.consumeContext(UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT, (workspaceContext) => { this.#groupStructureHelper.setStructureManager( // Assuming its the same content model type that we are working with here... [NL] - workspaceContext.structure as unknown as UmbContentTypeStructureManager, + workspaceContext?.structure as unknown as UmbContentTypeStructureManager, ); }); this.observe(this.#groupStructureHelper.mergedContainers, (groups) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts index f24cd448f310..6f9bb5f542bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts @@ -60,8 +60,8 @@ export class UmbContentWorkspaceViewEditElement extends UmbLitElement implements // _hasRootProperties can be gotten via _tabsStructureHelper.hasProperties. But we do not support root properties currently. this.consumeContext(UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT, (workspaceContext) => { - this.#structureManager = workspaceContext.structure; - this._tabsStructureHelper.setStructureManager(workspaceContext.structure); + this.#structureManager = workspaceContext?.structure; + this._tabsStructureHelper.setStructureManager(workspaceContext?.structure); this.#observeRootGroups(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/property-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/property-type-workspace-editor.element.ts index 1e1c30458048..611ccc724117 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/property-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/property-type-workspace-editor.element.ts @@ -17,10 +17,10 @@ export class UmbPropertyTypeWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT, (context) => { this.#workspaceContext = context; - this.observe(context.isNew, (isNew) => { + this.observe(context?.isNew, (isNew) => { this._isNew = isNew; }); - this.observe(context.name, (name) => { + this.observe(context?.name, (name) => { this._name = name; }); this.#workspaceContext?.createPropertyDatasetContext(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/views/settings/property-workspace-view-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/views/settings/property-workspace-view-settings.element.ts index b548f8a0e36c..b12707f699a3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/views/settings/property-workspace-view-settings.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/property-type/workspace/views/settings/property-workspace-view-settings.element.ts @@ -70,7 +70,7 @@ export class UmbPropertyTypeWorkspaceViewSettingsElement extends UmbLitElement i this.consumeContext(UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT, (instance) => { this.#context = instance; this.observe( - instance.data, + instance?.data, (data) => { if (!this._data && data?.alias) { // Initial. Loading existing property @@ -83,9 +83,15 @@ export class UmbPropertyTypeWorkspaceViewSettingsElement extends UmbLitElement i }); this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (instance) => { - this.observe(instance.variesByCulture, (variesByCulture) => (this._contentTypeVariesByCulture = variesByCulture)); - this.observe(instance.variesBySegment, (variesBySegment) => (this._contentTypeVariesBySegment = variesBySegment)); - this._entityType = instance.getEntityType(); + this.observe( + instance?.variesByCulture, + (variesByCulture) => (this._contentTypeVariesByCulture = variesByCulture), + ); + this.observe( + instance?.variesBySegment, + (variesBySegment) => (this._contentTypeVariesBySegment = variesBySegment), + ); + this._entityType = instance?.getEntityType(); }).passContextAliasMatches(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/action/action-event.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/action/action-event.context.ts index 6edcae712bd4..8a27568c6724 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/action/action-event.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/action/action-event.context.ts @@ -2,7 +2,7 @@ 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'; -export class UmbActionEventContext extends UmbContextBase { +export class UmbActionEventContext extends UmbContextBase { constructor(host: UmbControllerHost) { super(host, UMB_ACTION_EVENT_CONTEXT); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts index e8697f6567af..7dbfed5b5c70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/auth.context.ts @@ -10,7 +10,7 @@ import { ReplaySubject, Subject, firstValueFrom, switchMap } from '@umbraco-cms/ import type { UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { umbHttpClient } from '@umbraco-cms/backoffice/http-client'; -export class UmbAuthContext extends UmbContextBase { +export class UmbAuthContext extends UmbContextBase { #isAuthorized = new UmbBooleanState(false); // Timeout is different from `isAuthorized` because it can occur repeatedly #isTimeout = new Subject(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts index d274e37a8ae2..e9082ad7b5d9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/auth/modals/umb-app-auth-modal.element.ts @@ -46,19 +46,19 @@ export class UmbAppAuthModalElement extends UmbModalBaseElement { - this._serverUrl = context.getServerUrl(); + this._serverUrl = context?.getServerUrl() ?? ''; this.style.setProperty( '--image', `url('${this._serverUrl}/umbraco/management/api/v1/security/back-office/graphics/login-background') no-repeat center center/cover`, ); - const serverConnection = context.getServerConnection(); + const serverConnection = context?.getServerConnection(); - this.observe(serverConnection.allowLocalLogin, (allowLocalLogin) => { - this._allowLocalLogin = allowLocalLogin; + this.observe(serverConnection?.allowLocalLogin, (allowLocalLogin) => { + this._allowLocalLogin = allowLocalLogin ?? false; }); - this.observe(serverConnection.isConnected, (isConnected) => { + this.observe(serverConnection?.isConnected, (isConnected) => { this._loading = !isConnected; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-selection-actions.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-selection-actions.element.ts index 389f1d22acf1..c779be33c6c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-selection-actions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-selection-actions.element.ts @@ -45,7 +45,7 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement { }); this.consumeContext(UMB_ENTITY_CONTEXT, (entityContext) => { - this._entityType = entityContext.getEntityType(); + this._entityType = entityContext?.getEntityType(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts index da3467177b04..0fc06dc13ebf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/collection-view-bundle.element.ts @@ -36,7 +36,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement { super(); this.consumeContext(UMB_ROUTE_CONTEXT, (context) => { - this.observe(context.activePath, (activePath) => { + this.observe(context?.activePath, (activePath) => { this._collectionRootPathName = activePath; }); }); @@ -47,7 +47,7 @@ export class UmbCollectionViewBundleElement extends UmbLitElement { }); this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (context) => { - this._entityUnique = context.getUnique() ?? ''; + this._entityUnique = context?.getUnique() ?? ''; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/pagination/collection-pagination.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/pagination/collection-pagination.element.ts index e360833703ac..183b0e1f9f04 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/pagination/collection-pagination.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/components/pagination/collection-pagination.element.ts @@ -25,9 +25,9 @@ export class UmbCollectionPaginationElement extends UmbLitElement { #observeCurrentPage() { this.observe( - this._collectionContext!.pagination.currentPage, + this._collectionContext?.pagination.currentPage, (currentPage) => { - this._currentPage = currentPage; + this._currentPage = currentPage ?? 1; }, 'umbCurrentPageObserver', ); @@ -35,9 +35,9 @@ export class UmbCollectionPaginationElement extends UmbLitElement { #observerTotalPages() { this.observe( - this._collectionContext!.pagination.totalPages, + this._collectionContext?.pagination.totalPages, (totalPages) => { - this._totalPages = totalPages; + this._totalPages = totalPages ?? 1; }, 'umbTotalPagesObserver', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts index 623dccde66f4..2419198d94b9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-alias.condition.ts @@ -11,7 +11,7 @@ export class UmbCollectionAliasCondition constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); this.consumeContext(UMB_COLLECTION_CONTEXT, (context) => { - this.permitted = context.manifest?.alias === this.config.match; + this.permitted = context?.manifest?.alias === this.config.match; }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts index 7ae41de4bc62..767a30b14c6a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/conditions/collection-bulk-action-permission.condition.ts @@ -16,7 +16,7 @@ export class UmbCollectionBulkActionPermissionCondition super(host, args); this.consumeContext(UMB_COLLECTION_CONTEXT, (context) => { - const allowedActions = context.getConfig()?.allowedEntityBulkActions; + const allowedActions = context?.getConfig()?.allowedEntityBulkActions; this.permitted = allowedActions ? this.config.match(allowedActions) : false; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts index 7079ef7aeec4..9967dead3446 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/default/collection-default.context.ts @@ -35,7 +35,7 @@ export class UmbDefaultCollectionContext< CollectionItemType extends { entityType: string; unique: string } = any, FilterModelType extends UmbCollectionFilterModel = UmbCollectionFilterModel, > - extends UmbContextBase + extends UmbContextBase implements UmbCollectionContext, UmbApi { #config?: UmbCollectionConfiguration = { pageSize: 50 }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-color-picker-input/multiple-color-picker-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-color-picker-input/multiple-color-picker-input.element.ts index a76e4e56c574..bb27d257bfd3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-color-picker-input/multiple-color-picker-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-color-picker-input/multiple-color-picker-input.element.ts @@ -94,7 +94,7 @@ export class UmbMultipleColorPickerInputElement extends UUIFormControlMixin(UmbL this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { const workspace = instance; this.observe( - await workspace.propertyValueByAlias('useLabel'), + await workspace?.propertyValueByAlias('useLabel'), (value) => { this.showLabels = !!value; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/condition/entity-has-children.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/condition/entity-has-children.condition.ts index cc930c4cf8a9..41b468ad9977 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/condition/entity-has-children.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/condition/entity-has-children.condition.ts @@ -15,7 +15,7 @@ export class UmbEntityHasChildrenCondition super(host, args); this.consumeContext(UMB_HAS_CHILDREN_ENTITY_CONTEXT, (context) => { - this.observe(context.hasChildren, (hasChildren) => { + this.observe(context?.hasChildren, (hasChildren) => { this.permitted = hasChildren === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/context/has-children.entity-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/context/has-children.entity-context.ts index ed8d1c0de908..31bda167dc8c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/context/has-children.entity-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/has-children/context/has-children.entity-context.ts @@ -3,7 +3,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbHasChildrenEntityContext extends UmbContextBase { +export class UmbHasChildrenEntityContext extends UmbContextBase { #hasChildren = new UmbBooleanState(undefined); public readonly hasChildren = this.#hasChildren.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/contexts/ancestors/ancestors.entity-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/contexts/ancestors/ancestors.entity-context.ts index 5cbd6a8cedda..7aeb9892d060 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/contexts/ancestors/ancestors.entity-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/contexts/ancestors/ancestors.entity-context.ts @@ -7,10 +7,10 @@ import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; /** * A entity context for the ancestors * @class UmbAncestorsEntityContext - * @augments {UmbContextBase} + * @augments {UmbContextBase} * @implements {UmbAncestorsEntityContext} */ -export class UmbAncestorsEntityContext extends UmbContextBase { +export class UmbAncestorsEntityContext extends UmbContextBase { #ancestors = new UmbArrayState([], (x) => x.unique); ancestors = this.#ancestors.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity.context.ts index f3058608dfa7..d5577486c43b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity/entity.context.ts @@ -7,9 +7,9 @@ import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; /** * Provides the entity context * @class UmbEntityContext - * @augments {UmbContextBase} + * @augments {UmbContextBase} */ -export class UmbEntityContext extends UmbContextBase { +export class UmbEntityContext extends UmbContextBase { #entityType = new UmbStringState(undefined); public readonly entityType = this.#entityType.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts index cf71700dced6..0a23247e5ac7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entry-point.ts @@ -31,6 +31,6 @@ export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => { host.consumeContext(UMB_AUTH_CONTEXT, (authContext) => { // Initialize the auth context to let the app context know that the core module is ready - authContext.setInitialized(); + authContext?.setInitialized(); }); }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/condition-base.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/condition-base.controller.ts index 804684e1fb7c..9b6b6b53cc6a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/condition-base.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/condition-base.controller.ts @@ -14,11 +14,11 @@ export class UmbConditionBase void; + #onChange: (permitted: boolean) => void; - constructor(host: UmbControllerHost, args: { config: ConditionConfigType; onChange: () => void }) { + constructor(host: UmbControllerHost, args: { config: ConditionConfigType; onChange: (permitted: boolean) => void }) { super(host); this.config = args.config; this.#onChange = args.onChange; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts index d8483c4c3e7a..d2991a7aae98 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.element.ts @@ -30,7 +30,7 @@ export class UmbIconPickerModalElement extends UmbModalBaseElement { - this.observe(context.approvedIcons, (icons) => { + this.observe(context?.approvedIcons, (icons) => { this.#icons = icons; this.#filterIcons(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-registry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-registry.context.ts index 5695f636a814..015061ebfcde 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-registry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-registry.context.ts @@ -7,7 +7,7 @@ import { loadManifestPlainJs } from '@umbraco-cms/backoffice/extension-api'; import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -export class UmbIconRegistryContext extends UmbContextBase { +export class UmbIconRegistryContext extends UmbContextBase { #registry: UmbIconRegistry; #manifestMap = new Map(); #icons = new UmbArrayState([], (x) => x.name); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-structure-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-structure-workspace-context.interface.ts index 6b0827d2b6e1..c83b74dc0672 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-structure-workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-structure-workspace-context.interface.ts @@ -1,6 +1,7 @@ import type { UmbStructureItemModel } from './types.js'; +import type { UmbContext } from '@umbraco-cms/backoffice/class-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -export interface UmbMenuStructureWorkspaceContext { +export interface UmbMenuStructureWorkspaceContext extends UmbContext { structure: Observable; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-tree-structure-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-tree-structure-workspace-context-base.ts index 59da518fa33a..d461bff39130 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-tree-structure-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-tree-structure-workspace-context-base.ts @@ -2,7 +2,7 @@ import type { UmbStructureItemModel } from './types.js'; import type { UmbTreeRepository, UmbTreeItemModel, UmbTreeRootModel } from '@umbraco-cms/backoffice/tree'; import { createExtensionApiByAlias } from '@umbraco-cms/backoffice/extension-registry'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { UMB_SUBMITTABLE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -10,8 +10,8 @@ interface UmbMenuTreeStructureWorkspaceContextBaseArgs { treeRepositoryAlias: string; } -export abstract class UmbMenuTreeStructureWorkspaceContextBase extends UmbContextBase { - #workspaceContext?: any; +export abstract class UmbMenuTreeStructureWorkspaceContextBase extends UmbContextBase { + #workspaceContext?: typeof UMB_SUBMITTABLE_WORKSPACE_CONTEXT.TYPE; #args: UmbMenuTreeStructureWorkspaceContextBaseArgs; #structure = new UmbArrayState([], (x) => x.unique); @@ -25,11 +25,10 @@ export abstract class UmbMenuTreeStructureWorkspaceContextBase extends UmbContex super(host, 'UmbMenuStructureWorkspaceContext'); this.#args = args; - this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => { + // TODO: set up context token that supports parentEntityType, parentUnique, entityType. + this.consumeContext(UMB_SUBMITTABLE_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - this.#workspaceContext.observe(this.#workspaceContext.unique, (value) => { + this.observe(this.#workspaceContext?.unique, (value) => { if (!value) return; this.#requestStructure(); }); @@ -59,13 +58,15 @@ export abstract class UmbMenuTreeStructureWorkspaceContextBase extends UmbContex const isNew = this.#workspaceContext?.getIsNew(); - const entityTypeObservable = isNew ? this.#workspaceContext?.parentEntityType : this.#workspaceContext?.entityType; + const entityTypeObservable = isNew + ? (this.#workspaceContext as any)?.parentEntityType + : (this.#workspaceContext as any).entityType; const entityType = (await this.observe(entityTypeObservable, () => {})?.asPromise()) as string; if (!entityType) throw new Error('Entity type is not available'); // If the entity type is different from the root entity type, then we can request the ancestors. if (entityType !== root?.entityType) { - const uniqueObservable = isNew ? this.#workspaceContext?.parentUnique : this.#workspaceContext?.unique; + const uniqueObservable = isNew ? (this.#workspaceContext as any)?.parentUnique : this.#workspaceContext?.unique; const unique = (await this.observe(uniqueObservable, () => {})?.asPromise()) as string; if (!unique) throw new Error('Unique is not available'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts index 4233b340f53b..8268a9accc1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/menu-variant-tree-structure-workspace-context-base.ts @@ -11,9 +11,9 @@ interface UmbMenuVariantTreeStructureWorkspaceContextBaseArgs { treeRepositoryAlias: string; } -export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends UmbContextBase { +export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends UmbContextBase { // TODO: add correct interface - #workspaceContext?: any; + #workspaceContext?: typeof UMB_VARIANT_WORKSPACE_CONTEXT.TYPE; #args: UmbMenuVariantTreeStructureWorkspaceContextBaseArgs; #structure = new UmbArrayState([], (x) => x.unique); @@ -29,21 +29,26 @@ export abstract class UmbMenuVariantTreeStructureWorkspaceContextBase extends Um super(host, 'UmbMenuStructureWorkspaceContext'); this.#args = args; + // TODO: Implement a Context Token that supports parentUnique, parentEntityType, entityType this.consumeContext(UMB_VARIANT_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - this.#workspaceContext.observe(this.#workspaceContext.unique, (value) => { - if (!value) return; - this.#requestStructure(); - }); + this.observe( + this.#workspaceContext?.unique, + (value) => { + if (!value) return; + this.#requestStructure(); + }, + 'observeUnique', + ); }); } async #requestStructure() { const isNew = this.#workspaceContext?.getIsNew(); - const uniqueObservable = isNew ? this.#workspaceContext?.parentUnique : this.#workspaceContext?.unique; - const entityTypeObservable = isNew ? this.#workspaceContext?.parentEntityType : this.#workspaceContext?.entityType; + const uniqueObservable = isNew ? (this.#workspaceContext as any)?.parentUnique : this.#workspaceContext?.unique; + const entityTypeObservable = isNew + ? (this.#workspaceContext as any)?.parentEntityType + : (this.#workspaceContext as any)?.entityType; let structureItems: Array = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts index 655e9af94d88..aab771fba1cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/context/modal-manager.context.ts @@ -6,7 +6,7 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbModalManagerContext extends UmbContextBase { +export class UmbModalManagerContext extends UmbContextBase { // TODO: Investigate if we can get rid of HTML elements in our store, so we can use one of our states. #modals = new UmbBasicState(>[]); public readonly modals = this.#modals.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification.context.ts index e0990ecfe04a..25ffe285c592 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification.context.ts @@ -5,7 +5,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbNotificationContext extends UmbContextBase { +export class UmbNotificationContext extends UmbContextBase { // Notice this cannot use UniqueBehaviorSubject as it holds a HTML Element. which cannot be Serialized to JSON (it has some circular references) private _notifications = new UmbBasicState(>[]); public readonly notifications = this._notifications.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts index e443493a3ef2..2d219f34414f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts @@ -14,7 +14,7 @@ export class UmbPickerInputContext< PickerItemType extends PickerItemBaseType = PickedItemType, PickerModalConfigType extends UmbPickerModalData = UmbPickerModalData, PickerModalValueType extends UmbPickerModalValue = UmbPickerModalValue, -> extends UmbContextBase { +> extends UmbContextBase { modalAlias: string | UmbModalToken, PickerModalValueType>; repository?: UmbItemRepository; #getUnique: (entry: PickedItemType) => string | undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/picker.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/picker.context.ts index b586a90e3e25..52594864e89d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/picker.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/picker.context.ts @@ -4,7 +4,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; -export class UmbPickerContext extends UmbContextBase { +export class UmbPickerContext extends UmbContextBase { public readonly selection = new UmbSelectionManager(this); public readonly search = new UmbPickerSearchManager(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-field.element.ts index f4f7d45fdc9f..22287a8ff353 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-field.element.ts @@ -23,9 +23,12 @@ export class UmbPickerSearchFieldElement extends UmbLitElement { this.consumeContext(UMB_PICKER_CONTEXT, (context) => { this.#pickerContext = context; - this.observe(this.#pickerContext.search.searchable, (isSearchable) => (this._isSearchable = isSearchable)); - this.observe(this.#pickerContext.search.searching, (searching) => (this._searching = searching)); - this.observe(this.#pickerContext.search.query, (query) => (this._query = query?.query || '')); + this.observe( + this.#pickerContext?.search.searchable, + (isSearchable) => (this._isSearchable = isSearchable ?? false), + ); + this.observe(this.#pickerContext?.search.searching, (searching) => (this._searching = searching ?? false)); + this.observe(this.#pickerContext?.search.query, (query) => (this._query = query?.query || '')); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-result.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-result.element.ts index d43ba3a804f2..7b74306a45c7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-result.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/picker-search-result.element.ts @@ -27,10 +27,13 @@ export class UmbPickerSearchResultElement extends UmbLitElement { this.consumeContext(UMB_PICKER_CONTEXT, (context) => { this.#pickerContext = context; - this.observe(this.#pickerContext.search.searchable, (isSearchable) => (this._isSearchable = isSearchable)); - this.observe(this.#pickerContext.search.query, (query) => (this._query = query)); - this.observe(this.#pickerContext.search.searching, (query) => (this._searching = query)); - this.observe(this.#pickerContext.search.resultItems, (items) => (this._items = items)); + this.observe( + this.#pickerContext?.search.searchable, + (isSearchable) => (this._isSearchable = isSearchable ?? false), + ); + this.observe(this.#pickerContext?.search.query, (query) => (this._query = query)); + this.observe(this.#pickerContext?.search.searching, (query) => (this._searching = query ?? false)); + this.observe(this.#pickerContext?.search.resultItems, (items) => (this._items = items ?? [])); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/default/default-picker-search-result-item.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/default/default-picker-search-result-item.context.ts index 7204b6679d29..ad66b4da6142 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/default/default-picker-search-result-item.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker/search/result-item/default/default-picker-search-result-item.context.ts @@ -2,7 +2,7 @@ import { UMB_PICKER_SEARCH_RESULT_ITEM_CONTEXT } from './default-picker-search-r import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbDefaultPickerSearchResultItemContext extends UmbContextBase { +export class UmbDefaultPickerSearchResultItemContext extends UmbContextBase { constructor(host: UmbControllerHost) { super(host, UMB_PICKER_SEARCH_RESULT_ITEM_CONTEXT); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts index e6997d6f4a8d..78f037a246b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.context.ts @@ -23,7 +23,7 @@ import type { } from '@umbraco-cms/backoffice/content-type'; import { UmbReadOnlyStateManager } from '@umbraco-cms/backoffice/utils'; -export class UmbPropertyContext extends UmbContextBase> { +export class UmbPropertyContext extends UmbContextBase { #alias = new UmbStringState(undefined); public readonly alias = this.#alias.asObservable(); @@ -109,7 +109,7 @@ export class UmbPropertyContext extends UmbContextBase { this.#datasetContext = variantContext; - this.setVariantId(variantContext.getVariantId?.()); + this.setVariantId(variantContext?.getVariantId?.()); this._generateVariantDifferenceString(); this._observeProperty(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/has-value/has-value.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/has-value/has-value.condition.ts index d70f71f99726..d6f736941954 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/has-value/has-value.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/has-value/has-value.condition.ts @@ -12,7 +12,7 @@ export class UmbPropertyHasValueCondition super(host, args); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this.observe(context.value, (value) => { + this.observe(context?.value, (value) => { this.permitted = value !== undefined; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/writable/writable-property.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/writable/writable-property.condition.ts index c33a7e4b8cab..12c8b753dbc1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/writable/writable-property.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/conditions/writable/writable-property.condition.ts @@ -15,7 +15,7 @@ export class UmbWritablePropertyCondition super(host, args); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this.observe(context.isReadOnly, (value) => { + this.observe(context?.isReadOnly, (value) => { this.permitted = value !== true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts index 7b7a4c282239..9fbdd695bfc9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/property-dataset/property-dataset-base-context.ts @@ -13,7 +13,7 @@ import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; * @augments {UmbContextBase} */ export class UmbPropertyDatasetContextBase - extends UmbContextBase + extends UmbContextBase implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext { #name = new UmbStringState(undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition.ts index 1053e532461f..8b21b16c4dbd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-not-trashed/entity-is-not-trashed.condition.ts @@ -19,7 +19,7 @@ export class UmbEntityIsNotTrashedCondition this.permitted = true; this.consumeContext(UMB_IS_TRASHED_ENTITY_CONTEXT, (context) => { - this.observe(context.isTrashed, (isTrashed) => { + this.observe(context?.isTrashed, (isTrashed) => { this.permitted = isTrashed === false; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition.ts index d573f89faa42..d68af75ccac8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/conditions/is-trashed/entity-is-trashed.condition.ts @@ -12,7 +12,7 @@ export class UmbIsTrashedCondition extends UmbConditionBase { - this.observe(context.isTrashed, (isTrashed) => { + this.observe(context?.isTrashed, (isTrashed) => { this.permitted = isTrashed === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/contexts/is-trashed/is-trashed.entity-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/contexts/is-trashed/is-trashed.entity-context.ts index 5cf5f9d97c64..f42da5d5cc02 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/contexts/is-trashed/is-trashed.entity-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/contexts/is-trashed/is-trashed.entity-context.ts @@ -6,10 +6,10 @@ import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; /** * A entity context for the isTrashed state. * @class UmbIsTrashedEntityContext - * @augments {UmbContextBase} + * @augments {UmbContextBase} * @implements {UmbIsTrashedEntityContext} */ -export class UmbIsTrashedEntityContext extends UmbContextBase { +export class UmbIsTrashedEntityContext extends UmbContextBase { #isTrashed = new UmbBooleanState(false); isTrashed = this.#isTrashed.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts index 178b9062cd07..fe4e1a325604 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail/detail-repository-base.ts @@ -73,7 +73,7 @@ export abstract class UmbDetailRepositoryBase< const { data, error } = await this.detailDataSource.read(unique); if (data) { - this.#detailStore!.append(data); + this.#detailStore?.append(data); } return { @@ -121,7 +121,7 @@ export abstract class UmbDetailRepositoryBase< const { data: updatedData, error } = await this.detailDataSource.update(model); if (updatedData) { - this.#detailStore!.updateItem(model.unique, updatedData); + this.#detailStore?.updateItem(model.unique, updatedData); // TODO: how do we handle generic notifications? Is this the correct place to do it? this.#updateSuccessNotification?.close(); @@ -145,7 +145,7 @@ export abstract class UmbDetailRepositoryBase< const { error } = await this.detailDataSource.delete(unique); if (!error) { - this.#detailStore!.removeItem(unique); + this.#detailStore?.removeItem(unique); this.#deleteSuccessNotification?.close(); // TODO: how do we handle generic notifications? Is this the correct place to do it? diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository-base.ts index d53d64c5a512..cc6bfc743fb8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item/item-repository-base.ts @@ -38,6 +38,10 @@ export class UmbItemRepositoryBase const { data, error: _error } = await this.#itemSource.getItems(uniques); + if (!this._itemStore) { + // If store is gone, then we are most likely in a disassembled state. + return {}; + } const error: any = _error; if (data) { this._itemStore!.appendItems(data); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-details.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-details.manager.ts index fb58c28815b4..72663e8ad0bd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-details.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-details.manager.ts @@ -96,7 +96,7 @@ export class UmbRepositoryDetailsManager ); this.#eventContext = context; - this.#eventContext.addEventListener( + this.#eventContext?.addEventListener( UmbEntityUpdatedEvent.TYPE, this.#onEntityUpdatedEvent as unknown as EventListener, ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts index 24f8d84fe8dd..d5fac8fabbd1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts @@ -108,7 +108,7 @@ export class UmbRepositoryItemsManager exte ); this.#eventContext = context; - this.#eventContext.addEventListener( + this.#eventContext?.addEventListener( UmbEntityUpdatedEvent.TYPE, this.#onEntityUpdatedEvent as unknown as EventListener, ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum-reset.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum-reset.context.ts index 7421bfed87eb..f5b8f74a29b0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum-reset.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum-reset.context.ts @@ -4,10 +4,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbRoutePathAddendumResetContext - extends UmbContextBase - implements UmbRoutePathAddendum -{ +export class UmbRoutePathAddendumResetContext extends UmbContextBase implements UmbRoutePathAddendum { #appendum = new UmbStringState(''); readonly addendum = this.#appendum.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.context.ts index 9a2c2e4f2042..c9d6d32452f5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.context.ts @@ -4,10 +4,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbRoutePathAddendumContext - extends UmbContextBase - implements UmbRoutePathAddendum -{ +export class UmbRoutePathAddendumContext extends UmbContextBase implements UmbRoutePathAddendum { #parent?: string; #current?: string; @@ -18,7 +15,7 @@ export class UmbRoutePathAddendumContext super(host, UMB_ROUTE_PATH_ADDENDUM_CONTEXT); this.consumeContext(UMB_ROUTE_PATH_ADDENDUM_CONTEXT, (context) => { - this.observe(context.addendum, (addendum) => { + this.observe(context?.addendum, (addendum) => { this.#parent = addendum; this.#update(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.interface.ts index 32b57d05ad7a..75838e12b159 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/contexts/route-path-addendum.interface.ts @@ -1,5 +1,6 @@ +import type { UmbContext } from '@umbraco-cms/backoffice/class-api'; import type { Observable } from '@umbraco-cms/backoffice/observable-api'; -export interface UmbRoutePathAddendum { +export interface UmbRoutePathAddendum extends UmbContext { addendum: Observable; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/modal-registration/modal-route-registration.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/modal-registration/modal-route-registration.controller.ts index 8595b95f84a4..b8fe83766a35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/modal-registration/modal-route-registration.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/modal-registration/modal-route-registration.controller.ts @@ -92,10 +92,10 @@ export class UmbModalRouteRegistrationController< this.consumeContext(UMB_ROUTE_PATH_ADDENDUM_CONTEXT, (context) => { this.observe( - context.addendum, + context?.addendum, (addendum) => { this.#addendum = addendum; - this.#registerModal(); + this.#registerModal().catch(() => undefined); }, 'observeAddendum', ); @@ -103,7 +103,7 @@ export class UmbModalRouteRegistrationController< this.#init = this.consumeContext(UMB_ROUTE_CONTEXT, (_routeContext) => { this.#routeContext = _routeContext; - this.#registerModal(); + this.#registerModal().catch(() => undefined); }).asPromise({ preventTimeout: true }); } @@ -176,7 +176,7 @@ export class UmbModalRouteRegistrationController< if (oldValue === value) return; this.#uniquePaths.set(identifier, value); - this.#registerModal(); + this.#registerModal().catch(() => undefined); } getUniquePathValue(identifier: string): string | undefined { return this.#uniquePaths.get(identifier); @@ -223,7 +223,7 @@ export class UmbModalRouteRegistrationController< this.#modalRegistrationContext = this.#routeContext; } - async #unregisterModal() { + #unregisterModal() { if (!this.#routeContext) return; if (this.#modalRegistrationContext) { this.#modalRegistrationContext.unregisterModal(this); @@ -234,7 +234,7 @@ export class UmbModalRouteRegistrationController< override hostConnected() { super.hostConnected(); if (!this.#modalRegistrationContext) { - this.#registerModal(); + this.#registerModal().catch(() => undefined); } } override hostDisconnected(): void { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/router/route/route.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/router/route/route.context.ts index cb48d6ec4ccd..fd2e9daeb89f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/router/route/route.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/router/route/route.context.ts @@ -12,7 +12,7 @@ const EmptyDiv = document.createElement('div'); type UmbRoutePlusModalKey = UmbRoute & { __modalKey: string }; -export class UmbRouteContext extends UmbContextBase { +export class UmbRouteContext extends UmbContextBase { #modalRouter: IRouterSlot; #modalRegistrations: UmbModalRouteRegistration[] = []; #modalContext?: typeof UMB_MODAL_MANAGER_CONTEXT.TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-alias.condition.ts index b04ed41e460d..9a18d0ce1551 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-alias.condition.ts @@ -21,7 +21,7 @@ export class UmbSectionAliasCondition if (permissionCheck !== undefined) { this.consumeContext(UMB_SECTION_CONTEXT, (context) => { this.observe( - context.alias, + context?.alias, (sectionAlias) => { this.permitted = sectionAlias ? permissionCheck!(sectionAlias) : false; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.test.ts index 4bf20f789ac0..59f3f92c86ce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.test.ts @@ -36,30 +36,45 @@ describe('UmbSectionUserPermissionCondition', () => { }); it('should return true if the user have access to the section', (done) => { + let callbackCount = 0; condition = new UmbSectionUserPermissionCondition(hostElement, { host: hostElement, config: { alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, match: 'Umb.Section.Content', }, - onChange: (permitted) => { - expect(permitted).to.be.true; - done(); + onChange: () => { + callbackCount++; + if (callbackCount === 1) { + expect(condition.permitted).to.be.true; + condition.hostDisconnected(); + done(); + } }, }); }); - it('should return false if the user does not have access to the section', (done) => { + it('should return false if the user does not have access to the section', async () => { + let callbackCount = 0; condition = new UmbSectionUserPermissionCondition(hostElement, { host: hostElement, config: { alias: UMB_SECTION_USER_PERMISSION_CONDITION_ALIAS, match: 'DOES_NOT_EXIST', }, - onChange: (permitted) => { - expect(permitted).to.be.false; - done(); + onChange: () => { + callbackCount++; }, }); + + await new Promise((resolve) => { + requestAnimationFrame(() => { + expect(condition.permitted).to.be.false; + resolve(true); + }); + }); + + expect(callbackCount).to.equal(0); + condition.hostDisconnected(); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.ts index e56e38a17e16..dc753e563dcd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/conditions/section-user-permission.condition.ts @@ -1,34 +1,26 @@ import type { UmbSectionUserPermissionConditionConfig } from './types.js'; import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; -// Do not export - for internal use only -type UmbOnChangeCallbackType = (permitted: boolean) => void; +const ObserveSymbol = Symbol(); -export class UmbSectionUserPermissionCondition extends UmbControllerBase implements UmbExtensionCondition { - config: UmbSectionUserPermissionConditionConfig; - permitted = false; - #onChange: UmbOnChangeCallbackType; - - constructor( - host: UmbControllerHost, - args: UmbConditionControllerArguments, - ) { - super(host); - this.config = args.config; - this.#onChange = args.onChange; +export class UmbSectionUserPermissionCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.currentUser, + context?.currentUser, (currentUser) => { - const allowedSections = currentUser?.allowedSections || []; + const allowedSections = currentUser?.allowedSections ?? []; this.permitted = allowedSections.includes(this.config.match); - this.#onChange(this.permitted); }, - 'umbSectionUserPermissionConditionObserver', + ObserveSymbol, ); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts index 5fad1202bb48..6c1bce2e1922 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.context.ts @@ -4,7 +4,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbStringState, UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbSectionSidebarContext extends UmbContextBase { +export class UmbSectionSidebarContext extends UmbContextBase { #contextMenuIsOpen = new UmbBooleanState(false); contextMenuIsOpen = this.#contextMenuIsOpen.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section.context.ts index 24a31400cbcd..fbb626897fb3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section.context.ts @@ -4,7 +4,7 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -export class UmbSectionContext extends UmbContextBase { +export class UmbSectionContext extends UmbContextBase { #manifestAlias = new UmbStringState(undefined); #manifestPathname = new UmbStringState(undefined); #manifestLabel = new UmbStringState(undefined); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/server/server.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/server/server.context.ts index dea492b571e4..ce8ff9e75fc2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/server/server.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/server/server.context.ts @@ -3,7 +3,7 @@ import type { UmbServerContextConfig } from './types.js'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbServerContext extends UmbContextBase { +export class UmbServerContext extends UmbContextBase { #serverUrl: string; #backofficePath: string; #serverConnection; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/store/store-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/store/store-base.ts index 1d51ad902a28..5333902e4fba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/store/store-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/store/store-base.ts @@ -7,7 +7,7 @@ import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import type { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -export class UmbStoreBase extends UmbContextBase implements UmbStore, UmbApi { +export class UmbStoreBase extends UmbContextBase implements UmbStore, UmbApi { protected _data: UmbArrayState; constructor(host: UmbControllerHost, storeAlias: string, data: UmbArrayState) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/store/store-object-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/store/store-object-base.ts index 5d3004489b3d..b8cb035a86fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/store/store-object-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/store/store-object-base.ts @@ -7,7 +7,7 @@ import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; /** * The base class for a store that holds an object. */ -export class UmbStoreObjectBase extends UmbContextBase implements UmbApi { +export class UmbStoreObjectBase extends UmbContextBase implements UmbApi { protected _data; constructor(host: UmbControllerHost, storeAlias: string, initialData?: T) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/store/store.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/store/store.interface.ts index 579df7f66d05..cff6905cb10a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/store/store.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/store/store.interface.ts @@ -1,7 +1,7 @@ import type { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -export interface UmbStore extends UmbContextBase { +export interface UmbStore extends UmbContextBase { append: (item: T) => void; appendItems: (items: Array) => void; updateItem: (unique: string, item: Partial) => void; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts index dc1a02b85fce..d7d9ef7f3239 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/themes/theme.context.ts @@ -9,7 +9,7 @@ import type { UmbObserverController } from '@umbraco-cms/backoffice/observable-a const LOCAL_STORAGE_KEY = 'umb-theme-alias'; -export class UmbThemeContext extends UmbContextBase { +export class UmbThemeContext extends UmbContextBase { #theme = new UmbStringState('umb-light-theme'); #themeObserver?: UmbObserverController; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts index ef62e28205a3..2231b61aec33 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/data/tree-repository-base.ts @@ -81,13 +81,17 @@ export abstract class UmbTreeRepositoryBase< async requestTreeRootItems(args: TreeRootItemsRequestArgsType) { await this._init; - const { data, error: _error } = await this._treeSource.getRootItems(args); - const error: any = _error; + const { data, error } = await this._treeSource.getRootItems(args); + if (!this._treeStore) { + // If the tree store is not available, then we most likely are in a destructed setting. + return {}; + } if (data) { - this._treeStore!.appendItems(data.items); + this._treeStore?.appendItems(data.items); } - return { data, error, asObservable: () => this._treeStore!.rootItems }; + // TODO: Notice we are casting the error here, is that right? + return { data, error: error as unknown as UmbProblemDetails, asObservable: () => this._treeStore!.rootItems }; } /** @@ -106,7 +110,7 @@ export abstract class UmbTreeRepositoryBase< const { data, error: _error } = await this._treeSource.getChildrenOf(args); const error: any = _error; if (data) { - this._treeStore!.appendItems(data.items); + this._treeStore?.appendItems(data.items); } return { data, error, asObservable: () => this._treeStore!.childrenOf(args.parent.unique) }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts index c86822e93cd2..45ebfdd2ea86 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts @@ -24,7 +24,7 @@ export class UmbDefaultTreeContext< TreeRootType extends UmbTreeRootModel, RequestArgsType extends UmbTreeRootItemsRequestArgs = UmbTreeRootItemsRequestArgs, > - extends UmbContextBase> + extends UmbContextBase implements UmbTreeContext { #additionalRequestArgs = new UmbObjectState | object>({}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts index c86201cd3a7b..c8d9e15a3365 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts @@ -7,7 +7,6 @@ import type { } from '../types.js'; import type { UmbTreeExpansionModel } from '../expansion-manager/types.js'; import type { UmbDefaultTreeContext } from './default-tree.context.js'; -import { UMB_TREE_CONTEXT } from './default-tree.context-token.js'; import { css, customElement, html, nothing, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; @@ -20,6 +19,16 @@ export class UmbDefaultTreeElement extends UmbLitElement { selection: [], }; + private _api: UmbDefaultTreeContext | undefined; + @property({ type: Object, attribute: false }) + public get api(): UmbDefaultTreeContext | undefined { + return this._api; + } + public set api(value: UmbDefaultTreeContext | undefined) { + this._api = value; + this.#observeData(); + } + @property({ type: Object, attribute: false }) selectionConfiguration: UmbTreeSelectionConfiguration = this._selectionConfiguration; @@ -59,71 +68,62 @@ export class UmbDefaultTreeElement extends UmbLitElement { @state() private _totalPages = 1; - @state() - _treeContext?: UmbDefaultTreeContext; - - constructor() { - super(); - - // TODO: Notice this can be retrieve via a api property. [NL] - this.consumeContext(UMB_TREE_CONTEXT, (instance) => { - this._treeContext = instance; - this.observe(this._treeContext.treeRoot, (treeRoot) => (this._treeRoot = treeRoot)); - this.observe(this._treeContext.rootItems, (rootItems) => (this._rootItems = rootItems)); - this.observe(this._treeContext.pagination.currentPage, (value) => (this._currentPage = value)); - this.observe(this._treeContext.pagination.totalPages, (value) => (this._totalPages = value)); - }); + #observeData() { + this.observe(this._api?.treeRoot, (treeRoot) => (this._treeRoot = treeRoot)); + this.observe(this._api?.rootItems, (rootItems) => (this._rootItems = rootItems ?? [])); + this.observe(this._api?.pagination.currentPage, (value) => (this._currentPage = value ?? 1)); + this.observe(this._api?.pagination.totalPages, (value) => (this._totalPages = value ?? 1)); } protected override async updated( _changedProperties: PropertyValueMap | Map, ): Promise { super.updated(_changedProperties); - if (this._treeContext === undefined) return; + if (this._api === undefined) return; if (_changedProperties.has('selectionConfiguration')) { this._selectionConfiguration = this.selectionConfiguration; - this._treeContext!.selection.setMultiple(this._selectionConfiguration.multiple ?? false); - this._treeContext!.selection.setSelectable(this._selectionConfiguration.selectable ?? true); - this._treeContext!.selection.setSelection(this._selectionConfiguration.selection ?? []); + this._api!.selection.setMultiple(this._selectionConfiguration.multiple ?? false); + this._api!.selection.setSelectable(this._selectionConfiguration.selectable ?? true); + this._api!.selection.setSelection(this._selectionConfiguration.selection ?? []); } if (_changedProperties.has('startNode')) { - this._treeContext!.setStartNode(this.startNode); + this._api!.setStartNode(this.startNode); } if (_changedProperties.has('hideTreeRoot')) { - this._treeContext!.setHideTreeRoot(this.hideTreeRoot); + this._api!.setHideTreeRoot(this.hideTreeRoot); } if (_changedProperties.has('expandTreeRoot')) { - this._treeContext!.setExpandTreeRoot(this.expandTreeRoot); + this._api!.setExpandTreeRoot(this.expandTreeRoot); } if (_changedProperties.has('foldersOnly')) { - this._treeContext!.setFoldersOnly(this.foldersOnly ?? false); + this._api!.setFoldersOnly(this.foldersOnly ?? false); } if (_changedProperties.has('selectableFilter')) { - this._treeContext!.selectableFilter = this.selectableFilter; + this._api!.selectableFilter = this.selectableFilter; } if (_changedProperties.has('filter')) { - this._treeContext!.filter = this.filter; + this._api!.filter = this.filter; } if (_changedProperties.has('expansion')) { - this._treeContext!.setExpansion(this.expansion); + this._api!.setExpansion(this.expansion); } } getSelection() { - return this._treeContext?.selection.getSelection(); + return this._api?.selection.getSelection(); } getExpansion() { - return this._treeContext?.expansion.getExpansion(); + return this._api?.expansion.getExpansion(); } override render() { @@ -162,7 +162,7 @@ export class UmbDefaultTreeElement extends UmbLitElement { #onLoadMoreClick = (event: any) => { event.stopPropagation(); const next = (this._currentPage = this._currentPage + 1); - this._treeContext?.pagination.setCurrentPageNumber(next); + this._api?.pagination.setCurrentPageNumber(next); }; #renderPaging() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-context.interface.ts index dfca3c3672e8..1483fe7d6ca6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-context.interface.ts @@ -2,6 +2,6 @@ import type { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; // TODO: update interface -export interface UmbTreeContext extends UmbContextBase { +export interface UmbTreeContext extends UmbContextBase { selection: UmbSelectionManager; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts index 44e527a6a8fa..060824dc28ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts @@ -26,7 +26,7 @@ export abstract class UmbTreeItemContextBase< TreeRootType extends UmbTreeRootModel, ManifestType extends ManifestTreeItem = ManifestTreeItem, > - extends UmbContextBase> + extends UmbContextBase implements UmbTreeItemContext { public unique?: UmbEntityUnique; @@ -300,17 +300,17 @@ export abstract class UmbTreeItemContextBase< this.#removeEventListeners(); this.#actionEventContext = instance; - this.#actionEventContext.addEventListener( + this.#actionEventContext?.addEventListener( UmbRequestReloadTreeItemChildrenEvent.TYPE, this.#onReloadRequest as EventListener, ); - this.#actionEventContext.addEventListener( + this.#actionEventContext?.addEventListener( UmbRequestReloadChildrenOfEntityEvent.TYPE, this.#onReloadRequest as EventListener, ); - this.#actionEventContext.addEventListener( + this.#actionEventContext?.addEventListener( UmbRequestReloadStructureForEntityEvent.TYPE, this.#onReloadStructureRequest as unknown as EventListener, ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts index a9255fa94a4e..24432c3dfbff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts @@ -2,8 +2,9 @@ import type { UmbTreeItemModel } from '../types.js'; import type { UmbPaginationManager } from '../../utils/pagination-manager/pagination.manager.js'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbContextMinimal } from '@umbraco-cms/backoffice/context-api'; -export interface UmbTreeItemContext extends UmbApi { +export interface UmbTreeItemContext extends UmbApi, UmbContextMinimal { unique?: string | null; entityType?: string; treeItem: Observable; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validator.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validator.context.ts index 52822cfdd26b..1971488ed333 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validator.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/context/server-model-validator.context.ts @@ -11,10 +11,7 @@ import type { ClassConstructor } from '@umbraco-cms/backoffice/extension-api'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbApiError } from '@umbraco-cms/backoffice/resources'; -export class UmbServerModelValidatorContext - extends UmbContextBase - implements UmbValidator -{ +export class UmbServerModelValidatorContext extends UmbContextBase implements UmbValidator { #pathTranslators: Array>> = []; #validatePromise?: Promise; @@ -36,7 +33,7 @@ export class UmbServerModelValidatorContext this.#context.removeValidator(this); } this.#context = context; - context.addValidator(this); + context?.addValidator(this); // Run translators? }).asPromise({ preventTimeout: true }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-server-validation-to-form-control.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-server-validation-to-form-control.controller.ts index 7e91dfdd14c9..0c2593fd7844 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-server-validation-to-form-control.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/bind-server-validation-to-form-control.controller.ts @@ -43,7 +43,7 @@ export class UmbBindServerValidationToFormControl extends UmbControllerBase { this.#context = context; this.observe( - context.messages?.messagesOfNotTypeAndPath('client', dataPath), + context?.messages?.messagesOfNotTypeAndPath('client', dataPath), (messages) => { this.#messages = messages ?? []; this.#isValid = this.#messages.length === 0; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts index a0935d81951b..67bc5523ec78 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/form-control-validator.controller.ts @@ -28,9 +28,9 @@ export class UmbFormControlValidator extends UmbControllerBase implements UmbVal this.#context.removeValidator(this); } this.#context = context; - context.addValidator(this); + context?.addValidator(this); // If we have a message already, then un-pristine the control: - if (dataPath && context.messages.getHasMessagesOfPathAndDescendant(dataPath)) { + if (dataPath && context?.messages.getHasMessagesOfPathAndDescendant(dataPath)) { formControl.pristine = false; } }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/observe-validation-state.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/observe-validation-state.controller.ts index 798f63d6c02e..a6e10e153662 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/observe-validation-state.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/observe-validation-state.controller.ts @@ -14,7 +14,7 @@ export class UmbObserveValidationStateController extends UmbControllerBase { super(host, controllerAlias ?? 'observeValidationState_' + dataPath); if (dataPath) { this.consumeContext(UMB_VALIDATION_CONTEXT, (context) => { - this.observe(context.messages.hasMessagesOfPathAndDescendant(dataPath), callback, ObserveSymbol); + this.observe(context?.messages.hasMessagesOfPathAndDescendant(dataPath), callback, ObserveSymbol); }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts index 4eb5443df269..821324469ad6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/controllers/validation.controller.ts @@ -191,7 +191,7 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal * @param {UmbValidationController} parent - The parent validation context to inherit from. * @param {string} dataPath - The data path to bind this validation context to. */ - inheritFrom(parent: UmbValidationController, dataPath: string): void { + inheritFrom(parent: UmbValidationController | undefined, dataPath: string): void { if (this.#parent) { this.#parent.removeValidator(this); } @@ -205,7 +205,7 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal // @deprecated - Will be removed in v.17 this.observe( - parent.translationDataOf(dataPath), + parent?.translationDataOf(dataPath), (data) => { this.setTranslationData(data); }, @@ -213,8 +213,12 @@ export class UmbValidationController extends UmbControllerBase implements UmbVal ); this.observe( - parent.messages.messagesOfPathAndDescendant(dataPath), + parent?.messages.messagesOfPathAndDescendant(dataPath), (msgs) => { + if (!msgs) { + this.messages.clear(); + return; + } this.messages.initiateChange(); if (this.#parentMessages) { // Remove the local messages that does not exist in the parent anymore: diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/translators/validation-path-translator-base.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/translators/validation-path-translator-base.controller.ts index 9e84e0079443..a80c8ceeb557 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/translators/validation-path-translator-base.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/translators/validation-path-translator-base.controller.ts @@ -16,7 +16,7 @@ export abstract class UmbValidationPathTranslatorBase this.consumeContext(UMB_VALIDATION_CONTEXT, (context) => { this._context?.removeTranslator(this); this._context = context; - context.addTranslator(this); + context?.addTranslator(this); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-menu-breadcrumb/workspace-menu-breadcrumb.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-menu-breadcrumb/workspace-menu-breadcrumb.element.ts index fc7df3797e6d..ffae6d8183d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-menu-breadcrumb/workspace-menu-breadcrumb.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-menu-breadcrumb/workspace-menu-breadcrumb.element.ts @@ -32,9 +32,9 @@ export class UmbWorkspaceBreadcrumbElement extends UmbLitElement { }); // TODO: set up context token - this.consumeContext('UmbMenuStructureWorkspaceContext', (instance) => { + this.consumeContext('UmbMenuStructureWorkspaceContext', (instance) => { // TODO: get the correct interface from the context token - this.#structureContext = instance as UmbMenuStructureWorkspaceContext; + this.#structureContext = instance; this.#observeStructure(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts index 68dd87052a91..b55417012198 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-breadcrumb/workspace-variant-menu-breadcrumb/workspace-variant-menu-breadcrumb.element.ts @@ -66,7 +66,7 @@ export class UmbWorkspaceVariantMenuBreadcrumbElement extends UmbLitElement { } #observeDefaultCulture() { - this.observe(this.#appLanguageContext!.appDefaultLanguage, (value) => { + this.observe(this.#appLanguageContext?.appDefaultLanguage, (value) => { this._appDefaultCulture = value?.unique; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts index 897d37068f64..b1f5f733a267 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-entity-action-menu/workspace-entity-action-menu.element.ts @@ -26,7 +26,7 @@ export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement { this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this.observe(this._workspaceContext.unique, (unique) => { + this.observe(this._workspaceContext?.unique, (unique) => { this._unique = unique; // TODO: the context does not have an observable for the entity type, so we need to use the // getEntityType method until we can add an observable for it. diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts index b293cf725641..912b4f3f65e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts @@ -40,7 +40,7 @@ export class UmbWorkspaceFooterLayoutElement extends UmbLitElement { constructor() { super(); this.consumeContext(UMB_SUBMITTABLE_WORKSPACE_CONTEXT, (context) => { - this._isNew = context.getIsNew(); + this._isNew = context?.getIsNew(); }); this.consumeContext(UMB_MODAL_CONTEXT, (context) => { this._modalContext = context; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts index 89eaed83dfdd..4cb31ea938c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts @@ -71,22 +71,20 @@ export class UmbWorkspaceSplitViewVariantSelectorElement< this.consumeContext(UMB_WORKSPACE_SPLIT_VIEW_CONTEXT, (instance) => { this.#splitViewContext = instance; - const workspaceContext = - this.#splitViewContext.getWorkspaceContext() as unknown as UmbVariantDatasetWorkspaceContext; - if (!workspaceContext) throw new Error('Split View Workspace context not found'); + const workspaceContext = this.#splitViewContext?.getWorkspaceContext(); this.#observeVariants(workspaceContext); this.#observeActiveVariants(workspaceContext); this.#observeCurrentVariant(); this.observe( - workspaceContext.variesBySegment, + workspaceContext?.variesBySegment, (value) => (this._variesBySegment = value ?? false), 'umbObserveVariesBySegment', ); this.observe( - workspaceContext.variesByCulture, + workspaceContext?.variesByCulture, (value) => (this._variesByCulture = value ?? false), 'umbObserveVariesByCulture', ); @@ -99,11 +97,11 @@ export class UmbWorkspaceSplitViewVariantSelectorElement< }); } - async #observeVariants(workspaceContext: UmbVariantDatasetWorkspaceContext) { + async #observeVariants(workspaceContext?: UmbVariantDatasetWorkspaceContext) { this.observe( - workspaceContext.variantOptions, + workspaceContext?.variantOptions, (variantOptions) => { - this._variantOptions = (variantOptions as Array).sort(this._variantSorter); + this._variantOptions = ((variantOptions ?? []) as VariantOptionModelType[]).sort(this._variantSorter); this._cultureVariantOptions = this._variantOptions.filter((variant) => variant.segment === null); this.#setReadOnlyCultures(workspaceContext); }, @@ -111,9 +109,9 @@ export class UmbWorkspaceSplitViewVariantSelectorElement< ); } - async #observeActiveVariants(workspaceContext: UmbVariantDatasetWorkspaceContext) { + async #observeActiveVariants(workspaceContext?: UmbVariantDatasetWorkspaceContext) { this.observe( - workspaceContext.splitView.activeVariantsInfo, + workspaceContext?.splitView.activeVariantsInfo, (activeVariants) => { if (activeVariants) { this._activeVariants = activeVariants.map((variant) => UmbVariantId.Create(variant)); @@ -200,10 +198,14 @@ export class UmbWorkspaceSplitViewVariantSelectorElement< return this._variantOptions.length > 1; } - #setReadOnlyCultures(workspaceContext: UmbVariantDatasetWorkspaceContext) { - this._readOnlyCultures = this._variantOptions - .filter((variant) => workspaceContext.readOnlyGuard.getIsPermittedForVariant(UmbVariantId.Create(variant))) - .map((variant) => variant.culture); + #setReadOnlyCultures(workspaceContext?: UmbVariantDatasetWorkspaceContext) { + if (workspaceContext) { + this._readOnlyCultures = this._variantOptions + .filter((variant) => workspaceContext.readOnlyGuard.getIsPermittedForVariant(UmbVariantId.Create(variant))) + .map((variant) => variant.culture); + } else { + this._readOnlyCultures = []; + } } #onPopoverToggle(event: ToggleEvent) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts index 9e9d3cc226d9..e47996a8cf90 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts @@ -8,7 +8,7 @@ import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property import { UMB_MARK_ATTRIBUTE_NAME } from '@umbraco-cms/backoffice/const'; import type { UmbValidationController } from '@umbraco-cms/backoffice/validation'; -export class UmbWorkspaceSplitViewContext extends UmbContextBase { +export class UmbWorkspaceSplitViewContext extends UmbContextBase { // #variantVariantValidationContext?: UmbValidationController; #workspaceContext?: typeof UMB_VARIANT_WORKSPACE_CONTEXT.TYPE; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts index 71fe2260540b..bc7c58f7970c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts @@ -22,7 +22,11 @@ export class UmbWorkspaceAliasCondition if (permissionCheck !== undefined) { this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => { - this.permitted = permissionCheck!(context); + if (context) { + this.permitted = permissionCheck!(context); + } else { + this.permitted = false; + } }); } else { throw new Error( diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts index 3519d57fef35..fa1e059ae0cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-is-new.condition.ts @@ -16,7 +16,7 @@ export class UmbWorkspaceEntityIsNewCondition this.consumeContext(UMB_SUBMITTABLE_WORKSPACE_CONTEXT, (context) => { this.observe( - context.isNew, + context?.isNew, (isNew) => { if (isNew !== undefined) { // Check if equal to match, if match not set it defaults to true. diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts index d020386933e3..73f0dc0ecfd8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts @@ -11,7 +11,7 @@ export class UmbWorkspaceEntityTypeCondition constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => { - this.permitted = context.getEntityType().toLowerCase() === this.config.match.toLowerCase(); + this.permitted = context?.getEntityType().toLowerCase() === this.config.match.toLowerCase(); }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts index 9b4b33b05acf..14262b5877e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace-base.ts @@ -99,11 +99,11 @@ export abstract class UmbEntityDetailWorkspaceContextBase< this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => { this.#eventContext = context; - this.#eventContext.removeEventListener( + this.#eventContext?.removeEventListener( UmbEntityUpdatedEvent.TYPE, this.#onEntityUpdatedEvent as unknown as EventListener, ); - this.#eventContext.addEventListener( + this.#eventContext?.addEventListener( UmbEntityUpdatedEvent.TYPE, this.#onEntityUpdatedEvent as unknown as EventListener, ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts index 4b2296a64dd7..e98b9f46b4d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts @@ -27,7 +27,7 @@ export class UmbEntityDetailWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_ENTITY_DETAIL_WORKSPACE_CONTEXT, (context) => { this.#context = context; this.observe(this.#context?.entityType, (entityType) => (this._entityType = entityType)); - this.observe(this.#context?.loading.isOn, (isLoading) => (this._isLoading = isLoading)); + this.observe(this.#context?.loading.isOn, (isLoading) => (this._isLoading = isLoading ?? false)); this.observe(this.#context?.data, (data) => (this._exists = !!data)); this.observe(this.#context?.isNew, (isNew) => (this._isNew = isNew)); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/default/default-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/default/default-workspace.context.ts index f07f1c649c9e..00a1906991e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/default/default-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/default/default-workspace.context.ts @@ -1,14 +1,11 @@ import { UMB_WORKSPACE_CONTEXT } from '../../workspace.context-token.js'; import type { UmbWorkspaceContext } from '../../workspace-context.interface.js'; +import type { ManifestWorkspace } from '../../extensions/types.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbEntityContext, type UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; -import type { ManifestWorkspace } from '../../extensions/types.js'; -export class UmbDefaultWorkspaceContext - extends UmbContextBase - implements UmbWorkspaceContext -{ +export class UmbDefaultWorkspaceContext extends UmbContextBase implements UmbWorkspaceContext { public workspaceAlias!: string; #entityContext = new UmbEntityContext(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts index f018231dd19c..be57abe1df23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/submittable/submittable-workspace-context-base.ts @@ -10,7 +10,7 @@ import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; import type { UmbValidationController } from '@umbraco-cms/backoffice/validation'; export abstract class UmbSubmittableWorkspaceContextBase - extends UmbContextBase> + extends UmbContextBase implements UmbSubmittableWorkspaceContext { public readonly workspaceAlias: string; @@ -52,7 +52,7 @@ export abstract class UmbSubmittableWorkspaceContextBase this.workspaceAlias = workspaceAlias; // TODO: Consider if we can move this consumption to #resolveSubmit, just as a getContext, but it depends if others use the modalContext prop.. [NL] this.consumeContext(UMB_MODAL_CONTEXT, (context) => { - (this.modalContext as UmbModalContext) = context; + (this.modalContext as UmbModalContext | undefined) = context; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context.interface.ts index 941c7a064ca5..5ed6cf16728c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context.interface.ts @@ -1,8 +1,7 @@ +import type { UmbContextMinimal } from '@umbraco-cms/backoffice/context-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; -export interface UmbWorkspaceContext extends UmbApi { +export interface UmbWorkspaceContext extends UmbApi, UmbContextMinimal { readonly workspaceAlias: string; getEntityType(): string; - // TODO: Consider if its more right to make a new interface for UmbEntityWorkspaceContext, cause this on might be intended for the extension type Workspace Context - // TODO: add entityType observable } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts index 91267ee7fcd3..66fd7c095664 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-property-dataset/invariant-workspace-property-dataset-context.ts @@ -16,7 +16,7 @@ import { UmbBooleanState, type Observable } from '@umbraco-cms/backoffice/observ export class UmbInvariantWorkspacePropertyDatasetContext< WorkspaceType extends UmbInvariantDatasetWorkspaceContext = UmbInvariantDatasetWorkspaceContext, > - extends UmbContextBase + extends UmbContextBase implements UmbPropertyDatasetContext, UmbNameablePropertyDatasetContext { #readOnly = new UmbBooleanState(false); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts index 49ede5f33974..d198b414baa2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace-editor.element.ts @@ -11,7 +11,7 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement { super(); this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, (workspaceContext) => { - workspaceContext.createPropertyDatasetContext(this); + workspaceContext?.createPropertyDatasetContext(this); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/info-app/document-history-workspace-info-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/info-app/document-history-workspace-info-app.element.ts index a328dd8540ec..8bec97586c62 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/info-app/document-history-workspace-info-app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/audit-log/info-app/document-history-workspace-info-app.element.ts @@ -45,7 +45,7 @@ export class UmbDocumentHistoryWorkspaceInfoAppElement extends UmbLitElement { this.observe(this.#pagination.totalPages, (number) => (this._totalPages = number)); this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => { - context.addEventListener(UmbRequestReloadStructureForEntityEvent.TYPE, () => { + context?.addEventListener(UmbRequestReloadStructureForEntityEvent.TYPE, () => { this.#requestAuditLogs(); }); }); @@ -62,7 +62,8 @@ export class UmbDocumentHistoryWorkspaceInfoAppElement extends UmbLitElement { } async #requestAuditLogs() { - const unique = this.#workspaceContext?.getUnique(); + if (!this.#workspaceContext) return; + const unique = this.#workspaceContext.getUnique(); if (!unique) throw new Error('Document unique is required'); const { data } = await this.#auditLogRepository.requestAuditLog({ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts index 9a56dfca3507..61dc46fca310 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/action/create-document-collection-action.element.ts @@ -36,16 +36,16 @@ export class UmbCreateDocumentCollectionActionElement extends UmbLitElement { super(); this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (workspaceContext) => { - this.observe(workspaceContext.unique, (unique) => { + this.observe(workspaceContext?.unique, (unique) => { this._documentUnique = unique; }); - this.observe(workspaceContext.contentTypeUnique, (documentTypeUnique) => { + this.observe(workspaceContext?.contentTypeUnique, (documentTypeUnique) => { this._documentTypeUnique = documentTypeUnique; }); }); this.consumeContext(UMB_DOCUMENT_COLLECTION_CONTEXT, (collectionContext) => { - this.observe(collectionContext.workspacePathBuilder, (builder) => { + this.observe(collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts index ab57b821e275..e79fc9d102d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/grid/document-grid-collection-view.element.ts @@ -33,9 +33,9 @@ export class UmbDocumentGridCollectionViewElement extends UmbLitElement { this.consumeContext(UMB_DOCUMENT_COLLECTION_CONTEXT, (collectionContext) => { this.#collectionContext = collectionContext; - collectionContext.setupView(this); + collectionContext?.setupView(this); this.observe( - collectionContext.workspacePathBuilder, + collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts index d06973e3a7cc..d681550252d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/document-table-collection-view.element.ts @@ -70,9 +70,9 @@ export class UmbDocumentTableCollectionViewElement extends UmbLitElement { this.consumeContext(UMB_DOCUMENT_COLLECTION_CONTEXT, (collectionContext) => { this.#collectionContext = collectionContext; - collectionContext.setupView(this); + collectionContext?.setupView(this); this.observe( - collectionContext.workspacePathBuilder, + collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; if (this.#collectionContext) { 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 5179c90df82f..3bb91266f18d 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 @@ -10,10 +10,7 @@ import { tryExecute } from '@umbraco-cms/backoffice/resources'; * A context for fetching and caching the document configuration. * @internal */ -export class UmbDocumentConfigurationContext - extends UmbContextBase - implements UmbApi -{ +export class UmbDocumentConfigurationContext extends UmbContextBase implements UmbApi { /** * The cached document configuration. */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts index 58699b7d598b..cee91c4b0b51 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/item/document-item-data-resolver.ts @@ -48,17 +48,17 @@ export class UmbDocumentItemDataResolver { - this.#propertyDataSetCulture = context.getVariantId(); + this.#propertyDataSetCulture = context?.getVariantId(); this.#setVariantAwareValues(); }).asPromise({ preventTimeout: true }), this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (context) => { - this.observe(context.appLanguageCulture, (culture) => { + this.observe(context?.appLanguageCulture, (culture) => { this.#appCulture = culture; this.#setVariantAwareValues(); }); - this.observe(context.appDefaultLanguage, (value) => { + this.observe(context?.appDefaultLanguage, (value) => { this.#defaultCulture = value?.unique; this.#setVariantAwareValues(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts index 836a62ace4a4..07754f44fe35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/workspace-action/save-and-publish.action.ts @@ -22,7 +22,7 @@ export class UmbDocumentSaveAndPublishWorkspaceAction extends UmbWorkspaceAction alias: 'Umb.Condition.UserPermission.Document', allOf: [UMB_USER_PERMISSION_DOCUMENT_UPDATE, UMB_USER_PERMISSION_DOCUMENT_PUBLISH], }, - onChange: (permitted) => { + onChange: (permitted: boolean) => { if (permitted) { this.enable(); } else { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/workspace-context/document-publishing.workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/workspace-context/document-publishing.workspace-context.ts index 11b2f5b762c6..5e57d9d4cd97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/workspace-context/document-publishing.workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/workspace-context/document-publishing.workspace-context.ts @@ -27,7 +27,7 @@ import { DocumentVariantStateModel } from '@umbraco-cms/backoffice/external/back import type { UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -export class UmbDocumentPublishingWorkspaceContext extends UmbContextBase { +export class UmbDocumentPublishingWorkspaceContext extends UmbContextBase { /** * Manages the pending changes for the published document. * @memberof UmbDocumentPublishingWorkspaceContext @@ -424,7 +424,10 @@ export class UmbDocumentPublishingWorkspaceContext extends UmbContextBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts index bdd03fd19013..349b11eef5c5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/recycle-bin/allow-document-recycle-bin.condition.ts @@ -15,7 +15,7 @@ export class UmbAllowDocumentRecycleBinCurrentUserCondition super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.hasDocumentRootAccess, (hasAccess) => { + this.observe(context?.hasDocumentRootAccess, (hasAccess) => { this.permitted = hasAccess === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/modal/rollback-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/modal/rollback-modal.element.ts index 82fab6b2c2b0..56fa6371a355 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/modal/rollback-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/rollback/modal/rollback-modal.element.ts @@ -73,21 +73,22 @@ export class UmbRollbackModalElement extends UmbModalBaseElement { - this.#currentDatasetCulture = instance.getVariantId().culture ?? undefined; + this.#currentDatasetCulture = instance?.getVariantId().culture ?? undefined; this.#selectCulture(); }); this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (instance) => { - this.#currentAppCulture = instance.getAppCulture(); + this.#currentAppCulture = instance?.getAppCulture(); this.#selectCulture(); }); this.consumeContext(UMB_ENTITY_CONTEXT, async (instance) => { + if (!instance) return; if (instance.getEntityType() !== UMB_DOCUMENT_ENTITY_TYPE) { throw new Error(`Entity type is not ${UMB_DOCUMENT_ENTITY_TYPE}`); } - const unique = instance?.getUnique(); + const unique = instance.getUnique(); if (!unique) { throw new Error('Document unique is not set'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts index 7f190c28c8f6..b7dc6c2395ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/search/document-search-result-item.element.ts @@ -36,15 +36,15 @@ export class UmbDocumentSearchResultItemElement extends UmbLitElement { }); } - #observeAppCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE) { - this.observe(context.appLanguageCulture, (value) => { + #observeAppCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE | undefined) { + this.observe(context?.appLanguageCulture, (value) => { this._currentCulture = value; this._variant = this.#getVariant(value); }); } - #observeDefaultCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE) { - this.observe(context.appDefaultLanguage, (value) => { + #observeDefaultCulture(context: typeof UMB_APP_LANGUAGE_CONTEXT.TYPE | undefined) { + this.observe(context?.appDefaultLanguage, (value) => { this._defaultCulture = value?.unique; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/document-tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/document-tree.context.ts index 63c08e1a0cef..1348aa1bfc2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/document-tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/tree/document-tree.context.ts @@ -16,7 +16,7 @@ export class UmbDocumentTreeContext extends UmbDefaultTreeContext< super(host); this.consumeContext(UMB_CONTENT_PROPERTY_CONTEXT, (context) => { - this.observe(context.dataType, (value) => { + this.observe(context?.dataType, (value) => { this.updateAdditionalRequestArgs({ dataType: value }); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/url/info-app/document-links-workspace-info-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/url/info-app/document-links-workspace-info-app.element.ts index bfd6d56d45c2..f0630d09a77c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/url/info-app/document-links-workspace-info-app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/url/info-app/document-links-workspace-info-app.element.ts @@ -51,12 +51,12 @@ export class UmbDocumentLinksWorkspaceInfoAppElement extends UmbLitElement { this.consumeContext(UMB_ACTION_EVENT_CONTEXT, (context) => { this.#eventContext = context; - this.#eventContext.removeEventListener( + this.#eventContext?.removeEventListener( UmbRequestReloadStructureForEntityEvent.TYPE, this.#onReloadRequest as unknown as EventListener, ); - this.#eventContext.addEventListener( + this.#eventContext?.addEventListener( UmbRequestReloadStructureForEntityEvent.TYPE, this.#onReloadRequest as unknown as EventListener, ); @@ -64,24 +64,32 @@ export class UmbDocumentLinksWorkspaceInfoAppElement extends UmbLitElement { this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { this.#documentWorkspaceContext = context; - this.observe(observeMultiple([context.isNew, context.unique]), ([isNew, unique]) => { - if (!unique) return; - this._isNew = isNew === true; - - if (unique !== this._unique) { - this._unique = unique; - this.#requestUrls(); - } - }); + if (context) { + this.observe( + observeMultiple([context.isNew, context.unique]), + ([isNew, unique]) => { + if (!unique) return; + this._isNew = isNew === true; + + if (unique !== this._unique) { + this._unique = unique; + this.#requestUrls(); + } + }, + 'observeWorkspaceState', + ); + } else { + this.removeUmbControllerByAlias('observeWorkspaceState'); + } - this.observe(context.variantOptions, (variantOptions) => { + this.observe(context?.variantOptions, (variantOptions) => { this._variantOptions = variantOptions; this.#setLinks(); }); }); this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (instance) => { - this.observe(instance.appDefaultLanguage, (value) => { + this.observe(instance?.appDefaultLanguage, (value) => { this._defaultCulture = value?.unique; this.#setLinks(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts index 2332d0d03bff..e3dd9a7bdc27 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document-property-value/conditions/document-property-value-user-permission.condition.ts @@ -4,36 +4,24 @@ import { isDocumentPropertyValueUserPermission } from './utils.js'; import { UMB_CURRENT_USER_CONTEXT } from '@umbraco-cms/backoffice/current-user'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; - -// Do not export - for internal use only -type UmbOnChangeCallbackType = (permitted: boolean) => void; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; export class UmbDocumentPropertyValueUserPermissionCondition - extends UmbControllerBase + extends UmbConditionBase implements UmbExtensionCondition { - config: UmbDocumentPropertyValueUserPermissionConditionConfig; - permitted = false; - #documentPropertyValuePermissions: Array = []; #fallbackPermissions: string[] = []; - #onChange: UmbOnChangeCallbackType; constructor( host: UmbControllerHost, - args: UmbConditionControllerArguments< - UmbDocumentPropertyValueUserPermissionConditionConfig, - UmbOnChangeCallbackType - >, + args: UmbConditionControllerArguments, ) { - super(host); - this.config = args.config; - this.#onChange = args.onChange; + super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.currentUser, + context?.currentUser, (currentUser) => { this.#documentPropertyValuePermissions = currentUser?.permissions?.filter(isDocumentPropertyValueUserPermission) || []; @@ -94,11 +82,7 @@ export class UmbDocumentPropertyValueUserPermissionCondition oneOfPermitted = false; } - const permitted = allOfPermitted && oneOfPermitted; - if (permitted === this.permitted) return; - - this.permitted = permitted; - this.#onChange(permitted); + this.permitted = allOfPermitted && oneOfPermitted; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.test.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.test.ts index f69fdb83751e..667213f7eaef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.test.ts @@ -62,6 +62,8 @@ describe('UmbDocumentUserPermissionCondition', () => { // This entity does not have any ancestors. hostElement.setEntityAncestors([]); + let callbackCount = 0; + // We expect to find the read permission on the current entity condition = new UmbDocumentUserPermissionCondition(hostElement, { host: hostElement, @@ -69,9 +71,13 @@ describe('UmbDocumentUserPermissionCondition', () => { alias: UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, allOf: [UMB_USER_PERMISSION_DOCUMENT_READ], }, - onChange: (permitted) => { - expect(permitted).to.be.true; - done(); + onChange: () => { + callbackCount++; + if (callbackCount === 1) { + expect(condition.permitted).to.be.true; + condition.hostDisconnected(); + done(); + } }, }); }); @@ -88,6 +94,8 @@ describe('UmbDocumentUserPermissionCondition', () => { // Sets the ancestors of the current entity. These are the ancestors that will be checked for permissions. hostElement.setEntityAncestors([{ unique: 'permissions-document-id', entityType: UMB_DOCUMENT_ENTITY_TYPE }]); + let callbackCount = 0; + // We expect to find the read permission on the ancestor condition = new UmbDocumentUserPermissionCondition(hostElement, { host: hostElement, @@ -95,9 +103,13 @@ describe('UmbDocumentUserPermissionCondition', () => { alias: UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, allOf: [UMB_USER_PERMISSION_DOCUMENT_READ], }, - onChange: (permitted) => { - expect(permitted).to.be.true; - done(); + onChange: () => { + callbackCount++; + if (callbackCount === 1) { + expect(condition.permitted).to.be.true; + condition.hostDisconnected(); + done(); + } }, }); }); @@ -117,6 +129,8 @@ describe('UmbDocumentUserPermissionCondition', () => { { unique: 'no-permissions-parent-document-id', entityType: UMB_DOCUMENT_ENTITY_TYPE }, ]); + let callbackCount = 0; + // We expect to find the read permission in the fallback permissions condition = new UmbDocumentUserPermissionCondition(hostElement, { host: hostElement, @@ -124,9 +138,13 @@ describe('UmbDocumentUserPermissionCondition', () => { alias: UMB_DOCUMENT_USER_PERMISSION_CONDITION_ALIAS, allOf: [UMB_USER_PERMISSION_DOCUMENT_READ], }, - onChange: (permitted) => { - expect(permitted).to.be.true; - done(); + onChange: () => { + callbackCount++; + if (callbackCount === 1) { + expect(condition.permitted).to.be.true; + condition.hostDisconnected(); + done(); + } }, }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts index a91b99689a86..86edf4971127 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/conditions/document-user-permission.condition.ts @@ -6,33 +6,27 @@ import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { DocumentPermissionPresentationModel } from '@umbraco-cms/backoffice/external/backend-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; - -// Do not export - for internal use only -type UmbOnChangeCallbackType = (permitted: boolean) => void; - -export class UmbDocumentUserPermissionCondition extends UmbControllerBase implements UmbExtensionCondition { - config: UmbDocumentUserPermissionConditionConfig; - permitted = false; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +export class UmbDocumentUserPermissionCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ #entityType: string | undefined; #unique: string | null | undefined; #documentPermissions: Array = []; #fallbackPermissions: string[] = []; - #onChange: UmbOnChangeCallbackType; #ancestors: Array = []; constructor( host: UmbControllerHost, - args: UmbConditionControllerArguments, + args: UmbConditionControllerArguments, ) { - super(host); - this.config = args.config; - this.#onChange = args.onChange; + super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.currentUser, + context?.currentUser, (currentUser) => { this.#documentPermissions = currentUser?.permissions?.filter(isDocumentUserPermission) || []; this.#fallbackPermissions = currentUser?.fallbackPermissions || []; @@ -60,7 +54,7 @@ export class UmbDocumentUserPermissionCondition extends UmbControllerBase implem this.observe( instance?.ancestors, (ancestors) => { - this.#ancestors = ancestors.map((item) => item.unique); + this.#ancestors = ancestors?.map((item) => item.unique) ?? []; this.#checkPermissions(); }, 'observeAncestors', @@ -128,11 +122,7 @@ export class UmbDocumentUserPermissionCondition extends UmbControllerBase implem oneOfPermitted = false; } - const permitted = allOfPermitted && oneOfPermitted; - if (permitted === this.permitted) return; - - this.permitted = permitted; - this.#onChange(permitted); + this.permitted = allOfPermitted && oneOfPermitted; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts index f2e3d263ddad..bacebca22708 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/user-permissions/document/input-document-granular-user-permission/input-document-granular-user-permission.element.ts @@ -50,7 +50,7 @@ export class UmbInputDocumentGranularUserPermissionElement extends UUIFormContro async #observePickedDocuments(uniques: Array) { const { asObservable } = await this.#documentItemRepository.requestItems(uniques); - this.observe(asObservable(), (items) => (this._items = items)); + this.observe(asObservable?.(), (items) => (this._items = items), 'observeItems'); } async #editGranularPermission(item: UmbDocumentItemModel) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-not-trashed/document-is-not-trashed.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-not-trashed/document-is-not-trashed.condition.ts index 95c65660d388..b6bd7f2b3b76 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-not-trashed/document-is-not-trashed.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-not-trashed/document-is-not-trashed.condition.ts @@ -15,7 +15,7 @@ export class UmbDocumentIsNotTrashedWorkspaceCondition super(host, args); this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { - this.observe(context.isTrashed, (isTrashed) => { + this.observe(context?.isTrashed, (isTrashed) => { this.permitted = isTrashed === false; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-trashed/document-is-trashed.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-trashed/document-is-trashed.condition.ts index ca9cb1a35452..30d9ee0d27c5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-trashed/document-is-trashed.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/conditions/is-trashed/document-is-trashed.condition.ts @@ -15,7 +15,7 @@ export class UmbDocumentIsTrashedWorkspaceCondition super(host, args); this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { - this.observe(context.isTrashed, (isTrashed) => { + this.observe(context?.isTrashed, (isTrashed) => { this.permitted = isTrashed === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts index 417c8addcabf..3526d0ebf0b4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace-editor.element.ts @@ -29,7 +29,7 @@ export class UmbDocumentWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (instance) => { this.#appLanguage = instance; - this.observe(this.#appLanguage.appLanguageCulture, (appCulture) => { + this.observe(this.#appLanguage?.appLanguageCulture, (appCulture) => { this.#appCulture = appCulture; this.#generateRoutes(); }); @@ -38,7 +38,7 @@ export class UmbDocumentWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (instance) => { this.#workspaceContext = instance; this.observe( - this.#workspaceContext.variantOptions, + this.#workspaceContext?.variantOptions, (variants) => { this.#variants = variants; this.#generateRoutes(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 0878a1dd8662..e7a9f9bf722b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -89,7 +89,7 @@ export class UmbDocumentWorkspaceContext }); this.consumeContext(UMB_DOCUMENT_CONFIGURATION_CONTEXT, async (context) => { - const config = await context.getDocumentConfiguration(); + const config = await context?.getDocumentConfiguration(); const allowSegmentCreation = config?.allowNonExistingSegmentsCreation ?? false; this._variantOptionsFilter = (variantOption) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index 3297a794e3fb..4f0bfc8405e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -70,12 +70,12 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => { this.#workspaceContext = context; - this._documentTypeUnique = this.#workspaceContext.getContentTypeId()!; + this._documentTypeUnique = this.#workspaceContext?.getContentTypeId(); this.#observeContent(); }); this.consumeContext(UMB_DOCUMENT_PROPERTY_DATASET_CONTEXT, (context) => { - this.observe(context.currentVariant, (currentVariant) => { + this.observe(context?.currentVariant, (currentVariant) => { this._variant = currentVariant; }); }); 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 2d88ad8ec5d6..de3121c3dd0a 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 @@ -5,10 +5,7 @@ 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 extends UmbContextBase< - UmbHealthCheckDashboardContext, - typeof UMB_HEALTHCHECK_DASHBOARD_CONTEXT -> { +export class UmbHealthCheckDashboardContext extends UmbContextBase { #manifests: ManifestHealthCheck[] = []; set manifests(value: ManifestHealthCheck[]) { this.#manifests = value; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts index d72e5e6099d7..90ff3cf7d2e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/app-language-select.element.ts @@ -53,12 +53,12 @@ export class UmbAppLanguageSelectElement extends UmbLitElement { }); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.languages, (languages) => { + this.observe(context?.languages, (languages) => { this.#currentUserAllowedLanguages = languages; this.#checkForLanguageAccess(); }); - this.observe(context.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { + this.observe(context?.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { this.#currentUserHasAccessToAllLanguages = hasAccessToAllLanguages; this.#checkForLanguageAccess(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/conditions/language-user-permission/language-user-permission.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/language/conditions/language-user-permission/language-user-permission.condition.ts index 24c025566167..c2abc6be35d9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/conditions/language-user-permission/language-user-permission.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/conditions/language-user-permission/language-user-permission.condition.ts @@ -2,28 +2,21 @@ import type { UmbLanguageUserPermissionConditionConfig } from './types.js'; import { UMB_CURRENT_USER_CONTEXT, type UmbCurrentUserModel } from '@umbraco-cms/backoffice/current-user'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; - -// Do not export - for internal use only -type UmbOnChangeCallbackType = (permitted: boolean) => void; - -export class UmbLanguageUserPermissionCondition extends UmbControllerBase implements UmbExtensionCondition { - config: UmbLanguageUserPermissionConditionConfig; - permitted = false; - - #onChange: UmbOnChangeCallbackType; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +export class UmbLanguageUserPermissionCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ constructor( host: UmbControllerHost, - args: UmbConditionControllerArguments, + args: UmbConditionControllerArguments, ) { - super(host); - this.config = args.config; - this.#onChange = args.onChange; + super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.currentUser, + context?.currentUser, (currentUser) => { this.#check(currentUser); }, @@ -35,7 +28,6 @@ export class UmbLanguageUserPermissionCondition extends UmbControllerBase implem #check(currentUser?: UmbCurrentUserModel) { if (currentUser?.hasAccessToAllLanguages) { this.permitted = true; - this.#onChange(true); return; } const cultures = currentUser?.languages ?? []; @@ -54,11 +46,7 @@ export class UmbLanguageUserPermissionCondition extends UmbControllerBase implem oneOfPermitted = this.config.oneOf.some((verb) => cultures.includes(verb)); } - const permitted = allOfPermitted && oneOfPermitted; - if (permitted === this.permitted) return; - - this.permitted = permitted; - this.#onChange(permitted); + this.permitted = allOfPermitted && oneOfPermitted; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/conditions/multiple-app-languages/multiple-app-languages.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/language/conditions/multiple-app-languages/multiple-app-languages.condition.ts index 7025fa25ae8f..76ec709e0281 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/conditions/multiple-app-languages/multiple-app-languages.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/conditions/multiple-app-languages/multiple-app-languages.condition.ts @@ -17,9 +17,9 @@ export class UmbMultipleAppLanguageCondition this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (context) => { this.observe( - context.moreThanOneLanguage, + context?.moreThanOneLanguage, (moreThanOneLanguage) => { - this.permitted = moreThanOneLanguage; + this.permitted = moreThanOneLanguage ?? false; }, 'observeLanguages', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts index be3f908b1ffb..684686c1cf2d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts @@ -11,7 +11,7 @@ import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; // TODO: Make a store for the App Languages. // TODO: Implement default language end-point, in progress at backend team, so we can avoid getting all languages. -export class UmbAppLanguageContext extends UmbContextBase implements UmbApi { +export class UmbAppLanguageContext extends UmbContextBase implements UmbApi { #languagesResolve!: () => void; #languagesPromise = new Promise((resolve) => { this.#languagesResolve = resolve; @@ -56,19 +56,19 @@ export class UmbAppLanguageContext extends UmbContextBase // TODO: We need to ensure this request is called every time the user logs in, but this should be done somewhere across the app and not here [JOV] this.consumeContext(UMB_AUTH_CONTEXT, (authContext) => { - this.observe(authContext.isAuthorized, (isAuthorized) => { + this.observe(authContext?.isAuthorized, (isAuthorized) => { if (!isAuthorized) return; this.#requestLanguages(); }); }); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.languages, (languages) => { + this.observe(context?.languages, (languages) => { this.#currentUserAllowedLanguages = languages || []; this.#setIsReadOnly(); }); - this.observe(context.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { + this.observe(context?.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { this.#currentUserHasAccessToAllLanguages = hasAccessToAllLanguages || false; this.#setIsReadOnly(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/menu/language-menu-structure.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/menu/language-menu-structure.context.ts index 3a149c6d09fb..d41cb2dd279b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/menu/language-menu-structure.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/menu/language-menu-structure.context.ts @@ -6,7 +6,7 @@ import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbStructureItemModel } from '@umbraco-cms/backoffice/menu'; -export class UmbLanguageNavigationStructureWorkspaceContext extends UmbContextBase { +export class UmbLanguageNavigationStructureWorkspaceContext extends UmbContextBase { // TODO: figure out the correct type where we have "data" available #workspaceContext?: any; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace.context.ts index 5d83eae8ec34..569883440ffd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/permissions/language-access.workspace.context.ts @@ -6,7 +6,7 @@ import type { UmbEntityVariantOptionModel, UmbEntityVariantModel } from '@umbrac import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; -export class UmbLanguageAccessWorkspaceContext extends UmbContextBase { +export class UmbLanguageAccessWorkspaceContext extends UmbContextBase { #workspaceContext?: typeof UMB_CONTENT_WORKSPACE_CONTEXT.TYPE; #currentUserAllowedLanguages?: Array; #currentUserHasAccessToAllLanguages?: boolean; @@ -17,19 +17,19 @@ export class UmbLanguageAccessWorkspaceContext extends UmbContextBase { this.#workspaceContext = instance; - this.observe(instance.variantOptions, (variantOptions) => { + this.observe(instance?.variantOptions, (variantOptions) => { this.#variantOptions = variantOptions; this.#checkForLanguageAccess(); }); }); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.languages, (languages) => { + this.observe(context?.languages, (languages) => { this.#currentUserAllowedLanguages = languages; this.#checkForLanguageAccess(); }); - this.observe(context.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { + this.observe(context?.hasAccessToAllLanguages, (hasAccessToAllLanguages) => { this.#currentUserHasAccessToAllLanguages = hasAccessToAllLanguages; this.#checkForLanguageAccess(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts index 2dedb9087e09..9eb953093c6f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace-editor.element.ts @@ -15,7 +15,7 @@ export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_LANGUAGE_WORKSPACE_CONTEXT, (context) => { this.#workspaceContext = context; - this.observe(this.#workspaceContext.isNew, (isNew) => (this._isNew = isNew)); + this.observe(this.#workspaceContext?.isNew, (isNew) => (this._isNew = isNew)); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/views/language-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/views/language-details-workspace-view.element.ts index 61173d578745..b5e2674a886c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/views/language-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/views/language-details-workspace-view.element.ts @@ -34,7 +34,7 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement implem this.consumeContext(UMB_LANGUAGE_WORKSPACE_CONTEXT, (instance) => { this.#languageWorkspaceContext = instance; - this.observe(this.#languageWorkspaceContext.data, (language) => { + this.observe(this.#languageWorkspaceContext?.data, (language) => { this._language = language; /* Store the initial value of the default language. @@ -46,7 +46,7 @@ export class UmbLanguageDetailsWorkspaceViewElement extends UmbLitElement implem } }); - this.observe(this.#languageWorkspaceContext.isNew, (isNew) => { + this.observe(this.#languageWorkspaceContext?.isNew, (isNew) => { this._isNew = isNew; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context-token.ts index bb3bf53156da..e34320c1504b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/workspace/logviewer-workspace.context-token.ts @@ -1,6 +1,7 @@ import type { UmbLogViewerWorkspaceContext } from './logviewer-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -export const UMB_APP_LOG_VIEWER_CONTEXT = new UmbContextToken( - 'UmbLogViewerWorkspaceContext', -); +export const UMB_APP_LOG_VIEWER_CONTEXT = new UmbContextToken< + UmbLogViewerWorkspaceContext, + UmbLogViewerWorkspaceContext +>('UmbLogViewerWorkspaceContext'); 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 664927d4a69d..030360d083cf 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 @@ -27,10 +27,7 @@ export interface LogViewerDateRange { } // TODO: Revisit usage of workspace for this case... -export class UmbLogViewerWorkspaceContext - extends UmbContextBase - implements UmbWorkspaceContext -{ +export class UmbLogViewerWorkspaceContext extends UmbContextBase implements UmbWorkspaceContext { public readonly workspaceAlias: string = 'Umb.Workspace.LogViewer'; #repository: UmbLogViewerRepository; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/imaging.store.ts b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/imaging.store.ts index 5bff323f4fd7..8b4bf068bd37 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/imaging/imaging.store.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/imaging/imaging.store.ts @@ -4,7 +4,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -export class UmbImagingStore extends UmbContextBase implements UmbApi { +export class UmbImagingStore extends UmbContextBase implements UmbApi { #data; constructor(host: UmbControllerHost) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts index 0e05d732fca7..26d6b70db832 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/action/create-media-collection-action.element.ts @@ -36,17 +36,17 @@ export class UmbCreateMediaCollectionActionElement extends UmbLitElement { super(); this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (workspaceContext) => { - this.observe(workspaceContext.unique, (unique) => { + this.observe(workspaceContext?.unique, (unique) => { this._mediaUnique = unique; }); - this.observe(workspaceContext.contentTypeUnique, (mediaTypeUnique) => { + this.observe(workspaceContext?.contentTypeUnique, (mediaTypeUnique) => { this._mediaTypeUnique = mediaTypeUnique; }); }); this.consumeContext(UMB_MEDIA_COLLECTION_CONTEXT, (collectionContext) => { - this.observe(collectionContext.workspacePathBuilder, (builder) => { + this.observe(collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts index 76449134c9b8..75cc8be0a0da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/media-collection.element.ts @@ -26,7 +26,7 @@ export class UmbMediaCollectionElement extends UmbCollectionDefaultElement { }); this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (instance) => { - this.observe(instance.unique, (unique) => { + this.observe(instance?.unique, (unique) => { this._unique = unique ?? null; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts index 8fbd4fa2d513..141443fd196b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/grid/media-grid-collection-view.element.ts @@ -28,9 +28,9 @@ export class UmbMediaGridCollectionViewElement extends UmbLitElement { super(); this.consumeContext(UMB_MEDIA_COLLECTION_CONTEXT, (collectionContext) => { this.#collectionContext = collectionContext; - collectionContext.setupView(this); + collectionContext?.setupView(this); this.observe( - collectionContext.workspacePathBuilder, + collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index 9b295b2455c8..d7b59b22eda6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -59,9 +59,9 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { this.consumeContext(UMB_MEDIA_COLLECTION_CONTEXT, (collectionContext) => { this.#collectionContext = collectionContext; this.#observeCollectionContext(); - collectionContext.setupView(this); + collectionContext?.setupView(this); this.observe( - collectionContext.workspacePathBuilder, + collectionContext?.workspacePathBuilder, (builder) => { this._workspacePathBuilder = builder; this.#createTableItems(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts index 771b7d4860a1..f7a186fe9737 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-image-cropper/image-cropper-field.element.ts @@ -89,7 +89,7 @@ export class UmbInputImageCropperFieldElement extends UmbLitElement { super(); this.consumeContext(UMB_SERVER_CONTEXT, (context) => { - this._serverUrl = context.getServerUrl(); + this._serverUrl = context?.getServerUrl() ?? ''; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.element.ts index d00c85dd79c4..020dcd75f1d3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.element.ts @@ -67,7 +67,7 @@ export class UmbInputUploadFieldElement extends UmbLitElement { super(); this.consumeContext(UMB_SERVER_CONTEXT, (context) => { - this._serverUrl = context.getServerUrl(); + this._serverUrl = context?.getServerUrl() ?? ''; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/media-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/media-picker-modal.element.ts index 4704033a0487..8afae17b74ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/media-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/modals/media-picker/media-picker-modal.element.ts @@ -81,7 +81,7 @@ export class UmbMediaPickerModalElement extends UmbModalBaseElement { - this.observe(context.dataType, (dataType) => { + this.observe(context?.dataType, (dataType) => { this.#dataType = dataType; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.element.ts index be0ffd1bb9a9..d2e5d0a576bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.element.ts @@ -91,8 +91,8 @@ export class UmbPropertyEditorUIMediaPickerElement super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this.observe(context.alias, (alias) => (this._alias = alias)); - this.observe(context.variantId, (variantId) => (this._variantId = variantId?.toString() || 'invariant')); + this.observe(context?.alias, (alias) => (this._alias = alias)); + this.observe(context?.variantId, (variantId) => (this._variantId = variantId?.toString() || 'invariant')); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts index ca5f74bda243..6ecbbd20ede2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/recycle-bin/allow-media-recycle-bin.condition.ts @@ -15,7 +15,7 @@ export class UmbAllowMediaRecycleBinCurrentUserCondition super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.hasMediaRootAccess, (hasAccess) => { + this.observe(context?.hasMediaRootAccess, (hasAccess) => { this.permitted = hasAccess === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree.context.ts index 586166120627..ad3f204481c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/tree/media-tree.context.ts @@ -12,7 +12,7 @@ export class UmbMediaTreeContext extends UmbDefaultTreeContext< super(host); this.consumeContext(UMB_CONTENT_PROPERTY_CONTEXT, (context) => { - this.observe(context.dataType, (value) => { + this.observe(context?.dataType, (value) => { this.updateAdditionalRequestArgs({ dataType: value }); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts index 4dce9bd32ac2..0dd30bbea2ae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/views/info/media-workspace-view-info.element.ts @@ -66,13 +66,14 @@ export class UmbMediaWorkspaceViewInfoElement extends UmbLitElement { this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (context) => { this.#workspaceContext = context; - this._mediaTypeUnique = this.#workspaceContext.getContentTypeId()!; + this._mediaTypeUnique = context?.getContentTypeId(); this.#getData(); this.#observeContent(); }); } async #getData() { + if (!this.#workspaceContext) return; if (!this._mediaTypeUnique) throw new Error('Media type unique is not set'); const { data } = await this.#mediaTypeItemRepository.requestItems([this._mediaTypeUnique]); this._mediaTypeName = data?.[0].name; @@ -80,10 +81,8 @@ export class UmbMediaWorkspaceViewInfoElement extends UmbLitElement { } #observeContent() { - if (!this.#workspaceContext) return; - this.observe( - this.#workspaceContext.unique, + this.#workspaceContext?.unique, (unique) => { this._mediaUnique = unique!; }, @@ -91,10 +90,14 @@ export class UmbMediaWorkspaceViewInfoElement extends UmbLitElement { ); /** TODO: Doubt this is the right way to get the create date... */ - this.observe(this.#workspaceContext.variants, (variants) => { - this._createDate = variants?.[0]?.createDate; - this._updateDate = variants?.[0]?.updateDate; - }); + this.observe( + this.#workspaceContext?.variants, + (variants) => { + this._createDate = variants?.[0]?.createDate; + this._updateDate = variants?.[0]?.updateDate; + }, + 'observeVariants', + ); } override render() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts index 5abc7a6fa8e9..110b31e3a98b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/views/info/member-type-workspace-view-info.element.ts @@ -16,7 +16,7 @@ export class UmbMemberTypeWorkspaceViewMemberInfoElement extends UmbLitElement i this.consumeContext(UMB_MEMBER_GROUP_WORKSPACE_CONTEXT, async (context) => { this._workspaceContext = context; - this._unique = this._workspaceContext.getUnique() ?? ''; + this._unique = this._workspaceContext?.getUnique() ?? ''; }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts index 712896f81209..834e71cc1131 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member-info.element.ts @@ -58,11 +58,11 @@ export class UmbMemberWorkspaceViewMemberInfoElement extends UmbLitElement imple this.consumeContext(UMB_MEMBER_WORKSPACE_CONTEXT, async (context) => { this.#workspaceContext = context; - this.observe(this.#workspaceContext.contentTypeUnique, (unique) => (this._memberTypeUnique = unique || '')); - this.observe(this.#workspaceContext.createDate, (date) => (this._createDate = this.#setDateFormat(date))); - this.observe(this.#workspaceContext.updateDate, (date) => (this._updateDate = this.#setDateFormat(date))); - this.observe(this.#workspaceContext.unique, (unique) => (this._unique = unique || '')); - this.observe(this.#workspaceContext.kind, (kind) => (this._memberKind = kind)); + this.observe(this.#workspaceContext?.contentTypeUnique, (unique) => (this._memberTypeUnique = unique || '')); + this.observe(this.#workspaceContext?.createDate, (date) => (this._createDate = this.#setDateFormat(date))); + this.observe(this.#workspaceContext?.updateDate, (date) => (this._updateDate = this.#setDateFormat(date))); + this.observe(this.#workspaceContext?.unique, (unique) => (this._unique = unique || '')); + this.observe(this.#workspaceContext?.kind, (kind) => (this._memberKind = kind)); const memberType = (await this.#memberTypeItemRepository.requestItems([this._memberTypeUnique])).data?.[0]; if (!memberType) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts index 7e0f64532e83..4d163bc58cc0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/member/views/member/member-workspace-view-member.element.ts @@ -21,13 +21,13 @@ export class UmbMemberWorkspaceViewMemberElement extends UmbLitElement implement this.consumeContext(UMB_MEMBER_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this.observe(this._workspaceContext.isNew, (isNew) => { + this.observe(this._workspaceContext?.isNew, (isNew) => { this._isNew = !!isNew; }); }); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.hasAccessToSensitiveData, (hasAccessToSensitiveData) => { + this.observe(context?.hasAccessToSensitiveData, (hasAccessToSensitiveData) => { this._hasAccessToSensitiveData = hasAccessToSensitiveData === true; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts index 250d8702e3ce..d49b268abfff 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts @@ -69,9 +69,9 @@ export class UmbPropertyEditorUIMultiUrlPickerElement super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this._label = context.getLabel(); - this.observe(context.alias, (alias) => (this._alias = alias)); - this.observe(context.variantId, (variantId) => (this._variantId = variantId?.toString() || 'invariant')); + this._label = context?.getLabel(); + this.observe(context?.alias, (alias) => (this._alias = alias)); + this.observe(context?.variantId, (variantId) => (this._variantId = variantId?.toString() || 'invariant')); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/packages/package/repository/package.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/packages/package/repository/package.repository.ts index 0db496017c14..b1a1ee4b2c65 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/packages/package/repository/package.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/packages/package/repository/package.repository.ts @@ -10,7 +10,7 @@ import { UMB_SERVER_CONTEXT } from '@umbraco-cms/backoffice/server'; /** * A repository for Packages which mimics a tree store. - + */ export class UmbPackageRepository extends UmbControllerBase implements UmbApi { #init!: Promise; @@ -23,10 +23,12 @@ export class UmbPackageRepository extends UmbControllerBase implements UmbApi { this.#init = new Promise((resolve) => { this.consumeContext(UMB_PACKAGE_STORE_TOKEN, (instance) => { this.#packageStore = instance; - this.requestConfiguration(instance); - this.requestRootItems(instance); - this.requestPackageMigrations(instance); - resolve(); + if (instance) { + this.requestConfiguration(instance); + this.requestRootItems(instance); + this.requestPackageMigrations(instance); + resolve(); + } }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.element.ts index 0aa003204144..1d8884cad378 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.element.ts @@ -28,7 +28,7 @@ export class UmbPropertyEditorUICollectionOrderByElement extends UmbLitElement i this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (instance) => { const workspace = instance; this.observe( - await workspace.propertyValueByAlias>('includeProperties'), + await workspace?.propertyValueByAlias>('includeProperties'), (includeProperties) => { if (!includeProperties) return; const options = includeProperties.map((property) => ({ diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection.element.ts index 9f85591d2fd0..ec35f968ec5e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection.element.ts @@ -31,14 +31,14 @@ export class UmbPropertyEditorUICollectionElement extends UmbLitElement implemen super(); this.consumeContext(UMB_CONTENT_COLLECTION_WORKSPACE_CONTEXT, (workspaceContext) => { - this._collectionAlias = workspaceContext.getCollectionAlias(); + this._collectionAlias = workspaceContext?.getCollectionAlias() ?? UMB_DOCUMENT_COLLECTION_ALIAS; this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { - this.observe(propertyContext.alias, async (propertyAlias) => { + this.observe(propertyContext?.alias, async (propertyAlias) => { if (propertyAlias) { // Gets the Data Type ID for the current property. - const property = await workspaceContext.structure.getPropertyStructureByAlias(propertyAlias); - const unique = workspaceContext.getUnique(); + const property = await workspaceContext!.structure.getPropertyStructureByAlias(propertyAlias); + const unique = workspaceContext!.getUnique(); if (unique && property && this._config) { this._config.unique = unique; this._config.dataTypeId = property.dataType.unique; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.element.ts index 9f65a541f806..4fa71d9ba492 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.element.ts @@ -64,7 +64,7 @@ export class UmbPropertyEditorUIMultipleTextStringElement super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this._label = context.getLabel(); + this._label = context?.getLabel(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.element.ts index eedd195b0053..a7a1f1656daf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.element.ts @@ -49,7 +49,7 @@ export class UmbPropertyEditorUINumberElement super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this._label = context.getLabel(); + this._label = context?.getLabel(); }); this.addValidator( diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.element.ts index 83c6e64606cd..27feebb25cb5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.element.ts @@ -77,7 +77,7 @@ export class UmbPropertyEditorUISliderElement extends UmbLitElement implements U constructor() { super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this._label = context.getLabel(); + this._label = context?.getLabel(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.repository.ts index 4f79653af30e..4ab85c7c952c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/repository/detail/relation-type-detail.repository.ts @@ -36,7 +36,7 @@ export class UmbRelationTypeDetailRepository const { data, error } = await this.#detailSource.read(unique); if (data) { - this.#detailStore!.append(data); + this.#detailStore?.append(data); } return { data, error, asObservable: () => this.#detailStore!.byUnique(unique) }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/relation-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/relation-type-workspace.context.ts index 6149531eb2c3..220f5bdcf893 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/relation-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/relations/relation-types/workspace/relation-type/relation-type-workspace.context.ts @@ -7,7 +7,7 @@ import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -export class UmbRelationTypeWorkspaceContext extends UmbContextBase { +export class UmbRelationTypeWorkspaceContext extends UmbContextBase { public readonly workspaceAlias = 'Umb.Workspace.RelationType'; public readonly repository = new UmbRelationTypeDetailRepository(this); diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts index bd7d09a4728a..ecc7c2e45363 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts @@ -120,39 +120,44 @@ export abstract class UmbPropertyEditorUiRteElementBase super(); this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { - this.observe( - observeMultiple([ - this.#managerContext.blockTypes, - context.structure.variesByCulture, - context.structure.variesBySegment, - ]), - async ([blockTypes, variesByCulture, variesBySegment]) => { - if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { - // check if any of the Blocks varyByCulture or Segment and then display a warning. - const promises = await Promise.all( - blockTypes.map(async (blockType) => { - const elementType = blockType.contentElementTypeKey; - await this.#managerContext.contentTypesLoaded; - const structure = await this.#managerContext.getStructure(elementType); - if (variesByCulture === false && structure?.getVariesByCulture() === true) { - // If block varies by culture but document does not. - return true; - } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { - // If block varies by segment but document does not. - return true; - } - return false; - }), - ); - const notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; - - if (notSupportedVariantSetting) { - this.setCustomValidity('#blockEditor_blockVariantConfigurationNotSupported'); - this.checkValidity(); + if (context) { + this.observe( + observeMultiple([ + this.#managerContext.blockTypes, + context.structure.variesByCulture, + context.structure.variesBySegment, + ]), + async ([blockTypes, variesByCulture, variesBySegment]) => { + if (blockTypes.length > 0 && (variesByCulture === false || variesBySegment === false)) { + // check if any of the Blocks varyByCulture or Segment and then display a warning. + const promises = await Promise.all( + blockTypes.map(async (blockType) => { + const elementType = blockType.contentElementTypeKey; + await this.#managerContext.contentTypesLoaded; + const structure = await this.#managerContext.getStructure(elementType); + if (variesByCulture === false && structure?.getVariesByCulture() === true) { + // If block varies by culture but document does not. + return true; + } else if (variesBySegment === false && structure?.getVariesBySegment() === true) { + // If block varies by segment but document does not. + return true; + } + return false; + }), + ); + const notSupportedVariantSetting = promises.filter((x) => x === true).length > 0; + + if (notSupportedVariantSetting) { + this.setCustomValidity('#blockEditor_blockVariantConfigurationNotSupported'); + this.checkValidity(); + } } - } - }, - ); + }, + 'blockTypeConfigurationCheck', + ); + } else { + this.removeUmbControllerByAlias('blockTypeConfigurationCheck'); + } }).passContextAliasMatches(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { @@ -160,7 +165,7 @@ export abstract class UmbPropertyEditorUiRteElementBase }); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, (context) => { - this.#managerContext.setVariantId(context.getVariantId()); + this.#managerContext.setVariantId(context?.getVariantId()); }); this.observe( @@ -179,9 +184,9 @@ export abstract class UmbPropertyEditorUiRteElementBase ); } - #gotPropertyContext(context: typeof UMB_PROPERTY_CONTEXT.TYPE) { + #gotPropertyContext(context: typeof UMB_PROPERTY_CONTEXT.TYPE | undefined) { this.observe( - context.dataPath, + context?.dataPath, (dataPath) => { if (dataPath) { // Set the data path for the local validation context: @@ -240,7 +245,7 @@ export abstract class UmbPropertyEditorUiRteElementBase return; } - context.setValue(super.value); + context?.setValue(super.value); }, 'blockManagerObserver', ); diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts index b0d1ef864f95..ec160153b703 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.element.ts @@ -53,7 +53,7 @@ export class UmbPropertyEditorUITagsElement extends UmbLitElement implements Umb super(); this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this.observe(context.variantId, (id) => { + this.observe(context?.variantId, (id) => { if (id && id.culture !== undefined) { this._culture = id.culture; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts index 4bf7289934e0..21ee15a8b24d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace-editor.element.ts @@ -29,11 +29,11 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT, (workspaceContext) => { this.#workspaceContext = workspaceContext; - this.observe(this.#workspaceContext.content, (content) => { + this.observe(this.#workspaceContext?.content, (content) => { this._content = content; }); - this.observe(this.#workspaceContext.isNew, (isNew) => { + this.observe(this.#workspaceContext?.isNew, (isNew) => { this._isNew = isNew; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts index 0083ff5ee3e6..9636ec98a5f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace-editor.element.ts @@ -20,8 +20,8 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_SCRIPT_WORKSPACE_CONTEXT, (context) => { this.#context = context; - this.observe(this.#context.content, (content) => (this._content = content)); - this.observe(this.#context.isNew, (isNew) => (this._isNew = isNew)); + this.observe(this.#context?.content, (content) => (this._content = content)); + this.observe(this.#context?.isNew, (isNew) => (this._isNew = isNew)); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts index 20cb901935d8..c2cae9637889 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace-editor.element.ts @@ -15,7 +15,7 @@ export class UmbStylesheetWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_STYLESHEET_WORKSPACE_CONTEXT, (context) => { this.#context = context; - this.observe(this.#context.isNew, (isNew) => (this._isNew = isNew)); + this.observe(this.#context?.isNew, (isNew) => (this._isNew = isNew)); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-code-editor-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-code-editor-workspace-view.element.ts index 794662898c6c..2961b8ba6054 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-code-editor-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/views/code-editor/stylesheet-code-editor-workspace-view.element.ts @@ -20,7 +20,7 @@ export class UmbStylesheetCodeEditorWorkspaceViewElement extends UmbLitElement { this.consumeContext(UMB_STYLESHEET_WORKSPACE_CONTEXT, (workspaceContext) => { this.#stylesheetWorkspaceContext = workspaceContext; - this.observe(this.#stylesheetWorkspaceContext.content, (content) => { + this.observe(this.#stylesheetWorkspaceContext?.content, (content) => { this._content = content; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts index c1550dab72ab..16c27a7abb42 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/conditions/allow-delete/template-allow-delete-action.condition.ts @@ -9,7 +9,7 @@ export class UmbTemplateAllowDeleteActionCondition extends UmbConditionBase { this.observe( - context.hasChildren, + context?.hasChildren, (hasChildren) => { this.permitted = hasChildren === false; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts index 6708fa3e94d7..4350494327ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/input-template/input-template.element.ts @@ -91,10 +91,10 @@ export class UmbInputTemplateElement extends UUIFormControlMixin(UmbLitElement, async #observePickedTemplates() { this.observe( - (await this._templateItemRepository.requestItems(this._selection)).asObservable(), + (await this._templateItemRepository?.requestItems(this._selection))?.asObservable?.(), (data) => { const oldValue = this._pickedTemplates; - this._pickedTemplates = data; + this._pickedTemplates = data ?? []; this.requestUpdate('_pickedTemplates', oldValue); }, '_observeTemplates', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts index 6d2cfb1a731b..a81f4c0f54f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace-editor.element.ts @@ -48,24 +48,24 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement { this.consumeContext(UMB_TEMPLATE_WORKSPACE_CONTEXT, (workspaceContext) => { this.#templateWorkspaceContext = workspaceContext; - this.observe(this.#templateWorkspaceContext.name, (name) => { + this.observe(this.#templateWorkspaceContext?.name, (name) => { this._name = name; }); - this.observe(this.#templateWorkspaceContext.alias, (alias) => { + this.observe(this.#templateWorkspaceContext?.alias, (alias) => { this._alias = alias; }); - this.observe(this.#templateWorkspaceContext.content, (content) => { + this.observe(this.#templateWorkspaceContext?.content, (content) => { this._content = content; }); - this.observe(this.#templateWorkspaceContext.masterTemplate, (masterTemplate) => { + this.observe(this.#templateWorkspaceContext?.masterTemplate, (masterTemplate) => { this.#masterTemplateUnique = masterTemplate?.unique ?? null; this._masterTemplateName = masterTemplate?.name ?? null; }); - this.observe(this.#templateWorkspaceContext.isNew, (isNew) => { + this.observe(this.#templateWorkspaceContext?.isNew, (isNew) => { this.#isNew = !!isNew; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tipap-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tipap-api.ts index 38dc55c4f8f6..c90957b1715b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tipap-api.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tipap-api.ts @@ -92,10 +92,13 @@ export default class UmbTiptapBlockElementApi extends UmbTiptapExtensionApiBase this.consumeContext(UMB_BLOCK_RTE_MANAGER_CONTEXT, (context) => { this.observe( - context.contents.pipe( + context?.contents.pipe( distinctUntilChanged((prev, curr) => prev.map((y) => y.key).join() === curr.map((y) => y.key).join()), ), (contents) => { + if (!contents || !context) { + return; + } this.#updateBlocks(contents, context.getLayouts()); }, 'contents', diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tiptap-toolbar-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tiptap-toolbar-api.ts index c7a777e359b2..047054cc61a4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tiptap-toolbar-api.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/block/block.tiptap-toolbar-api.ts @@ -13,7 +13,7 @@ export default class UmbTiptapBlockPickerToolbarExtension extends UmbTiptapToolb this.consumeContext(UMB_BLOCK_RTE_MANAGER_CONTEXT, (context) => { this.observe( - context.blockTypes, + context?.blockTypes, (blockTypes) => { this.#blocks = blockTypes; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts index fae88717a98e..cf9da850f231 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-extensions-configuration.element.ts @@ -62,7 +62,7 @@ export class UmbPropertyEditorUiTiptapExtensionsConfigurationElement super(); this.consumeContext(UMB_PROPERTY_DATASET_CONTEXT, async (dataset) => { this.observe( - await dataset.propertyValueByAlias>('blocks'), + await dataset?.propertyValueByAlias>('blocks'), (blocks) => { const tmpValue = this.value ? [...this.value] : []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-statusbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-statusbar-configuration.element.ts index 246c0d668030..a1f0c9de2413 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-statusbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-statusbar-configuration.element.ts @@ -55,7 +55,7 @@ export class UmbPropertyEditorUiTiptapStatusbarConfigurationElement if (!statusbar.length) return; this._statusbar = statusbar; this.#value = statusbar.map((area) => [...area.data]); - propertyContext.setValue(this.#value); + propertyContext?.setValue(this.#value); }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts index a91e7ea652a5..de5628d18a54 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/components/property-editor-ui-tiptap-toolbar-configuration.element.ts @@ -59,7 +59,7 @@ export class UmbPropertyEditorUiTiptapToolbarConfigurationElement if (!toolbar.length) return; this._toolbar = toolbar; this.#value = toolbar.map((rows) => rows.data.map((groups) => [...groups.data])); - propertyContext.setValue(this.#value); + propertyContext?.setValue(this.#value); }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-statusbar-configuration.context.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-statusbar-configuration.context.ts index 90ccc26f80d0..107ef5cda148 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-statusbar-configuration.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-statusbar-configuration.context.ts @@ -7,7 +7,7 @@ import { UmbId } from '@umbraco-cms/backoffice/id'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbTiptapStatusbarConfigurationContext extends UmbContextBase { +export class UmbTiptapStatusbarConfigurationContext extends UmbContextBase { #extensions = new UmbArrayState([], (x) => x.alias); public readonly extensions = this.#extensions.asObservable(); @@ -43,7 +43,7 @@ export class UmbTiptapStatusbarConfigurationContext extends UmbContextBase { this.observe( - await dataset.propertyValueByAlias>('extensions'), + await dataset?.propertyValueByAlias>('extensions'), (extensions) => { if (extensions) { this.#extensionsEnabled.clear(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts index 8620fadef5b0..646c6c32d937 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/property-editors/tiptap/contexts/tiptap-toolbar-configuration.context.ts @@ -12,7 +12,7 @@ import { UmbId } from '@umbraco-cms/backoffice/id'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbTiptapToolbarConfigurationContext extends UmbContextBase { +export class UmbTiptapToolbarConfigurationContext extends UmbContextBase { #extensions = new UmbArrayState([], (x) => x.alias); public readonly extensions = this.#extensions.asObservable(); @@ -49,7 +49,7 @@ export class UmbTiptapToolbarConfigurationContext extends UmbContextBase { this.observe( - await dataset.propertyValueByAlias>('extensions'), + await dataset?.propertyValueByAlias>('extensions'), (extensions) => { if (extensions) { this.#extensionsEnabled.clear(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts index 215e53fc7213..b9875ce9f958 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/content-name/content-name.element.ts @@ -22,7 +22,7 @@ export class UmbUfmContentNameElement extends UmbUfmElementBase { this.consumeContext(UMB_UFM_RENDER_CONTEXT, (context) => { this.observe( - context.value, + context?.value, async (value) => { const temp = this.alias && typeof value === 'object' diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts index 64081048acbd..f2ab78c8ac4b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/label-value/label-value.element.ts @@ -14,7 +14,7 @@ export class UmbUfmLabelValueElement extends UmbUfmElementBase { this.consumeContext(UMB_UFM_RENDER_CONTEXT, (context) => { this.observe( - context.value, + context?.value, (value) => { if (this.alias !== undefined && value !== undefined && typeof value === 'object') { this.value = (value as Record)[this.alias]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/link/link.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/link/link.element.ts index b53b276b006d..268cd9c82fdd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/link/link.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/link/link.element.ts @@ -20,7 +20,7 @@ export class UmbUfmLinkElement extends UmbUfmElementBase { this.consumeContext(UMB_UFM_RENDER_CONTEXT, (context) => { this.observe( - context.value, + context?.value, async (value) => { const temp = this.alias && typeof value === 'object' diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts index 77de0e84a02a..2d327b7b8ad6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.context.ts @@ -3,7 +3,7 @@ import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -export class UmbUfmRenderContext extends UmbContextBase { +export class UmbUfmRenderContext extends UmbContextBase { #value = new UmbObjectState(undefined); readonly value = this.#value.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts index 8958aee37e2c..743a17c5d41d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/contexts/ufm.context.ts @@ -45,7 +45,7 @@ type UmbUfmFilterType = { filter: ((...args: Array) => string | undefined | null) | undefined; }; -export class UmbUfmContext extends UmbContextBase { +export class UmbUfmContext extends UmbContextBase { #filters = new UmbArrayState([], (x) => x.alias); public readonly filters = this.#filters.asObservable(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/group-id/group-id.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/group-id/group-id.condition.ts index 6dff9d744613..7e3c38db4b6c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/group-id/group-id.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/conditions/group-id/group-id.condition.ts @@ -13,7 +13,7 @@ export class UmbCurrentUserGroupCondition super(host, args); this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { - this.observe(context.currentUser, this.observeCurrentUser, 'umbCurrentUserGroupConditionObserver'); + this.observe(context?.currentUser, this.observeCurrentUser, 'umbCurrentUserGroupConditionObserver'); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts index eb725fc2aec9..c967ea1f6ddf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/current-user.context.ts @@ -9,7 +9,7 @@ import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import { umbLocalizationRegistry } from '@umbraco-cms/backoffice/localization'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; -export class UmbCurrentUserContext extends UmbContextBase { +export class UmbCurrentUserContext extends UmbContextBase { #currentUser = new UmbObjectState(undefined); readonly currentUser = this.#currentUser.asObservable().pipe(filter((user) => !!user)); readonly allowedSections = this.#currentUser.asObservablePart((user) => user?.allowedSections); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts index cdbda6f4c5b3..c42ed6fb85cf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/change-password-current-user.action.ts @@ -16,7 +16,7 @@ export class UmbChangePasswordCurrentUserAction this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.unique, + context?.unique, (unique) => { this.#unique = unique; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/edit-current-user.action.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/edit-current-user.action.ts index e40ae0130ecd..4fb9ec4f8d4a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/edit-current-user.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/profile/edit-current-user.action.ts @@ -17,7 +17,7 @@ export class UmbEditCurrentUserAction this.#init = new Promise((res) => { this.consumeContext(UMB_CURRENT_USER_CONTEXT, (context) => { this.observe( - context.unique, + context?.unique, (unique) => { this.#unique = unique; res(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.store.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.store.ts index 973247ff4d00..e26fdeb15744 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.store.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/repository/current-user.store.ts @@ -10,7 +10,7 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; -export class UmbCurrentUserStore extends UmbContextBase { +export class UmbCurrentUserStore extends UmbContextBase { #data = new UmbObjectState(undefined); readonly data = this.#data.asObservable(); @@ -27,7 +27,7 @@ export class UmbCurrentUserStore extends UmbContextBase { super(host, UMB_CURRENT_USER_STORE_CONTEXT); this.consumeContext(UMB_USER_DETAIL_STORE_CONTEXT, (instance) => { - this.observe(instance?.all(), (users) => this.#onUserDetailStoreUpdate(users)); + this.observe(instance?.all(), (users) => this.#onUserDetailStoreUpdate(users ?? [])); }); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/theme/current-user-theme-user-profile-app.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/theme/current-user-theme-user-profile-app.element.ts index b51383186342..1e748750aa25 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/theme/current-user-theme-user-profile-app.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/theme/current-user-theme-user-profile-app.element.ts @@ -10,7 +10,7 @@ export class UmbCurrentUserThemeUserProfileAppElement extends UmbLitElement { #themeContext?: UmbThemeContext; @state() - private _themeAlias: string | null = null; + private _themeAlias?: string; @state() private _themes: Array