Fix: Add "Not Found" empty state to detail workspaces (#17489)
Co-authored-by: Niels Lyngsø <nsl@umbraco.dk> Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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 div should be changed for the uui-scroll-container when it gets updated -->
|
||||
<div id="main">
|
||||
${this.loading ? html`<uui-loader-bar></uui-loader-bar>` : nothing}
|
||||
<slot></slot>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -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<ManifestWorkspaceView> = [];
|
||||
|
||||
@@ -83,7 +86,7 @@ export class UmbWorkspaceEditorElement extends UmbLitElement {
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-body-layout main-no-padding .headline=${this.headline}>
|
||||
<umb-body-layout main-no-padding .headline=${this.headline} ?loading=${this.loading}>
|
||||
${this.#renderBackButton()}
|
||||
<slot name="header" slot="header"></slot>
|
||||
${this.#renderViews()}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<DetailModelType> {
|
||||
parent: UmbEntityModel;
|
||||
preset?: Partial<DetailModelType>;
|
||||
}
|
||||
const LOADING_STATE_UNIQUE = 'umbLoadingEntityDetail';
|
||||
|
||||
export abstract class UmbEntityDetailWorkspaceContextBase<
|
||||
DetailModelType extends UmbEntityModel,
|
||||
DetailModelType extends UmbEntityModel = UmbEntityModel,
|
||||
DetailRepositoryType extends UmbDetailRepository<DetailModelType> = UmbDetailRepository<DetailModelType>,
|
||||
CreateArgsType extends
|
||||
UmbEntityDetailWorkspaceContextCreateArgs<DetailModelType> = UmbEntityDetailWorkspaceContextCreateArgs<DetailModelType>,
|
||||
> extends UmbSubmittableWorkspaceContextBase<DetailModelType> {
|
||||
// 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<DetailModelType>(this);
|
||||
|
||||
public readonly data = this._data.current;
|
||||
|
||||
protected _getDataPromise?: Promise<any>;
|
||||
protected _detailRepository?: DetailRepositoryType;
|
||||
|
||||
#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<any>;
|
||||
protected _detailRepository?: DetailRepositoryType;
|
||||
|
||||
#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<any> | 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();
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
@@ -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`
|
||||
<div class="uui-text">
|
||||
<h4>${this.localize.term('entityDetail_notFoundTitle', this.entityType)}</h4>
|
||||
${this.localize.term('entityDetail_notFoundDescription', this.entityType)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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`<umb-entity-detail-not-found entity-type=${ifDefined(this._entityType)}></umb-entity-detail-not-found>`
|
||||
: nothing}
|
||||
|
||||
<!-- TODO: It is currently on purpose that the workspace editor is always in the DOM, even when it doesn't have data.
|
||||
We currently rely on the entity actions to be available to execute, and we ran into an issue when the entity got deleted; then the DOM got cleared, and the delete action couldn't complete.
|
||||
We need to look into loading the entity actions in the workspace context instead so we don't rely on the DOM.
|
||||
-->
|
||||
<umb-workspace-editor
|
||||
?loading=${this._isLoading}
|
||||
.backPath=${this.backPath}
|
||||
class="${this._exists === false ? 'hide' : ''}">
|
||||
<slot name="header" slot="header"></slot>
|
||||
${this.#renderEntityActions()}
|
||||
<slot></slot>
|
||||
</umb-workspace-editor>`;
|
||||
}
|
||||
|
||||
#renderEntityActions() {
|
||||
if (this._isNew) return nothing;
|
||||
return html`<umb-workspace-entity-action-menu slot="action-menu"></umb-workspace-entity-action-menu>`;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
@@ -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';
|
||||
|
||||
@@ -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<DetailModelType> {
|
||||
parent: UmbEntityModel;
|
||||
preset?: Partial<DetailModelType>;
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ export class UmbDataTypeWorkspaceEditorElement extends UmbLitElement {
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-workspace-editor>
|
||||
<umb-entity-detail-workspace-editor>
|
||||
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -6,9 +6,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
|
||||
export class UmbDictionaryWorkspaceEditorElement extends UmbLitElement {
|
||||
override render() {
|
||||
return html`
|
||||
<umb-workspace-editor back-path=${UMB_DICTIONARY_OVERVIEW_DASHBOARD_PATH}>
|
||||
<umb-entity-detail-workspace-editor .backPath=${UMB_DICTIONARY_OVERVIEW_DASHBOARD_PATH}>
|
||||
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
@@ -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`<umb-workspace-editor back-path="section/settings/workspace/language-root">
|
||||
return html`<umb-entity-detail-workspace-editor .backPath=${UMB_LANGUAGE_ROOT_WORKSPACE_PATH}>
|
||||
${this._isNew
|
||||
? html`<h3 slot="header">Add language</h3>`
|
||||
: html`<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>`}
|
||||
</umb-workspace-editor>`;
|
||||
: html`<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable> `}
|
||||
</umb-entity-detail-workspace-editor>`;
|
||||
}
|
||||
|
||||
static override styles = [UmbTextStyles];
|
||||
|
||||
@@ -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`<umb-workspace-entity-action-menu slot="action-menu"></umb-workspace-entity-action-menu>`;
|
||||
}
|
||||
|
||||
override render() {
|
||||
return html`
|
||||
<umb-workspace-editor back-path=${UMB_MEMBER_GROUP_ROOT_WORKSPACE_PATH}>
|
||||
<umb-entity-detail-workspace-editor .backPath=${UMB_MEMBER_GROUP_ROOT_WORKSPACE_PATH}>
|
||||
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
|
||||
${this.#renderActions()}
|
||||
<umb-workspace-entity-action-menu slot="action-menu"></umb-workspace-entity-action-menu>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -77,9 +77,8 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (this._isNew === undefined) return;
|
||||
return html`
|
||||
<umb-workspace-editor>
|
||||
<umb-entity-detail-workspace-editor>
|
||||
<div id="workspace-header" slot="header">
|
||||
<uui-input
|
||||
placeholder=${this.localize.term('placeholders_entername')}
|
||||
@@ -103,7 +102,7 @@ export class UmbPartialViewWorkspaceEditorElement extends UmbLitElement {
|
||||
</div>
|
||||
${this.#renderCodeEditor()}
|
||||
</uui-box>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = '';
|
||||
|
||||
|
||||
@@ -52,9 +52,8 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (this._isNew === undefined) return;
|
||||
return html`
|
||||
<umb-workspace-editor>
|
||||
<umb-entity-detail-workspace-editor>
|
||||
<div id="workspace-header" slot="header">
|
||||
<uui-input
|
||||
placeholder=${this.localize.term('placeholders_entername')}
|
||||
@@ -70,7 +69,7 @@ export class UmbScriptWorkspaceEditorElement extends UmbLitElement {
|
||||
<div slot="header"></div>
|
||||
${this.#renderCodeEditor()}
|
||||
</uui-box>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<void>}
|
||||
* @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 };
|
||||
|
||||
@@ -160,7 +160,7 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement {
|
||||
override render() {
|
||||
// TODO: add correct UI elements
|
||||
return html`
|
||||
<umb-workspace-editor>
|
||||
<umb-entity-detail-workspace-editor>
|
||||
<umb-input-with-alias
|
||||
slot="header"
|
||||
id="name"
|
||||
@@ -195,7 +195,7 @@ export class UmbTemplateWorkspaceEditorElement extends UmbLitElement {
|
||||
|
||||
${this.#renderCodeEditor()}
|
||||
</uui-box>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,12 +168,10 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this._unique) return nothing;
|
||||
|
||||
return html`
|
||||
<umb-workspace-editor class="uui-text" back-path=${UMB_USER_GROUP_ROOT_WORKSPACE_PATH}>
|
||||
<umb-entity-detail-workspace-editor class="uui-text" back-path=${UMB_USER_GROUP_ROOT_WORKSPACE_PATH}>
|
||||
${this.#renderHeader()} ${this.#renderMain()}
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -219,8 +217,6 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement {
|
||||
${umbFocus()}>
|
||||
</umb-input-with-alias>
|
||||
</div>
|
||||
|
||||
<umb-workspace-entity-action-menu slot="action-menu"></umb-workspace-entity-action-menu>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,24 +35,19 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement {
|
||||
}
|
||||
|
||||
override render() {
|
||||
if (!this._user) return html`User not found`;
|
||||
|
||||
return html`
|
||||
<umb-workspace-editor class="uui-text" back-path=${UMB_USER_ROOT_WORKSPACE_PATH}>
|
||||
<umb-entity-detail-workspace-editor class="uui-text" .backPath=${UMB_USER_ROOT_WORKSPACE_PATH}>
|
||||
${this.#renderHeader()}
|
||||
<div id="main">
|
||||
<div id="left-column">${this.#renderLeftColumn()}</div>
|
||||
<div id="right-column">${this.#renderRightColumn()}</div>
|
||||
</div>
|
||||
</umb-workspace-editor>
|
||||
</umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
#renderHeader() {
|
||||
return html`
|
||||
<umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>
|
||||
<umb-workspace-entity-action-menu slot="action-menu"></umb-workspace-entity-action-menu>
|
||||
`;
|
||||
return html` <umb-workspace-header-name-editable slot="header"></umb-workspace-header-name-editable>`;
|
||||
}
|
||||
|
||||
#renderLeftColumn() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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` <umb-workspace-editor back-path="section/settings/workspace/webhook-root"></umb-workspace-editor> `;
|
||||
return html`
|
||||
<umb-entity-detail-workspace-editor
|
||||
back-path="section/settings/workspace/webhook-root"></umb-entity-detail-workspace-editor>
|
||||
`;
|
||||
}
|
||||
|
||||
static override styles = [UmbTextStyles];
|
||||
|
||||
Reference in New Issue
Block a user