Files
Umbraco-CMS/src/Umbraco.Web.UI.Client/src/backoffice/trees/shared/tree-navigator.element.ts
Niels Lyngsø c14c752ed7 refactor done
2022-12-22 10:33:43 +01:00

128 lines
3.4 KiB
TypeScript

import { css, html, LitElement } from 'lit';
import { repeat } from 'lit/directives/repeat.js';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { customElement, property, state } from 'lit/decorators.js';
import { ifDefined } from 'lit-html/directives/if-defined.js';
import { UmbSectionContext } from '../../sections/shared/section.context';
import { UmbTreeContext } from '../tree.context';
import { UmbObserverMixin } from '@umbraco-cms/observable-api';
import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api';
import type { Entity, ManifestSection, ManifestTree } from '@umbraco-cms/models';
import { UmbTreeDataStore } from 'src/core/stores/store';
import './tree-item.element';
@customElement('umb-tree-navigator')
export class UmbTreeNavigator extends UmbContextConsumerMixin(UmbContextProviderMixin(UmbObserverMixin(LitElement))) {
static styles = [UUITextStyles, css``];
private _storeContextAlias = '';
@property({ attribute: 'store-context-alias' })
public get storeContextAlias() {
return this._storeContextAlias;
}
public set storeContextAlias(value) {
this._storeContextAlias = value;
this._provideStoreContext();
}
@state()
private _loading = true;
@state()
private _items: Entity[] = [];
@state()
private _tree?: ManifestTree;
@state()
private _href?: string;
private _store?: UmbTreeDataStore<unknown>;
private _sectionContext?: UmbSectionContext;
constructor() {
super();
this.consumeContext('umbStore', (store) => {
this._store = store;
});
this.consumeContext('umbTreeContext', (treeContext: UmbTreeContext) => {
this._tree = treeContext.tree;
});
this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => {
this._sectionContext = sectionContext;
this._observeSection();
});
}
private _provideStoreContext() {
if (!this._storeContextAlias) return;
this.consumeContext(this._storeContextAlias, (store) => {
this._store = store;
this.provideContext('umbStore', store);
});
}
private _onShowRoot() {
this._observeTreeRoot();
}
private _observeTreeRoot() {
if (!this._store?.getTreeRoot) return;
this._loading = true;
this.observe<Entity[]>(this._store.getTreeRoot(), (rootItems) => {
if (rootItems?.length === 0) return;
this._items = rootItems;
this._loading = false;
});
}
private _observeSection() {
if (!this._sectionContext) return;
this.observe<ManifestSection>(this._sectionContext?.data, (section) => {
this._href = this._constructPath(section.meta.pathname, this._tree?.meta.rootNodeEntityType);
});
}
// TODO: how do we handle this?
private _constructPath(sectionPathname: string, type: string | undefined) {
return type ? `section/${sectionPathname}/${type}` : undefined;
}
render() {
// TODO: how do we know if a tree has children?
return html`<uui-menu-item
label="${ifDefined(this._tree?.meta.label)}"
@show-children=${this._onShowRoot}
href="${ifDefined(this._href)}"
has-children>
<uui-icon slot="icon" name="${ifDefined(this._tree?.meta.icon)}"></uui-icon>
${this._renderRootItems()}
</uui-menu-item>`;
}
private _renderRootItems() {
return html`
${repeat(
this._items,
(item) => item.key,
(item) => html`<umb-tree-item .treeItem=${item} .loading=${this._loading}></umb-tree-item>`
)}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'umb-tree-navigator': UmbTreeNavigator;
}
}