Commit ce9dcd17c6d94b279358656710295c7002c64afe
Committed by
Andrew Shvayka
1 parent
3cd96432
UI: Add Constant keys in the Device Profile Alarm Rules
Showing
21 changed files
with
96 additions
and
21 deletions
... | ... | @@ -25,6 +25,7 @@ |
25 | 25 | </mat-select> |
26 | 26 | </mat-form-field> |
27 | 27 | <tb-filter-predicate-value [allowUserDynamicSource]="allowUserDynamicSource" |
28 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
28 | 29 | fxFlex="70" |
29 | 30 | [valueType]="valueTypeEnum.BOOLEAN" |
30 | 31 | formControlName="value"> | ... | ... |
... | ... | @@ -41,6 +41,8 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On |
41 | 41 | |
42 | 42 | @Input() allowUserDynamicSource = true; |
43 | 43 | |
44 | + @Input() onlyUserDynamicSource = false; | |
45 | + | |
44 | 46 | valueTypeEnum = EntityKeyValueType; |
45 | 47 | |
46 | 48 | booleanFilterPredicateFormGroup: FormGroup; | ... | ... |
... | ... | @@ -39,6 +39,7 @@ |
39 | 39 | [valueType]="data.valueType" |
40 | 40 | [displayUserParameters]="data.displayUserParameters" |
41 | 41 | [allowUserDynamicSource]="data.allowUserDynamicSource" |
42 | + [onlyUserDynamicSource]="data.onlyUserDynamicSource" | |
42 | 43 | [operation]="complexFilterFormGroup.get('operation').value" |
43 | 44 | [key]="data.key" |
44 | 45 | formControlName="predicates"> | ... | ... |
... | ... | @@ -52,6 +52,8 @@ export class ComplexFilterPredicateComponent implements ControlValueAccessor, On |
52 | 52 | |
53 | 53 | @Input() allowUserDynamicSource = true; |
54 | 54 | |
55 | + @Input() onlyUserDynamicSource = false; | |
56 | + | |
55 | 57 | private propagateChange = null; |
56 | 58 | |
57 | 59 | private complexFilterPredicate: ComplexFilterPredicateInfo; |
... | ... | @@ -89,7 +91,8 @@ export class ComplexFilterPredicateComponent implements ControlValueAccessor, On |
89 | 91 | isAdd: false, |
90 | 92 | key: this.key, |
91 | 93 | displayUserParameters: this.displayUserParameters, |
92 | - allowUserDynamicSource: this.allowUserDynamicSource | |
94 | + allowUserDynamicSource: this.allowUserDynamicSource, | |
95 | + onlyUserDynamicSource: this.onlyUserDynamicSource | |
93 | 96 | } |
94 | 97 | }).afterClosed().subscribe( |
95 | 98 | (result) => { | ... | ... |
... | ... | @@ -53,6 +53,7 @@ |
53 | 53 | [valueType]="valueType" |
54 | 54 | [displayUserParameters]="displayUserParameters" |
55 | 55 | [allowUserDynamicSource]="allowUserDynamicSource" |
56 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
56 | 57 | [key]="key" |
57 | 58 | [formControl]="predicateControl"> |
58 | 59 | </tb-filter-predicate> | ... | ... |
... | ... | @@ -66,6 +66,8 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni |
66 | 66 | |
67 | 67 | @Input() allowUserDynamicSource = true; |
68 | 68 | |
69 | + @Input() onlyUserDynamicSource = false; | |
70 | + | |
69 | 71 | filterListFormGroup: FormGroup; |
70 | 72 | |
71 | 73 | valueTypeEnum = EntityKeyValueType; |
... | ... | @@ -159,7 +161,8 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni |
159 | 161 | key: this.key, |
160 | 162 | isAdd: true, |
161 | 163 | displayUserParameters: this.displayUserParameters, |
162 | - allowUserDynamicSource: this.allowUserDynamicSource | |
164 | + allowUserDynamicSource: this.allowUserDynamicSource, | |
165 | + onlyUserDynamicSource: this.onlyUserDynamicSource | |
163 | 166 | } |
164 | 167 | }).afterClosed().pipe( |
165 | 168 | map((result) => { | ... | ... |
... | ... | @@ -16,7 +16,7 @@ |
16 | 16 | |
17 | 17 | --> |
18 | 18 | <div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" [formGroup]="filterPredicateValueFormGroup"> |
19 | - <div fxFlex fxLayout="column" [fxShow]="!dynamicMode"> | |
19 | + <div fxFlex fxLayout="column" [fxShow]="!dynamicMode && !onlyUserDynamicSource"> | |
20 | 20 | <div fxLayout="column" [ngSwitch]="valueType"> |
21 | 21 | <ng-template [ngSwitchCase]="valueTypeEnum.STRING"> |
22 | 22 | <mat-form-field floatLabel="always" hideRequiredMarker class="mat-block"> |
... | ... | @@ -45,7 +45,7 @@ |
45 | 45 | </div> |
46 | 46 | <div class="tb-hint" translate>filter.default-value</div> |
47 | 47 | </div> |
48 | - <div fxFlex fxLayout="column" [fxShow]="dynamicMode"> | |
48 | + <div fxFlex fxLayout="column" [fxShow]="dynamicMode || onlyUserDynamicSource"> | |
49 | 49 | <div formGroupName="dynamicValue" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px"> |
50 | 50 | <div fxFlex="35" fxLayout="column"> |
51 | 51 | <mat-form-field floatLabel="always" hideRequiredMarker class="mat-block"> |
... | ... | @@ -78,7 +78,7 @@ |
78 | 78 | </div> |
79 | 79 | </div> |
80 | 80 | </div> |
81 | - <button mat-icon-button | |
81 | + <button mat-icon-button *ngIf="!onlyUserDynamicSource" | |
82 | 82 | class="mat-elevation-z1 tb-mat-32" |
83 | 83 | color="primary" |
84 | 84 | type="button" | ... | ... |
... | ... | @@ -20,12 +20,14 @@ |
20 | 20 | <ng-template [ngSwitchCase]="filterPredicateType.STRING"> |
21 | 21 | <tb-string-filter-predicate |
22 | 22 | [allowUserDynamicSource]="allowUserDynamicSource" |
23 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
23 | 24 | formControlName="predicate"> |
24 | 25 | </tb-string-filter-predicate> |
25 | 26 | </ng-template> |
26 | 27 | <ng-template [ngSwitchCase]="filterPredicateType.NUMERIC"> |
27 | 28 | <tb-numeric-filter-predicate |
28 | 29 | [allowUserDynamicSource]="allowUserDynamicSource" |
30 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
29 | 31 | [valueType]="valueType" |
30 | 32 | formControlName="predicate"> |
31 | 33 | </tb-numeric-filter-predicate> |
... | ... | @@ -33,12 +35,14 @@ |
33 | 35 | <ng-template [ngSwitchCase]="filterPredicateType.BOOLEAN"> |
34 | 36 | <tb-boolean-filter-predicate |
35 | 37 | [allowUserDynamicSource]="allowUserDynamicSource" |
38 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
36 | 39 | formControlName="predicate"> |
37 | 40 | </tb-boolean-filter-predicate> |
38 | 41 | </ng-template> |
39 | 42 | <ng-template [ngSwitchCase]="filterPredicateType.COMPLEX"> |
40 | 43 | <tb-complex-filter-predicate |
41 | 44 | [allowUserDynamicSource]="allowUserDynamicSource" |
45 | + [onlyUserDynamicSource]="onlyUserDynamicSource" | |
42 | 46 | [key]="key" |
43 | 47 | [valueType]="valueType" |
44 | 48 | [displayUserParameters]="displayUserParameters" | ... | ... |
... | ... | @@ -45,6 +45,8 @@ export class FilterPredicateComponent implements ControlValueAccessor, OnInit { |
45 | 45 | |
46 | 46 | @Input() allowUserDynamicSource = true; |
47 | 47 | |
48 | + @Input() onlyUserDynamicSource = false; | |
49 | + | |
48 | 50 | filterPredicateFormGroup: FormGroup; |
49 | 51 | |
50 | 52 | type: FilterPredicateType; | ... | ... |
... | ... | @@ -28,7 +28,7 @@ |
28 | 28 | <div mat-dialog-content> |
29 | 29 | <fieldset [disabled]="isLoading$ | async" fxLayout="column"> |
30 | 30 | <section fxLayout="row" fxLayoutGap="8px" class="entity-key"> |
31 | - <section fxFlex="70" fxLayout="row" formGroupName="key" fxLayoutGap="8px"> | |
31 | + <section [fxFlex]="isConstantKeyType ? 45 : 70" fxLayout="row" formGroupName="key" fxLayoutGap="8px"> | |
32 | 32 | <mat-form-field fxFlex="40" class="mat-block"> |
33 | 33 | <mat-label translate>filter.key-type.key-type</mat-label> |
34 | 34 | <mat-select required formControlName="type"> |
... | ... | @@ -60,7 +60,7 @@ |
60 | 60 | </mat-error> |
61 | 61 | </mat-form-field> |
62 | 62 | </section> |
63 | - <mat-form-field fxFlex="30" class="mat-block"> | |
63 | + <mat-form-field [fxFlex]="isConstantKeyType ? 20 : 30" class="mat-block"> | |
64 | 64 | <mat-label translate>filter.value-type.value-type</mat-label> |
65 | 65 | <mat-select formControlName="valueType"> |
66 | 66 | <mat-select-trigger> |
... | ... | @@ -76,9 +76,37 @@ |
76 | 76 | {{ 'filter.value-type-required' | translate }} |
77 | 77 | </mat-error> |
78 | 78 | </mat-form-field> |
79 | + <div fxFlex *ngIf="isConstantKeyType"> | |
80 | + <div fxLayout="column" [ngSwitch]="keyFilterFormGroup.get('valueType').value"> | |
81 | + <ng-template [ngSwitchCase]="entityKeyValueTypeEnum.STRING"> | |
82 | + <mat-form-field class="mat-block"> | |
83 | + <mat-label translate>filter.value</mat-label> | |
84 | + <input matInput required formControlName="value" placeholder="{{'filter.value' | translate}}"> | |
85 | + </mat-form-field> | |
86 | + </ng-template> | |
87 | + <ng-template [ngSwitchCase]="entityKeyValueTypeEnum.NUMERIC"> | |
88 | + <mat-form-field class="mat-block"> | |
89 | + <mat-label translate>filter.value</mat-label> | |
90 | + <input required type="number" matInput formControlName="value"> | |
91 | + </mat-form-field> | |
92 | + </ng-template> | |
93 | + <ng-template [ngSwitchCase]="entityKeyValueTypeEnum.DATE_TIME"> | |
94 | + <tb-datetime formControlName="value" | |
95 | + dateText="filter.date" | |
96 | + timeText="filter.time" | |
97 | + required></tb-datetime> | |
98 | + </ng-template> | |
99 | + <ng-template [ngSwitchCase]="entityKeyValueTypeEnum.BOOLEAN"> | |
100 | + <mat-checkbox formControlName="value" style="margin-top: 20px"> | |
101 | + {{ (keyFilterFormGroup.get('value').value ? 'value.true' : 'value.false') | translate }} | |
102 | + </mat-checkbox> | |
103 | + </ng-template> | |
104 | + </div> | |
105 | + </div> | |
79 | 106 | </section> |
80 | 107 | <tb-filter-predicate-list *ngIf="keyFilterFormGroup.get('valueType').value" |
81 | 108 | [allowUserDynamicSource]="data.allowUserDynamicSource" |
109 | + [onlyUserDynamicSource]="isConstantKeyType" | |
82 | 110 | [displayUserParameters]="data.displayUserParameters" |
83 | 111 | [valueType]="keyFilterFormGroup.get('valueType').value" |
84 | 112 | [key]="keyFilterFormGroup.get('key.key').value" | ... | ... |
... | ... | @@ -14,7 +14,7 @@ |
14 | 14 | /// limitations under the License. |
15 | 15 | /// |
16 | 16 | |
17 | -import { Component, ElementRef, Inject, OnDestroy, OnInit, SkipSelf, ViewChild } from '@angular/core'; | |
17 | +import { Component, ElementRef, Inject, OnDestroy, SkipSelf, ViewChild } from '@angular/core'; | |
18 | 18 | import { ErrorStateMatcher } from '@angular/material/core'; |
19 | 19 | import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
20 | 20 | import { Store } from '@ngrx/store'; |
... | ... | @@ -57,7 +57,7 @@ export interface KeyFilterDialogData { |
57 | 57 | }) |
58 | 58 | export class KeyFilterDialogComponent extends |
59 | 59 | DialogComponent<KeyFilterDialogComponent, KeyFilterInfo> |
60 | - implements OnInit, OnDestroy, ErrorStateMatcher { | |
60 | + implements OnDestroy, ErrorStateMatcher { | |
61 | 61 | |
62 | 62 | @ViewChild('keyNameInput', {static: true}) private keyNameInput: ElementRef; |
63 | 63 | |
... | ... | @@ -69,7 +69,7 @@ export class KeyFilterDialogComponent extends |
69 | 69 | |
70 | 70 | entityKeyTypes = |
71 | 71 | this.data.telemetryKeysOnly ? |
72 | - [EntityKeyType.ATTRIBUTE, EntityKeyType.TIME_SERIES] : | |
72 | + [EntityKeyType.ATTRIBUTE, EntityKeyType.TIME_SERIES, EntityKeyType.CONSTANT] : | |
73 | 73 | [EntityKeyType.ENTITY_FIELD, EntityKeyType.ATTRIBUTE, EntityKeyType.TIME_SERIES]; |
74 | 74 | |
75 | 75 | entityKeyTypeTranslations = entityKeyTypeTranslationMap; |
... | ... | @@ -107,6 +107,7 @@ export class KeyFilterDialogComponent extends |
107 | 107 | key: [this.data.keyFilter.key.key, [Validators.required]] |
108 | 108 | } |
109 | 109 | ), |
110 | + value: [this.data.keyFilter.value], | |
110 | 111 | valueType: [this.data.keyFilter.valueType, [Validators.required]], |
111 | 112 | predicates: [this.data.keyFilter.predicates, [Validators.required]] |
112 | 113 | } |
... | ... | @@ -143,6 +144,13 @@ export class KeyFilterDialogComponent extends |
143 | 144 | } else { |
144 | 145 | this.showAutocomplete = false; |
145 | 146 | } |
147 | + if (type === EntityKeyType.CONSTANT) { | |
148 | + this.keyFilterFormGroup.get('value').setValidators(Validators.required); | |
149 | + this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
150 | + } else { | |
151 | + this.keyFilterFormGroup.get('value').clearValidators(); | |
152 | + this.keyFilterFormGroup.get('value').updateValueAndValidity(); | |
153 | + } | |
146 | 154 | }); |
147 | 155 | |
148 | 156 | this.keyFilterFormGroup.get('key.key').valueChanges.pipe( |
... | ... | @@ -156,19 +164,18 @@ export class KeyFilterDialogComponent extends |
156 | 164 | this.keyFilterFormGroup.get('valueType').patchValue(newValueType, {emitEvent: false}); |
157 | 165 | } |
158 | 166 | }); |
167 | + | |
168 | + this.filteredKeysName = this.keyFilterFormGroup.get('key.key').valueChanges | |
169 | + .pipe( | |
170 | + map(value => value ? value : ''), | |
171 | + mergeMap(name => this.fetchEntityName(name)), | |
172 | + takeUntil(this.destroy$) | |
173 | + ); | |
159 | 174 | } else { |
160 | 175 | this.keyFilterFormGroup.disable({emitEvent: false}); |
161 | 176 | } |
162 | 177 | } |
163 | 178 | |
164 | - ngOnInit() { | |
165 | - this.filteredKeysName = this.keyFilterFormGroup.get('key.key').valueChanges | |
166 | - .pipe( | |
167 | - map(value => value ? value : ''), | |
168 | - mergeMap(name => this.fetchEntityName(name)) | |
169 | - ); | |
170 | - } | |
171 | - | |
172 | 179 | ngOnDestroy() { |
173 | 180 | super.ngOnDestroy(); |
174 | 181 | this.destroy$.next(); |
... | ... | @@ -208,6 +215,10 @@ export class KeyFilterDialogComponent extends |
208 | 215 | } |
209 | 216 | } |
210 | 217 | |
218 | + get isConstantKeyType(): boolean { | |
219 | + return this.keyFilterFormGroup.get('key.type').value === EntityKeyType.CONSTANT; | |
220 | + } | |
221 | + | |
211 | 222 | private fetchEntityName(searchText?: string): Observable<Array<string>> { |
212 | 223 | this.searchText = searchText; |
213 | 224 | return this.getEntityKeys().pipe( | ... | ... |
... | ... | @@ -42,6 +42,8 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On |
42 | 42 | |
43 | 43 | @Input() allowUserDynamicSource = true; |
44 | 44 | |
45 | + @Input() onlyUserDynamicSource = false; | |
46 | + | |
45 | 47 | @Input() valueType: EntityKeyValueType; |
46 | 48 | |
47 | 49 | numericFilterPredicateFormGroup: FormGroup; | ... | ... |
... | ... | @@ -42,6 +42,8 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI |
42 | 42 | |
43 | 43 | @Input() allowUserDynamicSource = true; |
44 | 44 | |
45 | + @Input() onlyUserDynamicSource = false; | |
46 | + | |
45 | 47 | valueTypeEnum = EntityKeyValueType; |
46 | 48 | |
47 | 49 | stringFilterPredicateFormGroup: FormGroup; | ... | ... |
... | ... | @@ -35,14 +35,16 @@ export enum EntityKeyType { |
35 | 35 | SERVER_ATTRIBUTE = 'SERVER_ATTRIBUTE', |
36 | 36 | TIME_SERIES = 'TIME_SERIES', |
37 | 37 | ENTITY_FIELD = 'ENTITY_FIELD', |
38 | - ALARM_FIELD = 'ALARM_FIELD' | |
38 | + ALARM_FIELD = 'ALARM_FIELD', | |
39 | + CONSTANT = 'CONSTANT' | |
39 | 40 | } |
40 | 41 | |
41 | 42 | export const entityKeyTypeTranslationMap = new Map<EntityKeyType, string>( |
42 | 43 | [ |
43 | 44 | [EntityKeyType.ATTRIBUTE, 'filter.key-type.attribute'], |
44 | 45 | [EntityKeyType.TIME_SERIES, 'filter.key-type.timeseries'], |
45 | - [EntityKeyType.ENTITY_FIELD, 'filter.key-type.entity-field'] | |
46 | + [EntityKeyType.ENTITY_FIELD, 'filter.key-type.entity-field'], | |
47 | + [EntityKeyType.CONSTANT, 'filter.key-type.constant'] | |
46 | 48 | ] |
47 | 49 | ); |
48 | 50 | |
... | ... | @@ -344,12 +346,14 @@ export interface KeyFilterPredicateInfo { |
344 | 346 | export interface KeyFilter { |
345 | 347 | key: EntityKey; |
346 | 348 | valueType: EntityKeyValueType; |
349 | + value: string | number | boolean; | |
347 | 350 | predicate: KeyFilterPredicate; |
348 | 351 | } |
349 | 352 | |
350 | 353 | export interface KeyFilterInfo { |
351 | 354 | key: EntityKey; |
352 | 355 | valueType: EntityKeyValueType; |
356 | + value: string | number | boolean; | |
353 | 357 | predicates: Array<KeyFilterPredicateInfo>; |
354 | 358 | } |
355 | 359 | |
... | ... | @@ -466,6 +470,7 @@ export function keyFilterInfosToKeyFilters(keyFilterInfos: Array<KeyFilterInfo>) |
466 | 470 | const keyFilter: KeyFilter = { |
467 | 471 | key, |
468 | 472 | valueType: keyFilterInfo.valueType, |
473 | + value: keyFilterInfo.value, | |
469 | 474 | predicate: keyFilterPredicateInfoToKeyFilterPredicate(predicate) |
470 | 475 | }; |
471 | 476 | keyFilters.push(keyFilter); |
... | ... | @@ -486,6 +491,7 @@ export function keyFiltersToKeyFilterInfos(keyFilters: Array<KeyFilter>): Array< |
486 | 491 | keyFilterInfo = { |
487 | 492 | key, |
488 | 493 | valueType: keyFilter.valueType, |
494 | + value: keyFilter.value, | |
489 | 495 | predicates: [] |
490 | 496 | }; |
491 | 497 | keyFilterInfoMap[infoKey] = keyFilterInfo; |
... | ... | @@ -508,6 +514,7 @@ export function filterInfoToKeyFilters(filter: FilterInfo): Array<KeyFilter> { |
508 | 514 | const keyFilter: KeyFilter = { |
509 | 515 | key, |
510 | 516 | valueType: keyFilterInfo.valueType, |
517 | + value: keyFilterInfo.value, | |
511 | 518 | predicate: keyFilterPredicateInfoToKeyFilterPredicate(predicate) |
512 | 519 | }; |
513 | 520 | keyFilters.push(keyFilter); | ... | ... |
... | ... | @@ -1564,7 +1564,8 @@ |
1564 | 1564 | "key-type": "Key type", |
1565 | 1565 | "attribute": "Attribute", |
1566 | 1566 | "timeseries": "Timeseries", |
1567 | - "entity-field": "Entity field" | |
1567 | + "entity-field": "Entity field", | |
1568 | + "constant": "Constant" | |
1568 | 1569 | }, |
1569 | 1570 | "value-type": { |
1570 | 1571 | "value-type": "Value type", | ... | ... |