From 0006a9bd87090632a78d3afce4100256f11f1c5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Wed, 29 Jan 2025 22:59:40 +0100
Subject: [PATCH 01/11] peek error notification element + controller/method
---
.../src/packages/core/manifests.ts | 2 +
.../controllers/peek-error/index.ts | 1 +
.../peek-error-notification.element.ts | 38 ++++++++++++
.../peek-error/peek-error.controller.ts | 33 +++++++++++
.../extractUmbNotificationColor.function.ts | 2 +-
.../src/packages/core/notification/index.ts | 12 ++--
.../packages/core/notification/manifests.ts | 3 +
.../error-viewer-modal.element.ts | 56 ++++++++++++++++++
.../error-viewer/error-viewer-modal.token.ts | 17 ++++++
.../notification/modals/error-viewer/index.ts | 2 +
.../modals/error-viewer/manifest.ts | 8 +++
.../notification/notification-handler.test.ts | 2 +-
.../core/notification/notification-handler.ts | 23 ++------
.../core/notification/notification.context.ts | 42 +++++---------
.../src/packages/core/notification/types.ts | 29 ++++++++++
.../core/resources/resource.controller.ts | 58 ++++++++-----------
.../entity-detail-workspace-base.ts | 2 +-
17 files changed, 241 insertions(+), 89 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/manifest.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
index 25e388e063..e904142eac 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts
@@ -11,6 +11,7 @@ import { manifests as iconRegistryManifests } from './icon-registry/manifests.js
import { manifests as localizationManifests } from './localization/manifests.js';
import { manifests as menuManifests } from './menu/manifests.js';
import { manifests as modalManifests } from './modal/manifests.js';
+import { manifests as notificationManifests } from './notification/manifests.js';
import { manifests as pickerManifests } from './picker/manifests.js';
import { manifests as propertyActionManifests } from './property-action/manifests.js';
import { manifests as propertyEditorManifests } from './property-editor/manifests.js';
@@ -39,6 +40,7 @@ export const manifests: Array =
...localizationManifests,
...menuManifests,
...modalManifests,
+ ...notificationManifests,
...pickerManifests,
...propertyActionManifests,
...propertyEditorManifests,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/index.ts
new file mode 100644
index 0000000000..c6d8745627
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/index.ts
@@ -0,0 +1 @@
+export * from './peek-error.controller.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
new file mode 100644
index 0000000000..73a2d064d0
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
@@ -0,0 +1,38 @@
+import { customElement, html, ifDefined, nothing, property } from '@umbraco-cms/backoffice/external/lit';
+import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
+import type { UmbNotificationHandler } from '../../notification-handler';
+import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
+import type { UmbPeekErrorArgs } from '../../types.js';
+import { UMB_ERROR_VIEWER_MODAL } from '../../index.js';
+
+@customElement('umb-peek-error-notification')
+export class UmbPeekErrorNotificationElement extends UmbLitElement {
+ @property({ attribute: false })
+ public data?: UmbPeekErrorArgs;
+
+ public notificationHandler!: UmbNotificationHandler;
+
+ async #onClick() {
+ const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
+
+ modalManager.open(this, UMB_ERROR_VIEWER_MODAL, { data: this.data });
+
+ this.notificationHandler.close();
+ }
+
+ protected override render() {
+ return this.data
+ ? html`${this.data.message}${this.data.details
+ ? html``
+ : nothing}`
+ : nothing;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-peek-error-notification': UmbPeekErrorNotificationElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
new file mode 100644
index 0000000000..6993a710ca
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
@@ -0,0 +1,33 @@
+import { UMB_NOTIFICATION_CONTEXT } from '../../notification.context.js';
+import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbPeekErrorArgs } from '../../types.js';
+
+import './peek-error-notification.element.js';
+
+export class UmbPeekErrorController extends UmbControllerBase {
+ async open(args: UmbPeekErrorArgs): Promise {
+ const context = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+
+ context.peek('danger', {
+ elementName: 'umb-peek-error-notification',
+ data: args,
+ });
+
+ // This is a one time off, so we can destroy our selfs.
+ this.destroy();
+
+ return;
+ }
+}
+
+/**
+ *
+ * @param host {UmbControllerHost} - The host controller
+ * @param args {UmbPeekErrorArgs} - The data to pass to the notification
+ * @returns {UmbPeekErrorController} The notification peek controller instance
+ */
+export function umbPeekError(host: UmbControllerHost, args: UmbPeekErrorArgs) {
+ console.log(host);
+ return new UmbPeekErrorController(host).open(args);
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
index 6ad0399501..d15b9cbcee 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
@@ -1,5 +1,5 @@
-import type { UmbNotificationColor } from './notification.context.js';
import { EventMessageTypeModel } from '@umbraco-cms/backoffice/external/backend-api';
+import type { UmbNotificationColor } from './types';
/**
*
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts
index ed8dcb76fc..8c3df6fa4c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/index.ts
@@ -1,7 +1,9 @@
import './layouts/default/index.js';
-
-export * from './notification.context.js';
-export * from './notification-handler.js';
-
-export * from './isUmbNotifications.function.js';
+export * from './controllers/peek-error/index.js';
export * from './extractUmbNotificationColor.function.js';
+export * from './isUmbNotifications.function.js';
+export * from './modals/error-viewer/index.js';
+export * from './notification-handler.js';
+export * from './notification.context.js';
+
+export type * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/manifests.ts
new file mode 100644
index 0000000000..a00e363447
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/manifests.ts
@@ -0,0 +1,3 @@
+import { manifest } from './modals/error-viewer/manifest.js';
+
+export const manifests = [manifest];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
new file mode 100644
index 0000000000..e33597d604
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
@@ -0,0 +1,56 @@
+import type { UmbErrorViewerModalData, UmbErrorViewerModalValue } from './error-viewer-modal.token.js';
+import { css, customElement, html, nothing } from '@umbraco-cms/backoffice/external/lit';
+import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
+
+@customElement('umb-error-viewer-modal')
+export class UmbErrorViewerModalElement extends UmbModalBaseElement {
+ // Code adapted from https://stackoverflow.com/a/57668208/12787
+ // Licensed under the permissions of the CC BY-SA 4.0 DEED
+ #stringify(obj: any): string {
+ let output = '{';
+ for (const key in obj) {
+ let value = obj[key];
+ if (typeof value === 'function') {
+ value = value.toString();
+ } else if (value instanceof Array) {
+ value = JSON.stringify(value);
+ } else if (typeof value === 'object') {
+ value = this.#stringify(value);
+ } else {
+ value = `"${value}"`;
+ }
+ output += `\n ${key}: ${value},`;
+ }
+ return output + '\n}';
+ }
+
+ override render() {
+ return html`
+
+ ${this.data
+ ? html`${this.#stringify(this.data)}`
+ : nothing}
+
+
+
+
+ `;
+ }
+
+ static override styles = [
+ css`
+ umb-code-block {
+ border: none;
+ height: 100%;
+ }
+ `,
+ ];
+}
+
+export default UmbErrorViewerModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-error-viewer-modal': UmbErrorViewerModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
new file mode 100644
index 0000000000..7cf1b87c03
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
@@ -0,0 +1,17 @@
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+import type { UmbPeekErrorArgs } from '../../types';
+
+// eslint-disable-next-line @typescript-eslint/no-empty-object-type
+export interface UmbErrorViewerModalData extends UmbPeekErrorArgs {}
+
+export type UmbErrorViewerModalValue = undefined;
+
+export const UMB_ERROR_VIEWER_MODAL = new UmbModalToken(
+ 'Umb.Modal.ErrorViewer',
+ {
+ modal: {
+ type: 'sidebar',
+ size: 'medium',
+ },
+ },
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/index.ts
new file mode 100644
index 0000000000..585082c38e
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/index.ts
@@ -0,0 +1,2 @@
+export * from './error-viewer-modal.token.js';
+export * from './manifest.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/manifest.ts
new file mode 100644
index 0000000000..7aae9d47bf
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/manifest.ts
@@ -0,0 +1,8 @@
+import type { ManifestModal } from '@umbraco-cms/backoffice/modal';
+
+export const manifest: ManifestModal = {
+ type: 'modal',
+ alias: 'Umb.Modal.ErrorViewer',
+ name: 'Error Viewer Modal',
+ element: () => import('./error-viewer-modal.element.js'),
+};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.test.ts
index 79a22c4cbf..155180f7e5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.test.ts
@@ -1,5 +1,5 @@
import { UmbNotificationHandler } from './notification-handler.js';
-import type { UmbNotificationOptions } from './notification.context.js';
+import type { UmbNotificationOptions } from './types.js';
import { assert, expect } from '@open-wc/testing';
import { UmbId } from '@umbraco-cms/backoffice/id';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.ts
index 09ff5d168d..ebbf9992e2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/notification-handler.ts
@@ -1,11 +1,9 @@
-import type {
- UmbNotificationOptions,
- UmbNotificationColor,
- UmbNotificationDefaultData,
-} from './notification.context.js';
+import type { UmbNotificationOptions, UmbNotificationColor, UmbNotificationDefaultData } from './types.js';
import type { UUIToastNotificationElement } from '@umbraco-cms/backoffice/external/uui';
import { UmbId } from '@umbraco-cms/backoffice/id';
+const DEFAULT_LAYOUT = 'umb-notification-layout-default';
+
/**
* @class UmbNotificationHandler
*/
@@ -17,10 +15,9 @@ export class UmbNotificationHandler {
private _defaultColor: UmbNotificationColor = 'default';
private _defaultDuration = 6000;
- private _defaultLayout = 'umb-notification-layout-default';
public key: string;
- public element: any;
+ public element!: UUIToastNotificationElement;
public color: UmbNotificationColor;
public duration: number | null;
@@ -34,23 +31,13 @@ export class UmbNotificationHandler {
this.color = options.color || this._defaultColor;
this.duration = options.duration !== undefined ? options.duration : this._defaultDuration;
- this._elementName = options.elementName || this._defaultLayout;
+ this._elementName = options.elementName || DEFAULT_LAYOUT;
this._data = options.data;
this._closePromise = new Promise((res) => {
this._closeResolver = res;
});
- this._createElement();
- }
-
- /**
- * @private
- * @memberof UmbNotificationHandler
- */
- private _createElement() {
- if (!this._elementName) return;
-
const notification: UUIToastNotificationElement = document.createElement('uui-toast-notification');
notification.color = this.color;
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 5bdbf98670..73f26422a2 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
@@ -3,29 +3,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';
import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api';
-
-/**
- * The default data of notifications
- * @interface UmbNotificationDefaultData
- */
-export interface UmbNotificationDefaultData {
- message: string;
- headline?: string;
- structuredList?: Record>;
-}
-
-/**
- * @interface UmbNotificationOptions
- * @template UmbNotificationData
- */
-export interface UmbNotificationOptions {
- color?: UmbNotificationColor;
- duration?: number | null;
- elementName?: string;
- data?: UmbNotificationData;
-}
-
-export type UmbNotificationColor = '' | 'default' | 'positive' | 'warning' | 'danger';
+import type { UmbNotificationColor, UmbNotificationOptions } from './types.js';
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)
@@ -42,9 +20,9 @@ export class UmbNotificationContext extends UmbContextBase(options: T): UmbNotificationHandler {
const notificationHandler = new UmbNotificationHandler(options);
- notificationHandler.element.addEventListener('closed', () => this._handleClosed(notificationHandler));
+ notificationHandler.element?.addEventListener('closed', () => this._handleClosed(notificationHandler));
this._notifications.setValue([...this._notifications.getValue(), notificationHandler]);
@@ -78,8 +56,11 @@ export class UmbNotificationContext extends UmbContextBase(
+ color: UmbNotificationColor,
+ options: T,
+ ): UmbNotificationHandler {
+ return this.#open({ color, ...options });
}
/**
@@ -89,8 +70,11 @@ export class UmbNotificationContext extends UmbContextBase(
+ color: UmbNotificationColor,
+ options: T,
+ ): UmbNotificationHandler {
+ return this.#open({ ...options, color, duration: null });
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts
new file mode 100644
index 0000000000..a843dc7ac6
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts
@@ -0,0 +1,29 @@
+/**
+ * The default data of notifications
+ * @interface UmbNotificationDefaultData
+ */
+export interface UmbNotificationDefaultData {
+ message: string;
+ headline?: string;
+ /**
+ * @deprecated, do not use this. It will be removed in v.16 — Use UmbPeekError instead
+ */
+ structuredList?: Record>;
+}
+
+/**
+ * @interface UmbNotificationOptions
+ * @template UmbNotificationData
+ */
+export interface UmbNotificationOptions {
+ color?: UmbNotificationColor;
+ duration?: number | null;
+ elementName?: string;
+ data?: UmbNotificationData;
+}
+
+export type UmbNotificationColor = '' | 'default' | 'positive' | 'warning' | 'danger';
+
+export interface UmbPeekErrorArgs extends UmbNotificationDefaultData {
+ details?: any;
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
index d92a68a38c..2f3b53b3c8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
@@ -5,7 +5,11 @@ import type { XhrRequestOptions } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
-import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';
+import {
+ UMB_NOTIFICATION_CONTEXT,
+ umbPeekError,
+ type UmbNotificationOptions,
+} from '@umbraco-cms/backoffice/notification';
import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
import {
ApiError,
@@ -17,29 +21,14 @@ import {
export class UmbResourceController extends UmbControllerBase {
#promise: Promise;
- #notificationContext?: typeof UMB_NOTIFICATION_CONTEXT.TYPE;
-
- #authContext?: typeof UMB_AUTH_CONTEXT.TYPE;
-
constructor(host: UmbControllerHost, promise: Promise, alias?: string) {
super(host, alias);
this.#promise = promise;
-
- new UmbContextConsumerController(host, UMB_NOTIFICATION_CONTEXT, (_instance) => {
- this.#notificationContext = _instance;
- });
-
- new UmbContextConsumerController(host, UMB_AUTH_CONTEXT, (_instance) => {
- this.#authContext = _instance;
- });
- }
-
- override hostConnected(): void {
- // Do nothing
}
override hostDisconnected(): void {
+ super.hostDisconnected();
this.cancel();
}
@@ -82,6 +71,7 @@ export class UmbResourceController extends UmbControllerBase {
console.error('Request failed', error.request);
console.error('Request body', error.body);
console.error('Error', error);
+ console.groupEnd();
let problemDetails: ProblemDetails | null = null;
@@ -111,23 +101,14 @@ export class UmbResourceController extends UmbControllerBase {
switch (error.status ?? 0) {
case 401: {
// See if we can get the UmbAuthContext and let it know the user is timed out
- if (this.#authContext) {
- this.#authContext.timeOut();
- } else {
- // If we can't get the auth context, show a notification
- this.#notificationContext?.peek('warning', {
- data: {
- headline: 'Session Expired',
- message: 'Your session has expired. Please refresh the page.',
- },
- });
- }
+ const authContext = await this.getContext(UMB_AUTH_CONTEXT);
+ authContext.timeOut();
break;
}
case 500:
// Server Error
- if (!isCancelledByNotification && this.#notificationContext) {
+ if (!isCancelledByNotification) {
let headline = problemDetails?.title ?? error.name ?? 'Server Error';
let message = 'A fatal server error occurred. If this continues, please reach out to your administrator.';
@@ -141,7 +122,8 @@ export class UmbResourceController extends UmbControllerBase {
'The Umbraco object cache is corrupt, but your action may still have been executed. Please restart the server to reset the cache. This is a work in progress.';
}
- this.#notificationContext.peek('danger', {
+ const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+ notificationContext.peek('danger', {
data: {
headline,
message,
@@ -152,8 +134,11 @@ export class UmbResourceController extends UmbControllerBase {
break;
default:
// Other errors
- if (!isCancelledByNotification && this.#notificationContext) {
- this.#notificationContext.peek('danger', {
+ if (!isCancelledByNotification) {
+ /*
+
+ const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
+ notificationContext.peek('danger', {
data: {
headline: problemDetails?.title ?? error.name ?? 'Server Error',
message: problemDetails?.detail ?? error.message ?? 'Something went wrong',
@@ -163,10 +148,15 @@ export class UmbResourceController extends UmbControllerBase {
},
...options,
});
+ */
+ const headline = problemDetails?.title ?? error.name ?? 'Server Error';
+ umbPeekError(this, {
+ headline: problemDetails?.detail ? headline : undefined,
+ message: problemDetails?.detail ?? headline,
+ details: problemDetails?.errors,
+ });
}
}
-
- console.groupEnd();
}
}
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 574f0e6faf..0c9cff4af9 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
@@ -382,7 +382,7 @@ export abstract class UmbEntityDetailWorkspaceContextBase<
this,
umbExtensionsRegistry,
repositoryAlias,
- [this._host],
+ [],
(permitted, ctrl) => {
this._detailRepository = permitted ? ctrl.api : undefined;
this.#checkIfInitialized();
From 6f9e66de8aa09e54642ac2ec821e51487baf56ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jan 2025 14:00:27 +0100
Subject: [PATCH 02/11] localizations
---
src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts | 2 ++
src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts | 2 ++
src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 2 ++
3 files changed, 6 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
index c6d6f63dbd..4769c1949d 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts
@@ -583,6 +583,8 @@ export default {
deleteLayout: 'You are deleting the layout',
deletingALayout:
'Modifying layout will result in loss of data for any existing content that is based on this configuration.',
+ seeErrorAction: 'Se fejlen',
+ seeErrorDialogHeadline: 'Fejl detaljer',
},
dictionary: {
noItems: 'Der er ingen ordbogselementer.',
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
index 995beb00d3..91897bc62b 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts
@@ -614,6 +614,8 @@ export default {
deleteLayout: 'You are deleting the layout',
deletingALayout:
'Modifying layout will result in loss of data for any existing content that is based on this configuration.',
+ seeErrorAction: 'See error',
+ seeErrorDialogHeadline: 'Error details',
},
dictionary: {
importDictionaryItemHelp:
diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
index dae39aa00f..1fc60ad171 100644
--- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
+++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts
@@ -606,6 +606,8 @@ export default {
deletingALayout:
'Modifying layout will result in loss of data for any existing content that is based on this configuration.',
selectEditorConfiguration: 'Select configuration',
+ seeErrorAction: 'See error',
+ seeErrorDialogHeadline: 'Error details',
},
dictionary: {
importDictionaryItemHelp:
From 7d703cc9bd2cac270d82160ec0851c89fb1f13a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jan 2025 14:01:31 +0100
Subject: [PATCH 03/11] peek error modal
---
.../peek-error-notification.element.ts | 9 ++++--
.../error-viewer-modal.element.ts | 30 +++++++++++++++----
.../core/resources/resource.controller.ts | 24 +++++----------
3 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
index 73a2d064d0..d9907b66cc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
@@ -15,7 +15,7 @@ export class UmbPeekErrorNotificationElement extends UmbLitElement {
async #onClick() {
const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT);
- modalManager.open(this, UMB_ERROR_VIEWER_MODAL, { data: this.data });
+ modalManager.open(this, UMB_ERROR_VIEWER_MODAL, { data: this.data?.details });
this.notificationHandler.close();
}
@@ -24,7 +24,12 @@ export class UmbPeekErrorNotificationElement extends UmbLitElement {
return this.data
? html`${this.data.message}${this.data.details
- ? html``
+ ? html``
: nothing}`
: nothing;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
index e33597d604..51a377cced 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
@@ -1,9 +1,15 @@
import type { UmbErrorViewerModalData, UmbErrorViewerModalValue } from './error-viewer-modal.token.js';
-import { css, customElement, html, nothing } from '@umbraco-cms/backoffice/external/lit';
+import { css, customElement, html, nothing, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal';
@customElement('umb-error-viewer-modal')
export class UmbErrorViewerModalElement extends UmbModalBaseElement {
+ @state()
+ _displayError?: string;
+
+ @state()
+ _displayLang?: string;
+
// Code adapted from https://stackoverflow.com/a/57668208/12787
// Licensed under the permissions of the CC BY-SA 4.0 DEED
#stringify(obj: any): string {
@@ -24,12 +30,26 @@ export class UmbErrorViewerModalElement extends UmbModalBaseElement
- ${this.data
- ? html`${this.#stringify(this.data)}`
- : nothing}
+
+ ${this.data ? html`${this.data}` : nothing}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
index 2f3b53b3c8..e1b0521c78 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
@@ -4,12 +4,7 @@ import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidat
import type { XhrRequestOptions } from './types.js';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
-import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
-import {
- UMB_NOTIFICATION_CONTEXT,
- umbPeekError,
- type UmbNotificationOptions,
-} from '@umbraco-cms/backoffice/notification';
+import { umbPeekError, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification';
import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository';
import {
ApiError,
@@ -122,13 +117,10 @@ export class UmbResourceController extends UmbControllerBase {
'The Umbraco object cache is corrupt, but your action may still have been executed. Please restart the server to reset the cache. This is a work in progress.';
}
- const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
- notificationContext.peek('danger', {
- data: {
- headline,
- message,
- },
- ...options,
+ umbPeekError(this, {
+ headline: headline,
+ message: message,
+ details: problemDetails?.errors ?? problemDetails?.detail,
});
}
break;
@@ -136,7 +128,6 @@ export class UmbResourceController extends UmbControllerBase {
// Other errors
if (!isCancelledByNotification) {
/*
-
const notificationContext = await this.getContext(UMB_NOTIFICATION_CONTEXT);
notificationContext.peek('danger', {
data: {
@@ -151,9 +142,8 @@ export class UmbResourceController extends UmbControllerBase {
*/
const headline = problemDetails?.title ?? error.name ?? 'Server Error';
umbPeekError(this, {
- headline: problemDetails?.detail ? headline : undefined,
- message: problemDetails?.detail ?? headline,
- details: problemDetails?.errors,
+ message: headline,
+ details: problemDetails?.errors ?? problemDetails?.detail,
});
}
}
From 2ca4e0e1bd9c5bd7533053b625f15613c558a463 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jan 2025 14:01:51 +0100
Subject: [PATCH 04/11] remove max-height setting from code-block
---
.../packages/core/components/code-block/code-block.element.ts | 1 -
.../models-builder/models-builder-dashboard.element.ts | 2 +-
.../templating-page-field-builder-modal.element.ts | 2 +-
.../modals/query-builder/query-builder-modal.element.ts | 4 +++-
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts
index ddcead0191..94551f5185 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.element.ts
@@ -68,7 +68,6 @@ export class UmbCodeBlockElement extends LitElement {
}
uui-scroll-container {
- max-height: 500px;
overflow-y: auto;
overflow-wrap: anywhere;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.element.ts b/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.element.ts
index 358d7ce045..de399a97e1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.element.ts
@@ -95,7 +95,7 @@ export class UmbModelsBuilderDashboardElement extends UmbLitElement {
${this._modelsBuilder?.lastError
? html`Last generation failed with the following error:
- ${this._modelsBuilder.lastError}`
+ ${this._modelsBuilder.lastError}`
: nothing}
`;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts
index 9d1eec32e3..f6092ec62d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/templating-page-field-builder-modal.element.ts
@@ -94,7 +94,7 @@ export class UmbTemplatingPageFieldBuilderModalElement extends UmbModalBaseEleme
?disabled=${this._field ? false : true}>
Output sample
- ${this._field ? getUmbracoFieldSnippet(this._field, this._default, this._recursive) : ''}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts
index 9edc5850e5..a3e2863471 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/modals/query-builder/query-builder-modal.element.ts
@@ -254,7 +254,9 @@ export default class UmbTemplateQueryBuilderModalElement extends UmbModalBaseEle
(sample) => html`${sample.name}`,
) ?? ''}
- ${this._templateQuery?.queryExpression ?? ''}
+ ${this._templateQuery?.queryExpression ?? ''}
From 32a2bab4f0dc5d57889971f2c139112e00df2974 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jan 2025 14:15:32 +0100
Subject: [PATCH 05/11] todo
---
.../src/packages/core/resources/resource.controller.ts | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
index e1b0521c78..44ae915af3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
@@ -32,6 +32,7 @@ export class UmbResourceController extends UmbControllerBase {
* @param promise
*/
static async tryExecute(promise: Promise): Promise> {
+ // TODO: tryExecute should not take a promise as argument, but should utilize the class property `#promise` instead. (In this way the promise can be cancelled when disconnected)
try {
return { data: await promise };
} catch (error) {
From 69e36a3b9444fb18d79b6bb3d15a389e94e513b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Thu, 30 Jan 2025 14:15:44 +0100
Subject: [PATCH 06/11] fix json display
---
.../modals/error-viewer/error-viewer-modal.element.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
index 51a377cced..40b6924fea 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts
@@ -32,7 +32,6 @@ export class UmbErrorViewerModalElement extends UmbModalBaseElement
- ${this.data ? html`${this.data}` : nothing}
+ ${this.data
+ ? html`${this._displayError}`
+ : nothing}
From e034a647233f9fa76cc8a3bd72f30b8385c62f89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 4 Feb 2025 13:44:18 +0100
Subject: [PATCH 07/11] Update
src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
---
.../core/notification/extractUmbNotificationColor.function.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
index d15b9cbcee..cf9b9e89d8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/extractUmbNotificationColor.function.ts
@@ -1,5 +1,5 @@
import { EventMessageTypeModel } from '@umbraco-cms/backoffice/external/backend-api';
-import type { UmbNotificationColor } from './types';
+import type { UmbNotificationColor } from './types.js';
/**
*
From cab07ba6f6e5d5e608941de7321f714e55b32df2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 4 Feb 2025 13:44:25 +0100
Subject: [PATCH 08/11] Update
src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
---
.../modals/error-viewer/error-viewer-modal.token.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
index 7cf1b87c03..1c09ed590c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.token.ts
@@ -1,5 +1,5 @@
import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
-import type { UmbPeekErrorArgs } from '../../types';
+import type { UmbPeekErrorArgs } from '../../types.js';
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface UmbErrorViewerModalData extends UmbPeekErrorArgs {}
From 97046b954696232751420e8bc4d04191d8a1d655 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 4 Feb 2025 13:44:33 +0100
Subject: [PATCH 09/11] Update
src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com>
---
.../controllers/peek-error/peek-error-notification.element.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
index d9907b66cc..a8b070cdbf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts
@@ -1,6 +1,6 @@
import { customElement, html, ifDefined, nothing, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
-import type { UmbNotificationHandler } from '../../notification-handler';
+import type { UmbNotificationHandler } from '../../notification-handler.js';
import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal';
import type { UmbPeekErrorArgs } from '../../types.js';
import { UMB_ERROR_VIEWER_MODAL } from '../../index.js';
From e2fd2afabd23d2ae87e8b62cdbcb84b36a5ea275 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Wed, 5 Feb 2025 15:49:47 +0100
Subject: [PATCH 10/11] mark options as deprecated and avoid lint issue on the
argument not used
---
.../packages/core/resources/resource.controller.ts | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
index 44ae915af3..24e142c6f1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts
@@ -12,6 +12,7 @@ import {
CancelError,
type ProblemDetails,
} from '@umbraco-cms/backoffice/external/backend-api';
+import { UmbDeprecation } from '../utils/deprecation/deprecation.js';
export class UmbResourceController extends UmbControllerBase {
#promise: Promise;
@@ -48,11 +49,20 @@ export class UmbResourceController extends UmbControllerBase {
/**
* Wrap the {tryExecute} function in a try/catch block and return the result.
* If the executor function throws an error, then show the details in a notification.
- * @param options
+ * @param _options
*/
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
async tryExecuteAndNotify(options?: UmbNotificationOptions): Promise> {
const { data, error } = await UmbResourceController.tryExecute(this.#promise);
+ if (options) {
+ new UmbDeprecation({
+ deprecated: 'tryExecuteAndNotify `options` argument is deprecated.',
+ removeInVersion: '17.0.0',
+ solution: 'Use the method without arguments.',
+ }).warn();
+ }
+
if (error) {
/**
* Determine if we want to show a notification or just log the error to the console.
From 64efd73dd8853d06f3b9428e3987fd751fc40389 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 12 Feb 2025 11:02:37 +0100
Subject: [PATCH 11/11] Update peek-error.controller.ts
remove console log
---
.../notification/controllers/peek-error/peek-error.controller.ts | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
index 6993a710ca..80dc9638a1 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts
@@ -28,6 +28,5 @@ export class UmbPeekErrorController extends UmbControllerBase {
* @returns {UmbPeekErrorController} The notification peek controller instance
*/
export function umbPeekError(host: UmbControllerHost, args: UmbPeekErrorArgs) {
- console.log(host);
return new UmbPeekErrorController(host).open(args);
}