Implement sync with parent state params for dashboard state component

This commit is contained in:
Igor Kulikov 2021-12-23 19:01:43 +02:00
parent ce3d929fec
commit 3ae20647aa
7 changed files with 47 additions and 11 deletions

View File

@ -150,6 +150,7 @@ export type StateControllerHolder = () => IStateController;
export interface IStateController { export interface IStateController {
dashboardCtrl: IDashboardController; dashboardCtrl: IDashboardController;
getStateParams(): StateParams; getStateParams(): StateParams;
stateChanged(): Observable<any>;
getStateParamsByStateId(stateId: string): StateParams; getStateParamsByStateId(stateId: string): StateParams;
openState(id: string, params?: StateParams, openRightLayout?: boolean): void; openState(id: string, params?: StateParams, openRightLayout?: boolean): void;
updateState(id?: string, params?: StateParams, openRightLayout?: boolean): void; updateState(id?: string, params?: StateParams, openRightLayout?: boolean): void;

View File

@ -14,23 +14,24 @@
/// limitations under the License. /// 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 { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { Dashboard } from '@shared/models/dashboard.models'; import { Dashboard } from '@shared/models/dashboard.models';
import { StateObject, StateParams } from '@core/api/widget-api.models'; import { StateObject } from '@core/api/widget-api.models';
import { updateEntityParams, WidgetContext } from '../../models/widget-component.models'; import { updateEntityParams, WidgetContext } from '@home/models/widget-component.models';
import { deepClone, objToBase64 } from '@core/utils'; import { deepClone, objToBase64 } from '@core/utils';
import { IDashboardComponent } from '@home/models/dashboard-component.models'; import { IDashboardComponent } from '@home/models/dashboard-component.models';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { Subscription } from 'rxjs';
@Component({ @Component({
selector: 'tb-dashboard-state', selector: 'tb-dashboard-state',
templateUrl: './dashboard-state.component.html', templateUrl: './dashboard-state.component.html',
styleUrls: [] styleUrls: []
}) })
export class DashboardStateComponent extends PageComponent implements OnInit { export class DashboardStateComponent extends PageComponent implements OnInit, OnDestroy {
@Input() @Input()
ctx: WidgetContext; ctx: WidgetContext;
@ -38,6 +39,9 @@ export class DashboardStateComponent extends PageComponent implements OnInit {
@Input() @Input()
stateId: string; stateId: string;
@Input()
syncParentStateParams = false;
@Input() @Input()
entityParamName: string; entityParamName: string;
@ -50,12 +54,31 @@ export class DashboardStateComponent extends PageComponent implements OnInit {
parentDashboard: IDashboardComponent; parentDashboard: IDashboardComponent;
private stateSubscription: Subscription;
constructor(protected store: Store<AppState>) { constructor(protected store: Store<AppState>) {
super(store); super(store);
} }
ngOnInit(): void { ngOnInit(): void {
this.dashboard = deepClone(this.ctx.stateController.dashboardCtrl.dashboardCtx.getDashboard()); 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 stateObject: StateObject = {};
const params = deepClone(this.ctx.stateController.getStateParams()); const params = deepClone(this.ctx.stateController.getStateParams());
updateEntityParams(params, this.entityParamName, this.entityId); updateEntityParams(params, this.entityParamName, this.entityId);
@ -64,7 +87,5 @@ export class DashboardStateComponent extends PageComponent implements OnInit {
stateObject.id = this.stateId; stateObject.id = this.stateId;
} }
this.currentState = objToBase64([stateObject]); this.currentState = objToBase64([stateObject]);
this.parentDashboard = this.ctx.parentDashboard ?
this.ctx.parentDashboard : this.ctx.dashboard;
} }
} }

View File

@ -54,7 +54,7 @@ export class DefaultStateControllerComponent extends StateControllerComponent im
super.ngOnDestroy(); super.ngOnDestroy();
} }
protected init() { public init() {
if (this.preservedState) { if (this.preservedState) {
this.stateObject = this.preservedState; this.stateObject = this.preservedState;
setTimeout(() => { setTimeout(() => {

View File

@ -58,7 +58,7 @@ export class EntityStateControllerComponent extends StateControllerComponent imp
super.ngOnDestroy(); super.ngOnDestroy();
} }
protected init() { public init() {
if (this.preservedState) { if (this.preservedState) {
this.stateObject = this.preservedState; this.stateObject = this.preservedState;
this.selectedStateIndex = this.stateObject.length - 1; this.selectedStateIndex = this.stateObject.length - 1;

View File

@ -17,7 +17,7 @@
import { IStateControllerComponent, StateControllerState } from '@home/components/dashboard-page/states/state-controller.models'; import { IStateControllerComponent, StateControllerState } from '@home/components/dashboard-page/states/state-controller.models';
import { IDashboardController } from '../dashboard-page.models'; import { IDashboardController } from '../dashboard-page.models';
import { DashboardState } from '@app/shared/models/dashboard.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 { NgZone, OnDestroy, OnInit, Directive } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router'; import { ActivatedRoute, Params, Router } from '@angular/router';
import { StatesControllerService } from '@home/components/dashboard-page/states/states-controller.service'; 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() @Directive()
export abstract class StateControllerComponent implements IStateControllerComponent, OnInit, OnDestroy { export abstract class StateControllerComponent implements IStateControllerComponent, OnInit, OnDestroy {
private stateChangedSubject = new Subject();
stateObject: StateControllerState = []; stateObject: StateControllerState = [];
dashboardCtrl: IDashboardController; dashboardCtrl: IDashboardController;
preservedState: any; preservedState: any;
@ -108,6 +109,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon
const newState = this.decodeStateParam(paramMap.get('state')); const newState = this.decodeStateParam(paramMap.get('state'));
if (this.currentState !== newState) { if (this.currentState !== newState) {
this.currentState = newState; this.currentState = newState;
this.stateChangedSubject.next();
if (this.inited) { if (this.inited) {
this.onStateChanged(); this.onStateChanged();
} }
@ -124,6 +126,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon
subscription.unsubscribe(); subscription.unsubscribe();
}); });
this.rxSubscriptions.length = 0; this.rxSubscriptions.length = 0;
this.stateChangedSubject.complete();
} }
protected updateStateParam(newState: string, replaceCurrentHistoryUrl = false) { protected updateStateParam(newState: string, replaceCurrentHistoryUrl = false) {
@ -142,6 +145,11 @@ export abstract class StateControllerComponent implements IStateControllerCompon
}); });
}); });
} }
this.stateChangedSubject.next();
}
public stateChanged(): Observable<any> {
return this.stateChangedSubject.asObservable();
} }
public openRightLayout(): void { public openRightLayout(): void {
@ -159,6 +167,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon
public reInit() { public reInit() {
this.preservedState = null; this.preservedState = null;
this.currentState = this.decodeStateParam(this.route.snapshot.queryParamMap.get('state')); this.currentState = this.decodeStateParam(this.route.snapshot.queryParamMap.get('state'));
this.stateChangedSubject.next();
this.init(); this.init();
} }
@ -166,7 +175,7 @@ export abstract class StateControllerComponent implements IStateControllerCompon
return stateURI !== null ? decodeURIComponent(stateURI) : null; return stateURI !== null ? decodeURIComponent(stateURI) : null;
} }
protected abstract init(); public abstract init();
protected abstract onMobileChanged(); protected abstract onMobileChanged();

View File

@ -30,4 +30,5 @@ export interface IStateControllerComponent extends IStateController {
dashboardId: string; dashboardId: string;
preservedState: any; preservedState: any;
reInit(): void; reInit(): void;
init(): void;
} }

View File

@ -76,6 +76,7 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges {
ngOnChanges(changes: SimpleChanges): void { ngOnChanges(changes: SimpleChanges): void {
let reInitController = false; let reInitController = false;
let initController = false;
for (const propName of Object.keys(changes)) { for (const propName of Object.keys(changes)) {
const change = changes[propName]; const change = changes[propName];
if (!change.firstChange && change.currentValue !== change.previousValue) { if (!change.firstChange && change.currentValue !== change.previousValue) {
@ -92,12 +93,15 @@ export class StatesComponentDirective implements OnInit, OnDestroy, OnChanges {
this.stateControllerComponent.state = this.state; this.stateControllerComponent.state = this.state;
} else if (propName === 'currentState') { } else if (propName === 'currentState') {
this.stateControllerComponent.currentState = this.currentState; this.stateControllerComponent.currentState = this.currentState;
initController = true;
} else if (propName === 'syncStateWithQueryParam') { } else if (propName === 'syncStateWithQueryParam') {
this.stateControllerComponent.syncStateWithQueryParam = this.syncStateWithQueryParam; this.stateControllerComponent.syncStateWithQueryParam = this.syncStateWithQueryParam;
} }
} }
} }
if (reInitController) { if (initController) {
this.stateControllerComponent.init();
} else if (reInitController) {
this.stateControllerComponent.reInit(); this.stateControllerComponent.reInit();
} }
} }