impl edit workspace route

This commit is contained in:
Niels Lyngsø
2024-07-04 20:06:05 +02:00
parent fe705c2f57
commit 47dedfe386
6 changed files with 115 additions and 58 deletions

View File

@@ -463,6 +463,10 @@ export class UmbContentTypeStructureManager<
property = { ...property, container: { id: container.id } };
}
if (property.sortOrder === undefined) {
property.sortOrder = 0;
}
const frozenProperties =
this.#contentTypes.getValue().find((x) => x.unique === contentTypeUnique)?.properties ?? [];

View File

@@ -99,16 +99,16 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
return this._containerId;
}
public set containerId(value: string | null | undefined) {
const oldValue = this._containerId;
if (value === oldValue) return;
if (value === this._containerId) return;
this._containerId = value;
this.createAddPropertyRoute();
this.createPropertyTypeWorkspaceRoutes();
this.#propertyStructureHelper.setContainerId(value);
this.#addPropertyModal?.setUniquePathValue('container-id', value === null ? 'root' : value);
this.requestUpdate('containerId', oldValue);
this.#editPropertyModal?.setUniquePathValue('container-id', value === null ? 'root' : value);
}
#addPropertyModal?: UmbModalRouteRegistrationController;
#editPropertyModal?: UmbModalRouteRegistrationController;
#propertyStructureHelper = new UmbContentTypePropertyStructureHelper<UmbContentTypeModel>(this);
@@ -124,6 +124,9 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
@state()
private _newPropertyPath?: string;
@state()
private _editPropertyTypePath?: string;
@state()
private _sortModeActive?: boolean;
@@ -154,6 +157,7 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
workspaceContext.structure.ownerContentType,
(contentType) => {
this._ownerContentType = contentType;
this.createPropertyTypeWorkspaceRoutes();
},
'observeOwnerContentType',
);
@@ -164,32 +168,67 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
});
}
createAddPropertyRoute() {
createPropertyTypeWorkspaceRoutes() {
if (!this._ownerContentType || this._containerId === undefined) return;
// Note: Route for adding a new property
this.#addPropertyModal?.destroy();
this.#addPropertyModal = new UmbModalRouteRegistrationController(this, UMB_PROPERTY_TYPE_WORKSPACE_MODAL)
this.#addPropertyModal = new UmbModalRouteRegistrationController(
this,
UMB_PROPERTY_TYPE_WORKSPACE_MODAL,
'addPropertyModal',
)
.addUniquePaths(['container-id'])
.addAdditionalPath('add-property')
.addAdditionalPath('add-property/:sortOrder')
.onSetup(async (params) => {
// TODO: Make a onInit promise, that can be awaited here.
if (!this._ownerContentType || this._containerId === undefined) return false;
const preset: Partial<UmbPropertyTypeModel> = {};
if (params.sortOrder !== undefined) {
let sortOrderInt = parseInt(params.sortOrder, 10);
let sortOrderInt = parseInt(params.sortOrder);
if (sortOrderInt === -1) {
// Find the highest sortOrder and add 1 to it:
sortOrderInt = Math.max(...this._propertyStructure.map((x) => x.sortOrder), -1);
sortOrderInt = Math.max(...this._propertyStructure.map((x) => x.sortOrder), -1) + 1;
}
preset.sortOrder = sortOrderInt + 1;
preset.sortOrder = sortOrderInt;
}
return { data: { contentTypeUnique: this._ownerContentType.unique, preset } };
return { data: { contentTypeUnique: this._ownerContentType.unique, preset: undefined } };
})
.observeRouteBuilder((routeBuilder) => {
this._newPropertyPath =
routeBuilder({}) +
UMB_CREATE_PROPERTY_TYPE_WORKSPACE_PATH_PATTERN.generateLocal({ containerUnique: this._containerId! });
routeBuilder({ sortOrder: '-1' }) +
UMB_CREATE_PROPERTY_TYPE_WORKSPACE_PATH_PATTERN.generateLocal({
containerUnique: this._containerId!,
});
});
if (this._containerId !== undefined) {
this.#addPropertyModal?.setUniquePathValue(
'container-id',
this._containerId === null ? 'root' : this._containerId,
);
}
this.#editPropertyModal?.destroy();
this.#editPropertyModal = new UmbModalRouteRegistrationController(
this,
UMB_PROPERTY_TYPE_WORKSPACE_MODAL,
'editPropertyModal',
)
.addUniquePaths(['container-id'])
.addAdditionalPath('edit-property')
.onSetup(async () => {
if (!this._ownerContentType || this._containerId === undefined) return false;
return { data: { contentTypeUnique: this._ownerContentType.unique, preset: undefined } };
})
.observeRouteBuilder((routeBuilder) => {
this._editPropertyTypePath = routeBuilder(null);
});
if (this._containerId !== undefined) {
this.#editPropertyModal?.setUniquePathValue(
'container-id',
this._containerId === null ? 'root' : this._containerId,
);
}
}
override render() {
@@ -204,6 +243,7 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
<umb-content-type-design-editor-property
data-umb-property-id=${property.id}
.editContentTypePath=${this.editContentTypePath}
.editPropertyTypePath=${this._editPropertyTypePath}
?sort-mode-active=${this._sortModeActive}
.propertyStructureHelper=${this.#propertyStructureHelper}
.property=${property}>

View File

@@ -2,9 +2,8 @@ import { UmbPropertyTypeContext } from './content-type-design-editor-property.co
import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type';
import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui';
import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit';
import { css, html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit';
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { generateAlias } from '@umbraco-cms/backoffice/utils';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@@ -14,7 +13,7 @@ import {
type UmbPropertyTypeModel,
type UmbPropertyTypeScaffoldModel,
} from '@umbraco-cms/backoffice/content-type';
import { UMB_PROPERTY_TYPE_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/property-type';
import { UMB_EDIT_PROPERTY_TYPE_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/property-type';
/**
* @element umb-content-type-design-editor-property
@@ -25,7 +24,6 @@ import { UMB_PROPERTY_TYPE_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/prope
export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
//
#dataTypeDetailRepository = new UmbDataTypeDetailRepository(this);
#settingsModal;
#dataTypeUnique?: string;
#context = new UmbPropertyTypeContext(this);
@@ -57,7 +55,6 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
this.#context.setAlias(value?.alias);
this.#context.setLabel(value?.name);
this.#checkInherited();
this.#settingsModal.setUniquePathValue('propertyId', value?.id);
this.#setDataType(this._property?.dataType?.unique);
this.requestUpdate('property', oldValue);
}
@@ -78,8 +75,8 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
@state()
public _inheritedContentTypeName?: string;
@state()
protected _modalRoute?: string;
@property({ type: String, reflect: false })
protected editPropertyTypePath?: string;
@state()
private _dataTypeName?: string;
@@ -87,24 +84,6 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
@state()
private _aliasLocked = true;
constructor() {
super();
// TODO: consider if this can be registered more globally/contextually. [NL]
this.#settingsModal = new UmbModalRouteRegistrationController(this, UMB_PROPERTY_TYPE_WORKSPACE_MODAL)
.addUniquePaths(['propertyId'])
.onSetup(() => {
const id = this._inheritedContentTypeId;
if (id === undefined) return false;
const propertyData = this.property;
if (propertyData === undefined) return false;
return { data: { contentTypeUnique: id, preset: {} } };
})
.observeRouteBuilder((routeBuilder) => {
this._modalRoute = routeBuilder(null);
});
}
async #checkInherited() {
if (this._propertyStructureHelper && this._property) {
// We can first match with something if we have a name [NL]
@@ -228,7 +207,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
}
renderEditableProperty() {
if (!this.property) return;
if (!this.property || !this.editPropertyTypePath) return;
if (this.sortModeActive) {
return this.renderSortableProperty();
@@ -260,7 +239,8 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
id="editor"
look="secondary"
label=${this.localize.term('contentTypeEditor_editorSettings')}
href=${ifDefined(this._modalRoute)}>
href=${this.editPropertyTypePath +
UMB_EDIT_PROPERTY_TYPE_WORKSPACE_PATH_PATTERN.generateLocal({ unique: this.property.id })}>
${this.renderPropertyTags()}
<uui-action-bar>
<uui-button label="${this.localize.term('actions_delete')}" @click="${this.#requestRemove}">

View File

@@ -23,7 +23,13 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
// Just for context token safety:
public readonly IS_PROPERTY_TYPE_WORKSPACE_CONTEXT = true;
#init: Promise<unknown>;
#contentTypeContext?: typeof UMB_CONTENT_TYPE_WORKSPACE_CONTEXT.TYPE;
#entityType: string;
// #persistedData
// #currentData
#data = new UmbObjectState<PropertyTypeData | undefined>(undefined);
readonly data = this.#data.asObservable();
@@ -35,6 +41,12 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
const manifest = args.manifest;
this.#entityType = manifest.meta?.entityType;
this.#init = this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (context) => {
this.#contentTypeContext = context;
})
.skipHost()
.asPromise();
this.routes.setRoutes([
{
// Would it make more sense to have groupKey before elementTypeKey?
@@ -70,6 +82,8 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
protected override resetState() {
super.resetState();
this.#data.setValue(undefined);
this.removeUmbControllerByAlias('isNewRedirectController');
this.removeUmbControllerByAlias('observePropertyTypeData');
}
createPropertyDatasetContext(host: UmbControllerHost): UmbPropertyDatasetContext {
@@ -78,14 +92,23 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
async load(unique: string) {
this.resetState();
const context = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT);
this.observe(await context.structure.propertyStructureById(unique), (property) => {
if (property) {
this.#data.setValue(property as PropertyTypeData);
}
// Fallback to undefined:
this.#data.setValue(undefined);
});
await this.#init;
this.observe(
await this.#contentTypeContext?.structure.propertyStructureById(unique),
(property) => {
if (property) {
this.#data.setValue(property as PropertyTypeData);
//this.#persistedData.setValue(property);
//this.#currentData.setValue(property);
this.setIsNew(false);
} else {
// Fallback to undefined:
this.#data.setValue(undefined);
}
},
'observePropertyTypeData',
);
}
async create(containerId?: string | null) {
@@ -116,9 +139,10 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
data = { ...data, ...this.modalContext.data.preset };
}
this.setIsNew(true);
this.#data.setValue(data);
return { data };
//this.#persistedData.setValue(property);
//this.#currentData.setValue(property);
this.setIsNew(true);
}
getData() {
@@ -169,11 +193,14 @@ export class UmbPropertyTypeWorkspaceContext<PropertyTypeData extends UmbPropert
throw new Error('No data to submit.');
}
const context = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT);
await this.#init;
if (this.#contentTypeContext) {
await this.#contentTypeContext.structure.insertProperty(contentTypeUnique, data);
context.structure.insertProperty(contentTypeUnique, data);
this.setIsNew(false);
this.setIsNew(false);
} else {
throw new Error('Failed to find content type context.');
}
}
public override destroy(): void {

View File

@@ -52,7 +52,9 @@ export class UmbPropertyTypeWorkspaceViewSettingsElement extends UmbLitElement i
this.consumeContext(UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT, (instance) => {
this.#context = instance;
this.observe(instance.data, (data) => (this._data = data));
this.observe(instance.data, (data) => {
this._data = data;
});
});
this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (instance) => {

View File

@@ -8,7 +8,7 @@ import type {
UmbModalManagerContext,
UmbModalToken,
} from '@umbraco-cms/backoffice/modal';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import type { UmbControllerAlias, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api';
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
import { UmbId } from '@umbraco-cms/backoffice/id';
@@ -80,8 +80,12 @@ export class UmbModalRouteRegistrationController<
* @param {UmbModalToken} alias - The alias of the modal, this is used to identify the modal.
* @memberof UmbModalRouteRegistrationController
*/
constructor(host: UmbControllerHost, alias: UmbModalToken<UmbModalTokenData, UmbModalTokenValue> | string) {
super(host, alias.toString());
constructor(
host: UmbControllerHost,
alias: UmbModalToken<UmbModalTokenData, UmbModalTokenValue> | string,
ctrlAlias?: UmbControllerAlias,
) {
super(host, ctrlAlias ?? alias.toString());
this.#key = UmbId.new();
this.#modalAlias = alias;
//this.#path = path;