use observer mixin

This commit is contained in:
Mads Rasmussen
2022-10-12 13:38:54 +02:00
parent c0c59355af
commit 64815ec621
9 changed files with 129 additions and 178 deletions

View File

@@ -1,16 +1,17 @@
import { css, html, LitElement } from 'lit';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { customElement, state } from 'lit/decorators.js';
import { Subscription, distinctUntilChanged } from 'rxjs';
import { distinctUntilChanged } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../../../../core/context';
import { UmbNodeContext } from '../../node.context';
import { UmbObserverMixin } from '../../../../../../core/observer';
import type { NodeEntity } from '../../../../../../mocks/data/node.data';
@customElement('umb-editor-view-node-info')
export class UmbEditorViewNodeInfoElement extends UmbContextConsumerMixin(LitElement) {
export class UmbEditorViewNodeInfoElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [UUITextStyles, css``];
private _nodeContext?: UmbNodeContext;
private _nodeContextSubscription?: Subscription;
@state()
private _nodeName = '';
@@ -20,14 +21,14 @@ export class UmbEditorViewNodeInfoElement extends UmbContextConsumerMixin(LitEle
this.consumeContext('umbNodeContext', (nodeContext) => {
this._nodeContext = nodeContext;
this._useNode();
this._observeNode();
});
}
private _useNode() {
this._nodeContextSubscription?.unsubscribe();
private _observeNode() {
if (!this._nodeContext) return;
this._nodeContextSubscription = this._nodeContext?.data.pipe(distinctUntilChanged()).subscribe((node) => {
this.observe<NodeEntity>(this._nodeContext.data.pipe(distinctUntilChanged()), (node) => {
this._nodeName = node.name;
});
}

View File

@@ -3,14 +3,17 @@ import '../property-action/property-action.element';
import { UUITextStyles } from '@umbraco-ui/uui';
import { css, CSSResultGroup, html, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { Subscription, map } from 'rxjs';
import { map } from 'rxjs';
import { UmbContextProviderMixin, UmbContextConsumerMixin } from '../../../../core/context';
import { UmbExtensionRegistry } from '../../../../core/extension';
import type { ManifestPropertyAction } from '../../../../core/models';
import { UmbObserverMixin } from '../../../../core/observer';
import { UmbPropertyActionMenuContext } from './property-action-menu.context';
@customElement('umb-property-action-menu')
export class UmbPropertyActionMenuElement extends UmbContextProviderMixin(UmbContextConsumerMixin(LitElement)) {
export class UmbPropertyActionMenuElement extends UmbContextProviderMixin(
UmbContextConsumerMixin(UmbObserverMixin(LitElement))
) {
static styles: CSSResultGroup = [
UUITextStyles,
css`
@@ -54,40 +57,44 @@ export class UmbPropertyActionMenuElement extends UmbContextProviderMixin(UmbCon
private _open = false;
private _extensionRegistry?: UmbExtensionRegistry;
private _propertyActionsSubscription?: Subscription;
private _propertyActionMenuContext = new UmbPropertyActionMenuContext();
private _propertyActionMenuOpenSubscription?: Subscription;
constructor() {
super();
this._propertyActionMenuOpenSubscription = this._propertyActionMenuContext.isOpen.subscribe((value: boolean) => {
this._open = value;
});
this.consumeContext('umbExtensionRegistry', (extensionRegistry: UmbExtensionRegistry) => {
this._extensionRegistry = extensionRegistry;
this._usePropertyActions();
this._observePropertyActions();
});
this.provideContext('umbPropertyActionMenu', this._propertyActionMenuContext);
}
private _usePropertyActions() {
this._propertyActionsSubscription?.unsubscribe();
connectedCallback(): void {
super.connectedCallback();
this._extensionRegistry
?.extensionsOfType('propertyAction')
.pipe(
map((propertyActions) =>
propertyActions.filter((propertyAction) =>
propertyAction.meta.propertyEditors.includes(this.propertyEditorUIAlias)
this.observe<boolean>(this._propertyActionMenuContext.isOpen, (value) => {
this._open = value;
});
}
private _observePropertyActions() {
if (!this._extensionRegistry) return;
this.observe<ManifestPropertyAction[]>(
this._extensionRegistry
.extensionsOfType('propertyAction')
.pipe(
map((propertyActions) =>
propertyActions.filter((propertyAction) =>
propertyAction.meta.propertyEditors.includes(this.propertyEditorUIAlias)
)
)
)
)
.subscribe((extensions) => {
this._actions = extensions;
});
),
(propertyActionManifests) => {
this._actions = propertyActionManifests;
}
);
}
private _toggleMenu() {
@@ -100,12 +107,6 @@ export class UmbPropertyActionMenuElement extends UmbContextProviderMixin(UmbCon
event.stopPropagation();
}
disconnectedCallback() {
super.disconnectedCallback();
this._propertyActionMenuOpenSubscription?.unsubscribe();
this._propertyActionsSubscription?.unsubscribe();
}
render() {
return html`
${this._actions?.length > 0

View File

@@ -1,15 +1,15 @@
import { css, html, LitElement, nothing } from 'lit';
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { customElement, property, state } from 'lit/decorators.js';
import type { Subscription } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../core/context';
import type { UmbModalService } from '../../../core/services/modal';
import type { UmbEntityStore } from '../../../core/stores/entity.store';
import type { Entity } from '../../../mocks/data/entities';
import { UmbObserverMixin } from '../../../core/observer';
@customElement('umb-property-editor-ui-content-picker')
export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerMixin(LitElement) {
export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [
UUITextStyles,
css`
@@ -45,7 +45,6 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerM
private _modalService?: UmbModalService;
private _entityStore?: UmbEntityStore;
private _pickedEntitiesSubscription?: Subscription;
constructor() {
super();
@@ -60,8 +59,8 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerM
}
private _observePickedEntities() {
this._pickedEntitiesSubscription?.unsubscribe();
this._pickedEntitiesSubscription = this._entityStore?.getByKeys(this.value).subscribe((entities) => {
if (!this._entityStore) return;
this.observe<Entity[]>(this._entityStore.getByKeys(this.value), (entities) => {
this._items = entities;
});
}
@@ -95,11 +94,6 @@ export class UmbPropertyEditorUIContentPickerElement extends UmbContextConsumerM
this.dispatchEvent(new CustomEvent('property-editor-change', { bubbles: true, composed: true }));
}
disconnectedCallback() {
super.disconnectedCallback();
this._pickedEntitiesSubscription?.unsubscribe();
}
private _renderItem(item: Entity) {
return html`
<uui-ref-node name=${item.name} detail=${item.key}>

View File

@@ -2,12 +2,18 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { html, LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { ifDefined } from 'lit-html/directives/if-defined.js';
import { Subscription } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../../core/context';
import { UmbExtensionRegistry } from '../../../../core/extension';
import { UmbPropertyEditorConfigStore } from '../../../../core/stores/property-editor-config/property-editor-config.store';
import type { PropertyEditorConfigDefaultData, PropertyEditorConfigProperty } from '../../../../core/models';
import {
PropertyEditorConfigRef,
UmbPropertyEditorConfigStore,
} from '../../../../core/stores/property-editor-config/property-editor-config.store';
import { UmbObserverMixin } from '../../../../core/observer';
import type {
ManifestTypes,
PropertyEditorConfigDefaultData,
PropertyEditorConfigProperty,
} from '../../../../core/models';
import '../../../components/entity-property/entity-property.element';
@@ -16,7 +22,7 @@ import '../../../components/entity-property/entity-property.element';
* @description - Element for displaying the configuration for a Property Editor and Property Editor UI.
*/
@customElement('umb-property-editor-config')
export class UmbPropertyEditorConfigElement extends UmbContextConsumerMixin(LitElement) {
export class UmbPropertyEditorConfigElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [UUITextStyles];
/**
@@ -77,10 +83,7 @@ export class UmbPropertyEditorConfigElement extends UmbContextConsumerMixin(LitE
private _propertyEditorUIConfigProperties: Array<PropertyEditorConfigProperty> = [];
private _propertyEditorConfigStore?: UmbPropertyEditorConfigStore;
private _propertyEditorConfigSubscription?: Subscription;
private _extensionRegistry?: UmbExtensionRegistry;
private _propertyEditorUIConfigSubscription?: Subscription;
constructor() {
super();
@@ -99,25 +102,22 @@ export class UmbPropertyEditorConfigElement extends UmbContextConsumerMixin(LitE
private _observePropertyEditorConfig() {
if (!this._propertyEditorConfigStore || !this._propertyEditorAlias) return;
this._propertyEditorConfigSubscription?.unsubscribe();
this._propertyEditorConfigSubscription = this._propertyEditorConfigStore
?.getByAlias(this.propertyEditorAlias)
.subscribe((propertyEditorConfig) => {
this.observe<PropertyEditorConfigRef>(
this._propertyEditorConfigStore.getByAlias(this.propertyEditorAlias),
(propertyEditorConfig) => {
if (!propertyEditorConfig) return;
this._propertyEditorConfigProperties = propertyEditorConfig?.config?.properties || [];
this._mergeProperties();
this._propertyEditorConfigDefaultData = propertyEditorConfig?.config?.defaultData || [];
this._mergeDefaultData();
});
}
);
}
private _observePropertyEditorUIConfig() {
if (!this._extensionRegistry || !this._propertyEditorUIAlias) return;
this._propertyEditorUIConfigSubscription?.unsubscribe();
this._extensionRegistry?.getByAlias(this.propertyEditorUIAlias).subscribe((manifest) => {
this.observe<ManifestTypes>(this._extensionRegistry.getByAlias(this.propertyEditorUIAlias), (manifest) => {
if (manifest?.type === 'propertyEditorUI') {
this._propertyEditorUIConfigProperties = manifest?.meta.config?.properties || [];
this._mergeProperties();
@@ -141,12 +141,6 @@ export class UmbPropertyEditorConfigElement extends UmbContextConsumerMixin(LitE
return value || defaultValue || null;
}
disconnectedCallback(): void {
super.disconnectedCallback();
this._propertyEditorConfigSubscription?.unsubscribe();
this._propertyEditorUIConfigSubscription?.unsubscribe();
}
render() {
return html`
${this._properties.length > 0

View File

@@ -8,10 +8,11 @@ import { UmbContextConsumerMixin } from '../../../core/context';
import { createExtensionElement, UmbExtensionRegistry } from '../../../core/extension';
import { UmbSectionContext } from '../section.context';
import type { ManifestDashboard } from '../../../core/models';
import type { ManifestDashboard, ManifestSection } from '../../../core/models';
import { UmbObserverMixin } from '../../../core/observer';
@customElement('umb-section-dashboards')
export class UmbSectionDashboards extends UmbContextConsumerMixin(LitElement) {
export class UmbSectionDashboards extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [
UUITextStyles,
css`
@@ -54,10 +55,7 @@ export class UmbSectionDashboards extends UmbContextConsumerMixin(LitElement) {
private _currentSectionAlias = '';
private _extensionRegistry?: UmbExtensionRegistry;
private _dashboardsSubscription?: Subscription;
private _sectionContext?: UmbSectionContext;
private _sectionContextSubscription?: Subscription;
constructor() {
super();
@@ -69,39 +67,39 @@ export class UmbSectionDashboards extends UmbContextConsumerMixin(LitElement) {
this.consumeContext('umbSectionContext', (context: UmbSectionContext) => {
this._sectionContext = context;
this._useSectionContext();
this._observeSectionContext();
});
}
private _useSectionContext() {
this._sectionContextSubscription?.unsubscribe();
private _observeSectionContext() {
if (!this._sectionContext) return;
this._sectionContextSubscription = this._sectionContext?.data.pipe(first()).subscribe((section) => {
this.observe<ManifestSection>(this._sectionContext.data.pipe(first()), (section) => {
this._currentSectionAlias = section.alias;
this._currentSectionPathname = section.meta.pathname;
this._useDashboards();
this._observeDashboards();
});
}
private _useDashboards() {
private _observeDashboards() {
if (!this._extensionRegistry || !this._currentSectionAlias) return;
this._dashboardsSubscription?.unsubscribe();
this._dashboardsSubscription = this._extensionRegistry
?.extensionsOfType('dashboard')
.pipe(
map((extensions) =>
extensions
.filter((extension) => extension.meta.sections.includes(this._currentSectionAlias))
.sort((a, b) => b.meta.weight - a.meta.weight)
)
)
.subscribe((dashboards) => {
this.observe<ManifestDashboard[]>(
this._extensionRegistry
?.extensionsOfType('dashboard')
.pipe(
map((extensions) =>
extensions
.filter((extension) => extension.meta.sections.includes(this._currentSectionAlias))
.sort((a, b) => b.meta.weight - a.meta.weight)
)
),
(dashboards) => {
if (dashboards?.length === 0) return;
this._dashboards = dashboards;
this._createRoutes();
});
}
);
}
private _createRoutes() {
@@ -142,12 +140,6 @@ export class UmbSectionDashboards extends UmbContextConsumerMixin(LitElement) {
`;
}
disconnectedCallback() {
super.disconnectedCallback();
this._dashboardsSubscription?.unsubscribe();
this._sectionContextSubscription?.unsubscribe();
}
render() {
return html`
${this._renderNavigation()}

View File

@@ -1,13 +1,14 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { Subscription } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../core/context';
import { UmbSectionContext } from '../section.context';
import '../../trees/shared/context-menu/tree-context-menu.service';
import { UmbObserverMixin } from '../../../core/observer';
import type { ManifestSection } from '../../../core/models';
@customElement('umb-section-sidebar')
export class UmbSectionSidebar extends UmbContextConsumerMixin(LitElement) {
export class UmbSectionSidebar extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [
UUITextStyles,
css`
@@ -34,31 +35,25 @@ export class UmbSectionSidebar extends UmbContextConsumerMixin(LitElement) {
private _sectionPathname = '';
private _sectionContext?: UmbSectionContext;
private _sectionContextSubscription?: Subscription;
constructor() {
super();
this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => {
this._sectionContext = sectionContext;
this._useSectionContext();
this._observeSectionContext();
});
}
private _useSectionContext() {
this._sectionContextSubscription?.unsubscribe();
private _observeSectionContext() {
if (!this._sectionContext) return;
this._sectionContextSubscription = this._sectionContext?.data.subscribe((section) => {
this.observe<ManifestSection>(this._sectionContext.data, (section) => {
this._sectionLabel = section.meta.label || section.name;
this._sectionPathname = section.meta.pathname;
});
}
disconnectedCallback(): void {
super.disconnectedCallback();
this._sectionContextSubscription?.unsubscribe();
}
render() {
return html`
<umb-tree-context-menu-service>

View File

@@ -1,26 +1,24 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { map, Subscription, switchMap, EMPTY, of } from 'rxjs';
import { map, switchMap, EMPTY, of } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../core/context';
import { UmbExtensionRegistry } from '../../../core/extension';
import { UmbSectionContext } from '../section.context';
import '../../trees/shared/tree-extension.element';
import { UmbObserverMixin } from '../../../core/observer';
@customElement('umb-section-trees')
export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) {
export class UmbSectionTrees extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [UUITextStyles];
@state()
private _treeAliases: Array<string> = [];
private _extensionStore?: UmbExtensionRegistry;
private _treesSubscription?: Subscription;
private _sectionContext?: UmbSectionContext;
private _sectionContextSubscription?: Subscription;
constructor() {
super();
@@ -28,22 +26,20 @@ export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) {
// TODO: wait for more contexts
this.consumeContext('umbExtensionRegistry', (extensionStore: UmbExtensionRegistry) => {
this._extensionStore = extensionStore;
this._useTrees();
this._observeTrees();
});
this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => {
this._sectionContext = sectionContext;
this._useTrees();
this._observeTrees();
});
}
private _useTrees() {
private _observeTrees() {
if (!this._extensionStore || !this._sectionContext) return;
this._treesSubscription?.unsubscribe();
this._treesSubscription = this._sectionContext?.data
.pipe(
this.observe<string[]>(
this._sectionContext?.data.pipe(
switchMap((section) => {
if (!section) return EMPTY;
@@ -58,16 +54,11 @@ export class UmbSectionTrees extends UmbContextConsumerMixin(LitElement) {
) ?? of([])
);
})
)
.subscribe((treeAliases) => {
),
(treeAliases) => {
this._treeAliases = treeAliases;
});
}
disconnectedCallback() {
super.disconnectedCallback();
this._treesSubscription?.unsubscribe();
this._sectionContextSubscription?.unsubscribe();
}
);
}
render() {

View File

@@ -1,18 +1,20 @@
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
import { css, html, LitElement } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { Subscription, map, switchMap, EMPTY, of } from 'rxjs';
import { map, switchMap, EMPTY, of } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../core/context';
import { UmbExtensionRegistry } from '../../../core/extension';
import { UmbSectionContext } from '../section.context';
import type { ManifestTree, ManifestEditor } from '../../../core/models';
import type { ManifestTree } from '../../../core/models';
import '../shared/section-trees.element.ts';
import { UmbEditorEntityElement } from '../../editors/shared/editor-entity/editor-entity.element';
import { UmbEntityStore } from '../../../core/stores/entity.store';
import { UmbObserverMixin } from '../../../core/observer';
import '../shared/section-trees.element.ts';
@customElement('umb-section')
export class UmbSectionElement extends UmbContextConsumerMixin(LitElement) {
export class UmbSectionElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
static styles = [
UUITextStyles,
css`
@@ -30,14 +32,9 @@ export class UmbSectionElement extends UmbContextConsumerMixin(LitElement) {
@state()
private _trees?: Array<ManifestTree>;
private _editors?: Array<ManifestEditor>;
private _editorsSubscription?: Subscription;
private _entityStore?: UmbEntityStore;
private _sectionContext?: UmbSectionContext;
private _extensionRegistry?: UmbExtensionRegistry;
private _treesSubscription?: Subscription;
constructor() {
super();
@@ -45,27 +42,25 @@ export class UmbSectionElement extends UmbContextConsumerMixin(LitElement) {
// TODO: wait for more contexts
this.consumeContext('umbExtensionRegistry', (extensionsRegistry: UmbExtensionRegistry) => {
this._extensionRegistry = extensionsRegistry;
this._useTrees();
this._observeTrees();
});
this.consumeContext('umbSectionContext', (sectionContext: UmbSectionContext) => {
this._sectionContext = sectionContext;
this._useTrees();
this._observeTrees();
});
this.consumeContext('umbEntityStore', (entityStore: UmbEntityStore) => {
this._entityStore = entityStore;
this._useTrees();
this._observeTrees();
});
}
private _useTrees() {
private _observeTrees() {
if (!this._sectionContext || !this._extensionRegistry || !this._entityStore) return;
this._treesSubscription?.unsubscribe();
this._treesSubscription = this._sectionContext?.data
.pipe(
this.observe<ManifestTree[]>(
this._sectionContext?.data.pipe(
switchMap((section) => {
if (!section) return EMPTY;
@@ -81,11 +76,12 @@ export class UmbSectionElement extends UmbContextConsumerMixin(LitElement) {
) ?? of([])
);
})
)
.subscribe((trees) => {
),
(trees) => {
this._trees = trees;
this._createRoutes();
});
}
);
}
private _createRoutes() {
@@ -114,12 +110,6 @@ export class UmbSectionElement extends UmbContextConsumerMixin(LitElement) {
];
}
disconnectedCallback(): void {
super.disconnectedCallback();
this._treesSubscription?.unsubscribe();
this._editorsSubscription?.unsubscribe();
}
render() {
return html`
<umb-section-layout>

View File

@@ -1,8 +1,8 @@
import { LitElement } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import { Subscription } from 'rxjs';
import { UmbContextConsumerMixin } from '../../../core/context';
import type { ManifestTreeItemAction, ManifestTree } from '../../../core/models';
import { UmbObserverMixin } from '../../../core/observer';
import { Entity } from '../../../mocks/data/entities';
import { UmbSectionContext } from '../../sections/section.context';
import { UmbTreeContextMenuPageService } from './context-menu/tree-context-menu-page.service';
@@ -14,7 +14,7 @@ export type ActionPageEntity = {
};
@customElement('umb-tree-item-action')
export default class UmbTreeItemActionElement extends UmbContextConsumerMixin(LitElement) {
export default class UmbTreeItemActionElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) {
@property({ attribute: false })
public treeAction?: ManifestTreeItemAction;
@@ -28,10 +28,6 @@ export default class UmbTreeItemActionElement extends UmbContextConsumerMixin(Li
protected _treeContextMenuService?: UmbTreeContextMenuService;
protected _actionPageService?: UmbTreeContextMenuPageService;
protected _actionPageSubscription?: Subscription;
protected _activeTreeSubscription?: Subscription;
protected _activeTreeItemSubscription?: Subscription;
connectedCallback() {
super.connectedCallback();
@@ -47,36 +43,33 @@ export default class UmbTreeItemActionElement extends UmbContextConsumerMixin(Li
this.consumeContext('umbTreeContextMenuPageService', (actionPageService: UmbTreeContextMenuPageService) => {
this._actionPageService = actionPageService;
this._observeEntity();
});
}
this._actionPageSubscription?.unsubscribe();
this._actionPageService?.entity.subscribe((entity: ActionPageEntity) => {
this._entity = entity;
});
private _observeEntity() {
if (!this._actionPageService) return;
this.observe<ActionPageEntity>(this._actionPageService.entity, (entity) => {
this._entity = entity;
});
}
private _observeActiveTree() {
this._activeTreeSubscription?.unsubscribe();
if (!this._sectionContext) return;
this._activeTreeSubscription = this._sectionContext?.activeTree.subscribe((tree) => {
this.observe<ManifestTree>(this._sectionContext.activeTree, (tree) => {
this._activeTree = tree;
});
}
private _observeActiveTreeItem() {
this._activeTreeItemSubscription?.unsubscribe();
if (!this._sectionContext) return;
this._activeTreeItemSubscription = this._sectionContext?.activeTreeItem.subscribe((treeItem) => {
this.observe<Entity>(this._sectionContext.activeTreeItem, (treeItem) => {
this._activeTreeItem = treeItem;
});
}
disconnectCallback() {
super.disconnectedCallback();
this._actionPageSubscription?.unsubscribe();
this._activeTreeSubscription?.unsubscribe();
this._activeTreeItemSubscription?.unsubscribe();
}
}
declare global {