From 4accfe1eb854f0365515c4cd44ac0ee8b47456ee Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 8 Sep 2022 21:57:35 +0200 Subject: [PATCH] split tree context and tree data context api's --- .../src/backoffice/backoffice.element.ts | 2 + .../sections/shared/section-trees.element.ts | 26 ++--- ...ext.ts => tree-data-types-data.context.ts} | 4 +- .../data-types/tree-data-types.element.ts | 41 ++----- ...ts => tree-document-types-data.context.ts} | 4 +- .../tree-document-types.element.ts | 30 ++--- ...text.ts => tree-documents-data.context.ts} | 4 +- .../trees/documents/tree-documents.element.ts | 62 ++-------- ...ext.ts => tree-extensions-data.context.ts} | 4 +- .../extensions/tree-extensions.element.ts | 25 ++-- ....context.ts => tree-media-data.context.ts} | 4 +- .../trees/media/tree-media.element.ts | 28 ++--- ....ts => tree-member-groups-data.context.ts} | 4 +- .../tree-member-groups.element.ts | 28 ++--- .../trees/members/tree-members.context.ts | 4 +- .../trees/members/tree-members.element.ts | 24 ++-- .../trees/shared/tree-base.element.ts | 20 ++++ .../trees/shared/tree-item.element.ts | 11 +- .../trees/shared/tree-navigator.element.ts | 18 +-- .../backoffice/trees/shared/tree.element.ts | 110 ++++++++++++++++++ .../src/backoffice/trees/tree-data.context.ts | 31 +++++ .../src/backoffice/trees/tree.context.ts | 26 +---- .../modal-layout-content-picker.element.ts | 10 +- 23 files changed, 279 insertions(+), 241 deletions(-) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/{tree-data-types.context.ts => tree-data-types-data.context.ts} (81%) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/{tree-document-types.context.ts => tree-document-types-data.context.ts} (81%) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/{tree-documents.context.ts => tree-documents-data.context.ts} (83%) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/{tree-extensions.context.ts => tree-extensions-data.context.ts} (70%) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/media/{tree-media.context.ts => tree-media-data.context.ts} (83%) rename src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/{tree-member-groups.context.ts => tree-member-groups-data.context.ts} (81%) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index ffc55365bd..3ce2a18181 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -8,6 +8,8 @@ import './sections/shared/section-layout.element'; import './sections/shared/section-main.element'; import './sections/shared/section-sidebar.element'; import './sections/shared/section.element'; +import './trees/shared/tree-base.element'; +import './trees/shared/tree.element'; import { defineElement } from '@umbraco-ui/uui-base/lib/registration'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section-trees.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section-trees.element.ts index f074aa935b..ed9af511ad 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section-trees.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/shared/section-trees.element.ts @@ -6,7 +6,6 @@ import { map, Subscription, switchMap, EMPTY, of } from 'rxjs'; import { UmbContextConsumerMixin } from '../../../core/context'; import { UmbExtensionRegistry } from '../../../core/extension'; import { UmbSectionContext } from '../section.context'; -import type { ManifestTree } from '../../../core/models'; import '../../trees/shared/tree-extension.element'; @@ -15,7 +14,7 @@ export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) { static styles = [UUITextStyles]; @state() - private _trees: Array = []; + private _treeAliases: Array = []; private _extensionStore?: UmbExtensionRegistry; private _treesSubscription?: Subscription; @@ -49,20 +48,19 @@ export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) { if (!section) return EMPTY; return ( - this._extensionStore - ?.extensionsOfType('tree') - .pipe( - map((trees) => - trees - .filter((tree) => tree.meta.sections.includes(section.alias)) - .sort((a, b) => b.meta.weight - a.meta.weight) - ) - ) ?? of([]) + this._extensionStore?.extensionsOfType('tree').pipe( + map((trees) => + trees + .filter((tree) => tree.meta.sections.includes(section.alias)) + .sort((a, b) => b.meta.weight - a.meta.weight) + .map((tree) => tree.alias) + ) + ) ?? of([]) ); }) ) - .subscribe((trees) => { - this._trees = trees; + .subscribe((treeAliases) => { + this._treeAliases = treeAliases; }); } @@ -73,7 +71,7 @@ export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) { } render() { - return html`${this._trees.map((tree) => html``)} `; + return html`${this._treeAliases.map((treeAlias) => html``)} `; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts similarity index 81% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts index feea66cd8d..91cb6ae396 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types-data.context.ts @@ -1,6 +1,6 @@ -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeDataTypesContext extends UmbTreeContextBase { +export class UmbTreeDataTypesDataContext extends UmbTreeDataContextBase { public rootKey = '29d78e6c-c1bf-4c15-b820-d511c237ffae'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts index b9f132cfce..98b4450506 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/data-types/tree-data-types.element.ts @@ -1,44 +1,23 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; -import '../shared/tree-navigator.element'; -import { UmbTreeDataTypesContext } from './tree-data-types.context'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeDataTypesDataContext } from './tree-data-types-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; -import type { ManifestTree } from '../../../core/models'; +import { UmbTreeBase } from '../shared/tree-base.element'; + +import '../shared/tree-navigator.element'; @customElement('umb-tree-data-types') -export class UmbTreeDataTypesElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _selectable = false; - @property({ type: Boolean, reflect: true }) - get selectable() { - return this._selectable; - } - set selectable(newVal) { - const oldVal = this._selectable; - this._selectable = newVal; - this.requestUpdate('selectable', oldVal); - this._treeContext?.setSelectable(newVal); - } - - private _treeContext?: UmbTreeDataTypesContext; - private _entityStore?: UmbEntityStore; - +export class UmbTreeDataTypesElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; + if (!this._entityStore) return; - this._treeContext = new UmbTreeDataTypesContext(this.tree, this._entityStore); - this._treeContext.setSelectable(this.selectable); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeDataTypesDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts similarity index 81% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts index b9fc63a2ad..42b23908e9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types-data.context.ts @@ -1,6 +1,6 @@ -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeDocumentTypesContext extends UmbTreeContextBase { +export class UmbTreeDocumentTypesDataContext extends UmbTreeDataContextBase { public rootKey = 'f50eb86d-3ef2-4011-8c5d-c56c04eec0da'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts index d57dde7cae..d00ed53be6 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/document-types/tree-document-types.element.ts @@ -1,40 +1,28 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; -import { UmbTreeDocumentTypesContext } from './tree-document-types.context'; +import { UmbTreeDocumentTypesDataContext } from './tree-document-types-data.context'; +import { UmbTreeBase } from '../shared/tree-base.element'; import '../shared/tree-navigator.element'; -import type { ManifestTree } from '../../../core/models'; @customElement('umb-tree-document-types') -export class UmbTreeDocumentTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - @property({ type: String }) - public alias = ''; - - private _entityStore?: UmbEntityStore; - private _treeContext?: UmbTreeDocumentTypesContext; - +export class UmbTreeDocumentTypes extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbTreeBase)) { constructor() { super(); this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; + if (!this._entityStore) return; - this._treeContext = new UmbTreeDocumentTypesContext(this.tree, this._entityStore); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeDocumentTypesDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } render() { - return html``; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts index c519771193..4c7e1e518e 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/documents/tree-documents-data.context.ts @@ -1,7 +1,7 @@ import { map } from 'rxjs'; -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeDocumentContext extends UmbTreeContextBase { +export class UmbTreeDocumentDataContext extends UmbTreeDataContextBase { public rootKey = 'ba23245c-d8c0-46f7-a2bc-7623743d6eba'; public rootChanges() { 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 0f0086fea4..75f7eb7115 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 @@ -1,48 +1,14 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; -import '../shared/tree-navigator.element'; -import { UmbTreeDocumentContext } from './tree-documents.context'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeDocumentDataContext } from './tree-documents-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; -import { Subscription } from 'rxjs'; -import type { ManifestTree } from '../../../core/models'; +import { UmbTreeBase } from '../shared/tree-base.element'; + +import '../shared/tree-navigator.element'; @customElement('umb-tree-document') -export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _selectable = false; - @property({ type: Boolean, reflect: true }) - get selectable() { - return this._selectable; - } - set selectable(newVal) { - const oldVal = this._selectable; - this._selectable = newVal; - this.requestUpdate('selectable', oldVal); - this._treeContext?.setSelectable(newVal); - } - - private _selection: Array = []; - @property({ type: Array }) - get selection() { - return this._selection; - } - set selection(newVal: Array) { - const oldVal = this._selection; - this._selection = newVal; - this.requestUpdate('selection', oldVal); - this._treeContext?.setSelection(newVal); - } - - private _entityStore?: UmbEntityStore; - private _treeContext?: UmbTreeDocumentContext; - private _selectionSubscription?: Subscription; - +export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); @@ -50,18 +16,8 @@ export class UmbTreeDocumentElement extends UmbContextProviderMixin(UmbContextCo this._entityStore = entityStore; if (!this._entityStore || !this.tree) return; - this._treeContext = new UmbTreeDocumentContext(this.tree, this._entityStore); - this._treeContext.setSelectable(this.selectable); - this._treeContext.setSelection(this.selection); - this._observeSelection(); - this.provideContext('umbTreeContext', this._treeContext); - }); - } - - private _observeSelection() { - this._selectionSubscription?.unsubscribe(); - this._selectionSubscription = this._treeContext?.selection.subscribe((selection) => { - this._selection = selection; + this._treeDataContext = new UmbTreeDocumentDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts similarity index 70% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts index e2d3ffc76d..4a161c7adf 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions-data.context.ts @@ -1,6 +1,6 @@ -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeExtensionsContext extends UmbTreeContextBase { +export class UmbTreeExtensionsDataContext extends UmbTreeDataContextBase { public rootKey = 'fd32ea8b-893b-4ee9-b1d0-72f41c4a6d38'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts index 7ee32f6eca..55390ff8e9 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/extensions/tree-extensions.element.ts @@ -1,32 +1,23 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; -import { UmbTreeExtensionsContext } from './tree-extensions.context'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeExtensionsDataContext } from './tree-extensions-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; +import { UmbTreeBase } from '../shared/tree-base.element'; import '../shared/tree-navigator.element'; -import type { ManifestTree } from '../../../core/models'; @customElement('umb-tree-extensions') -export class UmbTreeExtensionsElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _treeContext?: UmbTreeExtensionsContext; - private _entityStore?: UmbEntityStore; - +export class UmbTreeExtensionsElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; + if (!this._entityStore) return; - this._treeContext = new UmbTreeExtensionsContext(this.tree, this._entityStore); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeExtensionsDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts similarity index 83% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts index 57ab485c25..9a0969cec7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media-data.context.ts @@ -1,7 +1,7 @@ import { map } from 'rxjs'; -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeMediaContext extends UmbTreeContextBase { +export class UmbTreeMediaDataContext extends UmbTreeDataContextBase { public rootKey = 'c0858d71-52be-4bb2-822f-42fa0c9a1ea5'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts index 7a72e6be55..cbfb56df44 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/media/tree-media.element.ts @@ -1,31 +1,23 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; -import '../shared/tree-navigator.element'; -import { UmbTreeMediaContext } from './tree-media.context'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbTreeMediaDataContext } from './tree-media-data.context'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; -import type { ManifestTree } from '../../../core/models'; +import { UmbTreeBase } from '../shared/tree-base.element'; + +import '../shared/tree-navigator.element'; @customElement('umb-tree-media') -export class UmbTreeMediaElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _treeContext?: UmbTreeMediaContext; - private _entityStore?: UmbEntityStore; - +export class UmbTreeMediaElement extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => { this._entityStore = entityStore; - if (!this._entityStore || !this.tree) return; + if (!this._entityStore) return; - this._treeContext = new UmbTreeMediaContext(this.tree, this._entityStore); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeMediaDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts similarity index 81% rename from src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.context.ts rename to src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts index d0a407e3c6..ae61ae9484 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups-data.context.ts @@ -1,6 +1,6 @@ -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeMemberGroupsContext extends UmbTreeContextBase { +export class UmbTreeMemberGroupsDataContext extends UmbTreeDataContextBase { public rootKey = '575645a5-0f25-4671-b9a0-be515096ad6b'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts index f023b6f47a..e3b8db1676 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/member-groups/tree-member-groups.element.ts @@ -1,24 +1,14 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; +import { UmbTreeMemberGroupsDataContext } from './tree-member-groups-data.context'; +import { UmbEntityStore } from '../../../core/stores/entity.store'; import '../shared/tree-navigator.element'; - -import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; -import { UmbTreeMemberGroupsContext } from './tree-member-groups.context'; -import { UmbEntityStore } from '../../../core/stores/entity.store'; -import type { ManifestTree } from '../../../core/models'; +import { UmbTreeBase } from '../shared/tree-base.element'; @customElement('umb-tree-member-groups') -export class UmbTreeMemberGroups extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _treeContext?: UmbTreeMemberGroupsContext; - private _entityStore?: UmbEntityStore; - +export class UmbTreeMemberGroups extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); @@ -26,8 +16,8 @@ export class UmbTreeMemberGroups extends UmbContextProviderMixin(UmbContextConsu this._entityStore = entityStore; if (!this._entityStore || !this.tree) return; - this._treeContext = new UmbTreeMemberGroupsContext(this.tree, this._entityStore); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeMemberGroupsDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts index d5057e46fe..11be2dbc3a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.context.ts @@ -1,6 +1,6 @@ -import { UmbTreeContextBase } from '../tree.context'; +import { UmbTreeDataContextBase } from '../tree-data.context'; -export class UmbTreeMembersContext extends UmbTreeContextBase { +export class UmbTreeMembersDataContext extends UmbTreeDataContextBase { public rootKey = '8f974b62-392b-4ddd-908c-03c2e03ab1a6'; public rootChanges() { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts index d970fa66e3..1fbcbdd9bf 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/members/tree-members.element.ts @@ -1,24 +1,14 @@ -import { css, html, LitElement } from 'lit'; -import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement, property } from 'lit/decorators.js'; - +import { html } from 'lit'; +import { customElement } from 'lit/decorators.js'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; -import { UmbTreeMembersContext } from './tree-members.context'; +import { UmbTreeMembersDataContext } from './tree-members.context'; import { UmbEntityStore } from '../../../core/stores/entity.store'; +import { UmbTreeBase } from '../shared/tree-base.element'; import '../shared/tree-navigator.element'; -import type { ManifestTree } from '../../../core/models'; @customElement('umb-tree-members') -export class UmbTreeMembers extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { - static styles = [UUITextStyles, css``]; - - @property({ type: Object, attribute: false }) - tree?: ManifestTree; - - private _treeContext?: UmbTreeMembersContext; - private _entityStore?: UmbEntityStore; - +export class UmbTreeMembers extends UmbContextProviderMixin(UmbContextConsumerMixin(UmbTreeBase)) { constructor() { super(); @@ -26,8 +16,8 @@ export class UmbTreeMembers extends UmbContextProviderMixin(UmbContextConsumerMi this._entityStore = entityStore; if (!this._entityStore || !this.tree) return; - this._treeContext = new UmbTreeMembersContext(this.tree, this._entityStore); - this.provideContext('umbTreeContext', this._treeContext); + this._treeDataContext = new UmbTreeMembersDataContext(this._entityStore); + this.provideContext('umbTreeDataContext', this._treeDataContext); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts new file mode 100644 index 0000000000..c466adb6e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-base.element.ts @@ -0,0 +1,20 @@ +import { LitElement } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import type { ManifestTree } from '../../../core/models'; +import { UmbEntityStore } from '../../../core/stores/entity.store'; +import { UmbTreeDataContext } from '../tree-data.context'; + +@customElement('umb-tree-base') +export class UmbTreeBase extends LitElement { + @property({ type: Object, attribute: false }) + tree?: ManifestTree; + + protected _treeDataContext?: UmbTreeDataContext; + protected _entityStore?: UmbEntityStore; +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-tree-base': UmbTreeBase; + } +} 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 db76139fc7..2aeea39a33 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 @@ -9,6 +9,7 @@ import { map, Subscription } from 'rxjs'; import { Entity } from '../../../mocks/data/entity.data'; import { UmbTreeContextMenuService } from './context-menu/tree-context-menu.service'; import { repeat } from 'lit/directives/repeat.js'; +import { UmbTreeDataContextBase } from '../tree-data.context'; @customElement('umb-tree-item') export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { @@ -36,6 +37,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { private _isActive = false; private _treeContext?: UmbTreeContextBase; + private _treeDataContext?: UmbTreeDataContextBase; private _sectionContext?: UmbSectionContext; private _treeContextMenuService?: UmbTreeContextMenuService; @@ -54,6 +56,10 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this._observeSelection(); }); + this.consumeContext('umbTreeDataContext', (treeDataContext: UmbTreeDataContextBase) => { + this._treeDataContext = treeDataContext; + }); + this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => { this._sectionContext = sectionContext; this._observeSection(); @@ -70,6 +76,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this.addEventListener('selected', (e) => { e.stopPropagation(); this._treeContext?.select(this.treeItem.key); + this.dispatchEvent(new CustomEvent('change', { composed: true, bubbles: true })); }); } @@ -91,7 +98,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { private _observeSelection() { this._selectionSubscription?.unsubscribe(); this._selectionSubscription = this._treeContext?.selection - .pipe(map((keys) => keys.includes(this.treeItem.key))) + .pipe(map((keys) => keys?.includes(this.treeItem.key))) .subscribe((isSelected) => { this._selected = isSelected; }); @@ -118,7 +125,7 @@ export class UmbTreeItem extends UmbContextConsumerMixin(LitElement) { this._childrenSubscription?.unsubscribe(); - this._childrenSubscription = this._treeContext?.childrenChanges(this.treeItem.key).subscribe((items) => { + this._childrenSubscription = this._treeDataContext?.childrenChanges(this.treeItem.key).subscribe((items) => { if (items?.length === 0) return; this._childItems = items; this._loading = false; 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 360243ea90..79e7342f70 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 @@ -3,11 +3,11 @@ import { repeat } from 'lit/directives/repeat.js'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, state } from 'lit/decorators.js'; import { UmbContextConsumerMixin } from '../../../core/context'; -import { UmbTreeContextBase } from '../tree.context'; - -import './tree-item.element'; import { Subscription } from 'rxjs'; import { Entity } from '../../../mocks/data/entity.data'; +import { UmbTreeDataContextBase } from '../tree-data.context'; + +import './tree-item.element'; @customElement('umb-tree-navigator') export class UmbTreeNavigator extends UmbContextConsumerMixin(LitElement) { @@ -16,17 +16,17 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(LitElement) { @state() private _loading = true; - private _treeContext?: UmbTreeContextBase; - private _treeRootSubscription?: Subscription; - @state() private _items: Entity[] = []; + private _treeDataContext?: UmbTreeDataContextBase; + private _treeRootSubscription?: Subscription; + constructor() { super(); - this.consumeContext('umbTreeContext', (treeContext) => { - this._treeContext = treeContext; + this.consumeContext('umbTreeDataContext', (treeDataContext) => { + this._treeDataContext = treeDataContext; this._observeTreeRoot(); }); } @@ -34,7 +34,7 @@ export class UmbTreeNavigator extends UmbContextConsumerMixin(LitElement) { private _observeTreeRoot() { this._loading = true; - this._treeRootSubscription = this._treeContext?.rootChanges?.().subscribe((items) => { + this._treeRootSubscription = this._treeDataContext?.rootChanges?.().subscribe((items) => { if (items?.length === 0) return; this._items = items; this._loading = false; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts new file mode 100644 index 0000000000..fa75a70bf9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree.element.ts @@ -0,0 +1,110 @@ +import { html, LitElement } from 'lit'; +import { when } from 'lit-html/directives/when.js'; +import { customElement, property, state } from 'lit/decorators.js'; +import { map, Subscription } from 'rxjs'; +import { UmbContextConsumerMixin, UmbContextProviderMixin } from '../../../core/context'; +import { UmbExtensionRegistry } from '../../../core/extension'; +import type { ManifestTree } from '../../../core/models'; +import { UmbTreeContextBase } from '../tree.context'; + +@customElement('umb-tree') +export class UmbTreeElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) { + private _alias = ''; + @property({ type: String, reflect: true }) + get alias() { + return this._alias; + } + set alias(newVal) { + const oldVal = this._alias; + this._alias = newVal; + this.requestUpdate('alias', oldVal); + this._observeTree(); + } + + private _selectable = false; + @property({ type: Boolean, reflect: true }) + get selectable() { + return this._selectable; + } + set selectable(newVal) { + const oldVal = this._selectable; + this._selectable = newVal; + this.requestUpdate('selectable', oldVal); + this._treeContext?.setSelectable(newVal); + } + + private _selection: Array = []; + @property({ type: Array }) + get selection() { + return this._selection; + } + set selection(newVal: Array) { + const oldVal = this._selection; + this._selection = newVal; + this.requestUpdate('selection', oldVal); + this._treeContext?.setSelection(newVal); + } + + @state() + private _tree?: ManifestTree; + + private _treeContext?: UmbTreeContextBase; + private _extensionRegistry?: UmbExtensionRegistry; + private _treeSubscription?: Subscription; + private _selectionSubscription?: Subscription; + + constructor() { + super(); + this.consumeContext('umbExtensionRegistry', (extensionRegistry) => { + this._extensionRegistry = extensionRegistry; + this._observeTree(); + }); + } + + private _observeTree() { + this._treeSubscription?.unsubscribe(); + + this._treeSubscription = this._extensionRegistry + ?.extensionsOfType('tree') + .pipe(map((trees) => trees.find((tree) => tree.alias === this.alias))) + .subscribe((tree) => { + this._tree = tree; + this._provideTreeContext(); + }); + } + + private _provideTreeContext() { + if (!this._tree) return; + this._treeContext = new UmbTreeContextBase(this._tree); + this._treeContext.setSelectable(this.selectable); + this._treeContext.setSelection(this.selection); + this.provideContext('umbTreeContext', this._treeContext); + + if (this.selectable) { + this._observeSelection(); + } + } + + private _observeSelection() { + this._selectionSubscription = this._treeContext?.selection.subscribe((selection) => { + this._selection = selection; + this.dispatchEvent(new CustomEvent('change')); + }); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + this._treeSubscription?.unsubscribe(); + this._selectionSubscription?.unsubscribe(); + } + + render() { + return html`${when(this._tree, () => html``)}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-tree': UmbTreeElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts new file mode 100644 index 0000000000..79811a5f57 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree-data.context.ts @@ -0,0 +1,31 @@ +import { map, Observable } from 'rxjs'; +import type { UmbEntityStore } from '../../core/stores/entity.store'; +import { Entity } from '../../mocks/data/entity.data'; + +export interface UmbTreeDataContext { + rootKey: string; + entityStore: UmbEntityStore; + rootChanges?(key: string): Observable; + childrenChanges?(key: string): Observable; +} + +export class UmbTreeDataContextBase implements UmbTreeDataContext { + public entityStore: UmbEntityStore; + public rootKey = ''; + + constructor(entityStore: UmbEntityStore) { + this.entityStore = entityStore; + } + + public rootChanges() { + return this.entityStore.items.pipe( + map((items) => items.filter((item) => item.key === this.rootKey && !item.isTrashed)) + ); + } + + public childrenChanges(key: string) { + return this.entityStore.items.pipe( + map((items) => items.filter((item) => item.parentKey === key && !item.isTrashed)) + ); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts index ed6f99b4a8..7281d349b2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/trees/tree.context.ts @@ -1,23 +1,17 @@ -import { BehaviorSubject, map, Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import type { ManifestTree } from '../../core/models'; -import type { UmbEntityStore } from '../../core/stores/entity.store'; -import { Entity } from '../../mocks/data/entity.data'; export interface UmbTreeContext { tree: ManifestTree; - rootKey: string; - entityStore: UmbEntityStore; readonly selectable: Observable; readonly selection: Observable>; - rootChanges?(key: string): Observable; - childrenChanges?(key: string): Observable; setSelectable(value: boolean): void; + setSelection(value: Array): void; select(key: string): void; } export class UmbTreeContextBase implements UmbTreeContext { public tree: ManifestTree; - public entityStore: UmbEntityStore; public rootKey = ''; private _selectable: BehaviorSubject = new BehaviorSubject(false); @@ -26,21 +20,8 @@ export class UmbTreeContextBase implements UmbTreeContext { private _selection: BehaviorSubject> = new BehaviorSubject(>[]); public readonly selection: Observable> = this._selection.asObservable(); - constructor(tree: ManifestTree, entityStore: UmbEntityStore) { + constructor(tree: ManifestTree) { this.tree = tree; - this.entityStore = entityStore; - } - - public rootChanges() { - return this.entityStore.items.pipe( - map((items) => items.filter((item) => item.key === this.rootKey && !item.isTrashed)) - ); - } - - public childrenChanges(key: string) { - return this.entityStore.items.pipe( - map((items) => items.filter((item) => item.parentKey === key && !item.isTrashed)) - ); } public setSelectable(value: boolean) { @@ -48,6 +29,7 @@ export class UmbTreeContextBase implements UmbTreeContext { } public setSelection(value: Array) { + if (!value) return; this._selection.next(value); } diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts index 29a40378c0..76a99092fa 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/content-picker/modal-layout-content-picker.element.ts @@ -9,6 +9,7 @@ export interface UmbModalContentPickerData { } import '../../../../../backoffice/trees/documents/tree-documents.element'; +import { UmbTreeElement } from '../../../../../backoffice/trees/shared/tree.element'; @customElement('umb-modal-layout-content-picker') export class UmbModalLayoutContentPickerElement extends UmbModalLayoutElement { @@ -57,7 +58,7 @@ export class UmbModalLayoutContentPickerElement extends UmbModalLayoutElement
- + selectable>