From fdccc3ed118b6781cb1352e1bc9f5dbd2f14b2a1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 8 Sep 2022 14:37:01 +0200 Subject: [PATCH] handle data type create and delete --- .../backoffice/sections/section.context.ts | 9 +++ .../trees/actions/action-list-page.element.ts | 16 +++- .../trees/actions/action.element.ts | 36 ++++++++- .../action-data-type-create.element.ts | 16 +++- .../action-data-type-delete.element.ts | 37 ++++++++- .../trees/documents/tree-documents.element.ts | 1 - .../trees/shared/tree-item.element.ts | 78 ++++++++++--------- .../trees/shared/tree-navigator.element.ts | 8 +- .../src/core/stores/data-type.store.ts | 15 ++++ .../src/mocks/data/data-type.data.ts | 14 ++-- .../src/mocks/data/document-type.data.ts | 5 +- .../src/mocks/data/node.data.ts | 10 +-- .../src/mocks/domains/data-type.handlers.ts | 9 +++ .../src/temp-internal-manifests.ts | 16 +++- 14 files changed, 199 insertions(+), 71 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/section.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/section.context.ts index 3a60b827d2..785ac604c6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/section.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/section.context.ts @@ -1,6 +1,7 @@ import { BehaviorSubject, ReplaySubject } from 'rxjs'; import type { ManifestSection, ManifestTree } from '../../core/models'; +import { Entity } from '../../mocks/data/entity.data'; export class UmbSectionContext { // TODO: figure out how fine grained we want to make our observables. @@ -21,6 +22,10 @@ export class UmbSectionContext { private _activeTree = new ReplaySubject(1); public readonly activeTree = this._activeTree.asObservable(); + // TODO: what is the best context to put this in? + private _activeTreeItem = new ReplaySubject(1); + public readonly activeTreeItem = this._activeTreeItem.asObservable(); + constructor(section: ManifestSection) { if (!section) return; this._data.next(section); @@ -38,4 +43,8 @@ export class UmbSectionContext { public setActiveTree(tree: ManifestTree) { this._activeTree.next(tree); } + + public setActiveTreeItem(treeItem: Entity) { + this._activeTreeItem.next(treeItem); + } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action-list-page.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action-list-page.element.ts index 9b88d272e3..00acc133b4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action-list-page.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action-list-page.element.ts @@ -7,6 +7,7 @@ import { UmbExtensionRegistry } from '../../../core/extension'; import { UmbContextConsumerMixin } from '../../../core/context'; import { map, Subscription } from 'rxjs'; import { UmbSectionContext } from '../../sections/section.context'; +import { Entity } from '../../../mocks/data/entity.data'; @customElement('umb-action-list-page') export class UmbActionListPageElement extends UmbContextConsumerMixin(UmbActionElement) { @@ -34,11 +35,15 @@ export class UmbActionListPageElement extends UmbContextConsumerMixin(UmbActionE @state() private _activeTree?: ManifestTree; + @state() + private _activeTreeItem?: Entity; + private _extensionRegistry?: UmbExtensionRegistry; private _sectionContext?: UmbSectionContext; private _treeItemActionsSubscription?: Subscription; private _activeTreeSubscription?: Subscription; + private _activeTreeItemSubscription?: Subscription; connectedCallback() { super.connectedCallback(); @@ -51,6 +56,7 @@ export class UmbActionListPageElement extends UmbContextConsumerMixin(UmbActionE this.consumeContext('umbSectionContext', (sectionContext) => { this._sectionContext = sectionContext; this._observeActiveTree(); + this._observeActiveTreeItem(); this._observeTreeItemActions(); }); } @@ -76,6 +82,14 @@ export class UmbActionListPageElement extends UmbContextConsumerMixin(UmbActionE }); } + private _observeActiveTreeItem() { + this._activeTreeItemSubscription?.unsubscribe(); + + this._activeTreeItemSubscription = this._sectionContext?.activeTreeItem.subscribe((treeItem) => { + this._activeTreeItem = treeItem; + }); + } + private _renderActions() { return this._actions .sort((a, b) => a.meta.weight - b.meta.weight) @@ -93,7 +107,7 @@ export class UmbActionListPageElement extends UmbContextConsumerMixin(UmbActionE render() { return html`
-

${this._entity.name}

+

${this._activeTreeItem?.name}

${this._renderActions()}
`; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action.element.ts index 6d33493111..2677ecb164 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/actions/action.element.ts @@ -2,6 +2,9 @@ import { LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; import { Subscription } from 'rxjs'; import { UmbContextConsumerMixin } from '../../../core/context'; +import { ManifestTree } from '../../../core/models'; +import { Entity } from '../../../mocks/data/entity.data'; +import { UmbSectionContext } from '../../sections/section.context'; import { UmbActionPageService } from './action-page.service'; import { UmbActionService } from './actions.service'; @@ -15,13 +18,26 @@ export default class UmbActionElement extends UmbContextConsumerMixin(LitElement @state() protected _entity: ActionPageEntity = { name: '', key: '' }; + protected _activeTree?: ManifestTree; + protected _activeTreeItem?: Entity; + + protected _sectionContext?: UmbSectionContext; protected _actionService?: UmbActionService; protected _actionPageService?: UmbActionPageService; - private _actionPageSubscription?: Subscription; + + protected _actionPageSubscription?: Subscription; + protected _activeTreeSubscription?: Subscription; + protected _activeTreeItemSubscription?: Subscription; connectedCallback() { super.connectedCallback(); + this.consumeContext('umbSectionContext', (sectionContext) => { + this._sectionContext = sectionContext; + this._observeActiveTree(); + this._observeActiveTreeItem(); + }); + this.consumeContext('umbActionService', (actionService: UmbActionService) => { this._actionService = actionService; }); @@ -36,9 +52,27 @@ export default class UmbActionElement extends UmbContextConsumerMixin(LitElement }); } + private _observeActiveTree() { + this._activeTreeSubscription?.unsubscribe(); + + this._activeTreeSubscription = this._sectionContext?.activeTree.subscribe((tree) => { + this._activeTree = tree; + }); + } + + private _observeActiveTreeItem() { + this._activeTreeItemSubscription?.unsubscribe(); + + this._activeTreeItemSubscription = this._sectionContext?.activeTreeItem.subscribe((treeItem) => { + this._activeTreeItem = treeItem; + }); + } + disconnectCallback() { super.disconnectedCallback(); this._actionPageSubscription?.unsubscribe(); + this._activeTreeSubscription?.unsubscribe(); + this._activeTreeItemSubscription?.unsubscribe(); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-create.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-create.element.ts index 136f6c8302..a6bd8ebac8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-create.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-create.element.ts @@ -1,17 +1,27 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; -import { css, html, LitElement } from 'lit'; +import { css, html } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import type { ManifestEntityAction } from '../../../../core/models'; +import UmbActionElement from '../../actions/action.element'; @customElement('umb-tree-action-data-type-create') -export default class UmbTreeActionDataTypeCreateElement extends LitElement { +export default class UmbTreeActionDataTypeCreateElement extends UmbActionElement { static styles = [UUITextStyles, css``]; @property({ attribute: false }) public treeAction?: ManifestEntityAction; + // TODO: how do we handle the href? + private _constructUrl() { + return `/section/settings/${this._activeTreeItem?.type}/${this._activeTreeItem?.key}/view/edit?create=true`; + } + + // TODO: change to href. This is a temporary solution to get the link to work. For some reason query params gets removed when using href. private _handleLabelClick() { - console.log('create new treee item'); + if (!this._actionService) return; + const href = this._constructUrl(); + history.pushState(null, '', href); + this._actionService.close(); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-delete.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-delete.element.ts index 56cd9aa9fe..53537d08a8 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-delete.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/actions/action-data-type-delete.element.ts @@ -1,17 +1,48 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; -import { css, html, LitElement } from 'lit'; +import { css, html } from 'lit'; import { customElement, property } from 'lit/decorators.js'; +import { UmbContextConsumerMixin } from '../../../../core/context'; import type { ManifestEntityAction } from '../../../../core/models'; +import { UmbModalService } from '../../../../core/services/modal'; +import { UmbDataTypeStore } from '../../../../core/stores/data-type.store'; +import UmbActionElement from '../../actions/action.element'; @customElement('umb-tree-action-data-type-delete') -export default class UmbTreeActionDataTypeDeleteElement extends LitElement { +export default class UmbTreeActionDataTypeDeleteElement extends UmbContextConsumerMixin(UmbActionElement) { static styles = [UUITextStyles, css``]; @property({ attribute: false }) public treeAction?: ManifestEntityAction; + private _modalService?: UmbModalService; + private _dataTypeStore?: UmbDataTypeStore; + + connectedCallback(): void { + super.connectedCallback(); + + this.consumeContext('umbModalService', (modalService: UmbModalService) => { + this._modalService = modalService; + }); + + this.consumeContext('umbDataTypeStore', (dataTypeStore: UmbDataTypeStore) => { + this._dataTypeStore = dataTypeStore; + }); + } + private _handleLabelClick() { - console.log('delete this tree item'); + const modalHandler = this._modalService?.confirm({ + headline: `Delete ${this._activeTreeItem?.name ?? 'item'}`, + content: 'Are you sure you want to delete this item?', + color: 'danger', + confirmLabel: 'Delete', + }); + + modalHandler?.onClose.then(({ confirmed }: any) => { + if (confirmed && this._actionService && this._dataTypeStore && this._activeTreeItem) { + this._dataTypeStore?.trash(this._activeTreeItem.key); + this._actionService.close(); + } + }); } render() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts index bb22fa8e97..0f0086fea4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.element.ts @@ -62,7 +62,6 @@ export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextCo this._selectionSubscription?.unsubscribe(); this._selectionSubscription = this._treeContext?.selection.subscribe((selection) => { this._selection = selection; - this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true })); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts index d803b86904..62e76bad2c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-item.element.ts @@ -8,25 +8,14 @@ import { UmbSectionContext } from '../../sections/section.context'; import { map, Subscription } from 'rxjs'; import { Entity } from '../../../mocks/data/entity.data'; import { UmbActionService } from '../actions/actions.service'; +import { repeat } from 'lit/directives/repeat.js'; @customElement('umb-tree-item') export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { static styles = [UUITextStyles, css``]; - @property() - itemKey = ''; - - @property() - itemType = ''; - - @property({ type: String }) - label = ''; - - @property({ type: String }) - icon = ''; - - @property({ type: Boolean }) - hasChildren = false; + @property({ type: Object, attribute: false }) + treeItem!: Entity; @state() private _childItems: Entity[] = []; @@ -43,13 +32,18 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { @state() private _selected = false; + @state() + private _isActive = false; + private _treeContext?: UmbTreeContextBase; private _sectionContext?: UmbSectionContext; + private _actionService?: UmbActionService; + private _sectionSubscription?: Subscription; private _childrenSubscription?: Subscription; - private _actionService?: UmbActionService; private _selectableSubscription?: Subscription; private _selectionSubscription?: Subscription; + private _activeTreeItemSubscription?: Subscription; constructor() { super(); @@ -62,7 +56,8 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => { this._sectionContext = sectionContext; - this._useSection(); + this._observeSection(); + this._observeActiveTreeItem(); }); this.consumeContext('umbActionService', (actionService: UmbActionService) => { @@ -74,15 +69,15 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { super.connectedCallback(); this.addEventListener('selected', (e) => { e.stopPropagation(); - this._treeContext?.select(this.itemKey); + this._treeContext?.select(this.treeItem.key); }); } - private _useSection() { + private _observeSection() { this._sectionSubscription?.unsubscribe(); this._sectionSubscription = this._sectionContext?.data.subscribe((section) => { - this._href = this._constructPath(section.meta.pathname, this.itemType, this.itemKey); + this._href = this._constructPath(section.meta.pathname, this.treeItem.type, this.treeItem.key); }); } @@ -96,12 +91,20 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { private _observeSelection() { this._selectionSubscription?.unsubscribe(); this._selectionSubscription = this._treeContext?.selection - .pipe(map((keys) => keys.includes(this.itemKey))) + .pipe(map((keys) => keys.includes(this.treeItem.key))) .subscribe((isSelected) => { this._selected = isSelected; }); } + private _observeActiveTreeItem() { + this._activeTreeItemSubscription?.unsubscribe(); + + this._activeTreeItemSubscription = this._sectionContext?.activeTreeItem.subscribe((treeItem) => { + this._isActive = treeItem.key === this.treeItem.key; + }); + } + // TODO: how do we handle this? private _constructPath(sectionPathname: string, type: string, key: string) { return `/section/${sectionPathname}/${type}/${key}`; @@ -115,7 +118,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this._childrenSubscription?.unsubscribe(); - this._childrenSubscription = this._treeContext?.childrenChanges(this.itemKey).subscribe((items) => { + this._childrenSubscription = this._treeContext?.childrenChanges(this.treeItem.key).subscribe((items) => { if (items?.length === 0) return; this._childItems = items; this._loading = false; @@ -128,39 +131,40 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this._childrenSubscription?.unsubscribe(); this._selectableSubscription?.unsubscribe(); this._selectionSubscription?.unsubscribe(); + this._activeTreeItemSubscription?.unsubscribe(); } private _renderChildItems() { - return this._childItems.map((item) => { - return html` - `; - }); + return html` + ${repeat( + this._childItems, + (item) => item.key, + (item) => html`` + )} + `; } private _openActions() { - if (!this._treeContext || !this._sectionContext) return; + if (!this._treeContext || !this._sectionContext || !this.treeItem) return; this._sectionContext?.setActiveTree(this._treeContext?.tree); - this._actionService?.open({ name: this.label, key: this.itemKey }); + this._sectionContext?.setActiveTreeItem(this.treeItem); + this._actionService?.open({ name: this.treeItem.name, key: this.treeItem.key }); } render() { return html` + .hasChildren=${this.treeItem.hasChildren} + label="${this.treeItem.name}" + href="${this._href}" + ?active=${this._isActive}> ${this._renderChildItems()} - + diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts index 561ef453b1..360243ea90 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts @@ -51,13 +51,7 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(LitElement) { ${repeat( this._items, (item) => item.key, - (item) => html`` + (item) => html`` )} `; } diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/data-type.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/data-type.store.ts index 57afcda204..0418863440 100644 --- a/src/Umbraco.Web.UI.Client/src/core/stores/data-type.store.ts +++ b/src/Umbraco.Web.UI.Client/src/core/stores/data-type.store.ts @@ -42,4 +42,19 @@ export class UmbDataTypeStore extends UmbDataStoreBase { console.error('Save Data Type error', error); } } + + trash(key: string) { + return fetch('/umbraco/backoffice/data-type/trash', { + method: 'POST', + body: key, + headers: { + 'Content-Type': 'application/json', + }, + }) + .then((res) => res.json()) + .then((data: Array) => { + this.update(data); + this._entityStore.update(data); + }); + } } diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts index 29e2ceba99..56c33afee9 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts @@ -1,12 +1,7 @@ import { UmbData } from './data'; +import { Entity } from './entity.data'; -export interface DataTypeEntity { - key: string; - name: string; - type: string; - parentKey: string; - isTrashed: boolean; - hasChildren: boolean; +export interface DataTypeEntity extends Entity { propertyEditorUIAlias: string; //configUI: any; // this is the prevalues... } @@ -19,6 +14,7 @@ export const data: Array = [ parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, hasChildren: false, + icon: '', propertyEditorUIAlias: 'Umb.PropertyEditorUI.Text', }, { @@ -28,6 +24,7 @@ export const data: Array = [ parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, hasChildren: false, + icon: '', propertyEditorUIAlias: 'Umb.PropertyEditorUI.Textarea', }, { @@ -37,6 +34,7 @@ export const data: Array = [ parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, hasChildren: false, + icon: '', propertyEditorUIAlias: 'My.PropertyEditorUI.Custom', }, { @@ -46,6 +44,7 @@ export const data: Array = [ parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, hasChildren: false, + icon: '', propertyEditorUIAlias: 'Umb.PropertyEditorUI.ContextExample', }, { @@ -55,6 +54,7 @@ export const data: Array = [ parentKey: '29d78e6c-c1bf-4c15-b820-d511c237ffae', isTrashed: false, hasChildren: false, + icon: '', propertyEditorUIAlias: 'Umb.PropertyEditorUI.ContentPicker', }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type.data.ts index d5f9c40ff6..4ba7589a8a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type.data.ts @@ -1,6 +1,7 @@ import { UmbData } from './data'; +import { Entity } from './entity.data'; -export interface DocumentTypeEntity { +export interface DocumentTypeEntity extends Entity { key: string; name: string; alias: string; @@ -20,6 +21,7 @@ export const data: Array = [ parentKey: 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da', isTrashed: false, hasChildren: false, + icon: '', properties: [], }, { @@ -30,6 +32,7 @@ export const data: Array = [ parentKey: 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da', isTrashed: false, hasChildren: false, + icon: '', properties: [], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/node.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/node.data.ts index f08ba7e06a..41e58a27d5 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/node.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/node.data.ts @@ -1,13 +1,7 @@ import { UmbData } from './data'; +import { Entity } from './entity.data'; -export interface NodeEntity { - key: string; - name: string; - icon: string; // TODO: should come from the doc type? - type: string; - isTrashed: boolean; - hasChildren: boolean; - parentKey: string; +export interface NodeEntity extends Entity { properties: Array; data: Array; variants: Array; // TODO: define variant data diff --git a/src/Umbraco.Web.UI.Client/src/mocks/domains/data-type.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/domains/data-type.handlers.ts index 2450eaa16e..1bb23864f2 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/domains/data-type.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/domains/data-type.handlers.ts @@ -30,4 +30,13 @@ export const handlers = [ return res(ctx.status(200), ctx.json(saved)); }), + + rest.post('/umbraco/backoffice/data-type/trash', (req, res, ctx) => { + console.warn('Please move to schema'); + const key = req.body as string; + + const trashed = umbDataTypeData.trash(key); + + return res(ctx.status(200), ctx.json([trashed])); + }), ]; diff --git a/src/Umbraco.Web.UI.Client/src/temp-internal-manifests.ts b/src/Umbraco.Web.UI.Client/src/temp-internal-manifests.ts index ef93d39fd7..7ee71a1f98 100644 --- a/src/Umbraco.Web.UI.Client/src/temp-internal-manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/temp-internal-manifests.ts @@ -388,8 +388,8 @@ export const internalManifests: Array Promise import('./backoffice/trees/data-types/actions/action-data-type-create.element'), meta: { trees: ['Umb.Tree.DataTypes'], @@ -398,4 +398,16 @@ export const internalManifests: Array Promise import('./backoffice/trees/data-types/actions/action-data-type-delete.element'), + meta: { + trees: ['Umb.Tree.DataTypes'], + label: 'Delete', + icon: 'delete', + weight: 100, + }, + }, ];