Browse Source

UI: Device profile alarm rules improvements

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
c4e6721596
  1. 3
      ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html
  2. 2
      ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts
  3. 1
      ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html
  4. 1
      ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts
  5. 5
      ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts
  6. 1
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html
  7. 5
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts
  8. 2
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html
  9. 14
      ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts
  10. 15
      ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html
  11. 2
      ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts
  12. 1
      ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.html
  13. 1
      ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts
  14. 126
      ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.html
  15. 13
      ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.scss
  16. 21
      ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts
  17. 3
      ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html
  18. 2
      ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts
  19. 3
      ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html
  20. 2
      ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts
  21. 1
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html
  22. 3
      ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html
  23. 17
      ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts
  24. 24
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html
  25. 33
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts
  26. 3
      ui-ngx/src/app/shared/models/query/query.models.ts
  27. 3
      ui-ngx/src/assets/locale/locale.constant-en_US.json

3
ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html

@ -24,7 +24,8 @@
</mat-option>
</mat-select>
</mat-form-field>
<tb-filter-predicate-value fxFlex="60"
<tb-filter-predicate-value [allowUserDynamicSource]="allowUserDynamicSource"
fxFlex="60"
[valueType]="valueTypeEnum.BOOLEAN"
formControlName="value">
</tb-filter-predicate-value>

2
ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts

@ -39,6 +39,8 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On
@Input() disabled: boolean;
@Input() allowUserDynamicSource = true;
valueTypeEnum = EntityKeyValueType;
booleanFilterPredicateFormGroup: FormGroup;

1
ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html

@ -38,6 +38,7 @@
<tb-filter-predicate-list
[valueType]="data.valueType"
[displayUserParameters]="data.displayUserParameters"
[allowUserDynamicSource]="data.allowUserDynamicSource"
[operation]="complexFilterFormGroup.get('operation').value"
[key]="data.key"
formControlName="predicates">

1
ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts

@ -36,6 +36,7 @@ export interface ComplexFilterPredicateDialogData {
isAdd: boolean;
valueType: EntityKeyValueType;
displayUserParameters: boolean;
allowUserDynamicSource: boolean;
}
@Component({

5
ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts

@ -50,6 +50,8 @@ export class ComplexFilterPredicateComponent implements ControlValueAccessor, On
@Input() displayUserParameters = true;
@Input() allowUserDynamicSource = true;
private propagateChange = null;
private complexFilterPredicate: ComplexFilterPredicateInfo;
@ -86,7 +88,8 @@ export class ComplexFilterPredicateComponent implements ControlValueAccessor, On
valueType: this.valueType,
isAdd: false,
key: this.key,
displayUserParameters: this.displayUserParameters
displayUserParameters: this.displayUserParameters,
allowUserDynamicSource: this.allowUserDynamicSource
}
}).afterClosed().subscribe(
(result) => {

1
ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html

@ -52,6 +52,7 @@
fxFlex
[valueType]="valueType"
[displayUserParameters]="displayUserParameters"
[allowUserDynamicSource]="allowUserDynamicSource"
[key]="key"
[formControl]="predicateControl">
</tb-filter-predicate>

5
ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts

@ -64,6 +64,8 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni
@Input() displayUserParameters = true;
@Input() allowUserDynamicSource = true;
filterListFormGroup: FormGroup;
valueTypeEnum = EntityKeyValueType;
@ -156,7 +158,8 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni
valueType: this.valueType,
key: this.key,
isAdd: true,
displayUserParameters: this.displayUserParameters
displayUserParameters: this.displayUserParameters,
allowUserDynamicSource: this.allowUserDynamicSource
}
}).afterClosed().pipe(
map((result) => {

2
ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html

@ -55,7 +55,7 @@
{{'filter.no-dynamic-value' | translate}}
</mat-option>
<mat-option *ngFor="let sourceType of dynamicValueSourceTypes" [value]="sourceType">
{{dynamicValueSourceTypeTranslations.get(dynamicValueSourceTypeEnum[sourceType]) | translate}}
{{dynamicValueSourceTypeTranslations.get(sourceType) | translate}}
</mat-option>
</mat-select>
</mat-form-field>

14
ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts

@ -46,13 +46,23 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
@Input() disabled: boolean;
@Input()
set allowUserDynamicSource(allow: boolean) {
this.dynamicValueSourceTypes = [DynamicValueSourceType.CURRENT_TENANT,
DynamicValueSourceType.CURRENT_CUSTOMER];
if (allow) {
this.dynamicValueSourceTypes.push(DynamicValueSourceType.CURRENT_USER);
}
}
@Input()
valueType: EntityKeyValueType;
valueTypeEnum = EntityKeyValueType;
dynamicValueSourceTypes = Object.keys(DynamicValueSourceType);
dynamicValueSourceTypeEnum = DynamicValueSourceType;
dynamicValueSourceTypes: DynamicValueSourceType[] = [DynamicValueSourceType.CURRENT_TENANT,
DynamicValueSourceType.CURRENT_CUSTOMER, DynamicValueSourceType.CURRENT_USER];
dynamicValueSourceTypeTranslations = dynamicValueSourceTypeTranslationMap;
filterPredicateValueFormGroup: FormGroup;

15
ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html

@ -19,20 +19,27 @@
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" [formGroup]="filterPredicateFormGroup">
<div fxFlex fxLayout="column" [ngSwitch]="type">
<ng-template [ngSwitchCase]="filterPredicateType.STRING">
<tb-string-filter-predicate formControlName="predicate">
<tb-string-filter-predicate
[allowUserDynamicSource]="allowUserDynamicSource"
formControlName="predicate">
</tb-string-filter-predicate>
</ng-template>
<ng-template [ngSwitchCase]="filterPredicateType.NUMERIC">
<tb-numeric-filter-predicate [valueType]="valueType"
formControlName="predicate">
<tb-numeric-filter-predicate
[allowUserDynamicSource]="allowUserDynamicSource"
[valueType]="valueType"
formControlName="predicate">
</tb-numeric-filter-predicate>
</ng-template>
<ng-template [ngSwitchCase]="filterPredicateType.BOOLEAN">
<tb-boolean-filter-predicate formControlName="predicate">
<tb-boolean-filter-predicate
[allowUserDynamicSource]="allowUserDynamicSource"
formControlName="predicate">
</tb-boolean-filter-predicate>
</ng-template>
<ng-template [ngSwitchCase]="filterPredicateType.COMPLEX">
<tb-complex-filter-predicate
[allowUserDynamicSource]="allowUserDynamicSource"
[key]="key"
[valueType]="valueType"
[displayUserParameters]="displayUserParameters"

2
ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.ts

@ -43,6 +43,8 @@ export class FilterPredicateComponent implements ControlValueAccessor, OnInit {
@Input() displayUserParameters = true;
@Input() allowUserDynamicSource = true;
filterPredicateFormGroup: FormGroup;
type: FilterPredicateType;

1
ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.html

@ -70,6 +70,7 @@
</mat-form-field>
</section>
<tb-filter-predicate-list *ngIf="keyFilterFormGroup.get('valueType').value"
[allowUserDynamicSource]="data.allowUserDynamicSource"
[displayUserParameters]="data.displayUserParameters"
[valueType]="keyFilterFormGroup.get('valueType').value"
[key]="keyFilterFormGroup.get('key.key').value"

1
ui-ngx/src/app/modules/home/components/filter/key-filter-dialog.component.ts

@ -40,6 +40,7 @@ export interface KeyFilterDialogData {
keyFilter: KeyFilterInfo;
isAdd: boolean;
displayUserParameters: boolean;
allowUserDynamicSource: boolean;
readonly: boolean;
telemetryKeysOnly: boolean;
}

126
ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.html

@ -16,65 +16,77 @@
-->
<section fxLayout="column" [formGroup]="keyFilterListFormGroup">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div translate>filter.key-filters</div>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="row">
<span fxFlex="8"></span>
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="92">
<label fxFlex translate class="tb-title no-padding">filter.key-name</label>
<label fxFlex translate class="tb-title no-padding">filter.key-type.key-type</label>
<span [fxShow]="!disabled" style="min-width: 80px;">&nbsp;</span>
<span [fxShow]="disabled" style="min-width: 40px;">&nbsp;</span>
</div>
</div>
<mat-divider></mat-divider>
<div class="key-filter-list">
<div fxLayout="row" fxLayoutAlign="start center" style="max-height: 40px;"
formArrayName="keyFilters"
*ngFor="let keyFilterControl of keyFiltersFormArray().controls; let $index = index">
<div fxFlex="8" class="filters-operation">
<span *ngIf="$index > 0" translate>filter.operation.and</span>
<mat-accordion [multi]="true">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div translate>filter.key-filters</div>
</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="row">
<span fxFlex="8"></span>
<div fxLayout="row" fxLayoutAlign="start center" fxFlex="92">
<label fxFlex translate class="tb-title no-padding">filter.key-name</label>
<label fxFlex translate class="tb-title no-padding">filter.key-type.key-type</label>
<span [fxShow]="!disabled" style="min-width: 80px;">&nbsp;</span>
<span [fxShow]="disabled" style="min-width: 40px;">&nbsp;</span>
</div>
<div fxLayout="column" fxFlex="92">
<div fxLayout="row" fxLayoutAlign="start center" fxFlex>
<div fxFlex>{{ keyFilterControl.value.key.key }}</div>
<div fxFlex translate>{{ entityKeyTypeTranslations.get(keyFilterControl.value.key.type) }}</div>
<button mat-icon-button color="primary"
type="button"
(click)="editKeyFilter($index)"
matTooltip="{{ (disabled ? 'filter.key-filter' : 'filter.edit-key-filter') | translate }}"
matTooltipPosition="above">
<mat-icon>{{disabled ? 'more_vert' : 'edit'}}</mat-icon>
</button>
<button mat-icon-button color="primary"
[fxShow]="!disabled"
type="button"
(click)="removeKeyFilter($index)"
matTooltip="{{ 'filter.remove-key-filter' | translate }}"
matTooltipPosition="above">
<mat-icon>close</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
<div class="key-filter-list">
<div fxLayout="row" fxLayoutAlign="start center" style="max-height: 40px;"
formArrayName="keyFilters"
*ngFor="let keyFilterControl of keyFiltersFormArray().controls; let $index = index">
<div fxFlex="8" class="filters-operation">
<span *ngIf="$index > 0" translate>filter.operation.and</span>
</div>
<div fxLayout="column" fxFlex="92">
<div fxLayout="row" fxLayoutAlign="start center" fxFlex>
<div fxFlex>{{ keyFilterControl.value.key.key }}</div>
<div fxFlex translate>{{ entityKeyTypeTranslations.get(keyFilterControl.value.key.type) }}</div>
<button mat-icon-button color="primary"
type="button"
(click)="editKeyFilter($index)"
matTooltip="{{ (disabled ? 'filter.key-filter' : 'filter.edit-key-filter') | translate }}"
matTooltipPosition="above">
<mat-icon>{{disabled ? 'more_vert' : 'edit'}}</mat-icon>
</button>
<button mat-icon-button color="primary"
[fxShow]="!disabled"
type="button"
(click)="removeKeyFilter($index)"
matTooltip="{{ 'filter.remove-key-filter' | translate }}"
matTooltipPosition="above">
<mat-icon>close</mat-icon>
</button>
</div>
<mat-divider></mat-divider>
</div>
<mat-divider></mat-divider>
</div>
<span [fxShow]="!keyFiltersFormArray().length"
fxLayoutAlign="center center" [ngClass]="{'disabled': disabled}"
class="no-data-found" translate>filter.no-key-filters</span>
</div>
<div style="margin-top: 16px;">
<button mat-button mat-raised-button color="primary"
[fxShow]="!disabled"
(click)="addKeyFilter()"
type="button"
matTooltip="{{ 'filter.add-key-filter' | translate }}"
matTooltipPosition="above">
{{ 'filter.add-key-filter' | translate }}
</button>
</div>
</mat-expansion-panel>
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div translate>filter.preview</div>
</mat-panel-title>
</mat-expansion-panel-header>
<div class="tb-filter-preview">
<tb-filter-text [formControl]="keyFiltersControl"></tb-filter-text>
</div>
<span [fxShow]="!keyFiltersFormArray().length"
fxLayoutAlign="center center" [ngClass]="{'disabled': disabled}"
class="no-data-found" translate>filter.no-key-filters</span>
</div>
<div style="margin-top: 16px;">
<button mat-button mat-raised-button color="primary"
[fxShow]="!disabled"
(click)="addKeyFilter()"
type="button"
matTooltip="{{ 'filter.add-key-filter' | translate }}"
matTooltipPosition="above">
{{ 'filter.add-key-filter' | translate }}
</button>
</div>
</mat-expansion-panel>
</mat-expansion-panel>
</mat-accordion>
</section>

13
ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.scss

@ -26,4 +26,17 @@
color: #666;
font-weight: 500;
}
.tb-filter-preview {
padding: 8px;
border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px;
}
}
:host ::ng-deep {
.tb-filter-preview {
.tb-filter-text {
max-height: 200px;
}
}
}

21
ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts

@ -19,13 +19,18 @@ import {
AbstractControl,
ControlValueAccessor,
FormArray,
FormBuilder,
FormBuilder, FormControl,
FormGroup,
NG_VALUE_ACCESSOR,
Validators
} from '@angular/forms';
import { Observable, Subscription } from 'rxjs';
import { EntityKeyType, entityKeyTypeTranslationMap, KeyFilterInfo } from '@shared/models/query/query.models';
import {
EntityKeyType,
entityKeyTypeTranslationMap,
KeyFilter,
KeyFilterInfo, keyFilterInfosToKeyFilters
} from '@shared/models/query/query.models';
import { MatDialog } from '@angular/material/dialog';
import { deepClone } from '@core/utils';
import { KeyFilterDialogComponent, KeyFilterDialogData } from '@home/components/filter/key-filter-dialog.component';
@ -48,12 +53,16 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
@Input() displayUserParameters = true;
@Input() allowUserDynamicSource = true;
@Input() telemetryKeysOnly = false;
keyFilterListFormGroup: FormGroup;
entityKeyTypeTranslations = entityKeyTypeTranslationMap;
keyFiltersControl: FormControl;
private propagateChange = null;
private valueChangeSubscription: Subscription = null;
@ -66,6 +75,7 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
this.keyFilterListFormGroup = this.fb.group({});
this.keyFilterListFormGroup.addControl('keyFilters',
this.fb.array([]));
this.keyFiltersControl = this.fb.control(null);
}
keyFiltersFormArray(): FormArray {
@ -83,8 +93,10 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
this.disabled = isDisabled;
if (this.disabled) {
this.keyFilterListFormGroup.disable({emitEvent: false});
this.keyFiltersControl.disable({emitEvent: false});
} else {
this.keyFilterListFormGroup.enable({emitEvent: false});
this.keyFiltersControl.enable({emitEvent: false});
}
}
@ -107,6 +119,8 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
} else {
this.keyFilterListFormGroup.enable({emitEvent: false});
}
const keyFiltersArray = keyFilterInfosToKeyFilters(keyFilters);
this.keyFiltersControl.patchValue(keyFiltersArray, {emitEvent: false});
}
public removeKeyFilter(index: number) {
@ -155,6 +169,7 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
isAdd,
readonly: this.disabled,
displayUserParameters: this.displayUserParameters,
allowUserDynamicSource: this.allowUserDynamicSource,
telemetryKeysOnly: this.telemetryKeysOnly
}
}).afterClosed();
@ -167,5 +182,7 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
} else {
this.propagateChange(null);
}
const keyFiltersArray = keyFilterInfosToKeyFilters(keyFilters);
this.keyFiltersControl.patchValue(keyFiltersArray, {emitEvent: false});
}
}

3
ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html

@ -24,7 +24,8 @@
</mat-option>
</mat-select>
</mat-form-field>
<tb-filter-predicate-value fxFlex="60"
<tb-filter-predicate-value [allowUserDynamicSource]="allowUserDynamicSource"
fxFlex="60"
[valueType]="valueType"
formControlName="value">
</tb-filter-predicate-value>

2
ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts

@ -40,6 +40,8 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On
@Input() disabled: boolean;
@Input() allowUserDynamicSource = true;
@Input() valueType: EntityKeyValueType;
numericFilterPredicateFormGroup: FormGroup;

3
ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html

@ -28,7 +28,8 @@
<mat-checkbox fxLayout="row" fxLayoutAlign="center" formControlName="ignoreCase" style="min-width: 70px;">
</mat-checkbox>
</div>
<tb-filter-predicate-value fxFlex="60"
<tb-filter-predicate-value [allowUserDynamicSource]="allowUserDynamicSource"
fxFlex="60"
[valueType]="valueTypeEnum.STRING"
formControlName="value">
</tb-filter-predicate-value>

2
ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts

@ -40,6 +40,8 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI
@Input() disabled: boolean;
@Input() allowUserDynamicSource = true;
valueTypeEnum = EntityKeyValueType;
stringFilterPredicateFormGroup: FormGroup;

1
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html

@ -32,6 +32,7 @@
<div fxFlex fxLayout="column">
<tb-key-filter-list
[displayUserParameters]="false"
[allowUserDynamicSource]="false"
[telemetryKeysOnly]="true"
formControlName="keyFilters">
</tb-key-filter-list>

3
ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html

@ -25,7 +25,8 @@
<mat-select formControlName="severity"
required
placeholder="{{ 'device-profile.select-alarm-severity' | translate }}">
<mat-option *ngFor="let alarmSeverity of alarmSeverities" [value]="alarmSeverity">
<mat-option *ngFor="let alarmSeverity of alarmSeverities" [value]="alarmSeverity"
[disabled]="isDisabledSeverity(alarmSeverityEnum[alarmSeverity], $index)">
{{ alarmSeverityTranslationMap.get(alarmSeverityEnum[alarmSeverity]) | translate }}
</mat-option>
</mat-select>

17
ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts

@ -61,6 +61,8 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
createAlarmRulesFormGroup: FormGroup;
private usedSeverities: AlarmSeverity[] = [];
private valueChangeSubscription: Subscription = null;
private propagateChange = (v: any) => { };
@ -121,6 +123,7 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
this.valueChangeSubscription = this.createAlarmRulesFormGroup.valueChanges.subscribe(() => {
this.updateModel();
});
this.updateUsedSeverities();
}
public removeCreateAlarmRule(index: number) {
@ -149,12 +152,26 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
};
}
public isDisabledSeverity(severity: AlarmSeverity, index: number): boolean {
const usedIndex = this.usedSeverities.indexOf(severity);
return usedIndex > -1 && usedIndex !== index;
}
private updateUsedSeverities() {
this.usedSeverities = [];
const value: {severity: string, alarmRule: AlarmRule}[] = this.createAlarmRulesFormGroup.get('createAlarmRules').value;
value.forEach((rule, index) => {
this.usedSeverities[index] = AlarmSeverity[rule.severity];
});
}
private updateModel() {
const value: {severity: string, alarmRule: AlarmRule}[] = this.createAlarmRulesFormGroup.get('createAlarmRules').value;
const createAlarmRules: {[severity: string]: AlarmRule} = {};
value.forEach(v => {
createAlarmRules[v.severity] = v.alarmRule;
});
this.updateUsedSeverities();
this.propagateChange(createAlarmRules);
}
}

24
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html

@ -26,6 +26,7 @@
<mat-form-field floatLabel="always"
style="width: 600px;"
[fxShow]="expanded"
(keydown)="!disabled ? $event.stopPropagation() : null;"
(click)="!disabled ? $event.stopPropagation() : null;">
<mat-label>{{'device-profile.alarm-type' | translate}}</mat-label>
<input required matInput formControlName="alarmType" placeholder="Enter alarm type">
@ -90,9 +91,28 @@
</div>
</mat-panel-title>
</mat-expansion-panel-header>
<mat-checkbox formControlName="propagate" style="padding-bottom: 16px;">
<mat-checkbox formControlName="propagate" style="display: block; padding-bottom: 16px;">
{{ 'device-profile.propagate-alarm' | translate }}
</mat-checkbox>
<div>TODO: Propagate relation types</div>
<section *ngIf="alarmFormGroup.get('propagate').value === true">
<mat-form-field floatLabel="always" class="mat-block">
<mat-label translate>device-profile.alarm-rule-relation-types-list</mat-label>
<mat-chip-list #relationTypesChipList [disabled]="disabled">
<mat-chip
*ngFor="let key of alarmFormGroup.get('propagateRelationTypes').value;"
(removed)="removeRelationType(key)">
{{key}}
<mat-icon matChipRemove>close</mat-icon>
</mat-chip>
<input matInput type="text" placeholder="{{'device-profile.alarm-rule-relation-types-list' | translate}}"
style="max-width: 200px;"
[matChipInputFor]="relationTypesChipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
(matChipInputTokenEnd)="addRelationType($event)"
[matChipInputAddOnBlur]="true">
</mat-chip-list>
<mat-hint innerHTML="{{ 'device-profile.alarm-rule-relation-types-list-hint' | translate }}"></mat-hint>
</mat-form-field>
</section>
</mat-expansion-panel>
</mat-expansion-panel>

33
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts

@ -27,6 +27,8 @@ import {
} from '@angular/forms';
import { AlarmRule, DeviceProfileAlarm } from '@shared/models/device.models';
import { MatDialog } from '@angular/material/dialog';
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
import { MatChipInputEvent } from '@angular/material/chips';
@Component({
selector: 'tb-device-profile-alarm',
@ -53,6 +55,8 @@ export class DeviceProfileAlarmComponent implements ControlValueAccessor, OnInit
@Output()
removeAlarm = new EventEmitter();
separatorKeysCodes = [ENTER, COMMA, SEMICOLON];
expanded = false;
private modelValue: DeviceProfileAlarm;
@ -124,6 +128,35 @@ export class DeviceProfileAlarmComponent implements ControlValueAccessor, OnInit
};
}
removeRelationType(key: string): void {
const keys: string[] = this.alarmFormGroup.get('propagateRelationTypes').value;
const index = keys.indexOf(key);
if (index >= 0) {
keys.splice(index, 1);
this.alarmFormGroup.get('propagateRelationTypes').setValue(keys, {emitEvent: true});
}
}
addRelationType(event: MatChipInputEvent): void {
const input = event.input;
let value = event.value;
if ((value || '').trim()) {
value = value.trim();
let keys: string[] = this.alarmFormGroup.get('propagateRelationTypes').value;
if (!keys || keys.indexOf(value) === -1) {
if (!keys) {
keys = [];
}
keys.push(value);
this.alarmFormGroup.get('propagateRelationTypes').setValue(keys, {emitEvent: true});
}
}
if (input) {
input.value = '';
}
}
private updateModel() {
const value = this.alarmFormGroup.value;
this.modelValue = {...this.modelValue, ...value};

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

@ -453,6 +453,9 @@ function simpleKeyFilterPredicateToText(translate: TranslateService,
}
export function keyFilterInfosToKeyFilters(keyFilterInfos: Array<KeyFilterInfo>): Array<KeyFilter> {
if (!keyFilterInfos) {
return [];
}
const keyFilters: Array<KeyFilter> = [];
for (const keyFilterInfo of keyFilterInfos) {
const key = keyFilterInfo.key;

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

@ -834,6 +834,8 @@
"advanced-settings": "Advanced settings",
"alarm-rule-details": "Details",
"propagate-alarm": "Propagate alarm",
"alarm-rule-relation-types-list": "Relation types to propagate",
"alarm-rule-relation-types-list-hint": "If Propagate relation types are not selected, alarms will be propagated without filtering by relation type.",
"alarm-details": "Alarm details",
"alarm-rule-condition": "Alarm rule condition",
"enter-alarm-rule-condition-prompt": "Please add alarm rule condition",
@ -1302,6 +1304,7 @@
"ignore-case": "ignore case",
"value": "Value",
"remove-filter": "Remove filter",
"preview": "Filter preview",
"no-filters": "No filters configured",
"add-filter": "Add filter",
"add-complex-filter": "Add complex filter",

Loading…
Cancel
Save