Commit 76485dfdaddcb989c9e5196008eb4acfb8d62bbf

Authored by Vladyslav_Prykhodko
1 parent 30a6a462

UI: Improvement UI device profile alarm scheduler, added text select time interval

... ... @@ -29,7 +29,7 @@ import { AlarmConditionType, AlarmConditionTypeTranslationMap, AlarmRule } from
29 29 import { MatDialog } from '@angular/material/dialog';
30 30 import { TimeUnit, timeUnitTranslationMap } from '@shared/models/time/time.models';
31 31 import { coerceBooleanProperty } from '@angular/cdk/coercion';
32   -import { isDefinedAndNotNull } from '@core/utils';
  32 +import { isUndefined } from '@core/utils';
33 33
34 34 @Component({
35 35 selector: 'tb-alarm-rule',
... ... @@ -118,11 +118,11 @@ export class AlarmRuleComponent implements ControlValueAccessor, OnInit, Validat
118 118
119 119 writeValue(value: AlarmRule): void {
120 120 this.modelValue = value;
121   - if (!isDefinedAndNotNull(this.modelValue?.condition?.spec)) {
122   - this.modelValue = Object.assign({}, this.modelValue, {condition: {spec: {type: AlarmConditionType.SIMPLE}}});
  121 + if (this.modelValue !== null && isUndefined(this.modelValue?.condition?.spec)) {
  122 + this.modelValue = Object.assign(this.modelValue, {condition: {spec: {type: AlarmConditionType.SIMPLE}}});
123 123 }
124 124 this.alarmRuleFormGroup.reset(this.modelValue || undefined, {emitEvent: false});
125   - this.updateValidators(this.modelValue.condition.spec.type);
  125 + this.updateValidators(this.modelValue?.condition?.spec?.type);
126 126 }
127 127
128 128 public validate(c: FormControl) {
... ...
... ... @@ -35,7 +35,7 @@
35 35 </tb-timezone-select>
36 36 <section *ngIf="alarmScheduleForm.get('type').value === alarmScheduleType.SPECIFIC_TIME">
37 37 <div class="tb-small" style="margin-bottom: 0.5em" translate>device-profile.schedule-days</div>
38   - <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap="16px" style="padding-bottom: 16px;">
  38 + <div fxLayout="column" fxLayout.gt-md="row" fxLayoutGap="16px" style="padding-bottom: 16px;">
39 39 <div fxLayout="row" fxLayoutGap="16px">
40 40 <mat-checkbox [formControl]="weeklyRepeatControl(0)">
41 41 {{ 'device-profile.schedule-day.monday' | translate }}
... ... @@ -64,158 +64,189 @@
64 64 </div>
65 65 <div class="tb-small" style="margin-bottom: 0.5em" translate>device-profile.schedule-time</div>
66 66 <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
67   - <mat-form-field fxFlex>
68   - <mat-label translate>device-profile.schedule-time-from</mat-label>
69   - <mat-datetimepicker-toggle [for]="startTimePicker" matPrefix></mat-datetimepicker-toggle>
70   - <mat-datetimepicker #startTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
71   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker">
72   - </mat-form-field>
73   - <mat-form-field fxFlex>
74   - <mat-label translate>device-profile.schedule-time-to</mat-label>
75   - <mat-datetimepicker-toggle [for]="endTimePicker" matPrefix></mat-datetimepicker-toggle>
76   - <mat-datetimepicker #endTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
77   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker">
78   - </mat-form-field>
  67 + <div fxLayout="row" fxLayoutGap="8px" fxFlex.gt-md>
  68 + <mat-form-field fxFlex.xs fxFlex.sm="150px" fxFlex.md="150px" fxFlex.gt-md>
  69 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  70 + <mat-datetimepicker-toggle [for]="startTimePicker" matPrefix></mat-datetimepicker-toggle>
  71 + <mat-datetimepicker #startTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
  72 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker">
  73 + </mat-form-field>
  74 + <mat-form-field fxFlex.xs fxFlex.sm="150px" fxFlex.md="150px" fxFlex.gt-md>
  75 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  76 + <mat-datetimepicker-toggle [for]="endTimePicker" matPrefix></mat-datetimepicker-toggle>
  77 + <mat-datetimepicker #endTimePicker type="time" openOnFocus="true"></mat-datetimepicker>
  78 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker">
  79 + </mat-form-field>
  80 + </div>
  81 + <div fxFlex fxLayoutAlign="center center" style="margin: auto">
  82 + <div style="text-align: center"
  83 + [innerHTML]="getSchedulerRangeText(alarmScheduleForm)">
  84 + </div>
  85 + </div>
79 86 </div>
80 87 </section>
81 88 <section *ngIf="alarmScheduleForm.get('type').value === alarmScheduleType.CUSTOM">
82 89 <div class="tb-small" style="margin-bottom: 0.5em" translate>device-profile.schedule-days</div>
83   - <div fxLayout="column" fxLayout.gt-sm="row" fxLayoutGap.gt-sm="16px" formArrayName="items">
84   - <div fxLayout="column" fxFlex fxFlex.gt-sm="50">
85   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="0" fxLayoutAlign="start center">
86   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 0)">
87   - {{ 'device-profile.schedule-day.monday' | translate }}
88   - </mat-checkbox>
89   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
90   - <mat-form-field fxFlex="100px">
91   - <mat-label translate>device-profile.schedule-time-from</mat-label>
92   - <mat-datetimepicker-toggle [for]="startTimePicker1" matPrefix></mat-datetimepicker-toggle>
93   - <mat-datetimepicker #startTimePicker1 type="time" openOnFocus="true"></mat-datetimepicker>
94   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker1">
95   - </mat-form-field>
96   - <mat-form-field fxFlex="100px">
97   - <mat-label translate>device-profile.schedule-time-to</mat-label>
98   - <mat-datetimepicker-toggle [for]="endTimePicker1" matPrefix></mat-datetimepicker-toggle>
99   - <mat-datetimepicker #endTimePicker1 type="time" openOnFocus="true"></mat-datetimepicker>
100   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker1">
101   - </mat-form-field>
102   - </div>
  90 + <div fxLayout="column" formArrayName="items" fxLayoutGap="1em">
  91 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="0" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  92 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 0)">
  93 + {{ 'device-profile.schedule-day.monday' | translate }}
  94 + </mat-checkbox>
  95 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  96 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  97 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  98 + <mat-datetimepicker-toggle [for]="startTimePicker1" matPrefix></mat-datetimepicker-toggle>
  99 + <mat-datetimepicker #startTimePicker1 type="time" openOnFocus="true"></mat-datetimepicker>
  100 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker1">
  101 + </mat-form-field>
  102 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  103 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  104 + <mat-datetimepicker-toggle [for]="endTimePicker1" matPrefix></mat-datetimepicker-toggle>
  105 + <mat-datetimepicker #endTimePicker1 type="time" openOnFocus="true"></mat-datetimepicker>
  106 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker1">
  107 + </mat-form-field>
103 108 </div>
104   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="1" fxLayoutAlign="start center">
105   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 1)">
106   - {{ 'device-profile.schedule-day.tuesday' | translate }}
107   - </mat-checkbox>
108   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
109   - <mat-form-field fxFlex="100px">
110   - <mat-label translate>device-profile.schedule-time-from</mat-label>
111   - <mat-datetimepicker-toggle [for]="startTimePicker2" matPrefix></mat-datetimepicker-toggle>
112   - <mat-datetimepicker #startTimePicker2 type="time" openOnFocus="true"></mat-datetimepicker>
113   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker2">
114   - </mat-form-field>
115   - <mat-form-field fxFlex="100px">
116   - <mat-label translate>device-profile.schedule-time-to</mat-label>
117   - <mat-datetimepicker-toggle [for]="endTimePicker2" matPrefix></mat-datetimepicker-toggle>
118   - <mat-datetimepicker #endTimePicker2 type="time" openOnFocus="true"></mat-datetimepicker>
119   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker2">
120   - </mat-form-field>
121   - </div>
  109 + <div fxFlex fxLayoutAlign="center center"
  110 + style="text-align: center"
  111 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(0))">
122 112 </div>
123   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="2" fxLayoutAlign="start center">
124   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 2)">
125   - {{ 'device-profile.schedule-day.wednesday' | translate }}
126   - </mat-checkbox>
127   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
128   - <mat-form-field fxFlex="100px">
129   - <mat-label translate>device-profile.schedule-time-from</mat-label>
130   - <mat-datetimepicker-toggle [for]="startTimePicker3" matPrefix></mat-datetimepicker-toggle>
131   - <mat-datetimepicker #startTimePicker3 type="time" openOnFocus="true"></mat-datetimepicker>
132   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker3">
133   - </mat-form-field>
134   - <mat-form-field fxFlex="100px">
135   - <mat-label translate>device-profile.schedule-time-to</mat-label>
136   - <mat-datetimepicker-toggle [for]="endTimePicker3" matPrefix></mat-datetimepicker-toggle>
137   - <mat-datetimepicker #endTimePicker3 type="time" openOnFocus="true"></mat-datetimepicker>
138   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker3">
139   - </mat-form-field>
140   - </div>
  113 + </div>
  114 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="1" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  115 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 1)">
  116 + {{ 'device-profile.schedule-day.tuesday' | translate }}
  117 + </mat-checkbox>
  118 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  119 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  120 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  121 + <mat-datetimepicker-toggle [for]="startTimePicker2" matPrefix></mat-datetimepicker-toggle>
  122 + <mat-datetimepicker #startTimePicker2 type="time" openOnFocus="true"></mat-datetimepicker>
  123 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker2">
  124 + </mat-form-field>
  125 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  126 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  127 + <mat-datetimepicker-toggle [for]="endTimePicker2" matPrefix></mat-datetimepicker-toggle>
  128 + <mat-datetimepicker #endTimePicker2 type="time" openOnFocus="true"></mat-datetimepicker>
  129 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker2">
  130 + </mat-form-field>
141 131 </div>
142   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="3" fxLayoutAlign="start center">
143   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 3)">
144   - {{ 'device-profile.schedule-day.thursday' | translate }}
145   - </mat-checkbox>
146   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
147   - <mat-form-field fxFlex="100px">
148   - <mat-label translate>device-profile.schedule-time-from</mat-label>
149   - <mat-datetimepicker-toggle [for]="startTimePicker4" matPrefix></mat-datetimepicker-toggle>
150   - <mat-datetimepicker #startTimePicker4 type="time" openOnFocus="true"></mat-datetimepicker>
151   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker4">
152   - </mat-form-field>
153   - <mat-form-field fxFlex="100px">
154   - <mat-label translate>device-profile.schedule-time-to</mat-label>
155   - <mat-datetimepicker-toggle [for]="endTimePicker4" matPrefix></mat-datetimepicker-toggle>
156   - <mat-datetimepicker #endTimePicker4 type="time" openOnFocus="true"></mat-datetimepicker>
157   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker4">
158   - </mat-form-field>
159   - </div>
  132 + <div fxFlex fxLayoutAlign="center center"
  133 + style="text-align: center"
  134 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(1))">
160 135 </div>
161 136 </div>
162   - <div fxLayout="column" fxFlex fxFlex.gt-sm="50">
163   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="4" fxLayoutAlign="start center">
164   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 4)">
165   - {{ 'device-profile.schedule-day.friday' | translate }}
166   - </mat-checkbox>
167   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
168   - <mat-form-field fxFlex="100px">
169   - <mat-label translate>device-profile.schedule-time-from</mat-label>
170   - <mat-datetimepicker-toggle [for]="startTimePicker5" matPrefix></mat-datetimepicker-toggle>
171   - <mat-datetimepicker #startTimePicker5 type="time" openOnFocus="true"></mat-datetimepicker>
172   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker5">
173   - </mat-form-field>
174   - <mat-form-field fxFlex="100px">
175   - <mat-label translate>device-profile.schedule-time-to</mat-label>
176   - <mat-datetimepicker-toggle [for]="endTimePicker5" matPrefix></mat-datetimepicker-toggle>
177   - <mat-datetimepicker #endTimePicker5 type="time" openOnFocus="true"></mat-datetimepicker>
178   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker5">
179   - </mat-form-field>
180   - </div>
  137 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="2" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  138 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 2)">
  139 + {{ 'device-profile.schedule-day.wednesday' | translate }}
  140 + </mat-checkbox>
  141 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  142 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  143 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  144 + <mat-datetimepicker-toggle [for]="startTimePicker3" matPrefix></mat-datetimepicker-toggle>
  145 + <mat-datetimepicker #startTimePicker3 type="time" openOnFocus="true"></mat-datetimepicker>
  146 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker3">
  147 + </mat-form-field>
  148 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  149 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  150 + <mat-datetimepicker-toggle [for]="endTimePicker3" matPrefix></mat-datetimepicker-toggle>
  151 + <mat-datetimepicker #endTimePicker3 type="time" openOnFocus="true"></mat-datetimepicker>
  152 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker3">
  153 + </mat-form-field>
  154 + </div>
  155 + <div fxFlex fxLayoutAlign="center center"
  156 + style="text-align: center"
  157 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(2))">
  158 + </div>
  159 + </div>
  160 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="3" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  161 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 3)">
  162 + {{ 'device-profile.schedule-day.thursday' | translate }}
  163 + </mat-checkbox>
  164 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  165 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  166 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  167 + <mat-datetimepicker-toggle [for]="startTimePicker4" matPrefix></mat-datetimepicker-toggle>
  168 + <mat-datetimepicker #startTimePicker4 type="time" openOnFocus="true"></mat-datetimepicker>
  169 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker4">
  170 + </mat-form-field>
  171 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  172 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  173 + <mat-datetimepicker-toggle [for]="endTimePicker4" matPrefix></mat-datetimepicker-toggle>
  174 + <mat-datetimepicker #endTimePicker4 type="time" openOnFocus="true"></mat-datetimepicker>
  175 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker4">
  176 + </mat-form-field>
181 177 </div>
182   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="5" fxLayoutAlign="start center">
183   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 5)">
184   - {{ 'device-profile.schedule-day.saturday' | translate }}
185   - </mat-checkbox>
186   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
187   - <mat-form-field fxFlex="100px">
188   - <mat-label translate>device-profile.schedule-time-from</mat-label>
189   - <mat-datetimepicker-toggle [for]="startTimePicker6" matPrefix></mat-datetimepicker-toggle>
190   - <mat-datetimepicker #startTimePicker6 type="time" openOnFocus="true"></mat-datetimepicker>
191   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker6">
192   - </mat-form-field>
193   - <mat-form-field fxFlex="100px">
194   - <mat-label translate>device-profile.schedule-time-to</mat-label>
195   - <mat-datetimepicker-toggle [for]="endTimePicker6" matPrefix></mat-datetimepicker-toggle>
196   - <mat-datetimepicker #endTimePicker6 type="time" openOnFocus="true"></mat-datetimepicker>
197   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker6">
198   - </mat-form-field>
199   - </div>
  178 + <div fxFlex fxLayoutAlign="center center"
  179 + style="text-align: center"
  180 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(3))">
  181 + </div>
  182 + </div>
  183 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="4" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  184 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 4)">
  185 + {{ 'device-profile.schedule-day.friday' | translate }}
  186 + </mat-checkbox>
  187 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  188 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  189 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  190 + <mat-datetimepicker-toggle [for]="startTimePicker5" matPrefix></mat-datetimepicker-toggle>
  191 + <mat-datetimepicker #startTimePicker5 type="time" openOnFocus="true"></mat-datetimepicker>
  192 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker5">
  193 + </mat-form-field>
  194 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  195 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  196 + <mat-datetimepicker-toggle [for]="endTimePicker5" matPrefix></mat-datetimepicker-toggle>
  197 + <mat-datetimepicker #endTimePicker5 type="time" openOnFocus="true"></mat-datetimepicker>
  198 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker5">
  199 + </mat-form-field>
  200 + </div>
  201 + <div fxFlex fxLayoutAlign="center center"
  202 + style="text-align: center"
  203 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(4))">
  204 + </div>
  205 + </div>
  206 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="5" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  207 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 5)">
  208 + {{ 'device-profile.schedule-day.saturday' | translate }}
  209 + </mat-checkbox>
  210 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  211 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  212 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  213 + <mat-datetimepicker-toggle [for]="startTimePicker6" matPrefix></mat-datetimepicker-toggle>
  214 + <mat-datetimepicker #startTimePicker6 type="time" openOnFocus="true"></mat-datetimepicker>
  215 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker6">
  216 + </mat-form-field>
  217 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  218 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  219 + <mat-datetimepicker-toggle [for]="endTimePicker6" matPrefix></mat-datetimepicker-toggle>
  220 + <mat-datetimepicker #endTimePicker6 type="time" openOnFocus="true"></mat-datetimepicker>
  221 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker6">
  222 + </mat-form-field>
  223 + </div>
  224 + <div fxFlex fxLayoutAlign="center center"
  225 + style="text-align: center"
  226 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(5))">
  227 + </div>
  228 + </div>
  229 + <div fxLayout.xs="column" fxLayout="row" fxLayoutGap="8px" formGroupName="6" fxLayoutAlign="start center" fxLayoutAlign.xs="center start">
  230 + <mat-checkbox formControlName="enabled" fxFlex="17" (change)="changeCustomScheduler($event, 6)">
  231 + {{ 'device-profile.schedule-day.sunday' | translate }}
  232 + </mat-checkbox>
  233 + <div fxLayout="row" fxLayoutGap="8px" fxFlex>
  234 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  235 + <mat-label translate>device-profile.schedule-time-from</mat-label>
  236 + <mat-datetimepicker-toggle [for]="startTimePicker7" matPrefix></mat-datetimepicker-toggle>
  237 + <mat-datetimepicker #startTimePicker7 type="time" openOnFocus="true"></mat-datetimepicker>
  238 + <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker7">
  239 + </mat-form-field>
  240 + <mat-form-field fxFlex.xs fxFlex.sm="100px" fxFlex.md="100px">
  241 + <mat-label translate>device-profile.schedule-time-to</mat-label>
  242 + <mat-datetimepicker-toggle [for]="endTimePicker7" matPrefix></mat-datetimepicker-toggle>
  243 + <mat-datetimepicker #endTimePicker7 type="time" openOnFocus="true"></mat-datetimepicker>
  244 + <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker7">
  245 + </mat-form-field>
200 246 </div>
201   - <div fxLayout="row" fxLayoutGap="8px" formGroupName="6" fxLayoutAlign="start center">
202   - <mat-checkbox formControlName="enabled" fxFlex="40" (change)="changeCustomScheduler($event, 6)">
203   - {{ 'device-profile.schedule-day.sunday' | translate }}
204   - </mat-checkbox>
205   - <div fxLayout="row" fxLayoutGap="8px" fxFlex>
206   - <mat-form-field fxFlex="100px">
207   - <mat-label translate>device-profile.schedule-time-from</mat-label>
208   - <mat-datetimepicker-toggle [for]="startTimePicker7" matPrefix></mat-datetimepicker-toggle>
209   - <mat-datetimepicker #startTimePicker7 type="time" openOnFocus="true"></mat-datetimepicker>
210   - <input required matInput formControlName="startsOn" [matDatetimepicker]="startTimePicker7">
211   - </mat-form-field>
212   - <mat-form-field fxFlex="100px">
213   - <mat-label translate>device-profile.schedule-time-to</mat-label>
214   - <mat-datetimepicker-toggle [for]="endTimePicker7" matPrefix></mat-datetimepicker-toggle>
215   - <mat-datetimepicker #endTimePicker7 type="time" openOnFocus="true"></mat-datetimepicker>
216   - <input required matInput formControlName="endsOn" [matDatetimepicker]="endTimePicker7">
217   - </mat-form-field>
218   - </div>
  247 + <div fxFlex fxLayoutAlign="center center"
  248 + style="text-align: center"
  249 + [innerHTML]="getSchedulerRangeText(itemsSchedulerForm.at(6))">
219 250 </div>
220 251 </div>
221 252 </div>
... ...
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +::ng-deep {
  17 + .nowrap {
  18 + white-space: nowrap;
  19 + }
  20 +}
... ...
... ... @@ -16,6 +16,7 @@
16 16
17 17 import { Component, forwardRef, Input, OnInit } from '@angular/core';
18 18 import {
  19 + AbstractControl,
19 20 ControlValueAccessor,
20 21 FormArray,
21 22 FormBuilder,
... ... @@ -35,6 +36,7 @@ import { MatCheckboxChange } from '@angular/material/checkbox';
35 36 @Component({
36 37 selector: 'tb-alarm-schedule',
37 38 templateUrl: './alarm-schedule.component.html',
  39 + styleUrls: ['./alarm-schedule.component.scss'],
38 40 providers: [{
39 41 provide: NG_VALUE_ACCESSOR,
40 42 useExisting: forwardRef(() => AlarmScheduleComponent),
... ... @@ -79,7 +81,7 @@ export class AlarmScheduleComponent implements ControlValueAccessor, Validator,
79 81 items: this.fb.array(Array.from({length: 7}, (value, i) => this.defaultItemsScheduler(i)))
80 82 });
81 83 this.alarmScheduleForm.get('type').valueChanges.subscribe((type) => {
82   - this.alarmScheduleForm.reset({type, items: this.defaultItems}, {emitEvent: false});
  84 + this.alarmScheduleForm.reset({type, items: this.defaultItems, timezone: this.defaultTimezone}, {emitEvent: false});
83 85 this.updateValidators(type, true);
84 86 this.alarmScheduleForm.updateValueAndValidity();
85 87 });
... ... @@ -131,13 +133,7 @@ export class AlarmScheduleComponent implements ControlValueAccessor, Validator,
131 133 this.modelValue.items
132 134 .sort((a, b) => a.dayOfWeek - b.dayOfWeek)
133 135 .forEach((item, index) => {
134   - if (item.enabled) {
135   - this.itemsSchedulerForm.at(index).get('startsOn').enable({emitEvent: false});
136   - this.itemsSchedulerForm.at(index).get('endsOn').enable({emitEvent: false});
137   - } else {
138   - this.itemsSchedulerForm.at(index).get('startsOn').disable({emitEvent: false});
139   - this.itemsSchedulerForm.at(index).get('endsOn').disable({emitEvent: false});
140   - }
  136 + this.disabledSelectedTime(item.enabled, index);
141 137 alarmDays.push({
142 138 enabled: item.enabled,
143 139 startsOn: this.timestampToTime(item.startsOn),
... ... @@ -206,15 +202,15 @@ export class AlarmScheduleComponent implements ControlValueAccessor, Validator,
206 202 .filter(day => !!day);
207 203 }
208 204 if (isDefined(value.startsOn) && value.startsOn !== 0) {
209   - value.startsOn = this.timeToTimestamp(value.startsOn);
  205 + value.startsOn = this.timeToTimestampUTC(value.startsOn);
210 206 }
211 207 if (isDefined(value.endsOn) && value.endsOn !== 0) {
212   - value.endsOn = this.timeToTimestamp(value.endsOn);
  208 + value.endsOn = this.timeToTimestampUTC(value.endsOn);
213 209 }
214 210 if (isDefined(value.items)){
215 211 value.items = this.alarmScheduleForm.getRawValue().items;
216 212 value.items = value.items.map((item) => {
217   - return { ...item, startsOn: this.timeToTimestamp(item.startsOn), endsOn: this.timeToTimestamp(item.endsOn)};
  213 + return { ...item, startsOn: this.timeToTimestampUTC(item.startsOn), endsOn: this.timeToTimestampUTC(item.endsOn)};
218 214 });
219 215 }
220 216 this.modelValue = value;
... ... @@ -222,7 +218,7 @@ export class AlarmScheduleComponent implements ControlValueAccessor, Validator,
222 218 }
223 219 }
224 220
225   - private timeToTimestamp(date: Date | number): number {
  221 + private timeToTimestampUTC(date: Date | number): number {
226 222 if (typeof date === 'number' || date === null) {
227 223 return 0;
228 224 }
... ... @@ -244,16 +240,39 @@ export class AlarmScheduleComponent implements ControlValueAccessor, Validator,
244 240
245 241 changeCustomScheduler($event: MatCheckboxChange, index: number) {
246 242 const value = $event.checked;
247   - if (value) {
  243 + this.disabledSelectedTime(value, index, true);
  244 + }
  245 +
  246 + private disabledSelectedTime(enable: boolean, index: number, emitEvent = false) {
  247 + if (enable) {
248 248 this.itemsSchedulerForm.at(index).get('startsOn').enable({emitEvent: false});
249   - this.itemsSchedulerForm.at(index).get('endsOn').enable();
  249 + this.itemsSchedulerForm.at(index).get('endsOn').enable({emitEvent});
250 250 } else {
251 251 this.itemsSchedulerForm.at(index).get('startsOn').disable({emitEvent: false});
252   - this.itemsSchedulerForm.at(index).get('endsOn').disable();
  252 + this.itemsSchedulerForm.at(index).get('endsOn').disable({emitEvent});
  253 + }
  254 + }
  255 +
  256 + private timeToMoment(date: Date | number): _moment.Moment {
  257 + if (typeof date === 'number' || date === null) {
  258 + return _moment([1970, 0, 1, 0, 0, 0, 0]);
  259 + }
  260 + return _moment([1970, 0, 1, date.getHours(), date.getMinutes(), 0, 0]);
  261 + }
  262 +
  263 + getSchedulerRangeText(control: FormGroup | AbstractControl): string {
  264 + const start = this.timeToMoment(control.get('startsOn').value);
  265 + const end = this.timeToMoment(control.get('endsOn').value);
  266 + if (start < end) {
  267 + return `<span><span class="nowrap">${start.format('hh:mm A')}</span> – <span class="nowrap">${end.format('hh:mm A')}</span></span>`;
  268 + } else if (start.valueOf() === 0 && end.valueOf() === 0 || start.isSame(_moment([1970, 0])) && end.isSame(_moment([1970, 0]))) {
  269 + return '<span><span class="nowrap">12:00 AM</span> – <span class="nowrap">12:00 PM</span></span>';
253 270 }
  271 + return `<span><span class="nowrap">12:00 AM</span> – <span class="nowrap">${end.format('hh:mm A')}</span>` +
  272 + ` and <span class="nowrap">${start.format('hh:mm A')}</span> – <span class="nowrap">12:00 PM</span></span>`;
254 273 }
255 274
256   - private get itemsSchedulerForm(): FormArray {
  275 + get itemsSchedulerForm(): FormArray {
257 276 return this.alarmScheduleForm.get('items') as FormArray;
258 277 }
259 278 }
... ...
... ... @@ -39,7 +39,7 @@
39 39 </mat-tab>
40 40 <mat-tab *ngIf="entity"
41 41 label="{{'device-profile.alarm-rules' | translate:
42   - {count: entity.profileData.alarms.length ?
  42 + {count: entity.profileData.alarms && entity.profileData.alarms.length ?
43 43 entity.profileData.alarms.length : 0} }}" #alarmRules="matTab">
44 44 <div class="mat-padding" [formGroup]="detailsForm">
45 45 <div formGroupName="profileData">
... ...