From bb06f5ebe078035262544eb3501466b0f3a9f918 Mon Sep 17 00:00:00 2001 From: Chantsova Ekaterina Date: Tue, 15 Sep 2020 18:14:31 +0300 Subject: [PATCH 1/4] Add min/max validation --- .../lib/multiple-input-widget.component.html | 11 ++++++ .../lib/multiple-input-widget.component.ts | 39 +++++++++++++++---- .../assets/locale/locale.constant-en_US.json | 3 ++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html index 659a8156cb..1423000d4a 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html @@ -53,12 +53,20 @@ [readonly]="key.settings.isEditable === 'readonly'" type="number" step="{{key.settings.step}}" + min="{{key.settings.minValue}}" + max="{{key.settings.maxValue}}" (focus)="key.isFocused = true; focusInputElement($event)" (blur)="key.isFocused = false; inputChanged(source, key)"> {{key.settings.icon}} {{key.settings.requiredErrorMessage}} + + {{ 'widgets.input-widgets.min-value-error' | translate:{value: key.settings.minValue} }} + + + {{ 'widgets.input-widgets.max-value-error' | translate:{value: key.settings.maxValue} }} +
@@ -92,6 +100,9 @@ {{key.settings.requiredErrorMessage}} + + {{ 'widgets.input-widgets.invalid-date' | translate }} +
diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index e26600a939..21a8d1d062 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -24,7 +24,7 @@ import { UtilsService } from '@core/services/utils.service'; import { TranslateService } from '@ngx-translate/core'; import { DataKey, Datasource, DatasourceData, DatasourceType, WidgetConfig } from '@shared/models/widget.models'; import { IWidgetSubscription } from '@core/api/widget-api.models'; -import { isDefined, isEqual, isUndefined, createLabelFromDatasource } from '@core/utils'; +import { isDefined, isEqual, isUndefined, createLabelFromDatasource, isDefinedAndNotNull } from '@core/utils'; import { EntityType } from '@shared/models/entity-type.models'; import * as _moment from 'moment'; import { FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms'; @@ -62,19 +62,32 @@ interface MultipleInputWidgetDataKeySettings { isEditable: MultipleInputWidgetDataKeyEditableType; disabledOnDataKey: string; dataKeyHidden: boolean; - step: number; - requiredErrorMessage: string; + step?: number; + minValue?: number; + maxValue?: number; + requiredErrorMessage?: string; + invalidDateErrorMessage?: string; + minErrorMessage?: string; + maxErrorMessage?: string; icon: string; inputTypeNumber?: boolean; readOnly?: boolean; disabledOnCondition?: boolean; } +interface MultipleInputWidgetDataKeyErrorMessages { + requiredErrorMessage?: string; + invalidDateErrorMessage?: string; + minErrorMessage?: string; + maxErrorMessage?: string; +} + interface MultipleInputWidgetDataKey extends DataKey { formId?: string; settings: MultipleInputWidgetDataKeySettings; isFocused: boolean; value?: any; + errorMessages?: MultipleInputWidgetDataKeyErrorMessages; } interface MultipleInputWidgetSource { @@ -195,7 +208,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni if (dataKey.units) { dataKey.label += ' (' + dataKey.units + ')'; } - dataKey.formId = (++keyIndex)+''; + dataKey.formId = (++keyIndex) + ''; dataKey.isFocused = false; // For backward compatibility @@ -245,6 +258,14 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni if (key.settings.dataKeyValueType === 'integer') { validators.push(Validators.pattern(/^-?[0-9]+$/)); } + if (key.settings.dataKeyValueType === 'integer' || key.settings.dataKeyValueType === 'double') { + if (isDefinedAndNotNull(key.settings.minValue) && isFinite(key.settings.minValue)) { + validators.push(Validators.min(key.settings.minValue)); + } + if (isDefinedAndNotNull(key.settings.maxValue) && isFinite(key.settings.maxValue)) { + validators.push(Validators.max(key.settings.maxValue)); + } + } const formControl = this.fb.control( { value: key.value, disabled: key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition}, @@ -265,7 +286,11 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni switch (key.settings.dataKeyValueType) { case 'dateTime': case 'date': - value = _moment(keyData[0][1]).toDate(); + if (isDefinedAndNotNull(keyData[0][1]) && keyData[0][1] !== '') { + value = _moment(keyData[0][1]).toDate(); + } else { + value = null; + } break; case 'time': value = _moment().startOf('day').add(keyData[0][1], 'ms').toDate(); @@ -455,7 +480,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni if (tasks.length) { forkJoin(tasks).subscribe( () => { - this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); + // this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); this.multipleInputFormGroup.markAsPristine(); if (this.settings.showResultMessage) { this.ctx.showSuccessToast(this.translate.instant('widgets.input-widgets.update-successful'), @@ -469,7 +494,7 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni } }); } else { - this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); + // this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); this.multipleInputFormGroup.markAsPristine(); } } 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 9c36e0ee68..0258408d15 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1991,8 +1991,11 @@ "entity-coordinate-required": "Both fields, latitude and longitude, are required", "entity-timeseries-required": "Entity timeseries is required", "get-location": "Get current location", + "invalid-date": "Invalid Date", "latitude": "Latitude", "longitude": "Longitude", + "min-value-error": "Min value is {{value}}", + "max-value-error": "Max value is {{value}}", "not-allowed-entity": "Selected entity cannot have shared attributes", "no-attribute-selected": "No attribute is selected", "no-datakey-selected": "No datakey is selected", From ed2920eddc365383a50eb3ed087929d12b398609 Mon Sep 17 00:00:00 2001 From: Chantsova Ekaterina Date: Mon, 5 Oct 2020 18:00:26 +0300 Subject: [PATCH 2/4] Remove form reset when saving, add translatable error messages --- .../lib/multiple-input-widget.component.html | 60 ++++++++++--------- .../lib/multiple-input-widget.component.scss | 22 +++---- .../lib/multiple-input-widget.component.ts | 56 +++++++++++------ 3 files changed, 76 insertions(+), 62 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html index 1423000d4a..6d2b4d4a30 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html @@ -39,7 +39,7 @@ (blur)="key.isFocused = false; inputChanged(source, key)"> {{key.settings.icon}} - {{key.settings.requiredErrorMessage}} + {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} @@ -59,52 +59,54 @@ (blur)="key.isFocused = false; inputChanged(source, key)"> {{key.settings.icon}} - {{key.settings.requiredErrorMessage}} + {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} - {{ 'widgets.input-widgets.min-value-error' | translate:{value: key.settings.minValue} }} + {{ getErrorMessageText(key.settings.minValueErrorMessage, + 'widgets.input-widgets.min-value-error', + {value: key.settings.minValue}) }} - {{ 'widgets.input-widgets.max-value-error' | translate:{value: key.settings.maxValue} }} + {{ getErrorMessageText(key.settings.maxValueErrorMessage, + 'widgets.input-widgets.max-value-error', + {value: key.settings.maxValue}) }}
- {{key.label}} + {{key.label}}
- {{key.label}} + {{key.label}}
-
- - {{key.label}} - - - - - {{key.settings.requiredErrorMessage}} - - - {{ 'widgets.input-widgets.invalid-date' | translate }} - - -
+ + {{key.label}} + + + + + {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} + + + {{ getErrorMessageText(key.settings.invalidDateErrorMessage, 'widgets.input-widgets.invalid-date') }} + +
@@ -114,12 +116,12 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss index de1a672535..a5afcfabf3 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.scss @@ -44,7 +44,13 @@ display: block; margin-top: 20px; margin-bottom: 16px; - white-space: normal; + .label-wrapper { + white-space: normal; + } + } + + mat-slide-toggle { + height: auto; } .date-time-input { @@ -56,20 +62,6 @@ .vertical-alignment { flex-direction: column; - - mat-checkbox, - mat-slide-toggle { - margin-top: 18px; - } - - mat-slide-toggle { - display: flex; - justify-content: space-between; - } - } - - .vertically-aligned { - flex-direction: column; } } } diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index 21a8d1d062..361b1a06e9 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -47,6 +47,8 @@ interface MultipleInputWidgetSettings { widgetTitle: string; showActionButtons: boolean; updateAllValues: boolean; + saveButtonLabel: string; + resetButtonLabel: string; showResultMessage: boolean; showGroupTitle: boolean; groupTitle: string; @@ -67,27 +69,19 @@ interface MultipleInputWidgetDataKeySettings { maxValue?: number; requiredErrorMessage?: string; invalidDateErrorMessage?: string; - minErrorMessage?: string; - maxErrorMessage?: string; + minValueErrorMessage?: string; + maxValueErrorMessage?: string; icon: string; inputTypeNumber?: boolean; readOnly?: boolean; disabledOnCondition?: boolean; } -interface MultipleInputWidgetDataKeyErrorMessages { - requiredErrorMessage?: string; - invalidDateErrorMessage?: string; - minErrorMessage?: string; - maxErrorMessage?: string; -} - interface MultipleInputWidgetDataKey extends DataKey { formId?: string; settings: MultipleInputWidgetDataKeySettings; isFocused: boolean; value?: any; - errorMessages?: MultipleInputWidgetDataKeyErrorMessages; } interface MultipleInputWidgetSource { @@ -170,6 +164,17 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni this.settings.groupTitle = this.settings.groupTitle || '${entityName}'; + if (this.settings.saveButtonLabel && this.settings.saveButtonLabel.length) { + this.settings.saveButtonLabel = this.utils.customTranslation(this.settings.saveButtonLabel, this.settings.saveButtonLabel); + } else { + this.settings.saveButtonLabel = this.translate.instant('action.save'); + } + if (this.settings.resetButtonLabel && this.settings.resetButtonLabel.length) { + this.settings.resetButtonLabel = this.utils.customTranslation(this.settings.resetButtonLabel, this.settings.resetButtonLabel); + } else { + this.settings.resetButtonLabel = this.translate.instant('action.undo'); + } + // For backward compatibility if (isUndefined(this.settings.showActionButtons)) { this.settings.showActionButtons = true; @@ -338,25 +343,40 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni private updateWidgetDisplaying() { this.changeAlignment = (this.ctx.$container && this.ctx.$container[0].offsetWidth < 620); - this.smallWidthContainer = (this.ctx.$container && this.ctx.$container[0].offsetWidth < 420); } public onDataUpdated() { - this.ngZone.run(() => { + // this.ngZone.run(() => { this.updateWidgetData(this.subscription.data); this.ctx.detectChanges(); - }); + // }); } private resize() { - this.ngZone.run(() => { + // this.ngZone.run(() => { this.updateWidgetDisplaying(); this.ctx.detectChanges(); - }); + // }); } public getGroupTitle(datasource: Datasource): string { - return createLabelFromDatasource(datasource, this.settings.groupTitle); + const groupTitle = createLabelFromDatasource(datasource, this.settings.groupTitle); + return this.utils.customTranslation(groupTitle, groupTitle); + } + + public getErrorMessageText(errorMessage, defaultMessage, messageValues?): string { + let messageText; + if (errorMessage && errorMessage.length) { + messageText = this.utils.customTranslation(errorMessage, errorMessage); + } else if (defaultMessage && defaultMessage.length) { + if (!messageValues) { + messageValues = {}; + } + messageText = this.translate.instant(defaultMessage, messageValues); + } else { + messageText = ''; + } + return messageText; } public visibleKeys(source: MultipleInputWidgetSource): MultipleInputWidgetDataKey[] { @@ -480,8 +500,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni if (tasks.length) { forkJoin(tasks).subscribe( () => { - // this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); this.multipleInputFormGroup.markAsPristine(); + this.ctx.detectChanges(); if (this.settings.showResultMessage) { this.ctx.showSuccessToast(this.translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', this.toastTargetId); @@ -494,8 +514,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni } }); } else { - // this.multipleInputFormGroup.reset(undefined, {emitEvent: false}); this.multipleInputFormGroup.markAsPristine(); + this.ctx.detectChanges(); } } From aa87ab024e3ea513921f2be584d61137850e2cc2 Mon Sep 17 00:00:00 2001 From: Chantsova Ekaterina Date: Thu, 8 Oct 2020 16:21:04 +0300 Subject: [PATCH 3/4] Change widget json config --- .../system/widget_bundles/input_widgets.json | 4 ++-- .../lib/multiple-input-widget.component.html | 4 ++-- .../lib/multiple-input-widget.component.ts | 23 ++++++++----------- 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/application/src/main/data/json/system/widget_bundles/input_widgets.json b/application/src/main/data/json/system/widget_bundles/input_widgets.json index 1d5b28cba6..ac3486223a 100644 --- a/application/src/main/data/json/system/widget_bundles/input_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/input_widgets.json @@ -32,8 +32,8 @@ "templateHtml": "\n", "templateCss": ".tb-toast {\n min-width: 0;\n font-size: 14px !important;\n}", "controllerScript": "self.onInit = function() {\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.multipleInputWidget.onDataUpdated();\r\n}\r\n", - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"MultipleInput\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showActionButtons\":{\n \"title\":\"Show action buttons\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"updateAllValues\": {\n \"title\":\"Update all values, not only modified (only if action buttons are visible)\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"showGroupTitle\": {\n \"title\":\"Show title for group of fields, related to different entities\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"groupTitle\": {\n \"title\": \"Group title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"fieldsAlignment\": {\n \"title\": \"Fields alignment\",\n \"type\": \"string\",\n \"default\": \"row\"\n },\n \"fieldsInRow\": {\n \"title\": \"Number of fields in the row\",\n \"type\": \"number\",\n \"default\": \"2\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showActionButtons\",\n \"updateAllValues\",\n \"showResultMessage\",\n \"showGroupTitle\",\n \"groupTitle\",\n {\n \"key\": \"fieldsAlignment\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"row\",\n \"label\": \"Row (default)\"\n },\n {\n \"value\": \"column\",\n \"label\": \"Column\"\n }\n ]\n },\n \"fieldsInRow\"\n ]\n}", - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"dataKeyType\": {\n \"title\": \"Datakey type\",\n \"type\": \"string\",\n \"default\": \"server\"\n },\n \"dataKeyValueType\": {\n \"title\": \"Datakey value type\",\n \"type\": \"string\",\n \"default\": \"string\"\n },\n \"required\": {\n \"title\": \"Value is required\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"isEditable\": {\n \"title\": \"Ability to edit attribute\",\n \"type\": \"string\",\n \"default\": \"editable\"\n },\n \"disabledOnDataKey\": {\n \"title\": \"Disable on false value of another datakey (specify datakey name)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"dataKeyHidden\": {\n \"title\": \"Hide input field\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"step\": {\n \"title\": \"Step interval between values (only for numbers)\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"dataKeyType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"server\",\n \"label\": \"Server attribute (default)\"\n },\n {\n \"value\": \"shared\",\n \"label\": \"Shared attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Timeseries\"\n }\n ]\n },\n {\n \"key\": \"dataKeyValueType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"string\",\n \"label\": \"String\"\n },\n {\n \"value\": \"double\",\n \"label\": \"Double\"\n },\n {\n \"value\": \"integer\",\n \"label\": \"Integer\"\n },\n {\n \"value\": \"booleanCheckbox\",\n \"label\": \"Boolean (Checkbox)\"\n },\n {\n \"value\": \"booleanSwitch\",\n \"label\": \"Boolean (Switch)\"\n },\n {\n \"value\": \"dateTime\",\n \"label\": \"Date & Time\"\n },\n {\n \"value\": \"date\",\n \"label\": \"Date\"\n },\n {\n \"value\": \"time\",\n \"label\": \"Time\"\n }\n ]\n },\n \"required\",\n {\n \"key\": \"isEditable\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"editable\",\n \"label\": \"Editable (default)\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n },\n {\n \"value\": \"readonly\",\n \"label\": \"Read-only\"\n }\n ]\n },\n \"disabledOnDataKey\",\n \"dataKeyHidden\",\n \"step\",\n \"requiredErrorMessage\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t}\n ]\n}\n", + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"MultipleInput\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showActionButtons\":{\n \"title\":\"Show action buttons\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"updateAllValues\": {\n \"title\":\"Update all values, not only modified\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"saveButtonLabel\": {\n \"title\": \"'SAVE' button label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"resetButtonLabel\": {\n \"title\": \"'UNDO' button label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"showGroupTitle\": {\n \"title\":\"Show title for group of fields, related to different entities\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"groupTitle\": {\n \"title\": \"Group title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"fieldsAlignment\": {\n \"title\": \"Fields alignment\",\n \"type\": \"string\",\n \"default\": \"row\"\n },\n \"fieldsInRow\": {\n \"title\": \"Number of fields in the row\",\n \"type\": \"number\",\n \"default\": \"2\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showActionButtons\",\n {\n \"key\": \"updateAllValues\",\n \"condition\": \"model.showActionButtons === true\"\n },\n {\n \"key\": \"saveButtonLabel\",\n \"condition\": \"model.showActionButtons === true\"\n },\n {\n \"key\": \"resetButtonLabel\",\n \"condition\": \"model.showActionButtons === true\"\n },\n \"showResultMessage\",\n \"showGroupTitle\",\n \"groupTitle\",\n {\n \"key\": \"fieldsAlignment\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"row\",\n \"label\": \"Row (default)\"\n },\n {\n \"value\": \"column\",\n \"label\": \"Column\"\n }\n ]\n },\n {\n \"key\": \"fieldsInRow\",\n \"condition\": \"model.fieldsAlignment === 'row'\"\n }\n ]\n}", + "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"dataKeyType\": {\n \"title\": \"Datakey type\",\n \"type\": \"string\",\n \"default\": \"server\"\n },\n \"dataKeyValueType\": {\n \"title\": \"Datakey value type\",\n \"type\": \"string\",\n \"default\": \"string\"\n },\n \"step\": {\n \"title\": \"Step interval between values\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\"\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\"\n },\n \"required\": {\n \"title\": \"Value is required\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"minValueErrorMessage\": {\n \"title\": \"'Min Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValueErrorMessage\": {\n \"title\": \"'Max Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"invalidDateErrorMessage\": {\n \"title\": \"'Invalid Date' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"selectOptionsType\": {\n \"title\": \"Select options type\",\n \"type\": \"string\",\n \"default\": \"valueWithLabel\"\n },\n \"selectOptionsList\": {\n \"title\": \"Select options list\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"title\": \"Value\",\n \"type\": \"string\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n }\n },\n \"required\": [\"value\", \"label\"]\n }\n },\n \"isEditable\": {\n \"title\": \"Ability to edit attribute\",\n \"type\": \"string\",\n \"default\": \"editable\"\n },\n \"disabledOnDataKey\": {\n \"title\": \"Disable on false value of another datakey (specify datakey name)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"dataKeyHidden\": {\n \"title\": \"Hide input field\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"dataKeyType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"server\",\n \"label\": \"Server attribute (default)\"\n },\n {\n \"value\": \"shared\",\n \"label\": \"Shared attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Timeseries\"\n }\n ]\n },\n {\n \"key\": \"dataKeyValueType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"string\",\n \"label\": \"String\"\n },\n {\n \"value\": \"double\",\n \"label\": \"Double\"\n },\n {\n \"value\": \"integer\",\n \"label\": \"Integer\"\n },\n {\n \"value\": \"booleanCheckbox\",\n \"label\": \"Boolean (Checkbox)\"\n },\n {\n \"value\": \"booleanSwitch\",\n \"label\": \"Boolean (Switch)\"\n },\n {\n \"value\": \"dateTime\",\n \"label\": \"Date & Time\"\n },\n {\n \"value\": \"date\",\n \"label\": \"Date\"\n },\n {\n \"value\": \"time\",\n \"label\": \"Time\"\n },\n {\n \"value\": \"selectOption\",\n \"label\": \"Selectable option\"\n }\n ]\n },\n {\n \"key\": \"selectOptionsType\",\n \"condition\": \"model.dataKeyValueType === 'selectOption'\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"valueWithLabel\",\n \"label\": \"Values with labels\"\n },\n {\n \"value\": \"rawValue\",\n \"label\": \"Raw values\"\n }\n ]\n },\n {\n \"key\": \"selectOptionsList\",\n \"type\": \"array\",\n \"condition\": \"model.dataKeyValueType === 'selectOption'\",\n \"items\": [\n \"selectOptionsList[].value\",\n {\n \"key\": \"selectOptionsList[].label\",\n \"condition\": \"model.selectOptionsType === 'valueWithLabel'\"\n }\n ]\n },\n {\n \"key\": \"step\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"minValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n \"required\",\n {\n \"key\": \"requiredErrorMessage\",\n \"condition\": \"model.required === true\"\n },\n {\n \"key\": \"invalidDateErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'dateTime' || model.dataKeyValueType === 'date' || model.dataKeyValueType === 'time'\"\n },\n {\n \"key\": \"minValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"isEditable\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"editable\",\n \"label\": \"Editable (default)\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n },\n {\n \"value\": \"readonly\",\n \"label\": \"Read-only\"\n }\n ]\n },\n \"disabledOnDataKey\",\n \"dataKeyHidden\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t}\n ]\n}\n", "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.23592248334107624,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update Multiple Attributes\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" } }, diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html index 6d2b4d4a30..11666f82f6 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html @@ -116,12 +116,12 @@ diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index 361b1a06e9..63b461cc24 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -111,7 +111,8 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni isVerticalAlignment: boolean; inputWidthSettings: string; changeAlignment: boolean; - smallWidthContainer: boolean; + saveButtonLabel: string; + resetButtonLabel: string; entityDetected = false; isAllParametersValid = true; @@ -165,14 +166,14 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni this.settings.groupTitle = this.settings.groupTitle || '${entityName}'; if (this.settings.saveButtonLabel && this.settings.saveButtonLabel.length) { - this.settings.saveButtonLabel = this.utils.customTranslation(this.settings.saveButtonLabel, this.settings.saveButtonLabel); + this.saveButtonLabel = this.utils.customTranslation(this.settings.saveButtonLabel, this.settings.saveButtonLabel); } else { - this.settings.saveButtonLabel = this.translate.instant('action.save'); + this.saveButtonLabel = this.translate.instant('action.save'); } if (this.settings.resetButtonLabel && this.settings.resetButtonLabel.length) { - this.settings.resetButtonLabel = this.utils.customTranslation(this.settings.resetButtonLabel, this.settings.resetButtonLabel); + this.resetButtonLabel = this.utils.customTranslation(this.settings.resetButtonLabel, this.settings.resetButtonLabel); } else { - this.settings.resetButtonLabel = this.translate.instant('action.undo'); + this.resetButtonLabel = this.translate.instant('action.undo'); } // For backward compatibility @@ -346,17 +347,13 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni } public onDataUpdated() { - // this.ngZone.run(() => { - this.updateWidgetData(this.subscription.data); - this.ctx.detectChanges(); - // }); + this.updateWidgetData(this.subscription.data); + this.ctx.detectChanges(); } private resize() { - // this.ngZone.run(() => { - this.updateWidgetDisplaying(); - this.ctx.detectChanges(); - // }); + this.updateWidgetDisplaying(); + this.ctx.detectChanges(); } public getGroupTitle(datasource: Datasource): string { From 6de23fe3659a55b8c2c7ab90c5f1deb06f0fbc50 Mon Sep 17 00:00:00 2001 From: Chantsova Ekaterina Date: Fri, 9 Oct 2020 11:07:10 +0300 Subject: [PATCH 4/4] Refactoring --- .../lib/multiple-input-widget.component.html | 16 ++++----- .../lib/multiple-input-widget.component.ts | 35 ++++++++++++++++++- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html index 11666f82f6..6a964fc524 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.html @@ -39,7 +39,7 @@ (blur)="key.isFocused = false; inputChanged(source, key)"> {{key.settings.icon}} - {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} + {{ getErrorMessageText(key.settings, 'required') }} @@ -59,17 +59,13 @@ (blur)="key.isFocused = false; inputChanged(source, key)"> {{key.settings.icon}} - {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} + {{ getErrorMessageText(key.settings,'required') }} - {{ getErrorMessageText(key.settings.minValueErrorMessage, - 'widgets.input-widgets.min-value-error', - {value: key.settings.minValue}) }} + {{ getErrorMessageText(key.settings,'min') }} - {{ getErrorMessageText(key.settings.maxValueErrorMessage, - 'widgets.input-widgets.max-value-error', - {value: key.settings.maxValue}) }} + {{ getErrorMessageText(key.settings,'max') }} @@ -101,10 +97,10 @@ (blur)="key.isFocused = false;" (dateChange)="inputChanged(source, key)"> - {{ getErrorMessageText(key.settings.requiredErrorMessage, '') }} + {{ getErrorMessageText(key.settings, 'required') }} - {{ getErrorMessageText(key.settings.invalidDateErrorMessage, 'widgets.input-widgets.invalid-date') }} + {{ getErrorMessageText(key.settings, 'invalidDate') }} diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts index 63b461cc24..0403f2844c 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts +++ b/ui-ngx/src/app/modules/home/components/widget/lib/multiple-input-widget.component.ts @@ -361,7 +361,40 @@ export class MultipleInputWidgetComponent extends PageComponent implements OnIni return this.utils.customTranslation(groupTitle, groupTitle); } - public getErrorMessageText(errorMessage, defaultMessage, messageValues?): string { + public getErrorMessageText(keySettings: MultipleInputWidgetDataKeySettings, errorType: string): string { + let errorMessage; + let defaultMessage; + let messageValues; + switch (errorType) { + case 'required': + errorMessage = keySettings.requiredErrorMessage; + defaultMessage = ''; + break; + case 'min': + errorMessage = keySettings.minValueErrorMessage; + defaultMessage = 'widgets.input-widgets.min-value-error'; + messageValues = { + value: keySettings.minValue + }; + break; + case 'max': + errorMessage = keySettings.maxValueErrorMessage; + defaultMessage = 'widgets.input-widgets.max-value-error'; + messageValues = { + value: keySettings.maxValue + }; + break; + case 'invalidDate': + errorMessage = keySettings.invalidDateErrorMessage; + defaultMessage = 'widgets.input-widgets.invalid-date'; + break; + default: + return ''; + } + return this.getTranslatedErrorText(errorMessage, defaultMessage, messageValues); + } + + public getTranslatedErrorText(errorMessage: string, defaultMessage: string, messageValues?: object): string { let messageText; if (errorMessage && errorMessage.length) { messageText = this.utils.customTranslation(errorMessage, errorMessage);