UI: Refactoring dashboard managment
This commit is contained in:
		
							parent
							
								
									99b4c0fbda
								
							
						
					
					
						commit
						50e0272d34
					
				@ -58,7 +58,7 @@ import {
 | 
				
			|||||||
} from '@app/shared/models/dashboard.models';
 | 
					} from '@app/shared/models/dashboard.models';
 | 
				
			||||||
import { WINDOW } from '@core/services/window.service';
 | 
					import { WINDOW } from '@core/services/window.service';
 | 
				
			||||||
import { WindowMessage } from '@shared/models/window-message.model';
 | 
					import { WindowMessage } from '@shared/models/window-message.model';
 | 
				
			||||||
import { deepClone, guid, isDefined, isDefinedAndNotNull, isEqual, isNotEmptyStr } from '@app/core/utils';
 | 
					import { deepClone, guid, isDefined, isDefinedAndNotNull, isNotEmptyStr } from '@app/core/utils';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  DashboardContext,
 | 
					  DashboardContext,
 | 
				
			||||||
  DashboardPageInitData,
 | 
					  DashboardPageInitData,
 | 
				
			||||||
@ -119,7 +119,8 @@ import {
 | 
				
			|||||||
} from '@home/components/dashboard-page/dashboard-settings-dialog.component';
 | 
					} from '@home/components/dashboard-page/dashboard-settings-dialog.component';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  ManageDashboardStatesDialogComponent,
 | 
					  ManageDashboardStatesDialogComponent,
 | 
				
			||||||
  ManageDashboardStatesDialogData
 | 
					  ManageDashboardStatesDialogData,
 | 
				
			||||||
 | 
					  ManageDashboardStatesDialogResult
 | 
				
			||||||
} from '@home/components/dashboard-page/states/manage-dashboard-states-dialog.component';
 | 
					} from '@home/components/dashboard-page/states/manage-dashboard-states-dialog.component';
 | 
				
			||||||
import { ImportExportService } from '@shared/import-export/import-export.service';
 | 
					import { ImportExportService } from '@shared/import-export/import-export.service';
 | 
				
			||||||
import { AuthState } from '@app/core/auth/auth.models';
 | 
					import { AuthState } from '@app/core/auth/auth.models';
 | 
				
			||||||
@ -964,17 +965,17 @@ export class DashboardPageComponent extends PageComponent implements IDashboardC
 | 
				
			|||||||
      $event.stopPropagation();
 | 
					      $event.stopPropagation();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this.dialog.open<ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogData,
 | 
					    this.dialog.open<ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogData,
 | 
				
			||||||
      {states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>(ManageDashboardStatesDialogComponent, {
 | 
					      ManageDashboardStatesDialogResult>(ManageDashboardStatesDialogComponent, {
 | 
				
			||||||
      disableClose: true,
 | 
					      disableClose: true,
 | 
				
			||||||
      panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
 | 
					      panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
 | 
				
			||||||
      data: {
 | 
					      data: {
 | 
				
			||||||
        states: deepClone(this.dashboard.configuration.states),
 | 
					        states: deepClone(this.dashboard.configuration.states),
 | 
				
			||||||
        widgets: deepClone(this.dashboard.configuration.widgets) as {[id: string]: Widget}
 | 
					        widgets: this.dashboard.configuration.widgets as {[id: string]: Widget}
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }).afterClosed().subscribe((result) => {
 | 
					    }).afterClosed().subscribe((result) => {
 | 
				
			||||||
      if (result) {
 | 
					      if (result) {
 | 
				
			||||||
        if (!isEqual(result.widgets, this.dashboard.configuration.widgets)) {
 | 
					        if (result.addWidgets) {
 | 
				
			||||||
          this.dashboard.configuration.widgets = result.widgets;
 | 
					          Object.assign(this.dashboard.configuration.widgets, result.addWidgets);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (result.states) {
 | 
					        if (result.states) {
 | 
				
			||||||
          this.updateStates(result.states);
 | 
					          this.updateStates(result.states);
 | 
				
			||||||
 | 
				
			|||||||
@ -15,143 +15,134 @@
 | 
				
			|||||||
    limitations under the License.
 | 
					    limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
<form [formGroup]="statesFormGroup" (ngSubmit)="save()" style="width: 750px;">
 | 
					<mat-toolbar color="primary">
 | 
				
			||||||
  <mat-toolbar color="primary">
 | 
					  <h2 translate>dashboard.manage-states</h2>
 | 
				
			||||||
    <h2 translate>dashboard.manage-states</h2>
 | 
					  <span class="flex-1"></span>
 | 
				
			||||||
    <span class="flex-1"></span>
 | 
					  <button mat-icon-button
 | 
				
			||||||
    <button mat-icon-button
 | 
					          (click)="cancel()"
 | 
				
			||||||
            (click)="cancel()"
 | 
					          type="button">
 | 
				
			||||||
            type="button">
 | 
					    <mat-icon class="material-icons">close</mat-icon>
 | 
				
			||||||
      <mat-icon class="material-icons">close</mat-icon>
 | 
					  </button>
 | 
				
			||||||
    </button>
 | 
					</mat-toolbar>
 | 
				
			||||||
  </mat-toolbar>
 | 
					<div mat-dialog-content class="manage-dashboard-states">
 | 
				
			||||||
  <mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
 | 
					  <div class="tb-entity-table-content flex flex-col">
 | 
				
			||||||
  </mat-progress-bar>
 | 
					    <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="textSearchMode">
 | 
				
			||||||
  <div mat-dialog-content>
 | 
					      <div class="mat-toolbar-tools">
 | 
				
			||||||
    <fieldset [disabled]="isLoading$ | async">
 | 
					        <span class="tb-entity-table-title" translate>dashboard.states</span>
 | 
				
			||||||
      <div class="manage-dashboard-states">
 | 
					        <span class="flex-1"></span>
 | 
				
			||||||
        <div class="tb-entity-table">
 | 
					        <button mat-icon-button [disabled]="isLoading$ | async"
 | 
				
			||||||
          <div class="tb-entity-table-content flex flex-col">
 | 
					                type="button"
 | 
				
			||||||
            <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="textSearchMode">
 | 
					                (click)="addState($event)"
 | 
				
			||||||
              <div class="mat-toolbar-tools">
 | 
					                matTooltip="{{ 'dashboard.add-state' | translate }}"
 | 
				
			||||||
                <span class="tb-entity-table-title" translate>dashboard.states</span>
 | 
					                matTooltipPosition="above">
 | 
				
			||||||
                <span class="flex-1"></span>
 | 
					          <mat-icon>add</mat-icon>
 | 
				
			||||||
                <button mat-icon-button [disabled]="isLoading$ | async"
 | 
					        </button>
 | 
				
			||||||
                        type="button"
 | 
					        <button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
 | 
				
			||||||
                        (click)="addState($event)"
 | 
					                type="button"
 | 
				
			||||||
                        matTooltip="{{ 'dashboard.add-state' | translate }}"
 | 
					                matTooltip="{{ 'action.search' | translate }}"
 | 
				
			||||||
                        matTooltipPosition="above">
 | 
					                matTooltipPosition="above">
 | 
				
			||||||
                  <mat-icon>add</mat-icon>
 | 
					          <mat-icon>search</mat-icon>
 | 
				
			||||||
                </button>
 | 
					        </button>
 | 
				
			||||||
                <button mat-icon-button [disabled]="isLoading$ | async" (click)="enterFilterMode()"
 | 
					 | 
				
			||||||
                        type="button"
 | 
					 | 
				
			||||||
                        matTooltip="{{ 'action.search' | translate }}"
 | 
					 | 
				
			||||||
                        matTooltipPosition="above">
 | 
					 | 
				
			||||||
                  <mat-icon>search</mat-icon>
 | 
					 | 
				
			||||||
                </button>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </mat-toolbar>
 | 
					 | 
				
			||||||
            <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="!textSearchMode">
 | 
					 | 
				
			||||||
              <div class="mat-toolbar-tools">
 | 
					 | 
				
			||||||
                <button mat-icon-button
 | 
					 | 
				
			||||||
                        type="button"
 | 
					 | 
				
			||||||
                        matTooltip="{{ 'dashboard.search-states' | translate }}"
 | 
					 | 
				
			||||||
                        matTooltipPosition="above">
 | 
					 | 
				
			||||||
                  <mat-icon>search</mat-icon>
 | 
					 | 
				
			||||||
                </button>
 | 
					 | 
				
			||||||
                <mat-form-field class="flex-1">
 | 
					 | 
				
			||||||
                  <mat-label> </mat-label>
 | 
					 | 
				
			||||||
                  <input #searchInput matInput
 | 
					 | 
				
			||||||
                         [(ngModel)]="pageLink.textSearch"
 | 
					 | 
				
			||||||
                         [ngModelOptions]="{standalone: true}"
 | 
					 | 
				
			||||||
                         placeholder="{{ 'dashboard.search-states' | translate }}"/>
 | 
					 | 
				
			||||||
                </mat-form-field>
 | 
					 | 
				
			||||||
                <button mat-icon-button (click)="exitFilterMode()"
 | 
					 | 
				
			||||||
                        type="button"
 | 
					 | 
				
			||||||
                        matTooltip="{{ 'action.close' | translate }}"
 | 
					 | 
				
			||||||
                        matTooltipPosition="above">
 | 
					 | 
				
			||||||
                  <mat-icon>close</mat-icon>
 | 
					 | 
				
			||||||
                </button>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </mat-toolbar>
 | 
					 | 
				
			||||||
            <div class="table-container">
 | 
					 | 
				
			||||||
              <table  mat-table [dataSource]="dataSource"
 | 
					 | 
				
			||||||
                         matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
 | 
					 | 
				
			||||||
                <ng-container matColumnDef="name">
 | 
					 | 
				
			||||||
                  <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 60%"> {{ 'dashboard.state-name' | translate }} </mat-header-cell>
 | 
					 | 
				
			||||||
                  <mat-cell *matCellDef="let state">
 | 
					 | 
				
			||||||
                    {{ state.name }}
 | 
					 | 
				
			||||||
                  </mat-cell>
 | 
					 | 
				
			||||||
                </ng-container>
 | 
					 | 
				
			||||||
                <ng-container matColumnDef="id">
 | 
					 | 
				
			||||||
                  <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 40%"> {{ 'dashboard.state-id' | translate }} </mat-header-cell>
 | 
					 | 
				
			||||||
                  <mat-cell *matCellDef="let state">
 | 
					 | 
				
			||||||
                    {{ state.id }}
 | 
					 | 
				
			||||||
                  </mat-cell>
 | 
					 | 
				
			||||||
                </ng-container>
 | 
					 | 
				
			||||||
                <ng-container matColumnDef="root">
 | 
					 | 
				
			||||||
                  <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 80px"> {{ 'dashboard.is-root-state' | translate }} </mat-header-cell>
 | 
					 | 
				
			||||||
                  <mat-cell *matCellDef="let state">
 | 
					 | 
				
			||||||
                    <mat-icon class="material-icons mat-icon">{{state.root ? 'check_box' : 'check_box_outline_blank'}}</mat-icon>
 | 
					 | 
				
			||||||
                  </mat-cell>
 | 
					 | 
				
			||||||
                </ng-container>
 | 
					 | 
				
			||||||
                <ng-container matColumnDef="actions" stickyEnd>
 | 
					 | 
				
			||||||
                  <mat-header-cell *matHeaderCellDef style="min-width: 120px; max-width: 120px; width: 120px">
 | 
					 | 
				
			||||||
                  </mat-header-cell>
 | 
					 | 
				
			||||||
                  <mat-cell *matCellDef="let state">
 | 
					 | 
				
			||||||
                    <div class="flex flex-1 flex-row">
 | 
					 | 
				
			||||||
                      <button mat-icon-button [disabled]="isLoading$ | async"
 | 
					 | 
				
			||||||
                              type="button"
 | 
					 | 
				
			||||||
                              matTooltip="{{ 'dashboard.edit-state' | translate }}"
 | 
					 | 
				
			||||||
                              matTooltipPosition="above"
 | 
					 | 
				
			||||||
                              (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 [class.!hidden]="state.root" mat-icon-button [disabled]="isLoading$ | async"
 | 
					 | 
				
			||||||
                              type="button"
 | 
					 | 
				
			||||||
                              matTooltip="{{ 'dashboard.delete-state' | translate }}"
 | 
					 | 
				
			||||||
                              matTooltipPosition="above"
 | 
					 | 
				
			||||||
                              (click)="deleteState($event, state)">
 | 
					 | 
				
			||||||
                        <mat-icon>delete</mat-icon>
 | 
					 | 
				
			||||||
                      </button>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                  </mat-cell>
 | 
					 | 
				
			||||||
                </ng-container>
 | 
					 | 
				
			||||||
                <mat-header-row class="mat-row-select" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
 | 
					 | 
				
			||||||
                <mat-row class="mat-row-select"
 | 
					 | 
				
			||||||
                         *matRowDef="let state; columns: displayedColumns;"></mat-row>
 | 
					 | 
				
			||||||
              </table>
 | 
					 | 
				
			||||||
              <span [class.!hidden]="(dataSource.isEmpty() | async) === false"
 | 
					 | 
				
			||||||
                    class="no-data-found flex items-center justify-center" translate>{{ 'dashboard.no-states-text' }}</span>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <mat-divider></mat-divider>
 | 
					 | 
				
			||||||
            <mat-paginator [length]="dataSource.total() | async"
 | 
					 | 
				
			||||||
                           [pageIndex]="pageLink.page"
 | 
					 | 
				
			||||||
                           [pageSize]="pageLink.pageSize"
 | 
					 | 
				
			||||||
                           [pageSizeOptions]="[5, 10, 15]"></mat-paginator>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </fieldset>
 | 
					    </mat-toolbar>
 | 
				
			||||||
 | 
					    <mat-toolbar class="mat-mdc-table-toolbar" [class.!hidden]="!textSearchMode">
 | 
				
			||||||
 | 
					      <div class="mat-toolbar-tools">
 | 
				
			||||||
 | 
					        <button mat-icon-button
 | 
				
			||||||
 | 
					                type="button"
 | 
				
			||||||
 | 
					                matTooltip="{{ 'dashboard.search-states' | translate }}"
 | 
				
			||||||
 | 
					                matTooltipPosition="above">
 | 
				
			||||||
 | 
					          <mat-icon>search</mat-icon>
 | 
				
			||||||
 | 
					        </button>
 | 
				
			||||||
 | 
					        <mat-form-field class="flex-1">
 | 
				
			||||||
 | 
					          <mat-label> </mat-label>
 | 
				
			||||||
 | 
					          <input #searchInput matInput
 | 
				
			||||||
 | 
					                 [(ngModel)]="pageLink.textSearch"
 | 
				
			||||||
 | 
					                 [ngModelOptions]="{standalone: true}"
 | 
				
			||||||
 | 
					                 placeholder="{{ 'dashboard.search-states' | translate }}"/>
 | 
				
			||||||
 | 
					        </mat-form-field>
 | 
				
			||||||
 | 
					        <button mat-icon-button (click)="exitFilterMode()"
 | 
				
			||||||
 | 
					                type="button"
 | 
				
			||||||
 | 
					                matTooltip="{{ 'action.close' | translate }}"
 | 
				
			||||||
 | 
					                matTooltipPosition="above">
 | 
				
			||||||
 | 
					          <mat-icon>close</mat-icon>
 | 
				
			||||||
 | 
					        </button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </mat-toolbar>
 | 
				
			||||||
 | 
					    <div class="table-container">
 | 
				
			||||||
 | 
					      <table  mat-table [dataSource]="dataSource"
 | 
				
			||||||
 | 
					                 matSort [matSortActive]="pageLink.sortOrder.property" [matSortDirection]="pageLink.sortDirection()" matSortDisableClear>
 | 
				
			||||||
 | 
					        <ng-container matColumnDef="name">
 | 
				
			||||||
 | 
					          <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 60%"> {{ 'dashboard.state-name' | translate }} </mat-header-cell>
 | 
				
			||||||
 | 
					          <mat-cell *matCellDef="let state">
 | 
				
			||||||
 | 
					            {{ state.name }}
 | 
				
			||||||
 | 
					          </mat-cell>
 | 
				
			||||||
 | 
					        </ng-container>
 | 
				
			||||||
 | 
					        <ng-container matColumnDef="id">
 | 
				
			||||||
 | 
					          <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 40%"> {{ 'dashboard.state-id' | translate }} </mat-header-cell>
 | 
				
			||||||
 | 
					          <mat-cell *matCellDef="let state">
 | 
				
			||||||
 | 
					            {{ state.id }}
 | 
				
			||||||
 | 
					          </mat-cell>
 | 
				
			||||||
 | 
					        </ng-container>
 | 
				
			||||||
 | 
					        <ng-container matColumnDef="root">
 | 
				
			||||||
 | 
					          <mat-header-cell *matHeaderCellDef mat-sort-header style="width: 80px"> {{ 'dashboard.is-root-state' | translate }} </mat-header-cell>
 | 
				
			||||||
 | 
					          <mat-cell *matCellDef="let state">
 | 
				
			||||||
 | 
					            <mat-icon class="material-icons mat-icon">{{state.root ? 'check_box' : 'check_box_outline_blank'}}</mat-icon>
 | 
				
			||||||
 | 
					          </mat-cell>
 | 
				
			||||||
 | 
					        </ng-container>
 | 
				
			||||||
 | 
					        <ng-container matColumnDef="actions" stickyEnd>
 | 
				
			||||||
 | 
					          <mat-header-cell *matHeaderCellDef style="min-width: 120px; max-width: 120px; width: 120px">
 | 
				
			||||||
 | 
					          </mat-header-cell>
 | 
				
			||||||
 | 
					          <mat-cell *matCellDef="let state">
 | 
				
			||||||
 | 
					            <div class="flex flex-1 flex-row">
 | 
				
			||||||
 | 
					              <button mat-icon-button [disabled]="isLoading$ | async"
 | 
				
			||||||
 | 
					                      type="button"
 | 
				
			||||||
 | 
					                      matTooltip="{{ 'dashboard.edit-state' | translate }}"
 | 
				
			||||||
 | 
					                      matTooltipPosition="above"
 | 
				
			||||||
 | 
					                      (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 [class.!hidden]="state.root" mat-icon-button [disabled]="isLoading$ | async"
 | 
				
			||||||
 | 
					                      type="button"
 | 
				
			||||||
 | 
					                      matTooltip="{{ 'dashboard.delete-state' | translate }}"
 | 
				
			||||||
 | 
					                      matTooltipPosition="above"
 | 
				
			||||||
 | 
					                      (click)="deleteState($event, state)">
 | 
				
			||||||
 | 
					                <mat-icon>delete</mat-icon>
 | 
				
			||||||
 | 
					              </button>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </mat-cell>
 | 
				
			||||||
 | 
					        </ng-container>
 | 
				
			||||||
 | 
					        <mat-header-row class="mat-row-select" *matHeaderRowDef="displayedColumns; sticky: true"></mat-header-row>
 | 
				
			||||||
 | 
					        <mat-row class="mat-row-select"
 | 
				
			||||||
 | 
					                 *matRowDef="let state; columns: displayedColumns;"></mat-row>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					      <span [class.!hidden]="(dataSource.isEmpty() | async) === false"
 | 
				
			||||||
 | 
					            class="no-data-found flex items-center justify-center" translate>{{ 'dashboard.no-states-text' }}</span>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <mat-divider></mat-divider>
 | 
				
			||||||
 | 
					    <mat-paginator [length]="dataSource.total() | async"
 | 
				
			||||||
 | 
					                   [pageIndex]="pageLink.page"
 | 
				
			||||||
 | 
					                   [pageSize]="pageLink.pageSize"
 | 
				
			||||||
 | 
					                   [pageSizeOptions]="[5, 10, 15]"></mat-paginator>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <div mat-dialog-actions class="flex items-center justify-end">
 | 
					</div>
 | 
				
			||||||
    <button mat-button color="primary"
 | 
					<div mat-dialog-actions class="flex items-center justify-end">
 | 
				
			||||||
            type="button"
 | 
					  <button mat-button color="primary"
 | 
				
			||||||
            [disabled]="(isLoading$ | async)"
 | 
					          type="button"
 | 
				
			||||||
            (click)="cancel()" cdkFocusInitial>
 | 
					          [disabled]="(isLoading$ | async)"
 | 
				
			||||||
      {{ 'action.cancel' | translate }}
 | 
					          (click)="cancel()" cdkFocusInitial>
 | 
				
			||||||
    </button>
 | 
					    {{ 'action.cancel' | translate }}
 | 
				
			||||||
    <button mat-raised-button color="primary"
 | 
					  </button>
 | 
				
			||||||
            type="submit"
 | 
					  <button mat-raised-button color="primary"
 | 
				
			||||||
            [disabled]="(isLoading$ | async) || statesFormGroup.invalid || !statesFormGroup.dirty">
 | 
					          type="submit"
 | 
				
			||||||
      {{ 'action.save' | translate }}
 | 
					          (click)="save()"
 | 
				
			||||||
    </button>
 | 
					          [disabled]="(isLoading$ | async) || !isDirty">
 | 
				
			||||||
  </div>
 | 
					    {{ 'action.save' | translate }}
 | 
				
			||||||
</form>
 | 
					  </button>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -13,27 +13,39 @@
 | 
				
			|||||||
 * See the License for the specific language governing permissions and
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 * limitations under the License.
 | 
					 * limitations under the License.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					@import "../scss/constants";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:host {
 | 
					:host {
 | 
				
			||||||
 | 
					  height: 100%;
 | 
				
			||||||
 | 
					  display: grid;
 | 
				
			||||||
 | 
					  grid-template-rows: min-content auto min-content;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  .manage-dashboard-states {
 | 
					  .manage-dashboard-states {
 | 
				
			||||||
    .tb-entity-table {
 | 
					    .tb-entity-table-content {
 | 
				
			||||||
      .tb-entity-table-content {
 | 
					      width: 100%;
 | 
				
			||||||
        width: 100%;
 | 
					      height: 100%;
 | 
				
			||||||
        height: 100%;
 | 
					      background: #fff;
 | 
				
			||||||
        background: #fff;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .tb-entity-table-title {
 | 
					      .tb-entity-table-title {
 | 
				
			||||||
          padding-right: 20px;
 | 
					        padding-right: 20px;
 | 
				
			||||||
          white-space: nowrap;
 | 
					        white-space: nowrap;
 | 
				
			||||||
          overflow: hidden;
 | 
					        overflow: hidden;
 | 
				
			||||||
          text-overflow: ellipsis;
 | 
					        text-overflow: ellipsis;
 | 
				
			||||||
        }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .table-container {
 | 
					      .table-container {
 | 
				
			||||||
          overflow: auto;
 | 
					        overflow: auto;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @media #{$mat-sm} {
 | 
				
			||||||
 | 
					    min-width: 470px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @media #{$mat-gt-sm} {
 | 
				
			||||||
 | 
					    min-width: 750px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:host ::ng-deep {
 | 
					:host ::ng-deep {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,21 +14,10 @@
 | 
				
			|||||||
/// limitations under the License.
 | 
					/// limitations under the License.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import {
 | 
					import { AfterViewInit, Component, ElementRef, Inject, OnInit, SecurityContext, ViewChild } from '@angular/core';
 | 
				
			||||||
  AfterViewInit,
 | 
					 | 
				
			||||||
  Component,
 | 
					 | 
				
			||||||
  ElementRef,
 | 
					 | 
				
			||||||
  Inject,
 | 
					 | 
				
			||||||
  OnInit,
 | 
					 | 
				
			||||||
  SecurityContext,
 | 
					 | 
				
			||||||
  SkipSelf,
 | 
					 | 
				
			||||||
  ViewChild
 | 
					 | 
				
			||||||
} from '@angular/core';
 | 
					 | 
				
			||||||
import { ErrorStateMatcher } from '@angular/material/core';
 | 
					 | 
				
			||||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 | 
					import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
 | 
				
			||||||
import { Store } from '@ngrx/store';
 | 
					import { Store } from '@ngrx/store';
 | 
				
			||||||
import { AppState } from '@core/core.state';
 | 
					import { AppState } from '@core/core.state';
 | 
				
			||||||
import { FormGroupDirective, NgForm, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms';
 | 
					 | 
				
			||||||
import { Router } from '@angular/router';
 | 
					import { Router } from '@angular/router';
 | 
				
			||||||
import { DialogComponent } from '@app/shared/components/dialog.component';
 | 
					import { DialogComponent } from '@app/shared/components/dialog.component';
 | 
				
			||||||
import { DashboardState } from '@app/shared/models/dashboard.models';
 | 
					import { DashboardState } from '@app/shared/models/dashboard.models';
 | 
				
			||||||
@ -44,7 +33,7 @@ import { fromEvent, merge } from 'rxjs';
 | 
				
			|||||||
import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
 | 
					import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators';
 | 
				
			||||||
import { TranslateService } from '@ngx-translate/core';
 | 
					import { TranslateService } from '@ngx-translate/core';
 | 
				
			||||||
import { DialogService } from '@core/services/dialog.service';
 | 
					import { DialogService } from '@core/services/dialog.service';
 | 
				
			||||||
import { deepClone, isDefined } from '@core/utils';
 | 
					import { deepClone, isDefined, isEqual } from '@core/utils';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  DashboardStateDialogComponent,
 | 
					  DashboardStateDialogComponent,
 | 
				
			||||||
  DashboardStateDialogData
 | 
					  DashboardStateDialogData
 | 
				
			||||||
@ -58,42 +47,42 @@ export interface ManageDashboardStatesDialogData {
 | 
				
			|||||||
  widgets: {[id: string]: Widget };
 | 
					  widgets: {[id: string]: Widget };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ManageDashboardStatesDialogResult {
 | 
				
			||||||
 | 
					  states: {[id: string]: DashboardState };
 | 
				
			||||||
 | 
					  addWidgets?: {[id: string]: Widget };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'tb-manage-dashboard-states-dialog',
 | 
					  selector: 'tb-manage-dashboard-states-dialog',
 | 
				
			||||||
  templateUrl: './manage-dashboard-states-dialog.component.html',
 | 
					  templateUrl: './manage-dashboard-states-dialog.component.html',
 | 
				
			||||||
  providers: [{provide: ErrorStateMatcher, useExisting: ManageDashboardStatesDialogComponent}],
 | 
					 | 
				
			||||||
  styleUrls: ['./manage-dashboard-states-dialog.component.scss']
 | 
					  styleUrls: ['./manage-dashboard-states-dialog.component.scss']
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class ManageDashboardStatesDialogComponent
 | 
					export class ManageDashboardStatesDialogComponent
 | 
				
			||||||
  extends DialogComponent<ManageDashboardStatesDialogComponent, {states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>
 | 
					  extends DialogComponent<ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogResult>
 | 
				
			||||||
  implements OnInit, ErrorStateMatcher, AfterViewInit {
 | 
					  implements OnInit, AfterViewInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  statesFormGroup: UntypedFormGroup;
 | 
					  @ViewChild('searchInput', {static: false}) searchInputField: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  states: {[id: string]: DashboardState };
 | 
					  @ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
 | 
				
			||||||
  widgets: {[id: string]: Widget};
 | 
					  @ViewChild(MatSort, {static: false}) sort: MatSort;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  isDirty = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  displayedColumns: string[];
 | 
					  displayedColumns: string[];
 | 
				
			||||||
  pageLink: PageLink;
 | 
					  pageLink: PageLink;
 | 
				
			||||||
  textSearchMode = false;
 | 
					  textSearchMode = false;
 | 
				
			||||||
  dataSource: DashboardStatesDatasource;
 | 
					  dataSource: DashboardStatesDatasource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  submitted = false;
 | 
					  private states: {[id: string]: DashboardState };
 | 
				
			||||||
 | 
					  private widgets: {[id: string]: Widget};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  stateNames: Set<string> = new Set<string>();
 | 
					  private stateNames: Set<string> = new Set<string>();
 | 
				
			||||||
 | 
					  private addWidgets: {[id: string]: Widget} = {};
 | 
				
			||||||
  @ViewChild('searchInput') searchInputField: ElementRef;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @ViewChild(MatPaginator) paginator: MatPaginator;
 | 
					 | 
				
			||||||
  @ViewChild(MatSort) sort: MatSort;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(protected store: Store<AppState>,
 | 
					  constructor(protected store: Store<AppState>,
 | 
				
			||||||
              protected router: Router,
 | 
					              protected router: Router,
 | 
				
			||||||
              @Inject(MAT_DIALOG_DATA) public data: ManageDashboardStatesDialogData,
 | 
					              @Inject(MAT_DIALOG_DATA) public data: ManageDashboardStatesDialogData,
 | 
				
			||||||
              @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
 | 
					              public dialogRef: MatDialogRef<ManageDashboardStatesDialogComponent, ManageDashboardStatesDialogResult>,
 | 
				
			||||||
              public dialogRef: MatDialogRef<ManageDashboardStatesDialogComponent,
 | 
					 | 
				
			||||||
                {states: {[id: string]: DashboardState}; widgets: {[id: string]: Widget}}>,
 | 
					 | 
				
			||||||
              private fb: UntypedFormBuilder,
 | 
					 | 
				
			||||||
              private translate: TranslateService,
 | 
					              private translate: TranslateService,
 | 
				
			||||||
              private dialogs: DialogService,
 | 
					              private dialogs: DialogService,
 | 
				
			||||||
              private utils: UtilsService,
 | 
					              private utils: UtilsService,
 | 
				
			||||||
@ -103,7 +92,6 @@ export class ManageDashboardStatesDialogComponent
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    this.states = this.data.states;
 | 
					    this.states = this.data.states;
 | 
				
			||||||
    this.widgets = this.data.widgets;
 | 
					    this.widgets = this.data.widgets;
 | 
				
			||||||
    this.statesFormGroup = this.fb.group({});
 | 
					 | 
				
			||||||
    Object.values(this.states).forEach(value => this.stateNames.add(value.name));
 | 
					    Object.values(this.states).forEach(value => this.stateNames.add(value.name));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const sortOrder: SortOrder = { property: 'name', direction: Direction.ASC };
 | 
					    const sortOrder: SortOrder = { property: 'name', direction: Direction.ASC };
 | 
				
			||||||
@ -271,9 +259,7 @@ export class ManageDashboardStatesDialogComponent
 | 
				
			|||||||
        continue;
 | 
					        continue;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const originalState = state;
 | 
					      const duplicatedState = deepClone(state);
 | 
				
			||||||
      const duplicatedState = deepClone(originalState);
 | 
					 | 
				
			||||||
      const duplicatedWidgets = deepClone(this.widgets);
 | 
					 | 
				
			||||||
      const mainWidgets = {};
 | 
					      const mainWidgets = {};
 | 
				
			||||||
      const rightWidgets = {};
 | 
					      const rightWidgets = {};
 | 
				
			||||||
      duplicatedState.id = candidateId;
 | 
					      duplicatedState.id = candidateId;
 | 
				
			||||||
@ -284,8 +270,8 @@ export class ManageDashboardStatesDialogComponent
 | 
				
			|||||||
      for (const [key, value] of Object.entries(duplicatedState.layouts.main.widgets)) {
 | 
					      for (const [key, value] of Object.entries(duplicatedState.layouts.main.widgets)) {
 | 
				
			||||||
        const guid = this.utils.guid();
 | 
					        const guid = this.utils.guid();
 | 
				
			||||||
        mainWidgets[guid] = value;
 | 
					        mainWidgets[guid] = value;
 | 
				
			||||||
        duplicatedWidgets[guid] = this.widgets[key];
 | 
					        this.addWidgets[guid] = deepClone(this.widgets[key] ?? this.addWidgets[key]);
 | 
				
			||||||
        duplicatedWidgets[guid].id = guid;
 | 
					        this.addWidgets[guid].id = guid;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      duplicatedState.layouts.main.widgets = mainWidgets;
 | 
					      duplicatedState.layouts.main.widgets = mainWidgets;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -293,36 +279,32 @@ export class ManageDashboardStatesDialogComponent
 | 
				
			|||||||
        for (const [key, value] of Object.entries(duplicatedState.layouts.right.widgets)) {
 | 
					        for (const [key, value] of Object.entries(duplicatedState.layouts.right.widgets)) {
 | 
				
			||||||
          const guid = this.utils.guid();
 | 
					          const guid = this.utils.guid();
 | 
				
			||||||
          rightWidgets[guid] = value;
 | 
					          rightWidgets[guid] = value;
 | 
				
			||||||
          duplicatedWidgets[guid] = this.widgets[key];
 | 
					          this.addWidgets[guid] = deepClone(this.widgets[key] ?? this.addWidgets[key]);
 | 
				
			||||||
          duplicatedWidgets[guid].id = guid;
 | 
					          this.addWidgets[guid].id = guid;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        duplicatedState.layouts.right.widgets = rightWidgets;
 | 
					        duplicatedState.layouts.right.widgets = rightWidgets;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      this.states[duplicatedState.id] = duplicatedState;
 | 
					      this.states[duplicatedState.id] = duplicatedState;
 | 
				
			||||||
      this.widgets = duplicatedWidgets;
 | 
					 | 
				
			||||||
      this.onStatesUpdated();
 | 
					      this.onStatesUpdated();
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private onStatesUpdated() {
 | 
					  private onStatesUpdated() {
 | 
				
			||||||
    this.statesFormGroup.markAsDirty();
 | 
					    this.isDirty = true;
 | 
				
			||||||
    this.updateData(true);
 | 
					    this.updateData(true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
 | 
					 | 
				
			||||||
    const originalErrorState = this.errorStateMatcher.isErrorState(control, form);
 | 
					 | 
				
			||||||
    const customErrorState = !!(control && control.invalid && this.submitted);
 | 
					 | 
				
			||||||
    return originalErrorState || customErrorState;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  cancel(): void {
 | 
					  cancel(): void {
 | 
				
			||||||
    this.dialogRef.close(null);
 | 
					    this.dialogRef.close(null);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  save(): void {
 | 
					  save(): void {
 | 
				
			||||||
    this.submitted = true;
 | 
					    const result: ManageDashboardStatesDialogResult = {states: this.states};
 | 
				
			||||||
    this.dialogRef.close({ states: this.states, widgets: this.widgets });
 | 
					    if (!isEqual(this.addWidgets, {})) {
 | 
				
			||||||
 | 
					      result.addWidgets = this.addWidgets;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.dialogRef.close(result);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user