working context api proxy

This commit is contained in:
Niels Lyngsø
2023-12-20 22:13:59 +01:00
parent 5f83ec6661
commit a3f2890672
9 changed files with 81 additions and 33 deletions

View File

@@ -33,14 +33,8 @@ export class UmbInputBlockTypeElement<BlockType extends UmbBlockTypeBase = UmbBl
.onSetup(() => {
return { data: { entityType: 'block-type', preset: {} } };
})
// Set to any, to overwrite TS, as the Modal Token does not know about the type of the data. (We could make a Modal Token specific for this type, or a way to cast it more properly, but I skipped this for now.)
.onSubmit((value: any) => {
console.log('got', value);
this._items = appendToFrozenArray(this._items, value, (x) => x.contentElementTypeKey);
})
.observeRouteBuilder((routeBuilder) => {
const newpath = routeBuilder({});
console.log('_workspacePath', newpath);
this._workspacePath = newpath;
});
}

View File

@@ -1,12 +1,12 @@
import type { UmbBlockTypeBase } from '../types.js';
import { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import { UMB_PROPERTY_CONTEXT, UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property';
import {
UmbInvariantableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
UmbWorkspaceContextInterface,
UmbInvariantWorkspacePropertyDatasetContext,
} from '@umbraco-cms/backoffice/workspace';
import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHost, UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { PropertyEditorConfigProperty } from '@umbraco-cms/backoffice/extension-registry';
@@ -36,22 +36,19 @@ export default class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlock
async load(unique: string) {
// TODO: Get data, this requires the ability to proxy to the property editor.
/*
if (data) {
this.setIsNew(false);
this.#data.update(data);
}
*/
console.log('load', unique);
this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
this.observe(context.value, (value) => {
console.log('Got value from prop', value);
});
});
}
async create(contentElementTypeId: string) {
console.log('Contenxt Create', contentElementTypeId);
let data: BlockTypeData = {
const data: BlockTypeData = {
contentElementTypeKey: contentElementTypeId,
} as BlockTypeData;
if (this.modalContext) {
data = { ...data, ...this.modalContext.data.preset };
}
this.setIsNew(true);
this.#data.next(data);
return { data };
@@ -94,6 +91,15 @@ export default class UmbBlockTypeWorkspaceContext<BlockTypeData extends UmbBlock
async save() {
if (!this.#data.value) return;
console.log('Save!', this.#data.getValue());
this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => {
// TODO: We should most likely consume already, in this way I avoid having the reset this consumption.
context.setValue(
appendToFrozenArray(context.getValue() ?? [], this.#data.getValue(), (x) => x?.contentElementTypeKey),
);
});
this.saveComplete(this.#data.value);
}

View File

@@ -5,11 +5,11 @@ import type { ManifestWorkspaceAction, ManifestWorkspaceView } from '@umbraco-cm
const workspaceActions: Array<ManifestWorkspaceAction> = [
{
type: 'workspaceAction',
alias: 'Umb.WorkspaceAction.DataType.Save',
name: 'Save Data Type Workspace Action',
alias: 'Umb.WorkspaceAction.BlockType.Save',
name: 'Save Block Type Workspace Action',
api: UmbSaveWorkspaceAction,
meta: {
label: 'Save',
label: 'Submit',
look: 'primary',
color: 'positive',
},

View File

@@ -32,8 +32,8 @@ export class UmbBackofficeModalContainerElement extends UmbLitElement {
this.observe(this._modalManager.modals, (modals) => this.#createModalElements(modals));
}
/** We cannot render the umb-modal element directly in the uui-modal-container because it wont get reconised by UUI.
* We therefore have a helper class which creates the uui-modal element and returns it. */
/** We cannot render the umb-modal element directly in the uui-modal-container because it wont get recognized by UUI.
* We therefore have a helper class which creates the uui-modal element and returns it. */
#createModalElements(modals: Array<UmbModalContext>) {
this._modals = modals;

View File

@@ -9,6 +9,7 @@ export class UmbModalRouteRegistrationController<D extends object = object, R =
implements UmbController
{
//
#host;
#init;
#additionalPath?: string;
@@ -20,6 +21,9 @@ export class UmbModalRouteRegistrationController<D extends object = object, R =
public get controllerAlias() {
return undefined;
}
protected getControllerHostElement() {
return this.#host.getHostElement();
}
/**
* Creates an instance of UmbModalRouteRegistrationController.
@@ -29,6 +33,7 @@ export class UmbModalRouteRegistrationController<D extends object = object, R =
*/
constructor(host: UmbControllerHost, alias: UmbModalToken<D, R> | string) {
super(alias, null);
this.#host = host;
this.#init = new UmbContextConsumerController(host, UMB_ROUTE_CONTEXT_TOKEN, (_routeContext) => {
this.#routeContext = _routeContext;

View File

@@ -34,10 +34,17 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
#onSubmitCallback?: (data: UmbModalTokenValue) => void;
#onRejectCallback?: () => void;
#modalManagerContext: UmbModalContext<UmbModalTokenData, UmbModalTokenValue> | undefined;
#modalContext: UmbModalContext<UmbModalTokenData, UmbModalTokenValue> | undefined;
#routeBuilder?: UmbModalRouteBuilder;
#urlBuilderCallback: ((urlBuilder: UmbModalRouteBuilder) => void) | undefined;
/**
* Should returns the host element of the modal, but this simple registration is not capable of that. So it has to be overwritten by a more specific implementation.
*/
protected getControllerHostElement(): EventTarget | undefined {
return undefined;
}
// Notice i removed the key in the transferring to this class.
constructor(modalAlias: UmbModalToken<UmbModalTokenData, UmbModalTokenValue> | string, path: string | null = null) {
this.#key = UmbId.new();
@@ -69,7 +76,7 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
* Returns true if the modal is currently active.
*/
public get active() {
return !!this.#modalManagerContext;
return !!this.#modalContext;
}
public open(params: { [key: string]: string | number }, prepend?: string) {
@@ -82,7 +89,7 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
* Returns the modal handler if the modal is currently active. Otherwise its undefined.
*/
public get modalContext() {
return this.#modalManagerContext;
return this.#modalContext;
}
public observeRouteBuilder(callback: (urlBuilder: UmbModalRouteBuilder) => void) {
@@ -116,11 +123,11 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
#onSubmit = (data: UmbModalTokenValue) => {
this.#onSubmitCallback?.(data);
this.#modalManagerContext = undefined;
this.#modalContext = undefined;
};
#onReject = () => {
this.#onRejectCallback?.();
this.#modalManagerContext = undefined;
this.#modalContext = undefined;
};
async routeSetup(router: IRouterSlot, modalManagerContext: UmbModalManagerContext, params: Params) {
@@ -133,12 +140,13 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
modal: {},
...modalData,
router,
originTarget: this.getControllerHostElement(),
};
args.modal.key = this.#key;
this.#modalManagerContext = modalManagerContext.open(this.#modalAlias, args);
this.#modalManagerContext.onSubmit().then(this.#onSubmit, this.#onReject);
return this.#modalManagerContext;
this.#modalContext = modalManagerContext.open(this.#modalAlias, args);
this.#modalContext.onSubmit().then(this.#onSubmit, this.#onReject);
return this.#modalContext;
}
return null;
}

View File

@@ -18,10 +18,12 @@ export type UmbModalContextClassArgs<
data?: ModalAliasTypeAsToken['DATA'];
value?: ModalAliasTypeAsToken['VALUE'];
modal?: UmbModalConfig;
originTarget?: EventTarget;
};
// TODO: consider splitting this into two separate handlers
export class UmbModalContext<ModalPreset extends object = object, ModalValue = any> extends EventTarget {
//
#submitPromise: Promise<ModalValue>;
#submitResolver?: (value: ModalValue) => void;
#submitRejecter?: (reason?: UmbModalRejectReason) => void;
@@ -31,6 +33,7 @@ export class UmbModalContext<ModalPreset extends object = object, ModalValue = a
public readonly type: UmbModalType = 'dialog';
public readonly size: UUIModalSidebarSize = 'small';
public readonly router: IRouterSlot | null = null;
public readonly originTarget?: EventTarget;
public readonly alias: string | UmbModalToken<ModalPreset, ModalValue>;
#value;
@@ -43,6 +46,7 @@ export class UmbModalContext<ModalPreset extends object = object, ModalValue = a
super();
this.key = args.modal?.key || UmbId.new();
this.router = args.router ?? null;
this.originTarget = args.originTarget;
this.alias = modalAlias;
if (this.alias instanceof UmbModalToken) {

View File

@@ -8,7 +8,12 @@ import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api';
import { UUIDialogElement, UUIModalDialogElement, UUIModalSidebarElement } from '@umbraco-cms/backoffice/external/uui';
import { UmbRouterSlotElement } from '@umbraco-cms/backoffice/router';
import { createExtensionElement } from '@umbraco-cms/backoffice/extension-api';
import { UmbContextProvider } from '@umbraco-cms/backoffice/context-api';
import {
UMB_CONTENT_REQUEST_EVENT_TYPE,
UmbContextProvider,
UmbContextRequestEvent,
UmbContextRequestEventImplementation,
} from '@umbraco-cms/backoffice/context-api';
@customElement('umb-modal')
export class UmbModalElement extends UmbLitElement {
@@ -38,6 +43,20 @@ export class UmbModalElement extends UmbLitElement {
if (!this.#modalContext) return;
this.element = this.#createContainerElement();
if (this.#modalContext.originTarget) {
this.element.addEventListener(UMB_CONTENT_REQUEST_EVENT_TYPE, ((event: UmbContextRequestEvent) => {
if (!this.#modalContext) return;
if (this.#modalContext.originTarget) {
event.stopPropagation();
const clonedEvent = new UmbContextRequestEventImplementation(
event.contextAlias,
event.apiAlias,
event.callback,
);
this.#modalContext.originTarget.dispatchEvent(clonedEvent);
}
}) as EventListener);
}
this.#modalContext.onSubmit().then(
() => {

View File

@@ -113,11 +113,23 @@ export class UmbPropertyContext<ValueType = any> extends UmbBaseController {
public setDescription(description: WorkspacePropertyData<ValueType>['description']) {
this.#data.update({ description });
}
/**
* Set the value of this property.
* @param value {ValueType} the whole value to be set
*/
public setValue(value: WorkspacePropertyData<ValueType>['value']) {
const alias = this.#data.getValue().alias;
if (!this.#datasetContext || !alias) return;
this.#datasetContext?.setPropertyValue(alias, value);
}
/**
* Gets the current value of this property.
* Notice this is not reactive, you should us the `value` observable for that.
* @returns {ValueType}
*/
public getValue(): WorkspacePropertyData<ValueType>['value'] {
return this.#data.getValue().value;
}
public setConfig(config: WorkspacePropertyData<ValueType>['config'] | undefined) {
this.#data.update({ config });
}