Browse Source

Merge pull request #9735 from ArtemDzhereleiko/AD/imp/copy-states

Copy dashboard state
pull/9782/head
Igor Kulikov 3 years ago
committed by GitHub
parent
commit
399cbc89c7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts
  2. 11
      ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.html
  3. 83
      ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts
  4. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

18
ui-ngx/src/app/modules/home/components/dashboard-page/dashboard-page.component.ts

@ -55,7 +55,7 @@ import {
} from '@app/shared/models/dashboard.models';
import { WINDOW } from '@core/services/window.service';
import { WindowMessage } from '@shared/models/window-message.model';
import { deepClone, guid, isDefined, isDefinedAndNotNull, isNotEmptyStr } from '@app/core/utils';
import { deepClone, guid, isDefined, isDefinedAndNotNull, isEqual, isNotEmptyStr } from '@app/core/utils';
import {
DashboardContext,
DashboardPageInitData,
@ -868,15 +868,21 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
$event.stopPropagation();
}
this.dialog.open<ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogData,
{[id: string]: DashboardState }>(ManageDashboardStatesDialogComponent, {
{states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>(ManageDashboardStatesDialogComponent, {
disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: {
states: deepClone(this.dashboard.configuration.states)
states: deepClone(this.dashboard.configuration.states),
widgets: deepClone(this.dashboard.configuration.widgets) as {[id: string]: Widget}
}
}).afterClosed().subscribe((states) => {
if (states) {
this.updateStates(states);
}).afterClosed().subscribe((result) => {
if (result) {
if (!isEqual(result.widgets, this.dashboard.configuration.widgets)) {
this.dashboard.configuration.widgets = result.widgets;
}
if (result.states) {
this.updateStates(result.states);
}
}
});
}

11
ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.html

@ -15,7 +15,7 @@
limitations under the License.
-->
<form [formGroup]="statesFormGroup" (ngSubmit)="save()" style="min-width: 480px;">
<form [formGroup]="statesFormGroup" (ngSubmit)="save()" style="width: 750px;">
<mat-toolbar color="primary">
<h2 translate>dashboard.manage-states</h2>
<span fxFlex></span>
@ -96,7 +96,7 @@
</mat-cell>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<mat-header-cell *matHeaderCellDef style="min-width: 80px; max-width: 80px; width: 80px">
<mat-header-cell *matHeaderCellDef style="min-width: 120px; max-width: 120px; width: 120px">
</mat-header-cell>
<mat-cell *matCellDef="let state">
<div fxFlex fxLayout="row">
@ -107,6 +107,13 @@
(click)="editState($event, state)">
<mat-icon>edit</mat-icon>
</button>
<button mat-icon-button [disabled]="isLoading$ | async"
type="button"
matTooltip="{{ 'dashboard.duplicate-state-action' | translate }}"
matTooltipPosition="above"
(click)="duplicateState($event, state)">
<mat-icon>content_copy</mat-icon>
</button>
<button [fxShow]="!state.root" mat-icon-button [disabled]="isLoading$ | async"
type="button"
matTooltip="{{ 'dashboard.delete-state' | translate }}"

83
ui-ngx/src/app/modules/home/components/dashboard-page/states/manage-dashboard-states-dialog.component.ts

@ -19,7 +19,7 @@ import { ErrorStateMatcher } from '@angular/material/core';
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, FormGroupDirective, NgForm } from '@angular/forms';
import { FormGroupDirective, NgForm, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { DialogComponent } from '@app/shared/components/dialog.component';
import { DashboardState } from '@app/shared/models/dashboard.models';
@ -35,14 +35,17 @@ import { fromEvent, merge } from 'rxjs';
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
import { DialogService } from '@core/services/dialog.service';
import { deepClone, isUndefined } from '@core/utils';
import { deepClone, isDefined } from '@core/utils';
import {
DashboardStateDialogComponent,
DashboardStateDialogData
} from '@home/components/dashboard-page/states/dashboard-state-dialog.component';
import { UtilsService } from '@core/services/utils.service';
import { Widget } from '@shared/models/widget.models';
export interface ManageDashboardStatesDialogData {
states: {[id: string]: DashboardState };
widgets: {[id: string]: Widget };
}
@Component({
@ -51,13 +54,14 @@ export interface ManageDashboardStatesDialogData {
providers: [{provide: ErrorStateMatcher, useExisting: ManageDashboardStatesDialogComponent}],
styleUrls: ['./manage-dashboard-states-dialog.component.scss']
})
export class ManageDashboardStatesDialogComponent extends
DialogComponent<ManageDashboardStatesDialogComponent, {[id: string]: DashboardState }>
export class ManageDashboardStatesDialogComponent
extends DialogComponent<ManageDashboardStatesDialogComponent, {states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>
implements OnInit, ErrorStateMatcher, AfterViewInit {
statesFormGroup: UntypedFormGroup;
states: {[id: string]: DashboardState };
widgets: {[id: string]: Widget};
displayedColumns: string[];
pageLink: PageLink;
@ -66,6 +70,8 @@ export class ManageDashboardStatesDialogComponent extends
submitted = false;
stateNames: Set<string> = new Set<string>();
@ViewChild('searchInput') searchInputField: ElementRef;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ -75,15 +81,19 @@ export class ManageDashboardStatesDialogComponent extends
protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: ManageDashboardStatesDialogData,
@SkipSelf() private errorStateMatcher: ErrorStateMatcher,
public dialogRef: MatDialogRef<ManageDashboardStatesDialogComponent, {[id: string]: DashboardState }>,
public dialogRef: MatDialogRef<ManageDashboardStatesDialogComponent,
{states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>,
private fb: UntypedFormBuilder,
private translate: TranslateService,
private dialogs: DialogService,
private utils: UtilsService,
private dialog: MatDialog) {
super(store, router, dialogRef);
this.states = this.data.states;
this.widgets = this.data.widgets;
this.statesFormGroup = this.fb.group({});
Object.values(this.states).forEach(value => this.stateNames.add(value.name));
const sortOrder: SortOrder = { property: 'name', direction: Direction.ASC };
this.pageLink = new PageLink(5, 0, null, sortOrder);
@ -142,6 +152,7 @@ export class ManageDashboardStatesDialogComponent extends
this.translate.instant('action.yes')).subscribe(
(res) => {
if (res) {
this.stateNames.delete(state.name);
delete this.states[state.id];
this.onStatesUpdated();
}
@ -171,8 +182,10 @@ export class ManageDashboardStatesDialogComponent extends
}
const isAdd = state === null;
let prevStateId = null;
let prevStateName = '';
if (!isAdd) {
prevStateId = state.id;
prevStateName = state.name;
}
this.dialog.open<DashboardStateDialogComponent, DashboardStateDialogData,
DashboardStateInfo>(DashboardStateDialogComponent, {
@ -186,13 +199,13 @@ export class ManageDashboardStatesDialogComponent extends
}).afterClosed().subscribe(
(res) => {
if (res) {
this.saveState(res, prevStateId);
this.saveState(res, prevStateId, prevStateName);
}
}
);
}
saveState(state: DashboardStateInfo, prevStateId: string) {
saveState(state: DashboardStateInfo, prevStateId: string, prevStateName: string) {
const newState: DashboardState = {
name: state.name,
root: state.root,
@ -204,6 +217,10 @@ export class ManageDashboardStatesDialogComponent extends
} else {
this.states[state.id] = newState;
}
if (prevStateName && prevStateName !== state.name) {
this.stateNames.delete(prevStateName);
this.stateNames.add(state.name);
}
if (state.root) {
for (const id of Object.keys(this.states)) {
const otherState = this.states[id];
@ -228,6 +245,56 @@ export class ManageDashboardStatesDialogComponent extends
this.onStatesUpdated();
}
duplicateState($event: Event, state: DashboardStateInfo) {
const originalState = state;
const newStateName = this.getNextDuplicatedName(state.name);
if (newStateName) {
const duplicatedStates = deepClone(originalState);
const duplicatedWidgets = deepClone(this.widgets);
const mainWidgets = {};
const rightWidgets = {};
duplicatedStates.id = newStateName.toLowerCase().replace(/\W/g, '_');
duplicatedStates.name = newStateName;
duplicatedStates.root = false;
this.stateNames.add(duplicatedStates.name);
for (const [key, value] of Object.entries(duplicatedStates.layouts.main.widgets)) {
const guid = this.utils.guid();
mainWidgets[guid] = value;
duplicatedWidgets[guid] = this.widgets[key];
duplicatedWidgets[guid].id = guid;
}
duplicatedStates.layouts.main.widgets = mainWidgets;
if (isDefined(duplicatedStates.layouts?.right)) {
for (const [key, value] of Object.entries(duplicatedStates.layouts.right.widgets)) {
const guid = this.utils.guid();
rightWidgets[guid] = value;
duplicatedWidgets[guid] = this.widgets[key];
duplicatedWidgets[guid].id = guid;
}
duplicatedStates.layouts.right.widgets = rightWidgets;
}
this.states[duplicatedStates.id] = duplicatedStates;
this.widgets = duplicatedWidgets;
this.onStatesUpdated();
}
}
private getNextDuplicatedName(stateName: string): string {
const suffix = ` - ${this.translate.instant('action.copy')} `;
let counter = 0;
while (++counter < Number.MAX_SAFE_INTEGER) {
const newName = `${stateName}${suffix}${counter}`;
if (!this.stateNames.has(newName)) {
return newName;
}
}
return null;
}
private onStatesUpdated() {
this.statesFormGroup.markAsDirty();
this.updateData(true);
@ -245,6 +312,6 @@ export class ManageDashboardStatesDialogComponent extends
save(): void {
this.submitted = true;
this.dialogRef.close(this.states);
this.dialogRef.close({ states: this.states, widgets: this.widgets });
}
}

3
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -1191,7 +1191,8 @@
"assign-dashboard-to-edge": "Assign Dashboard(s) To Edge",
"assign-dashboard-to-edge-text": "Please select the dashboards to assign to the edge",
"non-existent-dashboard-state-error": "Dashboard state with id \"{{ stateId }}\" is not found",
"edit-mode": "Edit mode"
"edit-mode": "Edit mode",
"duplicate-state-action": "Duplicate state"
},
"datakey": {
"settings": "Settings",

Loading…
Cancel
Save