split tree context and tree data context api's

This commit is contained in:
Mads Rasmussen
2022-09-08 21:57:35 +02:00
parent ccfc79cad1
commit 4accfe1eb8
23 changed files with 279 additions and 241 deletions

View File

@@ -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';

View File

@@ -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<ManifestTree> = [];
private _treeAliases: Array<string> = [];
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`<umb-tree-extension .tree=${tree}></umb-tree-extension>`)} `;
return html`${this._treeAliases.map((treeAlias) => html`<umb-tree alias="${treeAlias}"></umb-tree>`)} `;
}
}

View File

@@ -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() {

View File

@@ -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);
});
}

View File

@@ -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() {

View File

@@ -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`<umb-tree-navigator .label=${this.alias}></umb-tree-navigator>`;
return html`<umb-tree-navigator></umb-tree-navigator>`;
}
}

View File

@@ -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() {

View File

@@ -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<string> = [];
@property({ type: Array })
get selection() {
return this._selection;
}
set selection(newVal: Array<string>) {
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);
});
}

View File

@@ -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() {

View File

@@ -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);
});
}

View File

@@ -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() {

View File

@@ -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);
});
}

View File

@@ -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() {

View File

@@ -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);
});
}

View File

@@ -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() {

View File

@@ -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);
});
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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<string> = [];
@property({ type: Array })
get selection() {
return this._selection;
}
set selection(newVal: Array<string>) {
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`<umb-tree-extension .tree=${this._tree}></umb-tree-extension>`)}`;
}
}
declare global {
interface HTMLElementTagNameMap {
'umb-tree': UmbTreeElement;
}
}

View File

@@ -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<Entity[]>;
childrenChanges?(key: string): Observable<Entity[]>;
}
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))
);
}
}

View File

@@ -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<boolean>;
readonly selection: Observable<Array<string>>;
rootChanges?(key: string): Observable<Entity[]>;
childrenChanges?(key: string): Observable<Entity[]>;
setSelectable(value: boolean): void;
setSelection(value: Array<string>): void;
select(key: string): void;
}
export class UmbTreeContextBase implements UmbTreeContext {
public tree: ManifestTree;
public entityStore: UmbEntityStore;
public rootKey = '';
private _selectable: BehaviorSubject<boolean> = new BehaviorSubject(false);
@@ -26,21 +20,8 @@ export class UmbTreeContextBase implements UmbTreeContext {
private _selection: BehaviorSubject<Array<string>> = new BehaviorSubject(<Array<string>>[]);
public readonly selection: Observable<Array<string>> = 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<string>) {
if (!value) return;
this._selection.next(value);
}

View File

@@ -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<UmbModalContentPickerData> {
@@ -57,7 +58,7 @@ export class UmbModalLayoutContentPickerElement extends UmbModalLayoutElement<Um
private _handleSelectionChange(e: CustomEvent) {
e.stopPropagation();
const element = e.composedPath()[0] as any;
const element = e.target as UmbTreeElement;
this._selection = element.selection;
}
@@ -77,10 +78,11 @@ export class UmbModalLayoutContentPickerElement extends UmbModalLayoutElement<Um
<uui-box>
<uui-input></uui-input>
<hr />
<umb-tree-document
@change="${this._handleSelectionChange}"
<umb-tree
alias="Umb.Tree.Content"
@change=${this._handleSelectionChange}
.selection=${this._selection}
selectable></umb-tree-document>
selectable></umb-tree>
</uui-box>
<div slot="actions">
<uui-button label="Close" @click=${this._close}></uui-button>