From 5ea3a3e2e7933f18a86bf8fc3928be1690d5949c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Mar 2024 23:15:02 +0100 Subject: [PATCH] keep tree items in the context and observe from element --- .../core/tree/default/default-tree.context.ts | 29 +++++------- .../core/tree/default/default-tree.element.ts | 44 +++---------------- .../tree-item-base/tree-item-context-base.ts | 16 ++++--- .../tree-item-base/tree-item-element-base.ts | 21 ++------- .../tree-item/tree-item-context.interface.ts | 9 +--- 5 files changed, 34 insertions(+), 85 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts index ddaa96d7f0..38a8c8231c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.context.ts @@ -13,7 +13,7 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbExtensionApiInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbPaginationManager, UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; import type { UmbEntityActionEvent } from '@umbraco-cms/backoffice/entity-action'; -import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @@ -24,6 +24,9 @@ export class UmbDefaultTreeContext #treeRoot = new UmbObjectState(undefined); treeRoot = this.#treeRoot.asObservable(); + #rootItems = new UmbArrayState([], (x) => x.unique); + rootItems = this.#rootItems.asObservable(); + public selectableFilter?: (item: TreeItemType) => boolean = () => true; public filter?: (item: TreeItemType) => boolean = () => true; public readonly selection = new UmbSelectionManager(this._host); @@ -52,7 +55,7 @@ export class UmbDefaultTreeContext // listen for page changes on the pagination manager this.pagination.addEventListener(UmbChangeEvent.TYPE, this.#onPageChange); - this.requestTreeRoot(); + this.loadTreeRoot(); } // TODO: find a generic way to do this @@ -91,35 +94,27 @@ export class UmbDefaultTreeContext return this.#repository; } - public async requestTreeRoot() { + public async loadTreeRoot() { await this.#init; const { data } = await this.#repository!.requestTreeRoot(); if (data) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore this.#treeRoot.setValue(data); } } - public async requestRootItems() { + public async loadRootItems() { await this.#init; - const { data, error, asObservable } = await this.#repository!.requestRootTreeItems({ + const { data } = await this.#repository!.requestRootTreeItems({ skip: this.#paging.skip, take: this.#paging.take, }); if (data) { + this.#rootItems.setValue(data.items); this.pagination.setTotalItems(data.total); } - - return { data, error, asObservable }; - } - - public async rootItems() { - await this.#init; - return this.#repository!.rootTreeItems(); } #consumeContexts() { @@ -139,7 +134,7 @@ export class UmbDefaultTreeContext #onPageChange = (event: UmbChangeEvent) => { const target = event.target as UmbPaginationManager; this.#paging.skip = target.getSkip(); - this.requestRootItems(); + this.loadRootItems(); }; #observeRepository(repositoryAlias?: string) { @@ -161,11 +156,9 @@ export class UmbDefaultTreeContext // Only handle root request here. Items are handled by the tree item context const treeRoot = this.#treeRoot.getValue(); if (treeRoot === undefined) return; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore if (event.getUnique() !== treeRoot.unique) return; if (event.getEntityType() !== treeRoot.entityType) return; - this.requestRootItems(); + this.loadRootItems(); }; destroy(): void { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts index 07d1f88f76..4fdf4748c3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/default/default-tree.element.ts @@ -26,7 +26,7 @@ export class UmbDefaultTreeElement extends UmbLitElement { filter: (item: UmbTreeItemModelBase) => boolean = () => true; @state() - private _items: UmbTreeItemModelBase[] = []; + private _rootItems: UmbTreeItemModelBase[] = []; @state() private _treeRoot?: UmbTreeItemModelBase; @@ -47,11 +47,10 @@ export class UmbDefaultTreeElement extends UmbLitElement { // TODO: Notice this can be retrieve via a api property. [NL] this.consumeContext(UMB_DEFAULT_TREE_CONTEXT, (instance) => { this.#treeContext = instance; - + this.observe(this.#treeContext.treeRoot, (treeRoot) => (this._treeRoot = treeRoot)); + this.observe(this.#treeContext.rootItems, (rootItems) => (this._rootItems = rootItems)); this.observe(this.#treeContext.pagination.currentPage, (value) => (this._currentPage = value)); this.observe(this.#treeContext.pagination.totalPages, (value) => (this._totalPages = value)); - - this.#observeTreeRoot(); }).asPromise(), ]); } @@ -70,7 +69,8 @@ export class UmbDefaultTreeElement extends UmbLitElement { if (_changedProperties.has('hideTreeRoot')) { if (this.hideTreeRoot === true) { - this.#observeRootItems(); + await this.#init; + this.#treeContext!.loadRootItems(); } } @@ -83,36 +83,6 @@ export class UmbDefaultTreeElement extends UmbLitElement { } } - #observeTreeRoot() { - if (!this.#treeContext) return; - this.observe( - this.#treeContext.treeRoot, - (treeRoot) => { - this._treeRoot = treeRoot; - }, - 'umbTreeRootObserver', - ); - } - - async #observeRootItems() { - await this.#init; - if (!this.#treeContext?.requestRootItems) throw new Error('Tree does not support root items'); - - const { asObservable } = await this.#treeContext.requestRootItems(); - - if (asObservable) { - this.observe( - asObservable(), - (rootItems) => { - const oldValue = this._items; - this._items = rootItems; - this.requestUpdate('_items', oldValue); - }, - 'umbRootItemsObserver', - ); - } - } - getSelection() { return this.#treeContext?.selection.getSelection(); } @@ -129,10 +99,10 @@ export class UmbDefaultTreeElement extends UmbLitElement { } #renderRootItems() { - if (this._items?.length === 0) return nothing; + if (this._rootItems?.length === 0) return nothing; return html` ${repeat( - this._items, + this._rootItems, (item, index) => item.name + '___' + index, (item) => html``, )} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts index 1058ab101a..270f01d12d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-context-base.ts @@ -7,7 +7,7 @@ import { UMB_SECTION_CONTEXT, UMB_SECTION_SIDEBAR_CONTEXT } from '@umbraco-cms/b import type { UmbSectionContext, UmbSectionSidebarContext } from '@umbraco-cms/backoffice/section'; import type { ManifestTreeItem } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbBooleanState, UmbDeepState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbArrayState, UmbBooleanState, UmbDeepState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; @@ -33,6 +33,9 @@ export abstract class UmbTreeItemContextBase(undefined); treeItem = this.#treeItem.asObservable(); + #childItems = new UmbArrayState([], (x) => x.unique); + childItems = this.#childItems.asObservable(); + #hasChildren = new UmbBooleanState(false); hasChildren = this.#hasChildren.asObservable(); #hasChildrenInitValueFlag = false; @@ -129,25 +132,26 @@ export abstract class UmbTreeItemContextBase { const target = event.target as UmbPaginationManager; this.#paging.skip = target.getSkip(); - this.requestChildren(); + this.loadChildren(); }; // TODO: use router context diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts index 5e64919b39..37a2d713f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-base/tree-item-element-base.ts @@ -60,6 +60,7 @@ export abstract class UmbTreeItemElementBase (this._item = value)); + this.observe(this.#treeItemContext.childItems, (value) => (this._childItems = value)); this.observe(this.#treeItemContext.hasChildren, (value) => (this._hasChildren = value)); this.observe(this.#treeItemContext.isLoading, (value) => (this._isLoading = value)); this.observe(this.#treeItemContext.isSelectableContext, (value) => (this._isSelectableContext = value)); @@ -89,21 +90,7 @@ export abstract class UmbTreeItemElementBase 0) return; - this.#observeChildren(); - } - - async #observeChildren() { - if (!this.#treeItemContext?.requestChildren) return; - - const { asObservable } = await this.#treeItemContext.requestChildren(); - if (!asObservable) return; - - this.observe(asObservable(), (childItems) => { - const oldValue = this._childItems; - this._childItems = childItems; - this.requestUpdate('_childItems', oldValue); - }); + this.#treeItemContext?.loadChildren(); } #onLoadMoreClick = (event: any) => { @@ -176,7 +163,7 @@ export abstract class UmbTreeItemElementBase - ` + ` : ''; } @@ -187,7 +174,7 @@ export abstract class UmbTreeItemElementBase item.name + '___' + index, (item) => html``, - ) + ) : ''} `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts index 8ae64f95df..a95973075f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree-item/tree-item-context.interface.ts @@ -1,14 +1,13 @@ import type { UmbTreeItemModelBase } from '../types.js'; import type { UmbPaginationManager } from '../../utils/pagination-manager/pagination.manager.js'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { ProblemDetails } from '@umbraco-cms/backoffice/external/backend-api'; -import type { UmbPagedModel } from '@umbraco-cms/backoffice/repository'; import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; export interface UmbTreeItemContext extends UmbApi { unique?: string | null; entityType?: string; treeItem: Observable; + childItems: Observable; hasChildren: Observable; isLoading: Observable; isSelectableContext: Observable; @@ -19,11 +18,7 @@ export interface UmbTreeItemContext e path: Observable; pagination: UmbPaginationManager; setTreeItem(treeItem: TreeItemType | undefined): void; - requestChildren(): Promise<{ - data?: UmbPagedModel | undefined; - error?: ProblemDetails | undefined; - asObservable?: () => Observable; - }>; + loadChildren(): void; toggleContextMenu(): void; select(): void; deselect(): void;