Merge pull request #10600 from rusikv/feature/cell-click-action
Cell click action type
This commit is contained in:
		
						commit
						9e3f3429e8
					
				@ -11,7 +11,7 @@
 | 
			
		||||
    "resources": [],
 | 
			
		||||
    "templateHtml": "<tb-alarms-table-widget \n    [ctx]=\"ctx\">\n</tb-alarms-table-widget>",
 | 
			
		||||
    "templateCss": "",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.alarmsTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.alarmsTableWidget.onEditModeChanged();\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.alarmsTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.alarmsTableWidget.onEditModeChanged();\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'cellClick': {\n            name: 'widget-action.cell-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "settingsSchema": "",
 | 
			
		||||
    "dataKeySettingsSchema": "",
 | 
			
		||||
    "settingsDirective": "tb-alarms-table-widget-settings",
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
    "resources": [],
 | 
			
		||||
    "templateHtml": "<tb-entities-table-widget \n    [ctx]=\"ctx\">\n</tb-entities-table-widget>",
 | 
			
		||||
    "templateCss": "",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        },\n        'cellClick': {\n            name: 'widget-action.cell-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "settingsSchema": "",
 | 
			
		||||
    "dataKeySettingsSchema": "",
 | 
			
		||||
    "settingsDirective": "tb-entities-table-widget-settings",
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
    "resources": [],
 | 
			
		||||
    "templateHtml": "<tb-entities-table-widget \n    [ctx]=\"ctx\">\n</tb-entities-table-widget>",
 | 
			
		||||
    "templateCss": "",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        },\n        'cellClick': {\n            name: 'widget-action.cell-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "settingsSchema": "",
 | 
			
		||||
    "dataKeySettingsSchema": "",
 | 
			
		||||
    "settingsDirective": "tb-entities-table-widget-settings",
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
    "resources": [],
 | 
			
		||||
    "templateHtml": "<tb-entities-table-widget \n    [ctx]=\"ctx\">\n</tb-entities-table-widget>",
 | 
			
		||||
    "templateCss": "",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true,\n        defaultDataKeysFunction: function() {\n            return [{ name: 'name', type: 'entityField' }];\n        }\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n    self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.$scope.entitiesTableWidget.onEditModeChanged();\n}\n\nself.typeParameters = function() {\n    return {\n        maxDatasources: 1,\n        hasDataPageLink: true,\n        warnOnPageDataOverflow: false,\n        dataKeysOptional: true,\n        defaultDataKeysFunction: function() {\n            return [{ name: 'name', type: 'entityField' }];\n        }\n    };\n}\n\nself.actionSources = function() {\n    return {\n        'actionCellButton': {\n            name: 'widget-action.action-cell-button',\n            multiple: true,\n            hasShowCondition: true\n        },\n        'rowClick': {\n            name: 'widget-action.row-click',\n            multiple: false\n        },\n        'rowDoubleClick': {\n            name: 'widget-action.row-double-click',\n            multiple: false\n        },\n        'cellClick': {\n            name: 'widget-action.cell-click',\n            multiple: false\n        }\n    };\n}\n\nself.onDestroy = function() {\n}\n",
 | 
			
		||||
    "settingsSchema": "",
 | 
			
		||||
    "dataKeySettingsSchema": "",
 | 
			
		||||
    "settingsDirective": "tb-entities-table-widget-settings",
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  CellClickColumnInfo,
 | 
			
		||||
  WidgetActionDescriptor,
 | 
			
		||||
  WidgetActionSource,
 | 
			
		||||
  widgetActionTypeTranslationMap
 | 
			
		||||
@ -30,6 +31,7 @@ import { deepClone } from '@core/utils';
 | 
			
		||||
 | 
			
		||||
export interface WidgetActionCallbacks {
 | 
			
		||||
  fetchDashboardStates: (query: string) => Array<string>;
 | 
			
		||||
  fetchCellClickColumns: () => Array<CellClickColumnInfo>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface WidgetActionsData {
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,27 @@
 | 
			
		||||
            </mat-icon>
 | 
			
		||||
          </mat-form-field>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="tb-form-row" *ngIf="widgetActionFormGroup.get('actionSourceId').value === 'cellClick'">
 | 
			
		||||
          <div class="fixed-title-width">{{'widget-config.column-index' | translate}}*</div>
 | 
			
		||||
          <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
 | 
			
		||||
            <mat-select #columnIndexSelect formControlName="columnIndex" placeholder="{{ columnIndexPlaceholderText }}">
 | 
			
		||||
              <mat-option *ngFor="let column of configuredColumns; let $index = index"
 | 
			
		||||
                          [value]="$index"
 | 
			
		||||
                          [disabled]="usedCellClickColumns.includes($index)">
 | 
			
		||||
                {{ getCellClickColumnInfo($index, column) }}
 | 
			
		||||
              </mat-option>
 | 
			
		||||
            </mat-select>
 | 
			
		||||
            <mat-icon matSuffix
 | 
			
		||||
                      matTooltipPosition="above"
 | 
			
		||||
                      matTooltipClass="tb-error-tooltip"
 | 
			
		||||
                      [matTooltip]="'widget-config.column-index-required' | translate"
 | 
			
		||||
                      *ngIf="widgetActionFormGroup.get('columnIndex').hasError('required') &&
 | 
			
		||||
                             widgetActionFormGroup.get('columnIndex').touched"
 | 
			
		||||
                      class="tb-error">
 | 
			
		||||
              warning
 | 
			
		||||
            </mat-icon>
 | 
			
		||||
          </mat-form-field>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="tb-form-row">
 | 
			
		||||
          <div class="fixed-title-width">{{'widget-config.action-name' | translate}}*</div>
 | 
			
		||||
          <mat-form-field fxFlex appearance="outline" subscriptSizing="dynamic">
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@
 | 
			
		||||
/// limitations under the License.
 | 
			
		||||
///
 | 
			
		||||
 | 
			
		||||
import { Component, Inject, OnDestroy, OnInit, SkipSelf } from '@angular/core';
 | 
			
		||||
import { Component, Inject, OnDestroy, OnInit, SkipSelf, ViewChild } from '@angular/core';
 | 
			
		||||
import { ErrorStateMatcher } from '@angular/material/core';
 | 
			
		||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
@ -40,6 +40,7 @@ import {
 | 
			
		||||
import { UtilsService } from '@core/services/utils.service';
 | 
			
		||||
import {
 | 
			
		||||
  actionDescriptorToAction,
 | 
			
		||||
  CellClickColumnInfo,
 | 
			
		||||
  defaultWidgetAction,
 | 
			
		||||
  WidgetActionSource,
 | 
			
		||||
  widgetType
 | 
			
		||||
@ -47,6 +48,9 @@ import {
 | 
			
		||||
import { takeUntil } from 'rxjs/operators';
 | 
			
		||||
import { CustomActionEditorCompleter } from '@home/components/widget/lib/settings/common/action/custom-action.models';
 | 
			
		||||
import { WidgetService } from '@core/http/widget.service';
 | 
			
		||||
import { isDefinedAndNotNull, isNotEmptyStr } from '@core/utils';
 | 
			
		||||
import { MatSelect } from '@angular/material/select';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
 | 
			
		||||
export interface WidgetActionDialogData {
 | 
			
		||||
  isAdd: boolean;
 | 
			
		||||
@ -78,6 +82,12 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
 | 
			
		||||
  functionScopeVariables: string[];
 | 
			
		||||
 | 
			
		||||
  configuredColumns: Array<CellClickColumnInfo> = [];
 | 
			
		||||
  usedCellClickColumns: Array<number> = [];
 | 
			
		||||
 | 
			
		||||
  @ViewChild('columnIndexSelect') columnIndexSelect: MatSelect;
 | 
			
		||||
  columnIndexPlaceholderText = this.translate.instant('widget-config.select-column-index');
 | 
			
		||||
 | 
			
		||||
  constructor(protected store: Store<AppState>,
 | 
			
		||||
              protected router: Router,
 | 
			
		||||
              private utils: UtilsService,
 | 
			
		||||
@ -85,7 +95,8 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
              @Inject(MAT_DIALOG_DATA) public data: WidgetActionDialogData,
 | 
			
		||||
              @SkipSelf() private errorStateMatcher: ErrorStateMatcher,
 | 
			
		||||
              public dialogRef: MatDialogRef<WidgetActionDialogComponent, WidgetActionDescriptorInfo>,
 | 
			
		||||
              public fb: FormBuilder) {
 | 
			
		||||
              public fb: FormBuilder,
 | 
			
		||||
              private translate: TranslateService) {
 | 
			
		||||
    super(store, router, dialogRef);
 | 
			
		||||
    this.isAdd = data.isAdd;
 | 
			
		||||
    if (this.isAdd) {
 | 
			
		||||
@ -99,11 +110,15 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
      this.action = this.data.action;
 | 
			
		||||
    }
 | 
			
		||||
    this.functionScopeVariables = this.widgetService.getWidgetScopeVariables();
 | 
			
		||||
    if (this.action.actionSourceId === 'cellClick') {
 | 
			
		||||
      this.getCellClickColumnsInfo();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit(): void {
 | 
			
		||||
    this.widgetActionFormGroup = this.fb.group({
 | 
			
		||||
      actionSourceId: [this.action.actionSourceId, Validators.required],
 | 
			
		||||
      columnIndex: [this.checkColumnIndex(this.action.columnIndex), Validators.required],
 | 
			
		||||
      name: [this.action.name, [this.validateActionName(), Validators.required]],
 | 
			
		||||
      icon: [this.action.icon, Validators.required],
 | 
			
		||||
      useShowWidgetActionFunction: [this.action.useShowWidgetActionFunction],
 | 
			
		||||
@ -113,15 +128,29 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
    this.updateShowWidgetActionForm();
 | 
			
		||||
    this.widgetActionFormGroup.get('actionSourceId').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
    ).subscribe(() => {
 | 
			
		||||
    ).subscribe((value) => {
 | 
			
		||||
      this.widgetActionFormGroup.get('name').updateValueAndValidity();
 | 
			
		||||
      this.updateShowWidgetActionForm();
 | 
			
		||||
      if (value === 'cellClick') {
 | 
			
		||||
        this.widgetActionFormGroup.get('columnIndex').setValidators([Validators.required]);
 | 
			
		||||
        this.getCellClickColumnsInfo();
 | 
			
		||||
      } else {
 | 
			
		||||
        this.widgetActionFormGroup.get('columnIndex').clearValidators();
 | 
			
		||||
      }
 | 
			
		||||
      this.widgetActionFormGroup.get('columnIndex').updateValueAndValidity();
 | 
			
		||||
    });
 | 
			
		||||
    this.widgetActionFormGroup.get('useShowWidgetActionFunction').valueChanges.pipe(
 | 
			
		||||
      takeUntil(this.destroy$)
 | 
			
		||||
    ).subscribe(() => {
 | 
			
		||||
      this.updateShowWidgetActionForm();
 | 
			
		||||
    });
 | 
			
		||||
    setTimeout(() => {
 | 
			
		||||
      if (this.action?.actionSourceId === 'cellClick' && isDefinedAndNotNull(this.action.columnIndex) &&
 | 
			
		||||
        this.widgetActionFormGroup.get('columnIndex').value === null) {
 | 
			
		||||
        this.columnIndexPlaceholderText = `${this.action.columnIndex} (${this.translate.instant('widget-config.not-set')})`;
 | 
			
		||||
        this.columnIndexSelect.focus();
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
@ -155,6 +184,22 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
    this.widgetActionFormGroup.get('showWidgetActionFunction').updateValueAndValidity();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private checkColumnIndex(columnIndex: number): number | null {
 | 
			
		||||
    return isDefinedAndNotNull(columnIndex) && this.configuredColumns.length - 1 < columnIndex ? null : columnIndex;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getCellClickColumnsInfo(): void {
 | 
			
		||||
    if (!this.configuredColumns.length) {
 | 
			
		||||
      this.configuredColumns = this.data.callbacks.fetchCellClickColumns();
 | 
			
		||||
      this.data.actionsData.actionsMap['cellClick']?.forEach(action => {
 | 
			
		||||
        const actionColumn = this.configuredColumns[action.columnIndex];
 | 
			
		||||
        if (actionColumn && action.columnIndex !== this.action.columnIndex) {
 | 
			
		||||
          this.usedCellClickColumns.push(action.columnIndex);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private validateActionName(): ValidatorFn {
 | 
			
		||||
    return (c: FormControl) => {
 | 
			
		||||
      const newName = c.value;
 | 
			
		||||
@ -193,6 +238,10 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getCellClickColumnInfo(index: number, columnInfo: CellClickColumnInfo): string {
 | 
			
		||||
    return `${index} (${isNotEmptyStr(columnInfo.label) ? columnInfo.label : columnInfo.name})`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cancel(): void {
 | 
			
		||||
    this.dialogRef.close(null);
 | 
			
		||||
  }
 | 
			
		||||
@ -204,6 +253,9 @@ export class WidgetActionDialogComponent extends DialogComponent<WidgetActionDia
 | 
			
		||||
        {...this.widgetActionFormGroup.value, ...this.widgetActionFormGroup.get('widgetAction').value};
 | 
			
		||||
      delete (result as any).widgetAction;
 | 
			
		||||
      result.id = this.action.id;
 | 
			
		||||
      if (!isDefinedAndNotNull(result.columnIndex)) {
 | 
			
		||||
        delete result.columnIndex;
 | 
			
		||||
      }
 | 
			
		||||
      this.dialogRef.close(result);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -77,12 +77,14 @@
 | 
			
		||||
            </mat-checkbox>
 | 
			
		||||
          </mat-cell>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
        <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;">
 | 
			
		||||
        <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; let $index = index; trackBy: trackByColumnDef;">
 | 
			
		||||
          <mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header [disabled]="isSorting(column)">
 | 
			
		||||
            {{ column.title }}
 | 
			
		||||
          </mat-header-cell>
 | 
			
		||||
          <mat-cell *matCellDef="let alarm; let row = index"
 | 
			
		||||
                    [ngStyle]="cellStyle(alarm, column, row)">
 | 
			
		||||
                    [ngStyle]="cellStyle(alarm, column, row)"
 | 
			
		||||
                    (click)="onCellClick($event, alarm, column, $index)"
 | 
			
		||||
                    [class.tb-pointer]="columnHasCellClick($index)">
 | 
			
		||||
            <span [innerHTML]="cellContent(alarm, column, row)"></span>
 | 
			
		||||
            <ng-container *ngIf="column.entityKey.key === 'assignee'">
 | 
			
		||||
              <span class="assignee-cell" fxLayout="row" fxLayoutAlign="start center">
 | 
			
		||||
 | 
			
		||||
@ -204,6 +204,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
 | 
			
		||||
  private columnWidth: {[key: string]: string} = {};
 | 
			
		||||
  private columnDefaultVisibility: {[key: string]: boolean} = {};
 | 
			
		||||
  private columnSelectionAvailability: {[key: string]: boolean} = {};
 | 
			
		||||
  private columnsWithCellClick: Array<number> = [];
 | 
			
		||||
 | 
			
		||||
  private rowStylesInfo: RowStyleInfo;
 | 
			
		||||
 | 
			
		||||
@ -358,6 +359,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
 | 
			
		||||
    this.enableStickyAction = isDefined(this.settings.enableStickyAction) ? this.settings.enableStickyAction : false;
 | 
			
		||||
    this.showCellActionsMenu = isDefined(this.settings.showCellActionsMenu) ? this.settings.showCellActionsMenu : true;
 | 
			
		||||
    this.columnDisplayAction.show = isDefined(this.settings.enableSelectColumnDisplay) ? this.settings.enableSelectColumnDisplay : true;
 | 
			
		||||
    this.columnsWithCellClick = this.ctx.actionsApi.getActionDescriptors('cellClick').map(action => action.columnIndex);
 | 
			
		||||
    let enableFilter;
 | 
			
		||||
    if (isDefined(this.settings.enableFilter)) {
 | 
			
		||||
      enableFilter = this.settings.enableFilter;
 | 
			
		||||
@ -794,6 +796,33 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onCellClick($event: Event, alarm: AlarmDataInfo, key: EntityColumn, columnIndex: number) {
 | 
			
		||||
    this.alarmsDatasource.toggleCurrentAlarm(alarm);
 | 
			
		||||
    const descriptors = this.ctx.actionsApi.getActionDescriptors('cellClick');
 | 
			
		||||
    let descriptor;
 | 
			
		||||
    if (descriptors.length) {
 | 
			
		||||
      descriptor = descriptors.find(desc => desc.columnIndex === columnIndex);
 | 
			
		||||
    }
 | 
			
		||||
    if ($event && descriptor) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
      let entityId;
 | 
			
		||||
      let entityName;
 | 
			
		||||
      let entityLabel;
 | 
			
		||||
      if (alarm && alarm.originator) {
 | 
			
		||||
        entityId = alarm.originator;
 | 
			
		||||
        entityName = alarm.entityName;
 | 
			
		||||
        entityLabel = alarm.entityLabel;
 | 
			
		||||
      }
 | 
			
		||||
      this.ctx.actionsApi.handleWidgetAction($event, descriptor, entityId, entityName, {alarm, key}, entityLabel);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public columnHasCellClick(columnIndex: number) {
 | 
			
		||||
    if (this.columnsWithCellClick.length) {
 | 
			
		||||
      return this.columnsWithCellClick.includes(columnIndex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onRowClick($event: Event, alarm: AlarmDataInfo) {
 | 
			
		||||
    if ($event) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
 | 
			
		||||
@ -40,12 +40,14 @@
 | 
			
		||||
    <div fxFlex class="table-container">
 | 
			
		||||
      <table mat-table [dataSource]="entityDatasource" [trackBy]="trackByEntityId"
 | 
			
		||||
                 matSort [matSortActive]="sortOrderProperty" [matSortDirection]="pageLinkSortDirection()" matSortDisableClear>
 | 
			
		||||
        <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; trackBy: trackByColumnDef;">
 | 
			
		||||
        <ng-container [matColumnDef]="column.def" *ngFor="let column of columns; let $index = index; trackBy: trackByColumnDef;">
 | 
			
		||||
          <mat-header-cell [ngStyle]="headerStyle(column)" *matHeaderCellDef mat-sort-header [disabled]="!column.sortable"> {{ column.title }} </mat-header-cell>
 | 
			
		||||
          <mat-cell *matCellDef="let entity; let row = index"
 | 
			
		||||
                    [innerHTML]="cellContent(entity, column, row)"
 | 
			
		||||
                    [ngStyle]="cellStyle(entity, column, row)">
 | 
			
		||||
          </mat-cell>
 | 
			
		||||
            <mat-cell *matCellDef="let entity; let row = index"
 | 
			
		||||
                      [innerHTML]="cellContent(entity, column, row)"
 | 
			
		||||
                      [ngStyle]="cellStyle(entity, column, row)"
 | 
			
		||||
                      (click)="onCellClick($event, entity, column, $index)"
 | 
			
		||||
                      [class.tb-pointer]="columnHasCellClick($index)">
 | 
			
		||||
            </mat-cell>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
        <ng-container matColumnDef="actions" [stickyEnd]="enableStickyAction">
 | 
			
		||||
          <mat-header-cell *matHeaderCellDef [ngStyle.gt-md]="{ minWidth: (entityDatasource.countCellButtonAction * 48) + 'px',
 | 
			
		||||
 | 
			
		||||
@ -169,6 +169,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
 | 
			
		||||
  private columnWidth: {[key: string]: string} = {};
 | 
			
		||||
  private columnDefaultVisibility: {[key: string]: boolean} = {};
 | 
			
		||||
  private columnSelectionAvailability: {[key: string]: boolean} = {};
 | 
			
		||||
  private columnsWithCellClick: Array<number> = [];
 | 
			
		||||
 | 
			
		||||
  private rowStylesInfo: RowStyleInfo;
 | 
			
		||||
 | 
			
		||||
@ -230,6 +231,12 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private isActionsConfigured(actionSourceIds: Array<string>): boolean {
 | 
			
		||||
    let configured = false;
 | 
			
		||||
    actionSourceIds.forEach(id => configured = configured || this.ctx.actionsApi.getActionDescriptors(id).length > 0 );
 | 
			
		||||
    return configured;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy(): void {
 | 
			
		||||
    if (this.widgetResize$) {
 | 
			
		||||
      this.widgetResize$.disconnect();
 | 
			
		||||
@ -284,6 +291,7 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
 | 
			
		||||
 | 
			
		||||
    this.hasRowAction = !!this.ctx.actionsApi.getActionDescriptors('rowClick').length ||
 | 
			
		||||
      !!this.ctx.actionsApi.getActionDescriptors('rowDoubleClick').length;
 | 
			
		||||
    this.columnsWithCellClick = this.ctx.actionsApi.getActionDescriptors('cellClick').map(action => action.columnIndex);
 | 
			
		||||
 | 
			
		||||
    if (this.settings.entitiesTitle && this.settings.entitiesTitle.length) {
 | 
			
		||||
      this.ctx.widgetTitle = this.settings.entitiesTitle;
 | 
			
		||||
@ -694,6 +702,33 @@ export class EntitiesTableWidgetComponent extends PageComponent implements OnIni
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onCellClick($event: Event, entity: EntityData, key: EntityColumn, columnIndex: number) {
 | 
			
		||||
    this.entityDatasource.toggleCurrentEntity(entity);
 | 
			
		||||
    const descriptors = this.ctx.actionsApi.getActionDescriptors('cellClick');
 | 
			
		||||
    let descriptor;
 | 
			
		||||
    if (descriptors.length) {
 | 
			
		||||
      descriptor = descriptors.find(desc => desc.columnIndex === columnIndex);
 | 
			
		||||
    }
 | 
			
		||||
    if ($event && descriptor) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
      let entityId;
 | 
			
		||||
      let entityName;
 | 
			
		||||
      let entityLabel;
 | 
			
		||||
      if (entity) {
 | 
			
		||||
        entityId = entity.id;
 | 
			
		||||
        entityName = entity.entityName;
 | 
			
		||||
        entityLabel = entity.entityLabel;
 | 
			
		||||
      }
 | 
			
		||||
      this.ctx.actionsApi.handleWidgetAction($event, descriptor, entityId, entityName, {entity, key}, entityLabel);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public columnHasCellClick(index: number) {
 | 
			
		||||
    if (this.columnsWithCellClick.length) {
 | 
			
		||||
      return this.columnsWithCellClick.includes(index);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public onRowClick($event: Event, entity: EntityData, isDouble?: boolean) {
 | 
			
		||||
    if ($event) {
 | 
			
		||||
      $event.stopPropagation();
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ import { PageComponent } from '@shared/components/page.component';
 | 
			
		||||
import { Store } from '@ngrx/store';
 | 
			
		||||
import { AppState } from '@core/core.state';
 | 
			
		||||
import {
 | 
			
		||||
  CellClickColumnInfo,
 | 
			
		||||
  DataKey,
 | 
			
		||||
  datasourcesHasAggregation,
 | 
			
		||||
  datasourcesHasOnlyComparisonAggregation,
 | 
			
		||||
@ -161,7 +162,8 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
 | 
			
		||||
    generateDataKey: this.generateDataKey.bind(this),
 | 
			
		||||
    fetchEntityKeysForDevice: this.fetchEntityKeysForDevice.bind(this),
 | 
			
		||||
    fetchEntityKeys: this.fetchEntityKeys.bind(this),
 | 
			
		||||
    fetchDashboardStates: this.fetchDashboardStates.bind(this)
 | 
			
		||||
    fetchDashboardStates: this.fetchDashboardStates.bind(this),
 | 
			
		||||
    fetchCellClickColumns: this.fetchCellClickColumns.bind(this)
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  widgetEditMode = this.utils.widgetEditMode;
 | 
			
		||||
@ -870,6 +872,30 @@ export class WidgetConfigComponent extends PageComponent implements OnInit, OnDe
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private fetchCellClickColumns(): Array<CellClickColumnInfo> {
 | 
			
		||||
    if (this.modelValue) {
 | 
			
		||||
      const configuredColumns = new Array<CellClickColumnInfo>();
 | 
			
		||||
      if (this.modelValue.config?.datasources[0]?.dataKeys?.length) {
 | 
			
		||||
        configuredColumns.push(...this.keysToCellClickColumns(this.modelValue.config.datasources[0].dataKeys));
 | 
			
		||||
      }
 | 
			
		||||
      if (this.modelValue.config?.alarmSource?.dataKeys?.length) {
 | 
			
		||||
        configuredColumns.push(...this.keysToCellClickColumns(this.modelValue.config.alarmSource.dataKeys));
 | 
			
		||||
      }
 | 
			
		||||
      return configuredColumns;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private keysToCellClickColumns(dataKeys: Array<DataKey>): Array<CellClickColumnInfo> {
 | 
			
		||||
    const result: Array<CellClickColumnInfo> = [];
 | 
			
		||||
    for (const dataKey of dataKeys) {
 | 
			
		||||
      result.push({
 | 
			
		||||
        name: dataKey.name,
 | 
			
		||||
        label: dataKey?.label
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createFilterForDashboardState(query: string): (stateId: string) => boolean {
 | 
			
		||||
    const lowercaseQuery = query.toLowerCase();
 | 
			
		||||
    return stateId => stateId.toLowerCase().indexOf(lowercaseQuery) === 0;
 | 
			
		||||
 | 
			
		||||
@ -359,6 +359,8 @@ export interface DataKey extends KeyInfo {
 | 
			
		||||
  _hash?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type CellClickColumnInfo = Pick<DataKey, 'name' | 'label'>
 | 
			
		||||
 | 
			
		||||
export enum DataKeyConfigMode {
 | 
			
		||||
  general = 'general',
 | 
			
		||||
  advanced = 'advanced'
 | 
			
		||||
@ -686,6 +688,7 @@ export interface WidgetActionDescriptor extends WidgetAction {
 | 
			
		||||
  displayName?: string;
 | 
			
		||||
  useShowWidgetActionFunction?: boolean;
 | 
			
		||||
  showWidgetActionFunction?: string;
 | 
			
		||||
  columnIndex?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const actionDescriptorToAction = (descriptor: WidgetActionDescriptor): WidgetAction => {
 | 
			
		||||
@ -696,6 +699,7 @@ export const actionDescriptorToAction = (descriptor: WidgetActionDescriptor): Wi
 | 
			
		||||
  delete result.displayName;
 | 
			
		||||
  delete result.useShowWidgetActionFunction;
 | 
			
		||||
  delete result.showWidgetActionFunction;
 | 
			
		||||
  delete result.columnIndex;
 | 
			
		||||
  return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5461,6 +5461,10 @@
 | 
			
		||||
        "action-source": "Action source",
 | 
			
		||||
        "select-action-source": "Select action source",
 | 
			
		||||
        "action-source-required": "Action source is required.",
 | 
			
		||||
        "column-index": "Column index",
 | 
			
		||||
        "select-column-index": "Select column index",
 | 
			
		||||
        "column-index-required": "Column index is required.",
 | 
			
		||||
        "not-set": "Not set",
 | 
			
		||||
        "action-name": "Name",
 | 
			
		||||
        "action-name-required": "Action name is required.",
 | 
			
		||||
        "action-name-not-unique": "Another action with the same name already exists.\nAction name should be unique within the same action source.",
 | 
			
		||||
@ -7465,6 +7469,7 @@
 | 
			
		||||
        "widget-action": {
 | 
			
		||||
            "action-cell-button": "Action cell button",
 | 
			
		||||
            "row-click": "On row click",
 | 
			
		||||
            "cell-click": "On cell click",
 | 
			
		||||
            "polygon-click": "On polygon click",
 | 
			
		||||
            "marker-click": "On marker click",
 | 
			
		||||
            "circle-click": "On circle click",
 | 
			
		||||
@ -7473,6 +7478,7 @@
 | 
			
		||||
            "element-click": "On HTML element click",
 | 
			
		||||
            "pie-slice-click": "On slice click",
 | 
			
		||||
            "row-double-click": "On row double click",
 | 
			
		||||
            "cell-double-click": "On cell double click",
 | 
			
		||||
            "card-click": "On card click",
 | 
			
		||||
            "click": "On click"
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -856,6 +856,9 @@ mat-icon {
 | 
			
		||||
    .mat-icon {
 | 
			
		||||
      color: rgba(0, 0, 0, .54);
 | 
			
		||||
    }
 | 
			
		||||
    &.tb-pointer {
 | 
			
		||||
      cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .mdc-data-table__row:last-child .mdc-data-table__cell {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user