Merge pull request #838 from umbraco/feature/document-type-groups

This commit is contained in:
Niels Lyngsø
2023-08-31 14:12:11 +02:00
committed by GitHub
8 changed files with 293 additions and 72 deletions

View File

@@ -29,6 +29,10 @@ export class UmbContentTypePropertyStructureHelper {
this.#propertyStructure.sortBy((a, b) => ((a as any).sortOrder ?? 0) - ((b as any).sortOrder ?? 0));
}
public getOwnerDocumentTypes() {
return this.#structure?.documentTypes;
}
public setStructureManager(structure: UmbContentTypePropertyStructureManager) {
this.#structure = structure;
this.#initResolver?.(undefined);
@@ -75,7 +79,7 @@ export class UmbContentTypePropertyStructureHelper {
(groupContainers) => {
groupContainers.forEach((group) => this._observePropertyStructureOf(group.id));
},
'_observeGroupContainers'
'_observeGroupContainers',
);
}
}
@@ -99,13 +103,20 @@ export class UmbContentTypePropertyStructureHelper {
// Fire update to subscribers:
this.#propertyStructure.next(_propertyStructure);
},
'_observePropertyStructureOfGroup' + groupId
'_observePropertyStructureOfGroup' + groupId,
);
}
// TODO: consider moving this to another class, to separate 'viewer' from 'manipulator':
/** Manipulate methods: */
async createPropertyScaffold(ownerId?: string, sortOrder?: number) {
await this.#init;
if (!this.#structure) return;
return await this.#structure.createPropertyScaffold(ownerId, sortOrder);
}
async addProperty(ownerId?: string, sortOrder?: number) {
await this.#init;
if (!this.#structure) return;

View File

@@ -33,7 +33,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
#documentTypes = new UmbArrayState<T>([], (x) => x.id);
readonly documentTypes = this.#documentTypes.asObservable();
private readonly _documentTypeContainers = this.#documentTypes.asObservablePart((x) =>
x.flatMap((x) => x.containers ?? [])
x.flatMap((x) => x.containers ?? []),
);
#containers: UmbArrayState<PropertyTypeContainerModelBaseModel> =
@@ -137,7 +137,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
*/
this.#documentTypes.appendOne(docType);
}
})
}),
);
}
@@ -173,7 +173,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
contentTypeId: string | null,
parentId: string | null = null,
type: PropertyContainerTypes = 'Group',
sortOrder?: number
sortOrder?: number,
) {
await this.#init;
contentTypeId = contentTypeId ?? this.#ownerDocumentTypeId!;
@@ -197,7 +197,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
makeContainerNameUniqueForOwnerDocument(
newName: string,
containerType: PropertyContainerTypes = 'Tab',
parentId: string | null = null
parentId: string | null = null,
) {
const ownerRootContainers = this.getOwnerContainers(containerType); //getRootContainers() can't differentiates between compositions and locals
@@ -215,7 +215,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
async updateContainer(
documentTypeId: string | null,
containerId: string,
partialUpdate: Partial<PropertyTypeContainerModelBaseModel>
partialUpdate: Partial<PropertyTypeContainerModelBaseModel>,
) {
await this.#init;
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
@@ -237,10 +237,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
this.#documentTypes.updateOne(documentTypeKey, { containers });
}
async createProperty(documentTypeId: string | null, containerId: string | null = null, sortOrder?: number) {
await this.#init;
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
createPropertyScaffold(containerId: string | null = null, sortOrder?: number) {
const property: PropertyTypeModelBaseModel = {
id: UmbId.new(),
containerId: containerId,
@@ -262,6 +259,15 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
sortOrder: sortOrder ?? 0,
} as any; // Sort order was not allowed when this was written.
return property;
}
async createProperty(documentTypeId: string | null, containerId: string | null = null, sortOrder?: number) {
await this.#init;
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
const property: PropertyTypeModelBaseModel = this.createPropertyScaffold(containerId, sortOrder);
const properties = [...(this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [])];
properties.push(property);
@@ -287,7 +293,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
const frozenProperties = this.#documentTypes.getValue().find((x) => x.id === documentTypeId)?.properties ?? [];
const properties = filterFrozenArray(frozenProperties, (x) => x.id === propertyId);
const properties = filterFrozenArray(frozenProperties, (x) => x.id !== propertyId);
this.#documentTypes.updateOne(documentTypeId, { properties });
}
@@ -295,7 +301,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
async updateProperty(
documentTypeId: string | null,
propertyId: string,
partialUpdate: Partial<PropertyTypeModelBaseModel>
partialUpdate: Partial<PropertyTypeModelBaseModel>,
) {
await this.#init;
documentTypeId = documentTypeId ?? this.#ownerDocumentTypeId!;
@@ -387,7 +393,7 @@ export class UmbContentTypePropertyStructureManager<R extends UmbDetailRepositor
containersOfParentKey(
parentId: PropertyTypeContainerModelBaseModel['parentId'],
containerType: PropertyContainerTypes
containerType: PropertyContainerTypes,
) {
return this.#containers.asObservablePart((data) => {
return data.filter((x) => x.parentId === parentId && x.type === containerType);

View File

@@ -153,7 +153,6 @@ export class UmbPropertySettingsModalElement extends UmbModalBaseElement<
this._customValidationOptions.forEach((option) => {
option.selected = option.value === regEx;
});
console.log(this._customValidationOptions);
this._returnData.validation!.regEx = regEx ?? null;
this.requestUpdate('_returnData');

View File

@@ -14,7 +14,7 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
#modalAlias: UmbModalToken<UmbModalTokenData, UmbModalTokenResult> | string;
#modalConfig?: UmbModalConfig;
#onSetupCallback?: (routingInfo: Params) => UmbModalTokenData | false;
#onSetupCallback?: (routingInfo: Params) => Promise<UmbModalTokenData | false> | UmbModalTokenData | false;
#onSubmitCallback?: (data: UmbModalTokenResult) => void;
#onRejectCallback?: () => void;
@@ -87,7 +87,7 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
this.#urlBuilderCallback?.(urlBuilder);
}
public onSetup(callback: (routingInfo: Params) => UmbModalTokenData | false) {
public onSetup(callback: (routingInfo: Params) => Promise<UmbModalTokenData | false> | UmbModalTokenData | false) {
this.#onSetupCallback = callback;
return this;
}
@@ -109,11 +109,11 @@ export class UmbModalRouteRegistration<UmbModalTokenData extends object = object
this.#modalContext = undefined;
};
routeSetup(router: IRouterSlot, modalContext: UmbModalManagerContext, params: Params) {
async routeSetup(router: IRouterSlot, modalContext: UmbModalManagerContext, params: Params) {
// If already open, don't do anything:
if (this.active) return;
const modalData = this.#onSetupCallback ? this.#onSetupCallback(params) : undefined;
const modalData = this.#onSetupCallback ? await this.#onSetupCallback(params) : undefined;
if (modalData !== false) {
this.#modalContext = modalContext.open(this.#modalAlias, modalData, this.modalConfig, router);
this.#modalContext.onSubmit().then(this.#onSubmit, this.#onReject);

View File

@@ -1,8 +1,8 @@
import { expect, fixture, html } from '@open-wc/testing';
import { UmbSorterConfig, UmbSorterController } from './sorter.controller.js';
import UmbTestSorterControllerElement from './stories/test-sorter-controller.element.js';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { customElement } from '@umbraco-cms/backoffice/external/lit';
import UmbTestSorterControllerElement from './stories/test-sorter-controller.element.js';
describe('UmbContextConsumer', () => {
let hostElement: UmbTestSorterControllerElement;

View File

@@ -1,13 +1,17 @@
import { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js';
import './document-type-workspace-view-edit-property.element.js';
import { css, html, customElement, property, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { UmbContentTypePropertyStructureHelper, PropertyContainerTypes } from '@umbraco-cms/backoffice/content-type';
import { UmbSorterController, UmbSorterConfig } from '@umbraco-cms/backoffice/sorter';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { DocumentTypePropertyTypeResponseModel, PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal';
import './document-type-workspace-view-edit-property.element.js';
import {
DocumentTypePropertyTypeResponseModel,
DocumentTypeResponseModel,
PropertyTypeModelBaseModel,
} from '@umbraco-cms/backoffice/backend-api';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UMB_PROPERTY_SETTINGS_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
const SORTER_CONFIG: UmbSorterConfig<DocumentTypePropertyTypeResponseModel> = {
compareElementToModel: (element: HTMLElement, model: DocumentTypePropertyTypeResponseModel) => {
return element.getAttribute('data-umb-property-id') === model.id;
@@ -77,26 +81,57 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
@state()
_propertyStructure: Array<PropertyTypeModelBaseModel> = [];
@state()
_ownerDocumentTypes?: DocumentTypeResponseModel[];
@state()
protected _modalRouteNewProperty?: string;
constructor() {
super();
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
this._propertyStructureHelper.setStructureManager(
(workspaceContext as UmbDocumentTypeWorkspaceContext).structure
(workspaceContext as UmbDocumentTypeWorkspaceContext).structure,
);
});
this.observe(this._propertyStructureHelper.propertyStructure, (propertyStructure) => {
this._propertyStructure = propertyStructure;
this.#propertySorter.setModel(this._propertyStructure);
});
// Note: Route for adding a new property
new UmbModalRouteRegistrationController(this, UMB_PROPERTY_SETTINGS_MODAL)
.addAdditionalPath('new-property')
.onSetup(async () => {
return (await this._propertyStructureHelper.createPropertyScaffold(this._containerId)) ?? false;
})
.onSubmit((result) => {
this.#addProperty(result);
})
.observeRouteBuilder((routeBuilder) => {
this._modalRouteNewProperty = routeBuilder(null);
});
}
async #onAddProperty() {
const property = await this._propertyStructureHelper.addProperty(this._containerId);
if (!property) return;
connectedCallback(): void {
super.connectedCallback();
const doctypes = this._propertyStructureHelper.getOwnerDocumentTypes();
if (!doctypes) return;
this.observe(
doctypes,
(documents) => {
this._ownerDocumentTypes = documents;
},
'observeOwnerDocumentTypes',
);
}
// TODO: Figure out how we from this location can get into the route modal, via URL.
// The modal is registered by the document-type-workspace-view-edit-property element, therefor a bit hard to get the URL from here.
async #addProperty(propertyData: PropertyTypeModelBaseModel) {
const propertyPlaceholder = await this._propertyStructureHelper.addProperty(this._containerId);
if (!propertyPlaceholder) return;
this._propertyStructureHelper.partialUpdateProperty(propertyPlaceholder.id, propertyData);
}
render() {
@@ -104,21 +139,35 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle
${repeat(
this._propertyStructure,
(property) => property.id ?? '' + property.containerId ?? '' + (property as any).sortOrder ?? '',
(property) =>
html`<document-type-workspace-view-edit-property
(property) => {
// Note: This piece might be moved into the property component
const inheritedFromDocument = this._ownerDocumentTypes?.find(
(types) => types.containers?.find((containers) => containers.id === property.containerId),
);
return html`<document-type-workspace-view-edit-property
class="property"
data-umb-property-id=${ifDefined(property.id)}
data-property-container-is=${ifDefined(property.containerId === null ? undefined : property.containerId)}
data-container-id=${ifDefined(this.containerId)}
owner-document-type-id=${ifDefined(inheritedFromDocument?.id)}
owner-document-type-name=${ifDefined(inheritedFromDocument?.name)}
?inherited=${property.containerId !== this.containerId}
.property=${property}
@partial-property-update=${(event: CustomEvent) => {
this._propertyStructureHelper.partialUpdateProperty(property.id, event.detail);
}}></document-type-workspace-view-edit-property>`
}}
@property-delete=${() => {
this._propertyStructureHelper.removeProperty(property.id!);
}}>
</document-type-workspace-view-edit-property>`;
},
)}
</div>
<uui-button label="Add property" id="add" look="placeholder" @click=${this.#onAddProperty}>
Add property
<uui-button
label=${this.localize.term('contentTypeEditor_addProprety')}
id="add"
look="placeholder"
href=${ifDefined(this._modalRouteNewProperty)}>
<umb-localize key="contentTypeEditor_addProprety">Add property</umb-localize>
</uui-button> `;
}

View File

@@ -1,9 +1,17 @@
import { UUIInputElement, UUIInputEvent, UUITextStyles } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit';
import { PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api';
import { UMB_PROPERTY_SETTINGS_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
import {
UMB_CONFIRM_MODAL,
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
UMB_PROPERTY_SETTINGS_MODAL,
UMB_WORKSPACE_MODAL,
UmbConfirmModalData,
UmbModalRouteRegistrationController,
} from '@umbraco-cms/backoffice/modal';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { generateAlias } from '@umbraco-cms/backoffice/utils';
import { UmbDataTypeRepository } from '@umbraco-cms/backoffice/data-type';
/**
* @element document-type-workspace-view-edit-property
@@ -27,6 +35,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
const oldValue = this._property;
this._property = value;
this.#modalRegistration.setUniquePathValue('propertyId', value?.id?.toString());
this.setDataType(this._property?.dataTypeId);
this.requestUpdate('property', oldValue);
}
@@ -40,11 +49,36 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
@property({ type: Boolean })
public inherited?: boolean;
#dataTypeRepository = new UmbDataTypeRepository(this);
#modalRegistration;
private _modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT_TOKEN.TYPE;
@state()
protected _modalRoute?: string;
@state()
protected _editDocumentTypePath?: string;
@property()
public get modalRoute() {
return this._modalRoute;
}
@property({ type: String, attribute: 'owner-document-type-id' })
public ownerDocumentTypeId?: string;
@property({ type: String, attribute: 'owner-document-type-name' })
public ownerDocumentTypeName?: string;
@state()
private _dataTypeName?: string;
async setDataType(dataTypeId: string | undefined) {
if (!dataTypeId) return;
this.#dataTypeRepository.requestById(dataTypeId).then((x) => (this._dataTypeName = x?.data?.name));
}
constructor() {
super();
@@ -59,6 +93,19 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
.observeRouteBuilder((routeBuilder) => {
this._modalRoute = routeBuilder(null);
});
new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
.addAdditionalPath('document-type')
.onSetup(() => {
return { entityType: 'document-type', preset: {} };
})
.observeRouteBuilder((routeBuilder) => {
this._editDocumentTypePath = routeBuilder({});
});
this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (context) => {
this._modalManagerContext = context;
});
}
_partialUpdate(partialObject: PropertyTypeModelBaseModel) {
@@ -72,19 +119,6 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
this.dispatchEvent(new CustomEvent('partial-property-update', { detail: partialObject }));
}
renderInheritedProperty() {
return this.property
? html`
<div id="header">
<b>${this.property.name}</b>
<i>${this.property.alias}</i>
<p>${this.property.description}</p>
</div>
<div id="editor"></div>
`
: '';
}
@state()
private _aliasLocked = true;
@@ -92,6 +126,36 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
this._aliasLocked = !this._aliasLocked;
}
#requestRemove(e: Event) {
e.preventDefault();
e.stopImmediatePropagation();
if (!this.property || !this.property.id) return;
const Message: UmbConfirmModalData = {
headline: `${this.localize.term('actions_delete')} property`,
content: html`<umb-localize key="contentTypeEditor_confirmDeletePropertyMessage" .args=${[
this.property.name || this.property.id,
]}>
Are you sure you want to delete the property <strong>${this.property.name || this.property.id}</strong>
</umb-localize>
</div>`,
confirmLabel: this.localize.term('actions_delete'),
color: 'danger',
};
const modalHandler = this._modalManagerContext?.open(UMB_CONFIRM_MODAL, Message);
modalHandler
?.onSubmit()
.then(() => {
this.dispatchEvent(new CustomEvent('property-delete'));
})
.catch(() => {
// We do not need to react to cancel, so we will leave an empty method to prevent Uncaught Promise Rejection error.
return;
});
}
#onNameChange(event: UUIInputEvent) {
if (event instanceof UUIInputEvent) {
const target = event.composedPath()[0] as UUIInputElement;
@@ -123,22 +187,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
label="label"
.value=${this.property.name}
@input=${this.#onNameChange}></uui-input>
<!-- TODO: should use UUI-LOCK-INPUT, but that does not fire an event when its locked/unlocked -->
<uui-input
name="alias"
id="alias-input"
label="alias"
placeholder=${this.localize.term('placeholders_alias')}
.value=${this.property.alias}
?disabled=${this._aliasLocked}
@input=${(e: CustomEvent) => {
if (e.target) this._singleValueUpdate('alias', (e.target as HTMLInputElement).value);
}}>
<!-- TODO: validation for bad characters -->
<div @click=${this.#onToggleAliasLock} @keydown=${() => ''} id="alias-lock" slot="prepend">
<uui-icon name=${this._aliasLocked ? 'umb:lock' : 'umb:unlocked'}></uui-icon>
</div>
</uui-input>
${this.renderPropertyAlias()}
<slot name="property-action-menu"></slot>
<p>
<uui-textarea
@@ -152,13 +201,84 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
}}></uui-textarea>
</p>
</div>
<uui-button id="editor" label="Edit property settings" href=${ifDefined(this._modalRoute)}>
<b></b>
<uui-button
id="editor"
label=${this.localize.term('contentTypeEditor_editorSettings')}
href=${ifDefined(this._modalRoute)}>
${this.renderPropertyTags()}
<uui-action-bar>
<uui-button label="${this.localize.term('actions_delete')}" @click="${this.#requestRemove}">
<uui-icon name="delete"></uui-icon>
</uui-button>
</uui-action-bar>
</uui-button>
`
: '';
}
renderInheritedProperty() {
return this.property
? html`
<div id="header">
<b>${this.property.name}</b>
<i>${this.property.alias}</i>
<p>${this.property.description}</p>
</div>
<div id="editor">
${this.renderPropertyTags()}
<uui-tag look="default" class="inherited">
<uui-icon name="umb:merge"></uui-icon>
<span>
${this.localize.term('contentTypeEditor_inheritedFrom')}
<a href=${this._editDocumentTypePath + 'edit/' + this.ownerDocumentTypeId}>
${this.ownerDocumentTypeName ?? '??'}
</a>
</span>
</uui-tag>
</div>
`
: '';
}
renderPropertyAlias() {
return this.property
? html`<uui-input
name="alias"
id="alias-input"
label="alias"
placeholder=${this.localize.term('placeholders_alias')}
.value=${this.property.alias}
?disabled=${this._aliasLocked}
@input=${(e: CustomEvent) => {
if (e.target) this._singleValueUpdate('alias', (e.target as HTMLInputElement).value);
}}>
<!-- TODO: should use UUI-LOCK-INPUT, but that does not fire an event when its locked/unlocked -->
<!-- TODO: validation for bad characters -->
<div @click=${this.#onToggleAliasLock} @keydown=${() => ''} id="alias-lock" slot="prepend">
<uui-icon name=${this._aliasLocked ? 'umb:lock' : 'umb:unlocked'}></uui-icon>
</div>
</uui-input>`
: '';
}
renderPropertyTags() {
return this.property
? html`<div class="types">
${this.property.dataTypeId ? html`<uui-tag look="default">${this._dataTypeName}</uui-tag>` : nothing}
${this.property.variesByCulture
? html`<uui-tag look="default">
<uui-icon name="umb:shuffle"></uui-icon> ${this.localize.term('contentTypeEditor_cultureVariantLabel')}
</uui-tag>`
: nothing}
${this.property.appearance?.labelOnTop == true
? html`<uui-tag look="default">
<span>${this.localize.term('contentTypeEditor_displaySettingsLabelOnTop')}</span>
</uui-tag>`
: nothing}
</div>`
: nothing;
}
render() {
// TODO: Only show alias on label if user has access to DocumentType within settings:
return this.inherited ? this.renderInheritedProperty() : this.renderEditableProperty();
@@ -201,7 +321,8 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
:host(.--umb-sorter-placeholder) {
height: 2px;
}
:host(.--umb-sorter-placeholder) > div {
:host(.--umb-sorter-placeholder) > div,
:host(.--umb-sorter-placeholder) > uui-button {
display: none;
}
:host(.--umb-sorter-placeholder)::after {
@@ -225,6 +346,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
}
#editor {
position: relative;
background-color: var(--uui-color-background);
}
#alias-input,
@@ -261,6 +383,40 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement {
--uui-textarea-border-color: transparent;
font-weight: 0.5rem; /* TODO: Cant change font size of UUI textarea yet */
}
.types > div uui-icon,
.inherited uui-icon {
vertical-align: sub;
}
.inherited {
position: absolute;
top: var(--uui-size-space-2);
right: var(--uui-size-space-2);
}
.types {
position: absolute;
top: var(--uui-size-space-2);
left: var(--uui-size-space-2);
display: flex;
gap: var(--uui-size-space-2);
}
#editor uui-action-bar {
position: absolute;
top: var(--uui-size-space-2);
right: var(--uui-size-space-2);
display: none;
}
#editor:hover uui-action-bar,
#editor:focus uui-action-bar {
display: block;
}
a {
color: inherit;
}
`,
];
}

View File

@@ -49,9 +49,9 @@ export class UmbRouteContext extends UmbBaseController {
__modalKey: modalRegistration.key,
path: '/' + modalRegistration.generateModalPath(),
component: EmptyDiv,
setup: (component, info) => {
setup: async (component, info) => {
if (!this.#modalContext) return;
const modalContext = modalRegistration.routeSetup(this.#modalRouter, this.#modalContext, info.match.params);
const modalContext = await modalRegistration.routeSetup(this.#modalRouter, this.#modalContext, info.match.params);
if (modalContext) {
modalContext.onSubmit().then(
() => {