From 3ae20647aa6fd46b9beaec4c9d19f1157ec831bf Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 23 Dec 2021 19:01:43 +0200 Subject: [PATCH] Implement sync with parent state params for dashboard state component --- ui-ngx/src/app/core/api/widget-api.models.ts | 1 + .../dashboard-state.component.ts | 33 +++++++++++++++---- .../default-state-controller.component.ts | 2 +- .../entity-state-controller.component.ts | 2 +- .../states/state-controller.component.ts | 13 ++++++-- .../states/state-controller.models.ts | 1 + .../states/states-component.directive.ts | 6 +++- 7 files changed, 47 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/core/api/widget-api.models.ts b/ui-ngx/src/app/core/api/widget-api.models.ts index d053efb601..8d7ea6dbe7 100644 --- a/ui-ngx/src/app/core/api/widget-api.models.ts +++ b/ui-ngx/src/app/core/api/widget-api.models.ts @@ -150,6 +150,7 @@ export type StateControllerHolder = () => IStateController; export interface IStateController { dashboardCtrl: IDashboardController; getStateParams(): StateParams; + stateChanged(): Observable; getStateParamsByStateId(stateId: string): StateParams; openState(id: string, params?: StateParams, openRightLayout?: boolean): void; updateState(id?: string, params?: StateParams, openRightLayout?: boolean): void; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts index 00bd266c2a..5c02f26227 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-state.component.ts @@ -14,23 +14,24 @@ /// limitations under the License. /// -import { Component, Input, OnInit } from '@angular/core'; +import { Component, Input, OnDestroy, OnInit } from '@angular/core'; import { PageComponent } from '@shared/components/page.component'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { Dashboard } from '@shared/models/dashboard.models'; -import { StateObject, StateParams } from '@core/api/widget-api.models'; -import { updateEntityParams, WidgetContext } from '../../models/widget-component.models'; +import { StateObject } from '@core/api/widget-api.models'; +import { updateEntityParams, WidgetContext } from '@home/models/widget-component.models'; import { deepClone, objToBase64 } from '@core/utils'; import { IDashboardComponent } from '@home/models/dashboard-component.models'; import { EntityId } from '@shared/models/id/entity-id'; +import { Subscription } from 'rxjs'; @Component({ selector: 'tb-dashboard-state', templateUrl: './dashboard-state.component.html', styleUrls: [] }) -export class DashboardStateComponent extends PageComponent implements OnInit { +export class DashboardStateComponent extends PageComponent implements OnInit, OnDestroy { @Input() ctx: WidgetContext; @@ -38,6 +39,9 @@ export class DashboardStateComponent extends PageComponent implements OnInit { @Input() stateId: string; + @Input() + syncParentStateParams = false; + @Input() entityParamName: string; @@ -50,12 +54,31 @@ export class DashboardStateComponent extends PageComponent implements OnInit { parentDashboard: IDashboardComponent; + private stateSubscription: Subscription; + constructor(protected store: Store) { super(store); } ngOnInit(): void { this.dashboard = deepClone(this.ctx.stateController.dashboardCtrl.dashboardCtx.getDashboard()); + this.updateCurrentState(); + this.parentDashboard = this.ctx.parentDashboard ? + this.ctx.parentDashboard : this.ctx.dashboard; + if (this.syncParentStateParams) { + this.stateSubscription = this.ctx.stateController.stateChanged().subscribe(() => { + this.updateCurrentState(); + }); + } + } + + ngOnDestroy(): void { + if (this.stateSubscription) { + this.stateSubscription.unsubscribe(); + } + } + + private updateCurrentState(): void { const stateObject: StateObject = {}; const params = deepClone(this.ctx.stateController.getStateParams()); updateEntityParams(params, this.entityParamName, this.entityId); @@ -64,7 +87,5 @@ export class DashboardStateComponent extends PageComponent implements OnInit { stateObject.id = this.stateId; } this.currentState = objToBase64([stateObject]); - this.parentDashboard = this.ctx.parentDashboard ? - this.ctx.parentDashboard : this.ctx.dashboard; } } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts index 674386f108..67e24b628c 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/default-state-controller.component.ts @@ -54,7 +54,7 @@ export class DefaultStateControllerComponent extends StateControllerComponent im super.ngOnDestroy(); } - protected init() { + public init() { if (this.preservedState) { this.stateObject = this.preservedState; setTimeout(() => { diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts index f12dd033aa..c559459819 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/entity-state-controller.component.ts @@ -58,7 +58,7 @@ export class EntityStateControllerComponent extends StateControllerComponent imp super.ngOnDestroy(); } - protected init() { + public init() { if (this.preservedState) { this.stateObject = this.preservedState; this.selectedStateIndex = this.stateObject.length - 1; diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts index 5acf57095f..fed15b9088 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.component.ts @@ -17,7 +17,7 @@ import { IStateControllerComponent, StateControllerState } from '@home/components/dashboard-page/states/state-controller.models'; import { IDashboardController } from '../dashboard-page.models'; import { DashboardState } from '@app/shared/models/dashboard.models'; -import { Subscription } from 'rxjs'; +import { Observable, Subject, Subscription } from 'rxjs'; import { NgZone, OnDestroy, OnInit, Directive } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { StatesControllerService } from '@home/components/dashboard-page/states/states-controller.service'; @@ -27,6 +27,7 @@ import { StateObject, StateParams } from '@app/core/api/widget-api.models'; @Directive() export abstract class StateControllerComponent implements IStateControllerComponent, OnInit, OnDestroy { + private stateChangedSubject = new Subject(); stateObject: StateControllerState = []; dashboardCtrl: IDashboardController; preservedState: any; @@ -108,6 +109,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon const newState = this.decodeStateParam(paramMap.get('state')); if (this.currentState !== newState) { this.currentState = newState; + this.stateChangedSubject.next(); if (this.inited) { this.onStateChanged(); } @@ -124,6 +126,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon subscription.unsubscribe(); }); this.rxSubscriptions.length = 0; + this.stateChangedSubject.complete(); } protected updateStateParam(newState: string, replaceCurrentHistoryUrl = false) { @@ -142,6 +145,11 @@ export abstract class StateControllerComponent implements IStateControllerCompon }); }); } + this.stateChangedSubject.next(); + } + + public stateChanged(): Observable { + return this.stateChangedSubject.asObservable(); } public openRightLayout(): void { @@ -159,6 +167,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon public reInit() { this.preservedState = null; this.currentState = this.decodeStateParam(this.route.snapshot.queryParamMap.get('state')); + this.stateChangedSubject.next(); this.init(); } @@ -166,7 +175,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon return stateURI !== null ? decodeURIComponent(stateURI) : null; } - protected abstract init(); + public abstract init(); protected abstract onMobileChanged(); diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.models.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.models.ts index 6a21ac564f..333a66b3d1 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.models.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/state-controller.models.ts @@ -30,4 +30,5 @@ export interface IStateControllerComponent extends IStateController { dashboardId: string; preservedState: any; reInit(): void; + init(): void; } diff --git a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts index b6911ed9d8..e9d65a6323 100644 --- a/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts +++ b/ui-ngx/src/app/modules/home/components/dashboard-page/states/states-component.directive.ts @@ -76,6 +76,7 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges { ngOnChanges(changes: SimpleChanges): void { let reInitController = false; + let initController = false; for (const propName of Object.keys(changes)) { const change = changes[propName]; if (!change.firstChange && change.currentValue !== change.previousValue) { @@ -92,12 +93,15 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges { this.stateControllerComponent.state = this.state; } else if (propName === 'currentState') { this.stateControllerComponent.currentState = this.currentState; + initController = true; } else if (propName === 'syncStateWithQueryParam') { this.stateControllerComponent.syncStateWithQueryParam = this.syncStateWithQueryParam; } } } - if (reInitController) { + if (initController) { + this.stateControllerComponent.init(); + } else if (reInitController) { this.stateControllerComponent.reInit(); } }