delete group + inheritance display + links
This commit is contained in:
@@ -240,6 +240,11 @@ export class UmbContentTypeContainerStructureHelper<T extends UmbContentTypeMode
|
||||
return this.#ownerChildContainers.some((x) => x.id === containerId);
|
||||
}
|
||||
|
||||
getContentTypeOfContainer(containerId?: string) {
|
||||
if (!this.#structure || !containerId) return;
|
||||
return this.#structure.getContentTypeOfContainer(containerId);
|
||||
}
|
||||
|
||||
containersByNameAndType(name: string, type: UmbPropertyContainerTypes) {
|
||||
return this.#childContainers.asObservablePart((cons) => cons.filter((x) => x.name === name && x.type === type));
|
||||
}
|
||||
|
||||
@@ -704,6 +704,12 @@ export class UmbContentTypeStructureManager<
|
||||
});
|
||||
}
|
||||
|
||||
getContentTypeOfContainer(containerId: string) {
|
||||
return this.#contentTypes
|
||||
.getValue()
|
||||
.find((contentType) => contentType.containers.some((c) => c.id === containerId));
|
||||
}
|
||||
|
||||
contentTypeOfProperty(propertyId: UmbPropertyTypeId) {
|
||||
return this.#contentTypes.asObservablePart((contentTypes) =>
|
||||
contentTypes.find((contentType) => contentType.properties.some((p) => p.id === propertyId)),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
|
||||
import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element';
|
||||
import { css, html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit';
|
||||
import { css, html, customElement, property, state, nothing, repeat } from '@umbraco-cms/backoffice/external/lit';
|
||||
import type {
|
||||
UmbContentTypeContainerStructureHelper,
|
||||
UmbContentTypeModel,
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
} from '@umbraco-cms/backoffice/content-type';
|
||||
|
||||
import './content-type-design-editor-properties.element.js';
|
||||
import { umbConfirmModal } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
@customElement('umb-content-type-design-editor-group')
|
||||
export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
@@ -37,6 +38,9 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
@property({ type: Boolean, attribute: 'sort-mode-active', reflect: true })
|
||||
sortModeActive = false;
|
||||
|
||||
@property({ attribute: false })
|
||||
editContentTypePath?: string;
|
||||
|
||||
@state()
|
||||
_groupId?: string;
|
||||
|
||||
@@ -46,6 +50,9 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
@state()
|
||||
_inherited?: boolean;
|
||||
|
||||
@state()
|
||||
_inheritedFrom?: Array<UmbContentTypeModel>;
|
||||
|
||||
#checkInherited() {
|
||||
if (this.groupStructureHelper && this.group) {
|
||||
// Check is this container matches with any other group. If so it is inherited aka. merged with others. [NL]
|
||||
@@ -54,18 +61,22 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
this.observe(
|
||||
this.groupStructureHelper.containersByNameAndType(this.group.name, 'Group'),
|
||||
(containers) => {
|
||||
const hasAOwnerContainer = containers.some((con) =>
|
||||
this.groupStructureHelper!.isOwnerChildContainer(con.id),
|
||||
);
|
||||
const ownerContainer = containers.find((con) => this.groupStructureHelper!.isOwnerChildContainer(con.id));
|
||||
const hasAOwnerContainer = !!ownerContainer;
|
||||
const pureOwnerContainer = hasAOwnerContainer && containers.length === 1;
|
||||
|
||||
// TODO: Check if requstUpdate is needed here, I do not think it is when i added it, but I just wanted to be safe when debugging [NL]
|
||||
// TODO: Check if requestUpdate is needed here, I do not think it is when i added it, but I just wanted to be safe when debugging [NL]
|
||||
const oldHasOwnerContainer = this._hasOwnerContainer;
|
||||
const oldInherited = this._inherited;
|
||||
const oldInheritedFrom = this._inheritedFrom;
|
||||
this._hasOwnerContainer = hasAOwnerContainer;
|
||||
this._inherited = !pureOwnerContainer;
|
||||
this._inheritedFrom = containers
|
||||
.filter((con) => con.id !== this.group!.id)
|
||||
.map((con) => this.groupStructureHelper!.getContentTypeOfContainer(con.id));
|
||||
this.requestUpdate('_hasOwnerContainer', oldHasOwnerContainer);
|
||||
this.requestUpdate('_inherited', oldInherited);
|
||||
this.requestUpdate('_inheritedFrom', oldInheritedFrom);
|
||||
},
|
||||
'observeGroupContainers',
|
||||
);
|
||||
@@ -112,6 +123,27 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
}
|
||||
}
|
||||
|
||||
async #requestRemove(e: Event) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
if (!this.groupStructureHelper || !this._group) return;
|
||||
|
||||
// TODO: Do proper localization here: [NL]
|
||||
await umbConfirmModal(this, {
|
||||
headline: `${this.localize.term('actions_delete')} property`,
|
||||
content: html`<umb-localize key="contentTypeEditor_confirmDeletePropertyMessage" .args=${[
|
||||
this._group.name ?? this._group.id,
|
||||
]}>
|
||||
Are you sure you want to delete the group <strong>${this._group.name ?? this._group.id}</strong>
|
||||
</umb-localize>
|
||||
</div>`,
|
||||
confirmLabel: this.localize.term('actions_delete'),
|
||||
color: 'danger',
|
||||
});
|
||||
|
||||
this.groupStructureHelper.removeContainer(this._group.id);
|
||||
}
|
||||
|
||||
render() {
|
||||
return this._inherited !== undefined && this._groupId
|
||||
? html`
|
||||
@@ -124,10 +156,9 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
: '';
|
||||
}
|
||||
|
||||
// TODO: impl UMB_EDIT_DOCUMENT_TYPE_PATH_PATTERN
|
||||
#renderContainerHeader() {
|
||||
return html`<div slot="header">
|
||||
<div>
|
||||
<uui-icon name=${this._inherited ? 'icon-merge' : 'icon-navigation'}></uui-icon>
|
||||
<uui-input
|
||||
label=${this.localize.term('contentTypeEditor_group')}
|
||||
placeholder=${this.localize.term('placeholders_entername')}
|
||||
@@ -136,17 +167,38 @@ export class UmbContentTypeWorkspaceViewEditGroupElement extends UmbLitElement {
|
||||
@change=${this.#renameGroup}
|
||||
@blur=${this.#blurGroup}
|
||||
${this._group!.name === '' ? umbFocus() : nothing}></uui-input>
|
||||
${this._inherited && this._inheritedFrom
|
||||
? html`<uui-tag look="default" class="inherited">
|
||||
<uui-icon name="icon-merge"></uui-icon>
|
||||
<span
|
||||
>${this.localize.term('contentTypeEditor_inheritedFrom')}
|
||||
${repeat(
|
||||
this._inheritedFrom,
|
||||
(inherited) => inherited.unique,
|
||||
(inherited) => html`
|
||||
<a href=${this.editContentTypePath + 'edit/' + inherited.unique}>${inherited.name}</a>
|
||||
`,
|
||||
)}
|
||||
</span>
|
||||
</uui-tag>`
|
||||
: null}
|
||||
</div>
|
||||
${this.sortModeActive
|
||||
? html` <uui-input
|
||||
type="number"
|
||||
label=${this.localize.term('sort_sortOrder')}
|
||||
@change=${(e: UUIInputEvent) =>
|
||||
this._singleValueUpdate('sortOrder', parseInt(e.target.value as string) || 0)}
|
||||
.value=${this.group!.sortOrder ?? 0}
|
||||
?disabled=${!this._hasOwnerContainer}></uui-input>`
|
||||
: ''}
|
||||
</div> `;
|
||||
<div slot="header-actions">
|
||||
${this._inherited
|
||||
? null
|
||||
: html`<uui-button compact label="${this.localize.term('actions_delete')}" @click="${this.#requestRemove}">
|
||||
<uui-icon name="delete"></uui-icon>
|
||||
</uui-button>`}
|
||||
${this.sortModeActive
|
||||
? html` <uui-input
|
||||
type="number"
|
||||
label=${this.localize.term('sort_sortOrder')}
|
||||
@change=${(e: UUIInputEvent) =>
|
||||
this._singleValueUpdate('sortOrder', parseInt(e.target.value as string) || 0)}
|
||||
.value=${this.group!.sortOrder ?? 0}
|
||||
?disabled=${!this._hasOwnerContainer}></uui-input>`
|
||||
: ''}
|
||||
</div> `;
|
||||
}
|
||||
|
||||
static styles = [
|
||||
|
||||
@@ -104,6 +104,9 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
|
||||
|
||||
#propertyStructureHelper = new UmbContentTypePropertyStructureHelper<UmbContentTypeModel>(this);
|
||||
|
||||
@property({ attribute: false })
|
||||
editContentTypePath?: string;
|
||||
|
||||
@state()
|
||||
private _propertyStructure: Array<UmbPropertyTypeModel> = [];
|
||||
|
||||
@@ -113,9 +116,6 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
|
||||
@state()
|
||||
private _modalRouteBuilderNewProperty?: UmbModalRouteBuilder;
|
||||
|
||||
@state()
|
||||
private _editContentTypePath?: string;
|
||||
|
||||
@state()
|
||||
private _sortModeActive?: boolean;
|
||||
|
||||
@@ -142,18 +142,6 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
|
||||
this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, async (workspaceContext) => {
|
||||
this.#propertyStructureHelper.setStructureManager(workspaceContext.structure);
|
||||
|
||||
const entityType = workspaceContext.getEntityType();
|
||||
|
||||
this.#workspaceModal?.destroy();
|
||||
this.#workspaceModal = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(entityType)
|
||||
.onSetup(async () => {
|
||||
return { data: { entityType: entityType, preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this._editContentTypePath = routeBuilder({});
|
||||
});
|
||||
|
||||
this.observe(
|
||||
workspaceContext.structure.ownerContentType,
|
||||
(contentType) => {
|
||||
@@ -208,7 +196,7 @@ export class UmbContentTypeDesignEditorPropertiesElement extends UmbLitElement {
|
||||
return html`
|
||||
<umb-content-type-design-editor-property
|
||||
data-umb-property-id=${property.id}
|
||||
.editContentTypePath=${this._editContentTypePath}
|
||||
.editContentTypePath=${this.editContentTypePath}
|
||||
?sort-mode-active=${this._sortModeActive}
|
||||
.propertyStructureHelper=${this.#propertyStructureHelper}
|
||||
.property=${property}>
|
||||
|
||||
@@ -258,6 +258,7 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
|
||||
</div>
|
||||
<uui-button
|
||||
id="editor"
|
||||
look="secondary"
|
||||
label=${this.localize.term('contentTypeEditor_editorSettings')}
|
||||
href=${ifDefined(this._modalRoute)}>
|
||||
${this.renderPropertyTags()}
|
||||
@@ -415,7 +416,6 @@ export class UmbContentTypeDesignEditorPropertyElement extends UmbLitElement {
|
||||
|
||||
#editor {
|
||||
position: relative;
|
||||
background-color: var(--uui-color-background);
|
||||
}
|
||||
#alias-input,
|
||||
#label-input,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import './content-type-design-editor-properties.element.js';
|
||||
import './content-type-design-editor-group.element.js';
|
||||
import { type UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter';
|
||||
import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal';
|
||||
|
||||
const SORTER_CONFIG: UmbSorterConfig<UmbPropertyTypeContainerModel, UmbContentTypeWorkspaceViewEditGroupElement> = {
|
||||
getUniqueOfElement: (element) => element.group?.id,
|
||||
@@ -71,16 +72,17 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement {
|
||||
},
|
||||
});
|
||||
|
||||
private _containerId?: string | null;
|
||||
#workspaceModal?: UmbModalRouteRegistrationController;
|
||||
#containerId?: string | null;
|
||||
|
||||
@property({ type: String })
|
||||
public get containerId(): string | null | undefined {
|
||||
return this._containerId;
|
||||
return this.#containerId;
|
||||
}
|
||||
public set containerId(value: string | null | undefined) {
|
||||
const oldValue = this._containerId;
|
||||
if (value === this._containerId) return;
|
||||
this._containerId = value;
|
||||
const oldValue = this.#containerId;
|
||||
if (value === this.#containerId) return;
|
||||
this.#containerId = value;
|
||||
this.#groupStructureHelper.setContainerId(value);
|
||||
this.requestUpdate('containerId', oldValue);
|
||||
}
|
||||
@@ -94,6 +96,9 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement {
|
||||
@state()
|
||||
_sortModeActive?: boolean;
|
||||
|
||||
@state()
|
||||
_editContentTypePath?: string;
|
||||
|
||||
#groupStructureHelper = new UmbContentTypeContainerStructureHelper<UmbContentTypeModel>(this);
|
||||
|
||||
constructor() {
|
||||
@@ -101,6 +106,18 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement {
|
||||
|
||||
this.consumeContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, (context) => {
|
||||
this.#groupStructureHelper.setStructureManager(context.structure);
|
||||
|
||||
const entityType = context.getEntityType();
|
||||
|
||||
this.#workspaceModal?.destroy();
|
||||
this.#workspaceModal = new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL)
|
||||
.addAdditionalPath(entityType)
|
||||
.onSetup(async () => {
|
||||
return { data: { entityType: entityType, preset: {} } };
|
||||
})
|
||||
.observeRouteBuilder((routeBuilder) => {
|
||||
this._editContentTypePath = routeBuilder({});
|
||||
});
|
||||
});
|
||||
this.consumeContext(UMB_CONTENT_TYPE_DESIGN_EDITOR_CONTEXT, (context) => {
|
||||
this.observe(
|
||||
@@ -138,19 +155,11 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement {
|
||||
// Idea, maybe we can gather the sortOrder from the last group rendered and add 1 to it?
|
||||
const len = this._groups.length;
|
||||
const sortOrder = len === 0 ? 0 : this._groups[len - 1].sortOrder + 1;
|
||||
this.#groupStructureHelper.addContainer(this._containerId, sortOrder);
|
||||
this.#groupStructureHelper.addContainer(this.#containerId, sortOrder);
|
||||
};
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${
|
||||
this._sortModeActive
|
||||
? html`<uui-button
|
||||
id="convert-to-tab"
|
||||
label=${this.localize.term('contentTypeEditor_convertToTab') + '(Not implemented)'}
|
||||
look="placeholder"></uui-button>`
|
||||
: ''
|
||||
}
|
||||
${
|
||||
this._hasProperties
|
||||
? html`
|
||||
@@ -169,6 +178,7 @@ export class UmbContentTypeDesignEditorTabElement extends UmbLitElement {
|
||||
<umb-content-type-design-editor-group
|
||||
class="container-handle"
|
||||
?sort-mode-active=${this._sortModeActive}
|
||||
.editContentTypePath=${this._editContentTypePath}
|
||||
.group=${group}
|
||||
.groupStructureHelper=${this.#groupStructureHelper as any}>
|
||||
</umb-content-type-design-editor-group>
|
||||
|
||||
@@ -276,7 +276,6 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
|
||||
if (tab) {
|
||||
const path = this._routerPath + '/tab/' + encodeFolderName(tab.name && tab.name !== '' ? tab.name : '-');
|
||||
window.history.replaceState(null, '', path);
|
||||
console.log('new tab', path);
|
||||
this.#focusInput();
|
||||
}
|
||||
}
|
||||
@@ -525,14 +524,6 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
|
||||
static styles = [
|
||||
UmbTextStyles,
|
||||
css`
|
||||
#buttons-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
:host {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@@ -541,6 +532,14 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
|
||||
--uui-tab-background: var(--uui-color-surface);
|
||||
}
|
||||
|
||||
#buttons-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
[drag-placeholder] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@@ -553,6 +552,7 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements
|
||||
|
||||
#header {
|
||||
width: 100%;
|
||||
min-height: var(--uui-size-15);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user