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 b34a87cec5e6..cec5993b563d 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 @@ -584,6 +584,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 8bdcd734b1a3..7cd7b8dbeb5e 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 4f816cb43bb4..cb184bbd3ff6 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -610,6 +610,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: 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 ddcead01910b..94551f518585 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/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index 60f4a53b2852..e8fb2ee19b15 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'; @@ -40,6 +41,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 000000000000..c6d8745627d0 --- /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 000000000000..a8b070cdbfd5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error-notification.element.ts @@ -0,0 +1,43 @@ +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.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'; + +@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?.details }); + + 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 000000000000..80dc9638a1e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/controllers/peek-error/peek-error.controller.ts @@ -0,0 +1,32 @@ +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) { + 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 6ad0399501b6..cf9b9e89d8bc 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.js'; /** * 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 ed8dcb76fc05..8c3df6fa4cd5 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 './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 * from './isUmbNotifications.function.js'; -export * from './extractUmbNotificationColor.function.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 000000000000..a00e36344748 --- /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 000000000000..40b6924feaa6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/modals/error-viewer/error-viewer-modal.element.ts @@ -0,0 +1,77 @@ +import type { UmbErrorViewerModalData, UmbErrorViewerModalValue } from './error-viewer-modal.token.js'; +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 { + 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}'; + } + + public override set data(value: UmbErrorViewerModalData | undefined) { + super.data = value; + // is JSON: + if (typeof value === 'string') { + this._displayLang = 'String'; + this._displayError = value; + } else { + this._displayLang = 'JSON'; + this._displayError = this.#stringify(value); + } + } + public override get data(): UmbErrorViewerModalData | undefined { + return super.data; + } + + override render() { + return html` + + ${this.data + ? html`${this._displayError}` + : 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 000000000000..1c09ed590c4c --- /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.js'; + +// 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 000000000000..585082c38eb8 --- /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 000000000000..7aae9d47bf30 --- /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 79a22c4cbfd7..155180f7e572 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 09ff5d168dcb..ebbf9992e210 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 5bdbf98670a6..73f26422a20e 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 000000000000..3ec0daea78ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/notification/types.ts @@ -0,0 +1,30 @@ +/** + * 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>; + whitespace?: 'normal' | 'pre-line' | 'pre-wrap' | 'nowrap' | 'pre'; +} + +/** + * @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 8274db8ce89e..346902dfbe06 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,8 +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, 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, @@ -13,33 +12,19 @@ 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; - #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(); } @@ -48,6 +33,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) { @@ -63,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. @@ -82,6 +77,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 +107,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,19 +128,19 @@ 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', { - data: { - headline, - message, - }, - ...options, + umbPeekError(this, { + headline: headline, + message: message, + details: problemDetails?.errors ?? problemDetails?.detail, }); } 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 +150,14 @@ export class UmbResourceController extends UmbControllerBase { }, ...options, }); + */ + const headline = problemDetails?.title ?? error.name ?? 'Server Error'; + umbPeekError(this, { + message: headline, + details: problemDetails?.errors ?? problemDetails?.detail, + }); } } - - 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 07e3c570f9df..88321ebd6f20 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 @@ -407,7 +407,7 @@ export abstract class UmbEntityDetailWorkspaceContextBase< this, umbExtensionsRegistry, repositoryAlias, - [this._host], + [], (permitted, ctrl) => { this._detailRepository = permitted ? ctrl.api : undefined; this.#checkIfInitialized(); 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 358d7ce045ac..de399a97e122 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 9d1eec32e3e4..f6092ec62dfd 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 9edc5850e535..a3e286347147 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 ?? ''}