Commit e253b6443c5aa3d08f4b8e3b4dccbbd062766cf2

Authored by Chantsova Ekaterina
Committed by Andrew Shvayka
1 parent 9c5dd434

Update widget for backward compatibility

@@ -319,7 +319,7 @@ @@ -319,7 +319,7 @@
319 "resources": [], 319 "resources": [],
320 "templateHtml": "<tb-multiple-input-widget \n form-id=\"formId\"\n ctx=\"ctx\">\n</tb-multiple-input-widget>", 320 "templateHtml": "<tb-multiple-input-widget \n form-id=\"formId\"\n ctx=\"ctx\">\n</tb-multiple-input-widget>",
321 "templateCss": "", 321 "templateCss": "",
322 - "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\n\r\nself.onInit = function() {\r\n var scope = self.ctx.$scope;\r\n var id = self.ctx.$scope.$injector.get('utils').guid();\r\n scope.formId = \"form-\"+id;\r\n scope.ctx = self.ctx;\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-data-updated', self.ctx.$scope.formId);\r\n}\r\n\r\nself.typeParameters = function() {\r\n return {\r\n maxDatasources: 1\r\n }\r\n}\r\n\r\nself.onResize = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-resize', self.ctx.$scope.formId);\r\n}\r\n", 322 + "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\n\r\nself.onInit = function() {\r\n var scope = self.ctx.$scope;\r\n var id = self.ctx.$scope.$injector.get('utils').guid();\r\n scope.formId = \"form-\"+id;\r\n scope.ctx = self.ctx;\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-data-updated', self.ctx.$scope.formId);\r\n}\r\n\r\nself.onResize = function() {\r\n self.ctx.$scope.$broadcast('multiple-input-resize', self.ctx.$scope.formId);\r\n}\r\n",
323 "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 \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\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 \"showResultMessage\",\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}", 323 "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 \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\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 \"showResultMessage\",\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}",
324 "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", 324 "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",
325 "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\":{}}" 325 "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\":{}}"
@@ -47,14 +47,14 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService, @@ -47,14 +47,14 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService,
47 vm.entityDetected = false; 47 vm.entityDetected = false;
48 vm.isAllParametersValid = true; 48 vm.isAllParametersValid = true;
49 49
50 - vm.data = []; 50 + vm.sources = [];
51 vm.datasources = null; 51 vm.datasources = null;
52 52
53 vm.discardAll = discardAll; 53 vm.discardAll = discardAll;
54 vm.inputChanged = inputChanged; 54 vm.inputChanged = inputChanged;
55 vm.save = save; 55 vm.save = save;
56 56
57 - $scope.$watch('vm.ctx', function() { 57 + $scope.$watch('vm.ctx', function () {
58 if (vm.ctx && vm.ctx.defaultSubscription) { 58 if (vm.ctx && vm.ctx.defaultSubscription) {
59 vm.settings = vm.ctx.settings; 59 vm.settings = vm.ctx.settings;
60 vm.widgetConfig = vm.ctx.widgetConfig; 60 vm.widgetConfig = vm.ctx.widgetConfig;
@@ -65,100 +65,113 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService, @@ -65,100 +65,113 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService,
65 } 65 }
66 }); 66 });
67 67
68 - $scope.$on('multiple-input-data-updated', function(event, formId) { 68 + $scope.$on('multiple-input-data-updated', function (event, formId) {
69 if (vm.formId == formId) { 69 if (vm.formId == formId) {
70 updateWidgetData(vm.subscription.data); 70 updateWidgetData(vm.subscription.data);
71 $scope.$digest(); 71 $scope.$digest();
72 } 72 }
73 }); 73 });
74 74
75 - $scope.$on('multiple-input-resize', function(event, formId) { 75 + $scope.$on('multiple-input-resize', function (event, formId) {
76 if (vm.formId == formId) { 76 if (vm.formId == formId) {
77 updateWidgetDisplaying(); 77 updateWidgetDisplaying();
78 } 78 }
79 }); 79 });
80 80
81 function discardAll() { 81 function discardAll() {
82 - for (var i = 0; i < vm.data.length; i++) {  
83 - vm.data[i].data.currentValue = vm.data[i].data.originalValue; 82 + for (var i = 0; i < vm.sources.length; i++) {
  83 + for (var j = 0; j < vm.sources[i].keys.length; j++) {
  84 + vm.sources[i].keys[j].data.currentValue = vm.sources[i].keys[j].data.originalValue;
  85 + }
84 } 86 }
85 $scope.multipleInputForm.$setPristine(); 87 $scope.multipleInputForm.$setPristine();
86 } 88 }
87 89
88 - function inputChanged(key) { 90 + function inputChanged(source, key) {
89 if (!vm.settings.showActionButtons) { 91 if (!vm.settings.showActionButtons) {
90 if (!key.settings.required || (key.settings.required && key.data && angular.isDefined(key.data.currentValue))) { 92 if (!key.settings.required || (key.settings.required && key.data && angular.isDefined(key.data.currentValue))) {
91 - vm.save(key); 93 + var dataToSave = {
  94 + datasource: source.datasource,
  95 + keys: [key]
  96 + };
  97 + vm.save(dataToSave);
92 } 98 }
93 } 99 }
94 } 100 }
95 101
96 - function save(key) { 102 + function save(dataToSave) {
97 var tasks = []; 103 var tasks = [];
98 - var serverAttributes = [], sharedAttributes = [], telemetry = [];  
99 var config = { 104 var config = {
100 ignoreLoading: !vm.settings.showActionButtons 105 ignoreLoading: !vm.settings.showActionButtons
101 }; 106 };
102 var data; 107 var data;
103 - if (key) {  
104 - data = [key]; 108 + if (dataToSave) {
  109 + data = [dataToSave];
105 } else { 110 } else {
106 - data = vm.data; 111 + data = vm.sources;
107 } 112 }
108 for (let i = 0; i < data.length; i++) { 113 for (let i = 0; i < data.length; i++) {
109 - var item = data[i];  
110 - if (item.data.currentValue !== item.data.originalValue) {  
111 - var attribute = {  
112 - key: item.name  
113 - };  
114 - switch (item.settings.dataKeyValueType) {  
115 - case 'dateTime':  
116 - case 'date':  
117 - attribute.value = item.data.currentValue.getTime();  
118 - break;  
119 - case 'time':  
120 - attribute.value = item.data.currentValue.getTime() - moment().startOf('day').valueOf();//eslint-disable-line  
121 - break;  
122 - default:  
123 - attribute.value = item.data.currentValue;  
124 - } 114 + var serverAttributes = [], sharedAttributes = [], telemetry = [];
  115 + for (let j = 0; j < data[i].keys.length; j++) {
  116 + var key = data[i].keys[j];
  117 + if (key.data.currentValue !== key.data.originalValue) {
  118 + var attribute = {
  119 + key: key.name
  120 + };
  121 + if (key.data.currentValue) {
  122 + switch (key.settings.dataKeyValueType) {
  123 + case 'dateTime':
  124 + case 'date':
  125 + attribute.value = key.data.currentValue.getTime();
  126 + break;
  127 + case 'time':
  128 + attribute.value = key.data.currentValue.getTime() - moment().startOf('day').valueOf();//eslint-disable-line
  129 + break;
  130 + default:
  131 + attribute.value = key.data.currentValue;
  132 + }
  133 + } else {
  134 + attribute.value = key.data.currentValue;
  135 + }
125 136
126 - switch (item.settings.dataKeyType) {  
127 - case 'shared':  
128 - sharedAttributes.push(attribute);  
129 - break;  
130 - case 'timeseries':  
131 - telemetry.push(attribute);  
132 - break;  
133 - default:  
134 - serverAttributes.push(attribute); 137 + switch (key.settings.dataKeyType) {
  138 + case 'shared':
  139 + sharedAttributes.push(attribute);
  140 + break;
  141 + case 'timeseries':
  142 + telemetry.push(attribute);
  143 + break;
  144 + default:
  145 + serverAttributes.push(attribute);
  146 + }
135 } 147 }
136 } 148 }
  149 + if (serverAttributes.length) {
  150 + tasks.push(attributeService.saveEntityAttributes(
  151 + data[i].datasource.entityType,
  152 + data[i].datasource.entityId,
  153 + types.attributesScope.server.value,
  154 + serverAttributes,
  155 + config));
  156 + }
  157 + if (sharedAttributes.length) {
  158 + tasks.push(attributeService.saveEntityAttributes(
  159 + data[i].datasource.entityType,
  160 + data[i].datasource.entityId,
  161 + types.attributesScope.shared.value,
  162 + sharedAttributes,
  163 + config));
  164 + }
  165 + if (telemetry.length) {
  166 + tasks.push(attributeService.saveEntityTimeseries(
  167 + data[i].datasource.entityType,
  168 + data[i].datasource.entityId,
  169 + types.latestTelemetry.value,
  170 + telemetry,
  171 + config));
  172 + }
137 } 173 }
138 - for (let i = 0; i < serverAttributes.length; i++) {  
139 - tasks.push(attributeService.saveEntityAttributes(  
140 - vm.datasources[0].entityType,  
141 - vm.datasources[0].entityId,  
142 - types.attributesScope.server.value,  
143 - serverAttributes,  
144 - config));  
145 - }  
146 - for (let i = 0; i < sharedAttributes.length; i++) {  
147 - tasks.push(attributeService.saveEntityAttributes(  
148 - vm.datasources[0].entityType,  
149 - vm.datasources[0].entityId,  
150 - types.attributesScope.shared.value,  
151 - sharedAttributes,  
152 - config));  
153 - }  
154 - for (let i = 0; i < telemetry.length; i++) {  
155 - tasks.push(attributeService.saveEntityTimeseries(  
156 - vm.datasources[0].entityType,  
157 - vm.datasources[0].entityId,  
158 - types.latestTelemetry.value,  
159 - telemetry,  
160 - config));  
161 - } 174 +
162 if (tasks.length) { 175 if (tasks.length) {
163 $q.all(tasks).then( 176 $q.all(tasks).then(
164 function success() { 177 function success() {
@@ -173,6 +186,8 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService, @@ -173,6 +186,8 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService,
173 } 186 }
174 } 187 }
175 ); 188 );
  189 + } else {
  190 + $scope.multipleInputForm.$setPristine();
176 } 191 }
177 } 192 }
178 193
@@ -186,6 +201,18 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService, @@ -186,6 +201,18 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService,
186 201
187 vm.ctx.widgetTitle = vm.widgetTitle; 202 vm.ctx.widgetTitle = vm.widgetTitle;
188 203
  204 + //For backward compatibility
  205 + if (angular.isUndefined(vm.settings.showActionButtons)) {
  206 + vm.settings.showActionButtons = true;
  207 + }
  208 + if (angular.isUndefined(vm.settings.fieldsAlignment)) {
  209 + vm.settings.fieldsAlignment = 'row';
  210 + }
  211 + if (angular.isUndefined(vm.settings.fieldsInRow)) {
  212 + vm.settings.fieldsInRow = 2;
  213 + }
  214 + //For backward compatibility
  215 +
189 vm.isVerticalAlignment = !(vm.settings.fieldsAlignment === 'row'); 216 vm.isVerticalAlignment = !(vm.settings.fieldsAlignment === 'row');
190 217
191 if (!vm.isVerticalAlignment && vm.settings.fieldsInRow) { 218 if (!vm.isVerticalAlignment && vm.settings.fieldsInRow) {
@@ -195,60 +222,105 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService, @@ -195,60 +222,105 @@ function MultipleInputWidgetController($q, $scope, $translate, attributeService,
195 222
196 function updateDatasources() { 223 function updateDatasources() {
197 if (vm.datasources && vm.datasources.length) { 224 if (vm.datasources && vm.datasources.length) {
198 - var datasource = vm.datasources[0];  
199 - if (datasource.type === types.datasourceType.entity) {  
200 - for (var i = 0; i < datasource.dataKeys.length; i++) {  
201 - if ((datasource.entityType !== types.entityType.device) && (datasource.dataKeys[i].settings.dataKeyType == 'shared')) {  
202 - vm.isAllParametersValid = false; 225 + vm.entityDetected = true;
  226 + for (var i = 0; i < vm.datasources.length; i++) {
  227 + var datasource = vm.datasources[i];
  228 + var source = {
  229 + datasource: datasource,
  230 + keys: []
  231 + };
  232 + if (datasource.type === types.datasourceType.entity) {
  233 + for (var j = 0; j < datasource.dataKeys.length; j++) {
  234 + if ((datasource.entityType !== types.entityType.device) && (datasource.dataKeys[j].settings.dataKeyType == 'shared')) {
  235 + vm.isAllParametersValid = false;
  236 + }
  237 + source.keys.push(datasource.dataKeys[j]);
  238 + if (source.keys[j].units) {
  239 + source.keys[j].label += ' (' + source.keys[j].units + ')';
  240 + }
  241 + source.keys[j].data = {};
  242 +
  243 + //For backward compatibility
  244 + if (angular.isUndefined(source.keys[j].settings.dataKeyType)) {
  245 + if (vm.settings.attributesShared === true) {
  246 + source.keys[j].settings.dataKeyType = 'shared';
  247 + } else {
  248 + source.keys[j].settings.dataKeyType = 'server';
  249 + }
  250 + }
  251 +
  252 + if (angular.isUndefined(source.keys[j].settings.dataKeyValueType)) {
  253 + if (source.keys[j].settings.inputTypeNumber === true) {
  254 + source.keys[j].settings.dataKeyValueType = 'double';
  255 + } else {
  256 + source.keys[j].settings.dataKeyValueType = 'string';
  257 + }
  258 + }
  259 +
  260 + if (angular.isUndefined(source.keys[j].settings.isEditable)) {
  261 + if (source.keys[j].settings.readOnly === true) {
  262 + source.keys[j].settings.isEditable = 'readonly';
  263 + } else {
  264 + source.keys[j].settings.isEditable = 'editable';
  265 + }
  266 + }
  267 + //For backward compatibility
  268 +
203 } 269 }
204 - vm.data.push(datasource.dataKeys[i]);  
205 - vm.data[i].data = {}; 270 + } else {
  271 + vm.entityDetected = false;
206 } 272 }
207 - vm.entityDetected = true; 273 + vm.sources.push(source);
208 } 274 }
209 } 275 }
210 } 276 }
211 277
212 function updateWidgetData(data) { 278 function updateWidgetData(data) {
213 - for (var i = 0; i < vm.data.length; i++) {  
214 - var keyData = data[i].data;  
215 - if (keyData && keyData.length) {  
216 - var value;  
217 - switch (vm.data[i].settings.dataKeyValueType) {  
218 - case 'dateTime':  
219 - case 'date':  
220 - value = moment(keyData[0][1]).toDate(); // eslint-disable-line  
221 - break;  
222 - case 'time':  
223 - value = moment().startOf('day').add(keyData[0][1], 'ms').toDate(); // eslint-disable-line  
224 - break;  
225 - case 'booleanCheckbox':  
226 - case 'booleanSwitch':  
227 - value = (keyData[0][1] === 'true');  
228 - break;  
229 - default:  
230 - value = keyData[0][1];  
231 - } 279 + var dataIndex = 0;
  280 + for (var i = 0; i < vm.sources.length; i++) {
  281 + var source = vm.sources[i];
  282 + for (var j = 0; j < source.keys.length; j++) {
  283 + var keyData = data[dataIndex].data;
  284 + var key = source.keys[j];
  285 + if (keyData && keyData.length) {
  286 + var value;
  287 + switch (key.settings.dataKeyValueType) {
  288 + case 'dateTime':
  289 + case 'date':
  290 + value = moment(keyData[0][1]).toDate(); // eslint-disable-line
  291 + break;
  292 + case 'time':
  293 + value = moment().startOf('day').add(keyData[0][1], 'ms').toDate(); // eslint-disable-line
  294 + break;
  295 + case 'booleanCheckbox':
  296 + case 'booleanSwitch':
  297 + value = (keyData[0][1] === 'true');
  298 + break;
  299 + default:
  300 + value = keyData[0][1];
  301 + }
232 302
233 - vm.data[i].data = {  
234 - currentValue: value,  
235 - originalValue: value  
236 - };  
237 - } 303 + key.data = {
  304 + currentValue: value,
  305 + originalValue: value
  306 + };
  307 + }
238 308
239 - if (vm.data[i].settings.isEditable === 'editable' && vm.data[i].settings.disabledOnDataKey) {  
240 - var conditions = data.filter((item) => {  
241 - return item.dataKey.name === vm.data[i].settings.disabledOnDataKey;  
242 - });  
243 - if (conditions && conditions.length) {  
244 - if (conditions[0].data.length) {  
245 - if (conditions[0].data[0][1] === 'false') {  
246 - vm.data[i].settings.disabledOnCondition = true;  
247 - } else {  
248 - vm.data[i].settings.disabledOnCondition = !conditions[0].data[0][1]; 309 + if (key.settings.isEditable === 'editable' && key.settings.disabledOnDataKey) {
  310 + var conditions = data.filter((item) => {
  311 + return item.dataKey.name === key.settings.disabledOnDataKey;
  312 + });
  313 + if (conditions && conditions.length) {
  314 + if (conditions[0].data.length) {
  315 + if (conditions[0].data[0][1] === 'false') {
  316 + key.settings.disabledOnCondition = true;
  317 + } else {
  318 + key.settings.disabledOnCondition = !conditions[0].data[0][1];
  319 + }
249 } 320 }
250 } 321 }
251 } 322 }
  323 + dataIndex++;
252 } 324 }
253 } 325 }
254 } 326 }
@@ -17,9 +17,9 @@ @@ -17,9 +17,9 @@
17 --> 17 -->
18 <form class="tb-multiple-input" name="multipleInputForm" ng-submit="vm.save()" novalidate autocomplete="off"> 18 <form class="tb-multiple-input" name="multipleInputForm" ng-submit="vm.save()" novalidate autocomplete="off">
19 <div style="padding: 0 8px;" ng-if="vm.entityDetected && vm.isAllParametersValid"> 19 <div style="padding: 0 8px;" ng-if="vm.entityDetected && vm.isAllParametersValid">
20 - <div layout="row" layout-wrap ng-class="{'vertical-alignment': vm.isVerticalAlignment || vm.changeAlignment}">  
21 - <div ng-repeat="key in vm.data" ng-style="{'width': (vm.isVerticalAlignment || vm.changeAlignment) ? '100%' : vm.inputWidthSettings}">  
22 - <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'string') && !key.settings.dataKeyHidden"> 20 + <div layout="row" ng-repeat="source in vm.sources" layout-wrap ng-class="{'vertical-alignment': vm.isVerticalAlignment || vm.changeAlignment}">
  21 + <div ng-repeat="key in source.keys" ng-if="!key.settings.dataKeyHidden" ng-style="{'width': (vm.isVerticalAlignment || vm.changeAlignment) ? '100%' : vm.inputWidthSettings}">
  22 + <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'string')">
23 <md-input-container class="md-block"> 23 <md-input-container class="md-block">
24 <label>{{key.label}}</label> 24 <label>{{key.label}}</label>
25 <md-icon class="material-icons" ng-if="key.settings.icon"> 25 <md-icon class="material-icons" ng-if="key.settings.icon">
@@ -32,13 +32,13 @@ @@ -32,13 +32,13 @@
32 ng-required="key.settings.required" 32 ng-required="key.settings.required"
33 type="text" 33 type="text"
34 md-select-on-focus 34 md-select-on-focus
35 - ng-blur="vm.inputChanged(key)"> 35 + ng-blur="vm.inputChanged(source,key)">
36 <div ng-messages="multipleInputForm[key.name].$error"> 36 <div ng-messages="multipleInputForm[key.name].$error">
37 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div> 37 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
38 </div> 38 </div>
39 </md-input-container> 39 </md-input-container>
40 </div> 40 </div>
41 - <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'double') && !key.settings.dataKeyHidden"> 41 + <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'double')">
42 <md-input-container class="md-block"> 42 <md-input-container class="md-block">
43 <label>{{key.label}}</label> 43 <label>{{key.label}}</label>
44 <md-icon class="material-icons" ng-if="key.settings.icon"> 44 <md-icon class="material-icons" ng-if="key.settings.icon">
@@ -52,13 +52,13 @@ @@ -52,13 +52,13 @@
52 type="number" 52 type="number"
53 step="key.settings.step" 53 step="key.settings.step"
54 md-select-on-focus 54 md-select-on-focus
55 - ng-blur="vm.inputChanged(key)"> 55 + ng-blur="vm.inputChanged(source,key)">
56 <div ng-messages="multipleInputForm[key.name].$error"> 56 <div ng-messages="multipleInputForm[key.name].$error">
57 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div> 57 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
58 </div> 58 </div>
59 </md-input-container> 59 </md-input-container>
60 </div> 60 </div>
61 - <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'integer') && !key.settings.dataKeyHidden"> 61 + <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'integer')">
62 <md-input-container class="md-block"> 62 <md-input-container class="md-block">
63 <label>{{key.label}}</label> 63 <label>{{key.label}}</label>
64 <md-icon class="material-icons" ng-if="key.settings.icon"> 64 <md-icon class="material-icons" ng-if="key.settings.icon">
@@ -73,26 +73,26 @@ @@ -73,26 +73,26 @@
73 step="key.settings.step" 73 step="key.settings.step"
74 md-select-on-focus 74 md-select-on-focus
75 ng-pattern="/^-?[0-9]+$/" 75 ng-pattern="/^-?[0-9]+$/"
76 - ng-blur="vm.inputChanged(key)"> 76 + ng-blur="vm.inputChanged(source,key)">
77 <div ng-messages="multipleInputForm[key.name].$error"> 77 <div ng-messages="multipleInputForm[key.name].$error">
78 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div> 78 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
79 <div translate ng-message="pattern">value.invalid-integer-value</div> 79 <div translate ng-message="pattern">value.invalid-integer-value</div>
80 </div> 80 </div>
81 </md-input-container> 81 </md-input-container>
82 </div> 82 </div>
83 - <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanCheckbox') && !key.settings.dataKeyHidden" class="md-block"> 83 + <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanCheckbox')" class="md-block">
84 <md-checkbox name="{{key.name}}" 84 <md-checkbox name="{{key.name}}"
85 ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition" 85 ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
86 ng-model="key.data.currentValue" 86 ng-model="key.data.currentValue"
87 - ng-change="vm.inputChanged(key)"> 87 + ng-change="vm.inputChanged(source,key)">
88 {{key.label}} 88 {{key.label}}
89 </md-checkbox> 89 </md-checkbox>
90 </div> 90 </div>
91 - <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanSwitch') && !key.settings.dataKeyHidden" class="md-block"> 91 + <div class="input-field" ng-if="(key.settings.dataKeyValueType === 'booleanSwitch')" class="md-block">
92 <md-switch name="{{key.name}}" 92 <md-switch name="{{key.name}}"
93 ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition" 93 ng-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
94 ng-model="key.data.currentValue" 94 ng-model="key.data.currentValue"
95 - ng-change="vm.inputChanged(key)" 95 + ng-change="vm.inputChanged(source,key)"
96 aria-label="{{key.label}}" 96 aria-label="{{key.label}}"
97 md-invert> 97 md-invert>
98 {{key.label}} 98 {{key.label}}
@@ -100,7 +100,7 @@ @@ -100,7 +100,7 @@
100 </div> 100 </div>
101 <div ng-if="(key.settings.dataKeyValueType === 'dateTime') || 101 <div ng-if="(key.settings.dataKeyValueType === 'dateTime') ||
102 (key.settings.dataKeyValueType === 'date') || 102 (key.settings.dataKeyValueType === 'date') ||
103 - (key.settings.dataKeyValueType === 'time') && !key.settings.dataKeyHidden" 103 + (key.settings.dataKeyValueType === 'time')"
104 class="md-block input-field date-time-input" layout="column"> 104 class="md-block input-field date-time-input" layout="column">
105 <label class="date-time-input__label">{{key.label}}</label> 105 <label class="date-time-input__label">{{key.label}}</label>
106 <div layout="row" ng-class="{'vertically-aligned': vm.smallWidthContainer}"> 106 <div layout="row" ng-class="{'vertically-aligned': vm.smallWidthContainer}">
@@ -108,7 +108,7 @@ @@ -108,7 +108,7 @@
108 ng-if="key.settings.dataKeyValueType !== 'time'" 108 ng-if="key.settings.dataKeyValueType !== 'time'"
109 mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition" 109 mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
110 ng-model="key.data.currentValue" 110 ng-model="key.data.currentValue"
111 - ng-change="vm.inputChanged(key)" 111 + ng-change="vm.inputChanged(source,key)"
112 mdp-placeholder="{{ 'widgets.input-widgets.date' | translate }}"> 112 mdp-placeholder="{{ 'widgets.input-widgets.date' | translate }}">
113 <div ng-messages="multipleInputForm[key.name].$error"> 113 <div ng-messages="multipleInputForm[key.name].$error">
114 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div> 114 <div ng-message="required">{{ key.settings.requiredErrorMessage }}</div>
@@ -118,7 +118,7 @@ @@ -118,7 +118,7 @@
118 ng-if="key.settings.dataKeyValueType !== 'date'" 118 ng-if="key.settings.dataKeyValueType !== 'date'"
119 mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition" 119 mdp-disabled="key.settings.isEditable === 'disabled' || key.settings.disabledOnCondition"
120 ng-model="key.data.currentValue" 120 ng-model="key.data.currentValue"
121 - ng-change="vm.inputChanged(key)" 121 + ng-change="vm.inputChanged(source,key)"
122 mdp-placeholder="{{ 'widgets.input-widgets.time' | translate }}" 122 mdp-placeholder="{{ 'widgets.input-widgets.time' | translate }}"
123 mdp-auto-switch="true"> 123 mdp-auto-switch="true">
124 <div ng-messages="multipleInputForm[key.name].$error"> 124 <div ng-messages="multipleInputForm[key.name].$error">