Merge pull request #838 from umbraco/feature/document-type-groups
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> `;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
() => {
|
||||
|
||||
Reference in New Issue
Block a user