Commit bb06f5ebe078035262544eb3501466b0f3a9f918

Authored by Chantsova Ekaterina
1 parent fe27cb1a

Add min/max validation

@@ -53,12 +53,20 @@ @@ -53,12 +53,20 @@
53 [readonly]="key.settings.isEditable === 'readonly'" 53 [readonly]="key.settings.isEditable === 'readonly'"
54 type="number" 54 type="number"
55 step="{{key.settings.step}}" 55 step="{{key.settings.step}}"
  56 + min="{{key.settings.minValue}}"
  57 + max="{{key.settings.maxValue}}"
56 (focus)="key.isFocused = true; focusInputElement($event)" 58 (focus)="key.isFocused = true; focusInputElement($event)"
57 (blur)="key.isFocused = false; inputChanged(source, key)"> 59 (blur)="key.isFocused = false; inputChanged(source, key)">
58 <mat-icon *ngIf="key.settings.icon" matPrefix>{{key.settings.icon}}</mat-icon> 60 <mat-icon *ngIf="key.settings.icon" matPrefix>{{key.settings.icon}}</mat-icon>
59 <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')"> 61 <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
60 {{key.settings.requiredErrorMessage}} 62 {{key.settings.requiredErrorMessage}}
61 </mat-error> 63 </mat-error>
  64 + <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('min')">
  65 + {{ 'widgets.input-widgets.min-value-error' | translate:{value: key.settings.minValue} }}
  66 + </mat-error>
  67 + <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('max')">
  68 + {{ 'widgets.input-widgets.max-value-error' | translate:{value: key.settings.maxValue} }}
  69 + </mat-error>
62 </mat-form-field> 70 </mat-form-field>
63 </div> 71 </div>
64 <div class="input-field mat-block" *ngIf="key.settings.dataKeyValueType === 'booleanCheckbox'"> 72 <div class="input-field mat-block" *ngIf="key.settings.dataKeyValueType === 'booleanCheckbox'">
@@ -92,6 +100,9 @@ @@ -92,6 +100,9 @@
92 <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')"> 100 <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('required')">
93 {{key.settings.requiredErrorMessage}} 101 {{key.settings.requiredErrorMessage}}
94 </mat-error> 102 </mat-error>
  103 + <mat-error *ngIf="multipleInputFormGroup.get(key.formId).hasError('matDatepickerParse')">
  104 + {{ 'widgets.input-widgets.invalid-date' | translate }}
  105 + </mat-error>
95 </mat-form-field> 106 </mat-form-field>
96 </div> 107 </div>
97 </div> 108 </div>
@@ -24,7 +24,7 @@ import { UtilsService } from '@core/services/utils.service'; @@ -24,7 +24,7 @@ import { UtilsService } from '@core/services/utils.service';
24 import { TranslateService } from '@ngx-translate/core'; 24 import { TranslateService } from '@ngx-translate/core';
25 import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; 25 import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models';
26 import { IWidgetSubscription } from '@core/api/widget-api.models'; 26 import { IWidgetSubscription } from '@core/api/widget-api.models';
27 -import { isDefined, isEqual, isUndefined, createLabelFromDatasource } from '@core/utils'; 27 +import { isDefined, isEqual, isUndefined, createLabelFromDatasource, isDefinedAndNotNull } from '@core/utils';
28 import { EntityType } from '@shared/models/entity-type.models'; 28 import { EntityType } from '@shared/models/entity-type.models';
29 import * as _moment from 'moment'; 29 import * as _moment from 'moment';
30 import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; 30 import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
@@ -62,19 +62,32 @@ interface MultipleInputWidgetDataKeySettings { @@ -62,19 +62,32 @@ interface MultipleInputWidgetDataKeySettings {
62 isEditable: MultipleInputWidgetDataKeyEditableType; 62 isEditable: MultipleInputWidgetDataKeyEditableType;
63 disabledOnDataKey: string; 63 disabledOnDataKey: string;
64 dataKeyHidden: boolean; 64 dataKeyHidden: boolean;
65 - step: number;  
66 - requiredErrorMessage: string; 65 + step?: number;
  66 + minValue?: number;
  67 + maxValue?: number;
  68 + requiredErrorMessage?: string;
  69 + invalidDateErrorMessage?: string;
  70 + minErrorMessage?: string;
  71 + maxErrorMessage?: string;
67 icon: string; 72 icon: string;
68 inputTypeNumber?: boolean; 73 inputTypeNumber?: boolean;
69 readOnly?: boolean; 74 readOnly?: boolean;
70 disabledOnCondition?: boolean; 75 disabledOnCondition?: boolean;
71 } 76 }
72 77
  78 +interface MultipleInputWidgetDataKeyErrorMessages {
  79 + requiredErrorMessage?: string;
  80 + invalidDateErrorMessage?: string;
  81 + minErrorMessage?: string;
  82 + maxErrorMessage?: string;
  83 +}
  84 +
73 interface MultipleInputWidgetDataKey extends DataKey { 85 interface MultipleInputWidgetDataKey extends DataKey {
74 formId?: string; 86 formId?: string;
75 settings: MultipleInputWidgetDataKeySettings; 87 settings: MultipleInputWidgetDataKeySettings;
76 isFocused: boolean; 88 isFocused: boolean;
77 value?: any; 89 value?: any;
  90 + errorMessages?: MultipleInputWidgetDataKeyErrorMessages;
78 } 91 }
79 92
80 interface MultipleInputWidgetSource { 93 interface MultipleInputWidgetSource {
@@ -195,7 +208,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -195,7 +208,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
195 if (dataKey.units) { 208 if (dataKey.units) {
196 dataKey.label += ' (' + dataKey.units + ')'; 209 dataKey.label += ' (' + dataKey.units + ')';
197 } 210 }
198 - dataKey.formId = (++keyIndex)+''; 211 + dataKey.formId = (++keyIndex) + '';
199 dataKey.isFocused = false; 212 dataKey.isFocused = false;
200 213
201 // For backward compatibility 214 // For backward compatibility
@@ -245,6 +258,14 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -245,6 +258,14 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
245 if (key.settings.dataKeyValueType === 'integer') { 258 if (key.settings.dataKeyValueType === 'integer') {
246 validators.push(Validators.pattern(/^-?[0-9]+$/)); 259 validators.push(Validators.pattern(/^-?[0-9]+$/));
247 } 260 }
  261 + if (key.settings.dataKeyValueType === 'integer' || key.settings.dataKeyValueType === 'double') {
  262 + if (isDefinedAndNotNull(key.settings.minValue) && isFinite(key.settings.minValue)) {
  263 + validators.push(Validators.min(key.settings.minValue));
  264 + }
  265 + if (isDefinedAndNotNull(key.settings.maxValue) && isFinite(key.settings.maxValue)) {
  266 + validators.push(Validators.max(key.settings.maxValue));
  267 + }
  268 + }
248 const formControl = this.fb.control( 269 const formControl = this.fb.control(
249 { value: key.value, 270 { value: key.value,
250 disabled: key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition}, 271 disabled: key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition},
@@ -265,7 +286,11 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -265,7 +286,11 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
265 switch (key.settings.dataKeyValueType) { 286 switch (key.settings.dataKeyValueType) {
266 case 'dateTime': 287 case 'dateTime':
267 case 'date': 288 case 'date':
268 - value = _moment(keyData[0][1]).toDate(); 289 + if (isDefinedAndNotNull(keyData[0][1]) && keyData[0][1] !== '') {
  290 + value = _moment(keyData[0][1]).toDate();
  291 + } else {
  292 + value = null;
  293 + }
269 break; 294 break;
270 case 'time': 295 case 'time':
271 value = _moment().startOf('day').add(keyData[0][1], 'ms').toDate(); 296 value = _moment().startOf('day').add(keyData[0][1], 'ms').toDate();
@@ -455,7 +480,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -455,7 +480,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
455 if (tasks.length) { 480 if (tasks.length) {
456 forkJoin(tasks).subscribe( 481 forkJoin(tasks).subscribe(
457 () => { 482 () => {
458 - this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); 483 + // this.multipleInputFormGroup.reset(undefined, {emitEvent: false});
459 this.multipleInputFormGroup.markAsPristine(); 484 this.multipleInputFormGroup.markAsPristine();
460 if (this.settings.showResultMessage) { 485 if (this.settings.showResultMessage) {
461 this.ctx.showSuccessToast(this.translate.instant('widgets.input-widgets.update-successful'), 486 this.ctx.showSuccessToast(this.translate.instant('widgets.input-widgets.update-successful'),
@@ -469,7 +494,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni @@ -469,7 +494,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni
469 } 494 }
470 }); 495 });
471 } else { 496 } else {
472 - this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); 497 + // this.multipleInputFormGroup.reset(undefined, {emitEvent: false});
473 this.multipleInputFormGroup.markAsPristine(); 498 this.multipleInputFormGroup.markAsPristine();
474 } 499 }
475 } 500 }
@@ -1991,8 +1991,11 @@ @@ -1991,8 +1991,11 @@
1991 "entity-coordinate-required": "Both fields, latitude and longitude, are required", 1991 "entity-coordinate-required": "Both fields, latitude and longitude, are required",
1992 "entity-timeseries-required": "Entity timeseries is required", 1992 "entity-timeseries-required": "Entity timeseries is required",
1993 "get-location": "Get current location", 1993 "get-location": "Get current location",
  1994 + "invalid-date": "Invalid Date",
1994 "latitude": "Latitude", 1995 "latitude": "Latitude",
1995 "longitude": "Longitude", 1996 "longitude": "Longitude",
  1997 + "min-value-error": "Min value is {{value}}",
  1998 + "max-value-error": "Max value is {{value}}",
1996 "not-allowed-entity": "Selected entity cannot have shared attributes", 1999 "not-allowed-entity": "Selected entity cannot have shared attributes",
1997 "no-attribute-selected": "No attribute is selected", 2000 "no-attribute-selected": "No attribute is selected",
1998 "no-datakey-selected": "No datakey is selected", 2001 "no-datakey-selected": "No datakey is selected",