From 310ccdc011a9d7fd279228df504fe76cf3be934b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 19 Nov 2024 09:14:41 +0100 Subject: [PATCH] Fix: Add "Not Found" empty state to detail workspaces (#17489) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Niels Lyngsø Co-authored-by: Niels Lyngsø --- .../src/assets/lang/en-us.ts | 10 +++ .../body-layout/body-layout.element.ts | 4 + .../workspace-editor.element.ts | 5 +- .../workspace-entity-action-menu.element.ts | 13 ++-- .../entity-detail-workspace-base.ts | 70 +++++++++-------- .../entity-detail-workspace.context-token.ts | 12 +++ .../entity-detail-not-found.element.ts | 50 ++++++++++++ .../entity-detail-workspace-editor.element.ts | 77 +++++++++++++++++++ .../entity-detail/global-components/index.ts | 5 ++ .../core/workspace/entity-detail/index.ts | 4 + .../core/workspace/entity-detail/types.ts | 17 ++++ .../src/packages/core/workspace/index.ts | 3 + .../workspace/workspace-context.interface.ts | 2 + .../data-type-workspace-editor.element.ts | 4 +- .../workspace/data-type-workspace.context.ts | 13 ---- .../dictionary-workspace-editor.element.ts | 4 +- .../language/workspace/language-root/paths.ts | 8 ++ .../language-workspace-editor.element.ts | 7 +- .../member-group-workspace-editor.element.ts | 31 +------- .../member-group-workspace.context.ts | 18 ----- .../partial-view-workspace-editor.element.ts | 5 +- .../partial-view-workspace.context.ts | 14 ---- .../script-workspace-editor.element.ts | 5 +- .../workspace/script-workspace.context.ts | 20 ----- .../template-workspace-editor.element.ts | 4 +- .../user-group-workspace-editor.element.ts | 8 +- .../user/user-workspace-editor.element.ts | 11 +-- .../workspace/user/user-workspace.context.ts | 7 +- .../webhook-workspace-editor.element.ts | 5 +- 29 files changed, 270 insertions(+), 166 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-not-found.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/paths.ts 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 6f53119e1481..3cd822caf09d 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 @@ -359,6 +359,16 @@ export default { blueprintDescription: 'A Document Blueprint is predefined content that an editor can select to use as the\n basis for creating new content\n ', }, + entityDetail: { + notFoundTitle: (entityType: string) => { + const entityName = entityType ?? 'Item'; + return `${entityName} not found`; + }, + notFoundDescription: (entityType: string) => { + const entityName = entityType ?? 'item'; + return `The requested ${entityName} could not be found. Please check the URL and try again.`; + }, + }, media: { clickToUpload: 'Click to upload', orClickHereToUpload: 'or click here to choose files', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts index d18591b19359..a9a5ff2f5428 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.element.ts @@ -37,6 +37,9 @@ export class UmbBodyLayoutElement extends LitElement { @property({ type: Boolean, reflect: true, attribute: 'header-transparent' }) public headerTransparent = false; + @property({ type: Boolean }) + loading = false; + @state() private _headerSlotHasChildren = false; @@ -116,6 +119,7 @@ export class UmbBodyLayoutElement extends LitElement {
+ ${this.loading ? html`` : nothing}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts index 61620df0db7c..7b23377d0615 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts @@ -32,6 +32,9 @@ export class UmbWorkspaceEditorElement extends UmbLitElement { @property({ attribute: 'back-path' }) public backPath?: string; + @property({ type: Boolean }) + public loading = false; + @state() private _workspaceViews: Array = []; @@ -83,7 +86,7 @@ export class UmbWorkspaceEditorElement extends UmbLitElement { override render() { return html` - + ${this.#renderBackButton()} ${this.#renderViews()} 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 d7647ae8064d..897d37068f64 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,16 +26,15 @@ export class UmbWorkspaceEntityActionMenuElement extends UmbLitElement { this.consumeContext(UMB_ENTITY_WORKSPACE_CONTEXT, (context) => { this._workspaceContext = context; - this._observeInfo(); + 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. + this._entityType = this._workspaceContext?.getEntityType(); + }); }); } - private _observeInfo() { - if (!this._workspaceContext) return; - this._unique = this._workspaceContext.getUnique(); - this._entityType = this._workspaceContext.getEntityType(); - } - #onActionExecuted(event: UmbActionExecutedEvent) { event.stopPropagation(); 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 b6af4f272889..bcb4b29eef42 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 @@ -1,5 +1,6 @@ import { UmbSubmittableWorkspaceContextBase } from '../submittable/index.js'; import { UmbEntityWorkspaceDataManager } from '../entity/entity-workspace-data-manager.js'; +import type { UmbEntityDetailWorkspaceContextArgs, UmbEntityDetailWorkspaceContextCreateArgs } from './types.js'; import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbEntityContext, type UmbEntityModel, type UmbEntityUnique } from '@umbraco-cms/backoffice/entity'; @@ -12,29 +13,19 @@ import { import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry, type ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbDetailRepository } from '@umbraco-cms/backoffice/repository'; +import { UmbStateManager } from '@umbraco-cms/backoffice/utils'; -export interface UmbEntityDetailWorkspaceContextArgs { - entityType: string; - workspaceAlias: string; - detailRepositoryAlias: string; -} - -/** - * @deprecated Use UmbEntityDetailWorkspaceContextArgs instead - */ -export type UmbEntityWorkspaceContextArgs = UmbEntityDetailWorkspaceContextArgs; - -export interface UmbEntityDetailWorkspaceContextCreateArgs { - parent: UmbEntityModel; - preset?: Partial; -} +const LOADING_STATE_UNIQUE = 'umbLoadingEntityDetail'; export abstract class UmbEntityDetailWorkspaceContextBase< - DetailModelType extends UmbEntityModel, + DetailModelType extends UmbEntityModel = UmbEntityModel, DetailRepositoryType extends UmbDetailRepository = UmbDetailRepository, CreateArgsType extends UmbEntityDetailWorkspaceContextCreateArgs = UmbEntityDetailWorkspaceContextCreateArgs, > extends UmbSubmittableWorkspaceContextBase { + // Just for context token safety: + public readonly IS_ENTITY_DETAIL_WORKSPACE_CONTEXT = true; + /** * @description Data manager for the workspace. * @protected @@ -42,15 +33,16 @@ export abstract class UmbEntityDetailWorkspaceContextBase< */ protected readonly _data = new UmbEntityWorkspaceDataManager(this); + #entityContext = new UmbEntityContext(this); + public readonly entityType = this.#entityContext.entityType; + public readonly unique = this.#entityContext.unique; + public readonly data = this._data.current; + public readonly loading = new UmbStateManager(this); protected _getDataPromise?: Promise; protected _detailRepository?: DetailRepositoryType; - #entityContext = new UmbEntityContext(this); - public readonly entityType = this.#entityContext.entityType; - public readonly unique = this.#entityContext.unique; - #parent = new UmbObjectState<{ entityType: string; unique: UmbEntityUnique } | undefined>(undefined); public readonly parentUnique = this.#parent.asObservablePart((parent) => (parent ? parent.unique : undefined)); public readonly parentEntityType = this.#parent.asObservablePart((parent) => @@ -131,6 +123,7 @@ export abstract class UmbEntityDetailWorkspaceContextBase< async load(unique: string) { this.#entityContext.setUnique(unique); + this.loading.addState({ unique: LOADING_STATE_UNIQUE, message: `Loading ${this.getEntityType()} Details` }); await this.#init; this.resetState(); this._getDataPromise = this._detailRepository!.requestByUnique(unique); @@ -142,8 +135,15 @@ export abstract class UmbEntityDetailWorkspaceContextBase< this._data.setPersisted(data); this._data.setCurrent(data); this.setIsNew(false); + + this.observe( + response.asObservable(), + (entity) => this.#onDetailStoreChange(entity), + 'umbEntityDetailTypeStoreObserver', + ); } + this.loading.removeState(LOADING_STATE_UNIQUE); return response; } @@ -166,6 +166,7 @@ export abstract class UmbEntityDetailWorkspaceContextBase< * @returns { Promise | undefined } The data of the scaffold. */ public async createScaffold(args: CreateArgsType) { + this.loading.addState({ unique: LOADING_STATE_UNIQUE, message: `Creating ${this.getEntityType()} scaffold` }); await this.#init; this.resetState(); this.setParent(args.parent); @@ -173,17 +174,20 @@ export abstract class UmbEntityDetailWorkspaceContextBase< const request = this._detailRepository!.createScaffold(args.preset); this._getDataPromise = request; let { data } = await request; - if (!data) return undefined; - this.#entityContext.setUnique(data.unique); + if (data) { + this.#entityContext.setUnique(data.unique); + + if (this.modalContext) { + data = { ...data, ...this.modalContext.data.preset }; + } - if (this.modalContext) { - data = { ...data, ...this.modalContext.data.preset }; + this.setIsNew(true); + this._data.setPersisted(data); + this._data.setCurrent(data); } - this.setIsNew(true); - this._data.setPersisted(data); - this._data.setCurrent(data); + this.loading.removeState(LOADING_STATE_UNIQUE); return data; } @@ -284,9 +288,9 @@ export abstract class UmbEntityDetailWorkspaceContextBase< } if (this._checkWillNavigateAway(newUrl) && this._getHasUnpersistedChanges()) { - /* Since ours modals are async while events are synchronous, we need to prevent the default behavior of the event, even if the modal hasn’t been resolved yet. - Once the modal is resolved (the user accepted to discard the changes and navigate away from the route), we will push a new history state. - This push will make the "willchangestate" event happen again and due to this somewhat "backward" behavior, + /* Since ours modals are async while events are synchronous, we need to prevent the default behavior of the event, even if the modal hasn’t been resolved yet. + Once the modal is resolved (the user accepted to discard the changes and navigate away from the route), we will push a new history state. + This push will make the "willchangestate" event happen again and due to this somewhat "backward" behavior, we set an "allowNavigateAway"-flag to prevent the "discard-changes" functionality from running in a loop.*/ e.preventDefault(); const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); @@ -342,6 +346,12 @@ export abstract class UmbEntityDetailWorkspaceContextBase< ); } + #onDetailStoreChange(entity: DetailModelType | undefined) { + if (!entity) { + this._data.clear(); + } + } + public override destroy(): void { window.removeEventListener('willchangestate', this.#onWillNavigate); this._detailRepository?.destroy(); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace.context-token.ts new file mode 100644 index 000000000000..a548bbb3411a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/entity-detail-workspace.context-token.ts @@ -0,0 +1,12 @@ +import type { UmbWorkspaceContext } from '../workspace-context.interface.js'; +import type { UmbEntityDetailWorkspaceContextBase } from './entity-detail-workspace-base.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; + +export const UMB_ENTITY_DETAIL_WORKSPACE_CONTEXT = new UmbContextToken< + UmbWorkspaceContext, + UmbEntityDetailWorkspaceContextBase +>( + 'UmbWorkspaceContext', + undefined, + (context): context is UmbEntityDetailWorkspaceContextBase => (context as any).IS_ENTITY_DETAIL_WORKSPACE_CONTEXT, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-not-found.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-not-found.element.ts new file mode 100644 index 000000000000..13662f4a6145 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-not-found.element.ts @@ -0,0 +1,50 @@ +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +@customElement('umb-entity-detail-not-found') +export class UmbEntityDetailNotFoundElement extends UmbLitElement { + @property({ type: String, attribute: 'entity-type' }) + entityType = ''; + + override render() { + return html` +
+

${this.localize.term('entityDetail_notFoundTitle', this.entityType)}

+ ${this.localize.term('entityDetail_notFoundDescription', this.entityType)} +
+ `; + } + + static override styles = [ + UmbTextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + min-width: 0; + } + + :host > div { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100%; + } + + @keyframes fadeIn { + 100% { + opacity: 100%; + } + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-entity-detail-not-found': UmbEntityDetailNotFoundElement; + } +} 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 new file mode 100644 index 000000000000..8add4ff8b902 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/entity-detail-workspace-editor.element.ts @@ -0,0 +1,77 @@ +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_ENTITY_DETAIL_WORKSPACE_CONTEXT } from '../entity-detail-workspace.context-token.js'; +import { css, customElement, html, ifDefined, nothing, property, state } from '@umbraco-cms/backoffice/external/lit'; + +@customElement('umb-entity-detail-workspace-editor') +export class UmbEntityDetailWorkspaceEditorElement extends UmbLitElement { + @property({ attribute: 'back-path' }) + public backPath?: string; + + @state() + private _entityType?: string; + + @state() + private _isLoading = false; + + @state() + private _exists = false; + + @state() + private _isNew? = false; + + #context?: typeof UMB_ENTITY_DETAIL_WORKSPACE_CONTEXT.TYPE; + + constructor() { + super(); + + 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?.data, (data) => (this._exists = !!data)); + this.observe(this.#context?.isNew, (isNew) => (this._isNew = isNew)); + }); + } + + protected override render() { + return html` ${!this._exists && !this._isLoading + ? html`` + : nothing} + + + + + ${this.#renderEntityActions()} + + `; + } + + #renderEntityActions() { + if (this._isNew) return nothing; + return html``; + } + + static override styles = [ + css` + umb-workspace-editor { + visibility: visible; + } + + umb-workspace-editor.hide { + visibility: hidden; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-entity-detail-workspace-editor': UmbEntityDetailWorkspaceEditorElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/index.ts new file mode 100644 index 000000000000..e6c2301b73fc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/global-components/index.ts @@ -0,0 +1,5 @@ +import './entity-detail-not-found.element.js'; +import './entity-detail-workspace-editor.element.js'; + +export * from './entity-detail-not-found.element.js'; +export * from './entity-detail-workspace-editor.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts index df254d21f0b9..ff2ab6d70c3d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/index.ts @@ -1 +1,5 @@ +import './global-components/index.js'; + export * from './entity-detail-workspace-base.js'; +export * from './global-components/index.js'; +export type * from './types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts new file mode 100644 index 000000000000..97bcf40aa501 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/entity-detail/types.ts @@ -0,0 +1,17 @@ +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; + +export interface UmbEntityDetailWorkspaceContextArgs { + entityType: string; + workspaceAlias: string; + detailRepositoryAlias: string; +} + +/** + * @deprecated Use UmbEntityDetailWorkspaceContextArgs instead + */ +export type UmbEntityWorkspaceContextArgs = UmbEntityDetailWorkspaceContextArgs; + +export interface UmbEntityDetailWorkspaceContextCreateArgs { + parent: UmbEntityModel; + preset?: Partial; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index 770523ca9967..d18c4a1451fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -1,3 +1,5 @@ +import './entity-detail/global-components/index.js'; + export * from './components/index.js'; export * from './conditions/const.js'; export * from './contexts/index.js'; @@ -15,3 +17,4 @@ export * from './workspace.context-token.js'; export * from './workspace.element.js'; export type * from './conditions/index.js'; export type * from './types.js'; +export * from './entity-detail/global-components/index.js'; 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 578ff818a0bb..941c7a064ca5 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 @@ -3,4 +3,6 @@ import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; export interface UmbWorkspaceContext extends UmbApi { 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/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 7456daa033c2..49ede5f33974 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 @@ -17,9 +17,9 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement { override render() { return html` - + - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 243e17d46bcb..eb2f69532f1e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -114,19 +114,6 @@ export class UmbDataTypeWorkspaceContext ]); } - override async load(unique: string) { - const response = await super.load(unique); - this.observe(response.asObservable?.(), (entity) => this.#onStoreChange(entity), 'umbDataTypeStoreObserver'); - return response; - } - - #onStoreChange(entity: EntityType | undefined) { - if (!entity) { - //TODO: This solution is alright for now. But reconsider when we introduce signal-r - history.pushState(null, '', 'section/settings/workspace/data-type-root'); - } - } - override resetState() { super.resetState(); this.#propertyEditorSchemaSettingsProperties = []; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts index 68314a229646..18529e2e86fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/dictionary-workspace-editor.element.ts @@ -6,9 +6,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement { override render() { return html` - + - + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/paths.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/paths.ts new file mode 100644 index 000000000000..67151808ab5c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language-root/paths.ts @@ -0,0 +1,8 @@ +import { UMB_SETTINGS_SECTION_PATHNAME } from '@umbraco-cms/backoffice/settings'; +import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; +import { UMB_LANGUAGE_ROOT_ENTITY_TYPE } from '../../entity.js'; + +export const UMB_LANGUAGE_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_SETTINGS_SECTION_PATHNAME, + entityType: UMB_LANGUAGE_ROOT_ENTITY_TYPE, +}); 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 64c379d4ab3a..c7fa01b792b9 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 @@ -2,6 +2,7 @@ import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from './language-workspace.context-tok import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UMB_LANGUAGE_ROOT_WORKSPACE_PATH } from '../language-root/paths.js'; @customElement('umb-language-workspace-editor') export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { #workspaceContext?: typeof UMB_LANGUAGE_WORKSPACE_CONTEXT.TYPE; @@ -19,11 +20,11 @@ export class UmbLanguageWorkspaceEditorElement extends UmbLitElement { } override render() { - return html` + return html` ${this._isNew ? html`

Add language

` - : html``} -
`; + : html` `} + `; } static override styles = [UmbTextStyles]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts index 7ac43079ade5..50ce0fd57106 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace-editor.element.ts @@ -1,40 +1,15 @@ import { UMB_MEMBER_GROUP_ROOT_WORKSPACE_PATH } from '../../paths.js'; -import { UMB_MEMBER_GROUP_WORKSPACE_CONTEXT } from './member-group-workspace.context-token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-member-group-workspace-editor') export class UmbMemberGroupWorkspaceEditorElement extends UmbLitElement { - @state() - private _unique?: string; - - #workspaceContext?: typeof UMB_MEMBER_GROUP_WORKSPACE_CONTEXT.TYPE; - - constructor() { - super(); - - this.consumeContext(UMB_MEMBER_GROUP_WORKSPACE_CONTEXT, (workspaceContext) => { - this.#workspaceContext = workspaceContext; - if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.unique, (unique) => (this._unique = unique ?? undefined)); - }); - } - - #renderActions() { - // Actions only works if we have a valid unique. - if (!this._unique || this.#workspaceContext?.getIsNew()) return nothing; - - return html``; - } - override render() { return html` - + - ${this.#renderActions()} - - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts index 7b8c8f56870c..cfd7df9b5795 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/workspace/member-group/member-group-workspace.context.ts @@ -50,24 +50,6 @@ export class UmbMemberGroupWorkspaceContext ]); } - override async load(unique: string) { - const response = await super.load(unique); - - this.observe( - response.asObservable?.(), - (memberGroup) => this.#onMemberGroupStoreChange(memberGroup), - 'umbMemberGroupStoreObserver', - ); - - return response; - } - - #onMemberGroupStoreChange(memberGroup: UmbMemberGroupDetailModel | undefined) { - if (!memberGroup) { - history.pushState(null, '', 'section/member-management/view/member-groups'); - } - } - getName() { return this._data.getCurrent()?.name; } 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 b7307edf859b..f5a7e79e8ea1 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 @@ -77,9 +77,8 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement { } override render() { - if (this._isNew === undefined) return; return html` - +
${this.#renderCodeEditor()} - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts index a26d2a1b5e23..4306af8a0a2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts @@ -96,20 +96,6 @@ export class UmbPartialViewWorkspaceContext this._data.updateCurrent({ content: value }); } - override async load(unique: string) { - const response = await super.load(unique); - this.observe(response.asObservable?.(), (data) => this.#onDetailStoreChanges(data), 'umbDetailStoreObserver'); - return response; - } - - #onDetailStoreChanges(data: UmbPartialViewDetailModel | undefined) { - // Data is removed from the store - // TODO: revisit. We need to handle what should happen when the data is removed from the store - if (data === undefined) { - this._data.clear(); - } - } - override async createScaffold(args: UmbPartialViewWorkspaceContextCreateArgs) { let snippetContent = ''; 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 52b5880fb024..461790808780 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 @@ -52,9 +52,8 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement { } override render() { - if (this._isNew === undefined) return; return html` - +
${this.#renderCodeEditor()} -
+ `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace.context.ts index 4bdc50a90ace..37308ec33a3d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/scripts/workspace/script-workspace.context.ts @@ -70,26 +70,6 @@ export class UmbScriptWorkspaceContext public setContent(value: string) { this._data.updateCurrent({ content: value }); } - - /** - * @description load the script - * @param unique The unique identifier of the script - * @returns {Promise} - * @memberof UmbScriptWorkspaceContext - */ - public override async load(unique: string) { - const response = await super.load(unique); - this.observe(response.asObservable?.(), (data) => this.#onDetailStoreChanges(data), 'umbDetailStoreObserver'); - return response; - } - - #onDetailStoreChanges(data: UmbScriptDetailModel | undefined) { - // Data is removed from the store - // TODO: revisit. We need to handle what should happen when the data is removed from the store - if (data === undefined) { - this._data.clear(); - } - } } export { UmbScriptWorkspaceContext as api }; 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 a883906a8345..3fb1a5563542 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 @@ -160,7 +160,7 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement { override render() { // TODO: add correct UI elements return html` - + - + `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts index c335e070a7eb..faad3211aee1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts @@ -168,12 +168,10 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { } override render() { - if (!this._unique) return nothing; - return html` - + ${this.#renderHeader()} ${this.#renderMain()} - + `; } @@ -219,8 +217,6 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { ${umbFocus()}>
- - `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace-editor.element.ts index 14346584fc4d..db74c4e2a4db 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace-editor.element.ts @@ -35,24 +35,19 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { } override render() { - if (!this._user) return html`User not found`; - return html` - + ${this.#renderHeader()}
${this.#renderLeftColumn()}
${this.#renderRightColumn()}
-
+
`; } #renderHeader() { - return html` - - - `; + return html` `; } #renderLeftColumn() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts index 5b0d7572db0e..8d0b4c3a1e9d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user/user-workspace.context.ts @@ -82,12 +82,9 @@ export class UmbUserWorkspaceContext There might be a less manual way to do this. */ onUserStoreChanges(user: EntityType | undefined) { - if (!user) { - //TODO: This solution is alright for now. But reconsider when we introduce signal-r - history.pushState(null, '', 'section/user-management'); - return; + if (user) { + this._data.updateCurrent({ state: user.state, avatarUrls: user.avatarUrls }); } - this._data.updateCurrent({ state: user.state, avatarUrls: user.avatarUrls }); } getState(): UmbUserStateEnum | null | undefined { diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/webhook-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/webhook-workspace-editor.element.ts index 1f190a1b04f4..6532bb03aa7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/webhook-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/webhook-workspace-editor.element.ts @@ -4,7 +4,10 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @customElement('umb-webhook-workspace-editor') export class UmbWebhookWorkspaceEditorElement extends UmbLitElement { override render() { - return html` `; + return html` + + `; } static override styles = [UmbTextStyles];