Commit 77d2c786afa1cd7386775a84e9b58adaecaf8da6
1 parent
1278339e
UI: Added device profile alarm conditional type
Showing
11 changed files
with
184 additions
and
130 deletions
@@ -15,11 +15,13 @@ | @@ -15,11 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.device.profile; | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
18 | import lombok.Data; | 19 | import lombok.Data; |
19 | 20 | ||
20 | import java.util.concurrent.TimeUnit; | 21 | import java.util.concurrent.TimeUnit; |
21 | 22 | ||
22 | @Data | 23 | @Data |
24 | +@JsonIgnoreProperties(ignoreUnknown = true) | ||
23 | public class DurationAlarmConditionSpec implements AlarmConditionSpec { | 25 | public class DurationAlarmConditionSpec implements AlarmConditionSpec { |
24 | 26 | ||
25 | private TimeUnit unit; | 27 | private TimeUnit unit; |
@@ -15,11 +15,13 @@ | @@ -15,11 +15,13 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.device.profile; | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
18 | import lombok.Data; | 19 | import lombok.Data; |
19 | 20 | ||
20 | import java.util.concurrent.TimeUnit; | 21 | import java.util.concurrent.TimeUnit; |
21 | 22 | ||
22 | @Data | 23 | @Data |
24 | +@JsonIgnoreProperties(ignoreUnknown = true) | ||
23 | public class RepeatingAlarmConditionSpec implements AlarmConditionSpec { | 25 | public class RepeatingAlarmConditionSpec implements AlarmConditionSpec { |
24 | 26 | ||
25 | private int count; | 27 | private int count; |
@@ -15,9 +15,11 @@ | @@ -15,9 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.common.data.device.profile; | 16 | package org.thingsboard.server.common.data.device.profile; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | ||
18 | import lombok.Data; | 19 | import lombok.Data; |
19 | 20 | ||
20 | @Data | 21 | @Data |
22 | +@JsonIgnoreProperties(ignoreUnknown = true) | ||
21 | public class SimpleAlarmConditionSpec implements AlarmConditionSpec { | 23 | public class SimpleAlarmConditionSpec implements AlarmConditionSpec { |
22 | @Override | 24 | @Override |
23 | public AlarmConditionSpecType getType() { | 25 | public AlarmConditionSpecType getType() { |
@@ -17,7 +17,6 @@ | @@ -17,7 +17,6 @@ | ||
17 | --> | 17 | --> |
18 | <div fxLayout="column" fxFlex> | 18 | <div fxLayout="column" fxFlex> |
19 | <div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;"> | 19 | <div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;"> |
20 | - <div class="tb-small" translate>device-profile.alarm-rule-condition</div> | ||
21 | <span fxFlex></span> | 20 | <span fxFlex></span> |
22 | <a mat-button color="primary" | 21 | <a mat-button color="primary" |
23 | type="button" | 22 | type="button" |
@@ -16,70 +16,90 @@ | @@ -16,70 +16,90 @@ | ||
16 | 16 | ||
17 | --> | 17 | --> |
18 | <div fxLayout="column" [formGroup]="alarmRuleFormGroup"> | 18 | <div fxLayout="column" [formGroup]="alarmRuleFormGroup"> |
19 | - <div formGroupName="condition" fxLayout="row" fxLayoutGap="8px" fxFlex> | ||
20 | - <tb-alarm-rule-condition fxFlex | ||
21 | - formControlName="condition"> | ||
22 | - </tb-alarm-rule-condition> | ||
23 | - <div fxLayout="column"> | ||
24 | - <div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;"> | ||
25 | - <div class="tb-small" translate>device-profile.condition-duration</div> | ||
26 | - <span fxFlex></span> | ||
27 | - <mat-slide-toggle [disabled]="disabled" | ||
28 | - color="primary" | ||
29 | - [ngModelOptions]="{standalone: true}" | ||
30 | - (ngModelChange)="enableDurationChanged($event)" | ||
31 | - [ngModel]="enableDuration"> | ||
32 | - </mat-slide-toggle> | ||
33 | - </div> | ||
34 | - <div class="tb-condition-duration" fxFlex fxLayout="row" fxLayoutGap="8px"> | ||
35 | - <span style="min-width: 250px;" *ngIf="!enableDuration"></span> | ||
36 | - <div style="min-width: 250px;" fxLayout="row" fxLayoutGap="8px" *ngIf="enableDuration"> | ||
37 | - <mat-form-field class="mat-block duration-value-field" hideRequiredMarker floatLabel="always"> | ||
38 | - <mat-label></mat-label> | ||
39 | - <input type="number" | ||
40 | - required | ||
41 | - step="1" | ||
42 | - min="1" max="2147483647" matInput | ||
43 | - placeholder="{{ 'device-profile.condition-duration-value' | translate }}" | ||
44 | - formControlName="durationValue"> | ||
45 | - <mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('required')"> | ||
46 | - {{ 'device-profile.condition-duration-value-required' | translate }} | ||
47 | - </mat-error> | ||
48 | - <mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('min')"> | ||
49 | - {{ 'device-profile.condition-duration-value-range' | translate }} | ||
50 | - </mat-error> | ||
51 | - <mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('max')"> | ||
52 | - {{ 'device-profile.condition-duration-value-range' | translate }} | ||
53 | - </mat-error> | ||
54 | - </mat-form-field> | ||
55 | - <mat-form-field class="mat-block duration-unit-field" hideRequiredMarker floatLabel="always"> | ||
56 | - <mat-label></mat-label> | ||
57 | - <mat-select formControlName="durationUnit" | ||
58 | - required | ||
59 | - placeholder="{{ 'device-profile.condition-duration-time-unit' | translate }}"> | ||
60 | - <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit"> | ||
61 | - {{ timeUnitTranslations.get(timeUnit) | translate }} | 19 | + <mat-tab-group> |
20 | + <mat-tab label="{{ 'device-profile.condition' | translate }}" formGroupName="condition"> | ||
21 | + <tb-alarm-rule-condition fxFlex class="row" | ||
22 | + formControlName="condition"> | ||
23 | + </tb-alarm-rule-condition> | ||
24 | + <section class="row"> | ||
25 | + <div formGroupName="spec"> | ||
26 | + <mat-form-field class="mat-block" hideRequiredMarker> | ||
27 | + <mat-label translate>device-profile.condition-type</mat-label> | ||
28 | + <mat-select formControlName="type" required> | ||
29 | + <mat-option *ngFor="let alarmConditionType of alarmConditionTypes" [value]="alarmConditionType"> | ||
30 | + {{ alarmConditionTypeTranslation.get(alarmConditionType) | translate }} | ||
62 | </mat-option> | 31 | </mat-option> |
63 | </mat-select> | 32 | </mat-select> |
64 | - <mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationUnit').hasError('required')"> | ||
65 | - {{ 'device-profile.condition-duration-time-unit-required' | translate }} | 33 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.type').hasError('required')"> |
34 | + {{ 'device-profile.condition-type-required' | translate }} | ||
66 | </mat-error> | 35 | </mat-error> |
67 | </mat-form-field> | 36 | </mat-form-field> |
37 | + <div fxLayout="row" fxLayoutGap="8px" *ngIf="alarmRuleFormGroup.get('condition.spec.type').value == AlarmConditionType.DURATION"> | ||
38 | + <mat-form-field class="mat-block" hideRequiredMarker fxFlex floatLabel="always"> | ||
39 | + <mat-label></mat-label> | ||
40 | + <input type="number" required | ||
41 | + step="1" min="1" max="2147483647" matInput | ||
42 | + placeholder="{{ 'device-profile.condition-duration-value' | translate }}" | ||
43 | + formControlName="value"> | ||
44 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.value').hasError('required')"> | ||
45 | + {{ 'device-profile.condition-duration-value-required' | translate }} | ||
46 | + </mat-error> | ||
47 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.value').hasError('min')"> | ||
48 | + {{ 'device-profile.condition-duration-value-range' | translate }} | ||
49 | + </mat-error> | ||
50 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.value').hasError('max')"> | ||
51 | + {{ 'device-profile.condition-duration-value-range' | translate }} | ||
52 | + </mat-error> | ||
53 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.value').hasError('pattern')"> | ||
54 | + {{ 'device-profile.condition-duration-value-pattern' | translate }} | ||
55 | + </mat-error> | ||
56 | + </mat-form-field> | ||
57 | + <mat-form-field class="mat-block" hideRequiredMarker fxFlex floatLabel="always"> | ||
58 | + <mat-label></mat-label> | ||
59 | + <mat-select formControlName="unit" | ||
60 | + required | ||
61 | + placeholder="{{ 'device-profile.condition-duration-time-unit' | translate }}"> | ||
62 | + <mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit"> | ||
63 | + {{ timeUnitTranslations.get(timeUnit) | translate }} | ||
64 | + </mat-option> | ||
65 | + </mat-select> | ||
66 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.unit').hasError('required')"> | ||
67 | + {{ 'device-profile.condition-duration-time-unit-required' | translate }} | ||
68 | + </mat-error> | ||
69 | + </mat-form-field> | ||
70 | + </div> | ||
71 | + <div fxLayout="row" fxLayoutGap="8px" *ngIf="alarmRuleFormGroup.get('condition.spec.type').value == AlarmConditionType.REPEATING"> | ||
72 | + <mat-form-field class="mat-block" hideRequiredMarker fxFlex floatLabel="always"> | ||
73 | + <mat-label></mat-label> | ||
74 | + <input type="number" required | ||
75 | + step="1" min="1" max="2147483647" matInput | ||
76 | + placeholder="{{ 'device-profile.condition-repeating-value' | translate }}" | ||
77 | + formControlName="count"> | ||
78 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.count').hasError('required')"> | ||
79 | + {{ 'device-profile.condition-repeating-value-required' | translate }} | ||
80 | + </mat-error> | ||
81 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.count').hasError('min')"> | ||
82 | + {{ 'device-profile.condition-repeating-value-range' | translate }} | ||
83 | + </mat-error> | ||
84 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.count').hasError('max')"> | ||
85 | + {{ 'device-profile.condition-repeating-value-range' | translate }} | ||
86 | + </mat-error> | ||
87 | + <mat-error *ngIf="alarmRuleFormGroup.get('condition.spec.count').hasError('pattern')"> | ||
88 | + {{ 'device-profile.condition-repeating-value-pattern' | translate }} | ||
89 | + </mat-error> | ||
90 | + </mat-form-field> | ||
91 | + </div> | ||
68 | </div> | 92 | </div> |
69 | - </div> | ||
70 | - </div> | ||
71 | - </div> | ||
72 | - <mat-expansion-panel class="advanced-settings" [expanded]="false"> | ||
73 | - <mat-expansion-panel-header> | ||
74 | - <mat-panel-title> | ||
75 | - <div fxFlex fxLayout="row" fxLayoutAlign="end center"> | ||
76 | - <div class="tb-small" translate>device-profile.alarm-rule-details</div> | ||
77 | - </div> | ||
78 | - </mat-panel-title> | ||
79 | - </mat-expansion-panel-header> | ||
80 | - <mat-form-field class="mat-block"> | ||
81 | - <mat-label translate>device-profile.alarm-details</mat-label> | ||
82 | - <textarea matInput formControlName="alarmDetails" rows="5"></textarea> | ||
83 | - </mat-form-field> | ||
84 | - </mat-expansion-panel> | 93 | + </section> |
94 | + </mat-tab> | ||
95 | + <mat-tab label="{{ 'device-profile.schedule' | translate }}"> | ||
96 | + <div class="row">{{ 'device-profile.schedule' | translate }}</div> | ||
97 | + </mat-tab> | ||
98 | + <mat-tab label="{{ 'device-profile.alarm-rule-details' | translate }}"> | ||
99 | + <mat-form-field class="mat-block row"> | ||
100 | + <mat-label translate>device-profile.alarm-details</mat-label> | ||
101 | + <textarea matInput formControlName="alarmDetails" rows="5"></textarea> | ||
102 | + </mat-form-field> | ||
103 | + </mat-tab> | ||
104 | + </mat-tab-group> | ||
85 | </div> | 105 | </div> |
@@ -14,33 +14,8 @@ | @@ -14,33 +14,8 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | :host { | 16 | :host { |
17 | - .tb-condition-duration { | ||
18 | - padding: 8px; | ||
19 | - border: 1px groove rgba(0, 0, 0, .25); | ||
20 | - border-radius: 4px; | ||
21 | - } | ||
22 | - .mat-expansion-panel.advanced-settings { | ||
23 | - box-shadow: none; | ||
24 | - border: none; | ||
25 | - padding: 0; | ||
26 | - } | ||
27 | -} | ||
28 | - | ||
29 | -:host ::ng-deep { | ||
30 | - .mat-expansion-panel.advanced-settings { | ||
31 | - .mat-expansion-panel-body { | ||
32 | - padding: 0; | ||
33 | - } | ||
34 | - } | ||
35 | - .mat-form-field.duration-value-field { | ||
36 | - .mat-form-field-infix { | ||
37 | - width: 120px; | ||
38 | - } | ||
39 | - } | ||
40 | - .mat-form-field.duration-unit-field { | ||
41 | - .mat-form-field-infix { | ||
42 | - width: 120px; | ||
43 | - } | 17 | + .row { |
18 | + margin-top: 1em; | ||
44 | } | 19 | } |
45 | } | 20 | } |
46 | 21 |
@@ -14,7 +14,7 @@ | @@ -14,7 +14,7 @@ | ||
14 | /// limitations under the License. | 14 | /// limitations under the License. |
15 | /// | 15 | /// |
16 | 16 | ||
17 | -import { ChangeDetectorRef, Component, forwardRef, Input, NgZone, OnInit } from '@angular/core'; | 17 | +import { Component, forwardRef, Input, OnInit } from '@angular/core'; |
18 | import { | 18 | import { |
19 | ControlValueAccessor, | 19 | ControlValueAccessor, |
20 | FormBuilder, | 20 | FormBuilder, |
@@ -25,9 +25,9 @@ import { | @@ -25,9 +25,9 @@ import { | ||
25 | Validator, | 25 | Validator, |
26 | Validators | 26 | Validators |
27 | } from '@angular/forms'; | 27 | } from '@angular/forms'; |
28 | -import { AlarmRule } from '@shared/models/device.models'; | 28 | +import { AlarmConditionType, AlarmConditionTypeTranslationMap, AlarmRule } from '@shared/models/device.models'; |
29 | import { MatDialog } from '@angular/material/dialog'; | 29 | import { MatDialog } from '@angular/material/dialog'; |
30 | -import { TimeUnit, timeUnitTranslationMap } from '../../../../../shared/models/time/time.models'; | 30 | +import { TimeUnit, timeUnitTranslationMap } from '@shared/models/time/time.models'; |
31 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; | 31 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
32 | 32 | ||
33 | @Component({ | 33 | @Component({ |
@@ -51,6 +51,9 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | @@ -51,6 +51,9 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | ||
51 | 51 | ||
52 | timeUnits = Object.keys(TimeUnit); | 52 | timeUnits = Object.keys(TimeUnit); |
53 | timeUnitTranslations = timeUnitTranslationMap; | 53 | timeUnitTranslations = timeUnitTranslationMap; |
54 | + alarmConditionTypes = Object.keys(AlarmConditionType); | ||
55 | + AlarmConditionType = AlarmConditionType; | ||
56 | + alarmConditionTypeTranslation = AlarmConditionTypeTranslationMap; | ||
54 | 57 | ||
55 | @Input() | 58 | @Input() |
56 | disabled: boolean; | 59 | disabled: boolean; |
@@ -64,8 +67,6 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | @@ -64,8 +67,6 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | ||
64 | this.requiredValue = coerceBooleanProperty(value); | 67 | this.requiredValue = coerceBooleanProperty(value); |
65 | } | 68 | } |
66 | 69 | ||
67 | - enableDuration = false; | ||
68 | - | ||
69 | private modelValue: AlarmRule; | 70 | private modelValue: AlarmRule; |
70 | 71 | ||
71 | alarmRuleFormGroup: FormGroup; | 72 | alarmRuleFormGroup: FormGroup; |
@@ -87,11 +88,18 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | @@ -87,11 +88,18 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | ||
87 | this.alarmRuleFormGroup = this.fb.group({ | 88 | this.alarmRuleFormGroup = this.fb.group({ |
88 | condition: this.fb.group({ | 89 | condition: this.fb.group({ |
89 | condition: [null, Validators.required], | 90 | condition: [null, Validators.required], |
90 | - durationUnit: [null], | ||
91 | - durationValue: [null] | 91 | + spec: this.fb.group({ |
92 | + type: [AlarmConditionType.SIMPLE, Validators.required], | ||
93 | + unit: [{value: null, disable: true}, Validators.required], | ||
94 | + value: [{value: null, disable: true}, [Validators.required, Validators.min(1), Validators.max(2147483647), Validators.pattern('[0-9]*')]], | ||
95 | + count: [{value: null, disable: true}, [Validators.required, Validators.min(1), Validators.max(2147483647), Validators.pattern('[0-9]*')]] | ||
96 | + }) | ||
92 | }, Validators.required), | 97 | }, Validators.required), |
93 | alarmDetails: [null] | 98 | alarmDetails: [null] |
94 | }); | 99 | }); |
100 | + this.alarmRuleFormGroup.get('condition.spec.type').valueChanges.subscribe((type) => { | ||
101 | + this.updateValidators(type, true, true); | ||
102 | + }); | ||
95 | this.alarmRuleFormGroup.valueChanges.subscribe(() => { | 103 | this.alarmRuleFormGroup.valueChanges.subscribe(() => { |
96 | this.updateModel(); | 104 | this.updateModel(); |
97 | }); | 105 | }); |
@@ -108,9 +116,13 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | @@ -108,9 +116,13 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | ||
108 | 116 | ||
109 | writeValue(value: AlarmRule): void { | 117 | writeValue(value: AlarmRule): void { |
110 | this.modelValue = value; | 118 | this.modelValue = value; |
111 | - this.enableDuration = value && !!value.condition.durationValue; | 119 | + if (this.modelValue?.condition?.spec === null) { |
120 | + this.modelValue.condition.spec = { | ||
121 | + type: AlarmConditionType.SIMPLE | ||
122 | + }; | ||
123 | + } | ||
112 | this.alarmRuleFormGroup.reset(this.modelValue || undefined, {emitEvent: false}); | 124 | this.alarmRuleFormGroup.reset(this.modelValue || undefined, {emitEvent: false}); |
113 | - this.updateValidators(); | 125 | + this.updateValidators(this.modelValue?.condition?.spec?.type); |
114 | } | 126 | } |
115 | 127 | ||
116 | public validate(c: FormControl) { | 128 | public validate(c: FormControl) { |
@@ -121,31 +133,45 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | @@ -121,31 +133,45 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat | ||
121 | }; | 133 | }; |
122 | } | 134 | } |
123 | 135 | ||
124 | - public enableDurationChanged(enableDuration) { | ||
125 | - this.enableDuration = enableDuration; | ||
126 | - this.updateValidators(true, true); | ||
127 | - } | ||
128 | - | ||
129 | - private updateValidators(resetDuration = false, emitEvent = false) { | ||
130 | - if (this.enableDuration) { | ||
131 | - this.alarmRuleFormGroup.get('condition').get('durationValue') | ||
132 | - .setValidators([Validators.required, Validators.min(1), Validators.max(2147483647)]); | ||
133 | - this.alarmRuleFormGroup.get('condition').get('durationUnit') | ||
134 | - .setValidators([Validators.required]); | ||
135 | - } else { | ||
136 | - this.alarmRuleFormGroup.get('condition').get('durationValue') | ||
137 | - .setValidators([]); | ||
138 | - this.alarmRuleFormGroup.get('condition').get('durationUnit') | ||
139 | - .setValidators([]); | ||
140 | - if (resetDuration) { | ||
141 | - this.alarmRuleFormGroup.get('condition').patchValue({ | ||
142 | - durationValue: null, | ||
143 | - durationUnit: null | ||
144 | - }); | ||
145 | - } | 136 | + private updateValidators(type: AlarmConditionType, resetDuration = false, emitEvent = false) { |
137 | + switch (type) { | ||
138 | + case AlarmConditionType.DURATION: | ||
139 | + this.alarmRuleFormGroup.get('condition.spec.value').enable(); | ||
140 | + this.alarmRuleFormGroup.get('condition.spec.unit').enable(); | ||
141 | + this.alarmRuleFormGroup.get('condition.spec.count').disable(); | ||
142 | + if (resetDuration) { | ||
143 | + this.alarmRuleFormGroup.get('condition.spec').patchValue({ | ||
144 | + count: null | ||
145 | + }); | ||
146 | + } | ||
147 | + break; | ||
148 | + case AlarmConditionType.REPEATING: | ||
149 | + this.alarmRuleFormGroup.get('condition.spec.count').enable(); | ||
150 | + this.alarmRuleFormGroup.get('condition.spec.value').disable(); | ||
151 | + this.alarmRuleFormGroup.get('condition.spec.unit').disable(); | ||
152 | + if (resetDuration) { | ||
153 | + this.alarmRuleFormGroup.get('condition.spec').patchValue({ | ||
154 | + value: null, | ||
155 | + unit: null | ||
156 | + }); | ||
157 | + } | ||
158 | + break; | ||
159 | + case AlarmConditionType.SIMPLE: | ||
160 | + this.alarmRuleFormGroup.get('condition.spec.value').disable(); | ||
161 | + this.alarmRuleFormGroup.get('condition.spec.unit').disable(); | ||
162 | + this.alarmRuleFormGroup.get('condition.spec.count').disable(); | ||
163 | + if (resetDuration) { | ||
164 | + this.alarmRuleFormGroup.get('condition.spec').patchValue({ | ||
165 | + value: null, | ||
166 | + unit: null, | ||
167 | + count: null | ||
168 | + }); | ||
169 | + } | ||
170 | + break; | ||
146 | } | 171 | } |
147 | - this.alarmRuleFormGroup.get('condition').get('durationValue').updateValueAndValidity({emitEvent}); | ||
148 | - this.alarmRuleFormGroup.get('condition').get('durationUnit').updateValueAndValidity({emitEvent}); | 172 | + this.alarmRuleFormGroup.get('condition.spec.value').updateValueAndValidity({emitEvent}); |
173 | + this.alarmRuleFormGroup.get('condition.spec.unit').updateValueAndValidity({emitEvent}); | ||
174 | + this.alarmRuleFormGroup.get('condition.spec.count').updateValueAndValidity({emitEvent}); | ||
149 | } | 175 | } |
150 | 176 | ||
151 | private updateModel() { | 177 | private updateModel() { |
@@ -19,7 +19,7 @@ | @@ -19,7 +19,7 @@ | ||
19 | <div *ngFor="let createAlarmRuleControl of createAlarmRulesFormArray().controls; let $index = index; | 19 | <div *ngFor="let createAlarmRuleControl of createAlarmRulesFormArray().controls; let $index = index; |
20 | last as isLast;" fxLayout="row" fxLayoutAlign="start center" | 20 | last as isLast;" fxLayout="row" fxLayoutAlign="start center" |
21 | fxLayoutGap="8px" style="padding-bottom: 8px;" [formGroup]="createAlarmRuleControl"> | 21 | fxLayoutGap="8px" style="padding-bottom: 8px;" [formGroup]="createAlarmRuleControl"> |
22 | - <div class="create-alarm-rule" fxFlex fxLayout="row" fxLayoutGap="8px" fxLayoutAlign="start"> | 22 | + <div class="create-alarm-rule" fxFlex fxLayout="column" fxLayoutGap="8px" fxLayoutAlign="start"> |
23 | <mat-form-field class="severity mat-block" floatLabel="always" hideRequiredMarker> | 23 | <mat-form-field class="severity mat-block" floatLabel="always" hideRequiredMarker> |
24 | <mat-label translate>alarm.severity</mat-label> | 24 | <mat-label translate>alarm.severity</mat-label> |
25 | <mat-select formControlName="severity" | 25 | <mat-select formControlName="severity" |
@@ -19,10 +19,6 @@ | @@ -19,10 +19,6 @@ | ||
19 | border: 1px groove rgba(0, 0, 0, .25); | 19 | border: 1px groove rgba(0, 0, 0, .25); |
20 | border-radius: 4px; | 20 | border-radius: 4px; |
21 | padding: 8px; | 21 | padding: 8px; |
22 | - .mat-form-field.severity { | ||
23 | - border-right: 1px groove rgba(0, 0, 0, 0.25); | ||
24 | - padding-right: 8px; | ||
25 | - } | ||
26 | } | 22 | } |
27 | } | 23 | } |
28 | 24 |
@@ -210,10 +210,30 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D | @@ -210,10 +210,30 @@ export function createDeviceTransportConfiguration(type: DeviceTransportType): D | ||
210 | return transportConfiguration; | 210 | return transportConfiguration; |
211 | } | 211 | } |
212 | 212 | ||
213 | +export enum AlarmConditionType { | ||
214 | + SIMPLE = 'SIMPLE', | ||
215 | + DURATION = 'DURATION', | ||
216 | + REPEATING = 'REPEATING' | ||
217 | +} | ||
218 | + | ||
219 | +export const AlarmConditionTypeTranslationMap = new Map<AlarmConditionType, string>( | ||
220 | + [ | ||
221 | + [AlarmConditionType.SIMPLE, 'device-profile.condition-type-simple'], | ||
222 | + [AlarmConditionType.DURATION, 'device-profile.condition-type-duration'], | ||
223 | + [AlarmConditionType.REPEATING, 'device-profile.condition-type-repeating'] | ||
224 | + ] | ||
225 | +); | ||
226 | + | ||
227 | +export interface AlarmConditionSpec{ | ||
228 | + type?: AlarmConditionType; | ||
229 | + unit?: TimeUnit; | ||
230 | + value?: number; | ||
231 | + count?: number; | ||
232 | +} | ||
233 | + | ||
213 | export interface AlarmCondition { | 234 | export interface AlarmCondition { |
214 | condition: Array<KeyFilter>; | 235 | condition: Array<KeyFilter>; |
215 | - durationUnit?: TimeUnit; | ||
216 | - durationValue?: number; | 236 | + spec?: AlarmConditionSpec; |
217 | } | 237 | } |
218 | 238 | ||
219 | export interface AlarmRule { | 239 | export interface AlarmRule { |
@@ -834,6 +834,7 @@ | @@ -834,6 +834,7 @@ | ||
834 | "condition-duration-value": "Duration value", | 834 | "condition-duration-value": "Duration value", |
835 | "condition-duration-time-unit": "Time unit", | 835 | "condition-duration-time-unit": "Time unit", |
836 | "condition-duration-value-range": "Duration value should be in a range from 1 to 2147483647.", | 836 | "condition-duration-value-range": "Duration value should be in a range from 1 to 2147483647.", |
837 | + "condition-duration-value-pattern": "Duration value should be integers.", | ||
837 | "condition-duration-value-required": "Duration value is required.", | 838 | "condition-duration-value-required": "Duration value is required.", |
838 | "condition-duration-time-unit-required": "Time unit is required.", | 839 | "condition-duration-time-unit-required": "Time unit is required.", |
839 | "advanced-settings": "Advanced settings", | 840 | "advanced-settings": "Advanced settings", |
@@ -844,7 +845,18 @@ | @@ -844,7 +845,18 @@ | ||
844 | "alarm-details": "Alarm details", | 845 | "alarm-details": "Alarm details", |
845 | "alarm-rule-condition": "Alarm rule condition", | 846 | "alarm-rule-condition": "Alarm rule condition", |
846 | "enter-alarm-rule-condition-prompt": "Please add alarm rule condition", | 847 | "enter-alarm-rule-condition-prompt": "Please add alarm rule condition", |
847 | - "edit-alarm-rule-condition": "Edit alarm rule condition" | 848 | + "edit-alarm-rule-condition": "Edit alarm rule condition", |
849 | + "condition": "Condition", | ||
850 | + "condition-type": "Condition type", | ||
851 | + "condition-type-simple": "Simple", | ||
852 | + "condition-type-duration": "Duration", | ||
853 | + "condition-type-repeating": "Repeating", | ||
854 | + "condition-type-required": "Condition type is required.", | ||
855 | + "condition-repeating-value": "Count of events", | ||
856 | + "condition-repeating-value-range": "Count of events should be in a range from 1 to 2147483647.", | ||
857 | + "condition-repeating-value-pattern": "Count of events should be integers.", | ||
858 | + "condition-repeating-value-required": "Count of events is required.", | ||
859 | + "schedule": "Schedule" | ||
848 | }, | 860 | }, |
849 | "dialog": { | 861 | "dialog": { |
850 | "close": "Close dialog" | 862 | "close": "Close dialog" |