From c4e67215969501693d89bc6a8659dbadc98fb458 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Mon, 14 Sep 2020 15:33:01 +0300 Subject: [PATCH] UI: Device profile alarm rules improvements --- .../boolean-filter-predicate.component.html | 3 +- .../boolean-filter-predicate.component.ts | 2 + ...lex-filter-predicate-dialog.component.html | 1 + ...mplex-filter-predicate-dialog.component.ts | 1 + .../complex-filter-predicate.component.ts | 5 +- .../filter-predicate-list.component.html | 1 + .../filter/filter-predicate-list.component.ts | 5 +- .../filter-predicate-value.component.html | 2 +- .../filter-predicate-value.component.ts | 14 +- .../filter/filter-predicate.component.html | 15 ++- .../filter/filter-predicate.component.ts | 2 + .../filter/key-filter-dialog.component.html | 1 + .../filter/key-filter-dialog.component.ts | 1 + .../filter/key-filter-list.component.html | 126 ++++++++++-------- .../filter/key-filter-list.component.scss | 13 ++ .../filter/key-filter-list.component.ts | 21 ++- .../numeric-filter-predicate.component.html | 3 +- .../numeric-filter-predicate.component.ts | 2 + .../string-filter-predicate.component.html | 3 +- .../string-filter-predicate.component.ts | 2 + ...arm-rule-key-filters-dialog.component.html | 1 + .../alarm/create-alarm-rules.component.html | 3 +- .../alarm/create-alarm-rules.component.ts | 17 +++ .../alarm/device-profile-alarm.component.html | 24 +++- .../alarm/device-profile-alarm.component.ts | 33 +++++ .../app/shared/models/query/query.models.ts | 3 + .../assets/locale/locale.constant-en_US.json | 3 + 27 files changed, 233 insertions(+), 74 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html index 5e4c597447..d05e4b3775 100644 --- a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html @@ -24,7 +24,8 @@ - diff --git a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts index e7e1dd5c81..aa264697b6 100644 --- a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts +++ b/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; diff --git a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html index a2e01977ea..4502e9da67 100644 --- a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.html @@ -38,6 +38,7 @@ diff --git a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts index 623ca4f968..8fe9e5a1b6 100644 --- a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate-dialog.component.ts +++ b/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({ diff --git a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts index 654eecdefd..87bad30d5a 100644 --- a/ui-ngx/src/app/modules/home/components/filter/complex-filter-predicate.component.ts +++ b/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) => { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 2da9a68e4d..ffef5e2349 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/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"> diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts index c5eb501b16..2e59e85123 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.ts +++ b/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) => { diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html index e9e38c71f5..524285ea3f 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html @@ -55,7 +55,7 @@ {{'filter.no-dynamic-value' | translate}} - {{dynamicValueSourceTypeTranslations.get(dynamicValueSourceTypeEnum[sourceType]) | translate}} + {{dynamicValueSourceTypeTranslations.get(sourceType) | translate}} diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts index 548137976e..aa430e596e 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts +++ b/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; diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html index abe231219b..3b9d89008b 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.component.html @@ -19,20 +19,27 @@
- + - + - +
- - - -
filter.key-filters
-
-
-
- -
- - -   -   -
-
- -
-
-
- filter.operation.and + + + + +
filter.key-filters
+
+
+
+ +
+ + +   +  
-
-
-
{{ keyFilterControl.value.key.key }}
-
{{ entityKeyTypeTranslations.get(keyFilterControl.value.key.type) }}
- - +
+ +
+
+
+ filter.operation.and +
+
+
+
{{ keyFilterControl.value.key.key }}
+
{{ entityKeyTypeTranslations.get(keyFilterControl.value.key.type) }}
+ + +
+
-
+ filter.no-key-filters +
+
+ +
+ + + + +
filter.preview
+
+
+
+
- filter.no-key-filters -
-
- -
- + +
diff --git a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.scss b/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.scss index 3951b5d640..bc47f04915 100644 --- a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.scss +++ b/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; + } + } } diff --git a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts b/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts index f78effb739..2779a35be9 100644 --- a/ui-ngx/src/app/modules/home/components/filter/key-filter-list.component.ts +++ b/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}); } } diff --git a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html index 7a4a9c552b..71cbbd0335 100644 --- a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html @@ -24,7 +24,8 @@ - diff --git a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts index e9e4f89c3b..32d5779c63 100644 --- a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts +++ b/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; diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html index ef9f2c01e7..92d470c6b8 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html @@ -28,7 +28,8 @@
- diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts index f115748e48..dffd52b274 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts +++ b/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; diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html index 3712ddff39..26defe62ff 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-key-filters-dialog.component.html @@ -32,6 +32,7 @@
diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html index 40b4fd0c35..c3ac14c757 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html @@ -25,7 +25,8 @@ - + {{ alarmSeverityTranslationMap.get(alarmSeverityEnum[alarmSeverity]) | translate }} diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts index 50604b9eab..caebff80b4 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts +++ b/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); } } diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html index f85fdc99d6..d827245abf 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html @@ -26,6 +26,7 @@ {{'device-profile.alarm-type' | translate}} @@ -90,9 +91,28 @@
- + {{ 'device-profile.propagate-alarm' | translate }} -
TODO: Propagate relation types
+
+ + device-profile.alarm-rule-relation-types-list + + + {{key}} + close + + + + + +
diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts index 9ab4e39e27..8befb6204d 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.ts +++ b/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}; diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index e9419a709d..3d3223bf34 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -453,6 +453,9 @@ function simpleKeyFilterPredicateToText(translate: TranslateService, } export function keyFilterInfosToKeyFilters(keyFilterInfos: Array): Array { + if (!keyFilterInfos) { + return []; + } const keyFilters: Array = []; for (const keyFilterInfo of keyFilterInfos) { const key = keyFilterInfo.key; diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 302d62133e..a3b7d8c1d5 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/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",