Saveable workspace interface + token (#19220)
Co-authored-by: Mads Rasmussen <madsr@hey.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
UmbWorkspaceSplitViewManager,
|
||||
type UmbEntityDetailWorkspaceContextArgs,
|
||||
type UmbEntityDetailWorkspaceContextCreateArgs,
|
||||
type UmbSaveableWorkspaceContext,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
import {
|
||||
UmbContentTypeStructureManager,
|
||||
@@ -97,7 +98,9 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
UmbEntityDetailWorkspaceContextCreateArgs<DetailModelType> = UmbEntityDetailWorkspaceContextCreateArgs<DetailModelType>,
|
||||
>
|
||||
extends UmbEntityDetailWorkspaceContextBase<DetailModelType, DetailRepositoryType, CreateArgsType>
|
||||
implements UmbContentWorkspaceContext<DetailModelType, ContentTypeDetailModelType, VariantModelType>
|
||||
implements
|
||||
UmbContentWorkspaceContext<DetailModelType, ContentTypeDetailModelType, VariantModelType>,
|
||||
UmbSaveableWorkspaceContext
|
||||
{
|
||||
public readonly IS_CONTENT_WORKSPACE_CONTEXT = true as const;
|
||||
|
||||
@@ -778,6 +781,14 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
return this._handleSubmit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a save of the workspace, in the case of Document Workspaces the validation does not need to be valid for this to be saved.
|
||||
* @returns {Promise<void>} a promise which resolves once it has been completed.
|
||||
*/
|
||||
public requestSave() {
|
||||
return this._handleSave();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data to save
|
||||
* @param {Array<UmbVariantId>} variantIds - The variant ids to save
|
||||
@@ -789,6 +800,10 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
}
|
||||
|
||||
protected async _handleSubmit() {
|
||||
await this._handleSave();
|
||||
this._closeModal();
|
||||
}
|
||||
protected async _handleSave() {
|
||||
const data = this.getData();
|
||||
if (!data) {
|
||||
throw new Error('Data is missing');
|
||||
@@ -818,8 +833,8 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
|
||||
variantIds = result?.selection.map((x) => UmbVariantId.FromString(x)) ?? [];
|
||||
} else {
|
||||
/* If there are multiple variants but no modal token is set
|
||||
we will save the variants that would have been preselected in the modal.
|
||||
/* If there are multiple variants but no modal token is set
|
||||
we will save the variants that would have been preselected in the modal.
|
||||
These are based on the variants that have been edited */
|
||||
variantIds = selected.map((x) => UmbVariantId.FromString(x));
|
||||
}
|
||||
@@ -829,18 +844,13 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
await this.runMandatoryValidationForSaveData(saveData, variantIds);
|
||||
if (this.#validateOnSubmit) {
|
||||
await this.askServerToValidate(saveData, variantIds);
|
||||
return this.validateAndSubmit(
|
||||
async () => {
|
||||
return this.performCreateOrUpdate(variantIds, saveData);
|
||||
},
|
||||
async (reason?: any) => {
|
||||
if (this.#ignoreValidationResultOnSubmit) {
|
||||
return this.performCreateOrUpdate(variantIds, saveData);
|
||||
} else {
|
||||
return this.invalidSubmit(reason);
|
||||
}
|
||||
},
|
||||
const valid = await this._validateAndLog().then(
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
if (valid || this.#ignoreValidationResultOnSubmit) {
|
||||
return this.performCreateOrUpdate(variantIds, saveData);
|
||||
}
|
||||
} else {
|
||||
await this.performCreateOrUpdate(variantIds, saveData);
|
||||
}
|
||||
@@ -915,8 +925,6 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
});
|
||||
eventContext.dispatchEvent(event);
|
||||
this.setIsNew(false);
|
||||
|
||||
this._closeModal();
|
||||
}
|
||||
|
||||
async #update(variantIds: Array<UmbVariantId>, saveData: DetailModelType) {
|
||||
@@ -966,8 +974,6 @@ export abstract class UmbContentDetailWorkspaceContextBase<
|
||||
});
|
||||
|
||||
eventContext.dispatchEvent(updatedEvent);
|
||||
|
||||
this._closeModal();
|
||||
}
|
||||
|
||||
override resetState() {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './save/index.js';
|
||||
export * from './submit/index.js';
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './save.action.js';
|
||||
export type * from './types.js';
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { MetaWorkspaceAction } from '../../../../types.js';
|
||||
import { UMB_SAVEABLE_WORKSPACE_CONTEXT } from '../../../../contexts/tokens/index.js';
|
||||
import type { UmbSaveableWorkspaceContext } from '../../../../contexts/tokens/index.js';
|
||||
import { UmbWorkspaceActionBase } from '../../workspace-action-base.controller.js';
|
||||
import type { UmbSaveWorkspaceActionArgs } from './types.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
|
||||
export class UmbSaveWorkspaceAction<
|
||||
ArgsMetaType extends MetaWorkspaceAction = MetaWorkspaceAction,
|
||||
WorkspaceContextType extends UmbSaveableWorkspaceContext = UmbSaveableWorkspaceContext,
|
||||
> extends UmbWorkspaceActionBase<ArgsMetaType> {
|
||||
protected _retrieveWorkspaceContext: Promise<unknown>;
|
||||
protected _workspaceContext?: WorkspaceContextType;
|
||||
|
||||
constructor(host: UmbControllerHost, args: UmbSaveWorkspaceActionArgs<ArgsMetaType, WorkspaceContextType>) {
|
||||
super(host, args);
|
||||
|
||||
this._retrieveWorkspaceContext = this.consumeContext(
|
||||
args.workspaceContextToken ?? UMB_SAVEABLE_WORKSPACE_CONTEXT,
|
||||
(context) => {
|
||||
this._workspaceContext = context as WorkspaceContextType | undefined;
|
||||
this.#observeUnique();
|
||||
this._gotWorkspaceContext();
|
||||
},
|
||||
).asPromise();
|
||||
}
|
||||
|
||||
#observeUnique() {
|
||||
this.observe(
|
||||
this._workspaceContext?.unique,
|
||||
(unique) => {
|
||||
// We can't save if we don't have a unique
|
||||
if (unique === undefined) {
|
||||
this.disable();
|
||||
} else {
|
||||
// Dangerous, cause this could enable despite a class extension decided to disable it?. [NL]
|
||||
this.enable();
|
||||
}
|
||||
},
|
||||
'saveWorkspaceActionUniqueObserver',
|
||||
);
|
||||
}
|
||||
|
||||
protected _gotWorkspaceContext() {
|
||||
// Override in subclass
|
||||
}
|
||||
|
||||
override async execute() {
|
||||
await this._retrieveWorkspaceContext;
|
||||
return await this._workspaceContext?.requestSave();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { UmbSaveableWorkspaceContext, UmbWorkspaceContext } from '../../../../contexts/index.js';
|
||||
import type { UmbWorkspaceActionArgs } from '../../types.js';
|
||||
import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export interface UmbSaveWorkspaceActionArgs<MetaArgsType, WorkspaceContextType extends UmbSaveableWorkspaceContext>
|
||||
extends UmbWorkspaceActionArgs<MetaArgsType> {
|
||||
workspaceContextToken?: string | UmbContextToken<UmbWorkspaceContext, WorkspaceContextType>;
|
||||
}
|
||||
@@ -51,8 +51,3 @@ export class UmbSubmitWorkspaceAction<
|
||||
return await this._workspaceContext!.requestSubmit();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @deprecated Use UmbSubmitWorkspaceAction instead
|
||||
*/
|
||||
export { UmbSubmitWorkspaceAction as UmbSaveWorkspaceAction };
|
||||
|
||||
@@ -2,11 +2,13 @@ export * from './entity-workspace.context-token.js';
|
||||
export * from './publishable-workspace.context-token.js';
|
||||
export * from './routable-workspace.context-token.js';
|
||||
export * from './submittable-workspace.context-token.js';
|
||||
export * from './saveable-workspace.context-token.js';
|
||||
export * from './variant-workspace.context-token.js';
|
||||
export type * from './entity-workspace-context.interface.js';
|
||||
export type * from './invariant-dataset-workspace-context.interface.js';
|
||||
export type * from './publishable-workspace-context.interface.js';
|
||||
export type * from './routable-workspace-context.interface.js';
|
||||
export type * from './submittable-workspace-context.interface.js';
|
||||
export type * from './saveable-workspace-context.interface.js';
|
||||
export type * from './variant-dataset-workspace-context.interface.js';
|
||||
export type * from '../../workspace-context.interface.js';
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { UmbSubmittableWorkspaceContext } from './submittable-workspace-context.interface.js';
|
||||
|
||||
export interface UmbSaveableWorkspaceContext extends UmbSubmittableWorkspaceContext {
|
||||
requestSave(): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { UmbWorkspaceContext } from '../../types.js';
|
||||
import type { UmbSaveableWorkspaceContext } from './saveable-workspace-context.interface.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
|
||||
export const UMB_SAVEABLE_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbSaveableWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbSaveableWorkspaceContext => 'requestSave' in context,
|
||||
);
|
||||
@@ -84,6 +84,17 @@ export abstract class UmbSubmittableWorkspaceContextBase<WorkspaceDataModelType>
|
||||
);
|
||||
}
|
||||
|
||||
protected async _validateAndLog(): Promise<void> {
|
||||
await this.validate().catch(async () => {
|
||||
// TODO: Implement developer-mode logging here. [NL]
|
||||
console.warn(
|
||||
'Validation failed because of these validation messages still begin present: ',
|
||||
this.#validationContexts.flatMap((x) => x.messages.getMessages()),
|
||||
);
|
||||
return Promise.reject();
|
||||
});
|
||||
}
|
||||
|
||||
public async validateAndSubmit(
|
||||
onValid: () => Promise<void>,
|
||||
onInvalid: (reason?: any) => Promise<void>,
|
||||
@@ -95,16 +106,11 @@ export abstract class UmbSubmittableWorkspaceContextBase<WorkspaceDataModelType>
|
||||
this.#submitResolve = resolve;
|
||||
this.#submitReject = reject;
|
||||
});
|
||||
this.validate().then(
|
||||
this._validateAndLog().then(
|
||||
async () => {
|
||||
onValid().then(this.#completeSubmit, this.#rejectSubmit);
|
||||
},
|
||||
async (error) => {
|
||||
// TODO: Implement developer-mode logging here. [NL]
|
||||
console.warn(
|
||||
'Validation failed because of these validation messages still begin present: ',
|
||||
this.#validationContexts.flatMap((x) => x.messages.getMessages()),
|
||||
);
|
||||
onInvalid(error).then(this.#resolveSubmit, this.#rejectSubmit);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -3,17 +3,20 @@ import type UmbDocumentWorkspaceContext from '../document-workspace.context.js';
|
||||
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
||||
import { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||
import {
|
||||
UmbSubmitWorkspaceAction,
|
||||
UmbSaveWorkspaceAction,
|
||||
type MetaWorkspaceAction,
|
||||
type UmbSubmitWorkspaceActionArgs,
|
||||
type UmbSaveWorkspaceActionArgs,
|
||||
type UmbWorkspaceActionDefaultKind,
|
||||
} from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export class UmbDocumentSaveWorkspaceAction
|
||||
extends UmbSubmitWorkspaceAction<MetaWorkspaceAction, UmbDocumentWorkspaceContext>
|
||||
extends UmbSaveWorkspaceAction<MetaWorkspaceAction, UmbDocumentWorkspaceContext>
|
||||
implements UmbWorkspaceActionDefaultKind<MetaWorkspaceAction>
|
||||
{
|
||||
constructor(host: UmbControllerHost, args: UmbSubmitWorkspaceActionArgs<MetaWorkspaceAction>) {
|
||||
constructor(
|
||||
host: UmbControllerHost,
|
||||
args: UmbSaveWorkspaceActionArgs<MetaWorkspaceAction, UmbDocumentWorkspaceContext>,
|
||||
) {
|
||||
super(host, { workspaceContextToken: UMB_DOCUMENT_WORKSPACE_CONTEXT, ...args });
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
|
||||
import type { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
|
||||
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
|
||||
import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace';
|
||||
|
||||
export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<
|
||||
UmbSubmittableWorkspaceContext,
|
||||
UmbDocumentWorkspaceContext
|
||||
>(
|
||||
export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<UmbWorkspaceContext, UmbDocumentWorkspaceContext>(
|
||||
'UmbWorkspaceContext',
|
||||
undefined,
|
||||
(context): context is UmbDocumentWorkspaceContext => context.getEntityType?.() === UMB_DOCUMENT_ENTITY_TYPE,
|
||||
|
||||
@@ -341,17 +341,13 @@ export class UmbDocumentWorkspaceContext
|
||||
this._data.updateCurrent({ template: { unique: templateUnique } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a submit of the workspace, in the case of Document Workspaces the validation does not need to be valid for this to be submitted.
|
||||
* @returns {Promise<void>} a promise which resolves once it has been completed.
|
||||
*/
|
||||
public override requestSubmit() {
|
||||
protected override async _handleSave() {
|
||||
const elementStyle = (this.getHostElement() as HTMLElement).style;
|
||||
elementStyle.setProperty('--uui-color-invalid', 'var(--uui-color-warning)');
|
||||
elementStyle.setProperty('--uui-color-invalid-emphasis', 'var(--uui-color-warning-emphasis)');
|
||||
elementStyle.setProperty('--uui-color-invalid-standalone', 'var(--uui-color-warning-standalone)');
|
||||
elementStyle.setProperty('--uui-color-invalid-contrast', 'var(--uui-color-warning-contrast)');
|
||||
return this._handleSubmit();
|
||||
await super._handleSave();
|
||||
}
|
||||
|
||||
public async saveAndPreview(): Promise<void> {
|
||||
|
||||
Reference in New Issue
Block a user