Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V16/feature: get context resolves in undefined if not found #18611

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e66abe4
implement getContext rejecter + allow for resolving in undefined
nielslyngsoe Mar 6, 2025
8f34e3c
fix test
nielslyngsoe Mar 6, 2025
5d10b37
timeout concept
nielslyngsoe Mar 6, 2025
3687892
adjustments
nielslyngsoe Mar 6, 2025
e3024a5
adapt implementation
nielslyngsoe Mar 6, 2025
4481d87
ability to set timeoutFrame for faster test
nielslyngsoe Mar 6, 2025
bb5cb1a
update
nielslyngsoe Mar 7, 2025
fccbf6b
make sure provider only provides when connected
nielslyngsoe Mar 7, 2025
0dfbe91
make sure action apis can fail without resolving
nielslyngsoe Mar 7, 2025
bb5a039
make sure to await the arrival of the UMB_AUTH_CONTEXT
nielslyngsoe Mar 7, 2025
71ca072
no need to be async
nielslyngsoe Mar 7, 2025
fdbcd6d
consume to stay up to date
nielslyngsoe Mar 7, 2025
3459a1b
one rendering cycle approach
nielslyngsoe Mar 7, 2025
91049f2
adjusting context consumption part 1
nielslyngsoe Mar 7, 2025
3cf5d78
implementation adjustments
nielslyngsoe Mar 7, 2025
dd37719
correction patch 2
nielslyngsoe Mar 8, 2025
631401f
correction patch 3
nielslyngsoe Mar 9, 2025
1c071fe
correction batch 4
nielslyngsoe Mar 9, 2025
c054ac9
correction batch 5
nielslyngsoe Mar 9, 2025
9e4ded5
correction batch 6
nielslyngsoe Mar 9, 2025
6720f44
Merge branch 'v16/dev' into v16/feature/get-context-resolves-in-undef…
nielslyngsoe Mar 9, 2025
79765df
Merge branch 'v16/dev' into v16/feature/get-context-resolves-in-undef…
madsrasmussen Mar 12, 2025
6256537
add null checks
madsrasmussen Mar 12, 2025
b21f81c
no need for promise.all
nielslyngsoe Mar 13, 2025
af56ecb
remove todo
nielslyngsoe Mar 13, 2025
89c064b
promise clean up
nielslyngsoe Mar 13, 2025
e76ceee
rejection reason
nielslyngsoe Mar 14, 2025
4dce0db
implement preventTimeouts where it makes sense
nielslyngsoe Mar 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context.js';
import { UmbWorkspaceActionBase, type UmbWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context';

// The Example Incrementor Workspace Action Controller:
export class ExampleIncrementorWorkspaceAction extends UmbWorkspaceActionBase implements UmbWorkspaceAction {
// This method is executed
override async execute() {
const context = await this.getContext(EXAMPLE_COUNTER_CONTEXT);
if (!context) {
throw new Error('Could not get the counter context');
}
context.increment();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class UmbApiInterceptorController extends UmbControllerBase {
if (!isUmbNotifications(notifications)) return response;

this.getContext(UMB_NOTIFICATION_CONTEXT).then((notificationContext) => {
if (notificationContext === undefined) {
throw new Error('Notification context is not available');
}
for (const notification of notifications) {
notificationContext.peek(extractUmbNotificationColor(notification.type), {
data: { headline: notification.category, message: notification.message },
Expand Down
11 changes: 9 additions & 2 deletions src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
import { setStoredPath } from '@umbraco-cms/backoffice/utils';

export class UmbAppAuthController extends UmbControllerBase {
#retrievedModal: Promise<unknown>;
#authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
#isFirstCheck = true;

constructor(host: UmbControllerHost) {
super(host);

this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
this.#retrievedModal = this.consumeContext(UMB_AUTH_CONTEXT, (context) => {
this.#authContext = context;

// Observe the user's authorization state and start the authorization flow if the user is not authorized
Expand All @@ -24,14 +25,15 @@
},
'_authState',
);
});
}).asPromise({ preventTimeout: true });
}

/**
* Checks if the user is authorized.
* If not, the authorization flow is started.
*/
async isAuthorized(): Promise<boolean> {
await this.#retrievedModal.catch(() => undefined);
if (!this.#authContext) {
throw new Error('[Fatal] Auth context is not available');
}
Expand Down Expand Up @@ -63,6 +65,7 @@
* @param userLoginState
*/
async makeAuthorizationRequest(userLoginState: UmbUserLoginState = 'loggingIn'): Promise<boolean> {
await this.#retrievedModal.catch(() => undefined);

Check warning on line 68 in src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v16/dev)

❌ Getting worse: Complex Method

UmbAppAuthController.makeAuthorizationRequest increases in cyclomatic complexity from 13 to 14, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
if (!this.#authContext) {
throw new Error('[Fatal] Auth context is not available');
}
Expand Down Expand Up @@ -111,13 +114,17 @@
}

async #showLoginModal(userLoginState: UmbUserLoginState): Promise<boolean> {
await this.#retrievedModal.catch(() => undefined);
if (!this.#authContext) {
throw new Error('[Fatal] Auth context is not available');
}

// Show the provider selection screen
const authModalKey = 'umbAuthModal';
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
if (!modalManager) {
throw new Error('[Fatal] Modal manager is not available');
}

Check warning on line 127 in src/Umbraco.Web.UI.Client/src/apps/app/app-auth.controller.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v16/dev)

❌ New issue: Complex Method

UmbAppAuthController.showLoginModal has a cyclomatic complexity of 9, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.

const selected = await modalManager
.open(this._host, UMB_MODAL_APP_AUTH, {
Expand Down
43 changes: 20 additions & 23 deletions src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,26 @@ export class UmbBackofficeContext extends UmbContextBase<UmbBackofficeContext> {
});
});

this.#init();
}

async #init() {
const userContext = await this.getContext(UMB_CURRENT_USER_CONTEXT);
this.observe(
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]
new UmbExtensionsManifestInitializer(
this,
umbExtensionsRegistry,
'section',
(manifest) => allowedSections.includes(manifest.alias),
async (sections) => {
this.#allowedSections.setValue([...sections]);
},
'umbAllowedSectionsManifestInitializer',
);
},
'umbAllowedSectionsObserver',
);
this.consumeContext(UMB_CURRENT_USER_CONTEXT, (userContext) => {
this.observe(
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]
new UmbExtensionsManifestInitializer(
this,
umbExtensionsRegistry,
'section',
(manifest) => allowedSections.includes(manifest.alias),
async (sections) => {
this.#allowedSections.setValue([...sections]);
},
'umbAllowedSectionsManifestInitializer',
);
},
'umbAllowedSectionsObserver',
);
});
}

async #getVersion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement {
});
}

protected override async firstUpdated() {
protected override firstUpdated() {
this.#isAdmin();
}

Expand Down Expand Up @@ -88,6 +88,10 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement {

async #openSystemInformation() {
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
if (!modalManager) {
throw new Error('Modal manager not found');
}

modalManager
.open(this, UMB_SYSINFO_MODAL)
.onSubmit()
Expand All @@ -97,6 +101,7 @@ export class UmbBackofficeHeaderLogoElement extends UmbLitElement {
async #openNewVersion() {
if (!this._serverUpgradeCheck) return;
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
if (!modalManager) return;
modalManager
.open(this, UMB_NEWVERSION_MODAL, {
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class UmbPreviewCultureElement extends UmbLitElement {
this._culture = culture;

const previewContext = await this.getContext(UMB_PREVIEW_CONTEXT);
previewContext.updateIFrame({ culture: culture.unique });
previewContext?.updateIFrame({ culture: culture.unique });
}

override render() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
export class UmbPreviewExitElement extends UmbLitElement {
async #onClick() {
const previewContext = await this.getContext(UMB_PREVIEW_CONTEXT);
previewContext.exitPreview(0);
previewContext?.exitPreview(0);
}

override render() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
export class UmbPreviewOpenWebsiteElement extends UmbLitElement {
async #onClick() {
const previewContext = await this.getContext(UMB_PREVIEW_CONTEXT);
previewContext.openWebsite();
previewContext?.openWebsite();
}

override render() {
Expand Down
24 changes: 11 additions & 13 deletions src/Umbraco.Web.UI.Client/src/apps/preview/preview.context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,22 @@ export class UmbPreviewContext extends UmbContextBase<UmbPreviewContext> {

constructor(host: UmbControllerHost) {
super(host, UMB_PREVIEW_CONTEXT);
this.#init();
}

async #init() {
const appContext = await this.getContext(UMB_APP_CONTEXT);
this.#serverUrl = appContext.getServerUrl();
this.consumeContext(UMB_APP_CONTEXT, (appContext) => {
this.#serverUrl = appContext.getServerUrl();

const params = new URLSearchParams(window.location.search);
const params = new URLSearchParams(window.location.search);

this.#culture = params.get('culture');
this.#unique = params.get('id');
this.#culture = params.get('culture');
this.#unique = params.get('id');

if (!this.#unique) {
console.error('No unique ID found in query string.');
return;
}
if (!this.#unique) {
console.error('No unique ID found in query string.');
return;
}

this.#setPreviewUrl();
this.#setPreviewUrl();
});
}

#configureWebSocket() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
UmbContextCallback,
UmbContextConsumerAsPromiseOptionsType,
UmbContextConsumerController,
UmbContextProviderController,
UmbContextToken,
Expand Down Expand Up @@ -64,5 +65,6 @@ export interface UmbClassInterface extends UmbControllerHost {
*/
getContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
alias: string | UmbContextToken<BaseType, ResultType>,
): Promise<ResultType>;
options?: UmbContextConsumerAsPromiseOptionsType,
): Promise<ResultType | undefined>;
}
18 changes: 13 additions & 5 deletions src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
type UmbContextCallback,
UmbContextConsumerController,
UmbContextProviderController,
type UmbContextConsumerAsPromiseOptionsType,
} from '@umbraco-cms/backoffice/context-api';
import { type ObserverCallback, UmbObserverController, simpleHashCode } from '@umbraco-cms/backoffice/observable-api';

Expand Down Expand Up @@ -98,12 +99,19 @@

async getContext<BaseType = unknown, ResultType extends BaseType = BaseType>(
contextAlias: string | UmbContextToken<BaseType, ResultType>,
): Promise<ResultType> {
options?: UmbContextConsumerAsPromiseOptionsType,
): Promise<ResultType | undefined> {
const controller = new UmbContextConsumerController(this, contextAlias);
const promise = controller.asPromise().then((result) => {
controller.destroy();
return result;
});
const promise = controller
.asPromise(options)
.then((result) => {
controller.destroy();
return result;
})
.catch(() => {
controller.destroy();
return undefined;
});

Check warning on line 114 in src/Umbraco.Web.UI.Client/src/libs/class-api/class.mixin.ts

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v16/dev)

❌ Getting worse: Complex Method

UmbClassMixin increases in cyclomatic complexity from 10 to 11, threshold = 9. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
return promise;
}

Expand Down
Loading
Loading