Merge branch 'master' into develop/2.3
This commit is contained in:
commit
ded035b927
@ -63,7 +63,7 @@
|
|||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
|
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
|
||||||
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
|
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
|
||||||
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n \n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:\"true\", [settings.falseValue]:\"false\"};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.server.value,\n [\n {\n key: $scope.currentKey,\n value: $scope.currentValue\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n $scope.checkboxValue = mapReverse[$scope.originalValue = self.ctx.data[0].data[0][1]] || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n\n}\n",
|
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n\n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:true, [settings.falseValue]:false};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.server.value,\n [\n {\n key: $scope.currentKey,\n value: mapReverse[$scope.currentValue] || false\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n if ($scope.dataKeyDetected) {\n $scope.checkboxValue = ($scope.originalValue = self.ctx.data[0].data[0][1]) || false;\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onResize = function() {}\nself.onDestroy = function() {}\n",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
|
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update server boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update server boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
||||||
@ -127,7 +127,7 @@
|
|||||||
"resources": [],
|
"resources": [],
|
||||||
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
|
"templateHtml": "<form class=\"attribute-update-form\"\n name=\"attrUpdateForm\"\n ng-submit=\"updateAttribute($event)\"\n>\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-checkbox ng-model=\"checkboxValue\"\n aria-label=\"Switch entity attribute value\"\n ng-change=\"changed()\"\n ng-true-value=\"'true'\"\n ng-false-value=\"'false'\"\n >\n {{currentValue}}\n </md-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\" ng-bind=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n No attribute is selected\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n Timeseries parameter cannot be used in this widget\n </div>\n </div>\n</form>",
|
||||||
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n.grid__element:last-child {\n margin-top: 19px;\n margin-left: 7px;\n}\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
|
"templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\n}\n\n.entity-title {\n font-weight: bold;\n font-size: 22px;\n padding-top: 12px;\n padding-bottom: 6px;\n color: #666;\n}\n\n.attribute-update-form__grid {\n display: flex;\n}\n.grid__element:first-child {\n flex: 1;\n}\n.grid__element:last-child {\n margin-top: 19px;\n margin-left: 7px;\n}\n.grid__element {\n display: flex;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .md-button.md-icon-button {\n width: 32px;\n min-width: 32px;\n height: 32px;\n min-height: 32px;\n padding: 0 !important;\n margin: 0 !important;\n line-height: 20px;\n}\n\n.attribute-update-form .md-icon-button md-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}",
|
||||||
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n \n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:\"true\", [settings.falseValue]:\"false\"};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n \n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType === \"DEVICE\") {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n } else {\n $scope.message = 'Selected entity cannot have shared attributes';\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.shared.value,\n [\n {\n key: $scope.currentKey,\n value: $scope.currentValue\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n\n try {\n $scope.checkboxValue = mapReverse[$scope.originalValue = self.ctx.data[0].data[0][1]] || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {\n\n}\n",
|
"controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get('attributeService');\n toast = $scope.$injector.get('toast');\n utils = $scope.$injector.get('utils');\n types = $scope.$injector.get('types');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = 'No entity selected';\n\n settings.trueValue = settings.trueValue || true;\n settings.falseValue = settings.falseValue || false;\n\n map = {\"true\":settings.trueValue, \"false\": settings.falseValue};\n mapReverse = {[settings.trueValue]:true, [settings.falseValue]:false};\n $scope.checkboxValue = \"false\";\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.changed = function () {\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.updateAttribute();\n }\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === 'entity') {\n if (datasource.entityType === \"DEVICE\") {\n if (datasource.entityType && datasource.entityId) {\n $scope.entityName = datasource.entityName;\n if (settings.widgetTitle && settings.widgetTitle.length) {\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\n } else {\n $scope.titleTemplate = self.ctx.widgetConfig.title;\n }\n\n $scope.entityDetected = true;\n }\n } else {\n $scope.message = 'Selected entity cannot have shared attributes';\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != \"attribute\") {\n $scope.isValidParameter = false;\n } else {\n $scope.currentKey = datasource.dataKeys[0].name;\n $scope.dataKeyType = datasource.dataKeys[0].type;\n $scope.dataKeyDetected = true;\n }\n }\n }\n\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\n\n $scope.updateAttribute = function () {\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entityType,\n datasource.entityId,\n types.attributesScope.shared.value,\n [\n {\n key: $scope.currentKey,\n value: mapReverse[$scope.currentValue] || false\n }\n ]\n ).then(\n function success() {\n $scope.originalValue = $scope.currentValue;\n if (settings.showResultMessage) {\n toast.showSuccess('Update successful', 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError('Update failed', angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n $scope.checkboxValue = ($scope.originalValue = self.ctx.data[0].data[0][1]) || 'false';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.$digest();\n\n } catch (e) {\n console.log(e);\n }\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onResize = function() {}\nself.onDestroy = function() {}\n",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
|
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"trueValue\": {\n \"title\": \"True value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"falseValue\": {\n \"title\": \"False value\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\":true\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showResultMessage\",\n \"trueValue\",\n \"falseValue\"\n ]\n}",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"trueValue\":\"active\",\"falseValue\":\"inactive\"},\"title\":\"Update shared boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"trueValue\":\"active\",\"falseValue\":\"inactive\"},\"title\":\"Update shared boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}"
|
||||||
|
|||||||
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2018 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.rule.engine.filter;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.thingsboard.rule.engine.api.RuleNode;
|
||||||
|
import org.thingsboard.rule.engine.api.TbContext;
|
||||||
|
import org.thingsboard.rule.engine.api.TbNode;
|
||||||
|
import org.thingsboard.rule.engine.api.TbNodeConfiguration;
|
||||||
|
import org.thingsboard.rule.engine.api.TbNodeException;
|
||||||
|
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
|
||||||
|
import org.thingsboard.server.common.data.plugin.ComponentType;
|
||||||
|
import org.thingsboard.server.common.msg.TbMsg;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RuleNode(
|
||||||
|
type = ComponentType.FILTER,
|
||||||
|
name = "check existence fields",
|
||||||
|
relationTypes = {"True", "False"},
|
||||||
|
configClazz = TbCheckMessageNodeConfiguration.class,
|
||||||
|
nodeDescription = "Checks the existence of the selected keys from message data and metadata.",
|
||||||
|
nodeDetails = "If selected checkbox 'Check that all selected keys are present'\" and all keys in message data and metadata are exist - send Message via <b>True</b> chain, otherwise <b>False</b> chain is used.\n" +
|
||||||
|
"Else if the checkbox is not selected, and at least one of the keys from data or metadata of the message exists - send Message via <b>True</b> chain, otherwise, <b>False</b> chain is used. ",
|
||||||
|
uiResources = {"static/rulenode/rulenode-core-config.js"},
|
||||||
|
configDirective = "tbFilterNodeCheckMessageConfig")
|
||||||
|
public class TbCheckMessageNode implements TbNode {
|
||||||
|
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
private TbCheckMessageNodeConfiguration config;
|
||||||
|
private List<String> messageNamesList;
|
||||||
|
private List<String> metadataNamesList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(TbContext tbContext, TbNodeConfiguration configuration) throws TbNodeException {
|
||||||
|
this.config = TbNodeUtils.convert(configuration, TbCheckMessageNodeConfiguration.class);
|
||||||
|
messageNamesList = config.getMessageNames();
|
||||||
|
metadataNamesList = config.getMetadataNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMsg(TbContext ctx, TbMsg msg) {
|
||||||
|
try {
|
||||||
|
if (config.isCheckAllKeys()) {
|
||||||
|
ctx.tellNext(msg, allKeysData(msg) && allKeysMetadata(msg) ? "True" : "False");
|
||||||
|
} else {
|
||||||
|
ctx.tellNext(msg, atLeastOneData(msg) || atLeastOneMetadata(msg) ? "True" : "False");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
ctx.tellFailure(msg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean allKeysData(TbMsg msg) {
|
||||||
|
if (!messageNamesList.isEmpty()) {
|
||||||
|
Map<String, String> dataMap = dataToMap(msg);
|
||||||
|
return processAllKeys(messageNamesList, dataMap);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean allKeysMetadata(TbMsg msg) {
|
||||||
|
if (!metadataNamesList.isEmpty()) {
|
||||||
|
Map<String, String> metadataMap = metadataToMap(msg);
|
||||||
|
return processAllKeys(metadataNamesList, metadataMap);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean atLeastOneData(TbMsg msg) {
|
||||||
|
if (!messageNamesList.isEmpty()) {
|
||||||
|
Map<String, String> dataMap = dataToMap(msg);
|
||||||
|
return processAtLeastOne(messageNamesList, dataMap);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean atLeastOneMetadata(TbMsg msg) {
|
||||||
|
if (!metadataNamesList.isEmpty()) {
|
||||||
|
Map<String, String> metadataMap = metadataToMap(msg);
|
||||||
|
return processAtLeastOne(metadataNamesList, metadataMap);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processAllKeys(List<String> data, Map<String, String> map) {
|
||||||
|
for (String field : data) {
|
||||||
|
if (!map.containsKey(field)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processAtLeastOne(List<String> data, Map<String, String> map) {
|
||||||
|
for (String field : data) {
|
||||||
|
if (map.containsKey(field)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> metadataToMap(TbMsg msg) {
|
||||||
|
return msg.getMetaData().getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Map<String, String> dataToMap(TbMsg msg) {
|
||||||
|
return (Map<String, String>) gson.fromJson(msg.getData(), Map.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright © 2016-2018 The Thingsboard Authors
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.thingsboard.rule.engine.filter;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.thingsboard.rule.engine.api.NodeConfiguration;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TbCheckMessageNodeConfiguration implements NodeConfiguration {
|
||||||
|
|
||||||
|
private List<String> messageNames;
|
||||||
|
private List<String> metadataNames;
|
||||||
|
|
||||||
|
private boolean checkAllKeys;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TbCheckMessageNodeConfiguration defaultConfiguration() {
|
||||||
|
TbCheckMessageNodeConfiguration configuration = new TbCheckMessageNodeConfiguration();
|
||||||
|
configuration.setMessageNames(Collections.emptyList());
|
||||||
|
configuration.setMetadataNames(Collections.emptyList());
|
||||||
|
configuration.setCheckAllKeys(true);
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@ -53,6 +53,19 @@
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (!String.prototype.includes) {
|
||||||
|
String.prototype.includes = function(search, start) {
|
||||||
|
if (angular.isNumber(start)) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start + search.length > this.length) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return this.indexOf(search, start) !== -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
(function (arr) {
|
(function (arr) {
|
||||||
arr.forEach(function (item) {
|
arr.forEach(function (item) {
|
||||||
|
|||||||
@ -539,10 +539,14 @@ export default class TbMapWidgetV2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (locationsChanged && tbMap.initBounds) {
|
if (locationsChanged && tbMap.initBounds) {
|
||||||
tbMap.initBounds = !datasources.every(
|
let dataReceived = datasources.every(
|
||||||
function (ds) {
|
function (ds) {
|
||||||
return ds.dataReceived === true;
|
return ds.dataReceived === true;
|
||||||
});
|
});
|
||||||
|
let dataValid = dataReceived && dataMap.dsDataMap.every(function (ds) {
|
||||||
|
return !(!ds[tbMap.locationSettings.latKeyName] && !ds[tbMap.locationSettings.lngKeyName]);
|
||||||
|
});
|
||||||
|
tbMap.initBounds = !dataValid;
|
||||||
tbMap.map.fitBounds(bounds);
|
tbMap.map.fitBounds(bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user