Browse Source

UI: Add reset option to alarm filter panel.

pull/8917/head
Igor Kulikov 3 years ago
parent
commit
4374b83b7f
  1. 37
      ui-ngx/src/app/core/utils.ts
  2. 7
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html
  3. 44
      ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts
  4. 11
      ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html
  5. 1
      ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html
  6. 2
      ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts
  7. 7
      ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts
  8. 12
      ui-ngx/src/app/modules/home/components/widget/widget-config.component.html
  9. 40
      ui-ngx/src/app/shared/models/query/query.models.ts
  10. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

37
ui-ngx/src/app/core/utils.ts

@ -20,7 +20,7 @@ import { finalize, share } from 'rxjs/operators';
import { Datasource, DatasourceData, FormattedData, ReplaceInfo } from '@app/shared/models/widget.models';
import { EntityId } from '@shared/models/id/entity-id';
import { NULL_UUID } from '@shared/models/id/has-uuid';
import { EntityType, baseDetailsPageByEntityType } from '@shared/models/entity-type.models';
import { baseDetailsPageByEntityType, EntityType } from '@shared/models/entity-type.models';
import { HttpErrorResponse } from '@angular/common/http';
import { TranslateService } from '@ngx-translate/core';
import { serverErrorCodesTranslations } from '@shared/models/constants';
@ -126,15 +126,6 @@ export function isString(value: any): boolean {
return typeof value === 'string';
}
export function isEmpty(obj: any): boolean {
for (const key of Object.keys(obj)) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
export function isLiteralObject(value: any) {
return (!!value) && (value.constructor === Object);
}
@ -320,9 +311,29 @@ export function extractType<T extends object>(target: any, keysOfProps: (keyof T
return _.pick(target, keysOfProps);
}
export function isEqual(a: any, b: any): boolean {
return _.isEqual(a, b);
}
export const isEqual = (a: any, b: any): boolean => _.isEqual(a, b);
export const isEmpty = (a: any): boolean => _.isEmpty(a);
export const isEqualIgnoreUndefined = (a: any, b: any): boolean => {
if (a === b) {
return true;
}
if (isDefinedAndNotNull(a) && isDefinedAndNotNull(b)) {
return isEqual(a, b);
} else {
return (isUndefinedOrNull(a) || !a) && (isUndefinedOrNull(b) || !b);
}
};
export const isArraysEqualIgnoreUndefined = (a: any[], b: any[]): boolean => {
const res = isEqualIgnoreUndefined(a, b);
if (!res) {
return (isUndefinedOrNull(a) || !a?.length) && (isUndefinedOrNull(b) || !b?.length);
} else {
return res;
}
};
export function mergeDeep<T>(target: T, ...sources: T[]): T {
return _.merge(target, ...sources);

7
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.html

@ -33,6 +33,13 @@
<form fxLayout="column" class="mat-content mat-padding" (ngSubmit)="update()">
<ng-container *ngTemplateOutlet="alarmFilter"></ng-container>
<div fxLayout="row" class="tb-panel-actions" fxLayoutAlign="end center">
<button type="button"
mat-button
color="primary"
(click)="reset()">
{{ 'action.reset' | translate }}
</button>
<span fxFlex></span>
<button type="button"
mat-button
(click)="cancel()">

44
ui-ngx/src/app/modules/home/components/alarm/alarm-filter-config.component.ts

@ -29,7 +29,7 @@ import {
ViewContainerRef
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { AlarmFilterConfig } from '@shared/models/query/query.models';
import { AlarmFilterConfig, alarmFilterConfigEquals } from '@shared/models/query/query.models';
import { coerceBoolean } from '@shared/decorators/coercion';
import { ConnectedPosition, Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { TemplatePortal } from '@angular/cdk/portal';
@ -43,6 +43,7 @@ import {
import { MatChipInputEvent } from '@angular/material/chips';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { TranslateService } from '@ngx-translate/core';
import { deepClone } from '@core/utils';
export const ALARM_FILTER_CONFIG_DATA = new InjectionToken<any>('AlarmFilterConfigData');
@ -50,6 +51,7 @@ export interface AlarmFilterConfigData {
panelMode: boolean;
userMode: boolean;
alarmFilterConfig: AlarmFilterConfig;
initialAlarmFilterConfig?: AlarmFilterConfig;
}
// @dynamic
@ -84,6 +86,9 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
@Input()
propagatedFilter = true;
@Input()
initialAlarmFilterConfig: AlarmFilterConfig;
panelMode = false;
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
@ -128,6 +133,10 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
this.panelMode = this.data.panelMode;
this.userMode = this.data.userMode;
this.alarmFilterConfig = this.data.alarmFilterConfig;
this.initialAlarmFilterConfig = this.data.initialAlarmFilterConfig;
if (this.panelMode && !this.initialAlarmFilterConfig) {
this.initialAlarmFilterConfig = deepClone(this.alarmFilterConfig);
}
}
this.alarmFilterConfigForm = this.fb.group({
statusList: [null, []],
@ -169,6 +178,9 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
writeValue(alarmFilterConfig?: AlarmFilterConfig): void {
this.alarmFilterConfig = alarmFilterConfig;
if (!this.initialAlarmFilterConfig && alarmFilterConfig) {
this.initialAlarmFilterConfig = deepClone(alarmFilterConfig);
}
this.updateButtonDisplayValue();
this.updateAlarmConfigForm(alarmFilterConfig);
}
@ -214,6 +226,7 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
update() {
this.alarmConfigUpdated(this.alarmFilterConfigForm.value);
this.alarmFilterConfigForm.markAsPristine();
if (this.panelMode) {
this.panelResult = this.alarmFilterConfig;
}
@ -224,6 +237,25 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
}
}
reset() {
if (this.initialAlarmFilterConfig) {
if (this.buttonMode || this.panelMode) {
const alarmFilterConfig = this.alarmFilterConfigFromFormValue(this.alarmFilterConfigForm.value);
if (!alarmFilterConfigEquals(alarmFilterConfig, this.initialAlarmFilterConfig)) {
this.updateAlarmConfigForm(this.initialAlarmFilterConfig);
this.alarmFilterConfigForm.markAsDirty();
}
} else {
if (!alarmFilterConfigEquals(this.alarmFilterConfig, this.initialAlarmFilterConfig)) {
this.alarmFilterConfig = this.initialAlarmFilterConfig;
this.updateButtonDisplayValue();
this.updateAlarmConfigForm(this.alarmFilterConfig);
this.propagateChange(this.alarmFilterConfig);
}
}
}
}
public alarmTypeList(): string[] {
return this.alarmFilterConfigForm.get('typeList').value;
}
@ -270,7 +302,13 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
}
private alarmConfigUpdated(formValue: any) {
this.alarmFilterConfig = {
this.alarmFilterConfig = this.alarmFilterConfigFromFormValue(formValue);
this.updateButtonDisplayValue();
this.propagateChange(this.alarmFilterConfig);
}
private alarmFilterConfigFromFormValue(formValue: any): AlarmFilterConfig {
return {
statusList: formValue.statusList,
severityList: formValue.severityList,
typeList: formValue.typeList,
@ -278,8 +316,6 @@ export class AlarmFilterConfigComponent implements OnInit, OnDestroy, ControlVal
assignedToCurrentUser: formValue.assigneeId === AlarmAssigneeOption.currentUser,
assigneeId: formValue.assigneeId?.id ? formValue.assigneeId : null
};
this.updateButtonDisplayValue();
this.propagateChange(this.alarmFilterConfig);
}
private updateButtonDisplayValue() {

11
ui-ngx/src/app/modules/home/components/widget/config/basic/alarm/alarms-table-basic-config.component.html

@ -19,8 +19,15 @@
<tb-timewindow-config-panel formControlName="timewindowConfig">
</tb-timewindow-config-panel>
<div class="tb-widget-config-panel">
<div class="tb-widget-config-panel-title" translate>alarm.filter</div>
<tb-alarm-filter-config buttonMode="false" formControlName="alarmFilterConfig"></tb-alarm-filter-config>
<div fxLayout="row" fxLayoutAlign="space-between center">
<div class="tb-widget-config-panel-title" translate>alarm.filter</div>
<button mat-button color="primary"
(click)="alarmFilterConfig.reset()">
{{ 'action.reset' | translate }}
</button>
</div>
<tb-alarm-filter-config #alarmFilterConfig buttonMode="false" formControlName="alarmFilterConfig"
[initialAlarmFilterConfig]="{}"></tb-alarm-filter-config>
</div>
<tb-datasources
[configMode]="basicMode"

1
ui-ngx/src/app/modules/home/components/widget/config/datasource.component.html

@ -38,6 +38,7 @@
datasourceFormGroup.get('type').value === datasourceType.alarmCount ? datasourceFormGroup.get('type').value : ''">
<tb-alarm-filter-config *ngIf="datasourceFormGroup.get('type').value === datasourceType.alarmCount"
propagatedFilter="false"
[initialAlarmFilterConfig]="{ statusList: [alarmSearchStatus.ACTIVE] }"
style="height: 56px; margin-bottom: 22px;"
formControlName="alarmFilterConfig"></tb-alarm-filter-config>
<tb-entity-autocomplete *ngIf="datasourceFormGroup.get('type').value === datasourceType.device"

2
ui-ngx/src/app/modules/home/components/widget/config/datasource.component.ts

@ -154,6 +154,8 @@ export class DatasourceComponent implements ControlValueAccessor, OnInit, Valida
datasourceTypes: Array<DatasourceType> = [];
datasourceTypesTranslations = datasourceTypeTranslationMap;
alarmSearchStatus = AlarmSearchStatus;
datasourceFormGroup: UntypedFormGroup;
private propagateChange = (_val: any) => {};

7
ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.ts

@ -384,7 +384,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
this.pageSizeOptions = [this.defaultPageSize, this.defaultPageSize * 2, this.defaultPageSize * 3];
this.pageLink.pageSize = this.displayPagination ? this.defaultPageSize : 1024;
const alarmFilter = this.entityService.resolveAlarmFilter(this.widgetConfig.alarmFilterConfig);
const alarmFilter = this.entityService.resolveAlarmFilter(this.widgetConfig.alarmFilterConfig, false);
this.pageLink = {...this.pageLink, ...alarmFilter};
this.noDataDisplayMessageText =
@ -624,7 +624,8 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
searchPropagatedAlarms: this.pageLink.searchPropagatedAlarms,
assignedToCurrentUser,
assigneeId
}
},
initialAlarmFilterConfig: deepClone(this.widgetConfig.alarmFilterConfig)
} as AlarmFilterConfigData
},
{
@ -638,7 +639,7 @@ export class AlarmsTableWidgetComponent extends PageComponent implements OnInit,
componentRef.onDestroy(() => {
if (componentRef.instance.panelResult) {
const result = componentRef.instance.panelResult;
const alarmFilter = this.entityService.resolveAlarmFilter(result);
const alarmFilter = this.entityService.resolveAlarmFilter(result, false);
this.pageLink = {...this.pageLink, ...alarmFilter};
this.resetPageIndex();
this.updateData();

12
ui-ngx/src/app/modules/home/components/widget/widget-config.component.html

@ -207,8 +207,16 @@
formControlName="timewindowConfig">
</tb-timewindow-config-panel>
</ng-container>
<div *ngIf="widgetType === widgetTypes.alarm" [formGroup]="dataSettings" class="tb-widget-config-panel" fxLayout="column" fxLayoutAlign="center">
<tb-alarm-filter-config buttonMode="false" formControlName="alarmFilterConfig"></tb-alarm-filter-config>
<div *ngIf="widgetType === widgetTypes.alarm" [formGroup]="dataSettings" class="tb-widget-config-panel">
<div fxLayout="row" fxLayoutAlign="space-between center">
<div class="tb-widget-config-panel-title" translate>alarm.filter</div>
<button mat-button color="primary"
(click)="alarmFilterConfig.reset()">
{{ 'action.reset' | translate }}
</button>
</div>
<tb-alarm-filter-config #alarmFilterConfig buttonMode="false"
formControlName="alarmFilterConfig" [initialAlarmFilterConfig]="{}"></tb-alarm-filter-config>
</div>
<div *ngIf="widgetType !== widgetTypes.rpc &&
widgetType !== widgetTypes.alarm &&

40
ui-ngx/src/app/shared/models/query/query.models.ts

@ -22,7 +22,15 @@ import { EntityInfo } from '@shared/models/entity.models';
import { EntityType } from '@shared/models/entity-type.models';
import { DataKey, Datasource, DatasourceType } from '@shared/models/widget.models';
import { PageData } from '@shared/models/page/page-data';
import { isDefined, isEqual } from '@core/utils';
import {
isArraysEqualIgnoreUndefined,
isDefined,
isDefinedAndNotNull,
isEmpty,
isEqual,
isEqualIgnoreUndefined,
isUndefinedOrNull
} from '@core/utils';
import { TranslateService } from '@ngx-translate/core';
import { AlarmInfo, AlarmSearchStatus, AlarmSeverity } from '../alarm.models';
import { Filter } from '@material-ui/icons';
@ -721,6 +729,36 @@ export interface AlarmFilterConfig extends AlarmFilter {
assignedToCurrentUser?: boolean;
}
export const alarmFilterConfigEquals = (filter1?: AlarmFilterConfig, filter2?: AlarmFilterConfig): boolean => {
if (filter1 === filter2) {
return true;
}
if ((isUndefinedOrNull(filter1) || isEmpty(filter1)) && (isUndefinedOrNull(filter2) || isEmpty(filter2))) {
return true;
} else if (isDefinedAndNotNull(filter1) && isDefinedAndNotNull(filter2)) {
if (!isArraysEqualIgnoreUndefined(filter1.typeList, filter2.typeList)) {
return false;
}
if (!isArraysEqualIgnoreUndefined(filter1.statusList, filter2.statusList)) {
return false;
}
if (!isArraysEqualIgnoreUndefined(filter1.severityList, filter2.severityList)) {
return false;
}
if (!isEqualIgnoreUndefined(filter1.assigneeId, filter2.assigneeId)) {
return false;
}
if (!isEqualIgnoreUndefined(filter1.searchPropagatedAlarms, filter2.searchPropagatedAlarms)) {
return false;
}
if (!isEqualIgnoreUndefined(filter1.assignedToCurrentUser, filter2.assignedToCurrentUser)) {
return false;
}
return true;
}
return false;
};
export type AlarmCountQuery = EntityCountQuery & AlarmFilter;
export type AlarmDataPageLink = EntityDataPageLink & AlarmFilter;

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

@ -67,7 +67,8 @@
"more": "More",
"less": "Less",
"skip": "Skip",
"send": "Send"
"send": "Send",
"reset": "Reset"
},
"aggregation": {
"aggregation": "Aggregation",

Loading…
Cancel
Save