Commit 9d33d5b4e500c0b783e835035ffc7bbbf0affcc9
Merge remote-tracking branch 'origin/develop/3.0' into feature/rest-client-improvement-3.0
Showing
85 changed files
with
1332 additions
and
1050 deletions
Too many changes to show.
To preserve performance only 85 of 1089 files are displayed.
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>application</artifactId> | 26 | <artifactId>application</artifactId> |
@@ -116,7 +116,7 @@ | @@ -116,7 +116,7 @@ | ||
116 | </dependency> | 116 | </dependency> |
117 | <dependency> | 117 | <dependency> |
118 | <groupId>org.thingsboard</groupId> | 118 | <groupId>org.thingsboard</groupId> |
119 | - <artifactId>ui</artifactId> | 119 | + <artifactId>ui-ngx</artifactId> |
120 | <version>${project.version}</version> | 120 | <version>${project.version}</version> |
121 | <scope>runtime</scope> | 121 | <scope>runtime</scope> |
122 | </dependency> | 122 | </dependency> |
@@ -13,9 +13,9 @@ | @@ -13,9 +13,9 @@ | ||
13 | "sizeX": 10.5, | 13 | "sizeX": 10.5, |
14 | "sizeY": 6.5, | 14 | "sizeY": 6.5, |
15 | "resources": [], | 15 | "resources": [], |
16 | - "templateHtml": "<tb-alarms-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-alarms-table-widget>", | 16 | + "templateHtml": "<tb-alarms-table-widget \n [ctx]=\"ctx\">\n</tb-alarms-table-widget>", |
17 | "templateCss": "", | 17 | "templateCss": "", |
18 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('alarms-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", | 18 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.alarmsTableWidget.onDataUpdated();\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", |
19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStatusFilter\": {\n \"title\": \"Enable alarm status filter\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"-createdTime\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableStatusFilter\",\n \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", | 19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"AlarmTableSettings\",\n \"properties\": {\n \"alarmsTitle\": {\n \"title\": \"Alarms table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSelection\": {\n \"title\": \"Enable alarms selection\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSearch\": {\n \"title\": \"Enable alarms search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableStatusFilter\": {\n \"title\": \"Enable alarm status filter\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayDetails\": {\n \"title\": \"Display alarm details\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowAcknowledgment\": {\n \"title\": \"Allow alarms acknowledgment\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"allowClear\": {\n \"title\": \"Allow alarms clear\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"-createdTime\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"alarmsTitle\",\n \"enableSelection\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"enableStatusFilter\",\n \"displayDetails\",\n \"allowAcknowledgment\",\n \"allowClear\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", |
20 | "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, alarm, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | 20 | "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, alarm, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
21 | "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStatusFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{}}" | 21 | "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"allowAcknowledgment\":true,\"allowClear\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"-createdTime\",\"enableSelectColumnDisplay\":true,\"enableStatusFilter\":true},\"title\":\"Alarms table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"alarmSource\":{\"type\":\"function\",\"dataKeys\":[{\"name\":\"createdTime\",\"type\":\"alarm\",\"label\":\"Created time\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.021092237451093787},{\"name\":\"originator\",\"type\":\"alarm\",\"label\":\"Originator\",\"color\":\"#4caf50\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.2780007688856758},{\"name\":\"type\",\"type\":\"alarm\",\"label\":\"Type\",\"color\":\"#f44336\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.7323586880398418},{\"name\":\"severity\",\"type\":\"alarm\",\"label\":\"Severity\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":false,\"useCellContentFunction\":false},\"_hash\":0.09927019860088193},{\"name\":\"status\",\"type\":\"alarm\",\"label\":\"Status\",\"color\":\"#607d8b\",\"settings\":{\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6588418951443418}],\"entityAliasId\":null,\"name\":\"alarms\"},\"alarmSearchStatus\":\"ANY\",\"alarmsPollingInterval\":5,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{}}" |
@@ -29,12 +29,12 @@ | @@ -29,12 +29,12 @@ | ||
29 | "sizeX": 7.5, | 29 | "sizeX": 7.5, |
30 | "sizeY": 6.5, | 30 | "sizeY": 6.5, |
31 | "resources": [], | 31 | "resources": [], |
32 | - "templateHtml": "<tb-entities-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-entities-table-widget>", | 32 | + "templateHtml": "<tb-entities-table-widget \n [ctx]=\"ctx\">\n</tb-entities-table-widget>", |
33 | "templateCss": "", | 33 | "templateCss": "", |
34 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('entities-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n },\n 'rowDoubleClick': {\n name: 'widget-action.row-double-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", | ||
35 | - "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"entitiesTitle\": {\n \"title\": \"Entities table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSearch\": {\n \"title\": \"Enable entities search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayEntityName\": {\n \"title\": \"Display entity name column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"entityNameColumnTitle\": {\n \"title\": \"Entity name column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityLabel\": {\n \"title\": \"Display entity label column\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"entityLabelColumnTitle\": {\n \"title\": \"Entity label column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityType\": {\n \"title\": \"Display entity type column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"entityName\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"entitiesTitle\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"displayEntityName\",\n \"entityNameColumnTitle\",\n \"displayEntityLabel\",\n \"entityLabelColumnTitle\",\n \"displayEntityType\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", | ||
36 | - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, entity, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | ||
37 | - "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSearch\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true,\"enableSelectColumnDisplay\":true},\"title\":\"Entity table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"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;\"}]}],\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"widgetStyle\":{},\"displayTimewindow\":true,\"actions\":{}}" | 34 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesTableWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", |
35 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"entitiesTitle\": {\n \"title\": \"Entities table title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"enableSearch\": {\n \"title\": \"Enable entities search\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"enableSelectColumnDisplay\": {\n \"title\": \"Enable select columns to display\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayEntityName\": {\n \"title\": \"Display entity name column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"entityNameColumnTitle\": {\n \"title\": \"Entity name column title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"displayEntityType\": {\n \"title\": \"Display entity type column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"defaultSortOrder\": {\n \"title\": \"Default sort order\",\n \"type\": \"string\",\n \"default\": \"entityName\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"entitiesTitle\",\n \"enableSearch\",\n \"enableSelectColumnDisplay\",\n \"displayEntityName\",\n \"entityNameColumnTitle\",\n \"displayEntityType\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"defaultSortOrder\"\n ]\n}", | ||
36 | + "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"columnWidth\": {\n \"title\": \"Column width (px or %)\",\n \"type\": \"string\",\n \"default\": \"0px\"\n },\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, entity, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"columnWidth\",\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | ||
37 | + "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"enableSelection\":true,\"enableSearch\":true,\"displayDetails\":true,\"displayPagination\":true,\"defaultPageSize\":10,\"defaultSortOrder\":\"entityName\",\"displayEntityName\":true,\"displayEntityType\":true},\"title\":\"Entities table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"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;\"}]}]}" | ||
38 | } | 38 | } |
39 | }, | 39 | }, |
40 | { | 40 | { |
@@ -63,7 +63,7 @@ | @@ -63,7 +63,7 @@ | ||
63 | "resources": [], | 63 | "resources": [], |
64 | "templateHtml": "", | 64 | "templateHtml": "", |
65 | "templateCss": "", | 65 | "templateCss": "", |
66 | - "controllerScript": "self.onInit = function() {\n self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n self.ctx.htmlSet = false;\n \n var cssParser = new cssjs();\n cssParser.testMode = false;\n var namespace = 'html-value-card-' + hashCode(self.ctx.settings.cardCss);\n cssParser.cssPreviewNamespace = namespace;\n cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n self.ctx.$container.addClass(namespace);\n var evtFnPrefix = 'htmlValueCard_' + Math.abs(hashCode(self.ctx.settings.cardCss + self.ctx.settings.cardHtml));\n self.ctx.html = '<div style=\"height:100%\" onclick=\"' + evtFnPrefix + '_onClickFn(event)\">' + \n self.ctx.settings.cardHtml + \n '</div>';\n\n self.ctx.replaceInfo = processHtmlPattern(self.ctx.html, self.ctx.data);\n \n updateHtml();\n \n window[evtFnPrefix + '_onClickFn'] = function (event) {\n self.ctx.actionsApi.elementClick(event);\n }\n\n function hashCode(str) {\n var hash = 0;\n var i, char;\n if (str.length === 0) return hash;\n for (i = 0; i < str.length; i++) {\n char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return hash;\n }\n \n function processHtmlPattern(pattern, data) {\n var match = self.ctx.varsRegex.exec(pattern);\n var replaceInfo = {};\n replaceInfo.variables = [];\n while (match !== null) {\n var variableInfo = {};\n variableInfo.dataKeyIndex = -1;\n var variable = match[0];\n var label = match[1];\n var valDec = 2;\n var splitVals = label.split(':');\n if (splitVals.length > 1) {\n label = splitVals[0];\n valDec = parseFloat(splitVals[1]);\n }\n variableInfo.variable = variable;\n variableInfo.valDec = valDec;\n if (label == 'entityName') {\n variableInfo.isEntityName = true;\n } else if (label == 'entityLabel') {\n variableInfo.isEntityLabel = true;\n } else if (label.startsWith('#')) {\n var keyIndexStr = label.substring(1);\n var n = Math.floor(Number(keyIndexStr));\n if (String(n) === keyIndexStr && n >= 0) {\n variableInfo.dataKeyIndex = n;\n }\n }\n if (!variableInfo.isEntityName && !variableInfo.isEntityLabel && variableInfo.dataKeyIndex === -1) {\n for (var i = 0; i < data.length; i++) {\n var datasourceData = data[i];\n var dataKey = datasourceData.dataKey;\n if (dataKey.label === label) {\n variableInfo.dataKeyIndex = i;\n break;\n }\n }\n }\n replaceInfo.variables.push(variableInfo);\n match = self.ctx.varsRegex.exec(pattern);\n }\n return replaceInfo;\n } \n}\n\nself.onDataUpdated = function() {\n updateHtml();\n}\n\nself.actionSources = function() {\n return {\n 'elementClick': {\n name: 'widget-action.element-click',\n multiple: true\n }\n };\n}\n\nself.onDestroy = function() {\n}\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n var i = 0;\n var s, strVal, n;\n\n val = parseFloat(val);\n n = (val < 0);\n val = Math.abs(val);\n\n if (dec > 0) {\n strVal = val.toFixed(dec).toString().split('.');\n s = int - strVal[0].length;\n\n for (; i < s; ++i) {\n strVal[0] = '0' + strVal[0];\n }\n\n strVal = (n ? '-' : '') + strVal[0] + '.' + strVal[1];\n }\n\n else {\n strVal = Math.round(val).toString();\n s = int - strVal.length;\n\n for (; i < s; ++i) {\n strVal = '0' + strVal;\n }\n\n strVal = (n ? '-' : '') + strVal;\n }\n\n return strVal;\n}\n\nfunction updateHtml() {\n var $injector = self.ctx.$scope.$injector;\n var utils = $injector.get('utils');\n var types = $injector.get('types');\n var text = self.ctx.html;\n var updated = false;\n for (var v in self.ctx.replaceInfo.variables) {\n var variableInfo = self.ctx.replaceInfo.variables[v];\n var txtVal = '';\n if (variableInfo.dataKeyIndex > -1) {\n var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n if (varData.length > 0) {\n var val = varData[varData.length-1][1];\n if (isNumber(val)) {\n txtVal = padValue(val, variableInfo.valDec, 0);\n } else {\n txtVal = val;\n }\n }\n } else if (variableInfo.isEntityName) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n } else if (variableInfo.isEntityLabel) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityLabel || self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n }\n if (typeof variableInfo.lastVal === undefined ||\n variableInfo.lastVal !== txtVal) {\n updated = true;\n variableInfo.lastVal = txtVal;\n }\n text = text.split(variableInfo.variable).join(txtVal);\n }\n if (updated || !self.ctx.htmlSet) {\n text = replaceCustomTranslations(text);\n self.ctx.$container.html(text);\n if (!self.ctx.htmlSet) {\n self.ctx.htmlSet = true;\n }\n }\n \n function replaceCustomTranslations (pattern) {\n var customTranslationRegex = new RegExp('{' + types.translate.i18nPrefix + ':[^{}]+}', 'g');\n pattern = pattern.replace(customTranslationRegex, getTranslationText);\n return pattern;\n }\n \n function getTranslationText (variable) {\n return utils.customTranslation(variable, variable);\n \n }\n}\n\n", | 66 | + "controllerScript": "self.onInit = function() {\n self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n self.ctx.htmlSet = false;\n \n var cssParser = new cssjs();\n cssParser.testMode = false;\n var namespace = 'html-value-card-' + hashCode(self.ctx.settings.cardCss);\n cssParser.cssPreviewNamespace = namespace;\n cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n self.ctx.$container.addClass(namespace);\n var evtFnPrefix = 'htmlValueCard_' + Math.abs(hashCode(self.ctx.settings.cardCss + self.ctx.settings.cardHtml));\n self.ctx.html = '<div style=\"height:100%\" onclick=\"' + evtFnPrefix + '_onClickFn(event)\">' + \n self.ctx.settings.cardHtml + \n '</div>';\n\n self.ctx.replaceInfo = processHtmlPattern(self.ctx.html, self.ctx.data);\n \n updateHtml();\n \n window[evtFnPrefix + '_onClickFn'] = function (event) {\n self.ctx.actionsApi.elementClick(event);\n }\n\n function hashCode(str) {\n var hash = 0;\n var i, char;\n if (str.length === 0) return hash;\n for (i = 0; i < str.length; i++) {\n char = str.charCodeAt(i);\n hash = ((hash << 5) - hash) + char;\n hash = hash & hash;\n }\n return hash;\n }\n \n function processHtmlPattern(pattern, data) {\n var match = self.ctx.varsRegex.exec(pattern);\n var replaceInfo = {};\n replaceInfo.variables = [];\n while (match !== null) {\n var variableInfo = {};\n variableInfo.dataKeyIndex = -1;\n var variable = match[0];\n var label = match[1];\n var valDec = 2;\n var splitVals = label.split(':');\n if (splitVals.length > 1) {\n label = splitVals[0];\n valDec = parseFloat(splitVals[1]);\n }\n variableInfo.variable = variable;\n variableInfo.valDec = valDec;\n if (label == 'entityName') {\n variableInfo.isEntityName = true;\n } else if (label == 'entityLabel') {\n variableInfo.isEntityLabel = true;\n } else if (label.startsWith('#')) {\n var keyIndexStr = label.substring(1);\n var n = Math.floor(Number(keyIndexStr));\n if (String(n) === keyIndexStr && n >= 0) {\n variableInfo.dataKeyIndex = n;\n }\n }\n if (!variableInfo.isEntityName && !variableInfo.isEntityLabel && variableInfo.dataKeyIndex === -1) {\n for (var i = 0; i < data.length; i++) {\n var datasourceData = data[i];\n var dataKey = datasourceData.dataKey;\n if (dataKey.label === label) {\n variableInfo.dataKeyIndex = i;\n break;\n }\n }\n }\n replaceInfo.variables.push(variableInfo);\n match = self.ctx.varsRegex.exec(pattern);\n }\n return replaceInfo;\n } \n}\n\nself.onDataUpdated = function() {\n updateHtml();\n}\n\nself.actionSources = function() {\n return {\n 'elementClick': {\n name: 'widget-action.element-click',\n multiple: true\n }\n };\n}\n\nself.onDestroy = function() {\n}\n\nfunction isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n var i = 0;\n var s, strVal, n;\n\n val = parseFloat(val);\n n = (val < 0);\n val = Math.abs(val);\n\n if (dec > 0) {\n strVal = val.toFixed(dec).toString().split('.');\n s = int - strVal[0].length;\n\n for (; i < s; ++i) {\n strVal[0] = '0' + strVal[0];\n }\n\n strVal = (n ? '-' : '') + strVal[0] + '.' + strVal[1];\n }\n\n else {\n strVal = Math.round(val).toString();\n s = int - strVal.length;\n\n for (; i < s; ++i) {\n strVal = '0' + strVal;\n }\n\n strVal = (n ? '-' : '') + strVal;\n }\n\n return strVal;\n}\n\nfunction updateHtml() {\n var $injector = self.ctx.$scope.$injector;\n var utils = $injector.get(self.ctx.servicesMap.get('utils'));\n var text = self.ctx.html;\n var updated = false;\n for (var v in self.ctx.replaceInfo.variables) {\n var variableInfo = self.ctx.replaceInfo.variables[v];\n var txtVal = '';\n if (variableInfo.dataKeyIndex > -1) {\n var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n if (varData.length > 0) {\n var val = varData[varData.length-1][1];\n if (isNumber(val)) {\n txtVal = padValue(val, variableInfo.valDec, 0);\n } else {\n txtVal = val;\n }\n }\n } else if (variableInfo.isEntityName) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n } else if (variableInfo.isEntityLabel) {\n if (self.ctx.defaultSubscription.datasources.length) {\n txtVal = self.ctx.defaultSubscription.datasources[0].entityLabel || self.ctx.defaultSubscription.datasources[0].entityName;\n } else {\n txtVal = 'Unknown';\n }\n }\n if (typeof variableInfo.lastVal === undefined ||\n variableInfo.lastVal !== txtVal) {\n updated = true;\n variableInfo.lastVal = txtVal;\n }\n text = text.split(variableInfo.variable).join(txtVal);\n }\n if (updated || !self.ctx.htmlSet) {\n text = replaceCustomTranslations(text);\n self.ctx.$container.html(text);\n if (!self.ctx.htmlSet) {\n self.ctx.htmlSet = true;\n }\n }\n \n function replaceCustomTranslations (pattern) {\n var customTranslationRegex = new RegExp('{i18n:[^{}]+}', 'g');\n pattern = pattern.replace(customTranslationRegex, getTranslationText);\n return pattern;\n }\n \n function getTranslationText (variable) {\n return utils.customTranslation(variable, variable);\n \n }\n}\n\n", |
67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"required\": [\"cardHtml\"],\n \"properties\": {\n \"cardCss\": {\n \"title\": \"CSS\",\n \"type\": \"string\",\n \"default\": \".card {\\n font-weight: bold; \\n}\"\n },\n \"cardHtml\": {\n \"title\": \"HTML\",\n \"type\": \"string\",\n \"default\": \"<div class='card'>HTML code here</div>\"\n }\n }\n },\n \"form\": [\n {\n \"key\": \"cardCss\",\n \"type\": \"css\"\n }, \n {\n \"key\": \"cardHtml\",\n \"type\": \"html\"\n } \n ]\n}", | 67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"required\": [\"cardHtml\"],\n \"properties\": {\n \"cardCss\": {\n \"title\": \"CSS\",\n \"type\": \"string\",\n \"default\": \".card {\\n font-weight: bold; \\n}\"\n },\n \"cardHtml\": {\n \"title\": \"HTML\",\n \"type\": \"string\",\n \"default\": \"<div class='card'>HTML code here</div>\"\n }\n }\n },\n \"form\": [\n {\n \"key\": \"cardCss\",\n \"type\": \"css\"\n }, \n {\n \"key\": \"cardHtml\",\n \"type\": \"html\"\n } \n ]\n}", |
68 | "dataKeySettingsSchema": "{}\n", | 68 | "dataKeySettingsSchema": "{}\n", |
69 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"My value\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.random() * 5.45;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"cardCss\":\".card {\\n width: 100%;\\n height: 100%;\\n border: 2px solid #ccc;\\n box-sizing: border-box;\\n}\\n\\n.card .content {\\n padding: 20px;\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n justify-content: space-around;\\n height: 100%;\\n box-sizing: border-box;\\n}\\n\\n.card .content .column {\\n display: flex;\\n flex-direction: column; \\n justify-content: space-around;\\n height: 100%;\\n}\\n\\n.card h1 {\\n text-transform: uppercase;\\n color: #999;\\n font-size: 20px;\\n font-weight: bold;\\n margin: 0;\\n padding-bottom: 10px;\\n line-height: 32px;\\n}\\n\\n.card .value {\\n font-size: 38px;\\n font-weight: 200;\\n}\\n\\n.card .description {\\n font-size: 20px;\\n color: #999;\\n}\\n\",\"cardHtml\":\"<div class='card'>\\n <div class='content'>\\n <div class='column'>\\n <h1>Value title</h1>\\n <div class='value'>\\n ${My value:2} units.\\n </div> \\n <div class='description'>\\n Value description text\\n </div>\\n </div>\\n <img height=\\\"80px\\\" src=\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIwIiB3aWR0aD0iMzIwIj48ZyBzdHJva2Utd2lkdGg9IjI4Ij48ZyBmaWxsPSIjMzA1NjgwIiBjb2xvcj0iIzAwMCIgd2hpdGUtc3BhY2U9Im5vcm1hbCI+PHBhdGggc3R5bGU9InRleHQtZGVjb3JhdGlvbi1jb2xvcjojMDAwO2lzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbDtibG9jay1wcm9ncmVzc2lvbjp0Yjt0ZXh0LWRlY29yYXRpb24tbGluZTpub25lO3RleHQtZGVjb3JhdGlvbi1zdHlsZTpzb2xpZDt0ZXh0LWluZGVudDowO3RleHQtdHJhbnNmb3JtOm5vbmUiIGQ9Ik0xNTEuMTMgMGMtMjguMzYzIDAtNTQuOTE1IDcuOTE1LTc3LjYxMyAyMS41MzdhMzYuNTc4IDM2LjU3OCAwIDAgMC0yMy4wNjctOC4xOTQgOC43NjYgOC43NjYgMCAwIDAtLjAwNCAwYy0yMC4xNTQuMDAxLTM2LjY3OSAxNi41MjgtMzYuNjc4IDM2LjY4MmE4Ljc2NiA4Ljc2NiAwIDAgMCAwIC4wMSAzNi42OSAzNi42OSAwIDAgMCA4LjEwNCAyMi45MjhjLTEzLjgzIDIyLjgzLTIxLjg3IDQ5LjU4LTIxLjg3IDc4LjE3YTguNzY2IDguNzY2IDAgMSAwIDE3LjUzIDBjMC0yNC43MDIgNi43Mi00Ny43NDggMTguMzc5LTY3LjU3NCA0LjU2NiAxLjk4NSA5LjQ3MiAzLjE1IDE0LjUxOSAzLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEyIDBjMjAuMTU1IDAgMzYuNjgzLTE2LjUyNyAzNi42ODItMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAwNGMtLjAwMS01LTEuMTM4LTkuODYzLTMuMDgzLTE0LjM5NyAxOS43MTctMTEuNDg0IDQyLjU4NS0xOC4wOTUgNjcuMDg1LTE4LjA5NWE4Ljc2NiA4Ljc2NiAwIDEgMCAwLTE3LjUzek01MC40NCAzMC44OGM1LjkxMy4wMDIgMTEuMTkxIDIuNTEyIDE0LjgzNiA3LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMTgzLjIxNCAxOS4xMzcgMTkuMTM3IDAgMCAxIDQuMTM0IDExLjg2M2MtLjAwMiAxMC42NzctOC40NjggMTkuMTQ0LTE5LjE0NCAxOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMS0xMi00LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEzLS4wMSAxOS4xMzYgMTkuMTM2IDAgMCAxLTcuMTQ0LTE0Ljg5MmMuMDAzLTEwLjY3NyA4LjQ3LTE5LjE0NCAxOS4xNDgtMTkuMTQ2eiIvPjxwYXRoIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb24tY29sb3I6IzAwMDtpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWw7YmxvY2stcHJvZ3Jlc3Npb246dGI7dGV4dC1kZWNvcmF0aW9uLWxpbmU6bm9uZTt0ZXh0LWRlY29yYXRpb24tc3R5bGU6c29saWQ7dGV4dC1pbmRlbnQ6MDt0ZXh0LXRyYW5zZm9ybTpub25lIiBkPSJNNjYuOTkyIDEwMi44M2E4LjE4NyA4LjE4NyAwIDAgMC0yLjI1OCA2LjA3MSA4LjYwNCA4LjYwNCAwIDAgMCAyLjMzOCA1LjUxOGM2LjgwNSA2Ljg1NiAyMC4yMjMgMjAuMjIzIDIwLjIyMyAyMC4yMjNsMTEuODQ0LTExLjgzcy0xMi45NzMtMTIuOTYxLTIwLjE3Ni0yMC4xNzFjLTEuNjA0LTEuNjMyLTMuNzUtMi4zMTQtNi4wMTItMi4zMjRhOC4xNSA4LjE1IDAgMCAwLTUuOTYgMi41MTJ6bTMyLjE0NyAxOS45ODNMNjIuNSAxNTkuNDUyYy0zLjk3NSAzLjk3Ni0zLjk3NSAxMC40MjEgMCAxNC4zOTdsMTguMTU2IDE4LjE1NiAzMS43NTMgMzEuNzUzIDMwLjQ3OCAzMC40NzhjMy45NzYgMy45NzYgMTAuNDIyIDMuOTc2IDE0LjM5OCAwbDI0Ljc5MS0yNC43OTEgMzcuOTE0LTM3LjkxNCAzNi42MzktMzYuNjM5YzMuOTc1LTMuOTc2IDMuOTc1LTEwLjQyMiAwLTE0LjM5OGwtMTguNjMtMTguNjMtMzEuNzUtMzEuNzYtMzAuMDEtMzBjLTMuOTc3LTMuOTc1LTEwLjQyMi0zLjk3NS0xNC4zOTggMGwtMjQuNzkgMjQuNzktMzcuOTEgMzcuOTF6bTM3LjkxMS0zNy45MXMtMTIuOTczLTEyLjk2MS0yMC4xNzYtMjAuMTcxYy0xLjYwNC0xLjYzMi0zLjc1LTIuMzE0LTYuMDEyLTIuMzI0LTQuNzE3LS4wMjMtOC40MzQgMy44NjEtOC4yMTcgOC41ODNhOC42MDQgOC42MDQgMCAwIDAgMi4zMzcgNS41MThjNi44MDUgNi44NTYgMjAuMjIzIDIwLjIyMyAyMC4yMjMgMjAuMjIzbDExLjg0NC0xMS44M3ptNjkuMTkzIDUuMjEzczEyLjk2MS0xMi45NzMgMjAuMTcxLTIwLjE3NmMxLjYzMy0xLjYwNCAyLjMxNC0zLjc1IDIuMzI0LTYuMDEyLjAyMy00LjcxNi0zLjg2MS04LjQzNC04LjU4My04LjIxN2E4LjYwNCA4LjYwNCAwIDAgMC01LjUxOCAyLjMzOGMtNi44NTYgNi44MDUtMjAuMjIzIDIwLjIyMy0yMC4yMjMgMjAuMjIzbDExLjgzIDExLjg0NHptMzEuNzUzIDMxLjc1M3MxMi45NjEtMTIuOTczIDIwLjE3MS0yMC4xNzZjMS42MzMtMS42MDQgMi4zMTQtMy43NSAyLjMyNC02LjAxMi4wMjMtNC43MTYtMy44NjEtOC40MzQtOC41ODMtOC4yMTdhOC42MDQgOC42MDQgMCAwIDAtNS41MTggMi4zMzhjLTYuODU2IDYuODA1LTIwLjIyMyAyMC4yMjMtMjAuMjIzIDIwLjIyM2wxMS44MyAxMS44NDR6bS0xOC4wMDkgNjkuNjY3czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjQgNC43MTcuMDIyIDguNDM0LTMuODYyIDguMjE3LTguNTg0bC0uMDAyLjAwMmE4LjYwNiA4LjYwNiAwIDAgMC0yLjMzOC01LjUxOGMtNi44MDUtNi44NTYtMjAuMjIyLTIwLjIyMi0yMC4yMjItMjAuMjIybC0xMS44NDQgMTEuODN6bS0zNy45MTQgMzcuOTE0czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjMgNC43MTcuMDIzIDguNDM0LTMuODYxIDguMjE3LTguNTgzaC0uMDAyYTguNjAzIDguNjAzIDAgMCAwLTIuMzM3LTUuNTE4Yy02LjgwNS02Ljg1Ni0yMC4yMjMtMjAuMjIzLTIwLjIyMy0yMC4yMjNsLTExLjg0NCAxMS44M3ptLTY5LjY2Ny01LjY4N3MtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDIgOC42MDIgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44Mi0xMS44NHptLTMxLjc0My0zMS43NHMtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDQgOC42MDQgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44My0xMS44NXpNMTY3LjkgMTAxLjQ3YzEuNjgtMS43MDYgMy45NjctMi42NiA2LjI5Ny0yLjYyNmE3Ljg5IDcuODkgMCAwIDEgNC41NjMgMS41MWwxNi40OTkgMTIuMWMzLjIgMi4yOTcgNC4xNDQgNi42NTkgMi4yMyAxMC4zMTItMS45MTMgMy42NTMtNi4xMjMgNS41MjQtOS45NSA0LjQyM2w2LjEyNCAyMy45NDhjMS4xMTMgNC4zNTEtMS41NjQgOC45NjctNS45ODQgMTAuMzE3bC00NC42NDIgMTMuNjMgOC4yNDYgMzEuODg0YzEuMTczIDQuMzctMS41MDIgOS4wNDQtNS45NTUgMTAuNDA3cy04Ljk3NS0xLjExMS0xMC4wNjgtNS41MDVsLTEwLjI4Mi0zOS43N2MtMS4xMjYtNC4zNTUgMS41NS04Ljk4NCA1Ljk3Ni0xMC4zMzdsNDQuNjYxLTEzLjYzNy00LjEyMi0xNi4xMThjLTIuNzYzIDMuMDY0LTcuMjMzIDMuODA4LTEwLjU4NiAxLjc2MS0zLjM1My0yLjA0Ny00LjYxNC02LjI5LTIuOTg2LTEwLjA0N2w4LjExNy0xOS40NTRhOC44NzIgOC44NzIgMCAwIDEgMS44NjMtMi43OTd6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBzdHlsZT0idGV4dC1kZWNvcmF0aW9uLWNvbG9yOiMwMDA7aXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsO2Jsb2NrLXByb2dyZXNzaW9uOnRiO3RleHQtZGVjb3JhdGlvbi1saW5lOm5vbmU7dGV4dC1kZWNvcmF0aW9uLXN0eWxlOnNvbGlkO3RleHQtaW5kZW50OjA7dGV4dC10cmFuc2Zvcm06bm9uZSIgZD0iTTE2OC44NyAzMjAuMDRjMjguMzYzIDAgNTQuOTE1LTcuOTE1IDc3LjYxNC0yMS41MzhhMzYuNTc4IDM2LjU3OCAwIDAgMCAyMy4wNjcgOC4xOTQgOC43NjYgOC43NjYgMCAwIDAgLjAwNCAwYzIwLjE1NSAwIDM2LjY4LTE2LjUyOCAzNi42NzktMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAxMSAzNi42ODggMzYuNjg4IDAgMCAwLTguMTAzLTIyLjkyN2MxMy44MjUtMjIuODIgMjEuODY2LTQ5LjU3MiAyMS44NjYtNzguMTYyYTguNzY2IDguNzY2IDAgMSAwLTE3LjUzMSAwYzAgMjQuNzAzLTYuNzIgNDcuNzQ5LTE4LjM3OCA2Ny41NzUtNC41NjctMS45ODUtOS40NzMtMy4xNS0xNC41Mi0zLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEyIDBjLTIwLjE1NS0uMDAxLTM2LjY4MyAxNi41MjctMzYuNjgyIDM2LjY4Mi4wMDIgNC45OTkgMS4xMzkgOS44NjIgMy4wODMgMTQuMzk3LTE5LjcxNyAxMS40ODQtNDIuNTg2IDE4LjA5NS02Ny4wODYgMTguMDk1YTguNzY2IDguNzY2IDAgMSAwIDAgMTcuNTN6bTEwMC42OS0zMC44NzVjLTUuOTEzIDAtMTEuMTkxLTIuNTEyLTE0LjgzNi03LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMTgzLS4yMTQgMTkuMTM2IDE5LjEzNiAwIDAgMS00LjEzNC0xMS44NjNjLjAwMi0xMC42NzcgOC40NjgtMTkuMTQ0IDE5LjE0NC0xOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMSAxMiA0LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEzLjAxIDE5LjEzNiAxOS4xMzYgMCAwIDEgNy4xNDQgMTQuODkyYy0uMDAzIDEwLjY3Ny04LjQ3IDE5LjE0NS0xOS4xNDggMTkuMTQ2eiIvPjwvZz48L2c+PC9zdmc+\\\" />\\n </div>\\n</div>\"},\"title\":\"HTML Value Card\",\"dropShadow\":false,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 69 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"My value\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.random() * 5.45;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"cardCss\":\".card {\\n width: 100%;\\n height: 100%;\\n border: 2px solid #ccc;\\n box-sizing: border-box;\\n}\\n\\n.card .content {\\n padding: 20px;\\n display: flex;\\n flex-direction: row;\\n align-items: center;\\n justify-content: space-around;\\n height: 100%;\\n box-sizing: border-box;\\n}\\n\\n.card .content .column {\\n display: flex;\\n flex-direction: column; \\n justify-content: space-around;\\n height: 100%;\\n}\\n\\n.card h1 {\\n text-transform: uppercase;\\n color: #999;\\n font-size: 20px;\\n font-weight: bold;\\n margin: 0;\\n padding-bottom: 10px;\\n line-height: 32px;\\n}\\n\\n.card .value {\\n font-size: 38px;\\n font-weight: 200;\\n}\\n\\n.card .description {\\n font-size: 20px;\\n color: #999;\\n}\\n\",\"cardHtml\":\"<div class='card'>\\n <div class='content'>\\n <div class='column'>\\n <h1>Value title</h1>\\n <div class='value'>\\n ${My value:2} units.\\n </div> \\n <div class='description'>\\n Value description text\\n </div>\\n </div>\\n <img height=\\\"80px\\\" src=\\\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzIwIiB3aWR0aD0iMzIwIj48ZyBzdHJva2Utd2lkdGg9IjI4Ij48ZyBmaWxsPSIjMzA1NjgwIiBjb2xvcj0iIzAwMCIgd2hpdGUtc3BhY2U9Im5vcm1hbCI+PHBhdGggc3R5bGU9InRleHQtZGVjb3JhdGlvbi1jb2xvcjojMDAwO2lzb2xhdGlvbjphdXRvO21peC1ibGVuZC1tb2RlOm5vcm1hbDtibG9jay1wcm9ncmVzc2lvbjp0Yjt0ZXh0LWRlY29yYXRpb24tbGluZTpub25lO3RleHQtZGVjb3JhdGlvbi1zdHlsZTpzb2xpZDt0ZXh0LWluZGVudDowO3RleHQtdHJhbnNmb3JtOm5vbmUiIGQ9Ik0xNTEuMTMgMGMtMjguMzYzIDAtNTQuOTE1IDcuOTE1LTc3LjYxMyAyMS41MzdhMzYuNTc4IDM2LjU3OCAwIDAgMC0yMy4wNjctOC4xOTQgOC43NjYgOC43NjYgMCAwIDAtLjAwNCAwYy0yMC4xNTQuMDAxLTM2LjY3OSAxNi41MjgtMzYuNjc4IDM2LjY4MmE4Ljc2NiA4Ljc2NiAwIDAgMCAwIC4wMSAzNi42OSAzNi42OSAwIDAgMCA4LjEwNCAyMi45MjhjLTEzLjgzIDIyLjgzLTIxLjg3IDQ5LjU4LTIxLjg3IDc4LjE3YTguNzY2IDguNzY2IDAgMSAwIDE3LjUzIDBjMC0yNC43MDIgNi43Mi00Ny43NDggMTguMzc5LTY3LjU3NCA0LjU2NiAxLjk4NSA5LjQ3MiAzLjE1IDE0LjUxOSAzLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEyIDBjMjAuMTU1IDAgMzYuNjgzLTE2LjUyNyAzNi42ODItMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAwNGMtLjAwMS01LTEuMTM4LTkuODYzLTMuMDgzLTE0LjM5NyAxOS43MTctMTEuNDg0IDQyLjU4NS0xOC4wOTUgNjcuMDg1LTE4LjA5NWE4Ljc2NiA4Ljc2NiAwIDEgMCAwLTE3LjUzek01MC40NCAzMC44OGM1LjkxMy4wMDIgMTEuMTkxIDIuNTEyIDE0LjgzNiA3LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMCAuMTgzLjIxNCAxOS4xMzcgMTkuMTM3IDAgMCAxIDQuMTM0IDExLjg2M2MtLjAwMiAxMC42NzctOC40NjggMTkuMTQ0LTE5LjE0NCAxOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMS0xMi00LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEzLS4wMSAxOS4xMzYgMTkuMTM2IDAgMCAxLTcuMTQ0LTE0Ljg5MmMuMDAzLTEwLjY3NyA4LjQ3LTE5LjE0NCAxOS4xNDgtMTkuMTQ2eiIvPjxwYXRoIHN0eWxlPSJ0ZXh0LWRlY29yYXRpb24tY29sb3I6IzAwMDtpc29sYXRpb246YXV0bzttaXgtYmxlbmQtbW9kZTpub3JtYWw7YmxvY2stcHJvZ3Jlc3Npb246dGI7dGV4dC1kZWNvcmF0aW9uLWxpbmU6bm9uZTt0ZXh0LWRlY29yYXRpb24tc3R5bGU6c29saWQ7dGV4dC1pbmRlbnQ6MDt0ZXh0LXRyYW5zZm9ybTpub25lIiBkPSJNNjYuOTkyIDEwMi44M2E4LjE4NyA4LjE4NyAwIDAgMC0yLjI1OCA2LjA3MSA4LjYwNCA4LjYwNCAwIDAgMCAyLjMzOCA1LjUxOGM2LjgwNSA2Ljg1NiAyMC4yMjMgMjAuMjIzIDIwLjIyMyAyMC4yMjNsMTEuODQ0LTExLjgzcy0xMi45NzMtMTIuOTYxLTIwLjE3Ni0yMC4xNzFjLTEuNjA0LTEuNjMyLTMuNzUtMi4zMTQtNi4wMTItMi4zMjRhOC4xNSA4LjE1IDAgMCAwLTUuOTYgMi41MTJ6bTMyLjE0NyAxOS45ODNMNjIuNSAxNTkuNDUyYy0zLjk3NSAzLjk3Ni0zLjk3NSAxMC40MjEgMCAxNC4zOTdsMTguMTU2IDE4LjE1NiAzMS43NTMgMzEuNzUzIDMwLjQ3OCAzMC40NzhjMy45NzYgMy45NzYgMTAuNDIyIDMuOTc2IDE0LjM5OCAwbDI0Ljc5MS0yNC43OTEgMzcuOTE0LTM3LjkxNCAzNi42MzktMzYuNjM5YzMuOTc1LTMuOTc2IDMuOTc1LTEwLjQyMiAwLTE0LjM5OGwtMTguNjMtMTguNjMtMzEuNzUtMzEuNzYtMzAuMDEtMzBjLTMuOTc3LTMuOTc1LTEwLjQyMi0zLjk3NS0xNC4zOTggMGwtMjQuNzkgMjQuNzktMzcuOTEgMzcuOTF6bTM3LjkxMS0zNy45MXMtMTIuOTczLTEyLjk2MS0yMC4xNzYtMjAuMTcxYy0xLjYwNC0xLjYzMi0zLjc1LTIuMzE0LTYuMDEyLTIuMzI0LTQuNzE3LS4wMjMtOC40MzQgMy44NjEtOC4yMTcgOC41ODNhOC42MDQgOC42MDQgMCAwIDAgMi4zMzcgNS41MThjNi44MDUgNi44NTYgMjAuMjIzIDIwLjIyMyAyMC4yMjMgMjAuMjIzbDExLjg0NC0xMS44M3ptNjkuMTkzIDUuMjEzczEyLjk2MS0xMi45NzMgMjAuMTcxLTIwLjE3NmMxLjYzMy0xLjYwNCAyLjMxNC0zLjc1IDIuMzI0LTYuMDEyLjAyMy00LjcxNi0zLjg2MS04LjQzNC04LjU4My04LjIxN2E4LjYwNCA4LjYwNCAwIDAgMC01LjUxOCAyLjMzOGMtNi44NTYgNi44MDUtMjAuMjIzIDIwLjIyMy0yMC4yMjMgMjAuMjIzbDExLjgzIDExLjg0NHptMzEuNzUzIDMxLjc1M3MxMi45NjEtMTIuOTczIDIwLjE3MS0yMC4xNzZjMS42MzMtMS42MDQgMi4zMTQtMy43NSAyLjMyNC02LjAxMi4wMjMtNC43MTYtMy44NjEtOC40MzQtOC41ODMtOC4yMTdhOC42MDQgOC42MDQgMCAwIDAtNS41MTggMi4zMzhjLTYuODU2IDYuODA1LTIwLjIyMyAyMC4yMjMtMjAuMjIzIDIwLjIyM2wxMS44MyAxMS44NDR6bS0xOC4wMDkgNjkuNjY3czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjQgNC43MTcuMDIyIDguNDM0LTMuODYyIDguMjE3LTguNTg0bC0uMDAyLjAwMmE4LjYwNiA4LjYwNiAwIDAgMC0yLjMzOC01LjUxOGMtNi44MDUtNi44NTYtMjAuMjIyLTIwLjIyMi0yMC4yMjItMjAuMjIybC0xMS44NDQgMTEuODN6bS0zNy45MTQgMzcuOTE0czEyLjk3MyAxMi45NjEgMjAuMTc4IDIwLjE3YzEuNjA0IDEuNjMyIDMuNzUgMi4zMTMgNi4wMTIgMi4zMjMgNC43MTcuMDIzIDguNDM0LTMuODYxIDguMjE3LTguNTgzaC0uMDAyYTguNjAzIDguNjAzIDAgMCAwLTIuMzM3LTUuNTE4Yy02LjgwNS02Ljg1Ni0yMC4yMjMtMjAuMjIzLTIwLjIyMy0yMC4yMjNsLTExLjg0NCAxMS44M3ptLTY5LjY2Ny01LjY4N3MtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDIgOC42MDIgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44Mi0xMS44NHptLTMxLjc0My0zMS43NHMtMTIuOTYxIDEyLjk3My0yMC4xNjkgMjAuMTc4Yy0xLjYzMiAxLjYwNC0yLjMxNCAzLjc1LTIuMzI0IDYuMDEyLS4wMjMgNC43MTcgMy44NjEgOC40MzQgOC41ODMgOC4yMTdoLS4wMDJhOC42MDQgOC42MDQgMCAwIDAgNS41MTgtMi4zMzdjNi44NTYtNi44MDUgMjAuMjIzLTIwLjIyMyAyMC4yMjMtMjAuMjIzbC0xMS44My0xMS44NXpNMTY3LjkgMTAxLjQ3YzEuNjgtMS43MDYgMy45NjctMi42NiA2LjI5Ny0yLjYyNmE3Ljg5IDcuODkgMCAwIDEgNC41NjMgMS41MWwxNi40OTkgMTIuMWMzLjIgMi4yOTcgNC4xNDQgNi42NTkgMi4yMyAxMC4zMTItMS45MTMgMy42NTMtNi4xMjMgNS41MjQtOS45NSA0LjQyM2w2LjEyNCAyMy45NDhjMS4xMTMgNC4zNTEtMS41NjQgOC45NjctNS45ODQgMTAuMzE3bC00NC42NDIgMTMuNjMgOC4yNDYgMzEuODg0YzEuMTczIDQuMzctMS41MDIgOS4wNDQtNS45NTUgMTAuNDA3cy04Ljk3NS0xLjExMS0xMC4wNjgtNS41MDVsLTEwLjI4Mi0zOS43N2MtMS4xMjYtNC4zNTUgMS41NS04Ljk4NCA1Ljk3Ni0xMC4zMzdsNDQuNjYxLTEzLjYzNy00LjEyMi0xNi4xMThjLTIuNzYzIDMuMDY0LTcuMjMzIDMuODA4LTEwLjU4NiAxLjc2MS0zLjM1My0yLjA0Ny00LjYxNC02LjI5LTIuOTg2LTEwLjA0N2w4LjExNy0xOS40NTRhOC44NzIgOC44NzIgMCAwIDEgMS44NjMtMi43OTd6IiBmaWxsLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBzdHlsZT0idGV4dC1kZWNvcmF0aW9uLWNvbG9yOiMwMDA7aXNvbGF0aW9uOmF1dG87bWl4LWJsZW5kLW1vZGU6bm9ybWFsO2Jsb2NrLXByb2dyZXNzaW9uOnRiO3RleHQtZGVjb3JhdGlvbi1saW5lOm5vbmU7dGV4dC1kZWNvcmF0aW9uLXN0eWxlOnNvbGlkO3RleHQtaW5kZW50OjA7dGV4dC10cmFuc2Zvcm06bm9uZSIgZD0iTTE2OC44NyAzMjAuMDRjMjguMzYzIDAgNTQuOTE1LTcuOTE1IDc3LjYxNC0yMS41MzhhMzYuNTc4IDM2LjU3OCAwIDAgMCAyMy4wNjcgOC4xOTQgOC43NjYgOC43NjYgMCAwIDAgLjAwNCAwYzIwLjE1NSAwIDM2LjY4LTE2LjUyOCAzNi42NzktMzYuNjgyYTguNzY2IDguNzY2IDAgMCAwIDAtLjAxMSAzNi42ODggMzYuNjg4IDAgMCAwLTguMTAzLTIyLjkyN2MxMy44MjUtMjIuODIgMjEuODY2LTQ5LjU3MiAyMS44NjYtNzguMTYyYTguNzY2IDguNzY2IDAgMSAwLTE3LjUzMSAwYzAgMjQuNzAzLTYuNzIgNDcuNzQ5LTE4LjM3OCA2Ny41NzUtNC41NjctMS45ODUtOS40NzMtMy4xNS0xNC41Mi0zLjE1N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMDEyIDBjLTIwLjE1NS0uMDAxLTM2LjY4MyAxNi41MjctMzYuNjgyIDM2LjY4Mi4wMDIgNC45OTkgMS4xMzkgOS44NjIgMy4wODMgMTQuMzk3LTE5LjcxNyAxMS40ODQtNDIuNTg2IDE4LjA5NS02Ny4wODYgMTguMDk1YTguNzY2IDguNzY2IDAgMSAwIDAgMTcuNTN6bTEwMC42OS0zMC44NzVjLTUuOTEzIDAtMTEuMTkxLTIuNTEyLTE0LjgzNi03LjA3N2E4Ljc2NiA4Ljc2NiAwIDAgMC0uMTgzLS4yMTQgMTkuMTM2IDE5LjEzNiAwIDAgMS00LjEzNC0xMS44NjNjLjAwMi0xMC42NzcgOC40NjgtMTkuMTQ0IDE5LjE0NC0xOS4xNDhhMTkuMTQ1IDE5LjE0NSAwIDAgMSAxMiA0LjI1NCA4Ljc2NiA4Ljc2NiAwIDAgMCAuMDEzLjAxIDE5LjEzNiAxOS4xMzYgMCAwIDEgNy4xNDQgMTQuODkyYy0uMDAzIDEwLjY3Ny04LjQ3IDE5LjE0NS0xOS4xNDggMTkuMTQ2eiIvPjwvZz48L2c+PC9zdmc+\\\" />\\n </div>\\n</div>\"},\"title\":\"HTML Value Card\",\"dropShadow\":false,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -109,12 +109,12 @@ | @@ -109,12 +109,12 @@ | ||
109 | "sizeX": 8, | 109 | "sizeX": 8, |
110 | "sizeY": 6.5, | 110 | "sizeY": 6.5, |
111 | "resources": [], | 111 | "resources": [], |
112 | - "templateHtml": "<tb-timeseries-table-widget \n table-id=\"tableId\"\n ctx=\"ctx\">\n</tb-timeseries-table-widget>", | 112 | + "templateHtml": "<tb-timeseries-table-widget \n [ctx]=\"ctx\">\n</tb-timeseries-table-widget>", |
113 | "templateCss": "", | 113 | "templateCss": "", |
114 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.tableId = \"table-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('timeseries-table-data-updated', self.ctx.$scope.tableId);\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}", | 114 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.timeseriesTableWidget.onDataUpdated();\n}\n\nself.actionSources = function() {\n return {\n 'actionCellButton': {\n name: 'widget-action.action-cell-button',\n multiple: true\n },\n 'rowClick': {\n name: 'widget-action.row-click',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}", |
115 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showMilliseconds\": {\n \"title\": \"Display timestamp milliseconds\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"hideEmptyLines\": {\n \"title\": \"Hide empty lines\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"showMilliseconds\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"hideEmptyLines\"\n ]\n}", | 115 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"TimeseriesTableSettings\",\n \"properties\": {\n \"showTimestamp\": {\n \"title\": \"Display timestamp column\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showMilliseconds\": {\n \"title\": \"Display timestamp milliseconds\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"displayPagination\": {\n \"title\": \"Display pagination\",\n \"type\": \"boolean\",\n \"default\": true\n }, \n \"defaultPageSize\": {\n \"title\": \"Default page size\",\n \"type\": \"number\",\n \"default\": 10\n },\n \"hideEmptyLines\": {\n \"title\": \"Hide empty lines\",\n \"type\": \"boolean\",\n \"default\": false\n }\n },\n \"required\": []\n },\n \"form\": [\n \"showTimestamp\",\n \"showMilliseconds\",\n \"displayPagination\",\n \"defaultPageSize\",\n \"hideEmptyLines\"\n ]\n}", |
116 | - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, filter)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | ||
117 | - "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{}}" | 116 | + "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"useCellStyleFunction\": {\n \"title\": \"Use cell style function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellStyleFunction\": {\n \"title\": \"Cell style function: f(value)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"useCellContentFunction\": {\n \"title\": \"Use cell content function\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"cellContentFunction\": {\n \"title\": \"Cell content function: f(value, rowData, ctx)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"useCellStyleFunction\",\n {\n \"key\": \"cellStyleFunction\",\n \"type\": \"javascript\"\n },\n \"useCellContentFunction\",\n {\n \"key\": \"cellContentFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
117 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', amount = percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true,\"displayPagination\":true,\"defaultPageSize\":10},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\"}" | ||
118 | } | 118 | } |
119 | }, | 119 | }, |
120 | { | 120 | { |
@@ -125,13 +125,13 @@ | @@ -125,13 +125,13 @@ | ||
125 | "sizeX": 7.5, | 125 | "sizeX": 7.5, |
126 | "sizeY": 3.5, | 126 | "sizeY": 3.5, |
127 | "resources": [], | 127 | "resources": [], |
128 | - "templateHtml": "<tb-entities-hierarchy-widget \n hierarchy-id=\"hierarchyId\"\n ctx=\"ctx\">\n</tb-entities-hierarchy-widget>", | 128 | + "templateHtml": "<tb-entities-hierarchy-widget \n [ctx]=\"ctx\">\n</tb-entities-hierarchy-widget>", |
129 | "templateCss": "", | 129 | "templateCss": "", |
130 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.hierarchyId = \"hierarchy-\"+id;\n scope.ctx = self.ctx;\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.$broadcast('entities-hierarchy-data-updated', self.ctx.$scope.hierarchyId);\n}\n\nself.typeParameters = function() {\n return {\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'nodeSelected': {\n name: 'widget-action.node-selected',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", | 130 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onDataUpdated = function() {\n self.ctx.$scope.entitiesHierarchyWidget.onDataUpdated();\n}\n\nself.typeParameters = function() {\n return {\n dataKeysOptional: true\n };\n}\n\nself.actionSources = function() {\n return {\n 'nodeSelected': {\n name: 'widget-action.node-selected',\n multiple: false\n }\n };\n}\n\nself.onDestroy = function() {\n}\n", |
131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesHierarchySettings\",\n \"properties\": {\n \"nodeRelationQueryFunction\": {\n \"title\": \"Node relations query function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeHasChildrenFunction\": {\n \"title\": \"Node has children function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeOpenedFunction\": {\n \"title\": \"Default node opened function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeDisabledFunction\": {\n \"title\": \"Node disabled function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeIconFunction\": {\n \"title\": \"Node icon function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeTextFunction\": {\n \"title\": \"Node text function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodesSortFunction\": {\n \"title\": \"Nodes sort function: f(nodeCtx1, nodeCtx2)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"nodeRelationQueryFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeHasChildrenFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeOpenedFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeDisabledFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeIconFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeTextFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodesSortFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | 131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesHierarchySettings\",\n \"properties\": {\n \"nodeRelationQueryFunction\": {\n \"title\": \"Node relations query function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeHasChildrenFunction\": {\n \"title\": \"Node has children function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeOpenedFunction\": {\n \"title\": \"Default node opened function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeDisabledFunction\": {\n \"title\": \"Node disabled function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeIconFunction\": {\n \"title\": \"Node icon function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodeTextFunction\": {\n \"title\": \"Node text function: f(nodeCtx)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"nodesSortFunction\": {\n \"title\": \"Nodes sort function: f(nodeCtx1, nodeCtx2)\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"nodeRelationQueryFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeHasChildrenFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeOpenedFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeDisabledFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeIconFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodeTextFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"nodesSortFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
132 | "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {},\n \"required\": []\n },\n \"form\": []\n}", | 132 | "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {},\n \"required\": []\n },\n \"form\": []\n}", |
133 | "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"nodeRelationQueryFunction\":\"/**\\n\\n// Function should return relations query object for current node used to fetch entity children.\\n// Function can return 'default' string value. In this case default relations query will be used.\\n\\n// The following example code will construct simple relations query that will fetch relations of type 'Contains'\\n// from the current entity.\\n\\nvar entity = nodeCtx.entity;\\nvar query = {\\n parameters: {\\n rootId: entity.id.id,\\n rootType: entity.id.entityType,\\n direction: types.entitySearchDirection.from,\\n relationTypeGroup: \\\"COMMON\\\",\\n maxLevel: 1\\n },\\n filters: [{\\n relationType: \\\"Contains\\\",\\n entityTypes: []\\n }]\\n};\\nreturn query;\\n\\n**/\\n\",\"nodeHasChildrenFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node has children (whether it can be expanded).\\n\\n// The following example code will restrict entities hierarchy expansion up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n// The next example code will restrict entities expansion according to the value of example 'nodeHasChildren' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {\\n return data['nodeHasChildren'] === 'true';\\n} else {\\n return true;\\n}\\n \\n**/\\n \",\"nodeTextFunction\":\"/**\\n\\n// Function should return text (can be HTML code) for the current node.\\n\\n// The following example code will generate node text consisting of entity name and temperature if temperature value is present in entity attributes/timeseries.\\n\\nvar data = nodeCtx.data;\\nvar entity = nodeCtx.entity;\\nvar text = entity.name;\\nif (data.hasOwnProperty('temperature') && data['temperature'] !== null) {\\n text += \\\" <b>\\\"+ data['temperature'] +\\\" °C</b>\\\";\\n}\\nreturn text;\\n\\n**/\",\"nodeIconFunction\":\"/** \\n\\n// Function should return node icon info object.\\n// Resulting object should contain either 'materialIcon' or 'iconUrl' property. \\n// Where:\\n - 'materialIcon' - name of the material icon to be used from the Material Icons Library (https://material.io/tools/icons);\\n - 'iconUrl' - url of the external image to be used as node icon.\\n// Function can return 'default' string value. In this case default icons according to entity type will be used.\\n\\n// The following example code shows how to use external image for devices which name starts with 'Test' and use \\n// default icons for the rest of entities.\\n\\nvar entity = nodeCtx.entity;\\nif (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {\\n return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};\\n} else {\\n return 'default';\\n}\\n \\n**/\",\"nodeDisabledFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be disabled (not selectable).\\n\\n// The following example code will disable current node according to the value of example 'nodeDisabled' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {\\n return data['nodeDisabled'] === 'true';\\n} else {\\n return false;\\n}\\n \\n**/\\n\",\"nodesSortFunction\":\"/**\\n\\n// This function is used to sort nodes of the same level. Function should compare two nodes and return \\n// integer value: \\n// - less than 0 - sort nodeCtx1 to an index lower than nodeCtx2\\n// - 0 - leave nodeCtx1 and nodeCtx2 unchanged with respect to each other\\n// - greater than 0 - sort nodeCtx2 to an index lower than nodeCtx1\\n\\n// The following example code will sort entities first by entity type in alphabetical order then\\n// by entity name in alphabetical order.\\n\\nvar result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);\\nif (result === 0) {\\n result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);\\n}\\nreturn result;\\n \\n**/\",\"nodeOpenedFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be opened (expanded) when it first loaded.\\n\\n// The following example code will open by default nodes up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n**/\\n \"},\"title\":\"Entities hierarchy\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"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;\"}]}],\"widgetStyle\":{},\"actions\":{}}" | 133 | "defaultConfig": "{\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":86400000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"4px\",\"settings\":{\"nodeRelationQueryFunction\":\"/**\\n\\n// Function should return relations query object for current node used to fetch entity children.\\n// Function can return 'default' string value. In this case default relations query will be used.\\n\\n// The following example code will construct simple relations query that will fetch relations of type 'Contains'\\n// from the current entity.\\n\\nvar entity = nodeCtx.entity;\\nvar query = {\\n parameters: {\\n rootId: entity.id.id,\\n rootType: entity.id.entityType,\\n direction: types.entitySearchDirection.from,\\n relationTypeGroup: \\\"COMMON\\\",\\n maxLevel: 1\\n },\\n filters: [{\\n relationType: \\\"Contains\\\",\\n entityTypes: []\\n }]\\n};\\nreturn query;\\n\\n**/\\n\",\"nodeHasChildrenFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node has children (whether it can be expanded).\\n\\n// The following example code will restrict entities hierarchy expansion up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n// The next example code will restrict entities expansion according to the value of example 'nodeHasChildren' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeHasChildren') && data['nodeHasChildren'] !== null) {\\n return data['nodeHasChildren'] === 'true';\\n} else {\\n return true;\\n}\\n \\n**/\\n \",\"nodeTextFunction\":\"/**\\n\\n// Function should return text (can be HTML code) for the current node.\\n\\n// The following example code will generate node text consisting of entity name and temperature if temperature value is present in entity attributes/timeseries.\\n\\nvar data = nodeCtx.data;\\nvar entity = nodeCtx.entity;\\nvar text = entity.name;\\nif (data.hasOwnProperty('temperature') && data['temperature'] !== null) {\\n text += \\\" <b>\\\"+ data['temperature'] +\\\" °C</b>\\\";\\n}\\nreturn text;\\n\\n**/\",\"nodeIconFunction\":\"/** \\n\\n// Function should return node icon info object.\\n// Resulting object should contain either 'materialIcon' or 'iconUrl' property. \\n// Where:\\n - 'materialIcon' - name of the material icon to be used from the Material Icons Library (https://material.io/tools/icons);\\n - 'iconUrl' - url of the external image to be used as node icon.\\n// Function can return 'default' string value. In this case default icons according to entity type will be used.\\n\\n// The following example code shows how to use external image for devices which name starts with 'Test' and use \\n// default icons for the rest of entities.\\n\\nvar entity = nodeCtx.entity;\\nif (entity.id.entityType === 'DEVICE' && entity.name.startsWith('Test')) {\\n return {iconUrl: 'https://avatars1.githubusercontent.com/u/14793288?v=4&s=117'};\\n} else {\\n return 'default';\\n}\\n \\n**/\",\"nodeDisabledFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be disabled (not selectable).\\n\\n// The following example code will disable current node according to the value of example 'nodeDisabled' attribute.\\n\\nvar data = nodeCtx.data;\\nif (data.hasOwnProperty('nodeDisabled') && data['nodeDisabled'] !== null) {\\n return data['nodeDisabled'] === 'true';\\n} else {\\n return false;\\n}\\n \\n**/\\n\",\"nodesSortFunction\":\"/**\\n\\n// This function is used to sort nodes of the same level. Function should compare two nodes and return \\n// integer value: \\n// - less than 0 - sort nodeCtx1 to an index lower than nodeCtx2\\n// - 0 - leave nodeCtx1 and nodeCtx2 unchanged with respect to each other\\n// - greater than 0 - sort nodeCtx2 to an index lower than nodeCtx1\\n\\n// The following example code will sort entities first by entity type in alphabetical order then\\n// by entity name in alphabetical order.\\n\\nvar result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType);\\nif (result === 0) {\\n result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name);\\n}\\nreturn result;\\n \\n**/\",\"nodeOpenedFunction\":\"/**\\n\\n// Function should return boolean value indicating whether current node should be opened (expanded) when it first loaded.\\n\\n// The following example code will open by default nodes up to third level.\\n\\nreturn nodeCtx.level <= 2;\\n\\n**/\\n \"},\"title\":\"Entities hierarchy\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":false,\"showLegend\":false,\"datasources\":[{\"type\":\"function\",\"name\":\"Simulated\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.472295003170325,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Cos\",\"color\":\"#4caf50\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.8926244886945558,\"funcBody\":\"return Math.round(1000*Math.cos(time/5000));\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#f44336\",\"settings\":{\"columnWidth\":\"0px\",\"useCellStyleFunction\":false,\"cellStyleFunction\":\"\",\"useCellContentFunction\":false,\"cellContentFunction\":\"\"},\"_hash\":0.6401141393938932,\"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;\"}]}],\"widgetStyle\":{},\"actions\":{}}" |
134 | } | 134 | } |
135 | } | 135 | } |
136 | ] | 136 | ] |
137 | -} | 137 | +} |
@@ -55,7 +55,7 @@ | @@ -55,7 +55,7 @@ | ||
55 | ], | 55 | ], |
56 | "templateHtml": "<canvas id=\"pieChart\"></canvas>\n", | 56 | "templateHtml": "<canvas id=\"pieChart\"></canvas>\n", |
57 | "templateCss": "", | 57 | "templateCss": "", |
58 | - "controllerScript": "self.onInit = function() {\n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n var borderColor = self.ctx.settings.borderColor || '#fff';\n var borderWidth = angular.isDefined(self.ctx.settings.borderWidth) ? self.ctx.settings.borderWidth : 5;\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n pieData.labels.push(dataKey.label);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push(borderColor);\n dataset.borderWidth.push(borderWidth);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var options = {\n responsive: false,\n maintainAspectRatio: false,\n legend: {\n display: true,\n labels: {\n fontColor: '#666'\n }\n },\n tooltips: {\n callbacks: {\n label: function(tooltipItem, data) {\n var label = data.labels[tooltipItem.index];\n var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n var content = label + ': ' + value;\n var units = self.ctx.settings.units ? self.ctx.settings.units : self.ctx.units;\n if (units) {\n content += ' ' + units;\n } \n return content;\n }\n }\n }\n };\n\n if (self.ctx.settings.legend) {\n options.legend.display = self.ctx.settings.legend.display !== false;\n options.legend.labels.fontColor = self.ctx.settings.legend.labelsFontColor || '#666';\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'doughnut',\n data: pieData,\n options: options\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = tvPair[1];\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\n", | 58 | + "controllerScript": "self.onInit = function() {\n var pieData = {\n labels: [],\n datasets: []\n };\n\n var dataset = {\n data: [],\n backgroundColor: [],\n borderColor: [],\n borderWidth: [],\n hoverBackgroundColor: []\n }\n \n var borderColor = self.ctx.settings.borderColor || '#fff';\n var borderWidth = typeof self.ctx.settings.borderWidth !== 'undefined' ? self.ctx.settings.borderWidth : 5;\n \n pieData.datasets.push(dataset);\n \n for (var i=0; i < self.ctx.data.length; i++) {\n var dataKey = self.ctx.data[i].dataKey;\n pieData.labels.push(dataKey.label);\n dataset.data.push(0);\n var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n dataset.backgroundColor.push(dataKey.color);\n dataset.borderColor.push(borderColor);\n dataset.borderWidth.push(borderWidth);\n dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n }\n\n var options = {\n responsive: false,\n maintainAspectRatio: false,\n legend: {\n display: true,\n labels: {\n fontColor: '#666'\n }\n },\n tooltips: {\n callbacks: {\n label: function(tooltipItem, data) {\n var label = data.labels[tooltipItem.index];\n var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n var content = label + ': ' + value;\n var units = self.ctx.settings.units ? self.ctx.settings.units : self.ctx.units;\n if (units) {\n content += ' ' + units;\n } \n return content;\n }\n }\n }\n };\n\n if (self.ctx.settings.legend) {\n options.legend.display = self.ctx.settings.legend.display !== false;\n options.legend.labels.fontColor = self.ctx.settings.legend.labelsFontColor || '#666';\n }\n\n var ctx = $('#pieChart', self.ctx.$container);\n self.ctx.chart = new Chart(ctx, {\n type: 'doughnut',\n data: pieData,\n options: options\n });\n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.data.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n var value = tvPair[1];\n self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n }\n }\n self.ctx.chart.update();\n}\n\nself.onResize = function() {\n self.ctx.chart.resize();\n}\n\n", |
59 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"borderWidth\": {\n \"title\": \"Border width\",\n \"type\": \"number\",\n \"default\": 5\n },\n \"borderColor\": {\n \"title\": \"Border color\",\n \"type\": \"string\",\n \"default\": \"#fff\"\n },\n \"legend\": {\n \"title\": \"Legend settings\",\n \"type\": \"object\",\n \"properties\": {\n \"display\": {\n \"title\": \"Display legend\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"labelsFontColor\": {\n \"title\": \"Labels font color\",\n \"type\": \"string\",\n \"default\": \"#666\"\n }\n }\n }\n },\n \"required\": []\n },\n \"form\": [\n \"borderWidth\", \n {\n \"key\": \"borderColor\",\n \"type\": \"color\"\n }, \n {\n \"key\": \"legend\",\n \"items\": [\n \"legend.display\",\n {\n \"key\": \"legend.labelsFontColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n}", | 59 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"borderWidth\": {\n \"title\": \"Border width\",\n \"type\": \"number\",\n \"default\": 5\n },\n \"borderColor\": {\n \"title\": \"Border color\",\n \"type\": \"string\",\n \"default\": \"#fff\"\n },\n \"legend\": {\n \"title\": \"Legend settings\",\n \"type\": \"object\",\n \"properties\": {\n \"display\": {\n \"title\": \"Display legend\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"labelsFontColor\": {\n \"title\": \"Labels font color\",\n \"type\": \"string\",\n \"default\": \"#666\"\n }\n }\n }\n },\n \"required\": []\n },\n \"form\": [\n \"borderWidth\", \n {\n \"key\": \"borderColor\",\n \"type\": \"color\"\n }, \n {\n \"key\": \"legend\",\n \"items\": [\n \"legend.display\",\n {\n \"key\": \"legend.labelsFontColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n}", |
60 | "dataKeySettingsSchema": "{}\n", | 60 | "dataKeySettingsSchema": "{}\n", |
61 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#26a69a\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#afb42b\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#673ab7\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"borderWidth\":5,\"borderColor\":\"#fff\",\"legend\":{\"display\":true,\"labelsFontColor\":\"#666666\"}},\"title\":\"Doughnut - Chart.js\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" | 61 | "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#26a69a\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#afb42b\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#673ab7\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"borderWidth\":5,\"borderColor\":\"#fff\",\"legend\":{\"display\":true,\"labelsFontColor\":\"#666666\"}},\"title\":\"Doughnut - Chart.js\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}" |
@@ -15,7 +15,7 @@ | @@ -15,7 +15,7 @@ | ||
15 | "resources": [], | 15 | "resources": [], |
16 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", | 16 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", |
17 | "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", | 17 | "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", |
18 | - "controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = angular.copy(command).trim();\n if (localCommand == 'help') {\n printUsage(this);\n } else {\n var cmdObj = $.terminal.parse_command(localCommand);\n if (cmdObj.args.length > 1) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (cmdObj.args.length && cmdObj.args[0]) {\n try {\n params = JSON.parse(cmdObj.args[0]);\n } catch (e) {\n params = cmdObj.args[0];\n }\n }\n performRpc(this, cmdObj.name, params);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt\n });\n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout).then(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n \nself.onDestroy = function() {\n}\n", | 18 | + "controllerScript": "var requestTimeout = 500;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n var rpcEnabled = subscription.rpcEnabled;\n var deviceName = 'Simulated';\n var prompt;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n var greetings = 'Welcome to ThingsBoard RPC debug terminal.\\n\\n';\n if (!rpcEnabled) {\n greetings += 'Target device is not set!\\n\\n';\n prompt = '';\n } else {\n greetings += 'Current target device for RPC commands: [[b;#fff;]' + deviceName + ']\\n\\n';\n greetings += 'Please type [[b;#fff;]\\'help\\'] to see usage.\\n';\n prompt = '[[b;#8bc34a;]' + deviceName +']> ';\n }\n \n var terminal = $('#device-terminal', self.ctx.$container).terminal(\n function(command) {\n if (command !== '') {\n try {\n var localCommand = command.trim();\n if (localCommand === 'help') {\n printUsage(this);\n } else {\n var cmdObj = $.terminal.parse_command(localCommand);\n if (cmdObj.args.length > 1) {\n this.error(\"Wrong number of arguments!\");\n this.echo(' ');\n } else {\n var params;\n if (cmdObj.args.length && cmdObj.args[0]) {\n try {\n params = JSON.parse(cmdObj.args[0]);\n } catch (e) {\n params = cmdObj.args[0];\n }\n }\n performRpc(this, cmdObj.name, params);\n }\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: greetings,\n prompt: prompt,\n enabled: rpcEnabled\n });\n \n \n \n if (!rpcEnabled) {\n terminal.error('No RPC target detected!').pause();\n }\n}\n\n\nfunction printUsage(terminal) {\n var commandsListText = '\\n[[b;#fff;]Usage:]\\n';\n commandsListText += ' <method> [params body]]\\n\\n';\n commandsListText += '[[b;#fff;]Example 1:]\\n'; \n commandsListText += ' myRemoteMethod1 myText\\n\\n'; \n commandsListText += '[[b;#fff;]Example 2:]\\n'; \n commandsListText += ' myOtherRemoteMethod \"{\\\\\"key1\\\\\": 2, \\\\\"key2\\\\\": \\\\\"myVal\\\\\"}\"\\n'; \n terminal.echo(new String(commandsListText));\n}\n\nfunction performRpc(terminal, method, params) {\n terminal.pause();\n self.ctx.controlApi.sendTwoWayCommand(method, params, requestTimeout).subscribe(\n function success(responseBody) {\n terminal.echo(JSON.stringify(responseBody));\n terminal.echo(' ');\n terminal.resume();\n },\n function fail() {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.echo(' ');\n terminal.resume();\n }\n );\n}\n\n \nself.onDestroy = function() {\n}\n", |
19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}", | 19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}", |
20 | "dataKeySettingsSchema": "{}\n", | 20 | "dataKeySettingsSchema": "{}\n", |
21 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 21 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC debug terminal\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | "resources": [], | 31 | "resources": [], |
32 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", | 32 | "templateHtml": "<div style=\"height: 100%; overflow-y: auto;\" id=\"device-terminal\"></div>", |
33 | "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", | 33 | "templateCss": ".cmd .cursor.blink {\n -webkit-animation-name: terminal-underline;\n -moz-animation-name: terminal-underline;\n -ms-animation-name: terminal-underline;\n animation-name: terminal-underline;\n}\n.terminal .inverted, .cmd .inverted {\n border-bottom-color: #aaa;\n}\n", |
34 | - "controllerScript": "var requestTimeout = 500;\nconst commandStatusPollingInterval = 200;\n\nconst welcome = 'Welcome to ThingsBoard RPC remote shell.\\n';\n\nvar terminal, rpcEnabled, simulated, deviceName, cwd;\nvar commandExecuting = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n rpcEnabled = subscription.rpcEnabled;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n } else {\n deviceName = 'Simulated';\n simulated = true;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n \n terminal = $('#device-terminal', self.ctx.$container).terminal(\n function (command) {\n if (command && command.trim().length) {\n try {\n if (simulated) {\n this.echo(command);\n } else {\n sendCommand(this, command);\n }\n } catch(e) {\n this.error(new String(e));\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: false,\n prompt: rpcEnabled ? currentPrompt : '',\n name: 'shell',\n pauseEvents: false,\n keydown: (e, term) => {\n if ((e.which == 67 || e.which == 68) && e.ctrlKey) { // CTRL+C || CTRL+D\n if (commandExecuting) {\n terminateCommand(term);\n return false;\n }\n }\n },\n onInit: initTerm\n }\n );\n}\n\nfunction initTerm(terminal) {\n terminal.echo(welcome);\n if (!rpcEnabled) {\n terminal.error('Target device is not set!\\n');\n } else {\n terminal.echo(`Current target device for RPC terminal: [[b;#fff;]${deviceName}]\\n`);\n if (!simulated) {\n terminal.pause();\n getTermInfo(terminal,\n (remoteTermInfo) => {\n if (remoteTermInfo) {\n terminal.echo(`Remote platform info:`);\n terminal.echo(`OS: [[b;#fff;]${remoteTermInfo.platform}]`);\n if (remoteTermInfo.release) {\n terminal.echo(`OS release: [[b;#fff;]${remoteTermInfo.release}]`);\n }\n terminal.echo('\\r');\n } else {\n terminal.echo('[[;#f00;]Unable to get remote platform info.\\nDevice is not responding.]\\n');\n }\n terminal.resume();\n });\n }\n }\n}\n\nfunction currentPrompt(callback) {\n if (cwd) {\n callback('[[b;#2196f3;]' + deviceName +']: [[b;#8bc34a;]' + cwd +']> ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName +']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).then(\n (termInfo) => {\n cwd = termInfo.cwd;\n if (callback) {\n callback(termInfo);\n } \n },\n () => {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).then(\n (responseBody) => {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout( pollCommandStatus.bind(null,terminal), commandStatusPollingInterval );\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n () => {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).then(\n (responseBody) => {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n } \n },\n () => {\n onRpcError(terminal);\n }\n ); \n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).then(\n (commandStatusResponse) => {\n commandStatusResponse.data.forEach((dataElement) => {\n if (dataElement.stdout) {\n terminal.echo(dataElement.stdout);\n }\n if (dataElement.stderr) {\n terminal.error(dataElement.stderr);\n }\n }); \n if (commandStatusResponse.done) {\n commandExecuting = false;\n cwd = commandStatusResponse.cwd;\n terminal.resume();\n } else {\n var interval = commandStatusPollingInterval;\n if (!commandStatusResponse.data.length) {\n interval *=5;\n }\n setTimeout( pollCommandStatus.bind(null,terminal), interval );\n }\n },\n () => {\n commandExecuting = false;\n onRpcError(terminal);\n }\n );\n}\n\nself.onResize = function () {\n if (terminal) {\n terminal.resize(self.ctx.width, self.ctx.height);\n }\n}\n\nself.onDestroy = function() {\n}\n", | 34 | + "controllerScript": "var requestTimeout = 500;\nvar commandStatusPollingInterval = 200;\n\nvar welcome = 'Welcome to ThingsBoard RPC remote shell.\\n';\n\nvar terminal, rpcEnabled, simulated, deviceName, cwd;\nvar commandExecuting = false;\n\nself.onInit = function() {\n var subscription = self.ctx.defaultSubscription;\n rpcEnabled = subscription.rpcEnabled;\n if (subscription.targetDeviceName && subscription.targetDeviceName.length) {\n deviceName = subscription.targetDeviceName;\n } else {\n deviceName = 'Simulated';\n simulated = true;\n }\n if (self.ctx.settings.requestTimeout) {\n requestTimeout = self.ctx.settings.requestTimeout;\n }\n \n terminal = $('#device-terminal', self.ctx.$container).terminal(\n function (command) {\n if (command && command.trim().length) {\n try {\n if (simulated) {\n this.echo(command);\n } else {\n sendCommand(this, command);\n }\n } catch(e) {\n this.error(e + '');\n }\n } else {\n this.echo('');\n }\n }, {\n greetings: false,\n enabled: rpcEnabled,\n prompt: rpcEnabled ? currentPrompt : '',\n name: 'shell',\n pauseEvents: false,\n keydown: function (e, term) {\n if ((e.which == 67 || e.which == 68) && e.ctrlKey) { // CTRL+C || CTRL+D\n if (commandExecuting) {\n terminateCommand(term);\n return false;\n }\n }\n },\n onInit: initTerm\n }\n );\n \n};\n\nfunction initTerm(terminal) {\n terminal.echo(welcome);\n if (!rpcEnabled) {\n terminal.error('Target device is not set!\\n');\n } else {\n terminal.echo('Current target device for RPC terminal: [[b;#fff;]' + deviceName + ']\\n');\n if (!simulated) {\n terminal.pause();\n getTermInfo(terminal,\n function (remoteTermInfo) {\n if (remoteTermInfo) {\n terminal.echo('Remote platform info:');\n terminal.echo('OS: [[b;#fff;]' + remoteTermInfo.platform + ']');\n if (remoteTermInfo.release) {\n terminal.echo('OS release: [[b;#fff;]' + remoteTermInfo.release + ']');\n }\n terminal.echo('\\r');\n } else {\n terminal.echo('[[;#f00;]Unable to get remote platform info.\\nDevice is not responding.]\\n');\n }\n terminal.resume();\n });\n }\n }\n}\n\nfunction currentPrompt(callback) {\n if (cwd) {\n callback('[[b;#2196f3;]' + deviceName +']: [[b;#8bc34a;]' + cwd +']> ');\n } else {\n callback('[[b;#8bc34a;]' + deviceName +']> ');\n }\n}\n\nfunction getTermInfo(terminal, callback) {\n self.ctx.controlApi.sendTwoWayCommand('getTermInfo', null, requestTimeout).subscribe(\n function (termInfo) {\n cwd = termInfo.cwd;\n if (callback) {\n callback(termInfo);\n } \n },\n function () {\n if (callback) {\n callback(null);\n }\n }\n );\n}\n\nfunction sendCommand(terminal, command) {\n terminal.pause();\n var sendCommandRequest = {\n command: command,\n cwd: cwd\n };\n self.ctx.controlApi.sendTwoWayCommand('sendCommand', sendCommandRequest, requestTimeout).subscribe(\n function (responseBody) {\n if (responseBody && responseBody.ok) {\n commandExecuting = true;\n setTimeout( pollCommandStatus.bind(null,terminal), commandStatusPollingInterval );\n } else {\n var error = responseBody ? responseBody.error : 'Unhandled error.';\n terminal.error(error);\n terminal.resume();\n }\n },\n function () {\n onRpcError(terminal);\n }\n );\n}\n\nfunction terminateCommand(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('terminateCommand', null, requestTimeout).subscribe(\n function (responseBody) {\n if (!responseBody.ok) {\n commandExecuting = false;\n terminal.error(responseBody.error);\n terminal.resume();\n } \n },\n function () {\n onRpcError(terminal);\n }\n ); \n}\n\nfunction onRpcError(terminal) {\n var errorText = self.ctx.defaultSubscription.rpcErrorText;\n terminal.error(errorText);\n terminal.resume();\n}\n\nfunction pollCommandStatus(terminal) {\n self.ctx.controlApi.sendTwoWayCommand('getCommandStatus', null, requestTimeout).subscribe(\n function (commandStatusResponse) {\n for (var i=0;i<commandStatusResponse.data.length;i++) {\n var dataElement = commandStatusResponse.data[i];\n if (dataElement.stdout) {\n terminal.echo(dataElement.stdout);\n }\n if (dataElement.stderr) {\n terminal.error(dataElement.stderr);\n }\n }\n if (commandStatusResponse.done) {\n commandExecuting = false;\n cwd = commandStatusResponse.cwd;\n terminal.resume();\n } else {\n var interval = commandStatusPollingInterval;\n if (!commandStatusResponse.data.length) {\n interval *=5;\n }\n setTimeout( pollCommandStatus.bind(null,terminal), interval );\n }\n },\n function () {\n commandExecuting = false;\n onRpcError(terminal);\n }\n );\n}\n\nself.onResize = function () {\n if (terminal) {\n terminal.resize(self.ctx.width, self.ctx.height);\n }\n};\n\nself.onDestroy = function() {\n};\n", |
35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}", | 35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"requestTimeout\"\n ]\n}", |
36 | "dataKeySettingsSchema": "{}\n", | 36 | "dataKeySettingsSchema": "{}\n", |
37 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC remote shell\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 37 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#010101\",\"color\":\"rgba(255, 254, 254, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"RPC remote shell\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -45,9 +45,9 @@ | @@ -45,9 +45,9 @@ | ||
45 | "sizeX": 5, | 45 | "sizeX": 5, |
46 | "sizeY": 4.5, | 46 | "sizeY": 4.5, |
47 | "resources": [], | 47 | "resources": [], |
48 | - "templateHtml": "<tb-knob ctx='ctx'></tb-knob>", | 48 | + "templateHtml": "<tb-knob [ctx]='ctx'></tb-knob>", |
49 | "templateCss": "", | 49 | "templateCss": "", |
50 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n", | 50 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"title\": {\n \"title\": \"Knob title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"Set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"minValue\", \"maxValue\", \"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n \"title\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\"\n ]\n}", | 51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\",\n \"default\": 0\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\",\n \"default\": 100\n },\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"number\",\n \"default\": 50\n },\n \"title\": {\n \"title\": \"Knob title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"getValueMethod\": {\n \"title\": \"Get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"Set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"minValue\", \"maxValue\", \"getValueMethod\", \"setValueMethod\", \"requestTimeout\"]\n },\n \"form\": [\n \"minValue\",\n \"maxValue\",\n \"initialValue\",\n \"title\",\n \"getValueMethod\",\n \"setValueMethod\",\n \"requestTimeout\"\n ]\n}", |
52 | "dataKeySettingsSchema": "{}\n", | 52 | "dataKeySettingsSchema": "{}\n", |
53 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"maxValue\":100,\"initialValue\":50,\"minValue\":0,\"title\":\"Knob control\",\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\"},\"title\":\"Knob Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | 53 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"maxValue\":100,\"initialValue\":50,\"minValue\":0,\"title\":\"Knob control\",\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\"},\"title\":\"Knob Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
@@ -61,9 +61,9 @@ | @@ -61,9 +61,9 @@ | ||
61 | "sizeX": 4, | 61 | "sizeX": 4, |
62 | "sizeY": 2.5, | 62 | "sizeY": 2.5, |
63 | "resources": [], | 63 | "resources": [], |
64 | - "templateHtml": "<tb-switch ctx='ctx'></tb-switch>", | 64 | + "templateHtml": "<tb-switch [ctx]='ctx'></tb-switch>", |
65 | "templateCss": "", | 65 | "templateCss": "", |
66 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n", | 66 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showOnOffLabels\": {\n \"title\": \"Show on/off labels\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n \"showOnOffLabels\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", | 67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showOnOffLabels\": {\n \"title\": \"Show on/off labels\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n \"showOnOffLabels\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", |
68 | "dataKeySettingsSchema": "{}\n", | 68 | "dataKeySettingsSchema": "{}\n", |
69 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"showOnOffLabels\":true,\"title\":\"Switch control\"},\"title\":\"Switch Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | 69 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"showOnOffLabels\":true,\"title\":\"Switch control\"},\"title\":\"Switch Control\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
@@ -77,9 +77,9 @@ | @@ -77,9 +77,9 @@ | ||
77 | "sizeX": 2.5, | 77 | "sizeX": 2.5, |
78 | "sizeY": 2, | 78 | "sizeY": 2, |
79 | "resources": [], | 79 | "resources": [], |
80 | - "templateHtml": "<tb-round-switch ctx='ctx'></tb-round-switch>", | 80 | + "templateHtml": "<tb-round-switch [ctx]='ctx'></tb-round-switch>", |
81 | "templateCss": "", | 81 | "templateCss": "", |
82 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n", | 82 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
83 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", | 83 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"Switch title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve on/off value using method\",\n \"type\": \"string\",\n \"default\": \"rpc\"\n },\n \"valueKey\": {\n \"title\": \"Attribute/Timeseries value key (only when subscribe for attribute/timeseries method)\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"getValueMethod\": {\n \"title\": \"RPC get value method\",\n \"type\": \"string\",\n \"default\": \"getValue\"\n },\n \"setValueMethod\": {\n \"title\": \"RPC set value method\",\n \"type\": \"string\",\n \"default\": \"setValue\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"convertValueFunction\": {\n \"title\": \"Convert value function, f(value), returns payload used by RPC set value method\",\n \"type\": \"string\",\n \"default\": \"return value;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"none\",\n \"label\": \"Don't retrieve\"\n },\n {\n \"value\": \"rpc\",\n \"label\": \"Call RPC get value method\"\n },\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueKey\",\n \"getValueMethod\",\n \"setValueMethod\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n {\n \"key\": \"convertValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", |
84 | "dataKeySettingsSchema": "{}\n", | 84 | "dataKeySettingsSchema": "{}\n", |
85 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"title\":\"Round switch\",\"retrieveValueMethod\":\"rpc\",\"valueKey\":\"value\",\"parseValueFunction\":\"return data ? true : false;\",\"convertValueFunction\":\"return value;\"},\"title\":\"Round switch\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | 85 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":false,\"getValueMethod\":\"getValue\",\"setValueMethod\":\"setValue\",\"title\":\"Round switch\",\"retrieveValueMethod\":\"rpc\",\"valueKey\":\"value\",\"parseValueFunction\":\"return data ? true : false;\",\"convertValueFunction\":\"return value;\"},\"title\":\"Round switch\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
@@ -93,9 +93,9 @@ | @@ -93,9 +93,9 @@ | ||
93 | "sizeX": 2.5, | 93 | "sizeX": 2.5, |
94 | "sizeY": 2.5, | 94 | "sizeY": 2.5, |
95 | "resources": [], | 95 | "resources": [], |
96 | - "templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>", | 96 | + "templateHtml": "<tb-led-indicator [ctx]='ctx'></tb-led-indicator>", |
97 | "templateCss": "", | 97 | "templateCss": "", |
98 | - "controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n", | 98 | + "controllerScript": "self.onInit = function() {\n}\n\nself.onResize = function() {\n}\n\nself.onDestroy = function() {\n}\n", |
99 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"performCheckStatus\": {\n \"title\": \"Perform RPC device status check\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"checkStatusMethod\": {\n \"title\": \"RPC check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve led status value using method\",\n \"type\": \"string\",\n \"default\": \"attribute\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute/timeseries containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse led status value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"performCheckStatus\",\n \"checkStatusMethod\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueAttribute\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", | 99 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"performCheckStatus\": {\n \"title\": \"Perform RPC device status check\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"checkStatusMethod\": {\n \"title\": \"RPC check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve led status value using method\",\n \"type\": \"string\",\n \"default\": \"attribute\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute/timeseries containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse led status value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"performCheckStatus\",\n \"checkStatusMethod\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueAttribute\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}", |
100 | "dataKeySettingsSchema": "{}\n", | 100 | "dataKeySettingsSchema": "{}\n", |
101 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"valueAttribute\":\"value\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\",\"performCheckStatus\":true,\"checkStatusMethod\":\"checkStatus\"},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" | 101 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"valueAttribute\":\"value\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\",\"performCheckStatus\":true,\"checkStatusMethod\":\"checkStatus\"},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}" |
@@ -109,9 +109,9 @@ | @@ -109,9 +109,9 @@ | ||
109 | "sizeX": 4, | 109 | "sizeX": 4, |
110 | "sizeY": 2, | 110 | "sizeY": 2, |
111 | "resources": [], | 111 | "resources": [], |
112 | - "templateHtml": "<div class=\"tb-rpc-button\" layout=\"column\">\n <div flex=\"20\" class=\"title-container\" layout=\"row\"\n layout-align=\"center center\" ng-show=\"showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div flex=\"{{showTitle ? 80 : 100}}\" ng-style=\"{paddingTop: showTitle ? '5px': '10px'}\"\n class=\"button-container\" layout=\"column\" layout-align=\"center center\">\n <div>\n <md-button ng-click=\"sendCommand()\" ng-class=\"{'md-raised': styleButton.isRaised, 'md-primary': styleButton.isPrimary}\" ng-style=\"customStyle\">\n {{buttonLabel}}\n </md-button>\n </div>\n </div>\n <div class=\"error-container\" ng-style=\"{'background': vm.error.length ? 'rgba(255,255,255,0.25)' : 'none'}\"\n layout=\"row\" layout-align=\"center center\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>", | ||
113 | - "templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .md-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}", | ||
114 | - "controllerScript": "self.onInit = function() {\n let rpcEnabled = self.ctx.defaultSubscription.rpcEnabled;\n\n self.ctx.$scope.buttonLabel = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton.bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n if (!rpcEnabled) {\n self.ctx.$scope.error =\n 'Target device is not set!';\n }\n\n self.ctx.$scope.sendCommand = function() {\n var rpcMethod = self.ctx.settings.methodName;\n var rpcParams = self.ctx.settings.methodParams;\n var timeout = self.ctx.settings.requestTimeout;\n var oneWayElseTwoWay = self.ctx.settings.oneWayElseTwoWay ?\n true : false;\n\n var commandPromise;\n if (oneWayElseTwoWay) {\n commandPromise = self.ctx.controlApi.sendOneWayCommand(\n rpcMethod, rpcParams, timeout);\n } else {\n commandPromise = self.ctx.controlApi.sendTwoWayCommand(\n rpcMethod, rpcParams, timeout);\n }\n commandPromise.then(\n function success() {\n self.ctx.$scope.error = \"\";\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n }\n }\n );\n };\n\n};", | 112 | + "templateHtml": "<div class=\"tb-rpc-button\" fxLayout=\"column\">\n <div fxFlex=\"20\" class=\"title-container\" fxLayout=\"row\"\n fxLayoutAlign=\"center center\" [fxShow]=\"showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div fxFlex=\"{{showTitle ? 80 : 100}}\" [ngStyle]=\"{paddingTop: showTitle ? '5px': '10px'}\"\n class=\"button-container\" fxLayout=\"column\" fxLayoutAlign=\"center center\">\n <div>\n <button mat-button (click)=\"sendCommand()\"\n [class.mat-raised-button]=\"styleButton?.isRaised\"\n [color]=\"styleButton?.isPrimary ? 'primary' : ''\"\n [ngStyle]=\"customStyle\">\n {{buttonLable}}\n </button>\n </div>\n </div>\n <div class=\"error-container\" [ngStyle]=\"{'background': error?.length ? 'rgba(255,255,255,0.25)' : 'none'}\"\n fxLayout=\"row\" fxLayoutAlign=\"center center\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>", |
113 | + "templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .mat-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}", | ||
114 | + "controllerScript": "self.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges();\n });\n};\n\nfunction init() {\n let rpcEnabled = self.ctx.defaultSubscription.rpcEnabled;\n\n self.ctx.$scope.buttonLable = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton.bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n if (!rpcEnabled) {\n self.ctx.$scope.error =\n 'Target device is not set!';\n }\n\n self.ctx.$scope.sendCommand = function() {\n var rpcMethod = self.ctx.settings.methodName;\n var rpcParams = self.ctx.settings.methodParams;\n var timeout = self.ctx.settings.requestTimeout;\n var oneWayElseTwoWay = self.ctx.settings.oneWayElseTwoWay ?\n true : false;\n\n var commandPromise;\n if (oneWayElseTwoWay) {\n commandPromise = self.ctx.controlApi.sendOneWayCommand(\n rpcMethod, rpcParams, timeout);\n } else {\n commandPromise = self.ctx.controlApi.sendTwoWayCommand(\n rpcMethod, rpcParams, timeout);\n }\n commandPromise.subscribe(\n function success() {\n self.ctx.$scope.error = \"\";\n self.ctx.detectChanges();\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n self.ctx.detectChanges();\n }\n }\n );\n };\n}\n", | ||
115 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Send RPC\"\n },\n \"oneWayElseTwoWay\": {\n \"title\": \"Is One Way Command\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showError\": {\n \"title\": \"Show RPC command execution error\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"methodName\": {\n \"title\": \"RPC method\",\n \"type\": \"string\",\n \"default\": \"rpcCommand\"\n },\n \"methodParams\": {\n \"title\": \"RPC method params\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 5000\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n \"oneWayElseTwoWay\",\n \"showError\",\n \"methodName\",\n {\n \"key\": \"methodParams\",\n \"type\": \"json\"\n },\n \"requestTimeout\",\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", | 115 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Send RPC\"\n },\n \"oneWayElseTwoWay\": {\n \"title\": \"Is One Way Command\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"showError\": {\n \"title\": \"Show RPC command execution error\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"methodName\": {\n \"title\": \"RPC method\",\n \"type\": \"string\",\n \"default\": \"rpcCommand\"\n },\n \"methodParams\": {\n \"title\": \"RPC method params\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 5000\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n \"oneWayElseTwoWay\",\n \"showError\",\n \"methodName\",\n {\n \"key\": \"methodParams\",\n \"type\": \"json\"\n },\n \"requestTimeout\",\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", |
116 | "dataKeySettingsSchema": "{}\n", | 116 | "dataKeySettingsSchema": "{}\n", |
117 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":5000,\"oneWayElseTwoWay\":true,\"buttonText\":\"Send RPC\",\"styleButton\":{\"isRaised\":true,\"isPrimary\":false},\"methodName\":\"rpcCommand\",\"methodParams\":\"{}\"},\"title\":\"RPC Button\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 117 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":5000,\"oneWayElseTwoWay\":true,\"buttonText\":\"Send RPC\",\"styleButton\":{\"isRaised\":true,\"isPrimary\":false},\"methodName\":\"rpcCommand\",\"methodParams\":\"{}\"},\"title\":\"RPC Button\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -125,13 +125,13 @@ | @@ -125,13 +125,13 @@ | ||
125 | "sizeX": 4, | 125 | "sizeX": 4, |
126 | "sizeY": 2, | 126 | "sizeY": 2, |
127 | "resources": [], | 127 | "resources": [], |
128 | - "templateHtml": "<div class=\"tb-rpc-button\" layout=\"column\">\n <div flex=\"20\" class=\"title-container\" layout=\"row\"\n layout-align=\"center center\" ng-show=\"showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div flex=\"{{showTitle ? 80 : 100}}\" ng-style=\"{paddingTop: showTitle ? '5px': '10px'}\"\n class=\"button-container\" layout=\"column\" layout-align=\"center center\">\n <div>\n <md-button ng-click=\"sendUpdate()\" ng-class=\"{'md-raised': styleButton.isRaised, 'md-primary': styleButton.isPrimary}\" ng-style=\"customStyle\">\n {{buttonLabel}}\n </md-button>\n </div>\n </div>\n <div class=\"error-container\" ng-style=\"{'background': vm.error.length ? 'rgba(255,255,255,0.25)' : 'none'}\"\n layout=\"row\" layout-align=\"center center\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>", | ||
129 | - "templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .md-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}", | ||
130 | - "controllerScript": "self.onInit = function() {\n self.ctx.$scope.buttonLabel = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n let entityAttributeType = self.ctx.settings.entityAttributeType;\n let entityParameters = JSON.parse(self.ctx.settings.entityParameters);\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton\n .bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n console.log(self.ctx);\n\n let attributeService = self.ctx.$scope.$injector.get('attributeService');\n\n self.ctx.$scope.sendUpdate = function() {\n let attributes = [];\n for (let key in entityParameters) {\n attributes.push({\n \"key\": key,\n \"value\": entityParameters[key]\n });\n }\n \n \n attributeService.saveEntityAttributes(\"DEVICE\", self.ctx.defaultSubscription.targetDeviceId,\n entityAttributeType, attributes).then(\n function success() {\n self.ctx.$scope.error = \"\";\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n }\n console.log(rejection);\n }\n\n );\n };\n\n};", | 128 | + "templateHtml": "<div class=\"tb-rpc-button\" fxLayout=\"column\">\n <div fxFlex=\"20\" class=\"title-container\" fxLayout=\"row\"\n fxLayoutAlign=\"center center\" [fxShow]=\"showTitle\">\n <span class=\"button-title\">{{title}}</span>\n </div>\n <div fxFlex=\"{{showTitle ? 80 : 100}}\" [ngStyle]=\"{paddingTop: showTitle ? '5px': '10px'}\"\n class=\"button-container\" fxLayout=\"column\" fxLayoutAlign=\"center center\">\n <div>\n <button mat-button (click)=\"sendUpdate()\"\n [class.mat-raised-button]=\"styleButton?.isRaised\"\n [color]=\"styleButton?.isPrimary ? 'primary' : ''\"\n [ngStyle]=\"customStyle\">\n {{buttonLable}}\n </button>\n </div>\n </div>\n <div class=\"error-container\" [ngStyle]=\"{'background': error?.length ? 'rgba(255,255,255,0.25)' : 'none'}\"\n fxLayout=\"row\" fxLayoutAlign=\"center center\">\n <span class=\"button-error\">{{ error }}</span>\n </div>\n</div>", |
129 | + "templateCss": ".tb-rpc-button {\n width: 100%;\n height: 100%;\n}\n\n.tb-rpc-button .title-container {\n font-weight: 500;\n white-space: nowrap;\n margin: 10px 0;\n}\n\n.tb-rpc-button .button-container div{\n min-width: 80%\n}\n\n.tb-rpc-button .button-container .mat-button{\n width: 100%;\n margin: 0;\n}\n\n.tb-rpc-button .error-container {\n position: absolute;\n top: 2%;\n right: 0;\n left: 0;\n z-index: 4;\n height: 14px;\n}\n\n.tb-rpc-button .error-container .button-error {\n color: #ff3315;\n white-space: nowrap;\n}", | ||
130 | + "controllerScript": "self.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges();\n });\n};\n\nfunction init() {\n self.ctx.$scope.buttonLable = self.ctx.settings.buttonText;\n self.ctx.$scope.showTitle = self.ctx.settings.title &&\n self.ctx.settings.title.length ? true : false;\n self.ctx.$scope.title = self.ctx.settings.title;\n self.ctx.$scope.styleButton = self.ctx.settings.styleButton;\n let entityAttributeType = self.ctx.settings.entityAttributeType;\n let entityParameters = JSON.parse(self.ctx.settings.entityParameters);\n\n if (self.ctx.settings.styleButton.isPrimary ===\n false) {\n self.ctx.$scope.customStyle = {\n 'background-color': self.ctx.$scope.styleButton\n .bgColor,\n 'color': self.ctx.$scope.styleButton.textColor\n };\n }\n\n let attributeService = self.ctx.$scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n\n self.ctx.$scope.sendUpdate = function() {\n let attributes = [];\n for (let key in entityParameters) {\n attributes.push({\n \"key\": key,\n \"value\": entityParameters[key]\n });\n }\n \n let entityId = {\n entityType: \"DEVICE\",\n id: self.ctx.defaultSubscription.targetDeviceId\n };\n attributeService.saveEntityAttributes(entityId,\n entityAttributeType, attributes).subscribe(\n function success() {\n self.ctx.$scope.error = \"\";\n self.ctx.detectChanges();\n },\n function fail(rejection) {\n if (self.ctx.settings.showError) {\n self.ctx.$scope.error =\n rejection.status + \": \" +\n rejection.statusText;\n self.ctx.detectChanges();\n }\n }\n\n );\n };\n}\n", | ||
131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Update device attribute\"\n },\n \"entityAttributeType\": {\n \"title\": \"Device attribute scope\",\n \"type\": \"string\",\n \"default\": \"SERVER_SCOPE\"\n },\n \"entityParameters\": {\n \"title\": \"Device attribute parameters\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n {\n \"key\": \"entityAttributeType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [{\n \"value\": \"SERVER_SCOPE\",\n \"label\": \"Server attribute\"\n }, {\n \"value\": \"SHARED_SCOPE\",\n \"label\": \"Shared attribute\"\n }]\n }, {\n \"key\": \"entityParameters\",\n \"type\": \"json\"\n },\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", | 131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"title\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"buttonText\": {\n \"title\": \"Button label\",\n \"type\": \"string\",\n \"default\": \"Update device attribute\"\n },\n \"entityAttributeType\": {\n \"title\": \"Device attribute scope\",\n \"type\": \"string\",\n \"default\": \"SERVER_SCOPE\"\n },\n \"entityParameters\": {\n \"title\": \"Device attribute parameters\",\n \"type\": \"string\",\n \"default\": \"{}\"\n },\n \"styleButton\": {\n \"type\": \"object\",\n \"title\": \"Button Style\",\n \"properties\": {\n \"isRaised\": {\n \"type\": \"boolean\",\n \"title\": \"Raised\",\n \"default\": true\n },\n \"isPrimary\": {\n \"type\": \"boolean\",\n \"title\": \"Primary color\",\n \"default\": false\n },\n \"bgColor\": {\n \"type\": \"string\",\n \"title\": \"Button background color\",\n \"default\": null\n },\n \"textColor\": {\n \"type\": \"string\",\n \"title\": \"Button text color\",\n \"default\": null\n }\n }\n },\n \"required\": []\n }\n },\n \"form\": [\n \"title\",\n \"buttonText\",\n {\n \"key\": \"entityAttributeType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [{\n \"value\": \"SERVER_SCOPE\",\n \"label\": \"Server attribute\"\n }, {\n \"value\": \"SHARED_SCOPE\",\n \"label\": \"Shared attribute\"\n }]\n }, {\n \"key\": \"entityParameters\",\n \"type\": \"json\"\n },\n {\n \"key\": \"styleButton\",\n \"items\": [\n \"styleButton.isRaised\",\n \"styleButton.isPrimary\",\n {\n \"key\": \"styleButton.bgColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"styleButton.textColor\",\n \"type\": \"color\"\n }\n ]\n }\n ]\n\n}", |
132 | "dataKeySettingsSchema": "{}\n", | 132 | "dataKeySettingsSchema": "{}\n", |
133 | "defaultConfig": "{\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"styleButton\":{\"isRaised\":true,\"isPrimary\":false},\"entityParameters\":\"{}\",\"entityAttributeType\":\"SERVER_SCOPE\",\"buttonText\":\"Update device attribute\"},\"title\":\"Update device attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"targetDeviceAliases\":[]}" | 133 | "defaultConfig": "{\"showTitle\":false,\"backgroundColor\":\"#e6e7e8\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"styleButton\":{\"isRaised\":true,\"isPrimary\":false},\"entityParameters\":\"{}\",\"entityAttributeType\":\"SERVER_SCOPE\",\"buttonText\":\"Update device attribute\"},\"title\":\"Update device attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"targetDeviceAliases\":[]}" |
134 | } | 134 | } |
135 | } | 135 | } |
136 | ] | 136 | ] |
137 | -} | ||
137 | +} |
@@ -13,9 +13,9 @@ | @@ -13,9 +13,9 @@ | ||
13 | "sizeX": 5, | 13 | "sizeX": 5, |
14 | "sizeY": 5.5, | 14 | "sizeY": 5.5, |
15 | "resources": [], | 15 | "resources": [], |
16 | - "templateHtml": "<date-range-navigator-widget class=\"date-range-navigator-widget\" ctx=\"ctx\"></date-range-navigator-widget>", | 16 | + "templateHtml": "<tb-date-range-navigator-widget [ctx]=\"ctx\"></tb-date-range-navigator-widget>", |
17 | "templateCss": "", | 17 | "templateCss": "", |
18 | - "controllerScript": "self.onInit = function() {\n scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}", | 18 | + "controllerScript": "self.onInit = function() {\n}\n", |
19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"hidePicker\": {\n \"title\": \"Hide date range picker\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"onePanel\": {\n \"title\": \"Date range picker one panel\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"autoConfirm\": {\n \"title\": \"Date range picker auto confirm\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"showTemplate\": {\n \"title\": \"Date range picker show template\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"firstDayOfWeek\": {\n \"title\": \"First day of the week\",\n \"type\": \"number\",\n \"default\": 1\n },\n \"hideInterval\": {\n \"title\": \"Hide interval\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"initialInterval\": {\n\t\t\t\t\"title\": \"Initial interval\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"week\"\n\t\t\t},\n \"hideStepSize\": {\n \"title\": \"Hide step size\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"stepSize\": {\n\t\t\t\t\"title\": \"Initial step size\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"day\"\n\t\t\t},\n \"hideLabels\": {\n \"title\": \"Hide labels\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"useSessionStorage\": {\n \"title\": \"Use session storage\",\n \"type\": \"boolean\",\n \"default\": true\n }\n }\n },\n \"form\": [\n \"hidePicker\",\n\t\t\"onePanel\",\n\t\t\"autoConfirm\",\n\t\t\"showTemplate\",\n\t\t\"firstDayOfWeek\",\n \"hideInterval\",\n {\n\t\t\t\"key\": \"initialInterval\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n \"hideStepSize\",\n {\n\t\t\t\"key\": \"stepSize\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t\"hideLabels\",\n\t\t\"useSessionStorage\"\n ]\n}", | 19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"hidePicker\": {\n \"title\": \"Hide date range picker\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"onePanel\": {\n \"title\": \"Date range picker one panel\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"autoConfirm\": {\n \"title\": \"Date range picker auto confirm\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"showTemplate\": {\n \"title\": \"Date range picker show template\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"firstDayOfWeek\": {\n \"title\": \"First day of the week\",\n \"type\": \"number\",\n \"default\": 1\n },\n \"hideInterval\": {\n \"title\": \"Hide interval\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"initialInterval\": {\n\t\t\t\t\"title\": \"Initial interval\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"week\"\n\t\t\t},\n \"hideStepSize\": {\n \"title\": \"Hide step size\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"stepSize\": {\n\t\t\t\t\"title\": \"Initial step size\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"day\"\n\t\t\t},\n \"hideLabels\": {\n \"title\": \"Hide labels\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"useSessionStorage\": {\n \"title\": \"Use session storage\",\n \"type\": \"boolean\",\n \"default\": true\n }\n }\n },\n \"form\": [\n \"hidePicker\",\n\t\t\"onePanel\",\n\t\t\"autoConfirm\",\n\t\t\"showTemplate\",\n\t\t\"firstDayOfWeek\",\n \"hideInterval\",\n {\n\t\t\t\"key\": \"initialInterval\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n \"hideStepSize\",\n {\n\t\t\t\"key\": \"stepSize\",\n\t\t\t\"type\": \"rc-select\",\n\t\t\t\"multiple\": false,\n\t\t\t\"items\": [\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"hour\",\n\t\t\t\t\t\"label\": \"Hour\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"day\",\n\t\t\t\t\t\"label\": \"Day\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"week\",\n\t\t\t\t\t\"label\": \"Week\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"twoWeeks\",\n\t\t\t\t\t\"label\": \"2 weeks\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"month\",\n\t\t\t\t\t\"label\": \"Month\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"threeMonths\",\n\t\t\t\t\t\"label\": \"3 months\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"value\": \"sixMonths\",\n\t\t\t\t\t\"label\": \"6 months\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t\"hideLabels\",\n\t\t\"useSessionStorage\"\n ]\n}", |
20 | "dataKeySettingsSchema": "{}\n", | 20 | "dataKeySettingsSchema": "{}\n", |
21 | "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"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\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"defaultInterval\":\"week\",\"stepSize\":\"day\"},\"title\":\"Date-range-navigator\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 21 | "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"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\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"defaultInterval\":\"week\",\"stepSize\":\"day\"},\"title\":\"Date-range-navigator\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -13,9 +13,9 @@ | @@ -13,9 +13,9 @@ | ||
13 | "sizeX": 4, | 13 | "sizeX": 4, |
14 | "sizeY": 2, | 14 | "sizeY": 2, |
15 | "resources": [], | 15 | "resources": [], |
16 | - "templateHtml": "<fieldset class=\"gpio-panel\" ng-disabled=\"!rpcEnabled || executingRpcRequest\" style=\"height: 100%;\">\n <section class=\"gpio-row\" layout=\"row\" ng-repeat=\"row in rows track by $index\" \n ng-style=\"{'height': prefferedRowHeight+'px'}\">\n <section flex layout=\"row\" ng-repeat=\"cell in row track by $index\">\n <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n <section layout=\"row\" class=\"switch-panel\" layout-align=\"start center\" ng-class=\"$index===0 ? 'col-0' : 'col-1'\"\n ng-style=\"{'height': prefferedRowHeight+'px', 'backgroundColor': '{{ switchPanelBackgroundColor }}'}\">\n <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n <span flex ng-show=\"$index===1\"></span>\n <md-switch\n aria-label=\"{{ cell.label }}\"\n ng-disabled=\"!rpcEnabled || executingRpcRequest\"\n ng-model=\"cell.enabled\" \n ng-change=\"cell.enabled = !cell.enabled\" \n ng-click=\"gpioClick($event, cell)\">\n </md-switch>\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section layout=\"row\" flex ng-if=\"!cell\">\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"switch-panel\"\n ng-style=\"{'height': prefferedRowHeight+'px', 'backgroundColor': '{{ switchPanelBackgroundColor }}'}\"></span>\n <span flex ng-show=\"$index===1\"></span>\n </section>\n </section>\n </section> \n <span class=\"error\" style=\"position: absolute; bottom: 5px;\" ng-show=\"rpcErrorText\">{{rpcErrorText}}</span>\n <md-progress-linear ng-show=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" md-mode=\"indeterminate\"></md-progress-linear> \n</fieldset>", | ||
17 | - "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.switch-panel {\n margin: 0;\n height: 32px;\n width: 66px;\n min-width: 66px;\n}\n\n.switch-panel md-switch {\n margin: 0;\n width: 36px;\n min-width: 36px;\n}\n\n.switch-panel md-switch > div.md-container {\n margin: 0;\n}\n\n.switch-panel.col-0 md-switch {\n padding-left: 8px;\n padding-right: 4px;\n}\n\n.switch-panel.col-1 md-switch {\n padding-left: 4px;\n padding-right: 8px;\n}\n\n.gpio-row {\n height: 32px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | ||
18 | - "controllerScript": "self.onInit = function() {\n \n var i, gpio;\n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n scope.gpioList = [];\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false\n }\n );\n }\n\n scope.requestTimeout = settings.requestTimeout || 1000;\n\n scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioStatusRequest = {\n method: \"getGpioStatus\",\n paramsBody: \"{}\"\n };\n \n if (settings.gpioStatusRequest) {\n scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n }\n \n scope.gpioStatusChangeRequest = {\n method: \"setGpioStatus\",\n paramsBody: \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n };\n \n if (settings.gpioStatusChangeRequest) {\n scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n }\n \n scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n \n if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n }\n \n scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n \n function requestGpioStatus() {\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n scope.gpioStatusRequest.paramsBody, \n scope.requestTimeout)\n .then(\n function success(responseBody) {\n for (var g = 0; g < scope.gpioList.length; g++) {\n var gpio = scope.gpioList[g];\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled; \n }\n }\n );\n }\n \n function changeGpioStatus(gpio) {\n var pin = gpio.pin + '';\n var enabled = !gpio.enabled;\n enabled = enabled === true ? 'true' : 'false';\n var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n requestBody, scope.requestTimeout)\n .then(\n function success(responseBody) {\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled;\n }\n );\n }\n \n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n }\n\n scope.gpioClick = function($event, gpio) {\n changeGpioStatus(gpio);\n };\n\n requestGpioStatus(); \n \n self.onResize();\n}\n\nself.onResize = function() {\n var scope = self.ctx.$scope;\n var rowCount = scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n scope.prefferedRowHeight = prefferedRowHeight;\n var ratio = prefferedRowHeight/32;\n var switches = $('md-switch', self.ctx.$container);\n switches.css('height', 30*ratio+'px');\n switches.css('width', 36*ratio+'px');\n switches.css('min-width', 36*ratio+'px');\n $('.md-container', switches).css('height', 24*ratio+'px');\n $('.md-container', switches).css('width', 36*ratio+'px');\n var bars = $('.md-bar', self.ctx.$container);\n bars.css('height', 14*ratio+'px');\n bars.css('width', 34*ratio+'px');\n var thumbs = $('.md-thumb', self.ctx.$container);\n thumbs.css('height', 20*ratio+'px');\n thumbs.css('width', 20*ratio+'px');\n \n var leftLabels = $('.gpio-left-label', self.ctx.$container);\n leftLabels.css('font-size', 16*ratio+'px');\n var rightLabels = $('.gpio-right-label', self.ctx.$container);\n rightLabels.css('font-size', 16*ratio+'px');\n var pins = $('.pin', self.ctx.$container);\n var pinsFontSize = Math.max(9, 12*ratio);\n pins.css('font-size', pinsFontSize+'px'); \n}\n\nself.onDestroy = function() {\n}\n", | 16 | + "templateHtml": "<fieldset class=\"gpio-panel\" style=\"height: 100%;\">\n <section class=\"gpio-row\" fxLayout=\"row\" *ngFor=\"let row of rows\" \n [ngStyle]=\"{'height': prefferedRowHeight+'px'}\">\n <section fxFlex fxLayout=\"row\" *ngFor=\"let cell of row; let $index = index\">\n <section fxLayout=\"row\" fxFlex *ngIf=\"cell\" fxLayoutAlign=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" [fxShow]=\"$index===0\">{{ cell.label }}</span>\n <section fxLayout=\"row\" class=\"switch-panel\" fxLayoutAlign=\"start center\" [ngClass]=\"$index===0 ? 'col-0' : 'col-1'\"\n [ngStyle]=\"{'height': prefferedRowHeight+'px', 'backgroundColor': switchPanelBackgroundColor }\">\n <span class=\"pin\" [fxShow]=\"$index===0\">{{cell.pin}}</span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n <mat-slide-toggle\n [disabled]=\"!rpcEnabled || executingRpcRequest\"\n [checked]=\"cell.enabled\" \n (change)=\"gpioToggleChange($event, cell)\" \n (click)=\"gpioClick($event, cell)\">\n </mat-slide-toggle>\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"pin\" [fxShow]=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" [fxShow]=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section fxLayout=\"row\" fxFlex *ngIf=\"!cell\">\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"switch-panel\"\n [ngStyle]=\"{'height': prefferedRowHeight+'px', 'backgroundColor': switchPanelBackgroundColor }\"></span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n </section>\n </section>\n </section> \n <span class=\"error\" style=\"position: absolute; bottom: 5px;\" [fxShow]=\"rpcErrorText\">{{rpcErrorText}}</span>\n <mat-progress-bar [fxShow]=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" mode=\"indeterminate\"></mat-progress-bar>\n</fieldset>", |
17 | + "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.switch-panel {\n margin: 0;\n height: 32px;\n width: 66px;\n min-width: 66px;\n}\n\n.switch-panel mat-slide-toggle {\n margin: 0;\n width: 36px;\n min-width: 36px;\n}\n\n.switch-panel.col-0 mat-slide-toggle {\n margin-left: 8px;\n margin-right: 4px;\n}\n\n.switch-panel.col-1 mat-slide-toggle {\n margin-left: 4px;\n margin-right: 8px;\n}\n\n.gpio-row {\n height: 32px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | ||
18 | + "controllerScript": "var namespace;\nvar cssParser = new cssjs();\n\nself.onInit = function() {\n var utils = self.ctx.$injector.get(self.ctx.servicesMap.get('utils'));\n namespace = 'gpio-control-' + utils.guid();\n cssParser.testMode = false;\n cssParser.cssPreviewNamespace = namespace;\n self.ctx.$container.addClass(namespace);\n self.ctx.ngZone.run(function() {\n init(); \n });\n}\n\nfunction init() {\n \n var i, gpio;\n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n scope.gpioList = [];\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false\n }\n );\n }\n\n scope.requestTimeout = settings.requestTimeout || 1000;\n\n scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioStatusRequest = {\n method: \"getGpioStatus\",\n paramsBody: \"{}\"\n };\n \n if (settings.gpioStatusRequest) {\n scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n }\n \n scope.gpioStatusChangeRequest = {\n method: \"setGpioStatus\",\n paramsBody: \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n };\n \n if (settings.gpioStatusChangeRequest) {\n scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n }\n \n scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n \n if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n }\n \n scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n \n function requestGpioStatus() {\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n scope.gpioStatusRequest.paramsBody, \n scope.requestTimeout)\n .subscribe(\n function success(responseBody) {\n for (var g = 0; g < scope.gpioList.length; g++) {\n var gpio = scope.gpioList[g];\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled; \n self.ctx.detectChanges();\n }\n }\n );\n }\n \n function changeGpioStatus(gpio) {\n var pin = gpio.pin + '';\n var enabled = !gpio.enabled;\n enabled = enabled === true ? 'true' : 'false';\n var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n requestBody, scope.requestTimeout)\n .subscribe(\n function success(responseBody) {\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled;\n self.ctx.detectChanges();\n }\n );\n }\n \n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n }\n\n scope.gpioClick = function($event, gpio) {\n if (scope.rpcEnabled && !scope.executingRpcRequest) {\n changeGpioStatus(gpio);\n }\n };\n \n scope.gpioToggleChange = function($event, gpio) {\n gpio.enabled = !$event.checked;\n $event.source.toggle();\n self.ctx.detectChanges();\n }\n \n if (scope.rpcEnabled) {\n requestGpioStatus(); \n }\n \n self.onResize();\n}\n\nself.onResize = function() {\n var scope = self.ctx.$scope;\n var rowCount = scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n scope.prefferedRowHeight = prefferedRowHeight;\n var ratio = prefferedRowHeight/32;\n \n var css = '.mat-slide-toggle .mat-slide-toggle-bar {\\n' +\n ' height: ' + 14*ratio+'px;\\n'+\n ' width: ' + 36*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-thumb-container {\\n' +\n ' height: ' + 20*ratio+'px;\\n'+\n ' width: ' + 20*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-thumb {\\n' +\n ' height: ' + 20*ratio+'px;\\n'+\n ' width: ' + 20*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-ripple {\\n' +\n ' height: ' + 40*ratio+'px;\\n'+\n ' width: ' + 40*ratio+'px;\\n'+\n ' top: calc(50% - '+20*ratio+'px);\\n'+\n ' left: calc(50% - '+20*ratio+'px);\\n'+\n '}\\n';\n css += '.gpio-left-label, .gpio-right-label {\\n' +\n ' font-size: ' + 16*ratio+'px;\\n'+\n '}\\n';\n var pinsFontSize = Math.max(9, 12*ratio);\n css += '.pin {\\n' +\n ' font-size: ' + pinsFontSize+'px;\\n'+\n '}\\n';\n\n cssParser.createStyleElement(namespace, css);\n \n self.ctx.detectChanges();\n}\n\nself.onDestroy = function() {\n}\n", | ||
19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio switches\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio switch\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n }\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"switchPanelBackgroundColor\": {\n \"title\": \"Switches panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n },\n \"gpioStatusRequest\": {\n \"title\": \"GPIO status request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"getGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"gpioStatusChangeRequest\": {\n \"title\": \"GPIO status change request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"setGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"parseGpioStatusFunction\": {\n \"title\": \"Parse gpio status function\",\n \"type\": \"string\",\n \"default\": \"return body[pin] === true;\"\n } \n },\n \"required\": [\"gpioList\", \n \"requestTimeout\",\n \"switchPanelBackgroundColor\",\n \"gpioStatusRequest\",\n \"gpioStatusChangeRequest\",\n \"parseGpioStatusFunction\"]\n },\n \"form\": [\n \"gpioList\",\n \"requestTimeout\",\n {\n \"key\": \"switchPanelBackgroundColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"gpioStatusRequest\",\n \"items\": [\n \"gpioStatusRequest.method\",\n {\n \"key\": \"gpioStatusRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"gpioStatusChangeRequest\",\n \"items\": [\n \"gpioStatusChangeRequest.method\",\n {\n \"key\": \"gpioStatusChangeRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"parseGpioStatusFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | 19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio switches\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio switch\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n }\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"switchPanelBackgroundColor\": {\n \"title\": \"Switches panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n },\n \"gpioStatusRequest\": {\n \"title\": \"GPIO status request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"getGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"gpioStatusChangeRequest\": {\n \"title\": \"GPIO status change request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"setGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"parseGpioStatusFunction\": {\n \"title\": \"Parse gpio status function\",\n \"type\": \"string\",\n \"default\": \"return body[pin] === true;\"\n } \n },\n \"required\": [\"gpioList\", \n \"requestTimeout\",\n \"switchPanelBackgroundColor\",\n \"gpioStatusRequest\",\n \"gpioStatusChangeRequest\",\n \"parseGpioStatusFunction\"]\n },\n \"form\": [\n \"gpioList\",\n \"requestTimeout\",\n {\n \"key\": \"switchPanelBackgroundColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"gpioStatusRequest\",\n \"items\": [\n \"gpioStatusRequest.method\",\n {\n \"key\": \"gpioStatusRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"gpioStatusChangeRequest\",\n \"items\": [\n \"gpioStatusChangeRequest.method\",\n {\n \"key\": \"gpioStatusChangeRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"parseGpioStatusFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
20 | "dataKeySettingsSchema": "{}\n", | 20 | "dataKeySettingsSchema": "{}\n", |
21 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"Basic GPIO Control\"}" | 21 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"Basic GPIO Control\"}" |
@@ -29,9 +29,9 @@ | @@ -29,9 +29,9 @@ | ||
29 | "sizeX": 5, | 29 | "sizeX": 5, |
30 | "sizeY": 2, | 30 | "sizeY": 2, |
31 | "resources": [], | 31 | "resources": [], |
32 | - "templateHtml": "<div class=\"gpio-panel\" style=\"height: 100%;\">\n <section layout=\"row\" ng-repeat=\"row in rows\">\n <section flex layout=\"row\" ng-repeat=\"cell in row\">\n <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n <section layout=\"row\" class=\"led-panel\" ng-class=\"$index===0 ? 'col-0' : 'col-1'\"\n ng-style=\"{backgroundColor: ledPanelBackgroundColor }\">\n <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n <span class=\"led-container\">\n <tb-led-light size=\"prefferedRowHeight\"\n color-on=\"cell.colorOn\"\n color-off=\"cell.colorOff\"\n off-opacity=\"'0.9'\"\n tb-enabled=\"cell.enabled\">\n </tb-led-light>\n </span>\n <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section layout=\"row\" flex ng-if=\"!cell\">\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"led-panel\"\n ng-style=\"{backgroundColor: ledPanelBackgroundColor }\"></span>\n <span flex ng-show=\"$index===1\"></span>\n </section>\n </section>\n </section> \n</div>", | 32 | + "templateHtml": "<div class=\"gpio-panel\" style=\"height: 100%;\">\n <section fxLayout=\"row\" *ngFor=\"let row of rows\">\n <section fxFlex fxLayout=\"row\" *ngFor=\"let cell of row; let $index = index\">\n <section fxLayout=\"row\" fxFlex *ngIf=\"cell\" fxLayoutAlign=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" [fxShow]=\"$index===0\">{{ cell.label }}</span>\n <section fxLayout=\"row\" class=\"led-panel\" [ngClass]=\"$index===0 ? 'col-0' : 'col-1'\"\n [ngStyle]=\"{backgroundColor: ledPanelBackgroundColor}\">\n <span class=\"pin\" [fxShow]=\"$index===0\">{{cell.pin}}</span>\n <span class=\"led-container\">\n <tb-led-light [size]=\"prefferedRowHeight\"\n [colorOn]=\"cell.colorOn\"\n [colorOff]=\"cell.colorOff\"\n [offOpacity]=\"'0.9'\"\n [enabled]=\"cell.enabled\">\n </tb-led-light>\n </span>\n <span class=\"pin\" [fxShow]=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" [fxShow]=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section fxLayout=\"row\" fxFlex *ngIf=\"!cell\">\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"led-panel\"\n [ngStyle]=\"{backgroundColor: ledPanelBackgroundColor}\"></span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n </section>\n </section>\n </section> \n</div>", |
33 | "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n margin: auto;\n}\n\n.led-panel {\n margin: 0;\n width: 66px;\n min-width: 66px;\n}\n\n.led-container {\n width: 48px;\n min-width: 48px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.led-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | 33 | "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n margin: auto;\n}\n\n.led-panel {\n margin: 0;\n width: 66px;\n min-width: 66px;\n}\n\n.led-container {\n width: 48px;\n min-width: 48px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.led-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", |
34 | - "controllerScript": "self.onInit = function() {\n var i, gpio;\n \n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n \n scope.gpioList = [];\n scope.gpioByPin = {};\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false,\n colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n colorOff: tinycolor(gpio.color).darken().toHexString()\n }\n );\n scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n }\n\n scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var changed = false;\n for (var d = 0; d < self.ctx.data.length; d++) {\n var cellData = self.ctx.data[d];\n var dataKey = cellData.dataKey;\n var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n if (gpio) {\n var enabled = false;\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n enabled = (tvPair[1] === true || tvPair[1] === 'true');\n }\n if (gpio.enabled != enabled) {\n changed = true;\n gpio.enabled = enabled;\n }\n }\n }\n if (changed) {\n self.ctx.$scope.$digest();\n } \n}\n\nself.onResize = function() {\n var rowCount = self.ctx.$scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n \n var ratio = prefferedRowHeight/32;\n \n var leftLabels = $('.gpio-left-label', self.ctx.$container);\n leftLabels.css('font-size', 16*ratio+'px');\n var rightLabels = $('.gpio-right-label', self.ctx.$container);\n rightLabels.css('font-size', 16*ratio+'px');\n var pins = $('.pin', self.ctx.$container);\n var pinsFontSize = Math.max(9, 12*ratio);\n pins.css('font-size', pinsFontSize+'px'); \n}\n\nself.onDestroy = function() {\n}\n", | 34 | + "controllerScript": "var namespace;\nvar cssParser = new cssjs();\n\nself.onInit = function() {\n var utils = self.ctx.$injector.get(self.ctx.servicesMap.get('utils'));\n namespace = 'gpio-panel-' + utils.guid();\n cssParser.testMode = false;\n cssParser.cssPreviewNamespace = namespace;\n self.ctx.$container.addClass(namespace);\n self.ctx.ngZone.run(function() {\n init(); \n });\n}\n\nfunction init() {\n var i, gpio;\n \n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n \n scope.gpioList = [];\n scope.gpioByPin = {};\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false,\n colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n colorOff: tinycolor(gpio.color).darken().toHexString()\n }\n );\n scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n }\n\n scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var changed = false;\n for (var d = 0; d < self.ctx.data.length; d++) {\n var cellData = self.ctx.data[d];\n var dataKey = cellData.dataKey;\n var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n if (gpio) {\n var enabled = false;\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n enabled = (tvPair[1] === true || tvPair[1] === 'true');\n }\n if (gpio.enabled != enabled) {\n changed = true;\n gpio.enabled = enabled;\n }\n }\n }\n if (changed) {\n self.ctx.detectChanges();\n } \n}\n\nself.onResize = function() {\n var rowCount = self.ctx.$scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n \n var ratio = prefferedRowHeight/32;\n \n var css = '.gpio-left-label, .gpio-right-label {\\n' +\n ' font-size: ' + 16*ratio+'px;\\n'+\n '}\\n';\n var pinsFontSize = Math.max(9, 12*ratio);\n css += '.pin {\\n' +\n ' font-size: ' + pinsFontSize+'px;\\n'+\n '}\\n';\n \n cssParser.createStyleElement(namespace, css); \n \n self.ctx.detectChanges();\n}\n\nself.onDestroy = function() {\n}\n", |
35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio leds\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio led\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n },\n \"color\": {\n \"title\": \"Color\",\n \"type\": \"string\",\n \"default\": \"red\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n }\n },\n \"ledPanelBackgroundColor\": {\n \"title\": \"LED panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n } \n },\n \"required\": [\"gpioList\", \n \"ledPanelBackgroundColor\"]\n },\n \"form\": [\n {\n \"key\": \"gpioList\",\n \"items\": [\n \"gpioList[].pin\",\n \"gpioList[].label\",\n \"gpioList[].row\",\n \"gpioList[].col\",\n {\n \"key\": \"gpioList[].color\",\n \"type\": \"color\"\n }\n ]\n },\n {\n \"key\": \"ledPanelBackgroundColor\",\n \"type\": \"color\"\n }\n ]\n}", | 35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio leds\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio led\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n },\n \"color\": {\n \"title\": \"Color\",\n \"type\": \"string\",\n \"default\": \"red\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n }\n },\n \"ledPanelBackgroundColor\": {\n \"title\": \"LED panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n } \n },\n \"required\": [\"gpioList\", \n \"ledPanelBackgroundColor\"]\n },\n \"form\": [\n {\n \"key\": \"gpioList\",\n \"items\": [\n \"gpioList[].pin\",\n \"gpioList[].label\",\n \"gpioList[].row\",\n \"gpioList[].col\",\n {\n \"key\": \"gpioList[].color\",\n \"type\": \"color\"\n }\n ]\n },\n {\n \"key\": \"ledPanelBackgroundColor\",\n \"type\": \"color\"\n }\n ]\n}", |
36 | "dataKeySettingsSchema": "{}\n", | 36 | "dataKeySettingsSchema": "{}\n", |
37 | "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"color\":\"#008000\",\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"color\":\"#ffff00\",\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"color\":\"#cf006f\",\"_uniqueKey\":2}],\"ledPanelBackgroundColor\":\"#b71c1c\"},\"title\":\"Basic GPIO Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"1\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"2\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"3\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}" | 37 | "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"color\":\"#008000\",\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"color\":\"#ffff00\",\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"color\":\"#cf006f\",\"_uniqueKey\":2}],\"ledPanelBackgroundColor\":\"#b71c1c\"},\"title\":\"Basic GPIO Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"1\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"2\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"3\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}" |
@@ -45,9 +45,9 @@ | @@ -45,9 +45,9 @@ | ||
45 | "sizeX": 6, | 45 | "sizeX": 6, |
46 | "sizeY": 10.5, | 46 | "sizeY": 10.5, |
47 | "resources": [], | 47 | "resources": [], |
48 | - "templateHtml": "<fieldset class=\"gpio-panel\" ng-disabled=\"!rpcEnabled || executingRpcRequest\" style=\"height: 100%;\">\n <section class=\"gpio-row\" layout=\"row\" ng-repeat=\"row in rows track by $index\" \n ng-style=\"{'height': prefferedRowHeight+'px'}\">\n <section flex layout=\"row\" ng-repeat=\"cell in row track by $index\">\n <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n <section layout=\"row\" class=\"switch-panel\" layout-align=\"start center\" ng-class=\"$index===0 ? 'col-0' : 'col-1'\"\n ng-style=\"{'height': prefferedRowHeight+'px', 'backgroundColor': '{{ switchPanelBackgroundColor }}'}\">\n <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n <span flex ng-show=\"$index===1\"></span>\n <md-switch\n aria-label=\"{{ cell.label }}\"\n ng-disabled=\"!rpcEnabled || executingRpcRequest\"\n ng-model=\"cell.enabled\" \n ng-change=\"cell.enabled = !cell.enabled\" \n ng-click=\"gpioClick($event, cell)\">\n </md-switch>\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section layout=\"row\" flex ng-if=\"!cell\">\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"switch-panel\"\n ng-style=\"{'height': prefferedRowHeight+'px', 'backgroundColor': '{{ switchPanelBackgroundColor }}'}\"></span>\n <span flex ng-show=\"$index===1\"></span>\n </section>\n </section>\n </section> \n <span class=\"error\" style=\"position: absolute; bottom: 5px;\" ng-show=\"rpcErrorText\">{{rpcErrorText}}</span>\n <md-progress-linear ng-show=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" md-mode=\"indeterminate\"></md-progress-linear> \n</fieldset>", | ||
49 | - "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.switch-panel {\n margin: 0;\n height: 32px;\n width: 66px;\n min-width: 66px;\n}\n\n.switch-panel md-switch {\n margin: 0;\n width: 36px;\n min-width: 36px;\n}\n\n.switch-panel md-switch > div.md-container {\n margin: 0;\n}\n\n.switch-panel.col-0 md-switch {\n margin-left: 8px;\n margin-right: 4px;\n}\n\n.switch-panel.col-1 md-switch {\n margin-left: 4px;\n margin-right: 8px;\n}\n\n.gpio-row {\n height: 32px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | ||
50 | - "controllerScript": "self.onInit = function() {\n \n var i, gpio;\n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n scope.gpioList = [];\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false\n }\n );\n }\n\n scope.requestTimeout = settings.requestTimeout || 1000;\n\n scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioStatusRequest = {\n method: \"getGpioStatus\",\n paramsBody: \"{}\"\n };\n \n if (settings.gpioStatusRequest) {\n scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n }\n \n scope.gpioStatusChangeRequest = {\n method: \"setGpioStatus\",\n paramsBody: \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n };\n \n if (settings.gpioStatusChangeRequest) {\n scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n }\n \n scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n \n if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n }\n \n scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n \n function requestGpioStatus() {\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n scope.gpioStatusRequest.paramsBody, \n scope.requestTimeout)\n .then(\n function success(responseBody) {\n for (var g = 0; g < scope.gpioList.length; g++) {\n var gpio = scope.gpioList[g];\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled; \n }\n }\n );\n }\n \n function changeGpioStatus(gpio) {\n var pin = gpio.pin + '';\n var enabled = !gpio.enabled;\n enabled = enabled === true ? 'true' : 'false';\n var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n requestBody, scope.requestTimeout)\n .then(\n function success(responseBody) {\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled;\n }\n );\n }\n \n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n }\n\n scope.gpioClick = function($event, gpio) {\n changeGpioStatus(gpio);\n };\n\n requestGpioStatus(); \n \n self.onResize();\n}\n\nself.onResize = function() {\n var scope = self.ctx.$scope;\n var rowCount = scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n scope.prefferedRowHeight = prefferedRowHeight;\n var ratio = prefferedRowHeight/32;\n var switches = $('md-switch', self.ctx.$container);\n switches.css('height', 30*ratio+'px');\n switches.css('width', 36*ratio+'px');\n switches.css('min-width', 36*ratio+'px');\n $('.md-container', switches).css('height', 24*ratio+'px');\n $('.md-container', switches).css('width', 36*ratio+'px');\n var bars = $('.md-bar', self.ctx.$container);\n bars.css('height', 14*ratio+'px');\n bars.css('width', 34*ratio+'px');\n var thumbs = $('.md-thumb', self.ctx.$container);\n thumbs.css('height', 20*ratio+'px');\n thumbs.css('width', 20*ratio+'px');\n \n var leftLabels = $('.gpio-left-label', self.ctx.$container);\n leftLabels.css('font-size', 16*ratio+'px');\n var rightLabels = $('.gpio-right-label', self.ctx.$container);\n rightLabels.css('font-size', 16*ratio+'px');\n var pins = $('.pin', self.ctx.$container);\n var pinsFontSize = Math.max(9, 12*ratio);\n pins.css('font-size', pinsFontSize+'px'); \n}\n\nself.onDestroy = function() {\n}\n", | 48 | + "templateHtml": "<fieldset class=\"gpio-panel\" style=\"height: 100%;\">\n <section class=\"gpio-row\" fxLayout=\"row\" *ngFor=\"let row of rows\" \n [ngStyle]=\"{'height': prefferedRowHeight+'px'}\">\n <section fxFlex fxLayout=\"row\" *ngFor=\"let cell of row; let $index = index\">\n <section fxLayout=\"row\" fxFlex *ngIf=\"cell\" fxLayoutAlign=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" [fxShow]=\"$index===0\">{{ cell.label }}</span>\n <section fxLayout=\"row\" class=\"switch-panel\" fxLayoutAlign=\"start center\" [ngClass]=\"$index===0 ? 'col-0' : 'col-1'\"\n [ngStyle]=\"{'height': prefferedRowHeight+'px', 'backgroundColor': switchPanelBackgroundColor }\">\n <span class=\"pin\" [fxShow]=\"$index===0\">{{cell.pin}}</span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n <mat-slide-toggle\n [disabled]=\"!rpcEnabled || executingRpcRequest\"\n [checked]=\"cell.enabled\" \n (change)=\"gpioToggleChange($event, cell)\" \n (click)=\"gpioClick($event, cell)\">\n </mat-slide-toggle>\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"pin\" [fxShow]=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" [fxShow]=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section fxLayout=\"row\" fxFlex *ngIf=\"!cell\">\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"switch-panel\"\n [ngStyle]=\"{'height': prefferedRowHeight+'px', 'backgroundColor': switchPanelBackgroundColor }\"></span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n </section>\n </section>\n </section> \n <span class=\"error\" style=\"position: absolute; bottom: 5px;\" [fxShow]=\"rpcErrorText\">{{rpcErrorText}}</span>\n <mat-progress-bar [fxShow]=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" mode=\"indeterminate\"></mat-progress-bar>\n</fieldset>", |
49 | + "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.switch-panel {\n margin: 0;\n height: 32px;\n width: 66px;\n min-width: 66px;\n}\n\n.switch-panel mat-slide-toggle {\n margin: 0;\n width: 36px;\n min-width: 36px;\n}\n\n.switch-panel.col-0 mat-slide-toggle {\n margin-left: 8px;\n margin-right: 4px;\n}\n\n.switch-panel.col-1 mat-slide-toggle {\n margin-left: 4px;\n margin-right: 8px;\n}\n\n.gpio-row {\n height: 32px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | ||
50 | + "controllerScript": "var namespace;\nvar cssParser = new cssjs();\n\nself.onInit = function() {\n var utils = self.ctx.$injector.get(self.ctx.servicesMap.get('utils'));\n namespace = 'gpio-control-' + utils.guid();\n cssParser.testMode = false;\n cssParser.cssPreviewNamespace = namespace;\n self.ctx.$container.addClass(namespace);\n self.ctx.ngZone.run(function() {\n init(); \n });\n}\n\nfunction init() {\n \n var i, gpio;\n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n scope.gpioList = [];\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false\n }\n );\n }\n\n scope.requestTimeout = settings.requestTimeout || 1000;\n\n scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioStatusRequest = {\n method: \"getGpioStatus\",\n paramsBody: \"{}\"\n };\n \n if (settings.gpioStatusRequest) {\n scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n }\n \n scope.gpioStatusChangeRequest = {\n method: \"setGpioStatus\",\n paramsBody: \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n };\n \n if (settings.gpioStatusChangeRequest) {\n scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n }\n \n scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n \n if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n }\n \n scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n \n function requestGpioStatus() {\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n scope.gpioStatusRequest.paramsBody, \n scope.requestTimeout)\n .subscribe(\n function success(responseBody) {\n for (var g = 0; g < scope.gpioList.length; g++) {\n var gpio = scope.gpioList[g];\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled; \n self.ctx.detectChanges();\n }\n }\n );\n }\n \n function changeGpioStatus(gpio) {\n var pin = gpio.pin + '';\n var enabled = !gpio.enabled;\n enabled = enabled === true ? 'true' : 'false';\n var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n requestBody, scope.requestTimeout)\n .subscribe(\n function success(responseBody) {\n var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n gpio.enabled = enabled;\n self.ctx.detectChanges();\n }\n );\n }\n \n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n }\n\n scope.gpioClick = function($event, gpio) {\n if (scope.rpcEnabled && !scope.executingRpcRequest) {\n changeGpioStatus(gpio);\n }\n };\n \n scope.gpioToggleChange = function($event, gpio) {\n gpio.enabled = !$event.checked;\n $event.source.toggle();\n self.ctx.detectChanges();\n }\n \n if (scope.rpcEnabled) {\n requestGpioStatus(); \n }\n \n self.onResize();\n}\n\nself.onResize = function() {\n var scope = self.ctx.$scope;\n var rowCount = scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n scope.prefferedRowHeight = prefferedRowHeight;\n var ratio = prefferedRowHeight/32;\n \n var css = '.mat-slide-toggle .mat-slide-toggle-bar {\\n' +\n ' height: ' + 14*ratio+'px;\\n'+\n ' width: ' + 36*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-thumb-container {\\n' +\n ' height: ' + 20*ratio+'px;\\n'+\n ' width: ' + 20*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-thumb {\\n' +\n ' height: ' + 20*ratio+'px;\\n'+\n ' width: ' + 20*ratio+'px;\\n'+\n '}\\n';\n css += '.mat-slide-toggle .mat-slide-toggle-ripple {\\n' +\n ' height: ' + 40*ratio+'px;\\n'+\n ' width: ' + 40*ratio+'px;\\n'+\n ' top: calc(50% - '+20*ratio+'px);\\n'+\n ' left: calc(50% - '+20*ratio+'px);\\n'+\n '}\\n';\n css += '.gpio-left-label, .gpio-right-label {\\n' +\n ' font-size: ' + 16*ratio+'px;\\n'+\n '}\\n';\n var pinsFontSize = Math.max(9, 12*ratio);\n css += '.pin {\\n' +\n ' font-size: ' + pinsFontSize+'px;\\n'+\n '}\\n';\n\n cssParser.createStyleElement(namespace, css);\n \n self.ctx.detectChanges();\n}\n\nself.onDestroy = function() {\n}\n", | ||
51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio switches\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio switch\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n }\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"switchPanelBackgroundColor\": {\n \"title\": \"Switches panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n },\n \"gpioStatusRequest\": {\n \"title\": \"GPIO status request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"getGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"gpioStatusChangeRequest\": {\n \"title\": \"GPIO status change request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"setGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"parseGpioStatusFunction\": {\n \"title\": \"Parse gpio status function\",\n \"type\": \"string\",\n \"default\": \"return body[pin] === true;\"\n } \n },\n \"required\": [\"gpioList\", \n \"requestTimeout\",\n \"switchPanelBackgroundColor\",\n \"gpioStatusRequest\",\n \"gpioStatusChangeRequest\",\n \"parseGpioStatusFunction\"]\n },\n \"form\": [\n \"gpioList\",\n \"requestTimeout\",\n {\n \"key\": \"switchPanelBackgroundColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"gpioStatusRequest\",\n \"items\": [\n \"gpioStatusRequest.method\",\n {\n \"key\": \"gpioStatusRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"gpioStatusChangeRequest\",\n \"items\": [\n \"gpioStatusChangeRequest.method\",\n {\n \"key\": \"gpioStatusChangeRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"parseGpioStatusFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", | 51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio switches\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio switch\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n }\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout\",\n \"type\": \"number\",\n \"default\": 500\n },\n \"switchPanelBackgroundColor\": {\n \"title\": \"Switches panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n },\n \"gpioStatusRequest\": {\n \"title\": \"GPIO status request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"getGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"gpioStatusChangeRequest\": {\n \"title\": \"GPIO status change request\",\n \"type\": \"object\",\n \"properties\": {\n \"method\": {\n \"title\": \"Method name\",\n \"type\": \"string\",\n \"default\": \"setGpioStatus\"\n },\n \"paramsBody\": {\n \"title\": \"Method body\",\n \"type\": \"string\",\n \"default\": \"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n }\n },\n \"required\": [\"method\", \"paramsBody\"]\n },\n \"parseGpioStatusFunction\": {\n \"title\": \"Parse gpio status function\",\n \"type\": \"string\",\n \"default\": \"return body[pin] === true;\"\n } \n },\n \"required\": [\"gpioList\", \n \"requestTimeout\",\n \"switchPanelBackgroundColor\",\n \"gpioStatusRequest\",\n \"gpioStatusChangeRequest\",\n \"parseGpioStatusFunction\"]\n },\n \"form\": [\n \"gpioList\",\n \"requestTimeout\",\n {\n \"key\": \"switchPanelBackgroundColor\",\n \"type\": \"color\"\n },\n {\n \"key\": \"gpioStatusRequest\",\n \"items\": [\n \"gpioStatusRequest.method\",\n {\n \"key\": \"gpioStatusRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"gpioStatusChangeRequest\",\n \"items\": [\n \"gpioStatusChangeRequest.method\",\n {\n \"key\": \"gpioStatusChangeRequest.paramsBody\",\n \"type\": \"json\"\n }\n ]\n },\n {\n \"key\": \"parseGpioStatusFunction\",\n \"type\": \"javascript\"\n }\n ]\n}", |
52 | "dataKeySettingsSchema": "{}\n", | 52 | "dataKeySettingsSchema": "{}\n", |
53 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#008a00\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":7,\"label\":\"GPIO 4 (GPCLK0)\",\"row\":3,\"col\":0,\"_uniqueKey\":0},{\"pin\":11,\"label\":\"GPIO 17\",\"row\":5,\"col\":0,\"_uniqueKey\":1},{\"pin\":12,\"label\":\"GPIO 18\",\"row\":5,\"col\":1,\"_uniqueKey\":2},{\"_uniqueKey\":3,\"pin\":13,\"label\":\"GPIO 27\",\"row\":6,\"col\":0},{\"_uniqueKey\":4,\"pin\":15,\"label\":\"GPIO 22\",\"row\":7,\"col\":0},{\"_uniqueKey\":5,\"pin\":16,\"label\":\"GPIO 23\",\"row\":7,\"col\":1},{\"_uniqueKey\":6,\"pin\":18,\"label\":\"GPIO 24\",\"row\":8,\"col\":1},{\"_uniqueKey\":7,\"pin\":22,\"label\":\"GPIO 25\",\"row\":10,\"col\":1},{\"_uniqueKey\":8,\"pin\":29,\"label\":\"GPIO 5\",\"row\":14,\"col\":0},{\"_uniqueKey\":9,\"pin\":31,\"label\":\"GPIO 6\",\"row\":15,\"col\":0},{\"_uniqueKey\":10,\"pin\":32,\"label\":\"GPIO 12\",\"row\":15,\"col\":1},{\"_uniqueKey\":11,\"pin\":33,\"label\":\"GPIO 13\",\"row\":16,\"col\":0},{\"_uniqueKey\":12,\"pin\":35,\"label\":\"GPIO 19\",\"row\":17,\"col\":0},{\"_uniqueKey\":13,\"pin\":36,\"label\":\"GPIO 16\",\"row\":17,\"col\":1},{\"_uniqueKey\":14,\"pin\":37,\"label\":\"GPIO 26\",\"row\":18,\"col\":0},{\"_uniqueKey\":15,\"pin\":38,\"label\":\"GPIO 20\",\"row\":18,\"col\":1},{\"_uniqueKey\":16,\"pin\":40,\"label\":\"GPIO 21\",\"row\":19,\"col\":1}]},\"title\":\"Raspberry Pi GPIO Control\"}" | 53 | "defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"parseGpioStatusFunction\":\"return body[pin] === true;\",\"gpioStatusChangeRequest\":{\"method\":\"setGpioStatus\",\"paramsBody\":\"{\\n \\\"pin\\\": \\\"{$pin}\\\",\\n \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"},\"requestTimeout\":500,\"switchPanelBackgroundColor\":\"#008a00\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":7,\"label\":\"GPIO 4 (GPCLK0)\",\"row\":3,\"col\":0,\"_uniqueKey\":0},{\"pin\":11,\"label\":\"GPIO 17\",\"row\":5,\"col\":0,\"_uniqueKey\":1},{\"pin\":12,\"label\":\"GPIO 18\",\"row\":5,\"col\":1,\"_uniqueKey\":2},{\"_uniqueKey\":3,\"pin\":13,\"label\":\"GPIO 27\",\"row\":6,\"col\":0},{\"_uniqueKey\":4,\"pin\":15,\"label\":\"GPIO 22\",\"row\":7,\"col\":0},{\"_uniqueKey\":5,\"pin\":16,\"label\":\"GPIO 23\",\"row\":7,\"col\":1},{\"_uniqueKey\":6,\"pin\":18,\"label\":\"GPIO 24\",\"row\":8,\"col\":1},{\"_uniqueKey\":7,\"pin\":22,\"label\":\"GPIO 25\",\"row\":10,\"col\":1},{\"_uniqueKey\":8,\"pin\":29,\"label\":\"GPIO 5\",\"row\":14,\"col\":0},{\"_uniqueKey\":9,\"pin\":31,\"label\":\"GPIO 6\",\"row\":15,\"col\":0},{\"_uniqueKey\":10,\"pin\":32,\"label\":\"GPIO 12\",\"row\":15,\"col\":1},{\"_uniqueKey\":11,\"pin\":33,\"label\":\"GPIO 13\",\"row\":16,\"col\":0},{\"_uniqueKey\":12,\"pin\":35,\"label\":\"GPIO 19\",\"row\":17,\"col\":0},{\"_uniqueKey\":13,\"pin\":36,\"label\":\"GPIO 16\",\"row\":17,\"col\":1},{\"_uniqueKey\":14,\"pin\":37,\"label\":\"GPIO 26\",\"row\":18,\"col\":0},{\"_uniqueKey\":15,\"pin\":38,\"label\":\"GPIO 20\",\"row\":18,\"col\":1},{\"_uniqueKey\":16,\"pin\":40,\"label\":\"GPIO 21\",\"row\":19,\"col\":1}]},\"title\":\"Raspberry Pi GPIO Control\"}" |
@@ -61,9 +61,9 @@ | @@ -61,9 +61,9 @@ | ||
61 | "sizeX": 7, | 61 | "sizeX": 7, |
62 | "sizeY": 10.5, | 62 | "sizeY": 10.5, |
63 | "resources": [], | 63 | "resources": [], |
64 | - "templateHtml": "<div class=\"gpio-panel\" style=\"height: 100%;\">\n <section layout=\"row\" ng-repeat=\"row in rows\">\n <section flex layout=\"row\" ng-repeat=\"cell in row\">\n <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n <section layout=\"row\" class=\"led-panel\" ng-class=\"$index===0 ? 'col-0' : 'col-1'\"\n ng-style=\"{backgroundColor: ledPanelBackgroundColor}\">\n <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n <span class=\"led-container\">\n <tb-led-light size=\"prefferedRowHeight\"\n color-on=\"cell.colorOn\"\n color-off=\"cell.colorOff\"\n off-opacity=\"'0.9'\"\n tb-enabled=\"cell.enabled\">\n </tb-led-light>\n </span>\n <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section layout=\"row\" flex ng-if=\"!cell\">\n <span flex ng-show=\"$index===0\"></span>\n <span class=\"led-panel\"\n ng-style=\"{backgroundColor: ledPanelBackgroundColor}\"></span>\n <span flex ng-show=\"$index===1\"></span>\n </section>\n </section>\n </section> \n</div>", | 64 | + "templateHtml": "<div class=\"gpio-panel\" style=\"height: 100%;\">\n <section fxLayout=\"row\" *ngFor=\"let row of rows\">\n <section fxFlex fxLayout=\"row\" *ngFor=\"let cell of row; let $index = index\">\n <section fxLayout=\"row\" fxFlex *ngIf=\"cell\" fxLayoutAlign=\"{{$index===0 ? 'end center' : 'start center'}}\">\n <span class=\"gpio-left-label\" [fxShow]=\"$index===0\">{{ cell.label }}</span>\n <section fxLayout=\"row\" class=\"led-panel\" [ngClass]=\"$index===0 ? 'col-0' : 'col-1'\"\n [ngStyle]=\"{backgroundColor: ledPanelBackgroundColor}\">\n <span class=\"pin\" [fxShow]=\"$index===0\">{{cell.pin}}</span>\n <span class=\"led-container\">\n <tb-led-light [size]=\"prefferedRowHeight\"\n [colorOn]=\"cell.colorOn\"\n [colorOff]=\"cell.colorOff\"\n [offOpacity]=\"'0.9'\"\n [enabled]=\"cell.enabled\">\n </tb-led-light>\n </span>\n <span class=\"pin\" [fxShow]=\"$index===1\">{{cell.pin}}</span>\n </section>\n <span class=\"gpio-right-label\" [fxShow]=\"$index===1\">{{ cell.label }}</span>\n </section>\n <section fxLayout=\"row\" fxFlex *ngIf=\"!cell\">\n <span fxFlex [fxShow]=\"$index===0\"></span>\n <span class=\"led-panel\"\n [ngStyle]=\"{backgroundColor: ledPanelBackgroundColor}\"></span>\n <span fxFlex [fxShow]=\"$index===1\"></span>\n </section>\n </section>\n </section> \n</div>", |
65 | "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n margin: auto;\n}\n\n.led-panel {\n margin: 0;\n width: 66px;\n min-width: 66px;\n}\n\n.led-container {\n width: 48px;\n min-width: 48px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.led-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", | 65 | "templateCss": ".error {\n font-size: 14px !important;\n color: maroon;/*rgb(250,250,250);*/\n background-color: transparent;\n padding: 6px;\n}\n\n.error span {\n margin: auto;\n}\n\n.gpio-panel {\n padding-top: 10px;\n white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n margin: auto;\n}\n\n.led-panel {\n margin: 0;\n width: 66px;\n min-width: 66px;\n}\n\n.led-container {\n width: 48px;\n min-width: 48px;\n}\n\n.pin {\n margin-top: auto;\n margin-bottom: auto;\n color: white;\n font-size: 12px;\n width: 16px;\n min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n margin-left: auto;\n padding-left: 2px;\n text-align: right;\n}\n\n.led-panel.col-1 .pin {\n margin-right: auto;\n \n text-align: left;\n}\n\n.gpio-left-label {\n margin-right: 8px;\n}\n\n.gpio-right-label {\n margin-left: 8px;\n}", |
66 | - "controllerScript": "self.onInit = function() {\n var i, gpio;\n \n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n \n scope.gpioList = [];\n scope.gpioByPin = {};\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false,\n colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n colorOff: tinycolor(gpio.color).darken().toHexString()\n }\n );\n scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n }\n\n scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var changed = false;\n for (var d = 0; d < self.ctx.data.length; d++) {\n var cellData = self.ctx.data[d];\n var dataKey = cellData.dataKey;\n var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n if (gpio) {\n var enabled = false;\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n enabled = (tvPair[1] === true || tvPair[1] === 'true');\n }\n if (gpio.enabled != enabled) {\n changed = true;\n gpio.enabled = enabled;\n }\n }\n }\n if (changed) {\n self.ctx.$scope.$digest();\n } \n}\n\nself.onResize = function() {\n var rowCount = self.ctx.$scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n \n var ratio = prefferedRowHeight/32;\n \n var leftLabels = $('.gpio-left-label', self.ctx.$container);\n leftLabels.css('font-size', 16*ratio+'px');\n var rightLabels = $('.gpio-right-label', self.ctx.$container);\n rightLabels.css('font-size', 16*ratio+'px');\n var pins = $('.pin', self.ctx.$container);\n var pinsFontSize = Math.max(9, 12*ratio);\n pins.css('font-size', pinsFontSize+'px'); \n}\n\nself.onDestroy = function() {\n}\n", | 66 | + "controllerScript": "var namespace;\nvar cssParser = new cssjs();\n\nself.onInit = function() {\n var utils = self.ctx.$injector.get(self.ctx.servicesMap.get('utils'));\n namespace = 'gpio-panel-' + utils.guid();\n cssParser.testMode = false;\n cssParser.cssPreviewNamespace = namespace;\n self.ctx.$container.addClass(namespace);\n self.ctx.ngZone.run(function() {\n init(); \n });\n}\n\nfunction init() {\n var i, gpio;\n \n var scope = self.ctx.$scope;\n var settings = self.ctx.settings;\n \n scope.gpioList = [];\n scope.gpioByPin = {};\n for (var g = 0; g < settings.gpioList.length; g++) {\n gpio = settings.gpioList[g];\n scope.gpioList.push(\n {\n row: gpio.row,\n col: gpio.col,\n pin: gpio.pin,\n label: gpio.label,\n enabled: false,\n colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n colorOff: tinycolor(gpio.color).darken().toHexString()\n }\n );\n scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n }\n\n scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor('green').lighten(2).toRgbString();\n\n scope.gpioCells = {};\n var rowCount = 0;\n for (i = 0; i < scope.gpioList.length; i++) {\n gpio = scope.gpioList[i];\n scope.gpioCells[gpio.row+'_'+gpio.col] = gpio;\n rowCount = Math.max(rowCount, gpio.row+1);\n }\n \n scope.prefferedRowHeight = 32;\n scope.rows = [];\n for (i = 0; i < rowCount; i++) {\n var row = [];\n for (var c =0; c<2;c++) {\n if (scope.gpioCells[i+'_'+c]) {\n row[c] = scope.gpioCells[i+'_'+c];\n } else {\n row[c] = null;\n }\n }\n scope.rows.push(row);\n } \n \n self.onResize();\n}\n\nself.onDataUpdated = function() {\n var changed = false;\n for (var d = 0; d < self.ctx.data.length; d++) {\n var cellData = self.ctx.data[d];\n var dataKey = cellData.dataKey;\n var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n if (gpio) {\n var enabled = false;\n if (cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length - 1];\n enabled = (tvPair[1] === true || tvPair[1] === 'true');\n }\n if (gpio.enabled != enabled) {\n changed = true;\n gpio.enabled = enabled;\n }\n }\n }\n if (changed) {\n self.ctx.detectChanges();\n } \n}\n\nself.onResize = function() {\n var rowCount = self.ctx.$scope.rows.length;\n var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n prefferedRowHeight = Math.min(32, prefferedRowHeight);\n prefferedRowHeight = Math.max(12, prefferedRowHeight);\n self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n \n var ratio = prefferedRowHeight/32;\n \n var css = '.gpio-left-label, .gpio-right-label {\\n' +\n ' font-size: ' + 16*ratio+'px;\\n'+\n '}\\n';\n var pinsFontSize = Math.max(9, 12*ratio);\n css += '.pin {\\n' +\n ' font-size: ' + pinsFontSize+'px;\\n'+\n '}\\n';\n \n cssParser.createStyleElement(namespace, css); \n \n self.ctx.detectChanges();\n}\n\nself.onDestroy = function() {\n}\n", |
67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio leds\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio led\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n },\n \"color\": {\n \"title\": \"Color\",\n \"type\": \"string\",\n \"default\": \"red\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n }\n },\n \"ledPanelBackgroundColor\": {\n \"title\": \"LED panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n } \n },\n \"required\": [\"gpioList\", \n \"ledPanelBackgroundColor\"]\n },\n \"form\": [\n {\n \"key\": \"gpioList\",\n \"items\": [\n \"gpioList[].pin\",\n \"gpioList[].label\",\n \"gpioList[].row\",\n \"gpioList[].col\",\n {\n \"key\": \"gpioList[].color\",\n \"type\": \"color\"\n }\n ]\n },\n {\n \"key\": \"ledPanelBackgroundColor\",\n \"type\": \"color\"\n }\n ]\n}", | 67 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"gpioList\": {\n \"title\": \"Gpio leds\",\n \"type\": \"array\",\n \"minItems\" : 1,\n \"items\": {\n \"title\": \"Gpio led\",\n \"type\": \"object\",\n \"properties\": {\n \"pin\": {\n \"title\": \"Pin\",\n \"type\": \"number\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n },\n \"row\": {\n \"title\": \"Row\",\n \"type\": \"number\"\n },\n \"col\": {\n \"title\": \"Column\",\n \"type\": \"number\"\n },\n \"color\": {\n \"title\": \"Color\",\n \"type\": \"string\",\n \"default\": \"red\"\n }\n },\n \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n }\n },\n \"ledPanelBackgroundColor\": {\n \"title\": \"LED panel background color\",\n \"type\": \"string\",\n \"default\": \"#008a00\"\n } \n },\n \"required\": [\"gpioList\", \n \"ledPanelBackgroundColor\"]\n },\n \"form\": [\n {\n \"key\": \"gpioList\",\n \"items\": [\n \"gpioList[].pin\",\n \"gpioList[].label\",\n \"gpioList[].row\",\n \"gpioList[].col\",\n {\n \"key\": \"gpioList[].color\",\n \"type\": \"color\"\n }\n ]\n },\n {\n \"key\": \"ledPanelBackgroundColor\",\n \"type\": \"color\"\n }\n ]\n}", |
68 | "dataKeySettingsSchema": "{}\n", | 68 | "dataKeySettingsSchema": "{}\n", |
69 | "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"gpioList\":[{\"pin\":1,\"label\":\"3.3V\",\"row\":0,\"col\":0,\"color\":\"#fc9700\",\"_uniqueKey\":0},{\"pin\":2,\"label\":\"5V\",\"row\":0,\"col\":1,\"color\":\"#fb0000\",\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 2 (I2C1_SDA)\",\"row\":1,\"col\":0,\"color\":\"#02fefb\",\"_uniqueKey\":2},{\"color\":\"#fb0000\",\"pin\":4,\"label\":\"5V\",\"row\":1,\"col\":1},{\"color\":\"#02fefb\",\"pin\":5,\"label\":\"GPIO 3 (I2C1_SCL)\",\"row\":2,\"col\":0},{\"color\":\"#000000\",\"pin\":6,\"label\":\"GND\",\"row\":2,\"col\":1},{\"color\":\"#00fd00\",\"pin\":7,\"label\":\"GPIO 4 (GPCLK0)\",\"row\":3,\"col\":0},{\"color\":\"#fdfb00\",\"pin\":8,\"label\":\"GPIO 14 (UART_TXD)\",\"row\":3,\"col\":1},{\"color\":\"#000000\",\"pin\":9,\"label\":\"GND\",\"row\":4,\"col\":0},{\"color\":\"#fdfb00\",\"pin\":10,\"label\":\"GPIO 15 (UART_RXD)\",\"row\":4,\"col\":1},{\"color\":\"#00fd00\",\"pin\":11,\"label\":\"GPIO 17\",\"row\":5,\"col\":0},{\"color\":\"#00fd00\",\"pin\":12,\"label\":\"GPIO 18\",\"row\":5,\"col\":1},{\"color\":\"#00fd00\",\"pin\":13,\"label\":\"GPIO 27\",\"row\":6,\"col\":0},{\"color\":\"#000000\",\"pin\":14,\"label\":\"GND\",\"row\":6,\"col\":1},{\"color\":\"#00fd00\",\"pin\":15,\"label\":\"GPIO 22\",\"row\":7,\"col\":0},{\"color\":\"#00fd00\",\"pin\":16,\"label\":\"GPIO 23\",\"row\":7,\"col\":1},{\"color\":\"#fc9700\",\"pin\":17,\"label\":\"3.3V\",\"row\":8,\"col\":0},{\"color\":\"#00fd00\",\"pin\":18,\"label\":\"GPIO 24\",\"row\":8,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":19,\"label\":\"GPIO 10 (SPI_MOSI)\",\"row\":9,\"col\":0},{\"color\":\"#000000\",\"pin\":20,\"label\":\"GND\",\"row\":9,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":21,\"label\":\"GPIO 9 (SPI_MISO)\",\"row\":10,\"col\":0},{\"color\":\"#00fd00\",\"pin\":22,\"label\":\"GPIO 25\",\"row\":10,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":23,\"label\":\"GPIO 11 (SPI_SCLK)\",\"row\":11,\"col\":0},{\"color\":\"#fd01fd\",\"pin\":24,\"label\":\"GPIO 8 (SPI_CE0)\",\"row\":11,\"col\":1},{\"color\":\"#000000\",\"pin\":25,\"label\":\"GND\",\"row\":12,\"col\":0},{\"color\":\"#fd01fd\",\"pin\":26,\"label\":\"GPIO 7 (SPI_CE1)\",\"row\":12,\"col\":1},{\"color\":\"#ffffff\",\"pin\":27,\"label\":\"ID_SD\",\"row\":13,\"col\":0},{\"color\":\"#ffffff\",\"pin\":28,\"label\":\"ID_SC\",\"row\":13,\"col\":1},{\"color\":\"#00fd00\",\"pin\":29,\"label\":\"GPIO 5\",\"row\":14,\"col\":0},{\"color\":\"#000000\",\"pin\":30,\"label\":\"GND\",\"row\":14,\"col\":1},{\"color\":\"#00fd00\",\"pin\":31,\"label\":\"GPIO 6\",\"row\":15,\"col\":0},{\"color\":\"#00fd00\",\"pin\":32,\"label\":\"GPIO 12\",\"row\":15,\"col\":1},{\"color\":\"#00fd00\",\"pin\":33,\"label\":\"GPIO 13\",\"row\":16,\"col\":0},{\"color\":\"#000000\",\"pin\":34,\"label\":\"GND\",\"row\":16,\"col\":1},{\"color\":\"#00fd00\",\"pin\":35,\"label\":\"GPIO 19\",\"row\":17,\"col\":0},{\"color\":\"#00fd00\",\"pin\":36,\"label\":\"GPIO 16\",\"row\":17,\"col\":1},{\"color\":\"#00fd00\",\"pin\":37,\"label\":\"GPIO 26\",\"row\":18,\"col\":0},{\"color\":\"#00fd00\",\"pin\":38,\"label\":\"GPIO 20\",\"row\":18,\"col\":1},{\"color\":\"#000000\",\"pin\":39,\"label\":\"GND\",\"row\":19,\"col\":0},{\"color\":\"#00fd00\",\"pin\":40,\"label\":\"GPIO 21\",\"row\":19,\"col\":1}],\"ledPanelBackgroundColor\":\"#008a00\"},\"title\":\"Raspberry Pi GPIO Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"7\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"11\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"12\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"13\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.48362241571415243,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"29\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.7217670147518815,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}" | 69 | "defaultConfig": "{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"gpioList\":[{\"pin\":1,\"label\":\"3.3V\",\"row\":0,\"col\":0,\"color\":\"#fc9700\",\"_uniqueKey\":0},{\"pin\":2,\"label\":\"5V\",\"row\":0,\"col\":1,\"color\":\"#fb0000\",\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 2 (I2C1_SDA)\",\"row\":1,\"col\":0,\"color\":\"#02fefb\",\"_uniqueKey\":2},{\"color\":\"#fb0000\",\"pin\":4,\"label\":\"5V\",\"row\":1,\"col\":1},{\"color\":\"#02fefb\",\"pin\":5,\"label\":\"GPIO 3 (I2C1_SCL)\",\"row\":2,\"col\":0},{\"color\":\"#000000\",\"pin\":6,\"label\":\"GND\",\"row\":2,\"col\":1},{\"color\":\"#00fd00\",\"pin\":7,\"label\":\"GPIO 4 (GPCLK0)\",\"row\":3,\"col\":0},{\"color\":\"#fdfb00\",\"pin\":8,\"label\":\"GPIO 14 (UART_TXD)\",\"row\":3,\"col\":1},{\"color\":\"#000000\",\"pin\":9,\"label\":\"GND\",\"row\":4,\"col\":0},{\"color\":\"#fdfb00\",\"pin\":10,\"label\":\"GPIO 15 (UART_RXD)\",\"row\":4,\"col\":1},{\"color\":\"#00fd00\",\"pin\":11,\"label\":\"GPIO 17\",\"row\":5,\"col\":0},{\"color\":\"#00fd00\",\"pin\":12,\"label\":\"GPIO 18\",\"row\":5,\"col\":1},{\"color\":\"#00fd00\",\"pin\":13,\"label\":\"GPIO 27\",\"row\":6,\"col\":0},{\"color\":\"#000000\",\"pin\":14,\"label\":\"GND\",\"row\":6,\"col\":1},{\"color\":\"#00fd00\",\"pin\":15,\"label\":\"GPIO 22\",\"row\":7,\"col\":0},{\"color\":\"#00fd00\",\"pin\":16,\"label\":\"GPIO 23\",\"row\":7,\"col\":1},{\"color\":\"#fc9700\",\"pin\":17,\"label\":\"3.3V\",\"row\":8,\"col\":0},{\"color\":\"#00fd00\",\"pin\":18,\"label\":\"GPIO 24\",\"row\":8,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":19,\"label\":\"GPIO 10 (SPI_MOSI)\",\"row\":9,\"col\":0},{\"color\":\"#000000\",\"pin\":20,\"label\":\"GND\",\"row\":9,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":21,\"label\":\"GPIO 9 (SPI_MISO)\",\"row\":10,\"col\":0},{\"color\":\"#00fd00\",\"pin\":22,\"label\":\"GPIO 25\",\"row\":10,\"col\":1},{\"color\":\"#fd01fd\",\"pin\":23,\"label\":\"GPIO 11 (SPI_SCLK)\",\"row\":11,\"col\":0},{\"color\":\"#fd01fd\",\"pin\":24,\"label\":\"GPIO 8 (SPI_CE0)\",\"row\":11,\"col\":1},{\"color\":\"#000000\",\"pin\":25,\"label\":\"GND\",\"row\":12,\"col\":0},{\"color\":\"#fd01fd\",\"pin\":26,\"label\":\"GPIO 7 (SPI_CE1)\",\"row\":12,\"col\":1},{\"color\":\"#ffffff\",\"pin\":27,\"label\":\"ID_SD\",\"row\":13,\"col\":0},{\"color\":\"#ffffff\",\"pin\":28,\"label\":\"ID_SC\",\"row\":13,\"col\":1},{\"color\":\"#00fd00\",\"pin\":29,\"label\":\"GPIO 5\",\"row\":14,\"col\":0},{\"color\":\"#000000\",\"pin\":30,\"label\":\"GND\",\"row\":14,\"col\":1},{\"color\":\"#00fd00\",\"pin\":31,\"label\":\"GPIO 6\",\"row\":15,\"col\":0},{\"color\":\"#00fd00\",\"pin\":32,\"label\":\"GPIO 12\",\"row\":15,\"col\":1},{\"color\":\"#00fd00\",\"pin\":33,\"label\":\"GPIO 13\",\"row\":16,\"col\":0},{\"color\":\"#000000\",\"pin\":34,\"label\":\"GND\",\"row\":16,\"col\":1},{\"color\":\"#00fd00\",\"pin\":35,\"label\":\"GPIO 19\",\"row\":17,\"col\":0},{\"color\":\"#00fd00\",\"pin\":36,\"label\":\"GPIO 16\",\"row\":17,\"col\":1},{\"color\":\"#00fd00\",\"pin\":37,\"label\":\"GPIO 26\",\"row\":18,\"col\":0},{\"color\":\"#00fd00\",\"pin\":38,\"label\":\"GPIO 20\",\"row\":18,\"col\":1},{\"color\":\"#000000\",\"pin\":39,\"label\":\"GND\",\"row\":19,\"col\":0},{\"color\":\"#00fd00\",\"pin\":40,\"label\":\"GPIO 21\",\"row\":19,\"col\":1}],\"ledPanelBackgroundColor\":\"#008a00\"},\"title\":\"Raspberry Pi GPIO Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"7\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"11\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"12\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"13\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.48362241571415243,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"29\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.7217670147518815,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}" |
@@ -11,11 +11,11 @@ | @@ -11,11 +11,11 @@ | ||
11 | "descriptor": { | 11 | "descriptor": { |
12 | "type": "latest", | 12 | "type": "latest", |
13 | "sizeX": 7.5, | 13 | "sizeX": 7.5, |
14 | - "sizeY": 3.5, | 14 | + "sizeY": 3, |
15 | "resources": [], | 15 | "resources": [], |
16 | - "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-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
17 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
18 | - "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\nlet $translate;\r\n\r\nself.onInit = function() {\r\n\r\n $scope = self.ctx.$scope;\r\n attributeService = $scope.$injector.get('attributeService');\r\n toast = $scope.$injector.get('toast');\r\n utils = $scope.$injector.get('utils');\r\n types = $scope.$injector.get('types');\r\n $translate = $scope.$injector.get('$translate');\r\n settings = self.ctx.settings || {};\r\n $scope.settings = settings;\r\n $scope.isValidParameter = true;\r\n $scope.dataKeyDetected = false;\r\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\r\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\r\n\r\n if (self.ctx.datasources && self.ctx.datasources.length) {\r\n var datasource = self.ctx.datasources[0];\r\n if (datasource.type === types.datasourceType.entity) {\r\n if (datasource.entityType && datasource.entityId) {\r\n $scope.entityName = datasource.entityName;\r\n if (settings.widgetTitle && settings.widgetTitle.length) {\r\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\r\n } else {\r\n $scope.titleTemplate = self.ctx.widgetConfig.title;\r\n }\r\n\r\n $scope.entityDetected = true;\r\n }\r\n }\r\n if (datasource.dataKeys.length) {\r\n if (datasource.dataKeys[0].type != types.dataKeyType.attribute) {\r\n $scope.isValidParameter = false;\r\n } else {\r\n $scope.currentKey = datasource.dataKeys[0].name;\r\n $scope.dataKeyType = datasource.dataKeys[0].type;\r\n $scope.dataKeyDetected = true;\r\n }\r\n }\r\n }\r\n\r\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\r\n\r\n $scope.updateAttribute = function () {\r\n if ($scope.entityDetected) {\r\n var datasource = self.ctx.datasources[0];\r\n\r\n attributeService.saveEntityAttributes(\r\n datasource.entityType,\r\n datasource.entityId,\r\n types.attributesScope.server.value,\r\n [\r\n {\r\n key: $scope.currentKey,\r\n value: $scope.currentValue\r\n }\r\n ]\r\n ).then(\r\n function success() {\r\n $scope.originalValue = $scope.currentValue;\r\n if (settings.showResultMessage) {\r\n toast.showSuccess($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n },\r\n function fail() {\r\n if (settings.showResultMessage) {\r\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n }\r\n );\r\n }\r\n };\r\n\r\n $scope.changeFocus = function () {\r\n if ($scope.currentValue === $scope.originalValue) {\r\n $scope.isFocused = false;\r\n }\r\n }\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n\r\n try {\r\n if ($scope.dataKeyDetected) {\r\n if (!$scope.isFocused) {\r\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\r\n $scope.$digest();\r\n }\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n}\r\n\r\nself.onResize = function() {\r\n\r\n}\r\n\r\nself.typeParameters = function() {\r\n return {\r\n maxDatasources: 1,\r\n maxDataKeys: 1\r\n }\r\n}\r\n\r\nself.onDestroy = function() {\r\n\r\n}\r\n", | 16 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
17 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
18 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.minLength(settings.minLength),\n $scope.validators.maxLength(settings.maxLength)]]}\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SERVER_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue($scope.originalValue);\n self.ctx.detectChanges();\n }\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}", | ||
19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", | 19 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", |
20 | "dataKeySettingsSchema": "{}\n", | 20 | "dataKeySettingsSchema": "{}\n", |
21 | "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 server string attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 21 | "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 server string attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -29,9 +29,9 @@ | @@ -29,9 +29,9 @@ | ||
29 | "sizeX": 7.5, | 29 | "sizeX": 7.5, |
30 | "sizeY": 3, | 30 | "sizeY": 3, |
31 | "resources": [], | 31 | "resources": [], |
32 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
33 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
34 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.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 != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n correctValue($scope.currentValue);\n $scope.$digest();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n $scope.currentValue = 0;\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", | 32 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n step=\"1\"\n pattern=\"^-?[0-9]+$\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" >\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
33 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
34 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue),\n $scope.validators.pattern(/^-?[0-9]+$/)]]}\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 }\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SERVER_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\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}", | ||
35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 35 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
36 | "dataKeySettingsSchema": "{}\n", | 36 | "dataKeySettingsSchema": "{}\n", |
37 | "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 integer attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 37 | "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 integer attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -45,9 +45,9 @@ | @@ -45,9 +45,9 @@ | ||
45 | "sizeX": 7.5, | 45 | "sizeX": 7.5, |
46 | "sizeY": 3, | 46 | "sizeY": 3, |
47 | "resources": [], | 47 | "resources": [], |
48 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n step=\"any\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
49 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
50 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n \n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.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 != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n correctValue($scope.currentValue);\n $scope.$digest();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n $scope.currentValue = 0;\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", | 48 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" >\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
49 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
50 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue)]]}\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SERVER_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\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}", | ||
51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 51 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
52 | "dataKeySettingsSchema": "{}\n", | 52 | "dataKeySettingsSchema": "{}\n", |
53 | "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 double attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 53 | "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 double attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -61,9 +61,9 @@ | @@ -61,9 +61,9 @@ | ||
61 | "sizeX": 7.5, | 61 | "sizeX": 7.5, |
62 | "sizeY": 3, | 62 | "sizeY": 3, |
63 | "resources": [], | 63 | "resources": [], |
64 | - "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=\"{{ 'widgets.input-widgets.switch-attribute-value' | translate }}\"\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\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
65 | - "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}", | ||
66 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n\n settings.trueValue = utils.customTranslation(settings.trueValue, settings.trueValue) || true;\n settings.falseValue = utils.customTranslation(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 === types.datasourceType.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 != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.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", | 64 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\r\n <form *ngIf=\"attributeUpdateFormGroup\"\r\n class=\"attribute-update-form\"\r\n [formGroup]=\"attributeUpdateFormGroup\"\r\n (ngSubmit)=\"updateAttribute()\">\r\n <div style=\"padding: 0 8px; margin: auto 0;\">\r\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\r\n <div class=\"grid__element\">\r\n <mat-checkbox formControlName=\"checkboxValue\"\r\n (change)=\"changed()\"\r\n aria-label=\"{{'widgets.input-widgets.switch-timeseries-value' | translate}}\">\r\n {{currentValue}}\r\n </mat-checkbox>\r\n </div>\r\n </div>\r\n\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\r\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\r\n </div>\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\r\n [fxShow]=\"entityDetected && !dataKeyDetected\">\r\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\r\n </div>\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\r\n [fxShow]=\"entityDetected && !isValidParameter\">\r\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\r\n </div>\r\n </div>\r\n </form>\r\n</div>", |
65 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
66 | + "controllerScript": "let settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\nlet $scope;\nlet map;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init();\n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n\n settings.trueValue = utils.defaultValue(utils.customTranslation(settings.trueValue, settings.trueValue), true);\n settings.falseValue = utils.defaultValue(utils.customTranslation(settings.falseValue, settings.falseValue), false);\n\n map = {\n true: settings.trueValue,\n false: settings.falseValue\n };\n \n $scope.checkboxValue = false;\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.attributeUpdateFormGroup = $scope.fb.group({checkboxValue: [$scope.checkboxValue]});\n\n $scope.changed = function() {\n $scope.checkboxValue = $scope.attributeUpdateFormGroup.get('checkboxValue').value;\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.entity.id,\n 'SERVER_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.checkboxValue\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('checkboxValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n $scope.checkboxValue = self.ctx.data[0].data[0][1] === 'true';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.attributeUpdateFormGroup.get('checkboxValue').patchValue($scope.checkboxValue);\n self.ctx.detectChanges();\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {}", | ||
67 | "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}", | 67 | "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}", |
68 | "dataKeySettingsSchema": "{}\n", | 68 | "dataKeySettingsSchema": "{}\n", |
69 | "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\":{}}" | 69 | "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\":{}}" |
@@ -123,11 +123,11 @@ | @@ -123,11 +123,11 @@ | ||
123 | "descriptor": { | 123 | "descriptor": { |
124 | "type": "latest", | 124 | "type": "latest", |
125 | "sizeX": 7.5, | 125 | "sizeX": 7.5, |
126 | - "sizeY": 3.5, | 126 | + "sizeY": 3, |
127 | "resources": [], | 127 | "resources": [], |
128 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n ng-hide=\"entityDetected\"\n ng-bind=\"message\"\n ></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
129 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
130 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = $translate.instant('widgets.input-widgets.no-entity-selected');\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.entity) {\n if (datasource.entityType === types.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 = $translate.instant('widgets.input-widgets.not-allowed-entity');\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.$digest();\n }\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", | 128 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" [innerHtml]=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
129 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
130 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n $scope.message = translate.instant('widgets.input-widgets.no-entity-selected');\n \n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.minLength(settings.minLength),\n $scope.validators.maxLength(settings.maxLength)]]}\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 = translate.instant('widgets.input-widgets.not-allowed-entity');\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SHARED_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue($scope.originalValue);\n self.ctx.detectChanges();\n }\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}", | ||
131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", | 131 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", |
132 | "dataKeySettingsSchema": "{}\n", | 132 | "dataKeySettingsSchema": "{}\n", |
133 | "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 shared string attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 133 | "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 shared string attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -141,9 +141,9 @@ | @@ -141,9 +141,9 @@ | ||
141 | "sizeX": 7.5, | 141 | "sizeX": 7.5, |
142 | "sizeY": 3, | 142 | "sizeY": 3, |
143 | "resources": [], | 143 | "resources": [], |
144 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n ng-hide=\"entityDetected\"\n ng-bind=\"message\"\n >\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
145 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
146 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n $scope.message = $translate.instant('widgets.input-widgets.no-entity-selected');\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.entity) {\n if (datasource.entityType === types.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 = $translate.instant('widgets.input-widgets.not-allowed-entity');\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n correctValue($scope.currentValue);\n $scope.$digest();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n $scope.currentValue = 0;\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", | 144 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n step=\"1\"\n pattern=\"^-?[0-9]+$\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" [innerHtml]=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
145 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
146 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n $scope.message = translate.instant('widgets.input-widgets.no-entity-selected');\n \n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue),\n $scope.validators.pattern(/^-?[0-9]+$/)]]}\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 = translate.instant('widgets.input-widgets.not-allowed-entity');\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SHARED_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\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}", | ||
147 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 147 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
148 | "dataKeySettingsSchema": "{}\n", | 148 | "dataKeySettingsSchema": "{}\n", |
149 | "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 shared integer attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 149 | "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 shared integer attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -157,9 +157,9 @@ | @@ -157,9 +157,9 @@ | ||
157 | "sizeX": 7.5, | 157 | "sizeX": 7.5, |
158 | "sizeY": 3, | 158 | "sizeY": 3, |
159 | "resources": [], | 159 | "resources": [], |
160 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n step=\"any\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-attribute' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-attribute' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\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 {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
161 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
162 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-attribute-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n $scope.message = $translate.instant('widgets.input-widgets.no-entity-selected');\n \n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.entity) {\n if (datasource.entityType === types.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 = $translate.instant('widgets.input-widgets.not-allowed-entity');\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n correctValue($scope.currentValue);\n $scope.$digest();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n $scope.currentValue = 0;\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", | 160 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" [innerHtml]=\"message\"></div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
161 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
162 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false; \n $scope.message = translate.instant('widgets.input-widgets.no-entity-selected');\n \n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue)]]}\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 = translate.instant('widgets.input-widgets.not-allowed-entity');\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SHARED_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n ).subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\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}", | ||
163 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 163 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
164 | "dataKeySettingsSchema": "{}\n", | 164 | "dataKeySettingsSchema": "{}\n", |
165 | "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 shared double attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 165 | "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 shared double attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -173,12 +173,12 @@ | @@ -173,12 +173,12 @@ | ||
173 | "sizeX": 7.5, | 173 | "sizeX": 7.5, |
174 | "sizeY": 3, | 174 | "sizeY": 3, |
175 | "resources": [], | 175 | "resources": [], |
176 | - "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=\"{{ 'widgets.input-widgets.switch-attribute-value' | translate }}\"\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 {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
177 | - "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}", | ||
178 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\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 $translate = $scope.$injector.get('$translate');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = $translate.instant('widgets.input-widgets.no-entity-selected');\n\n settings.trueValue = utils.customTranslation(settings.trueValue, settings.trueValue) || true;\n settings.falseValue = utils.customTranslation(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 === types.datasourceType.entity) {\n if (datasource.entityType === types.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 = $translate.instant('widgets.input-widgets.not-allowed-entity');\n }\n }\n if (datasource.dataKeys.length) {\n if (datasource.dataKeys[0].type != types.dataKeyType.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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.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", | 176 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\r\n <form *ngIf=\"attributeUpdateFormGroup\"\r\n class=\"attribute-update-form\"\r\n [formGroup]=\"attributeUpdateFormGroup\"\r\n (ngSubmit)=\"updateAttribute()\">\r\n <div style=\"padding: 0 8px; margin: auto 0;\">\r\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\r\n <div class=\"grid__element\">\r\n <mat-checkbox formControlName=\"checkboxValue\"\r\n (change)=\"changed()\"\r\n aria-label=\"{{'widgets.input-widgets.switch-timeseries-value' | translate}}\">\r\n {{currentValue}}\r\n </mat-checkbox>\r\n </div>\r\n </div>\r\n\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\" [innerHtml]=\"message\"></div>\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\r\n [fxShow]=\"entityDetected && !dataKeyDetected\">\r\n {{ 'widgets.input-widgets.no-attribute-selected' | translate }}\r\n </div>\r\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\r\n [fxShow]=\"entityDetected && !isValidParameter\">\r\n {{ 'widgets.input-widgets.timeseries-not-allowed' | translate }}\r\n </div>\r\n </div>\r\n </form>\r\n</div>", |
177 | + "templateCss": ".attribute-update-form {\r\n overflow: hidden;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.attribute-update-form__grid {\r\n display: flex;\r\n}\r\n.grid__element:first-child {\r\n flex: 1;\r\n}\r\n\r\n.grid__element {\r\n display: flex;\r\n}\r\n\r\n.attribute-update-form .mat-button.mat-icon-button {\r\n margin: 0;\r\n}\r\n\r\n.attribute-update-form .mat-button.mat-icon-button {\r\n width: 32px;\r\n min-width: 32px;\r\n height: 32px;\r\n min-height: 32px;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n line-height: 20px;\r\n}\r\n\r\n.attribute-update-form .mat-icon-button mat-icon {\r\n width: 20px;\r\n min-width: 20px;\r\n height: 20px;\r\n min-height: 20px;\r\n font-size: 20px;\r\n}\r\n\r\n.tb-toast {\r\n font-size: 14px!important;\r\n}", | ||
178 | + "controllerScript": "let settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\nlet $scope;\nlet map;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init();\n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.message = translate.instant('widgets.input-widgets.no-entity-selected');\n\n settings.trueValue = utils.defaultValue(utils.customTranslation(settings.trueValue, settings.trueValue), true);\n settings.falseValue = utils.defaultValue(utils.customTranslation(settings.falseValue, settings.falseValue), false);\n\n map = {\n true: settings.trueValue,\n false: settings.falseValue\n };\n \n $scope.checkboxValue = false;\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.attributeUpdateFormGroup = $scope.fb.group({checkboxValue: [$scope.checkboxValue]});\n\n $scope.changed = function() {\n $scope.checkboxValue = $scope.attributeUpdateFormGroup.get('checkboxValue').value;\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 = translate.instant('widgets.input-widgets.not-allowed-entity');\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 attributeService.saveEntityAttributes(\n datasource.entity.id,\n 'SHARED_SCOPE',\n [\n {\n key: $scope.currentKey,\n value: $scope.checkboxValue || false\n }\n ]\n ).subscribe(\n function success() {\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n };\n}\n\nself.onDataUpdated = function() {\n try {\n $scope.checkboxValue = self.ctx.data[0].data[0][1] === 'true';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.attributeUpdateFormGroup.get('checkboxValue').patchValue($scope.checkboxValue);\n self.ctx.detectChanges();\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {}", | ||
179 | "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}", | 179 | "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}", |
180 | "dataKeySettingsSchema": "{}\n", | 180 | "dataKeySettingsSchema": "{}\n", |
181 | - "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\":{}}" | 181 | + "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 shared boolean attribute\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
182 | } | 182 | } |
183 | }, | 183 | }, |
184 | { | 184 | { |
@@ -237,9 +237,9 @@ | @@ -237,9 +237,9 @@ | ||
237 | "sizeX": 7.5, | 237 | "sizeX": 7.5, |
238 | "sizeY": 3, | 238 | "sizeY": 3, |
239 | "resources": [], | 239 | "resources": [], |
240 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-timeseries' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
241 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
242 | - "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\nlet $translate;\r\nlet $q\r\nlet $http;\r\n\r\nself.onInit = function() {\r\n\r\n $scope = self.ctx.$scope;\r\n attributeService = $scope.$injector.get('attributeService');\r\n toast = $scope.$injector.get('toast');\r\n utils = $scope.$injector.get('utils');\r\n types = $scope.$injector.get('types');\r\n $translate = $scope.$injector.get('$translate');\r\n $q = $scope.$injector.get('$q');\r\n $http = $scope.$injector.get('$http');\r\n settings = self.ctx.settings || {};\r\n $scope.settings = settings;\r\n $scope.isValidParameter = true;\r\n $scope.dataKeyDetected = false;\r\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-timeseries-required');\r\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\r\n\r\n if (self.ctx.datasources && self.ctx.datasources.length) {\r\n var datasource = self.ctx.datasources[0];\r\n if (datasource.type === types.datasourceType.entity) {\r\n if (datasource.entityType && datasource.entityId) {\r\n $scope.entityName = datasource.entityName;\r\n if (settings.widgetTitle && settings.widgetTitle.length) {\r\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\r\n } else {\r\n $scope.titleTemplate = self.ctx.widgetConfig.title;\r\n }\r\n\r\n $scope.entityDetected = true;\r\n }\r\n }\r\n if (datasource.dataKeys.length) {\r\n if (datasource.dataKeys[0].type != types.dataKeyType.timeseries) {\r\n $scope.isValidParameter = false;\r\n } else {\r\n $scope.currentKey = datasource.dataKeys[0].name;\r\n $scope.dataKeyType = datasource.dataKeys[0].type;\r\n $scope.dataKeyDetected = true;\r\n }\r\n }\r\n }\r\n\r\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\r\n\r\n $scope.updateAttribute = function () {\r\n if ($scope.entityDetected) {\r\n var datasource = self.ctx.datasources[0];\r\n\r\n saveEntityTimeseries(\r\n datasource.entityType,\r\n datasource.entityId,\r\n [\r\n {\r\n key: $scope.currentKey,\r\n value: $scope.currentValue\r\n }\r\n ]\r\n ).then(\r\n function success() {\r\n $scope.originalValue = $scope.currentValue;\r\n if (settings.showResultMessage) {\r\n toast.showSuccess($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n },\r\n function fail() {\r\n if (settings.showResultMessage) {\r\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n }\r\n );\r\n }\r\n };\r\n\r\n $scope.changeFocus = function () {\r\n if ($scope.currentValue === $scope.originalValue) {\r\n $scope.isFocused = false;\r\n }\r\n }\r\n\r\n function saveEntityTimeseries(entityType, entityId, telemetries) {\r\n var deferred = $q.defer();\r\n var telemetriesData = {};\r\n for (var a = 0; a < telemetries.length; a++) {\r\n if (angular.isDefined(telemetries[a].value) && telemetries[a].value !== null) {\r\n telemetriesData[telemetries[a].key] = telemetries[a].value;\r\n }\r\n }\r\n if (Object.keys(telemetriesData).length) {\r\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\r\n $http.post(url, telemetriesData).then(\r\n function(response) {\r\n deferred.resolve(response.data);\r\n },\r\n function() {\r\n deferred.reject();\r\n }\r\n );\r\n }\r\n return deferred.promise;\r\n }\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n try {\r\n if ($scope.dataKeyDetected) {\r\n if (!$scope.isFocused) {\r\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\r\n $scope.$digest();\r\n }\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n}\r\n\r\nself.onResize = function() {\r\n\r\n}\r\n\r\nself.typeParameters = function() {\r\n return {\r\n maxDatasources: 1,\r\n maxDataKeys: 1\r\n }\r\n}\r\n\r\nself.onDestroy = function() {\r\n\r\n}\r\n", | 240 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n maxlength=\"{{settings.maxLength}}\"\n minlength=\"{{settings.minLength}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
241 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
242 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.minLength(settings.minLength),\n $scope.validators.maxLength(settings.maxLength)]]}\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 !== \"timeseries\") {\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n let observable = saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n );\n if (observable) {\n observable.subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (typeof telemetries[a].value !== 'undefined' && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n return http.post(url, telemetriesData);\n }\n return null;\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue($scope.originalValue);\n self.ctx.detectChanges();\n }\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", | ||
243 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", | 243 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxLength\": {\n \"title\": \"Max length\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minLength\": {\n \"title\": \"Min length\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxLength\",\n \"minLength\"\n ]\n}", |
244 | "dataKeySettingsSchema": "{}\n", | 244 | "dataKeySettingsSchema": "{}\n", |
245 | "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 string timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 245 | "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 string timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -253,12 +253,12 @@ | @@ -253,12 +253,12 @@ | ||
253 | "sizeX": 7.5, | 253 | "sizeX": 7.5, |
254 | "sizeY": 3, | 254 | "sizeY": 3, |
255 | "resources": [], | 255 | "resources": [], |
256 | - "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=\"{{ 'widgets.input-widgets.switch-timeseries-value' | translate }}\"\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\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
257 | - "templateCss": ".attribute-update-form {\r\n overflow: hidden;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.entity-title {\r\n font-weight: bold;\r\n font-size: 22px;\r\n padding-top: 12px;\r\n padding-bottom: 6px;\r\n color: #666;\r\n}\r\n\r\n.attribute-update-form__grid {\r\n display: flex;\r\n}\r\n.grid__element:first-child {\r\n flex: 1;\r\n}\r\n\r\n.grid__element {\r\n display: flex;\r\n}\r\n\r\n.attribute-update-form .md-button.md-icon-button {\r\n margin: 0;\r\n}\r\n\r\n.attribute-update-form .md-button.md-icon-button {\r\n width: 32px;\r\n min-width: 32px;\r\n height: 32px;\r\n min-height: 32px;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n line-height: 20px;\r\n}\r\n\r\n.attribute-update-form .md-icon-button md-icon {\r\n width: 20px;\r\n min-width: 20px;\r\n height: 20px;\r\n min-height: 20px;\r\n font-size: 20px;\r\n}\r\n\r\n\r\nmd-toast{\r\n min-width: 0;\r\n}\r\nmd-toast .md-toast-content {\r\n font-size: 14px!important;\r\n}", | ||
258 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\nlet $q\nlet $http;\nlet map;\nlet mapReverse;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n $q = $scope.$injector.get('$q');\n $http = $scope.$injector.get('$http');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n\n settings.trueValue = utils.customTranslation(settings.trueValue, settings.trueValue) || true;\n settings.falseValue = utils.customTranslation(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 === types.datasourceType.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 != types.dataKeyType.timeseries) {\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 saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var deferred = $q.defer();\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (angular.isDefined(telemetries[a].value) && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n $http.post(url, telemetriesData).then(\n function(response) {\n deferred.resolve(response.data);\n },\n function() {\n deferred.reject();\n }\n );\n }\n return deferred.promise;\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 } 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", | 256 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-checkbox formControlName=\"checkboxValue\"\n (change)=\"changed()\"\n aria-label=\"{{'widgets.input-widgets.switch-timeseries-value' | translate}}\">\n {{currentValue}}\n </mat-checkbox>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\"\n [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
257 | + "templateCss": ".attribute-update-form {\r\n overflow: hidden;\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n\r\n.attribute-update-form__grid {\r\n display: flex;\r\n}\r\n.grid__element:first-child {\r\n flex: 1;\r\n}\r\n\r\n.grid__element {\r\n display: flex;\r\n}\r\n\r\n.attribute-update-form .mat-button.mat-icon-button {\r\n margin: 0;\r\n}\r\n\r\n.attribute-update-form .mat-button.mat-icon-button {\r\n width: 32px;\r\n min-width: 32px;\r\n height: 32px;\r\n min-height: 32px;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n line-height: 20px;\r\n}\r\n\r\n.attribute-update-form .mat-icon-button mat-icon {\r\n width: 20px;\r\n min-width: 20px;\r\n height: 20px;\r\n min-height: 20px;\r\n font-size: 20px;\r\n}\r\n\r\n.tb-toast {\r\n font-size: 14px!important;\r\n}", | ||
258 | + "controllerScript": "let settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\nlet $scope;\nlet map;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init();\n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n\n settings.trueValue = utils.defaultValue(utils.customTranslation(settings.trueValue, settings.trueValue), true);\n settings.falseValue = utils.defaultValue(utils.customTranslation(settings.falseValue, settings.falseValue), false);\n\n map = {\n true: settings.trueValue,\n false: settings.falseValue\n };\n \n $scope.checkboxValue = false;\n $scope.currentValue = map[$scope.checkboxValue];\n\n $scope.attributeUpdateFormGroup = $scope.fb.group({checkboxValue: [$scope.checkboxValue]});\n\n $scope.changed = function() {\n $scope.checkboxValue = $scope.attributeUpdateFormGroup.get('checkboxValue').value;\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 !== \"timeseries\") {\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 let observable = saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\n [{\n key: $scope.currentKey,\n value: $scope.checkboxValue\n }]\n );\n\n if (observable) {\n observable.subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('checkboxValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n }\n };\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (typeof telemetries[a].value !== 'undefined' && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n return http.post(url, telemetriesData);\n }\n return null;\n }\n}\n\nself.onDataUpdated = function() {\n try {\n $scope.checkboxValue = self.ctx.data[0].data[0][1] === 'true';\n $scope.currentValue = map[$scope.checkboxValue];\n $scope.attributeUpdateFormGroup.get('checkboxValue').patchValue($scope.checkboxValue);\n self.ctx.detectChanges();\n } catch (e) {\n console.log(e);\n }\n}\n\nself.onResize = function() {}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1\n }\n}\n\nself.onDestroy = function() {}", | ||
259 | "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}", | 259 | "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}", |
260 | "dataKeySettingsSchema": "{}\n", | 260 | "dataKeySettingsSchema": "{}\n", |
261 | - "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 boolean timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 261 | + "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 boolean timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
262 | } | 262 | } |
263 | }, | 263 | }, |
264 | { | 264 | { |
@@ -269,9 +269,9 @@ | @@ -269,9 +269,9 @@ | ||
269 | "sizeX": 7.5, | 269 | "sizeX": 7.5, |
270 | "sizeY": 3, | 270 | "sizeY": 3, |
271 | "resources": [], | 271 | "resources": [], |
272 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n step=\"any\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-timeseries' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
273 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
274 | - "controllerScript": "let $scope;\r\nlet settings;\r\nlet attributeService;\r\nlet toast;\r\nlet utils;\r\nlet types;\r\nlet $translate;\r\nlet $q;\r\nlet $http;\r\n\r\nself.onInit = function() {\r\n\r\n $scope = self.ctx.$scope;\r\n attributeService = $scope.$injector.get('attributeService');\r\n toast = $scope.$injector.get('toast');\r\n utils = $scope.$injector.get('utils');\r\n types = $scope.$injector.get('types');\r\n $translate = $scope.$injector.get('$translate');\r\n $q = $scope.$injector.get('$q');\r\n $http = $scope.$injector.get('$http');\r\n settings = angular.copy(self.ctx.settings) || {};\r\n $scope.settings = settings;\r\n $scope.isValidParameter = true;\r\n $scope.dataKeyDetected = false;\r\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-timeseries-required');\r\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\r\n\r\n if (self.ctx.datasources && self.ctx.datasources.length) {\r\n var datasource = self.ctx.datasources[0];\r\n if (datasource.type === types.datasourceType.entity) {\r\n if (datasource.entityType && datasource.entityId) {\r\n $scope.entityName = datasource.entityName;\r\n if (settings.widgetTitle && settings.widgetTitle.length) {\r\n $scope.titleTemplate = utils.customTranslation(settings.widgetTitle, settings.widgetTitle);\r\n } else {\r\n $scope.titleTemplate = self.ctx.widgetConfig.title;\r\n }\r\n\r\n $scope.entityDetected = true;\r\n }\r\n }\r\n if (datasource.dataKeys.length) {\r\n if (datasource.dataKeys[0].type != types.dataKeyType.timeseries) {\r\n $scope.isValidParameter = false;\r\n } else {\r\n $scope.currentKey = datasource.dataKeys[0].name;\r\n $scope.dataKeyType = datasource.dataKeys[0].type;\r\n $scope.dataKeyDetected = true;\r\n }\r\n }\r\n }\r\n\r\n self.ctx.widgetTitle = utils.createLabelFromDatasource(self.ctx.datasources[0], $scope.titleTemplate);\r\n\r\n $scope.updateAttribute = function () {\r\n if ($scope.entityDetected) {\r\n var datasource = self.ctx.datasources[0];\r\n\r\n saveEntityTimeseries(\r\n datasource.entityType,\r\n datasource.entityId,\r\n [\r\n {\r\n key: $scope.currentKey,\r\n value: $scope.currentValue\r\n }\r\n ]\r\n ).then(\r\n function success() {\r\n $scope.originalValue = $scope.currentValue;\r\n if (settings.showResultMessage) {\r\n toast.showSuccess($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n },\r\n function fail() {\r\n if (settings.showResultMessage) {\r\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\r\n }\r\n }\r\n );\r\n }\r\n };\r\n\r\n $scope.changeFocus = function () {\r\n if ($scope.currentValue === $scope.originalValue) {\r\n $scope.isFocused = false;\r\n }\r\n }\r\n\r\n function saveEntityTimeseries(entityType, entityId, telemetries) {\r\n var deferred = $q.defer();\r\n var telemetriesData = {};\r\n for (var a = 0; a < telemetries.length; a++) {\r\n if (angular.isDefined(telemetries[a].value) && telemetries[a].value !== null) {\r\n telemetriesData[telemetries[a].key] = telemetries[a].value;\r\n }\r\n }\r\n if (Object.keys(telemetriesData).length) {\r\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\r\n $http.post(url, telemetriesData).then(\r\n function(response) {\r\n deferred.resolve(response.data);\r\n },\r\n function() {\r\n deferred.reject();\r\n }\r\n );\r\n }\r\n return deferred.promise;\r\n }\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n\r\n try {\r\n if ($scope.dataKeyDetected) {\r\n if (!$scope.isFocused) {\r\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\r\n correctValue($scope.currentValue);\r\n $scope.$digest();\r\n }\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n }\r\n}\r\n\r\nfunction correctValue(value) {\r\n if (typeof value !== \"number\") {\r\n $scope.currentValue = 0;\r\n }\r\n}\r\n\r\nself.onResize = function() {\r\n\r\n}\r\n\r\nself.typeParameters = function() {\r\n return {\r\n maxDatasources: 1,\r\n maxDataKeys: 1\r\n }\r\n}\r\n\r\nself.onDestroy = function() {\r\n\r\n}\r\n", | 272 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n <form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n \n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n \n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n </form>\n</div>", |
273 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}", | ||
274 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue)]]}\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 !== \"timeseries\") {\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n let observable = saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n );\n if (observable) {\n observable.subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (typeof telemetries[a].value !== 'undefined' && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n return http.post(url, telemetriesData);\n }\n return null;\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n dataKeyOptional: true\n }\n}\n\nself.onDestroy = function() {\n\n}", | ||
275 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 275 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
276 | "dataKeySettingsSchema": "{}\n", | 276 | "dataKeySettingsSchema": "{}\n", |
277 | "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 double timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 277 | "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 double timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
@@ -285,9 +285,9 @@ | @@ -285,9 +285,9 @@ | ||
285 | "sizeX": 7.5, | 285 | "sizeX": 7.5, |
286 | "sizeY": 3, | 286 | "sizeY": 3, |
287 | "resources": [], | 287 | "resources": [], |
288 | - "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\n <div class=\"attribute-update-form__grid\" ng-show=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <md-input-container ng-class=\"{'show-label': settings.showLabel}\" class=\"md-block\" style=\"width: 100%;\">\n <label>{{labelValue}}</label>\n <input required\n name=\"attribute\"\n ng-model=\"currentValue\"\n ng-focus=\"isFocused = true\"\n ng-blur=\"changeFocus()\"\n type=\"number\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"\n >\n <div ng-messages=\"attrUpdateForm.attribute.$error\">\n <div ng-message=\"required\">{{requiredErrorMessage}}</div>\n </div>\n </md-input-container>\n </div>\n\n <div class=\"grid__element\">\n <md-button class=\"md-icon-button applyChanges\"\n aria-label=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n type=\"submit\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"isFocused = false\"\n >\n <md-icon>check</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.update-timeseries' | translate }}</md-tooltip>\n </md-button>\n <md-button class=\"md-icon-button discardChanges\"\n aria-label=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n ng-disabled=\"originalValue === currentValue\"\n ng-click=\"currentValue = originalValue; isFocused = false\"\n >\n <md-icon>close</md-icon>\n <md-tooltip md-direction=\"top\">{{ 'widgets.input-widgets.discard-changes' | translate }}</md-tooltip>\n </md-button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-hide=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" ng-show=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n</form>", | ||
289 | - "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.show-label label {\n display: block;\n}\n\nlabel {\n display: none;\n}\n\nmd-toast{\n min-width: 0;\n}\nmd-toast .md-toast-content {\n font-size: 14px!important;\n}", | ||
290 | - "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet toast;\nlet utils;\nlet types;\nlet $translate;\nlet $q;\nlet $http;\n\nself.onInit = function() {\n\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 $translate = $scope.$injector.get('$translate');\n $q = $scope.$injector.get('$q');\n $http = $scope.$injector.get('$http');\n settings = angular.copy(self.ctx.settings) || {};\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || $translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || $translate.instant('widgets.input-widgets.value');\n\n if (self.ctx.datasources && self.ctx.datasources.length) {\n var datasource = self.ctx.datasources[0];\n if (datasource.type === types.datasourceType.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 != types.dataKeyType.timeseries) {\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 saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\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($translate.instant('widgets.input-widgets.update-successful'), 1000, angular.element(self.ctx.$container), 'bottom left');\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n toast.showError($translate.instant('widgets.input-widgets.update-failed'), angular.element(self.ctx.$container), 'bottom left');\n }\n }\n );\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.currentValue === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var deferred = $q.defer();\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (angular.isDefined(telemetries[a].value) && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n $http.post(url, telemetriesData).then(\n function(response) {\n deferred.resolve(response.data);\n },\n function() {\n deferred.reject();\n }\n );\n }\n return deferred.promise;\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.currentValue = $scope.originalValue = self.ctx.data[0].data[0][1];\n correctValue($scope.currentValue);\n $scope.$digest();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n $scope.currentValue = 0;\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", | 288 | + "templateHtml": "<div tb-toast toastTarget=\"{{ toastTargetId }}\" style=\"width: 100%; height: 100%;\">\n<form *ngIf=\"attributeUpdateFormGroup\"\n class=\"attribute-update-form\"\n [formGroup]=\"attributeUpdateFormGroup\"\n (ngSubmit)=\"updateAttribute()\">\n <div style=\"padding: 0 8px; margin: auto 0;\">\n <div class=\"attribute-update-form__grid\" [fxShow]=\"entityDetected && isValidParameter && dataKeyDetected\">\n <div class=\"grid__element\">\n <mat-form-field class=\"mat-block\" style=\"width: 100%;\"\n floatLabel=\"{{settings.showLabel ? 'auto' : 'always'}}\"\n [hideRequiredMarker]=\"!settings.showLabel\">\n <mat-label>{{ settings.showLabel ? labelValue : '' }}</mat-label>\n <input matInput\n formControlName=\"currentValue\"\n required\n type=\"number\"\n step=\"1\"\n pattern=\"^-?[0-9]+$\"\n (focus)=\"isFocused = true\"\n (blur)=\"changeFocus()\"\n max=\"{{settings.maxValue}}\"\n min=\"{{settings.minValue}}\"/>\n <mat-error *ngIf=\"attributeUpdateFormGroup.get('currentValue').hasError('required')\">\n {{requiredErrorMessage}}\n </mat-error>\n </mat-form-field> \n </div>\n\n <div class=\"grid__element\">\n <button mat-button mat-icon-button class=\"applyChanges\"\n type=\"submit\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value || attributeUpdateFormGroup.invalid || !attributeUpdateFormGroup.dirty\"\n matTooltip=\"{{ 'widgets.input-widgets.update-timeseries' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>check</mat-icon>\n </button>\n <button mat-button mat-icon-button class=\"discardChanges\"\n type=\"button\"\n [disabled]=\"originalValue === attributeUpdateFormGroup.get('currentValue').value\"\n (click)=\"attributeUpdateFormGroup.get('currentValue').patchValue(originalValue); isFocused = false\"\n matTooltip=\"{{ 'widgets.input-widgets.discard-changes' | translate }}\"\n matTooltipPosition=\"above\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n </div>\n\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxHide]=\"entityDetected\">\n {{ 'widgets.input-widgets.no-entity-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !dataKeyDetected\">\n {{ 'widgets.input-widgets.no-timeseries-selected' | translate }}\n </div>\n <div style=\"text-align: center; font-size: 18px; color: #a0a0a0;\" [fxShow]=\"entityDetected && !isValidParameter\">\n {{ 'widgets.input-widgets.attribute-not-allowed' | translate }}\n </div>\n </div>\n</form>\n</div>", |
289 | + "templateCss": ".attribute-update-form {\n overflow: hidden;\n height: 100%;\n display: flex;\n flex-direction: column;\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 .mat-button.mat-icon-button {\n margin: 0;\n}\n\n.attribute-update-form .mat-button.mat-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 .mat-icon-button mat-icon {\n width: 20px;\n min-width: 20px;\n height: 20px;\n min-height: 20px;\n font-size: 20px;\n}\n\n.tb-toast {\n font-size: 14px!important;\n}\n", | ||
290 | + "controllerScript": "let $scope;\nlet settings;\nlet attributeService;\nlet utils;\nlet translate;\nlet http;\n\nself.onInit = function() {\n self.ctx.ngZone.run(function() {\n init(); \n self.ctx.detectChanges(true);\n });\n};\n\n\nfunction init() {\n\n $scope = self.ctx.$scope;\n attributeService = $scope.$injector.get(self.ctx.servicesMap.get('attributeService'));\n utils = $scope.$injector.get(self.ctx.servicesMap.get('utils'));\n translate = $scope.$injector.get(self.ctx.servicesMap.get('translate'));\n http = $scope.$injector.get(self.ctx.servicesMap.get('http'));\n $scope.toastTargetId = 'input-widget' + utils.guid();\n settings = utils.deepClone(self.ctx.settings) || {};\n settings.showLabel = utils.defaultValue(settings.showLabel, true);\n settings.showResultMessage = utils.defaultValue(settings.showResultMessage, true);\n $scope.settings = settings;\n $scope.isValidParameter = true;\n $scope.dataKeyDetected = false;\n $scope.requiredErrorMessage = utils.customTranslation(settings.requiredErrorMessage, settings.requiredErrorMessage) || translate.instant('widgets.input-widgets.entity-timeseries-required');\n $scope.labelValue = utils.customTranslation(settings.labelValue, settings.labelValue) || translate.instant('widgets.input-widgets.value');\n\n $scope.attributeUpdateFormGroup = $scope.fb.group(\n {currentValue: [undefined, [$scope.validators.required,\n $scope.validators.min(settings.minValue),\n $scope.validators.max(settings.maxValue),\n $scope.validators.pattern(/^-?[0-9]+$/)]]}\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 !== \"timeseries\") {\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 $scope.isFocused = false;\n if ($scope.entityDetected) {\n var datasource = self.ctx.datasources[0];\n\n let observable = saveEntityTimeseries(\n datasource.entityType,\n datasource.entityId,\n [\n {\n key: $scope.currentKey,\n value: $scope.attributeUpdateFormGroup.get('currentValue').value\n }\n ]\n );\n if (observable) {\n observable.subscribe(\n function success() {\n $scope.originalValue = $scope.attributeUpdateFormGroup.get('currentValue').value;\n if (settings.showResultMessage) {\n $scope.showSuccessToast(translate.instant('widgets.input-widgets.update-successful'), 1000, 'bottom', 'left', $scope.toastTargetId);\n }\n },\n function fail() {\n if (settings.showResultMessage) {\n $scope.showErrorToast(translate.instant('widgets.input-widgets.update-failed'), 'bottom', 'left', $scope.toastTargetId);\n }\n }\n );\n }\n }\n };\n\n $scope.changeFocus = function () {\n if ($scope.attributeUpdateFormGroup.get('currentValue').value === $scope.originalValue) {\n $scope.isFocused = false;\n }\n }\n\n function saveEntityTimeseries(entityType, entityId, telemetries) {\n var telemetriesData = {};\n for (var a = 0; a < telemetries.length; a++) {\n if (typeof telemetries[a].value !== 'undefined' && telemetries[a].value !== null) {\n telemetriesData[telemetries[a].key] = telemetries[a].value;\n }\n }\n if (Object.keys(telemetriesData).length) {\n var url = '/api/plugins/telemetry/' + entityType + '/' + entityId + '/timeseries/scope';\n return http.post(url, telemetriesData);\n }\n return null;\n }\n}\n\nself.onDataUpdated = function() {\n\n try {\n if ($scope.dataKeyDetected) {\n if (!$scope.isFocused) {\n $scope.originalValue = self.ctx.data[0].data[0][1];\n $scope.attributeUpdateFormGroup.get('currentValue').patchValue(correctValue($scope.originalValue));\n self.ctx.detectChanges();\n }\n }\n } catch (e) {\n console.log(e);\n }\n}\n\nfunction correctValue(value) {\n if (typeof value !== \"number\") {\n return 0;\n }\n return value;\n}\n\nself.onResize = function() {\n\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\n maxDataKeys: 1,\n dataKeyOptional: true\n }\n}\n\nself.onDestroy = function() {\n\n}\n", | ||
291 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", | 291 | "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"EntitiesTableSettings\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showLabel\":{\n \"title\":\"Show label\",\n \"type\":\"boolean\",\n \"default\":true\n },\n \"labelValue\": {\n \"title\": \"Label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValue\": {\n \"title\": \"Max value\",\n \"type\": \"number\",\n \"default\": \"\"\n },\n \"minValue\": {\n \"title\": \"Min value\",\n \"type\": \"number\",\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 \"showLabel\",\n \"labelValue\",\n \"requiredErrorMessage\",\n \"maxValue\",\n \"minValue\"\n ]\n}", |
292 | "dataKeySettingsSchema": "{}\n", | 292 | "dataKeySettingsSchema": "{}\n", |
293 | "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 integer timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | 293 | "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 integer timeseries\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
application/src/main/java/org/thingsboard/server/actors/shared/rulechain/SystemRuleChainManager.java
@@ -18,8 +18,8 @@ package org.thingsboard.server.actors.shared.rulechain; | @@ -18,8 +18,8 @@ package org.thingsboard.server.actors.shared.rulechain; | ||
18 | import org.thingsboard.server.actors.ActorSystemContext; | 18 | import org.thingsboard.server.actors.ActorSystemContext; |
19 | import org.thingsboard.server.actors.service.DefaultActorService; | 19 | import org.thingsboard.server.actors.service.DefaultActorService; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
21 | +import org.thingsboard.server.common.data.page.PageData; | ||
21 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; | 22 | import org.thingsboard.server.common.data.page.PageDataIterable.FetchFunction; |
22 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
23 | import org.thingsboard.server.common.data.rule.RuleChain; | 23 | import org.thingsboard.server.common.data.rule.RuleChain; |
24 | import org.thingsboard.server.dao.model.ModelConstants; | 24 | import org.thingsboard.server.dao.model.ModelConstants; |
25 | 25 | ||
@@ -33,7 +33,7 @@ public class SystemRuleChainManager extends RuleChainManager { | @@ -33,7 +33,7 @@ public class SystemRuleChainManager extends RuleChainManager { | ||
33 | 33 | ||
34 | @Override | 34 | @Override |
35 | protected FetchFunction<RuleChain> getFetchEntitiesFunction() { | 35 | protected FetchFunction<RuleChain> getFetchEntitiesFunction() { |
36 | - return link -> new TextPageData<>(Collections.emptyList(), link); | 36 | + return link -> new PageData<>(); |
37 | } | 37 | } |
38 | 38 | ||
39 | @Override | 39 | @Override |
@@ -68,7 +68,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | @@ -68,7 +68,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | ||
68 | public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; | 68 | public static final String FORM_BASED_LOGIN_ENTRY_POINT = "/api/auth/login"; |
69 | public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; | 69 | public static final String PUBLIC_LOGIN_ENTRY_POINT = "/api/auth/login/public"; |
70 | public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; | 70 | public static final String TOKEN_REFRESH_ENTRY_POINT = "/api/auth/token"; |
71 | - protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/static/**", "/api/noauth/**", "/webjars/**"}; | 71 | + protected static final String[] NON_TOKEN_BASED_AUTH_ENTRY_POINTS = new String[] {"/index.html", "/assets/**", "/static/**", "/api/noauth/**", "/webjars/**"}; |
72 | public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; | 72 | public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/api/**"; |
73 | public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; | 73 | public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**"; |
74 | 74 | ||
@@ -155,7 +155,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | @@ -155,7 +155,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt | ||
155 | 155 | ||
156 | @Override | 156 | @Override |
157 | public void configure(WebSecurity web) throws Exception { | 157 | public void configure(WebSecurity web) throws Exception { |
158 | - web.ignoring().antMatchers("/static/**"); | 158 | + web.ignoring().antMatchers("/*.js","/*.css","/*.ico","/assets/**","/static/**"); |
159 | } | 159 | } |
160 | 160 | ||
161 | @Override | 161 | @Override |
@@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -21,7 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
21 | @Controller | 21 | @Controller |
22 | public class WebConfig { | 22 | public class WebConfig { |
23 | 23 | ||
24 | - @RequestMapping(value = "/{path:^(?!api$)(?!static$)(?!webjars$)[^\\.]*}/**") | 24 | + @RequestMapping(value = "/{path:^(?!api$)(?!assets$)(?!static$)(?!webjars$)[^\\.]*}/**") |
25 | public String redirect() { | 25 | public String redirect() { |
26 | return "forward:/index.html"; | 26 | return "forward:/index.html"; |
27 | } | 27 | } |
@@ -39,7 +39,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | @@ -39,7 +39,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | ||
39 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 39 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
40 | import org.thingsboard.server.common.data.id.EntityId; | 40 | import org.thingsboard.server.common.data.id.EntityId; |
41 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 41 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
42 | -import org.thingsboard.server.common.data.page.TimePageData; | 42 | +import org.thingsboard.server.common.data.page.PageData; |
43 | import org.thingsboard.server.common.data.page.TimePageLink; | 43 | import org.thingsboard.server.common.data.page.TimePageLink; |
44 | import org.thingsboard.server.service.security.permission.Operation; | 44 | import org.thingsboard.server.service.security.permission.Operation; |
45 | import org.thingsboard.server.service.security.permission.Resource; | 45 | import org.thingsboard.server.service.security.permission.Resource; |
@@ -143,16 +143,18 @@ public class AlarmController extends BaseController { | @@ -143,16 +143,18 @@ public class AlarmController extends BaseController { | ||
143 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 143 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
144 | @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) | 144 | @RequestMapping(value = "/alarm/{entityType}/{entityId}", method = RequestMethod.GET) |
145 | @ResponseBody | 145 | @ResponseBody |
146 | - public TimePageData<AlarmInfo> getAlarms( | 146 | + public PageData<AlarmInfo> getAlarms( |
147 | @PathVariable("entityType") String strEntityType, | 147 | @PathVariable("entityType") String strEntityType, |
148 | @PathVariable("entityId") String strEntityId, | 148 | @PathVariable("entityId") String strEntityId, |
149 | @RequestParam(required = false) String searchStatus, | 149 | @RequestParam(required = false) String searchStatus, |
150 | @RequestParam(required = false) String status, | 150 | @RequestParam(required = false) String status, |
151 | - @RequestParam int limit, | 151 | + @RequestParam int pageSize, |
152 | + @RequestParam int page, | ||
153 | + @RequestParam(required = false) String textSearch, | ||
154 | + @RequestParam(required = false) String sortProperty, | ||
155 | + @RequestParam(required = false) String sortOrder, | ||
152 | @RequestParam(required = false) Long startTime, | 156 | @RequestParam(required = false) Long startTime, |
153 | @RequestParam(required = false) Long endTime, | 157 | @RequestParam(required = false) Long endTime, |
154 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
155 | - @RequestParam(required = false) String offset, | ||
156 | @RequestParam(required = false) Boolean fetchOriginator | 158 | @RequestParam(required = false) Boolean fetchOriginator |
157 | ) throws ThingsboardException { | 159 | ) throws ThingsboardException { |
158 | checkParameter("EntityId", strEntityId); | 160 | checkParameter("EntityId", strEntityId); |
@@ -165,8 +167,8 @@ public class AlarmController extends BaseController { | @@ -165,8 +167,8 @@ public class AlarmController extends BaseController { | ||
165 | "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | 167 | "and 'status' can't be specified at the same time!", ThingsboardErrorCode.BAD_REQUEST_PARAMS); |
166 | } | 168 | } |
167 | checkEntityId(entityId, Operation.READ); | 169 | checkEntityId(entityId, Operation.READ); |
170 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | ||
168 | try { | 171 | try { |
169 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | ||
170 | return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); | 172 | return checkNotNull(alarmService.findAlarms(getCurrentUser().getTenantId(), new AlarmQuery(entityId, pageLink, alarmSearchStatus, alarmStatus, fetchOriginator)).get()); |
171 | } catch (Exception e) { | 173 | } catch (Exception e) { |
172 | throw handleException(e); | 174 | throw handleException(e); |
@@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.Customer; | @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.Customer; | ||
30 | import org.thingsboard.server.common.data.EntitySubtype; | 30 | import org.thingsboard.server.common.data.EntitySubtype; |
31 | import org.thingsboard.server.common.data.EntityType; | 31 | import org.thingsboard.server.common.data.EntityType; |
32 | import org.thingsboard.server.common.data.asset.Asset; | 32 | import org.thingsboard.server.common.data.asset.Asset; |
33 | +import org.thingsboard.server.common.data.asset.AssetInfo; | ||
33 | import org.thingsboard.server.common.data.asset.AssetSearchQuery; | 34 | import org.thingsboard.server.common.data.asset.AssetSearchQuery; |
34 | import org.thingsboard.server.common.data.audit.ActionType; | 35 | import org.thingsboard.server.common.data.audit.ActionType; |
35 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 36 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
@@ -37,8 +38,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -37,8 +38,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
37 | import org.thingsboard.server.common.data.id.AssetId; | 38 | import org.thingsboard.server.common.data.id.AssetId; |
38 | import org.thingsboard.server.common.data.id.CustomerId; | 39 | import org.thingsboard.server.common.data.id.CustomerId; |
39 | import org.thingsboard.server.common.data.id.TenantId; | 40 | import org.thingsboard.server.common.data.id.TenantId; |
40 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
41 | -import org.thingsboard.server.common.data.page.TextPageLink; | 41 | +import org.thingsboard.server.common.data.page.PageData; |
42 | +import org.thingsboard.server.common.data.page.PageLink; | ||
42 | import org.thingsboard.server.common.data.security.Authority; | 43 | import org.thingsboard.server.common.data.security.Authority; |
43 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 44 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
44 | import org.thingsboard.server.dao.model.ModelConstants; | 45 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -70,6 +71,19 @@ public class AssetController extends BaseController { | @@ -70,6 +71,19 @@ public class AssetController extends BaseController { | ||
70 | } | 71 | } |
71 | 72 | ||
72 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 73 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
74 | + @RequestMapping(value = "/asset/info/{assetId}", method = RequestMethod.GET) | ||
75 | + @ResponseBody | ||
76 | + public AssetInfo getAssetInfoById(@PathVariable(ASSET_ID) String strAssetId) throws ThingsboardException { | ||
77 | + checkParameter(ASSET_ID, strAssetId); | ||
78 | + try { | ||
79 | + AssetId assetId = new AssetId(toUUID(strAssetId)); | ||
80 | + return checkAssetInfoId(assetId, Operation.READ); | ||
81 | + } catch (Exception e) { | ||
82 | + throw handleException(e); | ||
83 | + } | ||
84 | + } | ||
85 | + | ||
86 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
73 | @RequestMapping(value = "/asset", method = RequestMethod.POST) | 87 | @RequestMapping(value = "/asset", method = RequestMethod.POST) |
74 | @ResponseBody | 88 | @ResponseBody |
75 | public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException { | 89 | public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException { |
@@ -207,17 +221,18 @@ public class AssetController extends BaseController { | @@ -207,17 +221,18 @@ public class AssetController extends BaseController { | ||
207 | } | 221 | } |
208 | 222 | ||
209 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 223 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
210 | - @RequestMapping(value = "/tenant/assets", params = {"limit"}, method = RequestMethod.GET) | 224 | + @RequestMapping(value = "/tenant/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) |
211 | @ResponseBody | 225 | @ResponseBody |
212 | - public TextPageData<Asset> getTenantAssets( | ||
213 | - @RequestParam int limit, | 226 | + public PageData<Asset> getTenantAssets( |
227 | + @RequestParam int pageSize, | ||
228 | + @RequestParam int page, | ||
214 | @RequestParam(required = false) String type, | 229 | @RequestParam(required = false) String type, |
215 | @RequestParam(required = false) String textSearch, | 230 | @RequestParam(required = false) String textSearch, |
216 | - @RequestParam(required = false) String idOffset, | ||
217 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 231 | + @RequestParam(required = false) String sortProperty, |
232 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
218 | try { | 233 | try { |
219 | TenantId tenantId = getCurrentUser().getTenantId(); | 234 | TenantId tenantId = getCurrentUser().getTenantId(); |
220 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 235 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
221 | if (type != null && type.trim().length()>0) { | 236 | if (type != null && type.trim().length()>0) { |
222 | return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); | 237 | return checkNotNull(assetService.findAssetsByTenantIdAndType(tenantId, type, pageLink)); |
223 | } else { | 238 | } else { |
@@ -229,6 +244,29 @@ public class AssetController extends BaseController { | @@ -229,6 +244,29 @@ public class AssetController extends BaseController { | ||
229 | } | 244 | } |
230 | 245 | ||
231 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 246 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
247 | + @RequestMapping(value = "/tenant/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
248 | + @ResponseBody | ||
249 | + public PageData<AssetInfo> getTenantAssetInfos( | ||
250 | + @RequestParam int pageSize, | ||
251 | + @RequestParam int page, | ||
252 | + @RequestParam(required = false) String type, | ||
253 | + @RequestParam(required = false) String textSearch, | ||
254 | + @RequestParam(required = false) String sortProperty, | ||
255 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
256 | + try { | ||
257 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
258 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
259 | + if (type != null && type.trim().length() > 0) { | ||
260 | + return checkNotNull(assetService.findAssetInfosByTenantIdAndType(tenantId, type, pageLink)); | ||
261 | + } else { | ||
262 | + return checkNotNull(assetService.findAssetInfosByTenantId(tenantId, pageLink)); | ||
263 | + } | ||
264 | + } catch (Exception e) { | ||
265 | + throw handleException(e); | ||
266 | + } | ||
267 | + } | ||
268 | + | ||
269 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
232 | @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) | 270 | @RequestMapping(value = "/tenant/assets", params = {"assetName"}, method = RequestMethod.GET) |
233 | @ResponseBody | 271 | @ResponseBody |
234 | public Asset getTenantAsset( | 272 | public Asset getTenantAsset( |
@@ -242,21 +280,22 @@ public class AssetController extends BaseController { | @@ -242,21 +280,22 @@ public class AssetController extends BaseController { | ||
242 | } | 280 | } |
243 | 281 | ||
244 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 282 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
245 | - @RequestMapping(value = "/customer/{customerId}/assets", params = {"limit"}, method = RequestMethod.GET) | 283 | + @RequestMapping(value = "/customer/{customerId}/assets", params = {"pageSize", "page"}, method = RequestMethod.GET) |
246 | @ResponseBody | 284 | @ResponseBody |
247 | - public TextPageData<Asset> getCustomerAssets( | 285 | + public PageData<Asset> getCustomerAssets( |
248 | @PathVariable("customerId") String strCustomerId, | 286 | @PathVariable("customerId") String strCustomerId, |
249 | - @RequestParam int limit, | 287 | + @RequestParam int pageSize, |
288 | + @RequestParam int page, | ||
250 | @RequestParam(required = false) String type, | 289 | @RequestParam(required = false) String type, |
251 | @RequestParam(required = false) String textSearch, | 290 | @RequestParam(required = false) String textSearch, |
252 | - @RequestParam(required = false) String idOffset, | ||
253 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 291 | + @RequestParam(required = false) String sortProperty, |
292 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
254 | checkParameter("customerId", strCustomerId); | 293 | checkParameter("customerId", strCustomerId); |
255 | try { | 294 | try { |
256 | TenantId tenantId = getCurrentUser().getTenantId(); | 295 | TenantId tenantId = getCurrentUser().getTenantId(); |
257 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 296 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
258 | checkCustomerId(customerId, Operation.READ); | 297 | checkCustomerId(customerId, Operation.READ); |
259 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 298 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
260 | if (type != null && type.trim().length()>0) { | 299 | if (type != null && type.trim().length()>0) { |
261 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | 300 | return checkNotNull(assetService.findAssetsByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); |
262 | } else { | 301 | } else { |
@@ -268,6 +307,33 @@ public class AssetController extends BaseController { | @@ -268,6 +307,33 @@ public class AssetController extends BaseController { | ||
268 | } | 307 | } |
269 | 308 | ||
270 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 309 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
310 | + @RequestMapping(value = "/customer/{customerId}/assetInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
311 | + @ResponseBody | ||
312 | + public PageData<AssetInfo> getCustomerAssetInfos( | ||
313 | + @PathVariable("customerId") String strCustomerId, | ||
314 | + @RequestParam int pageSize, | ||
315 | + @RequestParam int page, | ||
316 | + @RequestParam(required = false) String type, | ||
317 | + @RequestParam(required = false) String textSearch, | ||
318 | + @RequestParam(required = false) String sortProperty, | ||
319 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
320 | + checkParameter("customerId", strCustomerId); | ||
321 | + try { | ||
322 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
323 | + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | ||
324 | + checkCustomerId(customerId, Operation.READ); | ||
325 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
326 | + if (type != null && type.trim().length() > 0) { | ||
327 | + return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | ||
328 | + } else { | ||
329 | + return checkNotNull(assetService.findAssetInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
330 | + } | ||
331 | + } catch (Exception e) { | ||
332 | + throw handleException(e); | ||
333 | + } | ||
334 | + } | ||
335 | + | ||
336 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
271 | @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) | 337 | @RequestMapping(value = "/assets", params = {"assetIds"}, method = RequestMethod.GET) |
272 | @ResponseBody | 338 | @ResponseBody |
273 | public List<Asset> getAssetsByIds( | 339 | public List<Asset> getAssetsByIds( |
@@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -30,7 +30,7 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
30 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 30 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
31 | import org.thingsboard.server.common.data.id.TenantId; | 31 | import org.thingsboard.server.common.data.id.TenantId; |
32 | import org.thingsboard.server.common.data.id.UserId; | 32 | import org.thingsboard.server.common.data.id.UserId; |
33 | -import org.thingsboard.server.common.data.page.TimePageData; | 33 | +import org.thingsboard.server.common.data.page.PageData; |
34 | import org.thingsboard.server.common.data.page.TimePageLink; | 34 | import org.thingsboard.server.common.data.page.TimePageLink; |
35 | 35 | ||
36 | import java.util.Arrays; | 36 | import java.util.Arrays; |
@@ -43,20 +43,22 @@ import java.util.stream.Collectors; | @@ -43,20 +43,22 @@ import java.util.stream.Collectors; | ||
43 | public class AuditLogController extends BaseController { | 43 | public class AuditLogController extends BaseController { |
44 | 44 | ||
45 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 45 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
46 | - @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"limit"}, method = RequestMethod.GET) | 46 | + @RequestMapping(value = "/audit/logs/customer/{customerId}", params = {"pageSize", "page"}, method = RequestMethod.GET) |
47 | @ResponseBody | 47 | @ResponseBody |
48 | - public TimePageData<AuditLog> getAuditLogsByCustomerId( | 48 | + public PageData<AuditLog> getAuditLogsByCustomerId( |
49 | @PathVariable("customerId") String strCustomerId, | 49 | @PathVariable("customerId") String strCustomerId, |
50 | - @RequestParam int limit, | 50 | + @RequestParam int pageSize, |
51 | + @RequestParam int page, | ||
52 | + @RequestParam(required = false) String textSearch, | ||
53 | + @RequestParam(required = false) String sortProperty, | ||
54 | + @RequestParam(required = false) String sortOrder, | ||
51 | @RequestParam(required = false) Long startTime, | 55 | @RequestParam(required = false) Long startTime, |
52 | @RequestParam(required = false) Long endTime, | 56 | @RequestParam(required = false) Long endTime, |
53 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
54 | - @RequestParam(required = false) String offset, | ||
55 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { | 57 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { |
56 | try { | 58 | try { |
57 | checkParameter("CustomerId", strCustomerId); | 59 | checkParameter("CustomerId", strCustomerId); |
58 | TenantId tenantId = getCurrentUser().getTenantId(); | 60 | TenantId tenantId = getCurrentUser().getTenantId(); |
59 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | 61 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); |
60 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); | 62 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); |
61 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), actionTypes, pageLink)); | 63 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndCustomerId(tenantId, new CustomerId(UUID.fromString(strCustomerId)), actionTypes, pageLink)); |
62 | } catch (Exception e) { | 64 | } catch (Exception e) { |
@@ -65,20 +67,22 @@ public class AuditLogController extends BaseController { | @@ -65,20 +67,22 @@ public class AuditLogController extends BaseController { | ||
65 | } | 67 | } |
66 | 68 | ||
67 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 69 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
68 | - @RequestMapping(value = "/audit/logs/user/{userId}", params = {"limit"}, method = RequestMethod.GET) | 70 | + @RequestMapping(value = "/audit/logs/user/{userId}", params = {"pageSize", "page"}, method = RequestMethod.GET) |
69 | @ResponseBody | 71 | @ResponseBody |
70 | - public TimePageData<AuditLog> getAuditLogsByUserId( | 72 | + public PageData<AuditLog> getAuditLogsByUserId( |
71 | @PathVariable("userId") String strUserId, | 73 | @PathVariable("userId") String strUserId, |
72 | - @RequestParam int limit, | 74 | + @RequestParam int pageSize, |
75 | + @RequestParam int page, | ||
76 | + @RequestParam(required = false) String textSearch, | ||
77 | + @RequestParam(required = false) String sortProperty, | ||
78 | + @RequestParam(required = false) String sortOrder, | ||
73 | @RequestParam(required = false) Long startTime, | 79 | @RequestParam(required = false) Long startTime, |
74 | @RequestParam(required = false) Long endTime, | 80 | @RequestParam(required = false) Long endTime, |
75 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
76 | - @RequestParam(required = false) String offset, | ||
77 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { | 81 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { |
78 | try { | 82 | try { |
79 | checkParameter("UserId", strUserId); | 83 | checkParameter("UserId", strUserId); |
80 | TenantId tenantId = getCurrentUser().getTenantId(); | 84 | TenantId tenantId = getCurrentUser().getTenantId(); |
81 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | 85 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); |
82 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); | 86 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); |
83 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), actionTypes, pageLink)); | 87 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndUserId(tenantId, new UserId(UUID.fromString(strUserId)), actionTypes, pageLink)); |
84 | } catch (Exception e) { | 88 | } catch (Exception e) { |
@@ -87,22 +91,24 @@ public class AuditLogController extends BaseController { | @@ -87,22 +91,24 @@ public class AuditLogController extends BaseController { | ||
87 | } | 91 | } |
88 | 92 | ||
89 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 93 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
90 | - @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"limit"}, method = RequestMethod.GET) | 94 | + @RequestMapping(value = "/audit/logs/entity/{entityType}/{entityId}", params = {"pageSize", "page"}, method = RequestMethod.GET) |
91 | @ResponseBody | 95 | @ResponseBody |
92 | - public TimePageData<AuditLog> getAuditLogsByEntityId( | 96 | + public PageData<AuditLog> getAuditLogsByEntityId( |
93 | @PathVariable("entityType") String strEntityType, | 97 | @PathVariable("entityType") String strEntityType, |
94 | @PathVariable("entityId") String strEntityId, | 98 | @PathVariable("entityId") String strEntityId, |
95 | - @RequestParam int limit, | 99 | + @RequestParam int pageSize, |
100 | + @RequestParam int page, | ||
101 | + @RequestParam(required = false) String textSearch, | ||
102 | + @RequestParam(required = false) String sortProperty, | ||
103 | + @RequestParam(required = false) String sortOrder, | ||
96 | @RequestParam(required = false) Long startTime, | 104 | @RequestParam(required = false) Long startTime, |
97 | @RequestParam(required = false) Long endTime, | 105 | @RequestParam(required = false) Long endTime, |
98 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
99 | - @RequestParam(required = false) String offset, | ||
100 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { | 106 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { |
101 | try { | 107 | try { |
102 | checkParameter("EntityId", strEntityId); | 108 | checkParameter("EntityId", strEntityId); |
103 | checkParameter("EntityType", strEntityType); | 109 | checkParameter("EntityType", strEntityType); |
104 | TenantId tenantId = getCurrentUser().getTenantId(); | 110 | TenantId tenantId = getCurrentUser().getTenantId(); |
105 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | 111 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); |
106 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); | 112 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); |
107 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), actionTypes, pageLink)); | 113 | return checkNotNull(auditLogService.findAuditLogsByTenantIdAndEntityId(tenantId, EntityIdFactory.getByTypeAndId(strEntityType, strEntityId), actionTypes, pageLink)); |
108 | } catch (Exception e) { | 114 | } catch (Exception e) { |
@@ -111,19 +117,21 @@ public class AuditLogController extends BaseController { | @@ -111,19 +117,21 @@ public class AuditLogController extends BaseController { | ||
111 | } | 117 | } |
112 | 118 | ||
113 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 119 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
114 | - @RequestMapping(value = "/audit/logs", params = {"limit"}, method = RequestMethod.GET) | 120 | + @RequestMapping(value = "/audit/logs", params = {"pageSize", "page"}, method = RequestMethod.GET) |
115 | @ResponseBody | 121 | @ResponseBody |
116 | - public TimePageData<AuditLog> getAuditLogs( | ||
117 | - @RequestParam int limit, | 122 | + public PageData<AuditLog> getAuditLogs( |
123 | + @RequestParam int pageSize, | ||
124 | + @RequestParam int page, | ||
125 | + @RequestParam(required = false) String textSearch, | ||
126 | + @RequestParam(required = false) String sortProperty, | ||
127 | + @RequestParam(required = false) String sortOrder, | ||
118 | @RequestParam(required = false) Long startTime, | 128 | @RequestParam(required = false) Long startTime, |
119 | @RequestParam(required = false) Long endTime, | 129 | @RequestParam(required = false) Long endTime, |
120 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
121 | - @RequestParam(required = false) String offset, | ||
122 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { | 130 | @RequestParam(name = "actionTypes", required = false) String actionTypesStr) throws ThingsboardException { |
123 | try { | 131 | try { |
124 | TenantId tenantId = getCurrentUser().getTenantId(); | 132 | TenantId tenantId = getCurrentUser().getTenantId(); |
125 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | ||
126 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); | 133 | List<ActionType> actionTypes = parseActionTypesStr(actionTypesStr); |
134 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); | ||
127 | return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, actionTypes, pageLink)); | 135 | return checkNotNull(auditLogService.findAuditLogsByTenantId(tenantId, actionTypes, pageLink)); |
128 | } catch (Exception e) { | 136 | } catch (Exception e) { |
129 | throw handleException(e); | 137 | throw handleException(e); |
@@ -28,20 +28,12 @@ import org.springframework.security.core.Authentication; | @@ -28,20 +28,12 @@ import org.springframework.security.core.Authentication; | ||
28 | import org.springframework.security.core.context.SecurityContextHolder; | 28 | import org.springframework.security.core.context.SecurityContextHolder; |
29 | import org.springframework.web.bind.annotation.ExceptionHandler; | 29 | import org.springframework.web.bind.annotation.ExceptionHandler; |
30 | import org.thingsboard.server.actors.service.ActorService; | 30 | import org.thingsboard.server.actors.service.ActorService; |
31 | -import org.thingsboard.server.common.data.Customer; | ||
32 | -import org.thingsboard.server.common.data.Dashboard; | ||
33 | -import org.thingsboard.server.common.data.DashboardInfo; | ||
34 | -import org.thingsboard.server.common.data.DataConstants; | ||
35 | -import org.thingsboard.server.common.data.Device; | ||
36 | -import org.thingsboard.server.common.data.EntityType; | ||
37 | -import org.thingsboard.server.common.data.EntityView; | ||
38 | -import org.thingsboard.server.common.data.HasName; | ||
39 | -import org.thingsboard.server.common.data.Tenant; | ||
40 | -import org.thingsboard.server.common.data.User; | 31 | +import org.thingsboard.server.common.data.*; |
41 | import org.thingsboard.server.common.data.alarm.Alarm; | 32 | import org.thingsboard.server.common.data.alarm.Alarm; |
42 | import org.thingsboard.server.common.data.alarm.AlarmId; | 33 | import org.thingsboard.server.common.data.alarm.AlarmId; |
43 | import org.thingsboard.server.common.data.alarm.AlarmInfo; | 34 | import org.thingsboard.server.common.data.alarm.AlarmInfo; |
44 | import org.thingsboard.server.common.data.asset.Asset; | 35 | import org.thingsboard.server.common.data.asset.Asset; |
36 | +import org.thingsboard.server.common.data.asset.AssetInfo; | ||
45 | import org.thingsboard.server.common.data.audit.ActionType; | 37 | import org.thingsboard.server.common.data.audit.ActionType; |
46 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; | 38 | import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; |
47 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 39 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
@@ -60,7 +52,8 @@ import org.thingsboard.server.common.data.id.WidgetTypeId; | @@ -60,7 +52,8 @@ import org.thingsboard.server.common.data.id.WidgetTypeId; | ||
60 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 52 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
61 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 53 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
62 | import org.thingsboard.server.common.data.kv.DataType; | 54 | import org.thingsboard.server.common.data.kv.DataType; |
63 | -import org.thingsboard.server.common.data.page.TextPageLink; | 55 | +import org.thingsboard.server.common.data.page.PageLink; |
56 | +import org.thingsboard.server.common.data.page.SortOrder; | ||
64 | import org.thingsboard.server.common.data.page.TimePageLink; | 57 | import org.thingsboard.server.common.data.page.TimePageLink; |
65 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | 58 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
66 | import org.thingsboard.server.common.data.plugin.ComponentType; | 59 | import org.thingsboard.server.common.data.plugin.ComponentType; |
@@ -256,21 +249,27 @@ public abstract class BaseController { | @@ -256,21 +249,27 @@ public abstract class BaseController { | ||
256 | return UUID.fromString(id); | 249 | return UUID.fromString(id); |
257 | } | 250 | } |
258 | 251 | ||
259 | - TimePageLink createPageLink(int limit, Long startTime, Long endTime, boolean ascOrder, String idOffset) { | ||
260 | - UUID idOffsetUuid = null; | ||
261 | - if (StringUtils.isNotEmpty(idOffset)) { | ||
262 | - idOffsetUuid = toUUID(idOffset); | 252 | + PageLink createPageLink(int pageSize, int page, String textSearch, String sortProperty, String sortOrder) throws ThingsboardException { |
253 | + if (!StringUtils.isEmpty(sortProperty)) { | ||
254 | + SortOrder.Direction direction = SortOrder.Direction.ASC; | ||
255 | + if (!StringUtils.isEmpty(sortOrder)) { | ||
256 | + try { | ||
257 | + direction = SortOrder.Direction.valueOf(sortOrder.toUpperCase()); | ||
258 | + } catch (IllegalArgumentException e) { | ||
259 | + throw new ThingsboardException("Unsupported sort order '" + sortOrder + "'! Only 'ASC' or 'DESC' types are allowed.", ThingsboardErrorCode.BAD_REQUEST_PARAMS); | ||
260 | + } | ||
261 | + } | ||
262 | + SortOrder sort = new SortOrder(sortProperty, direction); | ||
263 | + return new PageLink(pageSize, page, textSearch, sort); | ||
264 | + } else { | ||
265 | + return new PageLink(pageSize, page, textSearch); | ||
263 | } | 266 | } |
264 | - return new TimePageLink(limit, startTime, endTime, ascOrder, idOffsetUuid); | ||
265 | } | 267 | } |
266 | 268 | ||
267 | - | ||
268 | - TextPageLink createPageLink(int limit, String textSearch, String idOffset, String textOffset) { | ||
269 | - UUID idOffsetUuid = null; | ||
270 | - if (StringUtils.isNotEmpty(idOffset)) { | ||
271 | - idOffsetUuid = toUUID(idOffset); | ||
272 | - } | ||
273 | - return new TextPageLink(limit, textSearch, idOffsetUuid, textOffset); | 269 | + TimePageLink createTimePageLink(int pageSize, int page, String textSearch, |
270 | + String sortProperty, String sortOrder, Long startTime, Long endTime) throws ThingsboardException { | ||
271 | + PageLink pageLink = this.createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
272 | + return new TimePageLink(pageLink, startTime, endTime); | ||
274 | } | 273 | } |
275 | 274 | ||
276 | protected SecurityUser getCurrentUser() throws ThingsboardException { | 275 | protected SecurityUser getCurrentUser() throws ThingsboardException { |
@@ -374,6 +373,18 @@ public abstract class BaseController { | @@ -374,6 +373,18 @@ public abstract class BaseController { | ||
374 | } | 373 | } |
375 | } | 374 | } |
376 | 375 | ||
376 | + DeviceInfo checkDeviceInfoId(DeviceId deviceId, Operation operation) throws ThingsboardException { | ||
377 | + try { | ||
378 | + validateId(deviceId, "Incorrect deviceId " + deviceId); | ||
379 | + DeviceInfo device = deviceService.findDeviceInfoById(getCurrentUser().getTenantId(), deviceId); | ||
380 | + checkNotNull(device); | ||
381 | + accessControlService.checkPermission(getCurrentUser(), Resource.DEVICE, operation, deviceId, device); | ||
382 | + return device; | ||
383 | + } catch (Exception e) { | ||
384 | + throw handleException(e, false); | ||
385 | + } | ||
386 | + } | ||
387 | + | ||
377 | protected EntityView checkEntityViewId(EntityViewId entityViewId, Operation operation) throws ThingsboardException { | 388 | protected EntityView checkEntityViewId(EntityViewId entityViewId, Operation operation) throws ThingsboardException { |
378 | try { | 389 | try { |
379 | validateId(entityViewId, "Incorrect entityViewId " + entityViewId); | 390 | validateId(entityViewId, "Incorrect entityViewId " + entityViewId); |
@@ -386,6 +397,18 @@ public abstract class BaseController { | @@ -386,6 +397,18 @@ public abstract class BaseController { | ||
386 | } | 397 | } |
387 | } | 398 | } |
388 | 399 | ||
400 | + EntityViewInfo checkEntityViewInfoId(EntityViewId entityViewId, Operation operation) throws ThingsboardException { | ||
401 | + try { | ||
402 | + validateId(entityViewId, "Incorrect entityViewId " + entityViewId); | ||
403 | + EntityViewInfo entityView = entityViewService.findEntityViewInfoById(getCurrentUser().getTenantId(), entityViewId); | ||
404 | + checkNotNull(entityView); | ||
405 | + accessControlService.checkPermission(getCurrentUser(), Resource.ENTITY_VIEW, operation, entityViewId, entityView); | ||
406 | + return entityView; | ||
407 | + } catch (Exception e) { | ||
408 | + throw handleException(e, false); | ||
409 | + } | ||
410 | + } | ||
411 | + | ||
389 | Asset checkAssetId(AssetId assetId, Operation operation) throws ThingsboardException { | 412 | Asset checkAssetId(AssetId assetId, Operation operation) throws ThingsboardException { |
390 | try { | 413 | try { |
391 | validateId(assetId, "Incorrect assetId " + assetId); | 414 | validateId(assetId, "Incorrect assetId " + assetId); |
@@ -398,6 +421,18 @@ public abstract class BaseController { | @@ -398,6 +421,18 @@ public abstract class BaseController { | ||
398 | } | 421 | } |
399 | } | 422 | } |
400 | 423 | ||
424 | + AssetInfo checkAssetInfoId(AssetId assetId, Operation operation) throws ThingsboardException { | ||
425 | + try { | ||
426 | + validateId(assetId, "Incorrect assetId " + assetId); | ||
427 | + AssetInfo asset = assetService.findAssetInfoById(getCurrentUser().getTenantId(), assetId); | ||
428 | + checkNotNull(asset); | ||
429 | + accessControlService.checkPermission(getCurrentUser(), Resource.ASSET, operation, assetId, asset); | ||
430 | + return asset; | ||
431 | + } catch (Exception e) { | ||
432 | + throw handleException(e, false); | ||
433 | + } | ||
434 | + } | ||
435 | + | ||
401 | Alarm checkAlarmId(AlarmId alarmId, Operation operation) throws ThingsboardException { | 436 | Alarm checkAlarmId(AlarmId alarmId, Operation operation) throws ThingsboardException { |
402 | try { | 437 | try { |
403 | validateId(alarmId, "Incorrect alarmId " + alarmId); | 438 | validateId(alarmId, "Incorrect alarmId " + alarmId); |
@@ -34,8 +34,8 @@ import org.thingsboard.server.common.data.audit.ActionType; | @@ -34,8 +34,8 @@ import org.thingsboard.server.common.data.audit.ActionType; | ||
34 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 34 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
35 | import org.thingsboard.server.common.data.id.CustomerId; | 35 | import org.thingsboard.server.common.data.id.CustomerId; |
36 | import org.thingsboard.server.common.data.id.TenantId; | 36 | import org.thingsboard.server.common.data.id.TenantId; |
37 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
38 | -import org.thingsboard.server.common.data.page.TextPageLink; | 37 | +import org.thingsboard.server.common.data.page.PageData; |
38 | +import org.thingsboard.server.common.data.page.PageLink; | ||
39 | import org.thingsboard.server.service.security.permission.Operation; | 39 | import org.thingsboard.server.service.security.permission.Operation; |
40 | import org.thingsboard.server.service.security.permission.Resource; | 40 | import org.thingsboard.server.service.security.permission.Resource; |
41 | 41 | ||
@@ -143,14 +143,15 @@ public class CustomerController extends BaseController { | @@ -143,14 +143,15 @@ public class CustomerController extends BaseController { | ||
143 | } | 143 | } |
144 | 144 | ||
145 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 145 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
146 | - @RequestMapping(value = "/customers", params = {"limit"}, method = RequestMethod.GET) | 146 | + @RequestMapping(value = "/customers", params = {"pageSize", "page"}, method = RequestMethod.GET) |
147 | @ResponseBody | 147 | @ResponseBody |
148 | - public TextPageData<Customer> getCustomers(@RequestParam int limit, | ||
149 | - @RequestParam(required = false) String textSearch, | ||
150 | - @RequestParam(required = false) String idOffset, | ||
151 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 148 | + public PageData<Customer> getCustomers(@RequestParam int pageSize, |
149 | + @RequestParam int page, | ||
150 | + @RequestParam(required = false) String textSearch, | ||
151 | + @RequestParam(required = false) String sortProperty, | ||
152 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
152 | try { | 153 | try { |
153 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 154 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
154 | TenantId tenantId = getCurrentUser().getTenantId(); | 155 | TenantId tenantId = getCurrentUser().getTenantId(); |
155 | return checkNotNull(customerService.findCustomersByTenantId(tenantId, pageLink)); | 156 | return checkNotNull(customerService.findCustomersByTenantId(tenantId, pageLink)); |
156 | } catch (Exception e) { | 157 | } catch (Exception e) { |
@@ -37,9 +37,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -37,9 +37,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
37 | import org.thingsboard.server.common.data.id.CustomerId; | 37 | import org.thingsboard.server.common.data.id.CustomerId; |
38 | import org.thingsboard.server.common.data.id.DashboardId; | 38 | import org.thingsboard.server.common.data.id.DashboardId; |
39 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
40 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
41 | -import org.thingsboard.server.common.data.page.TextPageLink; | ||
42 | -import org.thingsboard.server.common.data.page.TimePageData; | 40 | +import org.thingsboard.server.common.data.page.PageData; |
41 | +import org.thingsboard.server.common.data.page.PageLink; | ||
43 | import org.thingsboard.server.common.data.page.TimePageLink; | 42 | import org.thingsboard.server.common.data.page.TimePageLink; |
44 | import org.thingsboard.server.service.security.permission.Operation; | 43 | import org.thingsboard.server.service.security.permission.Operation; |
45 | import org.thingsboard.server.service.security.permission.Resource; | 44 | import org.thingsboard.server.service.security.permission.Resource; |
@@ -417,18 +416,19 @@ public class DashboardController extends BaseController { | @@ -417,18 +416,19 @@ public class DashboardController extends BaseController { | ||
417 | } | 416 | } |
418 | 417 | ||
419 | @PreAuthorize("hasAuthority('SYS_ADMIN')") | 418 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
420 | - @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = { "limit" }, method = RequestMethod.GET) | 419 | + @RequestMapping(value = "/tenant/{tenantId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) |
421 | @ResponseBody | 420 | @ResponseBody |
422 | - public TextPageData<DashboardInfo> getTenantDashboards( | 421 | + public PageData<DashboardInfo> getTenantDashboards( |
423 | @PathVariable("tenantId") String strTenantId, | 422 | @PathVariable("tenantId") String strTenantId, |
424 | - @RequestParam int limit, | 423 | + @RequestParam int pageSize, |
424 | + @RequestParam int page, | ||
425 | @RequestParam(required = false) String textSearch, | 425 | @RequestParam(required = false) String textSearch, |
426 | - @RequestParam(required = false) String idOffset, | ||
427 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 426 | + @RequestParam(required = false) String sortProperty, |
427 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
428 | try { | 428 | try { |
429 | TenantId tenantId = new TenantId(toUUID(strTenantId)); | 429 | TenantId tenantId = new TenantId(toUUID(strTenantId)); |
430 | checkTenantId(tenantId, Operation.READ); | 430 | checkTenantId(tenantId, Operation.READ); |
431 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 431 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
432 | return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink)); | 432 | return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink)); |
433 | } catch (Exception e) { | 433 | } catch (Exception e) { |
434 | throw handleException(e); | 434 | throw handleException(e); |
@@ -436,16 +436,17 @@ public class DashboardController extends BaseController { | @@ -436,16 +436,17 @@ public class DashboardController extends BaseController { | ||
436 | } | 436 | } |
437 | 437 | ||
438 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 438 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
439 | - @RequestMapping(value = "/tenant/dashboards", params = { "limit" }, method = RequestMethod.GET) | 439 | + @RequestMapping(value = "/tenant/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) |
440 | @ResponseBody | 440 | @ResponseBody |
441 | - public TextPageData<DashboardInfo> getTenantDashboards( | ||
442 | - @RequestParam int limit, | 441 | + public PageData<DashboardInfo> getTenantDashboards( |
442 | + @RequestParam int pageSize, | ||
443 | + @RequestParam int page, | ||
443 | @RequestParam(required = false) String textSearch, | 444 | @RequestParam(required = false) String textSearch, |
444 | - @RequestParam(required = false) String idOffset, | ||
445 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 445 | + @RequestParam(required = false) String sortProperty, |
446 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
446 | try { | 447 | try { |
447 | TenantId tenantId = getCurrentUser().getTenantId(); | 448 | TenantId tenantId = getCurrentUser().getTenantId(); |
448 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 449 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
449 | return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink)); | 450 | return checkNotNull(dashboardService.findDashboardsByTenantId(tenantId, pageLink)); |
450 | } catch (Exception e) { | 451 | } catch (Exception e) { |
451 | throw handleException(e); | 452 | throw handleException(e); |
@@ -453,22 +454,22 @@ public class DashboardController extends BaseController { | @@ -453,22 +454,22 @@ public class DashboardController extends BaseController { | ||
453 | } | 454 | } |
454 | 455 | ||
455 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 456 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
456 | - @RequestMapping(value = "/customer/{customerId}/dashboards", params = { "limit" }, method = RequestMethod.GET) | 457 | + @RequestMapping(value = "/customer/{customerId}/dashboards", params = {"pageSize", "page"}, method = RequestMethod.GET) |
457 | @ResponseBody | 458 | @ResponseBody |
458 | - public TimePageData<DashboardInfo> getCustomerDashboards( | 459 | + public PageData<DashboardInfo> getCustomerDashboards( |
459 | @PathVariable("customerId") String strCustomerId, | 460 | @PathVariable("customerId") String strCustomerId, |
460 | - @RequestParam int limit, | ||
461 | - @RequestParam(required = false) Long startTime, | ||
462 | - @RequestParam(required = false) Long endTime, | ||
463 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
464 | - @RequestParam(required = false) String offset) throws ThingsboardException { | 461 | + @RequestParam int pageSize, |
462 | + @RequestParam int page, | ||
463 | + @RequestParam(required = false) String textSearch, | ||
464 | + @RequestParam(required = false) String sortProperty, | ||
465 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
465 | checkParameter("customerId", strCustomerId); | 466 | checkParameter("customerId", strCustomerId); |
466 | try { | 467 | try { |
467 | TenantId tenantId = getCurrentUser().getTenantId(); | 468 | TenantId tenantId = getCurrentUser().getTenantId(); |
468 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 469 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
469 | checkCustomerId(customerId, Operation.READ); | 470 | checkCustomerId(customerId, Operation.READ); |
470 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | ||
471 | - return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink).get()); | 471 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
472 | + return checkNotNull(dashboardService.findDashboardsByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
472 | } catch (Exception e) { | 473 | } catch (Exception e) { |
473 | throw handleException(e); | 474 | throw handleException(e); |
474 | } | 475 | } |
@@ -30,19 +30,15 @@ import org.springframework.web.bind.annotation.ResponseBody; | @@ -30,19 +30,15 @@ import org.springframework.web.bind.annotation.ResponseBody; | ||
30 | import org.springframework.web.bind.annotation.ResponseStatus; | 30 | import org.springframework.web.bind.annotation.ResponseStatus; |
31 | import org.springframework.web.bind.annotation.RestController; | 31 | import org.springframework.web.bind.annotation.RestController; |
32 | import org.springframework.web.context.request.async.DeferredResult; | 32 | import org.springframework.web.context.request.async.DeferredResult; |
33 | -import org.thingsboard.server.common.data.Customer; | ||
34 | -import org.thingsboard.server.common.data.DataConstants; | ||
35 | -import org.thingsboard.server.common.data.Device; | ||
36 | -import org.thingsboard.server.common.data.EntitySubtype; | ||
37 | -import org.thingsboard.server.common.data.EntityType; | 33 | +import org.thingsboard.server.common.data.*; |
38 | import org.thingsboard.server.common.data.audit.ActionType; | 34 | import org.thingsboard.server.common.data.audit.ActionType; |
39 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 35 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
40 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 36 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
41 | import org.thingsboard.server.common.data.id.CustomerId; | 37 | import org.thingsboard.server.common.data.id.CustomerId; |
42 | import org.thingsboard.server.common.data.id.DeviceId; | 38 | import org.thingsboard.server.common.data.id.DeviceId; |
43 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
44 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
45 | -import org.thingsboard.server.common.data.page.TextPageLink; | 40 | +import org.thingsboard.server.common.data.page.PageData; |
41 | +import org.thingsboard.server.common.data.page.PageLink; | ||
46 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 42 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
47 | import org.thingsboard.server.common.data.ClaimRequest; | 43 | import org.thingsboard.server.common.data.ClaimRequest; |
48 | import org.thingsboard.server.dao.device.claim.ClaimResponse; | 44 | import org.thingsboard.server.dao.device.claim.ClaimResponse; |
@@ -80,6 +76,19 @@ public class DeviceController extends BaseController { | @@ -80,6 +76,19 @@ public class DeviceController extends BaseController { | ||
80 | } | 76 | } |
81 | 77 | ||
82 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 78 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
79 | + @RequestMapping(value = "/device/info/{deviceId}", method = RequestMethod.GET) | ||
80 | + @ResponseBody | ||
81 | + public DeviceInfo getDeviceInfoById(@PathVariable(DEVICE_ID) String strDeviceId) throws ThingsboardException { | ||
82 | + checkParameter(DEVICE_ID, strDeviceId); | ||
83 | + try { | ||
84 | + DeviceId deviceId = new DeviceId(toUUID(strDeviceId)); | ||
85 | + return checkDeviceInfoId(deviceId, Operation.READ); | ||
86 | + } catch (Exception e) { | ||
87 | + throw handleException(e); | ||
88 | + } | ||
89 | + } | ||
90 | + | ||
91 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
83 | @RequestMapping(value = "/device", method = RequestMethod.POST) | 92 | @RequestMapping(value = "/device", method = RequestMethod.POST) |
84 | @ResponseBody | 93 | @ResponseBody |
85 | public Device saveDevice(@RequestBody Device device, | 94 | public Device saveDevice(@RequestBody Device device, |
@@ -266,17 +275,18 @@ public class DeviceController extends BaseController { | @@ -266,17 +275,18 @@ public class DeviceController extends BaseController { | ||
266 | } | 275 | } |
267 | 276 | ||
268 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 277 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
269 | - @RequestMapping(value = "/tenant/devices", params = {"limit"}, method = RequestMethod.GET) | 278 | + @RequestMapping(value = "/tenant/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) |
270 | @ResponseBody | 279 | @ResponseBody |
271 | - public TextPageData<Device> getTenantDevices( | ||
272 | - @RequestParam int limit, | 280 | + public PageData<Device> getTenantDevices( |
281 | + @RequestParam int pageSize, | ||
282 | + @RequestParam int page, | ||
273 | @RequestParam(required = false) String type, | 283 | @RequestParam(required = false) String type, |
274 | @RequestParam(required = false) String textSearch, | 284 | @RequestParam(required = false) String textSearch, |
275 | - @RequestParam(required = false) String idOffset, | ||
276 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 285 | + @RequestParam(required = false) String sortProperty, |
286 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
277 | try { | 287 | try { |
278 | TenantId tenantId = getCurrentUser().getTenantId(); | 288 | TenantId tenantId = getCurrentUser().getTenantId(); |
279 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 289 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
280 | if (type != null && type.trim().length() > 0) { | 290 | if (type != null && type.trim().length() > 0) { |
281 | return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink)); | 291 | return checkNotNull(deviceService.findDevicesByTenantIdAndType(tenantId, type, pageLink)); |
282 | } else { | 292 | } else { |
@@ -288,6 +298,29 @@ public class DeviceController extends BaseController { | @@ -288,6 +298,29 @@ public class DeviceController extends BaseController { | ||
288 | } | 298 | } |
289 | 299 | ||
290 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 300 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
301 | + @RequestMapping(value = "/tenant/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
302 | + @ResponseBody | ||
303 | + public PageData<DeviceInfo> getTenantDeviceInfos( | ||
304 | + @RequestParam int pageSize, | ||
305 | + @RequestParam int page, | ||
306 | + @RequestParam(required = false) String type, | ||
307 | + @RequestParam(required = false) String textSearch, | ||
308 | + @RequestParam(required = false) String sortProperty, | ||
309 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
310 | + try { | ||
311 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
312 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
313 | + if (type != null && type.trim().length() > 0) { | ||
314 | + return checkNotNull(deviceService.findDeviceInfosByTenantIdAndType(tenantId, type, pageLink)); | ||
315 | + } else { | ||
316 | + return checkNotNull(deviceService.findDeviceInfosByTenantId(tenantId, pageLink)); | ||
317 | + } | ||
318 | + } catch (Exception e) { | ||
319 | + throw handleException(e); | ||
320 | + } | ||
321 | + } | ||
322 | + | ||
323 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
291 | @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) | 324 | @RequestMapping(value = "/tenant/devices", params = {"deviceName"}, method = RequestMethod.GET) |
292 | @ResponseBody | 325 | @ResponseBody |
293 | public Device getTenantDevice( | 326 | public Device getTenantDevice( |
@@ -301,21 +334,22 @@ public class DeviceController extends BaseController { | @@ -301,21 +334,22 @@ public class DeviceController extends BaseController { | ||
301 | } | 334 | } |
302 | 335 | ||
303 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 336 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
304 | - @RequestMapping(value = "/customer/{customerId}/devices", params = {"limit"}, method = RequestMethod.GET) | 337 | + @RequestMapping(value = "/customer/{customerId}/devices", params = {"pageSize", "page"}, method = RequestMethod.GET) |
305 | @ResponseBody | 338 | @ResponseBody |
306 | - public TextPageData<Device> getCustomerDevices( | 339 | + public PageData<Device> getCustomerDevices( |
307 | @PathVariable("customerId") String strCustomerId, | 340 | @PathVariable("customerId") String strCustomerId, |
308 | - @RequestParam int limit, | 341 | + @RequestParam int pageSize, |
342 | + @RequestParam int page, | ||
309 | @RequestParam(required = false) String type, | 343 | @RequestParam(required = false) String type, |
310 | @RequestParam(required = false) String textSearch, | 344 | @RequestParam(required = false) String textSearch, |
311 | - @RequestParam(required = false) String idOffset, | ||
312 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 345 | + @RequestParam(required = false) String sortProperty, |
346 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
313 | checkParameter("customerId", strCustomerId); | 347 | checkParameter("customerId", strCustomerId); |
314 | try { | 348 | try { |
315 | TenantId tenantId = getCurrentUser().getTenantId(); | 349 | TenantId tenantId = getCurrentUser().getTenantId(); |
316 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 350 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
317 | checkCustomerId(customerId, Operation.READ); | 351 | checkCustomerId(customerId, Operation.READ); |
318 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 352 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
319 | if (type != null && type.trim().length() > 0) { | 353 | if (type != null && type.trim().length() > 0) { |
320 | return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | 354 | return checkNotNull(deviceService.findDevicesByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); |
321 | } else { | 355 | } else { |
@@ -327,6 +361,33 @@ public class DeviceController extends BaseController { | @@ -327,6 +361,33 @@ public class DeviceController extends BaseController { | ||
327 | } | 361 | } |
328 | 362 | ||
329 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 363 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
364 | + @RequestMapping(value = "/customer/{customerId}/deviceInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
365 | + @ResponseBody | ||
366 | + public PageData<DeviceInfo> getCustomerDeviceInfos( | ||
367 | + @PathVariable("customerId") String strCustomerId, | ||
368 | + @RequestParam int pageSize, | ||
369 | + @RequestParam int page, | ||
370 | + @RequestParam(required = false) String type, | ||
371 | + @RequestParam(required = false) String textSearch, | ||
372 | + @RequestParam(required = false) String sortProperty, | ||
373 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
374 | + checkParameter("customerId", strCustomerId); | ||
375 | + try { | ||
376 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
377 | + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | ||
378 | + checkCustomerId(customerId, Operation.READ); | ||
379 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
380 | + if (type != null && type.trim().length() > 0) { | ||
381 | + return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | ||
382 | + } else { | ||
383 | + return checkNotNull(deviceService.findDeviceInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
384 | + } | ||
385 | + } catch (Exception e) { | ||
386 | + throw handleException(e); | ||
387 | + } | ||
388 | + } | ||
389 | + | ||
390 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
330 | @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) | 391 | @RequestMapping(value = "/devices", params = {"deviceIds"}, method = RequestMethod.GET) |
331 | @ResponseBody | 392 | @ResponseBody |
332 | public List<Device> getDevicesByIds( | 393 | public List<Device> getDevicesByIds( |
@@ -29,11 +29,7 @@ import org.springframework.web.bind.annotation.RequestParam; | @@ -29,11 +29,7 @@ import org.springframework.web.bind.annotation.RequestParam; | ||
29 | import org.springframework.web.bind.annotation.ResponseBody; | 29 | import org.springframework.web.bind.annotation.ResponseBody; |
30 | import org.springframework.web.bind.annotation.ResponseStatus; | 30 | import org.springframework.web.bind.annotation.ResponseStatus; |
31 | import org.springframework.web.bind.annotation.RestController; | 31 | import org.springframework.web.bind.annotation.RestController; |
32 | -import org.thingsboard.server.common.data.Customer; | ||
33 | -import org.thingsboard.server.common.data.DataConstants; | ||
34 | -import org.thingsboard.server.common.data.EntitySubtype; | ||
35 | -import org.thingsboard.server.common.data.EntityType; | ||
36 | -import org.thingsboard.server.common.data.EntityView; | 32 | +import org.thingsboard.server.common.data.*; |
37 | import org.thingsboard.server.common.data.audit.ActionType; | 33 | import org.thingsboard.server.common.data.audit.ActionType; |
38 | import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; | 34 | import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; |
39 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 35 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
@@ -43,8 +39,8 @@ import org.thingsboard.server.common.data.id.EntityViewId; | @@ -43,8 +39,8 @@ import org.thingsboard.server.common.data.id.EntityViewId; | ||
43 | import org.thingsboard.server.common.data.id.TenantId; | 39 | import org.thingsboard.server.common.data.id.TenantId; |
44 | import org.thingsboard.server.common.data.id.UUIDBased; | 40 | import org.thingsboard.server.common.data.id.UUIDBased; |
45 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 41 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
46 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
47 | -import org.thingsboard.server.common.data.page.TextPageLink; | 42 | +import org.thingsboard.server.common.data.page.PageData; |
43 | +import org.thingsboard.server.common.data.page.PageLink; | ||
48 | import org.thingsboard.server.dao.exception.IncorrectParameterException; | 44 | import org.thingsboard.server.dao.exception.IncorrectParameterException; |
49 | import org.thingsboard.server.dao.model.ModelConstants; | 45 | import org.thingsboard.server.dao.model.ModelConstants; |
50 | import org.thingsboard.server.service.security.model.SecurityUser; | 46 | import org.thingsboard.server.service.security.model.SecurityUser; |
@@ -83,6 +79,19 @@ public class EntityViewController extends BaseController { | @@ -83,6 +79,19 @@ public class EntityViewController extends BaseController { | ||
83 | } | 79 | } |
84 | 80 | ||
85 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 81 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
82 | + @RequestMapping(value = "/entityView/info/{entityViewId}", method = RequestMethod.GET) | ||
83 | + @ResponseBody | ||
84 | + public EntityViewInfo getEntityViewInfoById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { | ||
85 | + checkParameter(ENTITY_VIEW_ID, strEntityViewId); | ||
86 | + try { | ||
87 | + EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); | ||
88 | + return checkEntityViewInfoId(entityViewId, Operation.READ); | ||
89 | + } catch (Exception e) { | ||
90 | + throw handleException(e); | ||
91 | + } | ||
92 | + } | ||
93 | + | ||
94 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
86 | @RequestMapping(value = "/entityView", method = RequestMethod.POST) | 95 | @RequestMapping(value = "/entityView", method = RequestMethod.POST) |
87 | @ResponseBody | 96 | @ResponseBody |
88 | public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { | 97 | public EntityView saveEntityView(@RequestBody EntityView entityView) throws ThingsboardException { |
@@ -256,21 +265,22 @@ public class EntityViewController extends BaseController { | @@ -256,21 +265,22 @@ public class EntityViewController extends BaseController { | ||
256 | } | 265 | } |
257 | 266 | ||
258 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 267 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
259 | - @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"limit"}, method = RequestMethod.GET) | 268 | + @RequestMapping(value = "/customer/{customerId}/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) |
260 | @ResponseBody | 269 | @ResponseBody |
261 | - public TextPageData<EntityView> getCustomerEntityViews( | 270 | + public PageData<EntityView> getCustomerEntityViews( |
262 | @PathVariable("customerId") String strCustomerId, | 271 | @PathVariable("customerId") String strCustomerId, |
263 | - @RequestParam int limit, | 272 | + @RequestParam int pageSize, |
273 | + @RequestParam int page, | ||
264 | @RequestParam(required = false) String type, | 274 | @RequestParam(required = false) String type, |
265 | @RequestParam(required = false) String textSearch, | 275 | @RequestParam(required = false) String textSearch, |
266 | - @RequestParam(required = false) String idOffset, | ||
267 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 276 | + @RequestParam(required = false) String sortProperty, |
277 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
268 | checkParameter("customerId", strCustomerId); | 278 | checkParameter("customerId", strCustomerId); |
269 | try { | 279 | try { |
270 | TenantId tenantId = getCurrentUser().getTenantId(); | 280 | TenantId tenantId = getCurrentUser().getTenantId(); |
271 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 281 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
272 | checkCustomerId(customerId, Operation.READ); | 282 | checkCustomerId(customerId, Operation.READ); |
273 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 283 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
274 | if (type != null && type.trim().length() > 0) { | 284 | if (type != null && type.trim().length() > 0) { |
275 | return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); | 285 | return checkNotNull(entityViewService.findEntityViewsByTenantIdAndCustomerIdAndType(tenantId, customerId, pageLink, type)); |
276 | } else { | 286 | } else { |
@@ -281,18 +291,46 @@ public class EntityViewController extends BaseController { | @@ -281,18 +291,46 @@ public class EntityViewController extends BaseController { | ||
281 | } | 291 | } |
282 | } | 292 | } |
283 | 293 | ||
294 | + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | ||
295 | + @RequestMapping(value = "/customer/{customerId}/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
296 | + @ResponseBody | ||
297 | + public PageData<EntityViewInfo> getCustomerEntityViewInfos( | ||
298 | + @PathVariable("customerId") String strCustomerId, | ||
299 | + @RequestParam int pageSize, | ||
300 | + @RequestParam int page, | ||
301 | + @RequestParam(required = false) String type, | ||
302 | + @RequestParam(required = false) String textSearch, | ||
303 | + @RequestParam(required = false) String sortProperty, | ||
304 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
305 | + checkParameter("customerId", strCustomerId); | ||
306 | + try { | ||
307 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
308 | + CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | ||
309 | + checkCustomerId(customerId, Operation.READ); | ||
310 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
311 | + if (type != null && type.trim().length() > 0) { | ||
312 | + return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerIdAndType(tenantId, customerId, type, pageLink)); | ||
313 | + } else { | ||
314 | + return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndCustomerId(tenantId, customerId, pageLink)); | ||
315 | + } | ||
316 | + } catch (Exception e) { | ||
317 | + throw handleException(e); | ||
318 | + } | ||
319 | + } | ||
320 | + | ||
284 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 321 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
285 | - @RequestMapping(value = "/tenant/entityViews", params = {"limit"}, method = RequestMethod.GET) | 322 | + @RequestMapping(value = "/tenant/entityViews", params = {"pageSize", "page"}, method = RequestMethod.GET) |
286 | @ResponseBody | 323 | @ResponseBody |
287 | - public TextPageData<EntityView> getTenantEntityViews( | ||
288 | - @RequestParam int limit, | 324 | + public PageData<EntityView> getTenantEntityViews( |
325 | + @RequestParam int pageSize, | ||
326 | + @RequestParam int page, | ||
289 | @RequestParam(required = false) String type, | 327 | @RequestParam(required = false) String type, |
290 | @RequestParam(required = false) String textSearch, | 328 | @RequestParam(required = false) String textSearch, |
291 | - @RequestParam(required = false) String idOffset, | ||
292 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 329 | + @RequestParam(required = false) String sortProperty, |
330 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
293 | try { | 331 | try { |
294 | TenantId tenantId = getCurrentUser().getTenantId(); | 332 | TenantId tenantId = getCurrentUser().getTenantId(); |
295 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 333 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
296 | 334 | ||
297 | if (type != null && type.trim().length() > 0) { | 335 | if (type != null && type.trim().length() > 0) { |
298 | return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type)); | 336 | return checkNotNull(entityViewService.findEntityViewByTenantIdAndType(tenantId, pageLink, type)); |
@@ -304,6 +342,29 @@ public class EntityViewController extends BaseController { | @@ -304,6 +342,29 @@ public class EntityViewController extends BaseController { | ||
304 | } | 342 | } |
305 | } | 343 | } |
306 | 344 | ||
345 | + @PreAuthorize("hasAuthority('TENANT_ADMIN')") | ||
346 | + @RequestMapping(value = "/tenant/entityViewInfos", params = {"pageSize", "page"}, method = RequestMethod.GET) | ||
347 | + @ResponseBody | ||
348 | + public PageData<EntityViewInfo> getTenantEntityViewInfos( | ||
349 | + @RequestParam int pageSize, | ||
350 | + @RequestParam int page, | ||
351 | + @RequestParam(required = false) String type, | ||
352 | + @RequestParam(required = false) String textSearch, | ||
353 | + @RequestParam(required = false) String sortProperty, | ||
354 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
355 | + try { | ||
356 | + TenantId tenantId = getCurrentUser().getTenantId(); | ||
357 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); | ||
358 | + if (type != null && type.trim().length() > 0) { | ||
359 | + return checkNotNull(entityViewService.findEntityViewInfosByTenantIdAndType(tenantId, type, pageLink)); | ||
360 | + } else { | ||
361 | + return checkNotNull(entityViewService.findEntityViewInfosByTenantId(tenantId, pageLink)); | ||
362 | + } | ||
363 | + } catch (Exception e) { | ||
364 | + throw handleException(e); | ||
365 | + } | ||
366 | + } | ||
367 | + | ||
307 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") | 368 | @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") |
308 | @RequestMapping(value = "/entityViews", method = RequestMethod.POST) | 369 | @RequestMapping(value = "/entityViews", method = RequestMethod.POST) |
309 | @ResponseBody | 370 | @ResponseBody |
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
28 | import org.thingsboard.server.common.data.id.EntityId; | 28 | import org.thingsboard.server.common.data.id.EntityId; |
29 | import org.thingsboard.server.common.data.id.EntityIdFactory; | 29 | import org.thingsboard.server.common.data.id.EntityIdFactory; |
30 | import org.thingsboard.server.common.data.id.TenantId; | 30 | import org.thingsboard.server.common.data.id.TenantId; |
31 | -import org.thingsboard.server.common.data.page.TimePageData; | 31 | +import org.thingsboard.server.common.data.page.PageData; |
32 | import org.thingsboard.server.common.data.page.TimePageLink; | 32 | import org.thingsboard.server.common.data.page.TimePageLink; |
33 | import org.thingsboard.server.dao.event.EventService; | 33 | import org.thingsboard.server.dao.event.EventService; |
34 | import org.thingsboard.server.service.security.permission.Operation; | 34 | import org.thingsboard.server.service.security.permission.Operation; |
@@ -43,17 +43,18 @@ public class EventController extends BaseController { | @@ -43,17 +43,18 @@ public class EventController extends BaseController { | ||
43 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 43 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
44 | @RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET) | 44 | @RequestMapping(value = "/events/{entityType}/{entityId}/{eventType}", method = RequestMethod.GET) |
45 | @ResponseBody | 45 | @ResponseBody |
46 | - public TimePageData<Event> getEvents( | 46 | + public PageData<Event> getEvents( |
47 | @PathVariable("entityType") String strEntityType, | 47 | @PathVariable("entityType") String strEntityType, |
48 | @PathVariable("entityId") String strEntityId, | 48 | @PathVariable("entityId") String strEntityId, |
49 | @PathVariable("eventType") String eventType, | 49 | @PathVariable("eventType") String eventType, |
50 | @RequestParam("tenantId") String strTenantId, | 50 | @RequestParam("tenantId") String strTenantId, |
51 | - @RequestParam int limit, | 51 | + @RequestParam int pageSize, |
52 | + @RequestParam int page, | ||
53 | + @RequestParam(required = false) String textSearch, | ||
54 | + @RequestParam(required = false) String sortProperty, | ||
55 | + @RequestParam(required = false) String sortOrder, | ||
52 | @RequestParam(required = false) Long startTime, | 56 | @RequestParam(required = false) Long startTime, |
53 | - @RequestParam(required = false) Long endTime, | ||
54 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
55 | - @RequestParam(required = false) String offset | ||
56 | - ) throws ThingsboardException { | 57 | + @RequestParam(required = false) Long endTime) throws ThingsboardException { |
57 | checkParameter("EntityId", strEntityId); | 58 | checkParameter("EntityId", strEntityId); |
58 | checkParameter("EntityType", strEntityType); | 59 | checkParameter("EntityType", strEntityType); |
59 | try { | 60 | try { |
@@ -61,8 +62,7 @@ public class EventController extends BaseController { | @@ -61,8 +62,7 @@ public class EventController extends BaseController { | ||
61 | 62 | ||
62 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); | 63 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); |
63 | checkEntityId(entityId, Operation.READ); | 64 | checkEntityId(entityId, Operation.READ); |
64 | - | ||
65 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | 65 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); |
66 | return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink)); | 66 | return checkNotNull(eventService.findEvents(tenantId, entityId, eventType, pageLink)); |
67 | } catch (Exception e) { | 67 | } catch (Exception e) { |
68 | throw handleException(e); | 68 | throw handleException(e); |
@@ -72,16 +72,17 @@ public class EventController extends BaseController { | @@ -72,16 +72,17 @@ public class EventController extends BaseController { | ||
72 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 72 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
73 | @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET) | 73 | @RequestMapping(value = "/events/{entityType}/{entityId}", method = RequestMethod.GET) |
74 | @ResponseBody | 74 | @ResponseBody |
75 | - public TimePageData<Event> getEvents( | 75 | + public PageData<Event> getEvents( |
76 | @PathVariable("entityType") String strEntityType, | 76 | @PathVariable("entityType") String strEntityType, |
77 | @PathVariable("entityId") String strEntityId, | 77 | @PathVariable("entityId") String strEntityId, |
78 | @RequestParam("tenantId") String strTenantId, | 78 | @RequestParam("tenantId") String strTenantId, |
79 | - @RequestParam int limit, | 79 | + @RequestParam int pageSize, |
80 | + @RequestParam int page, | ||
81 | + @RequestParam(required = false) String textSearch, | ||
82 | + @RequestParam(required = false) String sortProperty, | ||
83 | + @RequestParam(required = false) String sortOrder, | ||
80 | @RequestParam(required = false) Long startTime, | 84 | @RequestParam(required = false) Long startTime, |
81 | - @RequestParam(required = false) Long endTime, | ||
82 | - @RequestParam(required = false, defaultValue = "false") boolean ascOrder, | ||
83 | - @RequestParam(required = false) String offset | ||
84 | - ) throws ThingsboardException { | 85 | + @RequestParam(required = false) Long endTime) throws ThingsboardException { |
85 | checkParameter("EntityId", strEntityId); | 86 | checkParameter("EntityId", strEntityId); |
86 | checkParameter("EntityType", strEntityType); | 87 | checkParameter("EntityType", strEntityType); |
87 | try { | 88 | try { |
@@ -90,7 +91,8 @@ public class EventController extends BaseController { | @@ -90,7 +91,8 @@ public class EventController extends BaseController { | ||
90 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); | 91 | EntityId entityId = EntityIdFactory.getByTypeAndId(strEntityType, strEntityId); |
91 | checkEntityId(entityId, Operation.READ); | 92 | checkEntityId(entityId, Operation.READ); |
92 | 93 | ||
93 | - TimePageLink pageLink = createPageLink(limit, startTime, endTime, ascOrder, offset); | 94 | + TimePageLink pageLink = createTimePageLink(pageSize, page, textSearch, sortProperty, sortOrder, startTime, endTime); |
95 | + | ||
94 | return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink)); | 96 | return checkNotNull(eventService.findEvents(tenantId, entityId, pageLink)); |
95 | } catch (Exception e) { | 97 | } catch (Exception e) { |
96 | throw handleException(e); | 98 | throw handleException(e); |
@@ -45,8 +45,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -45,8 +45,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
45 | import org.thingsboard.server.common.data.id.RuleChainId; | 45 | import org.thingsboard.server.common.data.id.RuleChainId; |
46 | import org.thingsboard.server.common.data.id.RuleNodeId; | 46 | import org.thingsboard.server.common.data.id.RuleNodeId; |
47 | import org.thingsboard.server.common.data.id.TenantId; | 47 | import org.thingsboard.server.common.data.id.TenantId; |
48 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
49 | -import org.thingsboard.server.common.data.page.TextPageLink; | 48 | +import org.thingsboard.server.common.data.page.PageData; |
49 | +import org.thingsboard.server.common.data.page.PageLink; | ||
50 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 50 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
51 | import org.thingsboard.server.common.data.rule.RuleChain; | 51 | import org.thingsboard.server.common.data.rule.RuleChain; |
52 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 52 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
@@ -220,16 +220,17 @@ public class RuleChainController extends BaseController { | @@ -220,16 +220,17 @@ public class RuleChainController extends BaseController { | ||
220 | } | 220 | } |
221 | 221 | ||
222 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 222 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
223 | - @RequestMapping(value = "/ruleChains", params = {"limit"}, method = RequestMethod.GET) | 223 | + @RequestMapping(value = "/ruleChains", params = {"pageSize", "page"}, method = RequestMethod.GET) |
224 | @ResponseBody | 224 | @ResponseBody |
225 | - public TextPageData<RuleChain> getRuleChains( | ||
226 | - @RequestParam int limit, | 225 | + public PageData<RuleChain> getRuleChains( |
226 | + @RequestParam int pageSize, | ||
227 | + @RequestParam int page, | ||
227 | @RequestParam(required = false) String textSearch, | 228 | @RequestParam(required = false) String textSearch, |
228 | - @RequestParam(required = false) String idOffset, | ||
229 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 229 | + @RequestParam(required = false) String sortProperty, |
230 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
230 | try { | 231 | try { |
231 | TenantId tenantId = getCurrentUser().getTenantId(); | 232 | TenantId tenantId = getCurrentUser().getTenantId(); |
232 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 233 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
233 | return checkNotNull(ruleChainService.findTenantRuleChains(tenantId, pageLink)); | 234 | return checkNotNull(ruleChainService.findTenantRuleChains(tenantId, pageLink)); |
234 | } catch (Exception e) { | 235 | } catch (Exception e) { |
235 | throw handleException(e); | 236 | throw handleException(e); |
@@ -30,8 +30,8 @@ import org.springframework.web.bind.annotation.RestController; | @@ -30,8 +30,8 @@ import org.springframework.web.bind.annotation.RestController; | ||
30 | import org.thingsboard.server.common.data.Tenant; | 30 | import org.thingsboard.server.common.data.Tenant; |
31 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 31 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
32 | import org.thingsboard.server.common.data.id.TenantId; | 32 | import org.thingsboard.server.common.data.id.TenantId; |
33 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
34 | -import org.thingsboard.server.common.data.page.TextPageLink; | 33 | +import org.thingsboard.server.common.data.page.PageData; |
34 | +import org.thingsboard.server.common.data.page.PageLink; | ||
35 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; | 35 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; |
36 | import org.thingsboard.server.dao.tenant.TenantService; | 36 | import org.thingsboard.server.dao.tenant.TenantService; |
37 | import org.thingsboard.server.service.install.InstallScripts; | 37 | import org.thingsboard.server.service.install.InstallScripts; |
@@ -102,14 +102,15 @@ public class TenantController extends BaseController { | @@ -102,14 +102,15 @@ public class TenantController extends BaseController { | ||
102 | } | 102 | } |
103 | 103 | ||
104 | @PreAuthorize("hasAuthority('SYS_ADMIN')") | 104 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
105 | - @RequestMapping(value = "/tenants", params = {"limit"}, method = RequestMethod.GET) | 105 | + @RequestMapping(value = "/tenants", params = {"pageSize", "page"}, method = RequestMethod.GET) |
106 | @ResponseBody | 106 | @ResponseBody |
107 | - public TextPageData<Tenant> getTenants(@RequestParam int limit, | ||
108 | - @RequestParam(required = false) String textSearch, | ||
109 | - @RequestParam(required = false) String idOffset, | ||
110 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 107 | + public PageData<Tenant> getTenants(@RequestParam int pageSize, |
108 | + @RequestParam int page, | ||
109 | + @RequestParam(required = false) String textSearch, | ||
110 | + @RequestParam(required = false) String sortProperty, | ||
111 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
111 | try { | 112 | try { |
112 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 113 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
113 | return checkNotNull(tenantService.findTenants(pageLink)); | 114 | return checkNotNull(tenantService.findTenants(pageLink)); |
114 | } catch (Exception e) { | 115 | } catch (Exception e) { |
115 | throw handleException(e); | 116 | throw handleException(e); |
@@ -40,8 +40,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | @@ -40,8 +40,8 @@ import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
40 | import org.thingsboard.server.common.data.id.CustomerId; | 40 | import org.thingsboard.server.common.data.id.CustomerId; |
41 | import org.thingsboard.server.common.data.id.TenantId; | 41 | import org.thingsboard.server.common.data.id.TenantId; |
42 | import org.thingsboard.server.common.data.id.UserId; | 42 | import org.thingsboard.server.common.data.id.UserId; |
43 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
44 | -import org.thingsboard.server.common.data.page.TextPageLink; | 43 | +import org.thingsboard.server.common.data.page.PageData; |
44 | +import org.thingsboard.server.common.data.page.PageLink; | ||
45 | import org.thingsboard.server.common.data.security.Authority; | 45 | import org.thingsboard.server.common.data.security.Authority; |
46 | import org.thingsboard.server.common.data.security.UserCredentials; | 46 | import org.thingsboard.server.common.data.security.UserCredentials; |
47 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | 47 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
@@ -247,18 +247,19 @@ public class UserController extends BaseController { | @@ -247,18 +247,19 @@ public class UserController extends BaseController { | ||
247 | } | 247 | } |
248 | 248 | ||
249 | @PreAuthorize("hasAuthority('SYS_ADMIN')") | 249 | @PreAuthorize("hasAuthority('SYS_ADMIN')") |
250 | - @RequestMapping(value = "/tenant/{tenantId}/users", params = { "limit" }, method = RequestMethod.GET) | 250 | + @RequestMapping(value = "/tenant/{tenantId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET) |
251 | @ResponseBody | 251 | @ResponseBody |
252 | - public TextPageData<User> getTenantAdmins( | 252 | + public PageData<User> getTenantAdmins( |
253 | @PathVariable("tenantId") String strTenantId, | 253 | @PathVariable("tenantId") String strTenantId, |
254 | - @RequestParam int limit, | 254 | + @RequestParam int pageSize, |
255 | + @RequestParam int page, | ||
255 | @RequestParam(required = false) String textSearch, | 256 | @RequestParam(required = false) String textSearch, |
256 | - @RequestParam(required = false) String idOffset, | ||
257 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 257 | + @RequestParam(required = false) String sortProperty, |
258 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
258 | checkParameter("tenantId", strTenantId); | 259 | checkParameter("tenantId", strTenantId); |
259 | try { | 260 | try { |
260 | TenantId tenantId = new TenantId(toUUID(strTenantId)); | 261 | TenantId tenantId = new TenantId(toUUID(strTenantId)); |
261 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 262 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
262 | return checkNotNull(userService.findTenantAdmins(tenantId, pageLink)); | 263 | return checkNotNull(userService.findTenantAdmins(tenantId, pageLink)); |
263 | } catch (Exception e) { | 264 | } catch (Exception e) { |
264 | throw handleException(e); | 265 | throw handleException(e); |
@@ -266,19 +267,20 @@ public class UserController extends BaseController { | @@ -266,19 +267,20 @@ public class UserController extends BaseController { | ||
266 | } | 267 | } |
267 | 268 | ||
268 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") | 269 | @PreAuthorize("hasAuthority('TENANT_ADMIN')") |
269 | - @RequestMapping(value = "/customer/{customerId}/users", params = { "limit" }, method = RequestMethod.GET) | 270 | + @RequestMapping(value = "/customer/{customerId}/users", params = {"pageSize", "page"}, method = RequestMethod.GET) |
270 | @ResponseBody | 271 | @ResponseBody |
271 | - public TextPageData<User> getCustomerUsers( | 272 | + public PageData<User> getCustomerUsers( |
272 | @PathVariable("customerId") String strCustomerId, | 273 | @PathVariable("customerId") String strCustomerId, |
273 | - @RequestParam int limit, | 274 | + @RequestParam int pageSize, |
275 | + @RequestParam int page, | ||
274 | @RequestParam(required = false) String textSearch, | 276 | @RequestParam(required = false) String textSearch, |
275 | - @RequestParam(required = false) String idOffset, | ||
276 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 277 | + @RequestParam(required = false) String sortProperty, |
278 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
277 | checkParameter("customerId", strCustomerId); | 279 | checkParameter("customerId", strCustomerId); |
278 | try { | 280 | try { |
279 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); | 281 | CustomerId customerId = new CustomerId(toUUID(strCustomerId)); |
280 | checkCustomerId(customerId, Operation.READ); | 282 | checkCustomerId(customerId, Operation.READ); |
281 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 283 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
282 | TenantId tenantId = getCurrentUser().getTenantId(); | 284 | TenantId tenantId = getCurrentUser().getTenantId(); |
283 | return checkNotNull(userService.findCustomerUsers(tenantId, customerId, pageLink)); | 285 | return checkNotNull(userService.findCustomerUsers(tenantId, customerId, pageLink)); |
284 | } catch (Exception e) { | 286 | } catch (Exception e) { |
@@ -28,8 +28,8 @@ import org.springframework.web.bind.annotation.RestController; | @@ -28,8 +28,8 @@ import org.springframework.web.bind.annotation.RestController; | ||
28 | import org.thingsboard.server.common.data.exception.ThingsboardException; | 28 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
29 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 30 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
31 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
32 | -import org.thingsboard.server.common.data.page.TextPageLink; | 31 | +import org.thingsboard.server.common.data.page.PageData; |
32 | +import org.thingsboard.server.common.data.page.PageLink; | ||
33 | import org.thingsboard.server.common.data.security.Authority; | 33 | import org.thingsboard.server.common.data.security.Authority; |
34 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 34 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
35 | import org.thingsboard.server.dao.model.ModelConstants; | 35 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -92,15 +92,16 @@ public class WidgetsBundleController extends BaseController { | @@ -92,15 +92,16 @@ public class WidgetsBundleController extends BaseController { | ||
92 | } | 92 | } |
93 | 93 | ||
94 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") | 94 | @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") |
95 | - @RequestMapping(value = "/widgetsBundles", params = { "limit" }, method = RequestMethod.GET) | 95 | + @RequestMapping(value = "/widgetsBundles", params = {"pageSize", "page"}, method = RequestMethod.GET) |
96 | @ResponseBody | 96 | @ResponseBody |
97 | - public TextPageData<WidgetsBundle> getWidgetsBundles( | ||
98 | - @RequestParam int limit, | 97 | + public PageData<WidgetsBundle> getWidgetsBundles( |
98 | + @RequestParam int pageSize, | ||
99 | + @RequestParam int page, | ||
99 | @RequestParam(required = false) String textSearch, | 100 | @RequestParam(required = false) String textSearch, |
100 | - @RequestParam(required = false) String idOffset, | ||
101 | - @RequestParam(required = false) String textOffset) throws ThingsboardException { | 101 | + @RequestParam(required = false) String sortProperty, |
102 | + @RequestParam(required = false) String sortOrder) throws ThingsboardException { | ||
102 | try { | 103 | try { |
103 | - TextPageLink pageLink = createPageLink(limit, textSearch, idOffset, textOffset); | 104 | + PageLink pageLink = createPageLink(pageSize, page, textSearch, sortProperty, sortOrder); |
104 | if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { | 105 | if (getCurrentUser().getAuthority() == Authority.SYS_ADMIN) { |
105 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); | 106 | return checkNotNull(widgetsBundleService.findSystemWidgetsBundlesByPageLink(getTenantId(), pageLink)); |
106 | } else { | 107 | } else { |
@@ -22,8 +22,8 @@ import org.springframework.stereotype.Service; | @@ -22,8 +22,8 @@ import org.springframework.stereotype.Service; | ||
22 | import org.thingsboard.server.common.data.SearchTextBased; | 22 | import org.thingsboard.server.common.data.SearchTextBased; |
23 | import org.thingsboard.server.common.data.Tenant; | 23 | import org.thingsboard.server.common.data.Tenant; |
24 | import org.thingsboard.server.common.data.id.UUIDBased; | 24 | import org.thingsboard.server.common.data.id.UUIDBased; |
25 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
26 | -import org.thingsboard.server.common.data.page.TextPageLink; | 25 | +import org.thingsboard.server.common.data.page.PageData; |
26 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | import org.thingsboard.server.common.data.rule.RuleChain; | 27 | import org.thingsboard.server.common.data.rule.RuleChain; |
28 | import org.thingsboard.server.dao.rule.RuleChainService; | 28 | import org.thingsboard.server.dao.rule.RuleChainService; |
29 | import org.thingsboard.server.dao.tenant.TenantService; | 29 | import org.thingsboard.server.dao.tenant.TenantService; |
@@ -59,7 +59,7 @@ public class DefaultDataUpdateService implements DataUpdateService { | @@ -59,7 +59,7 @@ public class DefaultDataUpdateService implements DataUpdateService { | ||
59 | new PaginatedUpdater<String, Tenant>() { | 59 | new PaginatedUpdater<String, Tenant>() { |
60 | 60 | ||
61 | @Override | 61 | @Override |
62 | - protected TextPageData<Tenant> findEntities(String region, TextPageLink pageLink) { | 62 | + protected PageData<Tenant> findEntities(String region, PageLink pageLink) { |
63 | return tenantService.findTenants(pageLink); | 63 | return tenantService.findTenants(pageLink); |
64 | } | 64 | } |
65 | 65 |
@@ -17,29 +17,29 @@ package org.thingsboard.server.service.install.update; | @@ -17,29 +17,29 @@ package org.thingsboard.server.service.install.update; | ||
17 | 17 | ||
18 | import org.thingsboard.server.common.data.SearchTextBased; | 18 | import org.thingsboard.server.common.data.SearchTextBased; |
19 | import org.thingsboard.server.common.data.id.UUIDBased; | 19 | import org.thingsboard.server.common.data.id.UUIDBased; |
20 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
21 | -import org.thingsboard.server.common.data.page.TextPageLink; | 20 | +import org.thingsboard.server.common.data.page.PageData; |
21 | +import org.thingsboard.server.common.data.page.PageLink; | ||
22 | 22 | ||
23 | public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> { | 23 | public abstract class PaginatedUpdater<I, D extends SearchTextBased<? extends UUIDBased>> { |
24 | 24 | ||
25 | private static final int DEFAULT_LIMIT = 100; | 25 | private static final int DEFAULT_LIMIT = 100; |
26 | 26 | ||
27 | public void updateEntities(I id) { | 27 | public void updateEntities(I id) { |
28 | - TextPageLink pageLink = new TextPageLink(DEFAULT_LIMIT); | 28 | + PageLink pageLink = new PageLink(DEFAULT_LIMIT); |
29 | boolean hasNext = true; | 29 | boolean hasNext = true; |
30 | while (hasNext) { | 30 | while (hasNext) { |
31 | - TextPageData<D> entities = findEntities(id, pageLink); | 31 | + PageData<D> entities = findEntities(id, pageLink); |
32 | for (D entity : entities.getData()) { | 32 | for (D entity : entities.getData()) { |
33 | updateEntity(entity); | 33 | updateEntity(entity); |
34 | } | 34 | } |
35 | hasNext = entities.hasNext(); | 35 | hasNext = entities.hasNext(); |
36 | if (hasNext) { | 36 | if (hasNext) { |
37 | - pageLink = entities.getNextPageLink(); | 37 | + pageLink = pageLink.nextPageLink(); |
38 | } | 38 | } |
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | - protected abstract TextPageData<D> findEntities(I id, TextPageLink pageLink); | 42 | + protected abstract PageData<D> findEntities(I id, PageLink pageLink); |
43 | 43 | ||
44 | protected abstract void updateEntity(D entity); | 44 | protected abstract void updateEntity(D entity); |
45 | 45 |
@@ -112,8 +112,11 @@ public class DefaultMailService implements MailService { | @@ -112,8 +112,11 @@ public class DefaultMailService implements MailService { | ||
112 | } | 112 | } |
113 | } | 113 | } |
114 | javaMailProperties.put(MAIL_PROP + protocol + ".starttls.enable", enableTls); | 114 | javaMailProperties.put(MAIL_PROP + protocol + ".starttls.enable", enableTls); |
115 | - if (enableTls && jsonConfig.has("tlsVersion") && StringUtils.isNoneEmpty(jsonConfig.get("tlsVersion").asText())) { | ||
116 | - javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", jsonConfig.get("tlsVersion").asText()); | 115 | + if (enableTls && jsonConfig.has("tlsVersion") && !jsonConfig.get("tlsVersion").isNull()) { |
116 | + String tlsVersion = jsonConfig.get("tlsVersion").asText(); | ||
117 | + if (StringUtils.isNoneEmpty(tlsVersion)) { | ||
118 | + javaMailProperties.put(MAIL_PROP + protocol + ".ssl.protocols", tlsVersion); | ||
119 | + } | ||
117 | } | 120 | } |
118 | return javaMailProperties; | 121 | return javaMailProperties; |
119 | } | 122 | } |
@@ -39,13 +39,13 @@ import org.thingsboard.server.common.data.Tenant; | @@ -39,13 +39,13 @@ import org.thingsboard.server.common.data.Tenant; | ||
39 | import org.thingsboard.server.common.data.id.DeviceId; | 39 | import org.thingsboard.server.common.data.id.DeviceId; |
40 | import org.thingsboard.server.common.data.id.TenantId; | 40 | import org.thingsboard.server.common.data.id.TenantId; |
41 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; | 41 | import org.thingsboard.server.common.data.kv.AttributeKvEntry; |
42 | +import org.thingsboard.server.common.data.page.PageData; | ||
43 | +import org.thingsboard.server.common.data.page.PageLink; | ||
42 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; | 44 | import org.thingsboard.server.common.data.kv.BasicTsKvEntry; |
43 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; | 45 | import org.thingsboard.server.common.data.kv.BooleanDataEntry; |
44 | import org.thingsboard.server.common.data.kv.KvEntry; | 46 | import org.thingsboard.server.common.data.kv.KvEntry; |
45 | import org.thingsboard.server.common.data.kv.LongDataEntry; | 47 | import org.thingsboard.server.common.data.kv.LongDataEntry; |
46 | import org.thingsboard.server.common.data.kv.TsKvEntry; | 48 | import org.thingsboard.server.common.data.kv.TsKvEntry; |
47 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
48 | -import org.thingsboard.server.common.data.page.TextPageLink; | ||
49 | import org.thingsboard.server.common.msg.TbMsg; | 49 | import org.thingsboard.server.common.msg.TbMsg; |
50 | import org.thingsboard.server.common.msg.TbMsgDataType; | 50 | import org.thingsboard.server.common.msg.TbMsgDataType; |
51 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 51 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
@@ -227,13 +227,13 @@ public class DefaultDeviceStateService implements DeviceStateService { | @@ -227,13 +227,13 @@ public class DefaultDeviceStateService implements DeviceStateService { | ||
227 | 227 | ||
228 | private void onClusterUpdateSync() { | 228 | private void onClusterUpdateSync() { |
229 | clusterUpdatePending = false; | 229 | clusterUpdatePending = false; |
230 | - List<Tenant> tenants = tenantService.findTenants(new TextPageLink(Integer.MAX_VALUE)).getData(); | 230 | + List<Tenant> tenants = tenantService.findTenants(new PageLink(Integer.MAX_VALUE)).getData(); |
231 | for (Tenant tenant : tenants) { | 231 | for (Tenant tenant : tenants) { |
232 | List<ListenableFuture<DeviceStateData>> fetchFutures = new ArrayList<>(); | 232 | List<ListenableFuture<DeviceStateData>> fetchFutures = new ArrayList<>(); |
233 | - TextPageLink pageLink = new TextPageLink(initFetchPackSize); | 233 | + PageLink pageLink = new PageLink(initFetchPackSize); |
234 | while (pageLink != null) { | 234 | while (pageLink != null) { |
235 | - TextPageData<Device> page = deviceService.findDevicesByTenantId(tenant.getId(), pageLink); | ||
236 | - pageLink = page.getNextPageLink(); | 235 | + PageData<Device> page = deviceService.findDevicesByTenantId(tenant.getId(), pageLink); |
236 | + pageLink = page.hasNext() ? pageLink.nextPageLink() : null; | ||
237 | for (Device device : page.getData()) { | 237 | for (Device device : page.getData()) { |
238 | if (!routingService.resolveById(device.getId()).isPresent()) { | 238 | if (!routingService.resolveById(device.getId()).isPresent()) { |
239 | if (!deviceStates.containsKey(device.getId())) { | 239 | if (!deviceStates.containsKey(device.getId())) { |
@@ -260,13 +260,13 @@ public class DefaultDeviceStateService implements DeviceStateService { | @@ -260,13 +260,13 @@ public class DefaultDeviceStateService implements DeviceStateService { | ||
260 | 260 | ||
261 | private void initStateFromDB() { | 261 | private void initStateFromDB() { |
262 | try { | 262 | try { |
263 | - List<Tenant> tenants = tenantService.findTenants(new TextPageLink(Integer.MAX_VALUE)).getData(); | 263 | + List<Tenant> tenants = tenantService.findTenants(new PageLink(Integer.MAX_VALUE)).getData(); |
264 | for (Tenant tenant : tenants) { | 264 | for (Tenant tenant : tenants) { |
265 | List<ListenableFuture<DeviceStateData>> fetchFutures = new ArrayList<>(); | 265 | List<ListenableFuture<DeviceStateData>> fetchFutures = new ArrayList<>(); |
266 | - TextPageLink pageLink = new TextPageLink(initFetchPackSize); | 266 | + PageLink pageLink = new PageLink(initFetchPackSize); |
267 | while (pageLink != null) { | 267 | while (pageLink != null) { |
268 | - TextPageData<Device> page = deviceService.findDevicesByTenantId(tenant.getId(), pageLink); | ||
269 | - pageLink = page.getNextPageLink(); | 268 | + PageData<Device> page = deviceService.findDevicesByTenantId(tenant.getId(), pageLink); |
269 | + pageLink = page.hasNext() ? pageLink.nextPageLink() : null; | ||
270 | for (Device device : page.getData()) { | 270 | for (Device device : page.getData()) { |
271 | if (!routingService.resolveById(device.getId()).isPresent()) { | 271 | if (!routingService.resolveById(device.getId()).isPresent()) { |
272 | fetchFutures.add(fetchDeviceState(device)); | 272 | fetchFutures.add(fetchDeviceState(device)); |
@@ -119,8 +119,6 @@ dashboard: | @@ -119,8 +119,6 @@ dashboard: | ||
119 | 119 | ||
120 | database: | 120 | database: |
121 | ts_max_intervals: "${DATABASE_TS_MAX_INTERVALS:700}" # Max number of DB queries generated by single API call to fetch telemetry records | 121 | ts_max_intervals: "${DATABASE_TS_MAX_INTERVALS:700}" # Max number of DB queries generated by single API call to fetch telemetry records |
122 | - entities: | ||
123 | - type: "${DATABASE_ENTITIES_TYPE:sql}" # cassandra OR sql | ||
124 | ts: | 122 | ts: |
125 | type: "${DATABASE_TS_TYPE:sql}" # cassandra, sql, or timescale (for hybrid mode, DATABASE_TS_TYPE value should be cassandra, or timescale) | 123 | type: "${DATABASE_TS_TYPE:sql}" # cassandra, sql, or timescale (for hybrid mode, DATABASE_TS_TYPE value should be cassandra, or timescale) |
126 | 124 | ||
@@ -366,6 +364,7 @@ spring.resources.chain: | @@ -366,6 +364,7 @@ spring.resources.chain: | ||
366 | enabled: "true" | 364 | enabled: "true" |
367 | 365 | ||
368 | spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation: "true" | 366 | spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation: "true" |
367 | +spring.jpa.properties.hibernate.order_by.default_null_ordering: "last" | ||
369 | 368 | ||
370 | # SQL DAO Configuration | 369 | # SQL DAO Configuration |
371 | spring: | 370 | spring: |
@@ -65,7 +65,8 @@ import org.thingsboard.server.common.data.Tenant; | @@ -65,7 +65,8 @@ import org.thingsboard.server.common.data.Tenant; | ||
65 | import org.thingsboard.server.common.data.User; | 65 | import org.thingsboard.server.common.data.User; |
66 | import org.thingsboard.server.common.data.id.TenantId; | 66 | import org.thingsboard.server.common.data.id.TenantId; |
67 | import org.thingsboard.server.common.data.id.UUIDBased; | 67 | import org.thingsboard.server.common.data.id.UUIDBased; |
68 | -import org.thingsboard.server.common.data.page.TextPageLink; | 68 | +import org.thingsboard.server.common.data.page.PageLink; |
69 | +import org.thingsboard.server.common.data.page.SortOrder; | ||
69 | import org.thingsboard.server.common.data.page.TimePageLink; | 70 | import org.thingsboard.server.common.data.page.TimePageLink; |
70 | import org.thingsboard.server.common.data.security.Authority; | 71 | import org.thingsboard.server.common.data.security.Authority; |
71 | import org.thingsboard.server.config.ThingsboardSecurityConfiguration; | 72 | import org.thingsboard.server.config.ThingsboardSecurityConfiguration; |
@@ -314,22 +315,20 @@ public abstract class AbstractControllerTest { | @@ -314,22 +315,20 @@ public abstract class AbstractControllerTest { | ||
314 | } | 315 | } |
315 | 316 | ||
316 | protected <T> T doGetTypedWithPageLink(String urlTemplate, TypeReference<T> responseType, | 317 | protected <T> T doGetTypedWithPageLink(String urlTemplate, TypeReference<T> responseType, |
317 | - TextPageLink pageLink, | 318 | + PageLink pageLink, |
318 | Object... urlVariables) throws Exception { | 319 | Object... urlVariables) throws Exception { |
319 | List<Object> pageLinkVariables = new ArrayList<>(); | 320 | List<Object> pageLinkVariables = new ArrayList<>(); |
320 | - urlTemplate += "limit={limit}"; | ||
321 | - pageLinkVariables.add(pageLink.getLimit()); | 321 | + urlTemplate += "pageSize={pageSize}&page={page}"; |
322 | + pageLinkVariables.add(pageLink.getPageSize()); | ||
323 | + pageLinkVariables.add(pageLink.getPage()); | ||
322 | if (StringUtils.isNotEmpty(pageLink.getTextSearch())) { | 324 | if (StringUtils.isNotEmpty(pageLink.getTextSearch())) { |
323 | urlTemplate += "&textSearch={textSearch}"; | 325 | urlTemplate += "&textSearch={textSearch}"; |
324 | pageLinkVariables.add(pageLink.getTextSearch()); | 326 | pageLinkVariables.add(pageLink.getTextSearch()); |
325 | } | 327 | } |
326 | - if (pageLink.getIdOffset() != null) { | ||
327 | - urlTemplate += "&idOffset={idOffset}"; | ||
328 | - pageLinkVariables.add(pageLink.getIdOffset().toString()); | ||
329 | - } | ||
330 | - if (StringUtils.isNotEmpty(pageLink.getTextOffset())) { | ||
331 | - urlTemplate += "&textOffset={textOffset}"; | ||
332 | - pageLinkVariables.add(pageLink.getTextOffset()); | 328 | + if (pageLink.getSortOrder() != null) { |
329 | + urlTemplate += "&sortProperty={sortProperty}&sortOrder={sortOrder}"; | ||
330 | + pageLinkVariables.add(pageLink.getSortOrder().getProperty()); | ||
331 | + pageLinkVariables.add(pageLink.getSortOrder().getDirection().name()); | ||
333 | } | 332 | } |
334 | 333 | ||
335 | Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()]; | 334 | Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()]; |
@@ -343,8 +342,9 @@ public abstract class AbstractControllerTest { | @@ -343,8 +342,9 @@ public abstract class AbstractControllerTest { | ||
343 | TimePageLink pageLink, | 342 | TimePageLink pageLink, |
344 | Object... urlVariables) throws Exception { | 343 | Object... urlVariables) throws Exception { |
345 | List<Object> pageLinkVariables = new ArrayList<>(); | 344 | List<Object> pageLinkVariables = new ArrayList<>(); |
346 | - urlTemplate += "limit={limit}"; | ||
347 | - pageLinkVariables.add(pageLink.getLimit()); | 345 | + urlTemplate += "pageSize={pageSize}&page={page}"; |
346 | + pageLinkVariables.add(pageLink.getPageSize()); | ||
347 | + pageLinkVariables.add(pageLink.getPage()); | ||
348 | if (pageLink.getStartTime() != null) { | 348 | if (pageLink.getStartTime() != null) { |
349 | urlTemplate += "&startTime={startTime}"; | 349 | urlTemplate += "&startTime={startTime}"; |
350 | pageLinkVariables.add(pageLink.getStartTime()); | 350 | pageLinkVariables.add(pageLink.getStartTime()); |
@@ -353,13 +353,14 @@ public abstract class AbstractControllerTest { | @@ -353,13 +353,14 @@ public abstract class AbstractControllerTest { | ||
353 | urlTemplate += "&endTime={endTime}"; | 353 | urlTemplate += "&endTime={endTime}"; |
354 | pageLinkVariables.add(pageLink.getEndTime()); | 354 | pageLinkVariables.add(pageLink.getEndTime()); |
355 | } | 355 | } |
356 | - if (pageLink.getIdOffset() != null) { | ||
357 | - urlTemplate += "&offset={offset}"; | ||
358 | - pageLinkVariables.add(pageLink.getIdOffset().toString()); | 356 | + if (StringUtils.isNotEmpty(pageLink.getTextSearch())) { |
357 | + urlTemplate += "&textSearch={textSearch}"; | ||
358 | + pageLinkVariables.add(pageLink.getTextSearch()); | ||
359 | } | 359 | } |
360 | - if (pageLink.isAscOrder()) { | ||
361 | - urlTemplate += "&ascOrder={ascOrder}"; | ||
362 | - pageLinkVariables.add(pageLink.isAscOrder()); | 360 | + if (pageLink.getSortOrder() != null) { |
361 | + urlTemplate += "&sortProperty={sortProperty}&sortOrder={sortOrder}"; | ||
362 | + pageLinkVariables.add(pageLink.getSortOrder().getProperty()); | ||
363 | + pageLinkVariables.add(pageLink.getSortOrder().getDirection().name()); | ||
363 | } | 364 | } |
364 | Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()]; | 365 | Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()]; |
365 | System.arraycopy(urlVariables, 0, vars, 0, urlVariables.length); | 366 | System.arraycopy(urlVariables, 0, vars, 0, urlVariables.length); |
@@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.Event; | @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.Event; | ||
23 | import org.thingsboard.server.common.data.id.EntityId; | 23 | import org.thingsboard.server.common.data.id.EntityId; |
24 | import org.thingsboard.server.common.data.id.RuleChainId; | 24 | import org.thingsboard.server.common.data.id.RuleChainId; |
25 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | -import org.thingsboard.server.common.data.page.TimePageData; | 26 | +import org.thingsboard.server.common.data.page.PageData; |
27 | import org.thingsboard.server.common.data.page.TimePageLink; | 27 | import org.thingsboard.server.common.data.page.TimePageLink; |
28 | import org.thingsboard.server.common.data.rule.RuleChain; | 28 | import org.thingsboard.server.common.data.rule.RuleChain; |
29 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 29 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
@@ -56,10 +56,10 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest { | @@ -56,10 +56,10 @@ public class AbstractRuleEngineControllerTest extends AbstractControllerTest { | ||
56 | return doGet("/api/ruleChain/metadata/" + ruleChainId.getId().toString(), RuleChainMetaData.class); | 56 | return doGet("/api/ruleChain/metadata/" + ruleChainId.getId().toString(), RuleChainMetaData.class); |
57 | } | 57 | } |
58 | 58 | ||
59 | - protected TimePageData<Event> getDebugEvents(TenantId tenantId, EntityId entityId, int limit) throws Exception { | 59 | + protected PageData<Event> getDebugEvents(TenantId tenantId, EntityId entityId, int limit) throws Exception { |
60 | TimePageLink pageLink = new TimePageLink(limit); | 60 | TimePageLink pageLink = new TimePageLink(limit); |
61 | return doGetTypedWithTimePageLink("/api/events/{entityType}/{entityId}/{eventType}?tenantId={tenantId}&", | 61 | return doGetTypedWithTimePageLink("/api/events/{entityType}/{entityId}/{eventType}?tenantId={tenantId}&", |
62 | - new TypeReference<TimePageData<Event>>() { | 62 | + new TypeReference<PageData<Event>>() { |
63 | }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG_RULE_NODE, tenantId.getId()); | 63 | }, pageLink, entityId.getEntityType(), entityId.getId(), DataConstants.DEBUG_RULE_NODE, tenantId.getId()); |
64 | } | 64 | } |
65 | 65 |
@@ -28,8 +28,8 @@ import org.thingsboard.server.common.data.Tenant; | @@ -28,8 +28,8 @@ import org.thingsboard.server.common.data.Tenant; | ||
28 | import org.thingsboard.server.common.data.User; | 28 | import org.thingsboard.server.common.data.User; |
29 | import org.thingsboard.server.common.data.asset.Asset; | 29 | import org.thingsboard.server.common.data.asset.Asset; |
30 | import org.thingsboard.server.common.data.id.CustomerId; | 30 | import org.thingsboard.server.common.data.id.CustomerId; |
31 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
32 | -import org.thingsboard.server.common.data.page.TextPageLink; | 31 | +import org.thingsboard.server.common.data.page.PageData; |
32 | +import org.thingsboard.server.common.data.page.PageLink; | ||
33 | import org.thingsboard.server.common.data.security.Authority; | 33 | import org.thingsboard.server.common.data.security.Authority; |
34 | import org.thingsboard.server.dao.model.ModelConstants; | 34 | import org.thingsboard.server.dao.model.ModelConstants; |
35 | 35 | ||
@@ -258,14 +258,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -258,14 +258,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
258 | assets.add(doPost("/api/asset", asset, Asset.class)); | 258 | assets.add(doPost("/api/asset", asset, Asset.class)); |
259 | } | 259 | } |
260 | List<Asset> loadedAssets = new ArrayList<>(); | 260 | List<Asset> loadedAssets = new ArrayList<>(); |
261 | - TextPageLink pageLink = new TextPageLink(23); | ||
262 | - TextPageData<Asset> pageData = null; | 261 | + PageLink pageLink = new PageLink(23); |
262 | + PageData<Asset> pageData = null; | ||
263 | do { | 263 | do { |
264 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", | 264 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", |
265 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 265 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
266 | loadedAssets.addAll(pageData.getData()); | 266 | loadedAssets.addAll(pageData.getData()); |
267 | if (pageData.hasNext()) { | 267 | if (pageData.hasNext()) { |
268 | - pageLink = pageData.getNextPageLink(); | 268 | + pageLink = pageLink.nextPageLink(); |
269 | } | 269 | } |
270 | } while (pageData.hasNext()); | 270 | } while (pageData.hasNext()); |
271 | 271 | ||
@@ -301,14 +301,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -301,14 +301,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
301 | } | 301 | } |
302 | 302 | ||
303 | List<Asset> loadedAssetsTitle1 = new ArrayList<>(); | 303 | List<Asset> loadedAssetsTitle1 = new ArrayList<>(); |
304 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
305 | - TextPageData<Asset> pageData = null; | 304 | + PageLink pageLink = new PageLink(15, 0, title1); |
305 | + PageData<Asset> pageData = null; | ||
306 | do { | 306 | do { |
307 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", | 307 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", |
308 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 308 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
309 | loadedAssetsTitle1.addAll(pageData.getData()); | 309 | loadedAssetsTitle1.addAll(pageData.getData()); |
310 | if (pageData.hasNext()) { | 310 | if (pageData.hasNext()) { |
311 | - pageLink = pageData.getNextPageLink(); | 311 | + pageLink = pageLink.nextPageLink(); |
312 | } | 312 | } |
313 | } while (pageData.hasNext()); | 313 | } while (pageData.hasNext()); |
314 | 314 | ||
@@ -318,13 +318,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -318,13 +318,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
318 | Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); | 318 | Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); |
319 | 319 | ||
320 | List<Asset> loadedAssetsTitle2 = new ArrayList<>(); | 320 | List<Asset> loadedAssetsTitle2 = new ArrayList<>(); |
321 | - pageLink = new TextPageLink(4, title2); | 321 | + pageLink = new PageLink(4, 0, title2); |
322 | do { | 322 | do { |
323 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", | 323 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", |
324 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 324 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
325 | loadedAssetsTitle2.addAll(pageData.getData()); | 325 | loadedAssetsTitle2.addAll(pageData.getData()); |
326 | if (pageData.hasNext()) { | 326 | if (pageData.hasNext()) { |
327 | - pageLink = pageData.getNextPageLink(); | 327 | + pageLink = pageLink.nextPageLink(); |
328 | } | 328 | } |
329 | } while (pageData.hasNext()); | 329 | } while (pageData.hasNext()); |
330 | 330 | ||
@@ -338,9 +338,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -338,9 +338,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
338 | .andExpect(status().isOk()); | 338 | .andExpect(status().isOk()); |
339 | } | 339 | } |
340 | 340 | ||
341 | - pageLink = new TextPageLink(4, title1); | 341 | + pageLink = new PageLink(4, 0, title1); |
342 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", | 342 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", |
343 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 343 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
344 | Assert.assertFalse(pageData.hasNext()); | 344 | Assert.assertFalse(pageData.hasNext()); |
345 | Assert.assertEquals(0, pageData.getData().size()); | 345 | Assert.assertEquals(0, pageData.getData().size()); |
346 | 346 | ||
@@ -349,9 +349,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -349,9 +349,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
349 | .andExpect(status().isOk()); | 349 | .andExpect(status().isOk()); |
350 | } | 350 | } |
351 | 351 | ||
352 | - pageLink = new TextPageLink(4, title2); | 352 | + pageLink = new PageLink(4, 0, title2); |
353 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", | 353 | pageData = doGetTypedWithPageLink("/api/tenant/assets?", |
354 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 354 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
355 | Assert.assertFalse(pageData.hasNext()); | 355 | Assert.assertFalse(pageData.hasNext()); |
356 | Assert.assertEquals(0, pageData.getData().size()); | 356 | Assert.assertEquals(0, pageData.getData().size()); |
357 | } | 357 | } |
@@ -384,14 +384,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -384,14 +384,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
384 | } | 384 | } |
385 | 385 | ||
386 | List<Asset> loadedAssetsType1 = new ArrayList<>(); | 386 | List<Asset> loadedAssetsType1 = new ArrayList<>(); |
387 | - TextPageLink pageLink = new TextPageLink(15); | ||
388 | - TextPageData<Asset> pageData = null; | 387 | + PageLink pageLink = new PageLink(15); |
388 | + PageData<Asset> pageData = null; | ||
389 | do { | 389 | do { |
390 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | 390 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", |
391 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | 391 | + new TypeReference<PageData<Asset>>(){}, pageLink, type1); |
392 | loadedAssetsType1.addAll(pageData.getData()); | 392 | loadedAssetsType1.addAll(pageData.getData()); |
393 | if (pageData.hasNext()) { | 393 | if (pageData.hasNext()) { |
394 | - pageLink = pageData.getNextPageLink(); | 394 | + pageLink = pageLink.nextPageLink(); |
395 | } | 395 | } |
396 | } while (pageData.hasNext()); | 396 | } while (pageData.hasNext()); |
397 | 397 | ||
@@ -401,13 +401,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -401,13 +401,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
401 | Assert.assertEquals(assetsType1, loadedAssetsType1); | 401 | Assert.assertEquals(assetsType1, loadedAssetsType1); |
402 | 402 | ||
403 | List<Asset> loadedAssetsType2 = new ArrayList<>(); | 403 | List<Asset> loadedAssetsType2 = new ArrayList<>(); |
404 | - pageLink = new TextPageLink(4); | 404 | + pageLink = new PageLink(4); |
405 | do { | 405 | do { |
406 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | 406 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", |
407 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | 407 | + new TypeReference<PageData<Asset>>(){}, pageLink, type2); |
408 | loadedAssetsType2.addAll(pageData.getData()); | 408 | loadedAssetsType2.addAll(pageData.getData()); |
409 | if (pageData.hasNext()) { | 409 | if (pageData.hasNext()) { |
410 | - pageLink = pageData.getNextPageLink(); | 410 | + pageLink = pageLink.nextPageLink(); |
411 | } | 411 | } |
412 | } while (pageData.hasNext()); | 412 | } while (pageData.hasNext()); |
413 | 413 | ||
@@ -421,9 +421,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -421,9 +421,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
421 | .andExpect(status().isOk()); | 421 | .andExpect(status().isOk()); |
422 | } | 422 | } |
423 | 423 | ||
424 | - pageLink = new TextPageLink(4); | 424 | + pageLink = new PageLink(4); |
425 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | 425 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", |
426 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | 426 | + new TypeReference<PageData<Asset>>(){}, pageLink, type1); |
427 | Assert.assertFalse(pageData.hasNext()); | 427 | Assert.assertFalse(pageData.hasNext()); |
428 | Assert.assertEquals(0, pageData.getData().size()); | 428 | Assert.assertEquals(0, pageData.getData().size()); |
429 | 429 | ||
@@ -432,9 +432,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -432,9 +432,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
432 | .andExpect(status().isOk()); | 432 | .andExpect(status().isOk()); |
433 | } | 433 | } |
434 | 434 | ||
435 | - pageLink = new TextPageLink(4); | 435 | + pageLink = new PageLink(4); |
436 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", | 436 | pageData = doGetTypedWithPageLink("/api/tenant/assets?type={type}&", |
437 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | 437 | + new TypeReference<PageData<Asset>>(){}, pageLink, type2); |
438 | Assert.assertFalse(pageData.hasNext()); | 438 | Assert.assertFalse(pageData.hasNext()); |
439 | Assert.assertEquals(0, pageData.getData().size()); | 439 | Assert.assertEquals(0, pageData.getData().size()); |
440 | } | 440 | } |
@@ -457,14 +457,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -457,14 +457,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
457 | } | 457 | } |
458 | 458 | ||
459 | List<Asset> loadedAssets = new ArrayList<>(); | 459 | List<Asset> loadedAssets = new ArrayList<>(); |
460 | - TextPageLink pageLink = new TextPageLink(23); | ||
461 | - TextPageData<Asset> pageData = null; | 460 | + PageLink pageLink = new PageLink(23); |
461 | + PageData<Asset> pageData = null; | ||
462 | do { | 462 | do { |
463 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | 463 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", |
464 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 464 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
465 | loadedAssets.addAll(pageData.getData()); | 465 | loadedAssets.addAll(pageData.getData()); |
466 | if (pageData.hasNext()) { | 466 | if (pageData.hasNext()) { |
467 | - pageLink = pageData.getNextPageLink(); | 467 | + pageLink = pageLink.nextPageLink(); |
468 | } | 468 | } |
469 | } while (pageData.hasNext()); | 469 | } while (pageData.hasNext()); |
470 | 470 | ||
@@ -509,14 +509,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -509,14 +509,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
509 | } | 509 | } |
510 | 510 | ||
511 | List<Asset> loadedAssetsTitle1 = new ArrayList<>(); | 511 | List<Asset> loadedAssetsTitle1 = new ArrayList<>(); |
512 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
513 | - TextPageData<Asset> pageData = null; | 512 | + PageLink pageLink = new PageLink(15, 0, title1); |
513 | + PageData<Asset> pageData = null; | ||
514 | do { | 514 | do { |
515 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | 515 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", |
516 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 516 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
517 | loadedAssetsTitle1.addAll(pageData.getData()); | 517 | loadedAssetsTitle1.addAll(pageData.getData()); |
518 | if (pageData.hasNext()) { | 518 | if (pageData.hasNext()) { |
519 | - pageLink = pageData.getNextPageLink(); | 519 | + pageLink = pageLink.nextPageLink(); |
520 | } | 520 | } |
521 | } while (pageData.hasNext()); | 521 | } while (pageData.hasNext()); |
522 | 522 | ||
@@ -526,13 +526,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -526,13 +526,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
526 | Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); | 526 | Assert.assertEquals(assetsTitle1, loadedAssetsTitle1); |
527 | 527 | ||
528 | List<Asset> loadedAssetsTitle2 = new ArrayList<>(); | 528 | List<Asset> loadedAssetsTitle2 = new ArrayList<>(); |
529 | - pageLink = new TextPageLink(4, title2); | 529 | + pageLink = new PageLink(4, 0, title2); |
530 | do { | 530 | do { |
531 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | 531 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", |
532 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 532 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
533 | loadedAssetsTitle2.addAll(pageData.getData()); | 533 | loadedAssetsTitle2.addAll(pageData.getData()); |
534 | if (pageData.hasNext()) { | 534 | if (pageData.hasNext()) { |
535 | - pageLink = pageData.getNextPageLink(); | 535 | + pageLink = pageLink.nextPageLink(); |
536 | } | 536 | } |
537 | } while (pageData.hasNext()); | 537 | } while (pageData.hasNext()); |
538 | 538 | ||
@@ -546,9 +546,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -546,9 +546,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
546 | .andExpect(status().isOk()); | 546 | .andExpect(status().isOk()); |
547 | } | 547 | } |
548 | 548 | ||
549 | - pageLink = new TextPageLink(4, title1); | 549 | + pageLink = new PageLink(4, 0, title1); |
550 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | 550 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", |
551 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 551 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
552 | Assert.assertFalse(pageData.hasNext()); | 552 | Assert.assertFalse(pageData.hasNext()); |
553 | Assert.assertEquals(0, pageData.getData().size()); | 553 | Assert.assertEquals(0, pageData.getData().size()); |
554 | 554 | ||
@@ -557,9 +557,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -557,9 +557,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
557 | .andExpect(status().isOk()); | 557 | .andExpect(status().isOk()); |
558 | } | 558 | } |
559 | 559 | ||
560 | - pageLink = new TextPageLink(4, title2); | 560 | + pageLink = new PageLink(4, 0, title2); |
561 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", | 561 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?", |
562 | - new TypeReference<TextPageData<Asset>>(){}, pageLink); | 562 | + new TypeReference<PageData<Asset>>(){}, pageLink); |
563 | Assert.assertFalse(pageData.hasNext()); | 563 | Assert.assertFalse(pageData.hasNext()); |
564 | Assert.assertEquals(0, pageData.getData().size()); | 564 | Assert.assertEquals(0, pageData.getData().size()); |
565 | } | 565 | } |
@@ -601,14 +601,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -601,14 +601,14 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
601 | } | 601 | } |
602 | 602 | ||
603 | List<Asset> loadedAssetsType1 = new ArrayList<>(); | 603 | List<Asset> loadedAssetsType1 = new ArrayList<>(); |
604 | - TextPageLink pageLink = new TextPageLink(15); | ||
605 | - TextPageData<Asset> pageData = null; | 604 | + PageLink pageLink = new PageLink(15); |
605 | + PageData<Asset> pageData = null; | ||
606 | do { | 606 | do { |
607 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | 607 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", |
608 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | 608 | + new TypeReference<PageData<Asset>>(){}, pageLink, type1); |
609 | loadedAssetsType1.addAll(pageData.getData()); | 609 | loadedAssetsType1.addAll(pageData.getData()); |
610 | if (pageData.hasNext()) { | 610 | if (pageData.hasNext()) { |
611 | - pageLink = pageData.getNextPageLink(); | 611 | + pageLink = pageLink.nextPageLink(); |
612 | } | 612 | } |
613 | } while (pageData.hasNext()); | 613 | } while (pageData.hasNext()); |
614 | 614 | ||
@@ -618,13 +618,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -618,13 +618,13 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
618 | Assert.assertEquals(assetsType1, loadedAssetsType1); | 618 | Assert.assertEquals(assetsType1, loadedAssetsType1); |
619 | 619 | ||
620 | List<Asset> loadedAssetsType2 = new ArrayList<>(); | 620 | List<Asset> loadedAssetsType2 = new ArrayList<>(); |
621 | - pageLink = new TextPageLink(4); | 621 | + pageLink = new PageLink(4); |
622 | do { | 622 | do { |
623 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | 623 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", |
624 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | 624 | + new TypeReference<PageData<Asset>>(){}, pageLink, type2); |
625 | loadedAssetsType2.addAll(pageData.getData()); | 625 | loadedAssetsType2.addAll(pageData.getData()); |
626 | if (pageData.hasNext()) { | 626 | if (pageData.hasNext()) { |
627 | - pageLink = pageData.getNextPageLink(); | 627 | + pageLink = pageLink.nextPageLink(); |
628 | } | 628 | } |
629 | } while (pageData.hasNext()); | 629 | } while (pageData.hasNext()); |
630 | 630 | ||
@@ -638,9 +638,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -638,9 +638,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
638 | .andExpect(status().isOk()); | 638 | .andExpect(status().isOk()); |
639 | } | 639 | } |
640 | 640 | ||
641 | - pageLink = new TextPageLink(4); | 641 | + pageLink = new PageLink(4); |
642 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | 642 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", |
643 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type1); | 643 | + new TypeReference<PageData<Asset>>(){}, pageLink, type1); |
644 | Assert.assertFalse(pageData.hasNext()); | 644 | Assert.assertFalse(pageData.hasNext()); |
645 | Assert.assertEquals(0, pageData.getData().size()); | 645 | Assert.assertEquals(0, pageData.getData().size()); |
646 | 646 | ||
@@ -649,9 +649,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | @@ -649,9 +649,9 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { | ||
649 | .andExpect(status().isOk()); | 649 | .andExpect(status().isOk()); |
650 | } | 650 | } |
651 | 651 | ||
652 | - pageLink = new TextPageLink(4); | 652 | + pageLink = new PageLink(4); |
653 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", | 653 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/assets?type={type}&", |
654 | - new TypeReference<TextPageData<Asset>>(){}, pageLink, type2); | 654 | + new TypeReference<PageData<Asset>>(){}, pageLink, type2); |
655 | Assert.assertFalse(pageData.hasNext()); | 655 | Assert.assertFalse(pageData.hasNext()); |
656 | Assert.assertEquals(0, pageData.getData().size()); | 656 | Assert.assertEquals(0, pageData.getData().size()); |
657 | } | 657 | } |
@@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.Device; | @@ -24,7 +24,7 @@ import org.thingsboard.server.common.data.Device; | ||
24 | import org.thingsboard.server.common.data.Tenant; | 24 | import org.thingsboard.server.common.data.Tenant; |
25 | import org.thingsboard.server.common.data.User; | 25 | import org.thingsboard.server.common.data.User; |
26 | import org.thingsboard.server.common.data.audit.AuditLog; | 26 | import org.thingsboard.server.common.data.audit.AuditLog; |
27 | -import org.thingsboard.server.common.data.page.TimePageData; | 27 | +import org.thingsboard.server.common.data.page.PageData; |
28 | import org.thingsboard.server.common.data.page.TimePageLink; | 28 | import org.thingsboard.server.common.data.page.TimePageLink; |
29 | import org.thingsboard.server.common.data.security.Authority; | 29 | import org.thingsboard.server.common.data.security.Authority; |
30 | import org.thingsboard.server.dao.model.ModelConstants; | 30 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -77,14 +77,14 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | @@ -77,14 +77,14 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | ||
77 | 77 | ||
78 | List<AuditLog> loadedAuditLogs = new ArrayList<>(); | 78 | List<AuditLog> loadedAuditLogs = new ArrayList<>(); |
79 | TimePageLink pageLink = new TimePageLink(23); | 79 | TimePageLink pageLink = new TimePageLink(23); |
80 | - TimePageData<AuditLog> pageData; | 80 | + PageData<AuditLog> pageData; |
81 | do { | 81 | do { |
82 | pageData = doGetTypedWithTimePageLink("/api/audit/logs?", | 82 | pageData = doGetTypedWithTimePageLink("/api/audit/logs?", |
83 | - new TypeReference<TimePageData<AuditLog>>() { | 83 | + new TypeReference<PageData<AuditLog>>() { |
84 | }, pageLink); | 84 | }, pageLink); |
85 | loadedAuditLogs.addAll(pageData.getData()); | 85 | loadedAuditLogs.addAll(pageData.getData()); |
86 | if (pageData.hasNext()) { | 86 | if (pageData.hasNext()) { |
87 | - pageLink = pageData.getNextPageLink(); | 87 | + pageLink = pageLink.nextPageLink(); |
88 | } | 88 | } |
89 | } while (pageData.hasNext()); | 89 | } while (pageData.hasNext()); |
90 | 90 | ||
@@ -94,11 +94,11 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | @@ -94,11 +94,11 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | ||
94 | pageLink = new TimePageLink(23); | 94 | pageLink = new TimePageLink(23); |
95 | do { | 95 | do { |
96 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/customer/" + ModelConstants.NULL_UUID + "?", | 96 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/customer/" + ModelConstants.NULL_UUID + "?", |
97 | - new TypeReference<TimePageData<AuditLog>>() { | 97 | + new TypeReference<PageData<AuditLog>>() { |
98 | }, pageLink); | 98 | }, pageLink); |
99 | loadedAuditLogs.addAll(pageData.getData()); | 99 | loadedAuditLogs.addAll(pageData.getData()); |
100 | if (pageData.hasNext()) { | 100 | if (pageData.hasNext()) { |
101 | - pageLink = pageData.getNextPageLink(); | 101 | + pageLink = pageLink.nextPageLink(); |
102 | } | 102 | } |
103 | } while (pageData.hasNext()); | 103 | } while (pageData.hasNext()); |
104 | 104 | ||
@@ -108,11 +108,11 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | @@ -108,11 +108,11 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | ||
108 | pageLink = new TimePageLink(23); | 108 | pageLink = new TimePageLink(23); |
109 | do { | 109 | do { |
110 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/user/" + tenantAdmin.getId().getId().toString() + "?", | 110 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/user/" + tenantAdmin.getId().getId().toString() + "?", |
111 | - new TypeReference<TimePageData<AuditLog>>() { | 111 | + new TypeReference<PageData<AuditLog>>() { |
112 | }, pageLink); | 112 | }, pageLink); |
113 | loadedAuditLogs.addAll(pageData.getData()); | 113 | loadedAuditLogs.addAll(pageData.getData()); |
114 | if (pageData.hasNext()) { | 114 | if (pageData.hasNext()) { |
115 | - pageLink = pageData.getNextPageLink(); | 115 | + pageLink = pageLink.nextPageLink(); |
116 | } | 116 | } |
117 | } while (pageData.hasNext()); | 117 | } while (pageData.hasNext()); |
118 | 118 | ||
@@ -132,14 +132,14 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | @@ -132,14 +132,14 @@ public abstract class BaseAuditLogControllerTest extends AbstractControllerTest | ||
132 | 132 | ||
133 | List<AuditLog> loadedAuditLogs = new ArrayList<>(); | 133 | List<AuditLog> loadedAuditLogs = new ArrayList<>(); |
134 | TimePageLink pageLink = new TimePageLink(23); | 134 | TimePageLink pageLink = new TimePageLink(23); |
135 | - TimePageData<AuditLog> pageData; | 135 | + PageData<AuditLog> pageData; |
136 | do { | 136 | do { |
137 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/entity/DEVICE/" + savedDevice.getId().getId() + "?", | 137 | pageData = doGetTypedWithTimePageLink("/api/audit/logs/entity/DEVICE/" + savedDevice.getId().getId() + "?", |
138 | - new TypeReference<TimePageData<AuditLog>>() { | 138 | + new TypeReference<PageData<AuditLog>>() { |
139 | }, pageLink); | 139 | }, pageLink); |
140 | loadedAuditLogs.addAll(pageData.getData()); | 140 | loadedAuditLogs.addAll(pageData.getData()); |
141 | if (pageData.hasNext()) { | 141 | if (pageData.hasNext()) { |
142 | - pageLink = pageData.getNextPageLink(); | 142 | + pageLink = pageLink.nextPageLink(); |
143 | } | 143 | } |
144 | } while (pageData.hasNext()); | 144 | } while (pageData.hasNext()); |
145 | 145 |
@@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.Customer; | @@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.Customer; | ||
27 | import org.thingsboard.server.common.data.Tenant; | 27 | import org.thingsboard.server.common.data.Tenant; |
28 | import org.thingsboard.server.common.data.User; | 28 | import org.thingsboard.server.common.data.User; |
29 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
31 | -import org.thingsboard.server.common.data.page.TextPageLink; | 30 | +import org.thingsboard.server.common.data.page.PageData; |
31 | +import org.thingsboard.server.common.data.page.PageLink; | ||
32 | import org.thingsboard.server.common.data.security.Authority; | 32 | import org.thingsboard.server.common.data.security.Authority; |
33 | import org.junit.Assert; | 33 | import org.junit.Assert; |
34 | import org.junit.Test; | 34 | import org.junit.Test; |
@@ -241,13 +241,13 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -241,13 +241,13 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
241 | } | 241 | } |
242 | 242 | ||
243 | List<Customer> loadedCustomers = new ArrayList<>(); | 243 | List<Customer> loadedCustomers = new ArrayList<>(); |
244 | - TextPageLink pageLink = new TextPageLink(23); | ||
245 | - TextPageData<Customer> pageData = null; | 244 | + PageLink pageLink = new PageLink(23); |
245 | + PageData<Customer> pageData = null; | ||
246 | do { | 246 | do { |
247 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 247 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<PageData<Customer>>(){}, pageLink); |
248 | loadedCustomers.addAll(pageData.getData()); | 248 | loadedCustomers.addAll(pageData.getData()); |
249 | if (pageData.hasNext()) { | 249 | if (pageData.hasNext()) { |
250 | - pageLink = pageData.getNextPageLink(); | 250 | + pageLink = pageLink.nextPageLink(); |
251 | } | 251 | } |
252 | } while (pageData.hasNext()); | 252 | } while (pageData.hasNext()); |
253 | 253 | ||
@@ -307,13 +307,13 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -307,13 +307,13 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
307 | } | 307 | } |
308 | 308 | ||
309 | List<Customer> loadedCustomersTitle1 = new ArrayList<>(); | 309 | List<Customer> loadedCustomersTitle1 = new ArrayList<>(); |
310 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
311 | - TextPageData<Customer> pageData = null; | 310 | + PageLink pageLink = new PageLink(15, 0, title1); |
311 | + PageData<Customer> pageData = null; | ||
312 | do { | 312 | do { |
313 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 313 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<PageData<Customer>>(){}, pageLink); |
314 | loadedCustomersTitle1.addAll(pageData.getData()); | 314 | loadedCustomersTitle1.addAll(pageData.getData()); |
315 | if (pageData.hasNext()) { | 315 | if (pageData.hasNext()) { |
316 | - pageLink = pageData.getNextPageLink(); | 316 | + pageLink = pageLink.nextPageLink(); |
317 | } | 317 | } |
318 | } while (pageData.hasNext()); | 318 | } while (pageData.hasNext()); |
319 | 319 | ||
@@ -323,12 +323,12 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -323,12 +323,12 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
323 | Assert.assertEquals(customersTitle1, loadedCustomersTitle1); | 323 | Assert.assertEquals(customersTitle1, loadedCustomersTitle1); |
324 | 324 | ||
325 | List<Customer> loadedCustomersTitle2 = new ArrayList<>(); | 325 | List<Customer> loadedCustomersTitle2 = new ArrayList<>(); |
326 | - pageLink = new TextPageLink(4, title2); | 326 | + pageLink = new PageLink(4, 0, title2); |
327 | do { | 327 | do { |
328 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 328 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<PageData<Customer>>(){}, pageLink); |
329 | loadedCustomersTitle2.addAll(pageData.getData()); | 329 | loadedCustomersTitle2.addAll(pageData.getData()); |
330 | if (pageData.hasNext()) { | 330 | if (pageData.hasNext()) { |
331 | - pageLink = pageData.getNextPageLink(); | 331 | + pageLink = pageLink.nextPageLink(); |
332 | } | 332 | } |
333 | } while (pageData.hasNext()); | 333 | } while (pageData.hasNext()); |
334 | 334 | ||
@@ -342,8 +342,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -342,8 +342,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
342 | .andExpect(status().isOk()); | 342 | .andExpect(status().isOk()); |
343 | } | 343 | } |
344 | 344 | ||
345 | - pageLink = new TextPageLink(4, title1); | ||
346 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 345 | + pageLink = new PageLink(4, 0, title1); |
346 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<PageData<Customer>>(){}, pageLink); | ||
347 | Assert.assertFalse(pageData.hasNext()); | 347 | Assert.assertFalse(pageData.hasNext()); |
348 | Assert.assertEquals(0, pageData.getData().size()); | 348 | Assert.assertEquals(0, pageData.getData().size()); |
349 | 349 | ||
@@ -352,8 +352,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | @@ -352,8 +352,8 @@ public abstract class BaseCustomerControllerTest extends AbstractControllerTest | ||
352 | .andExpect(status().isOk()); | 352 | .andExpect(status().isOk()); |
353 | } | 353 | } |
354 | 354 | ||
355 | - pageLink = new TextPageLink(4, title2); | ||
356 | - pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<TextPageData<Customer>>(){}, pageLink); | 355 | + pageLink = new PageLink(4, 0, title2); |
356 | + pageData = doGetTypedWithPageLink("/api/customers?", new TypeReference<PageData<Customer>>(){}, pageLink); | ||
357 | Assert.assertFalse(pageData.hasNext()); | 357 | Assert.assertFalse(pageData.hasNext()); |
358 | Assert.assertEquals(0, pageData.getData().size()); | 358 | Assert.assertEquals(0, pageData.getData().size()); |
359 | 359 |
@@ -28,9 +28,8 @@ import com.datastax.driver.core.utils.UUIDs; | @@ -28,9 +28,8 @@ import com.datastax.driver.core.utils.UUIDs; | ||
28 | import org.apache.commons.lang3.RandomStringUtils; | 28 | import org.apache.commons.lang3.RandomStringUtils; |
29 | import org.thingsboard.server.common.data.*; | 29 | import org.thingsboard.server.common.data.*; |
30 | import org.thingsboard.server.common.data.id.CustomerId; | 30 | import org.thingsboard.server.common.data.id.CustomerId; |
31 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
32 | -import org.thingsboard.server.common.data.page.TextPageLink; | ||
33 | -import org.thingsboard.server.common.data.page.TimePageData; | 31 | +import org.thingsboard.server.common.data.page.PageData; |
32 | +import org.thingsboard.server.common.data.page.PageLink; | ||
34 | import org.thingsboard.server.common.data.page.TimePageLink; | 33 | import org.thingsboard.server.common.data.page.TimePageLink; |
35 | import org.thingsboard.server.common.data.security.Authority; | 34 | import org.thingsboard.server.common.data.security.Authority; |
36 | import org.thingsboard.server.dao.model.ModelConstants; | 35 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -211,14 +210,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -211,14 +210,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
211 | dashboards.add(new DashboardInfo(doPost("/api/dashboard", dashboard, Dashboard.class))); | 210 | dashboards.add(new DashboardInfo(doPost("/api/dashboard", dashboard, Dashboard.class))); |
212 | } | 211 | } |
213 | List<DashboardInfo> loadedDashboards = new ArrayList<>(); | 212 | List<DashboardInfo> loadedDashboards = new ArrayList<>(); |
214 | - TextPageLink pageLink = new TextPageLink(24); | ||
215 | - TextPageData<DashboardInfo> pageData = null; | 213 | + PageLink pageLink = new PageLink(24); |
214 | + PageData<DashboardInfo> pageData = null; | ||
216 | do { | 215 | do { |
217 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", | 216 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", |
218 | - new TypeReference<TextPageData<DashboardInfo>>(){}, pageLink); | 217 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); |
219 | loadedDashboards.addAll(pageData.getData()); | 218 | loadedDashboards.addAll(pageData.getData()); |
220 | if (pageData.hasNext()) { | 219 | if (pageData.hasNext()) { |
221 | - pageLink = pageData.getNextPageLink(); | 220 | + pageLink = pageLink.nextPageLink(); |
222 | } | 221 | } |
223 | } while (pageData.hasNext()); | 222 | } while (pageData.hasNext()); |
224 | 223 | ||
@@ -252,14 +251,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -252,14 +251,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
252 | } | 251 | } |
253 | 252 | ||
254 | List<DashboardInfo> loadedDashboardsTitle1 = new ArrayList<>(); | 253 | List<DashboardInfo> loadedDashboardsTitle1 = new ArrayList<>(); |
255 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
256 | - TextPageData<DashboardInfo> pageData = null; | 254 | + PageLink pageLink = new PageLink(15, 0, title1); |
255 | + PageData<DashboardInfo> pageData = null; | ||
257 | do { | 256 | do { |
258 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", | 257 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", |
259 | - new TypeReference<TextPageData<DashboardInfo>>(){}, pageLink); | 258 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); |
260 | loadedDashboardsTitle1.addAll(pageData.getData()); | 259 | loadedDashboardsTitle1.addAll(pageData.getData()); |
261 | if (pageData.hasNext()) { | 260 | if (pageData.hasNext()) { |
262 | - pageLink = pageData.getNextPageLink(); | 261 | + pageLink = pageLink.nextPageLink(); |
263 | } | 262 | } |
264 | } while (pageData.hasNext()); | 263 | } while (pageData.hasNext()); |
265 | 264 | ||
@@ -269,13 +268,13 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -269,13 +268,13 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
269 | Assert.assertEquals(dashboardsTitle1, loadedDashboardsTitle1); | 268 | Assert.assertEquals(dashboardsTitle1, loadedDashboardsTitle1); |
270 | 269 | ||
271 | List<DashboardInfo> loadedDashboardsTitle2 = new ArrayList<>(); | 270 | List<DashboardInfo> loadedDashboardsTitle2 = new ArrayList<>(); |
272 | - pageLink = new TextPageLink(4, title2); | 271 | + pageLink = new PageLink(4, 0, title2); |
273 | do { | 272 | do { |
274 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", | 273 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", |
275 | - new TypeReference<TextPageData<DashboardInfo>>(){}, pageLink); | 274 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); |
276 | loadedDashboardsTitle2.addAll(pageData.getData()); | 275 | loadedDashboardsTitle2.addAll(pageData.getData()); |
277 | if (pageData.hasNext()) { | 276 | if (pageData.hasNext()) { |
278 | - pageLink = pageData.getNextPageLink(); | 277 | + pageLink = pageLink.nextPageLink(); |
279 | } | 278 | } |
280 | } while (pageData.hasNext()); | 279 | } while (pageData.hasNext()); |
281 | 280 | ||
@@ -289,9 +288,9 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -289,9 +288,9 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
289 | .andExpect(status().isOk()); | 288 | .andExpect(status().isOk()); |
290 | } | 289 | } |
291 | 290 | ||
292 | - pageLink = new TextPageLink(4, title1); | 291 | + pageLink = new PageLink(4, 0, title1); |
293 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", | 292 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", |
294 | - new TypeReference<TextPageData<DashboardInfo>>(){}, pageLink); | 293 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); |
295 | Assert.assertFalse(pageData.hasNext()); | 294 | Assert.assertFalse(pageData.hasNext()); |
296 | Assert.assertEquals(0, pageData.getData().size()); | 295 | Assert.assertEquals(0, pageData.getData().size()); |
297 | 296 | ||
@@ -300,9 +299,9 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -300,9 +299,9 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
300 | .andExpect(status().isOk()); | 299 | .andExpect(status().isOk()); |
301 | } | 300 | } |
302 | 301 | ||
303 | - pageLink = new TextPageLink(4, title2); | 302 | + pageLink = new PageLink(4, 0, title2); |
304 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", | 303 | pageData = doGetTypedWithPageLink("/api/tenant/dashboards?", |
305 | - new TypeReference<TextPageData<DashboardInfo>>(){}, pageLink); | 304 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); |
306 | Assert.assertFalse(pageData.hasNext()); | 305 | Assert.assertFalse(pageData.hasNext()); |
307 | Assert.assertEquals(0, pageData.getData().size()); | 306 | Assert.assertEquals(0, pageData.getData().size()); |
308 | } | 307 | } |
@@ -324,14 +323,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | @@ -324,14 +323,14 @@ public abstract class BaseDashboardControllerTest extends AbstractControllerTest | ||
324 | } | 323 | } |
325 | 324 | ||
326 | List<DashboardInfo> loadedDashboards = new ArrayList<>(); | 325 | List<DashboardInfo> loadedDashboards = new ArrayList<>(); |
327 | - TimePageLink pageLink = new TimePageLink(21); | ||
328 | - TimePageData<DashboardInfo> pageData = null; | 326 | + PageLink pageLink = new PageLink(21); |
327 | + PageData<DashboardInfo> pageData = null; | ||
329 | do { | 328 | do { |
330 | - pageData = doGetTypedWithTimePageLink("/api/customer/" + customerId.getId().toString() + "/dashboards?", | ||
331 | - new TypeReference<TimePageData<DashboardInfo>>(){}, pageLink); | 329 | + pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/dashboards?", |
330 | + new TypeReference<PageData<DashboardInfo>>(){}, pageLink); | ||
332 | loadedDashboards.addAll(pageData.getData()); | 331 | loadedDashboards.addAll(pageData.getData()); |
333 | if (pageData.hasNext()) { | 332 | if (pageData.hasNext()) { |
334 | - pageLink = pageData.getNextPageLink(); | 333 | + pageLink = pageLink.nextPageLink(); |
335 | } | 334 | } |
336 | } while (pageData.hasNext()); | 335 | } while (pageData.hasNext()); |
337 | 336 |
@@ -29,8 +29,8 @@ import org.thingsboard.server.common.data.*; | @@ -29,8 +29,8 @@ import org.thingsboard.server.common.data.*; | ||
29 | import org.thingsboard.server.common.data.id.CustomerId; | 29 | import org.thingsboard.server.common.data.id.CustomerId; |
30 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; | 30 | import org.thingsboard.server.common.data.id.DeviceCredentialsId; |
31 | import org.thingsboard.server.common.data.id.DeviceId; | 31 | import org.thingsboard.server.common.data.id.DeviceId; |
32 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
33 | -import org.thingsboard.server.common.data.page.TextPageLink; | 32 | +import org.thingsboard.server.common.data.page.PageData; |
33 | +import org.thingsboard.server.common.data.page.PageLink; | ||
34 | import org.thingsboard.server.common.data.security.Authority; | 34 | import org.thingsboard.server.common.data.security.Authority; |
35 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 35 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
36 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; | 36 | import org.thingsboard.server.common.data.security.DeviceCredentialsType; |
@@ -366,14 +366,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -366,14 +366,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
366 | devices.add(doPost("/api/device", device, Device.class)); | 366 | devices.add(doPost("/api/device", device, Device.class)); |
367 | } | 367 | } |
368 | List<Device> loadedDevices = new ArrayList<>(); | 368 | List<Device> loadedDevices = new ArrayList<>(); |
369 | - TextPageLink pageLink = new TextPageLink(23); | ||
370 | - TextPageData<Device> pageData = null; | 369 | + PageLink pageLink = new PageLink(23); |
370 | + PageData<Device> pageData = null; | ||
371 | do { | 371 | do { |
372 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", | 372 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", |
373 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 373 | + new TypeReference<PageData<Device>>(){}, pageLink); |
374 | loadedDevices.addAll(pageData.getData()); | 374 | loadedDevices.addAll(pageData.getData()); |
375 | if (pageData.hasNext()) { | 375 | if (pageData.hasNext()) { |
376 | - pageLink = pageData.getNextPageLink(); | 376 | + pageLink = pageLink.nextPageLink(); |
377 | } | 377 | } |
378 | } while (pageData.hasNext()); | 378 | } while (pageData.hasNext()); |
379 | 379 | ||
@@ -409,14 +409,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -409,14 +409,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
409 | } | 409 | } |
410 | 410 | ||
411 | List<Device> loadedDevicesTitle1 = new ArrayList<>(); | 411 | List<Device> loadedDevicesTitle1 = new ArrayList<>(); |
412 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
413 | - TextPageData<Device> pageData = null; | 412 | + PageLink pageLink = new PageLink(15, 0, title1); |
413 | + PageData<Device> pageData = null; | ||
414 | do { | 414 | do { |
415 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", | 415 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", |
416 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 416 | + new TypeReference<PageData<Device>>(){}, pageLink); |
417 | loadedDevicesTitle1.addAll(pageData.getData()); | 417 | loadedDevicesTitle1.addAll(pageData.getData()); |
418 | if (pageData.hasNext()) { | 418 | if (pageData.hasNext()) { |
419 | - pageLink = pageData.getNextPageLink(); | 419 | + pageLink = pageLink.nextPageLink(); |
420 | } | 420 | } |
421 | } while (pageData.hasNext()); | 421 | } while (pageData.hasNext()); |
422 | 422 | ||
@@ -426,13 +426,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -426,13 +426,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
426 | Assert.assertEquals(devicesTitle1, loadedDevicesTitle1); | 426 | Assert.assertEquals(devicesTitle1, loadedDevicesTitle1); |
427 | 427 | ||
428 | List<Device> loadedDevicesTitle2 = new ArrayList<>(); | 428 | List<Device> loadedDevicesTitle2 = new ArrayList<>(); |
429 | - pageLink = new TextPageLink(4, title2); | 429 | + pageLink = new PageLink(4, 0, title2); |
430 | do { | 430 | do { |
431 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", | 431 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", |
432 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 432 | + new TypeReference<PageData<Device>>(){}, pageLink); |
433 | loadedDevicesTitle2.addAll(pageData.getData()); | 433 | loadedDevicesTitle2.addAll(pageData.getData()); |
434 | if (pageData.hasNext()) { | 434 | if (pageData.hasNext()) { |
435 | - pageLink = pageData.getNextPageLink(); | 435 | + pageLink = pageLink.nextPageLink(); |
436 | } | 436 | } |
437 | } while (pageData.hasNext()); | 437 | } while (pageData.hasNext()); |
438 | 438 | ||
@@ -446,9 +446,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -446,9 +446,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
446 | .andExpect(status().isOk()); | 446 | .andExpect(status().isOk()); |
447 | } | 447 | } |
448 | 448 | ||
449 | - pageLink = new TextPageLink(4, title1); | 449 | + pageLink = new PageLink(4, 0, title1); |
450 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", | 450 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", |
451 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 451 | + new TypeReference<PageData<Device>>(){}, pageLink); |
452 | Assert.assertFalse(pageData.hasNext()); | 452 | Assert.assertFalse(pageData.hasNext()); |
453 | Assert.assertEquals(0, pageData.getData().size()); | 453 | Assert.assertEquals(0, pageData.getData().size()); |
454 | 454 | ||
@@ -457,9 +457,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -457,9 +457,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
457 | .andExpect(status().isOk()); | 457 | .andExpect(status().isOk()); |
458 | } | 458 | } |
459 | 459 | ||
460 | - pageLink = new TextPageLink(4, title2); | 460 | + pageLink = new PageLink(4, 0, title2); |
461 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", | 461 | pageData = doGetTypedWithPageLink("/api/tenant/devices?", |
462 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 462 | + new TypeReference<PageData<Device>>(){}, pageLink); |
463 | Assert.assertFalse(pageData.hasNext()); | 463 | Assert.assertFalse(pageData.hasNext()); |
464 | Assert.assertEquals(0, pageData.getData().size()); | 464 | Assert.assertEquals(0, pageData.getData().size()); |
465 | } | 465 | } |
@@ -492,14 +492,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -492,14 +492,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
492 | } | 492 | } |
493 | 493 | ||
494 | List<Device> loadedDevicesType1 = new ArrayList<>(); | 494 | List<Device> loadedDevicesType1 = new ArrayList<>(); |
495 | - TextPageLink pageLink = new TextPageLink(15); | ||
496 | - TextPageData<Device> pageData = null; | 495 | + PageLink pageLink = new PageLink(15); |
496 | + PageData<Device> pageData = null; | ||
497 | do { | 497 | do { |
498 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | 498 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", |
499 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | 499 | + new TypeReference<PageData<Device>>(){}, pageLink, type1); |
500 | loadedDevicesType1.addAll(pageData.getData()); | 500 | loadedDevicesType1.addAll(pageData.getData()); |
501 | if (pageData.hasNext()) { | 501 | if (pageData.hasNext()) { |
502 | - pageLink = pageData.getNextPageLink(); | 502 | + pageLink = pageLink.nextPageLink(); |
503 | } | 503 | } |
504 | } while (pageData.hasNext()); | 504 | } while (pageData.hasNext()); |
505 | 505 | ||
@@ -509,13 +509,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -509,13 +509,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
509 | Assert.assertEquals(devicesType1, loadedDevicesType1); | 509 | Assert.assertEquals(devicesType1, loadedDevicesType1); |
510 | 510 | ||
511 | List<Device> loadedDevicesType2 = new ArrayList<>(); | 511 | List<Device> loadedDevicesType2 = new ArrayList<>(); |
512 | - pageLink = new TextPageLink(4); | 512 | + pageLink = new PageLink(4); |
513 | do { | 513 | do { |
514 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | 514 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", |
515 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | 515 | + new TypeReference<PageData<Device>>(){}, pageLink, type2); |
516 | loadedDevicesType2.addAll(pageData.getData()); | 516 | loadedDevicesType2.addAll(pageData.getData()); |
517 | if (pageData.hasNext()) { | 517 | if (pageData.hasNext()) { |
518 | - pageLink = pageData.getNextPageLink(); | 518 | + pageLink = pageLink.nextPageLink(); |
519 | } | 519 | } |
520 | } while (pageData.hasNext()); | 520 | } while (pageData.hasNext()); |
521 | 521 | ||
@@ -529,9 +529,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -529,9 +529,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
529 | .andExpect(status().isOk()); | 529 | .andExpect(status().isOk()); |
530 | } | 530 | } |
531 | 531 | ||
532 | - pageLink = new TextPageLink(4); | 532 | + pageLink = new PageLink(4); |
533 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | 533 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", |
534 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | 534 | + new TypeReference<PageData<Device>>(){}, pageLink, type1); |
535 | Assert.assertFalse(pageData.hasNext()); | 535 | Assert.assertFalse(pageData.hasNext()); |
536 | Assert.assertEquals(0, pageData.getData().size()); | 536 | Assert.assertEquals(0, pageData.getData().size()); |
537 | 537 | ||
@@ -540,9 +540,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -540,9 +540,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
540 | .andExpect(status().isOk()); | 540 | .andExpect(status().isOk()); |
541 | } | 541 | } |
542 | 542 | ||
543 | - pageLink = new TextPageLink(4); | 543 | + pageLink = new PageLink(4); |
544 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", | 544 | pageData = doGetTypedWithPageLink("/api/tenant/devices?type={type}&", |
545 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | 545 | + new TypeReference<PageData<Device>>(){}, pageLink, type2); |
546 | Assert.assertFalse(pageData.hasNext()); | 546 | Assert.assertFalse(pageData.hasNext()); |
547 | Assert.assertEquals(0, pageData.getData().size()); | 547 | Assert.assertEquals(0, pageData.getData().size()); |
548 | } | 548 | } |
@@ -565,14 +565,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -565,14 +565,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
565 | } | 565 | } |
566 | 566 | ||
567 | List<Device> loadedDevices = new ArrayList<>(); | 567 | List<Device> loadedDevices = new ArrayList<>(); |
568 | - TextPageLink pageLink = new TextPageLink(23); | ||
569 | - TextPageData<Device> pageData = null; | 568 | + PageLink pageLink = new PageLink(23); |
569 | + PageData<Device> pageData = null; | ||
570 | do { | 570 | do { |
571 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", | 571 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", |
572 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 572 | + new TypeReference<PageData<Device>>(){}, pageLink); |
573 | loadedDevices.addAll(pageData.getData()); | 573 | loadedDevices.addAll(pageData.getData()); |
574 | if (pageData.hasNext()) { | 574 | if (pageData.hasNext()) { |
575 | - pageLink = pageData.getNextPageLink(); | 575 | + pageLink = pageLink.nextPageLink(); |
576 | } | 576 | } |
577 | } while (pageData.hasNext()); | 577 | } while (pageData.hasNext()); |
578 | 578 | ||
@@ -617,14 +617,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -617,14 +617,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
617 | } | 617 | } |
618 | 618 | ||
619 | List<Device> loadedDevicesTitle1 = new ArrayList<>(); | 619 | List<Device> loadedDevicesTitle1 = new ArrayList<>(); |
620 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
621 | - TextPageData<Device> pageData = null; | 620 | + PageLink pageLink = new PageLink(15, 0, title1); |
621 | + PageData<Device> pageData = null; | ||
622 | do { | 622 | do { |
623 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", | 623 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", |
624 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 624 | + new TypeReference<PageData<Device>>(){}, pageLink); |
625 | loadedDevicesTitle1.addAll(pageData.getData()); | 625 | loadedDevicesTitle1.addAll(pageData.getData()); |
626 | if (pageData.hasNext()) { | 626 | if (pageData.hasNext()) { |
627 | - pageLink = pageData.getNextPageLink(); | 627 | + pageLink = pageLink.nextPageLink(); |
628 | } | 628 | } |
629 | } while (pageData.hasNext()); | 629 | } while (pageData.hasNext()); |
630 | 630 | ||
@@ -634,13 +634,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -634,13 +634,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
634 | Assert.assertEquals(devicesTitle1, loadedDevicesTitle1); | 634 | Assert.assertEquals(devicesTitle1, loadedDevicesTitle1); |
635 | 635 | ||
636 | List<Device> loadedDevicesTitle2 = new ArrayList<>(); | 636 | List<Device> loadedDevicesTitle2 = new ArrayList<>(); |
637 | - pageLink = new TextPageLink(4, title2); | 637 | + pageLink = new PageLink(4, 0, title2); |
638 | do { | 638 | do { |
639 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", | 639 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", |
640 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 640 | + new TypeReference<PageData<Device>>(){}, pageLink); |
641 | loadedDevicesTitle2.addAll(pageData.getData()); | 641 | loadedDevicesTitle2.addAll(pageData.getData()); |
642 | if (pageData.hasNext()) { | 642 | if (pageData.hasNext()) { |
643 | - pageLink = pageData.getNextPageLink(); | 643 | + pageLink = pageLink.nextPageLink(); |
644 | } | 644 | } |
645 | } while (pageData.hasNext()); | 645 | } while (pageData.hasNext()); |
646 | 646 | ||
@@ -654,9 +654,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -654,9 +654,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
654 | .andExpect(status().isOk()); | 654 | .andExpect(status().isOk()); |
655 | } | 655 | } |
656 | 656 | ||
657 | - pageLink = new TextPageLink(4, title1); | 657 | + pageLink = new PageLink(4, 0, title1); |
658 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", | 658 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", |
659 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 659 | + new TypeReference<PageData<Device>>(){}, pageLink); |
660 | Assert.assertFalse(pageData.hasNext()); | 660 | Assert.assertFalse(pageData.hasNext()); |
661 | Assert.assertEquals(0, pageData.getData().size()); | 661 | Assert.assertEquals(0, pageData.getData().size()); |
662 | 662 | ||
@@ -665,9 +665,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -665,9 +665,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
665 | .andExpect(status().isOk()); | 665 | .andExpect(status().isOk()); |
666 | } | 666 | } |
667 | 667 | ||
668 | - pageLink = new TextPageLink(4, title2); | 668 | + pageLink = new PageLink(4, 0, title2); |
669 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", | 669 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?", |
670 | - new TypeReference<TextPageData<Device>>(){}, pageLink); | 670 | + new TypeReference<PageData<Device>>(){}, pageLink); |
671 | Assert.assertFalse(pageData.hasNext()); | 671 | Assert.assertFalse(pageData.hasNext()); |
672 | Assert.assertEquals(0, pageData.getData().size()); | 672 | Assert.assertEquals(0, pageData.getData().size()); |
673 | } | 673 | } |
@@ -709,14 +709,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -709,14 +709,14 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
709 | } | 709 | } |
710 | 710 | ||
711 | List<Device> loadedDevicesType1 = new ArrayList<>(); | 711 | List<Device> loadedDevicesType1 = new ArrayList<>(); |
712 | - TextPageLink pageLink = new TextPageLink(15); | ||
713 | - TextPageData<Device> pageData = null; | 712 | + PageLink pageLink = new PageLink(15); |
713 | + PageData<Device> pageData = null; | ||
714 | do { | 714 | do { |
715 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | 715 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", |
716 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | 716 | + new TypeReference<PageData<Device>>(){}, pageLink, type1); |
717 | loadedDevicesType1.addAll(pageData.getData()); | 717 | loadedDevicesType1.addAll(pageData.getData()); |
718 | if (pageData.hasNext()) { | 718 | if (pageData.hasNext()) { |
719 | - pageLink = pageData.getNextPageLink(); | 719 | + pageLink = pageLink.nextPageLink(); |
720 | } | 720 | } |
721 | } while (pageData.hasNext()); | 721 | } while (pageData.hasNext()); |
722 | 722 | ||
@@ -726,13 +726,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -726,13 +726,13 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
726 | Assert.assertEquals(devicesType1, loadedDevicesType1); | 726 | Assert.assertEquals(devicesType1, loadedDevicesType1); |
727 | 727 | ||
728 | List<Device> loadedDevicesType2 = new ArrayList<>(); | 728 | List<Device> loadedDevicesType2 = new ArrayList<>(); |
729 | - pageLink = new TextPageLink(4); | 729 | + pageLink = new PageLink(4); |
730 | do { | 730 | do { |
731 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | 731 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", |
732 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | 732 | + new TypeReference<PageData<Device>>(){}, pageLink, type2); |
733 | loadedDevicesType2.addAll(pageData.getData()); | 733 | loadedDevicesType2.addAll(pageData.getData()); |
734 | if (pageData.hasNext()) { | 734 | if (pageData.hasNext()) { |
735 | - pageLink = pageData.getNextPageLink(); | 735 | + pageLink = pageLink.nextPageLink(); |
736 | } | 736 | } |
737 | } while (pageData.hasNext()); | 737 | } while (pageData.hasNext()); |
738 | 738 | ||
@@ -746,9 +746,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -746,9 +746,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
746 | .andExpect(status().isOk()); | 746 | .andExpect(status().isOk()); |
747 | } | 747 | } |
748 | 748 | ||
749 | - pageLink = new TextPageLink(4); | 749 | + pageLink = new PageLink(4); |
750 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | 750 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", |
751 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type1); | 751 | + new TypeReference<PageData<Device>>(){}, pageLink, type1); |
752 | Assert.assertFalse(pageData.hasNext()); | 752 | Assert.assertFalse(pageData.hasNext()); |
753 | Assert.assertEquals(0, pageData.getData().size()); | 753 | Assert.assertEquals(0, pageData.getData().size()); |
754 | 754 | ||
@@ -757,9 +757,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | @@ -757,9 +757,9 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { | ||
757 | .andExpect(status().isOk()); | 757 | .andExpect(status().isOk()); |
758 | } | 758 | } |
759 | 759 | ||
760 | - pageLink = new TextPageLink(4); | 760 | + pageLink = new PageLink(4); |
761 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", | 761 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/devices?type={type}&", |
762 | - new TypeReference<TextPageData<Device>>(){}, pageLink, type2); | 762 | + new TypeReference<PageData<Device>>(){}, pageLink, type2); |
763 | Assert.assertFalse(pageData.hasNext()); | 763 | Assert.assertFalse(pageData.hasNext()); |
764 | Assert.assertEquals(0, pageData.getData().size()); | 764 | Assert.assertEquals(0, pageData.getData().size()); |
765 | } | 765 | } |
@@ -25,16 +25,12 @@ import org.junit.After; | @@ -25,16 +25,12 @@ import org.junit.After; | ||
25 | import org.junit.Assert; | 25 | import org.junit.Assert; |
26 | import org.junit.Before; | 26 | import org.junit.Before; |
27 | import org.junit.Test; | 27 | import org.junit.Test; |
28 | -import org.thingsboard.server.common.data.Customer; | ||
29 | -import org.thingsboard.server.common.data.Device; | ||
30 | -import org.thingsboard.server.common.data.EntityView; | ||
31 | -import org.thingsboard.server.common.data.Tenant; | ||
32 | -import org.thingsboard.server.common.data.User; | 28 | +import org.thingsboard.server.common.data.*; |
33 | import org.thingsboard.server.common.data.id.CustomerId; | 29 | import org.thingsboard.server.common.data.id.CustomerId; |
34 | import org.thingsboard.server.common.data.objects.AttributesEntityView; | 30 | import org.thingsboard.server.common.data.objects.AttributesEntityView; |
35 | import org.thingsboard.server.common.data.objects.TelemetryEntityView; | 31 | import org.thingsboard.server.common.data.objects.TelemetryEntityView; |
36 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
37 | -import org.thingsboard.server.common.data.page.TextPageLink; | 32 | +import org.thingsboard.server.common.data.page.PageData; |
33 | +import org.thingsboard.server.common.data.page.PageLink; | ||
38 | import org.thingsboard.server.common.data.security.Authority; | 34 | import org.thingsboard.server.common.data.security.Authority; |
39 | import org.thingsboard.server.common.data.security.DeviceCredentials; | 35 | import org.thingsboard.server.common.data.security.DeviceCredentials; |
40 | import org.thingsboard.server.dao.model.ModelConstants; | 36 | import org.thingsboard.server.dao.model.ModelConstants; |
@@ -214,16 +210,20 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -214,16 +210,20 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
214 | 210 | ||
215 | @Test | 211 | @Test |
216 | public void testGetCustomerEntityViews() throws Exception { | 212 | public void testGetCustomerEntityViews() throws Exception { |
217 | - CustomerId customerId = doPost("/api/customer", getNewCustomer("Test customer"), Customer.class).getId(); | ||
218 | - String urlTemplate = "/api/customer/" + customerId.getId().toString() + "/entityViews?"; | 213 | + Customer customer = doPost("/api/customer", getNewCustomer("Test customer"), Customer.class); |
214 | + CustomerId customerId = customer.getId(); | ||
215 | + String urlTemplate = "/api/customer/" + customerId.getId().toString() + "/entityViewInfos?"; | ||
219 | 216 | ||
220 | - List<EntityView> views = new ArrayList<>(); | 217 | + List<EntityViewInfo> views = new ArrayList<>(); |
221 | for (int i = 0; i < 128; i++) { | 218 | for (int i = 0; i < 128; i++) { |
222 | - views.add(doPost("/api/customer/" + customerId.getId().toString() + "/entityView/" | ||
223 | - + getNewSavedEntityView("Test entity view " + i).getId().getId().toString(), EntityView.class)); | 219 | + views.add( |
220 | + new EntityViewInfo(doPost("/api/customer/" + customerId.getId().toString() + "/entityView/" | ||
221 | + + getNewSavedEntityView("Test entity view " + i).getId().getId().toString(), EntityView.class), | ||
222 | + customer.getTitle(), customer.isPublic()) | ||
223 | + ); | ||
224 | } | 224 | } |
225 | 225 | ||
226 | - List<EntityView> loadedViews = loadListOf(new TextPageLink(23), urlTemplate); | 226 | + List<EntityViewInfo> loadedViews = loadListOfInfo(new PageLink(23), urlTemplate); |
227 | 227 | ||
228 | Collections.sort(views, idComparator); | 228 | Collections.sort(views, idComparator); |
229 | Collections.sort(loadedViews, idComparator); | 229 | Collections.sort(loadedViews, idComparator); |
@@ -239,7 +239,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -239,7 +239,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
239 | String name1 = "Entity view name1"; | 239 | String name1 = "Entity view name1"; |
240 | List<EntityView> namesOfView1 = fillListOf(125, name1, "/api/customer/" + customerId.getId().toString() | 240 | List<EntityView> namesOfView1 = fillListOf(125, name1, "/api/customer/" + customerId.getId().toString() |
241 | + "/entityView/"); | 241 | + "/entityView/"); |
242 | - List<EntityView> loadedNamesOfView1 = loadListOf(new TextPageLink(15, name1), urlTemplate); | 242 | + List<EntityView> loadedNamesOfView1 = loadListOf(new PageLink(15, 0, name1), urlTemplate); |
243 | Collections.sort(namesOfView1, idComparator); | 243 | Collections.sort(namesOfView1, idComparator); |
244 | Collections.sort(loadedNamesOfView1, idComparator); | 244 | Collections.sort(loadedNamesOfView1, idComparator); |
245 | assertEquals(namesOfView1, loadedNamesOfView1); | 245 | assertEquals(namesOfView1, loadedNamesOfView1); |
@@ -247,7 +247,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -247,7 +247,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
247 | String name2 = "Entity view name2"; | 247 | String name2 = "Entity view name2"; |
248 | List<EntityView> NamesOfView2 = fillListOf(143, name2, "/api/customer/" + customerId.getId().toString() | 248 | List<EntityView> NamesOfView2 = fillListOf(143, name2, "/api/customer/" + customerId.getId().toString() |
249 | + "/entityView/"); | 249 | + "/entityView/"); |
250 | - List<EntityView> loadedNamesOfView2 = loadListOf(new TextPageLink(4, name2), urlTemplate); | 250 | + List<EntityView> loadedNamesOfView2 = loadListOf(new PageLink(4, 0, name2), urlTemplate); |
251 | Collections.sort(NamesOfView2, idComparator); | 251 | Collections.sort(NamesOfView2, idComparator); |
252 | Collections.sort(loadedNamesOfView2, idComparator); | 252 | Collections.sort(loadedNamesOfView2, idComparator); |
253 | assertEquals(NamesOfView2, loadedNamesOfView2); | 253 | assertEquals(NamesOfView2, loadedNamesOfView2); |
@@ -255,18 +255,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -255,18 +255,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
255 | for (EntityView view : loadedNamesOfView1) { | 255 | for (EntityView view : loadedNamesOfView1) { |
256 | doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); | 256 | doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); |
257 | } | 257 | } |
258 | - TextPageData<EntityView> pageData = doGetTypedWithPageLink(urlTemplate, | ||
259 | - new TypeReference<TextPageData<EntityView>>() { | ||
260 | - }, new TextPageLink(4, name1)); | 258 | + PageData<EntityView> pageData = doGetTypedWithPageLink(urlTemplate, |
259 | + new TypeReference<PageData<EntityView>>() { | ||
260 | + }, new PageLink(4, 0, name1)); | ||
261 | Assert.assertFalse(pageData.hasNext()); | 261 | Assert.assertFalse(pageData.hasNext()); |
262 | assertEquals(0, pageData.getData().size()); | 262 | assertEquals(0, pageData.getData().size()); |
263 | 263 | ||
264 | for (EntityView view : loadedNamesOfView2) { | 264 | for (EntityView view : loadedNamesOfView2) { |
265 | doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); | 265 | doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); |
266 | } | 266 | } |
267 | - pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<TextPageData<EntityView>>() { | 267 | + pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<PageData<EntityView>>() { |
268 | }, | 268 | }, |
269 | - new TextPageLink(4, name2)); | 269 | + new PageLink(4, 0, name2)); |
270 | Assert.assertFalse(pageData.hasNext()); | 270 | Assert.assertFalse(pageData.hasNext()); |
271 | assertEquals(0, pageData.getData().size()); | 271 | assertEquals(0, pageData.getData().size()); |
272 | } | 272 | } |
@@ -274,11 +274,11 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -274,11 +274,11 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
274 | @Test | 274 | @Test |
275 | public void testGetTenantEntityViews() throws Exception { | 275 | public void testGetTenantEntityViews() throws Exception { |
276 | 276 | ||
277 | - List<EntityView> views = new ArrayList<>(); | 277 | + List<EntityViewInfo> views = new ArrayList<>(); |
278 | for (int i = 0; i < 178; i++) { | 278 | for (int i = 0; i < 178; i++) { |
279 | - views.add(getNewSavedEntityView("Test entity view" + i)); | 279 | + views.add(new EntityViewInfo(getNewSavedEntityView("Test entity view" + i), null, false)); |
280 | } | 280 | } |
281 | - List<EntityView> loadedViews = loadListOf(new TextPageLink(23), "/api/tenant/entityViews?"); | 281 | + List<EntityViewInfo> loadedViews = loadListOfInfo(new PageLink(23), "/api/tenant/entityViewInfos?"); |
282 | 282 | ||
283 | Collections.sort(views, idComparator); | 283 | Collections.sort(views, idComparator); |
284 | Collections.sort(loadedViews, idComparator); | 284 | Collections.sort(loadedViews, idComparator); |
@@ -290,14 +290,14 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -290,14 +290,14 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
290 | public void testGetTenantEntityViewsByName() throws Exception { | 290 | public void testGetTenantEntityViewsByName() throws Exception { |
291 | String name1 = "Entity view name1"; | 291 | String name1 = "Entity view name1"; |
292 | List<EntityView> namesOfView1 = fillListOf(143, name1); | 292 | List<EntityView> namesOfView1 = fillListOf(143, name1); |
293 | - List<EntityView> loadedNamesOfView1 = loadListOf(new TextPageLink(15, name1), "/api/tenant/entityViews?"); | 293 | + List<EntityView> loadedNamesOfView1 = loadListOf(new PageLink(15, 0, name1), "/api/tenant/entityViews?"); |
294 | Collections.sort(namesOfView1, idComparator); | 294 | Collections.sort(namesOfView1, idComparator); |
295 | Collections.sort(loadedNamesOfView1, idComparator); | 295 | Collections.sort(loadedNamesOfView1, idComparator); |
296 | assertEquals(namesOfView1, loadedNamesOfView1); | 296 | assertEquals(namesOfView1, loadedNamesOfView1); |
297 | 297 | ||
298 | String name2 = "Entity view name2"; | 298 | String name2 = "Entity view name2"; |
299 | List<EntityView> NamesOfView2 = fillListOf(75, name2); | 299 | List<EntityView> NamesOfView2 = fillListOf(75, name2); |
300 | - List<EntityView> loadedNamesOfView2 = loadListOf(new TextPageLink(4, name2), "/api/tenant/entityViews?"); | 300 | + List<EntityView> loadedNamesOfView2 = loadListOf(new PageLink(4, 0, name2), "/api/tenant/entityViews?"); |
301 | Collections.sort(NamesOfView2, idComparator); | 301 | Collections.sort(NamesOfView2, idComparator); |
302 | Collections.sort(loadedNamesOfView2, idComparator); | 302 | Collections.sort(loadedNamesOfView2, idComparator); |
303 | assertEquals(NamesOfView2, loadedNamesOfView2); | 303 | assertEquals(NamesOfView2, loadedNamesOfView2); |
@@ -305,18 +305,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -305,18 +305,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
305 | for (EntityView view : loadedNamesOfView1) { | 305 | for (EntityView view : loadedNamesOfView1) { |
306 | doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); | 306 | doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); |
307 | } | 307 | } |
308 | - TextPageData<EntityView> pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", | ||
309 | - new TypeReference<TextPageData<EntityView>>() { | ||
310 | - }, new TextPageLink(4, name1)); | 308 | + PageData<EntityView> pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", |
309 | + new TypeReference<PageData<EntityView>>() { | ||
310 | + }, new PageLink(4, 0, name1)); | ||
311 | Assert.assertFalse(pageData.hasNext()); | 311 | Assert.assertFalse(pageData.hasNext()); |
312 | assertEquals(0, pageData.getData().size()); | 312 | assertEquals(0, pageData.getData().size()); |
313 | 313 | ||
314 | for (EntityView view : loadedNamesOfView2) { | 314 | for (EntityView view : loadedNamesOfView2) { |
315 | doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); | 315 | doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); |
316 | } | 316 | } |
317 | - pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", new TypeReference<TextPageData<EntityView>>() { | 317 | + pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", new TypeReference<PageData<EntityView>>() { |
318 | }, | 318 | }, |
319 | - new TextPageLink(4, name2)); | 319 | + new PageLink(4, 0, name2)); |
320 | Assert.assertFalse(pageData.hasNext()); | 320 | Assert.assertFalse(pageData.hasNext()); |
321 | assertEquals(0, pageData.getData().size()); | 321 | assertEquals(0, pageData.getData().size()); |
322 | } | 322 | } |
@@ -516,15 +516,30 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | @@ -516,15 +516,30 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes | ||
516 | return viewNames; | 516 | return viewNames; |
517 | } | 517 | } |
518 | 518 | ||
519 | - private List<EntityView> loadListOf(TextPageLink pageLink, String urlTemplate) throws Exception { | 519 | + private List<EntityView> loadListOf(PageLink pageLink, String urlTemplate) throws Exception { |
520 | List<EntityView> loadedItems = new ArrayList<>(); | 520 | List<EntityView> loadedItems = new ArrayList<>(); |
521 | - TextPageData<EntityView> pageData; | 521 | + PageData<EntityView> pageData; |
522 | + do { | ||
523 | + pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<PageData<EntityView>>() { | ||
524 | + }, pageLink); | ||
525 | + loadedItems.addAll(pageData.getData()); | ||
526 | + if (pageData.hasNext()) { | ||
527 | + pageLink = pageLink.nextPageLink(); | ||
528 | + } | ||
529 | + } while (pageData.hasNext()); | ||
530 | + | ||
531 | + return loadedItems; | ||
532 | + } | ||
533 | + | ||
534 | + private List<EntityViewInfo> loadListOfInfo(PageLink pageLink, String urlTemplate) throws Exception { | ||
535 | + List<EntityViewInfo> loadedItems = new ArrayList<>(); | ||
536 | + PageData<EntityViewInfo> pageData; | ||
522 | do { | 537 | do { |
523 | - pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<TextPageData<EntityView>>() { | 538 | + pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference<PageData<EntityViewInfo>>() { |
524 | }, pageLink); | 539 | }, pageLink); |
525 | loadedItems.addAll(pageData.getData()); | 540 | loadedItems.addAll(pageData.getData()); |
526 | if (pageData.hasNext()) { | 541 | if (pageData.hasNext()) { |
527 | - pageLink = pageData.getNextPageLink(); | 542 | + pageLink = pageLink.nextPageLink(); |
528 | } | 543 | } |
529 | } while (pageData.hasNext()); | 544 | } while (pageData.hasNext()); |
530 | 545 |
@@ -24,8 +24,8 @@ import java.util.List; | @@ -24,8 +24,8 @@ import java.util.List; | ||
24 | 24 | ||
25 | import org.apache.commons.lang3.RandomStringUtils; | 25 | import org.apache.commons.lang3.RandomStringUtils; |
26 | import org.thingsboard.server.common.data.Tenant; | 26 | import org.thingsboard.server.common.data.Tenant; |
27 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
28 | -import org.thingsboard.server.common.data.page.TextPageLink; | 27 | +import org.thingsboard.server.common.data.page.PageData; |
28 | +import org.thingsboard.server.common.data.page.PageLink; | ||
29 | import org.junit.Assert; | 29 | import org.junit.Assert; |
30 | import org.junit.Test; | 30 | import org.junit.Test; |
31 | 31 | ||
@@ -102,8 +102,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -102,8 +102,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
102 | public void testFindTenants() throws Exception { | 102 | public void testFindTenants() throws Exception { |
103 | loginSysAdmin(); | 103 | loginSysAdmin(); |
104 | List<Tenant> tenants = new ArrayList<>(); | 104 | List<Tenant> tenants = new ArrayList<>(); |
105 | - TextPageLink pageLink = new TextPageLink(17); | ||
106 | - TextPageData<Tenant> pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 105 | + PageLink pageLink = new PageLink(17); |
106 | + PageData<Tenant> pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); | ||
107 | Assert.assertFalse(pageData.hasNext()); | 107 | Assert.assertFalse(pageData.hasNext()); |
108 | Assert.assertEquals(1, pageData.getData().size()); | 108 | Assert.assertEquals(1, pageData.getData().size()); |
109 | tenants.addAll(pageData.getData()); | 109 | tenants.addAll(pageData.getData()); |
@@ -115,12 +115,12 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -115,12 +115,12 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
115 | } | 115 | } |
116 | 116 | ||
117 | List<Tenant> loadedTenants = new ArrayList<>(); | 117 | List<Tenant> loadedTenants = new ArrayList<>(); |
118 | - pageLink = new TextPageLink(17); | 118 | + pageLink = new PageLink(17); |
119 | do { | 119 | do { |
120 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 120 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); |
121 | loadedTenants.addAll(pageData.getData()); | 121 | loadedTenants.addAll(pageData.getData()); |
122 | if (pageData.hasNext()) { | 122 | if (pageData.hasNext()) { |
123 | - pageLink = pageData.getNextPageLink(); | 123 | + pageLink = pageLink.nextPageLink(); |
124 | } | 124 | } |
125 | } while (pageData.hasNext()); | 125 | } while (pageData.hasNext()); |
126 | 126 | ||
@@ -136,8 +136,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -136,8 +136,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
136 | } | 136 | } |
137 | } | 137 | } |
138 | 138 | ||
139 | - pageLink = new TextPageLink(17); | ||
140 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 139 | + pageLink = new PageLink(17); |
140 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); | ||
141 | Assert.assertFalse(pageData.hasNext()); | 141 | Assert.assertFalse(pageData.hasNext()); |
142 | Assert.assertEquals(1, pageData.getData().size()); | 142 | Assert.assertEquals(1, pageData.getData().size()); |
143 | } | 143 | } |
@@ -167,13 +167,13 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -167,13 +167,13 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
167 | } | 167 | } |
168 | 168 | ||
169 | List<Tenant> loadedTenantsTitle1 = new ArrayList<>(); | 169 | List<Tenant> loadedTenantsTitle1 = new ArrayList<>(); |
170 | - TextPageLink pageLink = new TextPageLink(15, title1); | ||
171 | - TextPageData<Tenant> pageData = null; | 170 | + PageLink pageLink = new PageLink(15, 0, title1); |
171 | + PageData<Tenant> pageData = null; | ||
172 | do { | 172 | do { |
173 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 173 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); |
174 | loadedTenantsTitle1.addAll(pageData.getData()); | 174 | loadedTenantsTitle1.addAll(pageData.getData()); |
175 | if (pageData.hasNext()) { | 175 | if (pageData.hasNext()) { |
176 | - pageLink = pageData.getNextPageLink(); | 176 | + pageLink = pageLink.nextPageLink(); |
177 | } | 177 | } |
178 | } while (pageData.hasNext()); | 178 | } while (pageData.hasNext()); |
179 | 179 | ||
@@ -183,12 +183,12 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -183,12 +183,12 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
183 | Assert.assertEquals(tenantsTitle1, loadedTenantsTitle1); | 183 | Assert.assertEquals(tenantsTitle1, loadedTenantsTitle1); |
184 | 184 | ||
185 | List<Tenant> loadedTenantsTitle2 = new ArrayList<>(); | 185 | List<Tenant> loadedTenantsTitle2 = new ArrayList<>(); |
186 | - pageLink = new TextPageLink(4, title2); | 186 | + pageLink = new PageLink(4, 0, title2); |
187 | do { | 187 | do { |
188 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 188 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); |
189 | loadedTenantsTitle2.addAll(pageData.getData()); | 189 | loadedTenantsTitle2.addAll(pageData.getData()); |
190 | if (pageData.hasNext()) { | 190 | if (pageData.hasNext()) { |
191 | - pageLink = pageData.getNextPageLink(); | 191 | + pageLink = pageLink.nextPageLink(); |
192 | } | 192 | } |
193 | } while (pageData.hasNext()); | 193 | } while (pageData.hasNext()); |
194 | 194 | ||
@@ -202,8 +202,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -202,8 +202,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
202 | .andExpect(status().isOk()); | 202 | .andExpect(status().isOk()); |
203 | } | 203 | } |
204 | 204 | ||
205 | - pageLink = new TextPageLink(4, title1); | ||
206 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 205 | + pageLink = new PageLink(4, 0, title1); |
206 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); | ||
207 | Assert.assertFalse(pageData.hasNext()); | 207 | Assert.assertFalse(pageData.hasNext()); |
208 | Assert.assertEquals(0, pageData.getData().size()); | 208 | Assert.assertEquals(0, pageData.getData().size()); |
209 | 209 | ||
@@ -212,8 +212,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | @@ -212,8 +212,8 @@ public abstract class BaseTenantControllerTest extends AbstractControllerTest { | ||
212 | .andExpect(status().isOk()); | 212 | .andExpect(status().isOk()); |
213 | } | 213 | } |
214 | 214 | ||
215 | - pageLink = new TextPageLink(4, title2); | ||
216 | - pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<TextPageData<Tenant>>(){}, pageLink); | 215 | + pageLink = new PageLink(4, 0, title2); |
216 | + pageData = doGetTypedWithPageLink("/api/tenants?", new TypeReference<PageData<Tenant>>(){}, pageLink); | ||
217 | Assert.assertFalse(pageData.hasNext()); | 217 | Assert.assertFalse(pageData.hasNext()); |
218 | Assert.assertEquals(0, pageData.getData().size()); | 218 | Assert.assertEquals(0, pageData.getData().size()); |
219 | } | 219 | } |
@@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.Tenant; | @@ -27,8 +27,8 @@ import org.thingsboard.server.common.data.Tenant; | ||
27 | import org.thingsboard.server.common.data.User; | 27 | import org.thingsboard.server.common.data.User; |
28 | import org.thingsboard.server.common.data.id.CustomerId; | 28 | import org.thingsboard.server.common.data.id.CustomerId; |
29 | import org.thingsboard.server.common.data.id.TenantId; | 29 | import org.thingsboard.server.common.data.id.TenantId; |
30 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
31 | -import org.thingsboard.server.common.data.page.TextPageLink; | 30 | +import org.thingsboard.server.common.data.page.PageData; |
31 | +import org.thingsboard.server.common.data.page.PageLink; | ||
32 | import org.thingsboard.server.common.data.security.Authority; | 32 | import org.thingsboard.server.common.data.security.Authority; |
33 | import org.thingsboard.server.service.mail.TestMailService; | 33 | import org.thingsboard.server.service.mail.TestMailService; |
34 | 34 | ||
@@ -326,14 +326,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -326,14 +326,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
326 | } | 326 | } |
327 | 327 | ||
328 | List<User> loadedTenantAdmins = new ArrayList<>(); | 328 | List<User> loadedTenantAdmins = new ArrayList<>(); |
329 | - TextPageLink pageLink = new TextPageLink(33); | ||
330 | - TextPageData<User> pageData = null; | 329 | + PageLink pageLink = new PageLink(33); |
330 | + PageData<User> pageData = null; | ||
331 | do { | 331 | do { |
332 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 332 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
333 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 333 | + new TypeReference<PageData<User>>(){}, pageLink); |
334 | loadedTenantAdmins.addAll(pageData.getData()); | 334 | loadedTenantAdmins.addAll(pageData.getData()); |
335 | if (pageData.hasNext()) { | 335 | if (pageData.hasNext()) { |
336 | - pageLink = pageData.getNextPageLink(); | 336 | + pageLink = pageLink.nextPageLink(); |
337 | } | 337 | } |
338 | } while (pageData.hasNext()); | 338 | } while (pageData.hasNext()); |
339 | 339 | ||
@@ -345,9 +345,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -345,9 +345,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
345 | doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) | 345 | doDelete("/api/tenant/"+savedTenant.getId().getId().toString()) |
346 | .andExpect(status().isOk()); | 346 | .andExpect(status().isOk()); |
347 | 347 | ||
348 | - pageLink = new TextPageLink(33); | 348 | + pageLink = new PageLink(33); |
349 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 349 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
350 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 350 | + new TypeReference<PageData<User>>(){}, pageLink); |
351 | Assert.assertFalse(pageData.hasNext()); | 351 | Assert.assertFalse(pageData.hasNext()); |
352 | Assert.assertTrue(pageData.getData().isEmpty()); | 352 | Assert.assertTrue(pageData.getData().isEmpty()); |
353 | } | 353 | } |
@@ -393,14 +393,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -393,14 +393,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
393 | } | 393 | } |
394 | 394 | ||
395 | List<User> loadedTenantAdminsEmail1 = new ArrayList<>(); | 395 | List<User> loadedTenantAdminsEmail1 = new ArrayList<>(); |
396 | - TextPageLink pageLink = new TextPageLink(33, email1); | ||
397 | - TextPageData<User> pageData = null; | 396 | + PageLink pageLink = new PageLink(33, 0, email1); |
397 | + PageData<User> pageData = null; | ||
398 | do { | 398 | do { |
399 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 399 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
400 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 400 | + new TypeReference<PageData<User>>(){}, pageLink); |
401 | loadedTenantAdminsEmail1.addAll(pageData.getData()); | 401 | loadedTenantAdminsEmail1.addAll(pageData.getData()); |
402 | if (pageData.hasNext()) { | 402 | if (pageData.hasNext()) { |
403 | - pageLink = pageData.getNextPageLink(); | 403 | + pageLink = pageLink.nextPageLink(); |
404 | } | 404 | } |
405 | } while (pageData.hasNext()); | 405 | } while (pageData.hasNext()); |
406 | 406 | ||
@@ -410,13 +410,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -410,13 +410,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
410 | Assert.assertEquals(tenantAdminsEmail1, loadedTenantAdminsEmail1); | 410 | Assert.assertEquals(tenantAdminsEmail1, loadedTenantAdminsEmail1); |
411 | 411 | ||
412 | List<User> loadedTenantAdminsEmail2 = new ArrayList<>(); | 412 | List<User> loadedTenantAdminsEmail2 = new ArrayList<>(); |
413 | - pageLink = new TextPageLink(16, email2); | 413 | + pageLink = new PageLink(16, 0, email2); |
414 | do { | 414 | do { |
415 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 415 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
416 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 416 | + new TypeReference<PageData<User>>(){}, pageLink); |
417 | loadedTenantAdminsEmail2.addAll(pageData.getData()); | 417 | loadedTenantAdminsEmail2.addAll(pageData.getData()); |
418 | if (pageData.hasNext()) { | 418 | if (pageData.hasNext()) { |
419 | - pageLink = pageData.getNextPageLink(); | 419 | + pageLink = pageLink.nextPageLink(); |
420 | } | 420 | } |
421 | } while (pageData.hasNext()); | 421 | } while (pageData.hasNext()); |
422 | 422 | ||
@@ -430,9 +430,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -430,9 +430,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
430 | .andExpect(status().isOk()); | 430 | .andExpect(status().isOk()); |
431 | } | 431 | } |
432 | 432 | ||
433 | - pageLink = new TextPageLink(4, email1); | 433 | + pageLink = new PageLink(4, 0, email1); |
434 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 434 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
435 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 435 | + new TypeReference<PageData<User>>(){}, pageLink); |
436 | Assert.assertFalse(pageData.hasNext()); | 436 | Assert.assertFalse(pageData.hasNext()); |
437 | Assert.assertEquals(0, pageData.getData().size()); | 437 | Assert.assertEquals(0, pageData.getData().size()); |
438 | 438 | ||
@@ -441,9 +441,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -441,9 +441,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
441 | .andExpect(status().isOk()); | 441 | .andExpect(status().isOk()); |
442 | } | 442 | } |
443 | 443 | ||
444 | - pageLink = new TextPageLink(4, email2); | 444 | + pageLink = new PageLink(4, 0, email2); |
445 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", | 445 | pageData = doGetTypedWithPageLink("/api/tenant/" + tenantId.getId().toString() + "/users?", |
446 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 446 | + new TypeReference<PageData<User>>(){}, pageLink); |
447 | Assert.assertFalse(pageData.hasNext()); | 447 | Assert.assertFalse(pageData.hasNext()); |
448 | Assert.assertEquals(0, pageData.getData().size()); | 448 | Assert.assertEquals(0, pageData.getData().size()); |
449 | 449 | ||
@@ -486,14 +486,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -486,14 +486,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
486 | } | 486 | } |
487 | 487 | ||
488 | List<User> loadedCustomerUsers = new ArrayList<>(); | 488 | List<User> loadedCustomerUsers = new ArrayList<>(); |
489 | - TextPageLink pageLink = new TextPageLink(33); | ||
490 | - TextPageData<User> pageData = null; | 489 | + PageLink pageLink = new PageLink(33); |
490 | + PageData<User> pageData = null; | ||
491 | do { | 491 | do { |
492 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | 492 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
493 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 493 | + new TypeReference<PageData<User>>(){}, pageLink); |
494 | loadedCustomerUsers.addAll(pageData.getData()); | 494 | loadedCustomerUsers.addAll(pageData.getData()); |
495 | if (pageData.hasNext()) { | 495 | if (pageData.hasNext()) { |
496 | - pageLink = pageData.getNextPageLink(); | 496 | + pageLink = pageLink.nextPageLink(); |
497 | } | 497 | } |
498 | } while (pageData.hasNext()); | 498 | } while (pageData.hasNext()); |
499 | 499 | ||
@@ -565,14 +565,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -565,14 +565,14 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
565 | } | 565 | } |
566 | 566 | ||
567 | List<User> loadedCustomerUsersEmail1 = new ArrayList<>(); | 567 | List<User> loadedCustomerUsersEmail1 = new ArrayList<>(); |
568 | - TextPageLink pageLink = new TextPageLink(33, email1); | ||
569 | - TextPageData<User> pageData = null; | 568 | + PageLink pageLink = new PageLink(33, 0, email1); |
569 | + PageData<User> pageData = null; | ||
570 | do { | 570 | do { |
571 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | 571 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
572 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 572 | + new TypeReference<PageData<User>>(){}, pageLink); |
573 | loadedCustomerUsersEmail1.addAll(pageData.getData()); | 573 | loadedCustomerUsersEmail1.addAll(pageData.getData()); |
574 | if (pageData.hasNext()) { | 574 | if (pageData.hasNext()) { |
575 | - pageLink = pageData.getNextPageLink(); | 575 | + pageLink = pageLink.nextPageLink(); |
576 | } | 576 | } |
577 | } while (pageData.hasNext()); | 577 | } while (pageData.hasNext()); |
578 | 578 | ||
@@ -582,13 +582,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -582,13 +582,13 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
582 | Assert.assertEquals(customerUsersEmail1, loadedCustomerUsersEmail1); | 582 | Assert.assertEquals(customerUsersEmail1, loadedCustomerUsersEmail1); |
583 | 583 | ||
584 | List<User> loadedCustomerUsersEmail2 = new ArrayList<>(); | 584 | List<User> loadedCustomerUsersEmail2 = new ArrayList<>(); |
585 | - pageLink = new TextPageLink(16, email2); | 585 | + pageLink = new PageLink(16, 0, email2); |
586 | do { | 586 | do { |
587 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | 587 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
588 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 588 | + new TypeReference<PageData<User>>(){}, pageLink); |
589 | loadedCustomerUsersEmail2.addAll(pageData.getData()); | 589 | loadedCustomerUsersEmail2.addAll(pageData.getData()); |
590 | if (pageData.hasNext()) { | 590 | if (pageData.hasNext()) { |
591 | - pageLink = pageData.getNextPageLink(); | 591 | + pageLink = pageLink.nextPageLink(); |
592 | } | 592 | } |
593 | } while (pageData.hasNext()); | 593 | } while (pageData.hasNext()); |
594 | 594 | ||
@@ -602,9 +602,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -602,9 +602,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
602 | .andExpect(status().isOk()); | 602 | .andExpect(status().isOk()); |
603 | } | 603 | } |
604 | 604 | ||
605 | - pageLink = new TextPageLink(4, email1); | 605 | + pageLink = new PageLink(4, 0, email1); |
606 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | 606 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
607 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 607 | + new TypeReference<PageData<User>>(){}, pageLink); |
608 | Assert.assertFalse(pageData.hasNext()); | 608 | Assert.assertFalse(pageData.hasNext()); |
609 | Assert.assertEquals(0, pageData.getData().size()); | 609 | Assert.assertEquals(0, pageData.getData().size()); |
610 | 610 | ||
@@ -613,9 +613,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | @@ -613,9 +613,9 @@ public abstract class BaseUserControllerTest extends AbstractControllerTest { | ||
613 | .andExpect(status().isOk()); | 613 | .andExpect(status().isOk()); |
614 | } | 614 | } |
615 | 615 | ||
616 | - pageLink = new TextPageLink(4, email2); | 616 | + pageLink = new PageLink(4, 0, email2); |
617 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", | 617 | pageData = doGetTypedWithPageLink("/api/customer/" + customerId.getId().toString() + "/users?", |
618 | - new TypeReference<TextPageData<User>>(){}, pageLink); | 618 | + new TypeReference<PageData<User>>(){}, pageLink); |
619 | Assert.assertFalse(pageData.hasNext()); | 619 | Assert.assertFalse(pageData.hasNext()); |
620 | Assert.assertEquals(0, pageData.getData().size()); | 620 | Assert.assertEquals(0, pageData.getData().size()); |
621 | 621 |
@@ -22,8 +22,8 @@ import org.junit.Before; | @@ -22,8 +22,8 @@ import org.junit.Before; | ||
22 | import org.junit.Test; | 22 | import org.junit.Test; |
23 | import org.thingsboard.server.common.data.Tenant; | 23 | import org.thingsboard.server.common.data.Tenant; |
24 | import org.thingsboard.server.common.data.User; | 24 | import org.thingsboard.server.common.data.User; |
25 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
26 | -import org.thingsboard.server.common.data.page.TextPageLink; | 25 | +import org.thingsboard.server.common.data.page.PageData; |
26 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | import org.thingsboard.server.common.data.security.Authority; | 27 | import org.thingsboard.server.common.data.security.Authority; |
28 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 28 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
29 | 29 | ||
@@ -150,14 +150,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | @@ -150,14 +150,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | ||
150 | widgetsBundles.addAll(sysWidgetsBundles); | 150 | widgetsBundles.addAll(sysWidgetsBundles); |
151 | 151 | ||
152 | List<WidgetsBundle> loadedWidgetsBundles = new ArrayList<>(); | 152 | List<WidgetsBundle> loadedWidgetsBundles = new ArrayList<>(); |
153 | - TextPageLink pageLink = new TextPageLink(14); | ||
154 | - TextPageData<WidgetsBundle> pageData; | 153 | + PageLink pageLink = new PageLink(14); |
154 | + PageData<WidgetsBundle> pageData; | ||
155 | do { | 155 | do { |
156 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", | 156 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", |
157 | - new TypeReference<TextPageData<WidgetsBundle>>(){}, pageLink); | 157 | + new TypeReference<PageData<WidgetsBundle>>(){}, pageLink); |
158 | loadedWidgetsBundles.addAll(pageData.getData()); | 158 | loadedWidgetsBundles.addAll(pageData.getData()); |
159 | if (pageData.hasNext()) { | 159 | if (pageData.hasNext()) { |
160 | - pageLink = pageData.getNextPageLink(); | 160 | + pageLink = pageLink.nextPageLink(); |
161 | } | 161 | } |
162 | } while (pageData.hasNext()); | 162 | } while (pageData.hasNext()); |
163 | 163 | ||
@@ -186,14 +186,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | @@ -186,14 +186,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | ||
186 | widgetsBundles.addAll(sysWidgetsBundles); | 186 | widgetsBundles.addAll(sysWidgetsBundles); |
187 | 187 | ||
188 | List<WidgetsBundle> loadedWidgetsBundles = new ArrayList<>(); | 188 | List<WidgetsBundle> loadedWidgetsBundles = new ArrayList<>(); |
189 | - TextPageLink pageLink = new TextPageLink(14); | ||
190 | - TextPageData<WidgetsBundle> pageData; | 189 | + PageLink pageLink = new PageLink(14); |
190 | + PageData<WidgetsBundle> pageData; | ||
191 | do { | 191 | do { |
192 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", | 192 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", |
193 | - new TypeReference<TextPageData<WidgetsBundle>>(){}, pageLink); | 193 | + new TypeReference<PageData<WidgetsBundle>>(){}, pageLink); |
194 | loadedWidgetsBundles.addAll(pageData.getData()); | 194 | loadedWidgetsBundles.addAll(pageData.getData()); |
195 | if (pageData.hasNext()) { | 195 | if (pageData.hasNext()) { |
196 | - pageLink = pageData.getNextPageLink(); | 196 | + pageLink = pageLink.nextPageLink(); |
197 | } | 197 | } |
198 | } while (pageData.hasNext()); | 198 | } while (pageData.hasNext()); |
199 | 199 | ||
@@ -207,14 +207,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | @@ -207,14 +207,14 @@ public abstract class BaseWidgetsBundleControllerTest extends AbstractController | ||
207 | .andExpect(status().isOk()); | 207 | .andExpect(status().isOk()); |
208 | } | 208 | } |
209 | 209 | ||
210 | - pageLink = new TextPageLink(17); | 210 | + pageLink = new PageLink(17); |
211 | loadedWidgetsBundles.clear(); | 211 | loadedWidgetsBundles.clear(); |
212 | do { | 212 | do { |
213 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", | 213 | pageData = doGetTypedWithPageLink("/api/widgetsBundles?", |
214 | - new TypeReference<TextPageData<WidgetsBundle>>(){}, pageLink); | 214 | + new TypeReference<PageData<WidgetsBundle>>(){}, pageLink); |
215 | loadedWidgetsBundles.addAll(pageData.getData()); | 215 | loadedWidgetsBundles.addAll(pageData.getData()); |
216 | if (pageData.hasNext()) { | 216 | if (pageData.hasNext()) { |
217 | - pageLink = pageData.getNextPageLink(); | 217 | + pageLink = pageLink.nextPageLink(); |
218 | } | 218 | } |
219 | } while (pageData.hasNext()); | 219 | } while (pageData.hasNext()); |
220 | 220 |
@@ -20,6 +20,7 @@ import org.junit.ClassRule; | @@ -20,6 +20,7 @@ import org.junit.ClassRule; | ||
20 | import org.junit.extensions.cpsuite.ClasspathSuite; | 20 | import org.junit.extensions.cpsuite.ClasspathSuite; |
21 | import org.junit.runner.RunWith; | 21 | import org.junit.runner.RunWith; |
22 | import org.thingsboard.server.dao.CustomCassandraCQLUnit; | 22 | import org.thingsboard.server.dao.CustomCassandraCQLUnit; |
23 | +import org.thingsboard.server.dao.CustomSqlUnit; | ||
23 | 24 | ||
24 | import java.util.Arrays; | 25 | import java.util.Arrays; |
25 | 26 | ||
@@ -29,11 +30,15 @@ import java.util.Arrays; | @@ -29,11 +30,15 @@ import java.util.Arrays; | ||
29 | public class MqttNoSqlTestSuite { | 30 | public class MqttNoSqlTestSuite { |
30 | 31 | ||
31 | @ClassRule | 32 | @ClassRule |
33 | + public static CustomSqlUnit sqlUnit = new CustomSqlUnit( | ||
34 | + Arrays.asList("sql/schema-entities-hsql.sql", "sql/system-data.sql"), | ||
35 | + "sql/drop-all-tables.sql", | ||
36 | + "nosql-test.properties"); | ||
37 | + | ||
38 | + @ClassRule | ||
32 | public static CustomCassandraCQLUnit cassandraUnit = | 39 | public static CustomCassandraCQLUnit cassandraUnit = |
33 | new CustomCassandraCQLUnit( | 40 | new CustomCassandraCQLUnit( |
34 | Arrays.asList( | 41 | Arrays.asList( |
35 | - new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false), | ||
36 | - new ClassPathCQLDataSet("cassandra/schema-entities.cql", false, false), | ||
37 | - new ClassPathCQLDataSet("cassandra/system-data.cql", false, false)), | 42 | + new ClassPathCQLDataSet("cassandra/schema-ts.cql", false, false)), |
38 | "cassandra-test.yaml", 30000l); | 43 | "cassandra-test.yaml", 30000l); |
39 | } | 44 | } |
@@ -30,8 +30,7 @@ import org.thingsboard.server.actors.service.ActorService; | @@ -30,8 +30,7 @@ import org.thingsboard.server.actors.service.ActorService; | ||
30 | import org.thingsboard.server.common.data.*; | 30 | import org.thingsboard.server.common.data.*; |
31 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 31 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
32 | import org.thingsboard.server.common.data.kv.StringDataEntry; | 32 | import org.thingsboard.server.common.data.kv.StringDataEntry; |
33 | -import org.thingsboard.server.common.data.page.TextPageLink; | ||
34 | -import org.thingsboard.server.common.data.page.TimePageData; | 33 | +import org.thingsboard.server.common.data.page.PageData; |
35 | import org.thingsboard.server.common.data.rule.RuleChain; | 34 | import org.thingsboard.server.common.data.rule.RuleChain; |
36 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 35 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
37 | import org.thingsboard.server.common.data.rule.RuleNode; | 36 | import org.thingsboard.server.common.data.rule.RuleNode; |
@@ -160,7 +159,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | @@ -160,7 +159,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | ||
160 | 159 | ||
161 | Thread.sleep(3000); | 160 | Thread.sleep(3000); |
162 | 161 | ||
163 | - TimePageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); | 162 | + PageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); |
164 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); | 163 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); |
165 | Assert.assertEquals(2, events.size()); | 164 | Assert.assertEquals(2, events.size()); |
166 | 165 | ||
@@ -275,7 +274,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | @@ -275,7 +274,7 @@ public abstract class AbstractRuleEngineFlowIntegrationTest extends AbstractRule | ||
275 | 274 | ||
276 | Thread.sleep(3000); | 275 | Thread.sleep(3000); |
277 | 276 | ||
278 | - TimePageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), rootRuleChain.getFirstRuleNodeId(), 1000); | 277 | + PageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), rootRuleChain.getFirstRuleNodeId(), 1000); |
279 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); | 278 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); |
280 | 279 | ||
281 | Assert.assertEquals(2, events.size()); | 280 | Assert.assertEquals(2, events.size()); |
@@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.Tenant; | @@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.Tenant; | ||
32 | import org.thingsboard.server.common.data.User; | 32 | import org.thingsboard.server.common.data.User; |
33 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | 33 | import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; |
34 | import org.thingsboard.server.common.data.kv.StringDataEntry; | 34 | import org.thingsboard.server.common.data.kv.StringDataEntry; |
35 | -import org.thingsboard.server.common.data.page.TimePageData; | 35 | +import org.thingsboard.server.common.data.page.PageData; |
36 | import org.thingsboard.server.common.data.rule.RuleChain; | 36 | import org.thingsboard.server.common.data.rule.RuleChain; |
37 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 37 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
38 | import org.thingsboard.server.common.data.rule.RuleNode; | 38 | import org.thingsboard.server.common.data.rule.RuleNode; |
@@ -147,7 +147,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac | @@ -147,7 +147,7 @@ public abstract class AbstractRuleEngineLifecycleIntegrationTest extends Abstrac | ||
147 | 147 | ||
148 | Thread.sleep(3000); | 148 | Thread.sleep(3000); |
149 | 149 | ||
150 | - TimePageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); | 150 | + PageData<Event> eventsPage = getDebugEvents(savedTenant.getId(), ruleChain.getFirstRuleNodeId(), 1000); |
151 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); | 151 | List<Event> events = eventsPage.getData().stream().filter(filterByCustomEvent()).collect(Collectors.toList()); |
152 | 152 | ||
153 | Assert.assertEquals(2, events.size()); | 153 | Assert.assertEquals(2, events.size()); |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; | @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; | ||
26 | import org.thingsboard.server.common.data.alarm.AlarmStatus; | 26 | import org.thingsboard.server.common.data.alarm.AlarmStatus; |
27 | import org.thingsboard.server.common.data.id.EntityId; | 27 | import org.thingsboard.server.common.data.id.EntityId; |
28 | import org.thingsboard.server.common.data.id.TenantId; | 28 | import org.thingsboard.server.common.data.id.TenantId; |
29 | -import org.thingsboard.server.common.data.page.TimePageData; | 29 | +import org.thingsboard.server.common.data.page.PageData; |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Created by ashvayka on 11.05.17. | 32 | * Created by ashvayka on 11.05.17. |
@@ -45,7 +45,7 @@ public interface AlarmService { | @@ -45,7 +45,7 @@ public interface AlarmService { | ||
45 | 45 | ||
46 | ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(TenantId tenantId, AlarmId alarmId); | 46 | ListenableFuture<AlarmInfo> findAlarmInfoByIdAsync(TenantId tenantId, AlarmId alarmId); |
47 | 47 | ||
48 | - ListenableFuture<TimePageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); | 48 | + ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); |
49 | 49 | ||
50 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, | 50 | AlarmSeverity findHighestAlarmSeverity(TenantId tenantId, EntityId entityId, AlarmSearchStatus alarmSearchStatus, |
51 | AlarmStatus alarmStatus); | 51 | AlarmStatus alarmStatus); |
@@ -18,18 +18,21 @@ package org.thingsboard.server.dao.asset; | @@ -18,18 +18,21 @@ package org.thingsboard.server.dao.asset; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.EntitySubtype; | 19 | import org.thingsboard.server.common.data.EntitySubtype; |
20 | import org.thingsboard.server.common.data.asset.Asset; | 20 | import org.thingsboard.server.common.data.asset.Asset; |
21 | +import org.thingsboard.server.common.data.asset.AssetInfo; | ||
21 | import org.thingsboard.server.common.data.asset.AssetSearchQuery; | 22 | import org.thingsboard.server.common.data.asset.AssetSearchQuery; |
22 | import org.thingsboard.server.common.data.id.AssetId; | 23 | import org.thingsboard.server.common.data.id.AssetId; |
23 | import org.thingsboard.server.common.data.id.CustomerId; | 24 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
25 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
26 | -import org.thingsboard.server.common.data.page.TextPageLink; | 26 | +import org.thingsboard.server.common.data.page.PageData; |
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | 28 | ||
28 | import java.util.List; | 29 | import java.util.List; |
29 | import java.util.Optional; | 30 | import java.util.Optional; |
30 | 31 | ||
31 | public interface AssetService { | 32 | public interface AssetService { |
32 | 33 | ||
34 | + AssetInfo findAssetInfoById(TenantId tenantId, AssetId assetId); | ||
35 | + | ||
33 | Asset findAssetById(TenantId tenantId, AssetId assetId); | 36 | Asset findAssetById(TenantId tenantId, AssetId assetId); |
34 | 37 | ||
35 | ListenableFuture<Asset> findAssetByIdAsync(TenantId tenantId, AssetId assetId); | 38 | ListenableFuture<Asset> findAssetByIdAsync(TenantId tenantId, AssetId assetId); |
@@ -44,17 +47,25 @@ public interface AssetService { | @@ -44,17 +47,25 @@ public interface AssetService { | ||
44 | 47 | ||
45 | void deleteAsset(TenantId tenantId, AssetId assetId); | 48 | void deleteAsset(TenantId tenantId, AssetId assetId); |
46 | 49 | ||
47 | - TextPageData<Asset> findAssetsByTenantId(TenantId tenantId, TextPageLink pageLink); | 50 | + PageData<Asset> findAssetsByTenantId(TenantId tenantId, PageLink pageLink); |
51 | + | ||
52 | + PageData<AssetInfo> findAssetInfosByTenantId(TenantId tenantId, PageLink pageLink); | ||
53 | + | ||
54 | + PageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); | ||
48 | 55 | ||
49 | - TextPageData<Asset> findAssetsByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | 56 | + PageData<AssetInfo> findAssetInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); |
50 | 57 | ||
51 | ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); | 58 | ListenableFuture<List<Asset>> findAssetsByTenantIdAndIdsAsync(TenantId tenantId, List<AssetId> assetIds); |
52 | 59 | ||
53 | void deleteAssetsByTenantId(TenantId tenantId); | 60 | void deleteAssetsByTenantId(TenantId tenantId); |
54 | 61 | ||
55 | - TextPageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 62 | + PageData<Asset> findAssetsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); |
63 | + | ||
64 | + PageData<AssetInfo> findAssetInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); | ||
65 | + | ||
66 | + PageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); | ||
56 | 67 | ||
57 | - TextPageData<Asset> findAssetsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink); | 68 | + PageData<AssetInfo> findAssetInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); |
58 | 69 | ||
59 | ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); | 70 | ListenableFuture<List<Asset>> findAssetsByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<AssetId> assetIds); |
60 | 71 |
@@ -25,20 +25,20 @@ import org.thingsboard.server.common.data.id.EntityId; | @@ -25,20 +25,20 @@ import org.thingsboard.server.common.data.id.EntityId; | ||
25 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
26 | import org.thingsboard.server.common.data.id.UUIDBased; | 26 | import org.thingsboard.server.common.data.id.UUIDBased; |
27 | import org.thingsboard.server.common.data.id.UserId; | 27 | import org.thingsboard.server.common.data.id.UserId; |
28 | -import org.thingsboard.server.common.data.page.TimePageData; | 28 | +import org.thingsboard.server.common.data.page.PageData; |
29 | import org.thingsboard.server.common.data.page.TimePageLink; | 29 | import org.thingsboard.server.common.data.page.TimePageLink; |
30 | 30 | ||
31 | import java.util.List; | 31 | import java.util.List; |
32 | 32 | ||
33 | public interface AuditLogService { | 33 | public interface AuditLogService { |
34 | 34 | ||
35 | - TimePageData<AuditLog> findAuditLogsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, List<ActionType> actionTypes, TimePageLink pageLink); | 35 | + PageData<AuditLog> findAuditLogsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, List<ActionType> actionTypes, TimePageLink pageLink); |
36 | 36 | ||
37 | - TimePageData<AuditLog> findAuditLogsByTenantIdAndUserId(TenantId tenantId, UserId userId, List<ActionType> actionTypes, TimePageLink pageLink); | 37 | + PageData<AuditLog> findAuditLogsByTenantIdAndUserId(TenantId tenantId, UserId userId, List<ActionType> actionTypes, TimePageLink pageLink); |
38 | 38 | ||
39 | - TimePageData<AuditLog> findAuditLogsByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, List<ActionType> actionTypes, TimePageLink pageLink); | 39 | + PageData<AuditLog> findAuditLogsByTenantIdAndEntityId(TenantId tenantId, EntityId entityId, List<ActionType> actionTypes, TimePageLink pageLink); |
40 | 40 | ||
41 | - TimePageData<AuditLog> findAuditLogsByTenantId(TenantId tenantId, List<ActionType> actionTypes, TimePageLink pageLink); | 41 | + PageData<AuditLog> findAuditLogsByTenantId(TenantId tenantId, List<ActionType> actionTypes, TimePageLink pageLink); |
42 | 42 | ||
43 | <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> logEntityAction( | 43 | <E extends HasName, I extends EntityId> ListenableFuture<List<Void>> logEntityAction( |
44 | TenantId tenantId, | 44 | TenantId tenantId, |
@@ -18,8 +18,8 @@ package org.thingsboard.server.dao.component; | @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.component; | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import org.thingsboard.server.common.data.id.ComponentDescriptorId; | 19 | import org.thingsboard.server.common.data.id.ComponentDescriptorId; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
21 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
22 | -import org.thingsboard.server.common.data.page.TextPageLink; | 21 | +import org.thingsboard.server.common.data.page.PageData; |
22 | +import org.thingsboard.server.common.data.page.PageLink; | ||
23 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; | 23 | import org.thingsboard.server.common.data.plugin.ComponentDescriptor; |
24 | import org.thingsboard.server.common.data.plugin.ComponentScope; | 24 | import org.thingsboard.server.common.data.plugin.ComponentScope; |
25 | import org.thingsboard.server.common.data.plugin.ComponentType; | 25 | import org.thingsboard.server.common.data.plugin.ComponentType; |
@@ -35,9 +35,9 @@ public interface ComponentDescriptorService { | @@ -35,9 +35,9 @@ public interface ComponentDescriptorService { | ||
35 | 35 | ||
36 | ComponentDescriptor findByClazz(TenantId tenantId, String clazz); | 36 | ComponentDescriptor findByClazz(TenantId tenantId, String clazz); |
37 | 37 | ||
38 | - TextPageData<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, TextPageLink pageLink); | 38 | + PageData<ComponentDescriptor> findByTypeAndPageLink(TenantId tenantId, ComponentType type, PageLink pageLink); |
39 | 39 | ||
40 | - TextPageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, TextPageLink pageLink); | 40 | + PageData<ComponentDescriptor> findByScopeAndTypeAndPageLink(TenantId tenantId, ComponentScope scope, ComponentType type, PageLink pageLink); |
41 | 41 | ||
42 | boolean validate(TenantId tenantId, ComponentDescriptor component, JsonNode configuration); | 42 | boolean validate(TenantId tenantId, ComponentDescriptor component, JsonNode configuration); |
43 | 43 |
@@ -19,8 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -19,8 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
19 | import org.thingsboard.server.common.data.Customer; | 19 | import org.thingsboard.server.common.data.Customer; |
20 | import org.thingsboard.server.common.data.id.CustomerId; | 20 | import org.thingsboard.server.common.data.id.CustomerId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
23 | -import org.thingsboard.server.common.data.page.TextPageLink; | 22 | +import org.thingsboard.server.common.data.page.PageData; |
23 | +import org.thingsboard.server.common.data.page.PageLink; | ||
24 | 24 | ||
25 | import java.util.Optional; | 25 | import java.util.Optional; |
26 | 26 | ||
@@ -38,7 +38,7 @@ public interface CustomerService { | @@ -38,7 +38,7 @@ public interface CustomerService { | ||
38 | 38 | ||
39 | Customer findOrCreatePublicCustomer(TenantId tenantId); | 39 | Customer findOrCreatePublicCustomer(TenantId tenantId); |
40 | 40 | ||
41 | - TextPageData<Customer> findCustomersByTenantId(TenantId tenantId, TextPageLink pageLink); | 41 | + PageData<Customer> findCustomersByTenantId(TenantId tenantId, PageLink pageLink); |
42 | 42 | ||
43 | void deleteCustomersByTenantId(TenantId tenantId); | 43 | void deleteCustomersByTenantId(TenantId tenantId); |
44 | 44 |
@@ -21,9 +21,8 @@ import org.thingsboard.server.common.data.DashboardInfo; | @@ -21,9 +21,8 @@ import org.thingsboard.server.common.data.DashboardInfo; | ||
21 | import org.thingsboard.server.common.data.id.CustomerId; | 21 | import org.thingsboard.server.common.data.id.CustomerId; |
22 | import org.thingsboard.server.common.data.id.DashboardId; | 22 | import org.thingsboard.server.common.data.id.DashboardId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
25 | -import org.thingsboard.server.common.data.page.TextPageLink; | ||
26 | -import org.thingsboard.server.common.data.page.TimePageData; | 24 | +import org.thingsboard.server.common.data.page.PageData; |
25 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | import org.thingsboard.server.common.data.page.TimePageLink; | 26 | import org.thingsboard.server.common.data.page.TimePageLink; |
28 | 27 | ||
29 | public interface DashboardService { | 28 | public interface DashboardService { |
@@ -44,11 +43,11 @@ public interface DashboardService { | @@ -44,11 +43,11 @@ public interface DashboardService { | ||
44 | 43 | ||
45 | void deleteDashboard(TenantId tenantId, DashboardId dashboardId); | 44 | void deleteDashboard(TenantId tenantId, DashboardId dashboardId); |
46 | 45 | ||
47 | - TextPageData<DashboardInfo> findDashboardsByTenantId(TenantId tenantId, TextPageLink pageLink); | 46 | + PageData<DashboardInfo> findDashboardsByTenantId(TenantId tenantId, PageLink pageLink); |
48 | 47 | ||
49 | void deleteDashboardsByTenantId(TenantId tenantId); | 48 | void deleteDashboardsByTenantId(TenantId tenantId); |
50 | 49 | ||
51 | - ListenableFuture<TimePageData<DashboardInfo>> findDashboardsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TimePageLink pageLink); | 50 | + PageData<DashboardInfo> findDashboardsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); |
52 | 51 | ||
53 | void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId); | 52 | void unassignCustomerDashboards(TenantId tenantId, CustomerId customerId); |
54 | 53 |
@@ -17,18 +17,21 @@ package org.thingsboard.server.dao.device; | @@ -17,18 +17,21 @@ package org.thingsboard.server.dao.device; | ||
17 | 17 | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.Device; | 19 | import org.thingsboard.server.common.data.Device; |
20 | +import org.thingsboard.server.common.data.DeviceInfo; | ||
20 | import org.thingsboard.server.common.data.EntitySubtype; | 21 | import org.thingsboard.server.common.data.EntitySubtype; |
21 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; | 22 | import org.thingsboard.server.common.data.device.DeviceSearchQuery; |
22 | import org.thingsboard.server.common.data.id.CustomerId; | 23 | import org.thingsboard.server.common.data.id.CustomerId; |
23 | import org.thingsboard.server.common.data.id.DeviceId; | 24 | import org.thingsboard.server.common.data.id.DeviceId; |
24 | import org.thingsboard.server.common.data.id.TenantId; | 25 | import org.thingsboard.server.common.data.id.TenantId; |
25 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
26 | -import org.thingsboard.server.common.data.page.TextPageLink; | 26 | +import org.thingsboard.server.common.data.page.PageData; |
27 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | 28 | ||
28 | import java.util.List; | 29 | import java.util.List; |
29 | 30 | ||
30 | public interface DeviceService { | 31 | public interface DeviceService { |
31 | - | 32 | + |
33 | + DeviceInfo findDeviceInfoById(TenantId tenantId, DeviceId deviceId); | ||
34 | + | ||
32 | Device findDeviceById(TenantId tenantId, DeviceId deviceId); | 35 | Device findDeviceById(TenantId tenantId, DeviceId deviceId); |
33 | 36 | ||
34 | ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId); | 37 | ListenableFuture<Device> findDeviceByIdAsync(TenantId tenantId, DeviceId deviceId); |
@@ -45,17 +48,25 @@ public interface DeviceService { | @@ -45,17 +48,25 @@ public interface DeviceService { | ||
45 | 48 | ||
46 | void deleteDevice(TenantId tenantId, DeviceId deviceId); | 49 | void deleteDevice(TenantId tenantId, DeviceId deviceId); |
47 | 50 | ||
48 | - TextPageData<Device> findDevicesByTenantId(TenantId tenantId, TextPageLink pageLink); | 51 | + PageData<Device> findDevicesByTenantId(TenantId tenantId, PageLink pageLink); |
52 | + | ||
53 | + PageData<DeviceInfo> findDeviceInfosByTenantId(TenantId tenantId, PageLink pageLink); | ||
49 | 54 | ||
50 | - TextPageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, TextPageLink pageLink); | 55 | + PageData<Device> findDevicesByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); |
56 | + | ||
57 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); | ||
51 | 58 | ||
52 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); | 59 | ListenableFuture<List<Device>> findDevicesByTenantIdAndIdsAsync(TenantId tenantId, List<DeviceId> deviceIds); |
53 | 60 | ||
54 | void deleteDevicesByTenantId(TenantId tenantId); | 61 | void deleteDevicesByTenantId(TenantId tenantId); |
55 | 62 | ||
56 | - TextPageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 63 | + PageData<Device> findDevicesByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); |
64 | + | ||
65 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); | ||
66 | + | ||
67 | + PageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); | ||
57 | 68 | ||
58 | - TextPageData<Device> findDevicesByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, TextPageLink pageLink); | 69 | + PageData<DeviceInfo> findDeviceInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); |
59 | 70 | ||
60 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); | 71 | ListenableFuture<List<Device>> findDevicesByTenantIdCustomerIdAndIdsAsync(TenantId tenantId, CustomerId customerId, List<DeviceId> deviceIds); |
61 | 72 |
@@ -18,14 +18,15 @@ package org.thingsboard.server.dao.entityview; | @@ -18,14 +18,15 @@ package org.thingsboard.server.dao.entityview; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.EntitySubtype; | 19 | import org.thingsboard.server.common.data.EntitySubtype; |
20 | import org.thingsboard.server.common.data.EntityView; | 20 | import org.thingsboard.server.common.data.EntityView; |
21 | +import org.thingsboard.server.common.data.EntityViewInfo; | ||
21 | import org.thingsboard.server.common.data.Tenant; | 22 | import org.thingsboard.server.common.data.Tenant; |
22 | import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; | 23 | import org.thingsboard.server.common.data.entityview.EntityViewSearchQuery; |
23 | import org.thingsboard.server.common.data.id.CustomerId; | 24 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | import org.thingsboard.server.common.data.id.EntityId; | 25 | import org.thingsboard.server.common.data.id.EntityId; |
25 | import org.thingsboard.server.common.data.id.EntityViewId; | 26 | import org.thingsboard.server.common.data.id.EntityViewId; |
26 | import org.thingsboard.server.common.data.id.TenantId; | 27 | import org.thingsboard.server.common.data.id.TenantId; |
27 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
28 | -import org.thingsboard.server.common.data.page.TextPageLink; | 28 | +import org.thingsboard.server.common.data.page.PageData; |
29 | +import org.thingsboard.server.common.data.page.PageLink; | ||
29 | 30 | ||
30 | import java.util.List; | 31 | import java.util.List; |
31 | 32 | ||
@@ -42,17 +43,27 @@ public interface EntityViewService { | @@ -42,17 +43,27 @@ public interface EntityViewService { | ||
42 | 43 | ||
43 | void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); | 44 | void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); |
44 | 45 | ||
46 | + EntityViewInfo findEntityViewInfoById(TenantId tenantId, EntityViewId entityViewId); | ||
47 | + | ||
45 | EntityView findEntityViewById(TenantId tenantId, EntityViewId entityViewId); | 48 | EntityView findEntityViewById(TenantId tenantId, EntityViewId entityViewId); |
46 | 49 | ||
47 | EntityView findEntityViewByTenantIdAndName(TenantId tenantId, String name); | 50 | EntityView findEntityViewByTenantIdAndName(TenantId tenantId, String name); |
48 | 51 | ||
49 | - TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink); | 52 | + PageData<EntityView> findEntityViewByTenantId(TenantId tenantId, PageLink pageLink); |
53 | + | ||
54 | + PageData<EntityViewInfo> findEntityViewInfosByTenantId(TenantId tenantId, PageLink pageLink); | ||
55 | + | ||
56 | + PageData<EntityView> findEntityViewByTenantIdAndType(TenantId tenantId, PageLink pageLink, String type); | ||
57 | + | ||
58 | + PageData<EntityViewInfo> findEntityViewInfosByTenantIdAndType(TenantId tenantId, String type, PageLink pageLink); | ||
59 | + | ||
60 | + PageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); | ||
50 | 61 | ||
51 | - TextPageData<EntityView> findEntityViewByTenantIdAndType(TenantId tenantId, TextPageLink pageLink, String type); | 62 | + PageData<EntityViewInfo> findEntityViewInfosByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, PageLink pageLink); |
52 | 63 | ||
53 | - TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 64 | + PageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, PageLink pageLink, String type); |
54 | 65 | ||
55 | - TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, TextPageLink pageLink, String type); | 66 | + PageData<EntityViewInfo> findEntityViewInfosByTenantIdAndCustomerIdAndType(TenantId tenantId, CustomerId customerId, String type, PageLink pageLink); |
56 | 67 | ||
57 | ListenableFuture<List<EntityView>> findEntityViewsByQuery(TenantId tenantId, EntityViewSearchQuery query); | 68 | ListenableFuture<List<EntityView>> findEntityViewsByQuery(TenantId tenantId, EntityViewSearchQuery query); |
58 | 69 |
@@ -19,7 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -19,7 +19,7 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
19 | import org.thingsboard.server.common.data.Event; | 19 | import org.thingsboard.server.common.data.Event; |
20 | import org.thingsboard.server.common.data.id.EntityId; | 20 | import org.thingsboard.server.common.data.id.EntityId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | -import org.thingsboard.server.common.data.page.TimePageData; | 22 | +import org.thingsboard.server.common.data.page.PageData; |
23 | import org.thingsboard.server.common.data.page.TimePageLink; | 23 | import org.thingsboard.server.common.data.page.TimePageLink; |
24 | 24 | ||
25 | import java.util.List; | 25 | import java.util.List; |
@@ -35,9 +35,9 @@ public interface EventService { | @@ -35,9 +35,9 @@ public interface EventService { | ||
35 | 35 | ||
36 | Optional<Event> findEvent(TenantId tenantId, EntityId entityId, String eventType, String eventUid); | 36 | Optional<Event> findEvent(TenantId tenantId, EntityId entityId, String eventType, String eventUid); |
37 | 37 | ||
38 | - TimePageData<Event> findEvents(TenantId tenantId, EntityId entityId, TimePageLink pageLink); | 38 | + PageData<Event> findEvents(TenantId tenantId, EntityId entityId, TimePageLink pageLink); |
39 | 39 | ||
40 | - TimePageData<Event> findEvents(TenantId tenantId, EntityId entityId, String eventType, TimePageLink pageLink); | 40 | + PageData<Event> findEvents(TenantId tenantId, EntityId entityId, String eventType, TimePageLink pageLink); |
41 | 41 | ||
42 | List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit); | 42 | List<Event> findLatestEvents(TenantId tenantId, EntityId entityId, String eventType, int limit); |
43 | 43 |
@@ -19,8 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; | @@ -19,8 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; | ||
19 | import org.thingsboard.server.common.data.id.RuleChainId; | 19 | import org.thingsboard.server.common.data.id.RuleChainId; |
20 | import org.thingsboard.server.common.data.id.RuleNodeId; | 20 | import org.thingsboard.server.common.data.id.RuleNodeId; |
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
23 | -import org.thingsboard.server.common.data.page.TextPageLink; | 22 | +import org.thingsboard.server.common.data.page.PageData; |
23 | +import org.thingsboard.server.common.data.page.PageLink; | ||
24 | import org.thingsboard.server.common.data.relation.EntityRelation; | 24 | import org.thingsboard.server.common.data.relation.EntityRelation; |
25 | import org.thingsboard.server.common.data.rule.RuleChain; | 25 | import org.thingsboard.server.common.data.rule.RuleChain; |
26 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; | 26 | import org.thingsboard.server.common.data.rule.RuleChainMetaData; |
@@ -57,7 +57,7 @@ public interface RuleChainService { | @@ -57,7 +57,7 @@ public interface RuleChainService { | ||
57 | 57 | ||
58 | List<EntityRelation> getRuleNodeRelations(TenantId tenantId, RuleNodeId ruleNodeId); | 58 | List<EntityRelation> getRuleNodeRelations(TenantId tenantId, RuleNodeId ruleNodeId); |
59 | 59 | ||
60 | - TextPageData<RuleChain> findTenantRuleChains(TenantId tenantId, TextPageLink pageLink); | 60 | + PageData<RuleChain> findTenantRuleChains(TenantId tenantId, PageLink pageLink); |
61 | 61 | ||
62 | void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId); | 62 | void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId); |
63 | 63 |
@@ -18,8 +18,8 @@ package org.thingsboard.server.dao.tenant; | @@ -18,8 +18,8 @@ package org.thingsboard.server.dao.tenant; | ||
18 | import com.google.common.util.concurrent.ListenableFuture; | 18 | import com.google.common.util.concurrent.ListenableFuture; |
19 | import org.thingsboard.server.common.data.Tenant; | 19 | import org.thingsboard.server.common.data.Tenant; |
20 | import org.thingsboard.server.common.data.id.TenantId; | 20 | import org.thingsboard.server.common.data.id.TenantId; |
21 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
22 | -import org.thingsboard.server.common.data.page.TextPageLink; | 21 | +import org.thingsboard.server.common.data.page.PageData; |
22 | +import org.thingsboard.server.common.data.page.PageLink; | ||
23 | 23 | ||
24 | public interface TenantService { | 24 | public interface TenantService { |
25 | 25 | ||
@@ -31,7 +31,7 @@ public interface TenantService { | @@ -31,7 +31,7 @@ public interface TenantService { | ||
31 | 31 | ||
32 | void deleteTenant(TenantId tenantId); | 32 | void deleteTenant(TenantId tenantId); |
33 | 33 | ||
34 | - TextPageData<Tenant> findTenants(TextPageLink pageLink); | 34 | + PageData<Tenant> findTenants(PageLink pageLink); |
35 | 35 | ||
36 | void deleteTenants(); | 36 | void deleteTenants(); |
37 | } | 37 | } |
@@ -21,8 +21,8 @@ import org.thingsboard.server.common.data.id.CustomerId; | @@ -21,8 +21,8 @@ import org.thingsboard.server.common.data.id.CustomerId; | ||
21 | import org.thingsboard.server.common.data.id.TenantId; | 21 | import org.thingsboard.server.common.data.id.TenantId; |
22 | import org.thingsboard.server.common.data.id.UserCredentialsId; | 22 | import org.thingsboard.server.common.data.id.UserCredentialsId; |
23 | import org.thingsboard.server.common.data.id.UserId; | 23 | import org.thingsboard.server.common.data.id.UserId; |
24 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
25 | -import org.thingsboard.server.common.data.page.TextPageLink; | 24 | +import org.thingsboard.server.common.data.page.PageData; |
25 | +import org.thingsboard.server.common.data.page.PageLink; | ||
26 | import org.thingsboard.server.common.data.security.UserCredentials; | 26 | import org.thingsboard.server.common.data.security.UserCredentials; |
27 | 27 | ||
28 | public interface UserService { | 28 | public interface UserService { |
@@ -53,11 +53,11 @@ public interface UserService { | @@ -53,11 +53,11 @@ public interface UserService { | ||
53 | 53 | ||
54 | void deleteUser(TenantId tenantId, UserId userId); | 54 | void deleteUser(TenantId tenantId, UserId userId); |
55 | 55 | ||
56 | - TextPageData<User> findTenantAdmins(TenantId tenantId, TextPageLink pageLink); | 56 | + PageData<User> findTenantAdmins(TenantId tenantId, PageLink pageLink); |
57 | 57 | ||
58 | void deleteTenantAdmins(TenantId tenantId); | 58 | void deleteTenantAdmins(TenantId tenantId); |
59 | - | ||
60 | - TextPageData<User> findCustomerUsers(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); | 59 | + |
60 | + PageData<User> findCustomerUsers(TenantId tenantId, CustomerId customerId, PageLink pageLink); | ||
61 | 61 | ||
62 | void deleteCustomerUsers(TenantId tenantId, CustomerId customerId); | 62 | void deleteCustomerUsers(TenantId tenantId, CustomerId customerId); |
63 | 63 |
@@ -17,6 +17,5 @@ package org.thingsboard.server.dao.util; | @@ -17,6 +17,5 @@ package org.thingsboard.server.dao.util; | ||
17 | 17 | ||
18 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 18 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
19 | 19 | ||
20 | -@ConditionalOnProperty(prefix = "database.entities", value = "type", havingValue = "sql") | ||
21 | public @interface SqlDao { | 20 | public @interface SqlDao { |
22 | } | 21 | } |
@@ -17,8 +17,8 @@ package org.thingsboard.server.dao.widget; | @@ -17,8 +17,8 @@ package org.thingsboard.server.dao.widget; | ||
17 | 17 | ||
18 | import org.thingsboard.server.common.data.id.TenantId; | 18 | import org.thingsboard.server.common.data.id.TenantId; |
19 | import org.thingsboard.server.common.data.id.WidgetsBundleId; | 19 | import org.thingsboard.server.common.data.id.WidgetsBundleId; |
20 | -import org.thingsboard.server.common.data.page.TextPageData; | ||
21 | -import org.thingsboard.server.common.data.page.TextPageLink; | 20 | +import org.thingsboard.server.common.data.page.PageData; |
21 | +import org.thingsboard.server.common.data.page.PageLink; | ||
22 | import org.thingsboard.server.common.data.widget.WidgetsBundle; | 22 | import org.thingsboard.server.common.data.widget.WidgetsBundle; |
23 | 23 | ||
24 | import java.util.List; | 24 | import java.util.List; |
@@ -33,13 +33,13 @@ public interface WidgetsBundleService { | @@ -33,13 +33,13 @@ public interface WidgetsBundleService { | ||
33 | 33 | ||
34 | WidgetsBundle findWidgetsBundleByTenantIdAndAlias(TenantId tenantId, String alias); | 34 | WidgetsBundle findWidgetsBundleByTenantIdAndAlias(TenantId tenantId, String alias); |
35 | 35 | ||
36 | - TextPageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, TextPageLink pageLink); | 36 | + PageData<WidgetsBundle> findSystemWidgetsBundlesByPageLink(TenantId tenantId, PageLink pageLink); |
37 | 37 | ||
38 | List<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId); | 38 | List<WidgetsBundle> findSystemWidgetsBundles(TenantId tenantId); |
39 | 39 | ||
40 | - TextPageData<WidgetsBundle> findTenantWidgetsBundlesByTenantId(TenantId tenantId, TextPageLink pageLink); | 40 | + PageData<WidgetsBundle> findTenantWidgetsBundlesByTenantId(TenantId tenantId, PageLink pageLink); |
41 | 41 | ||
42 | - TextPageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, TextPageLink pageLink); | 42 | + PageData<WidgetsBundle> findAllTenantWidgetsBundlesByTenantIdAndPageLink(TenantId tenantId, PageLink pageLink); |
43 | 43 | ||
44 | List<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(TenantId tenantId); | 44 | List<WidgetsBundle> findAllTenantWidgetsBundlesByTenantId(TenantId tenantId); |
45 | 45 |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.DeviceId; | ||
20 | + | ||
21 | +@Data | ||
22 | +public class DeviceInfo extends Device { | ||
23 | + | ||
24 | + private String customerTitle; | ||
25 | + private boolean customerIsPublic; | ||
26 | + | ||
27 | + public DeviceInfo() { | ||
28 | + super(); | ||
29 | + } | ||
30 | + | ||
31 | + public DeviceInfo(DeviceId deviceId) { | ||
32 | + super(deviceId); | ||
33 | + } | ||
34 | + | ||
35 | + public DeviceInfo(Device device, String customerTitle, boolean customerIsPublic) { | ||
36 | + super(device); | ||
37 | + this.customerTitle = customerTitle; | ||
38 | + this.customerIsPublic = customerIsPublic; | ||
39 | + } | ||
40 | +} |
@@ -55,6 +55,14 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> | @@ -55,6 +55,14 @@ public class EntityView extends SearchTextBasedWithAdditionalInfo<EntityViewId> | ||
55 | 55 | ||
56 | public EntityView(EntityView entityView) { | 56 | public EntityView(EntityView entityView) { |
57 | super(entityView); | 57 | super(entityView); |
58 | + this.entityId = entityView.getEntityId(); | ||
59 | + this.tenantId = entityView.getTenantId(); | ||
60 | + this.customerId = entityView.getCustomerId(); | ||
61 | + this.name = entityView.getName(); | ||
62 | + this.type = entityView.getType(); | ||
63 | + this.keys = entityView.getKeys(); | ||
64 | + this.startTimeMs = entityView.getStartTimeMs(); | ||
65 | + this.endTimeMs = entityView.getEndTimeMs(); | ||
58 | } | 66 | } |
59 | 67 | ||
60 | @Override | 68 | @Override |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.EntityViewId; | ||
20 | + | ||
21 | +@Data | ||
22 | +public class EntityViewInfo extends EntityView { | ||
23 | + | ||
24 | + private String customerTitle; | ||
25 | + private boolean customerIsPublic; | ||
26 | + | ||
27 | + public EntityViewInfo() { | ||
28 | + super(); | ||
29 | + } | ||
30 | + | ||
31 | + public EntityViewInfo(EntityViewId entityViewId) { | ||
32 | + super(entityViewId); | ||
33 | + } | ||
34 | + | ||
35 | + public EntityViewInfo(EntityView entityView, String customerTitle, boolean customerIsPublic) { | ||
36 | + super(entityView); | ||
37 | + this.customerTitle = customerTitle; | ||
38 | + this.customerIsPublic = customerIsPublic; | ||
39 | + } | ||
40 | +} |
@@ -29,6 +29,11 @@ public class AlarmInfo extends Alarm { | @@ -29,6 +29,11 @@ public class AlarmInfo extends Alarm { | ||
29 | super(alarm); | 29 | super(alarm); |
30 | } | 30 | } |
31 | 31 | ||
32 | + public AlarmInfo(Alarm alarm, String originatorName) { | ||
33 | + super(alarm); | ||
34 | + this.originatorName = originatorName; | ||
35 | + } | ||
36 | + | ||
32 | public String getOriginatorName() { | 37 | public String getOriginatorName() { |
33 | return originatorName; | 38 | return originatorName; |
34 | } | 39 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.asset; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | +import org.thingsboard.server.common.data.id.AssetId; | ||
20 | + | ||
21 | +@Data | ||
22 | +public class AssetInfo extends Asset { | ||
23 | + | ||
24 | + private String customerTitle; | ||
25 | + private boolean customerIsPublic; | ||
26 | + | ||
27 | + public AssetInfo() { | ||
28 | + super(); | ||
29 | + } | ||
30 | + | ||
31 | + public AssetInfo(AssetId assetId) { | ||
32 | + super(assetId); | ||
33 | + } | ||
34 | + | ||
35 | + public AssetInfo(Asset asset, String customerTitle, boolean customerIsPublic) { | ||
36 | + super(asset); | ||
37 | + this.customerTitle = customerTitle; | ||
38 | + this.customerIsPublic = customerIsPublic; | ||
39 | + } | ||
40 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/page/PageData.java
renamed from
common/data/src/main/java/org/thingsboard/server/common/data/page/TimePageData.java
@@ -18,39 +18,29 @@ package org.thingsboard.server.common.data.page; | @@ -18,39 +18,29 @@ package org.thingsboard.server.common.data.page; | ||
18 | import com.fasterxml.jackson.annotation.JsonCreator; | 18 | import com.fasterxml.jackson.annotation.JsonCreator; |
19 | import com.fasterxml.jackson.annotation.JsonProperty; | 19 | import com.fasterxml.jackson.annotation.JsonProperty; |
20 | import org.thingsboard.server.common.data.BaseData; | 20 | import org.thingsboard.server.common.data.BaseData; |
21 | -import org.thingsboard.server.common.data.SearchTextBased; | ||
22 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
23 | 21 | ||
22 | +import java.util.Collections; | ||
24 | import java.util.List; | 23 | import java.util.List; |
25 | -import java.util.UUID; | ||
26 | 24 | ||
27 | -public class TimePageData<T extends BaseData<? extends UUIDBased>> { | 25 | +public class PageData<T> { |
28 | 26 | ||
29 | private final List<T> data; | 27 | private final List<T> data; |
30 | - private final TimePageLink nextPageLink; | 28 | + private final int totalPages; |
29 | + private final long totalElements; | ||
31 | private final boolean hasNext; | 30 | private final boolean hasNext; |
32 | 31 | ||
33 | - public TimePageData(List<T> data, TimePageLink pageLink) { | ||
34 | - super(); | ||
35 | - this.data = data; | ||
36 | - int limit = pageLink.getLimit(); | ||
37 | - if (data != null && data.size() == limit) { | ||
38 | - int index = data.size() - 1; | ||
39 | - UUID idOffset = data.get(index).getId().getId(); | ||
40 | - nextPageLink = new TimePageLink(limit, pageLink.getStartTime(), pageLink.getEndTime(), pageLink.isAscOrder(), idOffset); | ||
41 | - hasNext = true; | ||
42 | - } else { | ||
43 | - nextPageLink = null; | ||
44 | - hasNext = false; | ||
45 | - } | 32 | + public PageData() { |
33 | + this(Collections.emptyList(), 0, 0, false); | ||
46 | } | 34 | } |
47 | 35 | ||
48 | @JsonCreator | 36 | @JsonCreator |
49 | - public TimePageData(@JsonProperty("data") List<T> data, | ||
50 | - @JsonProperty("nextPageLink") TimePageLink nextPageLink, | ||
51 | - @JsonProperty("hasNext") boolean hasNext) { | 37 | + public PageData(@JsonProperty("data") List<T> data, |
38 | + @JsonProperty("totalPages") int totalPages, | ||
39 | + @JsonProperty("totalElements") long totalElements, | ||
40 | + @JsonProperty("hasNext") boolean hasNext) { | ||
52 | this.data = data; | 41 | this.data = data; |
53 | - this.nextPageLink = nextPageLink; | 42 | + this.totalPages = totalPages; |
43 | + this.totalElements = totalElements; | ||
54 | this.hasNext = hasNext; | 44 | this.hasNext = hasNext; |
55 | } | 45 | } |
56 | 46 | ||
@@ -58,13 +48,17 @@ public class TimePageData<T extends BaseData<? extends UUIDBased>> { | @@ -58,13 +48,17 @@ public class TimePageData<T extends BaseData<? extends UUIDBased>> { | ||
58 | return data; | 48 | return data; |
59 | } | 49 | } |
60 | 50 | ||
51 | + public int getTotalPages() { | ||
52 | + return totalPages; | ||
53 | + } | ||
54 | + | ||
55 | + public long getTotalElements() { | ||
56 | + return totalElements; | ||
57 | + } | ||
58 | + | ||
61 | @JsonProperty("hasNext") | 59 | @JsonProperty("hasNext") |
62 | public boolean hasNext() { | 60 | public boolean hasNext() { |
63 | return hasNext; | 61 | return hasNext; |
64 | } | 62 | } |
65 | 63 | ||
66 | - public TimePageLink getNextPageLink() { | ||
67 | - return nextPageLink; | ||
68 | - } | ||
69 | - | ||
70 | } | 64 | } |
@@ -19,11 +19,12 @@ import java.util.Iterator; | @@ -19,11 +19,12 @@ import java.util.Iterator; | ||
19 | import java.util.List; | 19 | import java.util.List; |
20 | import java.util.NoSuchElementException; | 20 | import java.util.NoSuchElementException; |
21 | 21 | ||
22 | +import org.thingsboard.server.common.data.BaseData; | ||
22 | import org.thingsboard.server.common.data.SearchTextBased; | 23 | import org.thingsboard.server.common.data.SearchTextBased; |
23 | import org.thingsboard.server.common.data.id.EntityId; | 24 | import org.thingsboard.server.common.data.id.EntityId; |
24 | import org.thingsboard.server.common.data.id.UUIDBased; | 25 | import org.thingsboard.server.common.data.id.UUIDBased; |
25 | 26 | ||
26 | -public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> implements Iterable<T>, Iterator<T> { | 27 | +public class PageDataIterable<T> implements Iterable<T>, Iterator<T> { |
27 | 28 | ||
28 | private final FetchFunction<T> function; | 29 | private final FetchFunction<T> function; |
29 | private final int fetchSize; | 30 | private final int fetchSize; |
@@ -31,7 +32,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -31,7 +32,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
31 | private List<T> currentItems; | 32 | private List<T> currentItems; |
32 | private int currentIdx; | 33 | private int currentIdx; |
33 | private boolean hasNextPack; | 34 | private boolean hasNextPack; |
34 | - private TextPageLink nextPackLink; | 35 | + private PageLink nextPackLink; |
35 | private boolean initialized; | 36 | private boolean initialized; |
36 | 37 | ||
37 | public PageDataIterable(FetchFunction<T> function, int fetchSize) { | 38 | public PageDataIterable(FetchFunction<T> function, int fetchSize) { |
@@ -48,7 +49,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -48,7 +49,7 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
48 | @Override | 49 | @Override |
49 | public boolean hasNext() { | 50 | public boolean hasNext() { |
50 | if(!initialized){ | 51 | if(!initialized){ |
51 | - fetch(new TextPageLink(fetchSize)); | 52 | + fetch(new PageLink(fetchSize)); |
52 | initialized = true; | 53 | initialized = true; |
53 | } | 54 | } |
54 | if(currentIdx == currentItems.size()){ | 55 | if(currentIdx == currentItems.size()){ |
@@ -59,12 +60,12 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -59,12 +60,12 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
59 | return currentIdx < currentItems.size(); | 60 | return currentIdx < currentItems.size(); |
60 | } | 61 | } |
61 | 62 | ||
62 | - private void fetch(TextPageLink link) { | ||
63 | - TextPageData<T> pageData = function.fetch(link); | 63 | + private void fetch(PageLink link) { |
64 | + PageData<T> pageData = function.fetch(link); | ||
64 | currentIdx = 0; | 65 | currentIdx = 0; |
65 | currentItems = pageData.getData(); | 66 | currentItems = pageData.getData(); |
66 | hasNextPack = pageData.hasNext(); | 67 | hasNextPack = pageData.hasNext(); |
67 | - nextPackLink = pageData.getNextPageLink(); | 68 | + nextPackLink = link.nextPageLink(); |
68 | } | 69 | } |
69 | 70 | ||
70 | @Override | 71 | @Override |
@@ -75,9 +76,9 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | @@ -75,9 +76,9 @@ public class PageDataIterable<T extends SearchTextBased<? extends UUIDBased>> im | ||
75 | return currentItems.get(currentIdx++); | 76 | return currentItems.get(currentIdx++); |
76 | } | 77 | } |
77 | 78 | ||
78 | - public static interface FetchFunction<T extends SearchTextBased<? extends UUIDBased>> { | 79 | + public static interface FetchFunction<T> { |
79 | 80 | ||
80 | - TextPageData<T> fetch(TextPageLink link); | 81 | + PageData<T> fetch(PageLink link); |
81 | 82 | ||
82 | } | 83 | } |
83 | } | 84 | } |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.page; | ||
17 | + | ||
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | +import lombok.Data; | ||
20 | + | ||
21 | +@Data | ||
22 | +public class PageLink { | ||
23 | + | ||
24 | + private final String textSearch; | ||
25 | + private final int pageSize; | ||
26 | + private final int page; | ||
27 | + private final SortOrder sortOrder; | ||
28 | + | ||
29 | + public PageLink(PageLink pageLink) { | ||
30 | + this.pageSize = pageLink.getPageSize(); | ||
31 | + this.page = pageLink.getPage(); | ||
32 | + this.textSearch = pageLink.getTextSearch(); | ||
33 | + this.sortOrder = pageLink.getSortOrder(); | ||
34 | + } | ||
35 | + | ||
36 | + public PageLink(int pageSize) { | ||
37 | + this(pageSize, 0); | ||
38 | + } | ||
39 | + | ||
40 | + public PageLink(int pageSize, int page) { | ||
41 | + this(pageSize, page, null, null); | ||
42 | + } | ||
43 | + | ||
44 | + public PageLink(int pageSize, int page, String textSearch) { | ||
45 | + this(pageSize, page, textSearch, null); | ||
46 | + } | ||
47 | + | ||
48 | + public PageLink(int pageSize, int page, String textSearch, SortOrder sortOrder) { | ||
49 | + this.pageSize = pageSize; | ||
50 | + this.page = page; | ||
51 | + this.textSearch = textSearch; | ||
52 | + this.sortOrder = sortOrder; | ||
53 | + } | ||
54 | + | ||
55 | + @JsonIgnore | ||
56 | + public PageLink nextPageLink() { | ||
57 | + return new PageLink(this.pageSize, this.page+1, this.textSearch, this.sortOrder); | ||
58 | + } | ||
59 | + | ||
60 | +} |
1 | +/** | ||
2 | + * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.thingsboard.server.common.data.page; | ||
17 | + | ||
18 | +import lombok.Data; | ||
19 | + | ||
20 | +@Data | ||
21 | +public class SortOrder { | ||
22 | + | ||
23 | + private final String property; | ||
24 | + private final Direction direction; | ||
25 | + | ||
26 | + public SortOrder(String property) { | ||
27 | + this(property, Direction.ASC); | ||
28 | + } | ||
29 | + | ||
30 | + public SortOrder(String property, Direction direction) { | ||
31 | + this.property = property; | ||
32 | + this.direction = direction; | ||
33 | + } | ||
34 | + | ||
35 | + public static enum Direction { | ||
36 | + ASC, DESC | ||
37 | + } | ||
38 | + | ||
39 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/page/TextPageData.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.common.data.page; | ||
17 | - | ||
18 | -import java.util.List; | ||
19 | -import java.util.UUID; | ||
20 | - | ||
21 | -import org.thingsboard.server.common.data.SearchTextBased; | ||
22 | -import org.thingsboard.server.common.data.id.UUIDBased; | ||
23 | - | ||
24 | -import com.fasterxml.jackson.annotation.JsonCreator; | ||
25 | -import com.fasterxml.jackson.annotation.JsonProperty; | ||
26 | - | ||
27 | -public class TextPageData<T extends SearchTextBased<? extends UUIDBased>> { | ||
28 | - | ||
29 | - private final List<T> data; | ||
30 | - private final TextPageLink nextPageLink; | ||
31 | - private final boolean hasNext; | ||
32 | - | ||
33 | - public TextPageData(List<T> data, TextPageLink pageLink) { | ||
34 | - super(); | ||
35 | - this.data = data; | ||
36 | - int limit = pageLink.getLimit(); | ||
37 | - if (data != null && data.size() == limit) { | ||
38 | - int index = data.size()-1; | ||
39 | - UUID idOffset = data.get(index).getId().getId(); | ||
40 | - String textOffset = data.get(index).getSearchText(); | ||
41 | - nextPageLink = new TextPageLink(limit, pageLink.getTextSearch(), idOffset, textOffset); | ||
42 | - hasNext = true; | ||
43 | - } else { | ||
44 | - nextPageLink = null; | ||
45 | - hasNext = false; | ||
46 | - } | ||
47 | - } | ||
48 | - | ||
49 | - @JsonCreator | ||
50 | - public TextPageData(@JsonProperty("data") List<T> data, | ||
51 | - @JsonProperty("nextPageLink") TextPageLink nextPageLink, | ||
52 | - @JsonProperty("hasNext") boolean hasNext) { | ||
53 | - this.data = data; | ||
54 | - this.nextPageLink = nextPageLink; | ||
55 | - this.hasNext = hasNext; | ||
56 | - } | ||
57 | - | ||
58 | - public List<T> getData() { | ||
59 | - return data; | ||
60 | - } | ||
61 | - | ||
62 | - @JsonProperty("hasNext") | ||
63 | - public boolean hasNext() { | ||
64 | - return hasNext; | ||
65 | - } | ||
66 | - | ||
67 | - public TextPageLink getNextPageLink() { | ||
68 | - return nextPageLink; | ||
69 | - } | ||
70 | - | ||
71 | -} |
common/data/src/main/java/org/thingsboard/server/common/data/page/TextPageLink.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.common.data.page; | ||
17 | - | ||
18 | -import com.fasterxml.jackson.annotation.JsonCreator; | ||
19 | -import com.fasterxml.jackson.annotation.JsonProperty; | ||
20 | -import lombok.Getter; | ||
21 | -import lombok.ToString; | ||
22 | - | ||
23 | -import java.io.Serializable; | ||
24 | -import java.util.Arrays; | ||
25 | -import java.util.UUID; | ||
26 | - | ||
27 | -@ToString | ||
28 | -public class TextPageLink extends BasePageLink implements Serializable { | ||
29 | - | ||
30 | - private static final long serialVersionUID = -4189954843653250480L; | ||
31 | - | ||
32 | - @Getter private final String textSearch; | ||
33 | - @Getter private final String textSearchBound; | ||
34 | - @Getter private final String textOffset; | ||
35 | - | ||
36 | - public TextPageLink(int limit) { | ||
37 | - this(limit, null, null, null); | ||
38 | - } | ||
39 | - | ||
40 | - public TextPageLink(int limit, String textSearch) { | ||
41 | - this(limit, textSearch, null, null); | ||
42 | - } | ||
43 | - | ||
44 | - public TextPageLink(int limit, String textSearch, UUID idOffset, String textOffset) { | ||
45 | - super(limit, idOffset); | ||
46 | - this.textSearch = textSearch != null ? textSearch.toLowerCase() : null; | ||
47 | - this.textSearchBound = nextSequence(this.textSearch); | ||
48 | - this.textOffset = textOffset != null ? textOffset.toLowerCase() : null; | ||
49 | - } | ||
50 | - | ||
51 | - @JsonCreator | ||
52 | - public TextPageLink(@JsonProperty("limit") int limit, | ||
53 | - @JsonProperty("textSearch") String textSearch, | ||
54 | - @JsonProperty("textSearchBound") String textSearchBound, | ||
55 | - @JsonProperty("textOffset") String textOffset, | ||
56 | - @JsonProperty("idOffset") UUID idOffset) { | ||
57 | - super(limit, idOffset); | ||
58 | - this.textSearch = textSearch; | ||
59 | - this.textSearchBound = textSearchBound; | ||
60 | - this.textOffset = textOffset; | ||
61 | - this.idOffset = idOffset; | ||
62 | - } | ||
63 | - | ||
64 | - private static String nextSequence(String input) { | ||
65 | - if (input != null && input.length() > 0) { | ||
66 | - char[] chars = input.toCharArray(); | ||
67 | - int i = chars.length - 1; | ||
68 | - while (i >= 0 && ++chars[i--] == Character.MIN_VALUE) ; | ||
69 | - if (i == -1 && (chars.length == 0 || chars[0] == Character.MIN_VALUE)) { | ||
70 | - char buf[] = Arrays.copyOf(input.toCharArray(), input.length() + 1); | ||
71 | - buf[buf.length - 1] = Character.MIN_VALUE; | ||
72 | - return new String(buf); | ||
73 | - } | ||
74 | - return new String(chars); | ||
75 | - } else { | ||
76 | - return null; | ||
77 | - } | ||
78 | - } | ||
79 | - | ||
80 | -} |
@@ -16,7 +16,9 @@ | @@ -16,7 +16,9 @@ | ||
16 | package org.thingsboard.server.common.data.page; | 16 | package org.thingsboard.server.common.data.page; |
17 | 17 | ||
18 | import com.fasterxml.jackson.annotation.JsonCreator; | 18 | import com.fasterxml.jackson.annotation.JsonCreator; |
19 | +import com.fasterxml.jackson.annotation.JsonIgnore; | ||
19 | import com.fasterxml.jackson.annotation.JsonProperty; | 20 | import com.fasterxml.jackson.annotation.JsonProperty; |
21 | +import lombok.Data; | ||
20 | import lombok.Getter; | 22 | import lombok.Getter; |
21 | import lombok.ToString; | 23 | import lombok.ToString; |
22 | 24 | ||
@@ -24,40 +26,43 @@ import java.io.Serializable; | @@ -24,40 +26,43 @@ import java.io.Serializable; | ||
24 | import java.util.Arrays; | 26 | import java.util.Arrays; |
25 | import java.util.UUID; | 27 | import java.util.UUID; |
26 | 28 | ||
27 | -@ToString | ||
28 | -public class TimePageLink extends BasePageLink implements Serializable { | 29 | +@Data |
30 | +public class TimePageLink extends PageLink { | ||
29 | 31 | ||
30 | - private static final long serialVersionUID = -4189954843653250480L; | 32 | + private final Long startTime; |
33 | + private final Long endTime; | ||
31 | 34 | ||
32 | - @Getter private final Long startTime; | ||
33 | - @Getter private final Long endTime; | ||
34 | - @Getter private final boolean ascOrder; | 35 | + public TimePageLink(PageLink pageLink, Long startTime, Long endTime) { |
36 | + super(pageLink); | ||
37 | + this.startTime = startTime; | ||
38 | + this.endTime = endTime; | ||
39 | + } | ||
35 | 40 | ||
36 | - public TimePageLink(int limit) { | ||
37 | - this(limit, null, null, false, null); | 41 | + public TimePageLink(int pageSize) { |
42 | + this(pageSize, 0); | ||
38 | } | 43 | } |
39 | 44 | ||
40 | - public TimePageLink(int limit, Long startTime) { | ||
41 | - this(limit, startTime, null, false, null); | 45 | + public TimePageLink(int pageSize, int page) { |
46 | + this(pageSize, page, null); | ||
42 | } | 47 | } |
43 | 48 | ||
44 | - public TimePageLink(int limit, Long startTime, Long endTime) { | ||
45 | - this(limit, startTime, endTime, false, null); | 49 | + public TimePageLink(int pageSize, int page, String textSearch) { |
50 | + this(pageSize, page, textSearch, null, null, null); | ||
46 | } | 51 | } |
47 | 52 | ||
48 | - public TimePageLink(int limit, Long startTime, Long endTime, boolean ascOrder) { | ||
49 | - this(limit, startTime, endTime, ascOrder, null); | 53 | + public TimePageLink(int pageSize, int page, String textSearch, SortOrder sortOrder) { |
54 | + this(pageSize, page, textSearch, sortOrder, null, null); | ||
50 | } | 55 | } |
51 | 56 | ||
52 | - @JsonCreator | ||
53 | - public TimePageLink(@JsonProperty("limit") int limit, | ||
54 | - @JsonProperty("startTime") Long startTime, | ||
55 | - @JsonProperty("endTime") Long endTime, | ||
56 | - @JsonProperty("ascOrder") boolean ascOrder, | ||
57 | - @JsonProperty("idOffset") UUID idOffset) { | ||
58 | - super(limit, idOffset); | 57 | + public TimePageLink(int pageSize, int page, String textSearch, SortOrder sortOrder, Long startTime, Long endTime) { |
58 | + super(pageSize, page, textSearch, sortOrder); | ||
59 | this.startTime = startTime; | 59 | this.startTime = startTime; |
60 | this.endTime = endTime; | 60 | this.endTime = endTime; |
61 | - this.ascOrder = ascOrder; | 61 | + } |
62 | + | ||
63 | + @JsonIgnore | ||
64 | + public TimePageLink nextPageLink() { | ||
65 | + return new TimePageLink(this.getPageSize(), this.getPage()+1, this.getTextSearch(), this.getSortOrder(), | ||
66 | + this.startTime, this.endTime); | ||
62 | } | 67 | } |
63 | } | 68 | } |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>common</artifactId> | 26 | <artifactId>common</artifactId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard.common</groupId> | 22 | <groupId>org.thingsboard.common</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>transport</artifactId> | 24 | <artifactId>transport</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common.transport</groupId> | 26 | <groupId>org.thingsboard.common.transport</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>common</artifactId> | 24 | <artifactId>common</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <groupId>org.thingsboard.common</groupId> | 26 | <groupId>org.thingsboard.common</groupId> |
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | <modelVersion>4.0.0</modelVersion> | 20 | <modelVersion>4.0.0</modelVersion> |
21 | <parent> | 21 | <parent> |
22 | <groupId>org.thingsboard</groupId> | 22 | <groupId>org.thingsboard</groupId> |
23 | - <version>2.5.0-SNAPSHOT</version> | 23 | + <version>3.0.0-SNAPSHOT</version> |
24 | <artifactId>thingsboard</artifactId> | 24 | <artifactId>thingsboard</artifactId> |
25 | </parent> | 25 | </parent> |
26 | <artifactId>dao</artifactId> | 26 | <artifactId>dao</artifactId> |
@@ -15,7 +15,16 @@ | @@ -15,7 +15,16 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao; | 16 | package org.thingsboard.server.dao; |
17 | 17 | ||
18 | +import com.datastax.driver.core.utils.UUIDs; | ||
19 | +import org.springframework.data.domain.Page; | ||
20 | +import org.springframework.data.domain.PageRequest; | ||
21 | +import org.springframework.data.domain.Pageable; | ||
22 | +import org.springframework.data.domain.Sort; | ||
23 | +import org.thingsboard.server.common.data.UUIDConverter; | ||
18 | import org.thingsboard.server.common.data.id.UUIDBased; | 24 | import org.thingsboard.server.common.data.id.UUIDBased; |
25 | +import org.thingsboard.server.common.data.page.PageData; | ||
26 | +import org.thingsboard.server.common.data.page.PageLink; | ||
27 | +import org.thingsboard.server.common.data.page.SortOrder; | ||
19 | import org.thingsboard.server.dao.model.ToData; | 28 | import org.thingsboard.server.dao.model.ToData; |
20 | 29 | ||
21 | import java.util.*; | 30 | import java.util.*; |
@@ -25,6 +34,56 @@ public abstract class DaoUtil { | @@ -25,6 +34,56 @@ public abstract class DaoUtil { | ||
25 | private DaoUtil() { | 34 | private DaoUtil() { |
26 | } | 35 | } |
27 | 36 | ||
37 | + public static <T> PageData<T> toPageData(Page<? extends ToData<T>> page) { | ||
38 | + List<T> data = convertDataList(page.getContent()); | ||
39 | + return new PageData(data, page.getTotalPages(), page.getTotalElements(), page.hasNext()); | ||
40 | + } | ||
41 | + | ||
42 | + public static Pageable toPageable(PageLink pageLink) { | ||
43 | + return toPageable(pageLink, Collections.emptyMap()); | ||
44 | + } | ||
45 | + | ||
46 | + public static Pageable toPageable(PageLink pageLink, Map<String,String> columnMap) { | ||
47 | + return PageRequest.of(pageLink.getPage(), pageLink.getPageSize(), toSort(pageLink.getSortOrder(), columnMap)); | ||
48 | + } | ||
49 | + | ||
50 | + public static String startTimeToId(Long startTime) { | ||
51 | + if (startTime != null) { | ||
52 | + UUID startOf = UUIDs.startOf(startTime); | ||
53 | + return UUIDConverter.fromTimeUUID(startOf); | ||
54 | + } else { | ||
55 | + return null; | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + public static String endTimeToId(Long endTime) { | ||
60 | + if (endTime != null) { | ||
61 | + UUID endOf = UUIDs.endOf(endTime); | ||
62 | + return UUIDConverter.fromTimeUUID(endOf); | ||
63 | + } else { | ||
64 | + return null; | ||
65 | + } | ||
66 | + } | ||
67 | + | ||
68 | + public static Sort toSort(SortOrder sortOrder) { | ||
69 | + return toSort(sortOrder, Collections.emptyMap()); | ||
70 | + } | ||
71 | + | ||
72 | + public static Sort toSort(SortOrder sortOrder, Map<String,String> columnMap) { | ||
73 | + if (sortOrder == null) { | ||
74 | + return Sort.unsorted(); | ||
75 | + } else { | ||
76 | + String property = sortOrder.getProperty(); | ||
77 | + if (columnMap.containsKey(property)) { | ||
78 | + property = columnMap.get(property); | ||
79 | + } | ||
80 | + if (property.equals("createdTime")) { | ||
81 | + property = "id"; | ||
82 | + } | ||
83 | + return Sort.by(Sort.Direction.fromString(sortOrder.getDirection().name()), property); | ||
84 | + } | ||
85 | + } | ||
86 | + | ||
28 | public static <T> List<T> convertDataList(Collection<? extends ToData<T>> toDataList) { | 87 | public static <T> List<T> convertDataList(Collection<? extends ToData<T>> toDataList) { |
29 | List<T> list = Collections.emptyList(); | 88 | List<T> list = Collections.emptyList(); |
30 | if (toDataList != null && !toDataList.isEmpty()) { | 89 | if (toDataList != null && !toDataList.isEmpty()) { |
@@ -21,6 +21,7 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo; | @@ -21,6 +21,7 @@ import org.thingsboard.server.common.data.alarm.AlarmInfo; | ||
21 | import org.thingsboard.server.common.data.alarm.AlarmQuery; | 21 | import org.thingsboard.server.common.data.alarm.AlarmQuery; |
22 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | import org.thingsboard.server.common.data.id.TenantId; | 23 | import org.thingsboard.server.common.data.id.TenantId; |
24 | +import org.thingsboard.server.common.data.page.PageData; | ||
24 | import org.thingsboard.server.dao.Dao; | 25 | import org.thingsboard.server.dao.Dao; |
25 | 26 | ||
26 | import java.util.List; | 27 | import java.util.List; |
@@ -39,5 +40,5 @@ public interface AlarmDao extends Dao<Alarm> { | @@ -39,5 +40,5 @@ public interface AlarmDao extends Dao<Alarm> { | ||
39 | 40 | ||
40 | Alarm save(TenantId tenantId, Alarm alarm); | 41 | Alarm save(TenantId tenantId, Alarm alarm); |
41 | 42 | ||
42 | - ListenableFuture<List<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query); | 43 | + PageData<AlarmInfo> findAlarms(TenantId tenantId, AlarmQuery query); |
43 | } | 44 | } |
@@ -36,7 +36,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; | @@ -36,7 +36,7 @@ import org.thingsboard.server.common.data.alarm.AlarmSeverity; | ||
36 | import org.thingsboard.server.common.data.alarm.AlarmStatus; | 36 | import org.thingsboard.server.common.data.alarm.AlarmStatus; |
37 | import org.thingsboard.server.common.data.id.EntityId; | 37 | import org.thingsboard.server.common.data.id.EntityId; |
38 | import org.thingsboard.server.common.data.id.TenantId; | 38 | import org.thingsboard.server.common.data.id.TenantId; |
39 | -import org.thingsboard.server.common.data.page.TimePageData; | 39 | +import org.thingsboard.server.common.data.page.PageData; |
40 | import org.thingsboard.server.common.data.page.TimePageLink; | 40 | import org.thingsboard.server.common.data.page.TimePageLink; |
41 | import org.thingsboard.server.common.data.relation.EntityRelation; | 41 | import org.thingsboard.server.common.data.relation.EntityRelation; |
42 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; | 42 | import org.thingsboard.server.common.data.relation.EntityRelationsQuery; |
@@ -270,32 +270,26 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -270,32 +270,26 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
270 | } | 270 | } |
271 | 271 | ||
272 | @Override | 272 | @Override |
273 | - public ListenableFuture<TimePageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { | ||
274 | - ListenableFuture<List<AlarmInfo>> alarms = alarmDao.findAlarms(tenantId, query); | 273 | + public ListenableFuture<PageData<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { |
274 | + PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); | ||
275 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { | 275 | if (query.getFetchOriginator() != null && query.getFetchOriginator().booleanValue()) { |
276 | - alarms = Futures.transformAsync(alarms, input -> { | ||
277 | - List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size()); | ||
278 | - for (AlarmInfo alarmInfo : input) { | ||
279 | - alarmFutures.add(Futures.transform( | ||
280 | - entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
281 | - if (originatorName == null) { | ||
282 | - originatorName = "Deleted"; | ||
283 | - } | ||
284 | - alarmInfo.setOriginatorName(originatorName); | ||
285 | - return alarmInfo; | 276 | + List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(alarms.getData().size()); |
277 | + for (AlarmInfo alarmInfo : alarms.getData()) { | ||
278 | + alarmFutures.add(Futures.transform( | ||
279 | + entityService.fetchEntityNameAsync(tenantId, alarmInfo.getOriginator()), originatorName -> { | ||
280 | + if (originatorName == null) { | ||
281 | + originatorName = "Deleted"; | ||
286 | } | 282 | } |
287 | - )); | ||
288 | - } | ||
289 | - return Futures.successfulAsList(alarmFutures); | 283 | + alarmInfo.setOriginatorName(originatorName); |
284 | + return alarmInfo; | ||
285 | + } | ||
286 | + )); | ||
287 | + } | ||
288 | + return Futures.transform(Futures.successfulAsList(alarmFutures), alarmInfos -> { | ||
289 | + return new PageData(alarmInfos, alarms.getTotalPages(), alarms.getTotalElements(), alarms.hasNext()); | ||
290 | }); | 290 | }); |
291 | } | 291 | } |
292 | - return Futures.transform(alarms, new Function<List<AlarmInfo>, TimePageData<AlarmInfo>>() { | ||
293 | - @Nullable | ||
294 | - @Override | ||
295 | - public TimePageData<AlarmInfo> apply(@Nullable List<AlarmInfo> alarms) { | ||
296 | - return new TimePageData<>(alarms, query.getPageLink()); | ||
297 | - } | ||
298 | - }); | 292 | + return Futures.immediateFuture(alarms); |
299 | } | 293 | } |
300 | 294 | ||
301 | @Override | 295 | @Override |
@@ -307,19 +301,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | @@ -307,19 +301,11 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ | ||
307 | AlarmQuery query; | 301 | AlarmQuery query; |
308 | while (hasNext && AlarmSeverity.CRITICAL != highestSeverity) { | 302 | while (hasNext && AlarmSeverity.CRITICAL != highestSeverity) { |
309 | query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false); | 303 | query = new AlarmQuery(entityId, nextPageLink, alarmSearchStatus, alarmStatus, false); |
310 | - List<AlarmInfo> alarms; | ||
311 | - try { | ||
312 | - alarms = alarmDao.findAlarms(tenantId, query).get(); | ||
313 | - } catch (ExecutionException | InterruptedException e) { | ||
314 | - log.warn("Failed to find highest alarm severity. EntityId: [{}], AlarmSearchStatus: [{}], AlarmStatus: [{}]", | ||
315 | - entityId, alarmSearchStatus, alarmStatus); | ||
316 | - throw new RuntimeException(e); | ||
317 | - } | ||
318 | - hasNext = alarms.size() == nextPageLink.getLimit(); | ||
319 | - if (hasNext) { | ||
320 | - nextPageLink = new TimePageData<>(alarms, nextPageLink).getNextPageLink(); | 304 | + PageData<AlarmInfo> alarms = alarmDao.findAlarms(tenantId, query); |
305 | + if (alarms.hasNext()) { | ||
306 | + nextPageLink = nextPageLink.nextPageLink(); | ||
321 | } | 307 | } |
322 | - AlarmSeverity severity = detectHighestSeverity(alarms); | 308 | + AlarmSeverity severity = detectHighestSeverity(alarms.getData()); |
323 | if (severity == null) { | 309 | if (severity == null) { |
324 | continue; | 310 | continue; |
325 | } | 311 | } |
dao/src/main/java/org/thingsboard/server/dao/alarm/CassandraAlarmDao.java
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2020 The Thingsboard Authors | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | -package org.thingsboard.server.dao.alarm; | ||
17 | - | ||
18 | -import com.datastax.driver.core.Statement; | ||
19 | -import com.datastax.driver.core.querybuilder.QueryBuilder; | ||
20 | -import com.datastax.driver.core.querybuilder.Select; | ||
21 | -import com.google.common.util.concurrent.Futures; | ||
22 | -import com.google.common.util.concurrent.ListenableFuture; | ||
23 | -import lombok.extern.slf4j.Slf4j; | ||
24 | -import org.springframework.beans.factory.annotation.Autowired; | ||
25 | -import org.springframework.stereotype.Component; | ||
26 | -import org.thingsboard.server.common.data.EntityType; | ||
27 | -import org.thingsboard.server.common.data.alarm.Alarm; | ||
28 | -import org.thingsboard.server.common.data.alarm.AlarmInfo; | ||
29 | -import org.thingsboard.server.common.data.alarm.AlarmQuery; | ||
30 | -import org.thingsboard.server.common.data.alarm.AlarmSearchStatus; | ||
31 | -import org.thingsboard.server.common.data.id.EntityId; | ||
32 | -import org.thingsboard.server.common.data.id.TenantId; | ||
33 | -import org.thingsboard.server.common.data.relation.EntityRelation; | ||
34 | -import org.thingsboard.server.common.data.relation.RelationTypeGroup; | ||
35 | -import org.thingsboard.server.dao.model.ModelConstants; | ||
36 | -import org.thingsboard.server.dao.model.nosql.AlarmEntity; | ||
37 | -import org.thingsboard.server.dao.nosql.CassandraAbstractModelDao; | ||
38 | -import org.thingsboard.server.dao.relation.RelationDao; | ||
39 | -import org.thingsboard.server.dao.util.NoSqlDao; | ||
40 | - | ||
41 | -import java.util.ArrayList; | ||
42 | -import java.util.List; | ||
43 | -import java.util.UUID; | ||
44 | - | ||
45 | -import static com.datastax.driver.core.querybuilder.QueryBuilder.eq; | ||
46 | -import static com.datastax.driver.core.querybuilder.QueryBuilder.select; | ||
47 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_BY_ID_VIEW_NAME; | ||
48 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_COLUMN_FAMILY_NAME; | ||
49 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_ID_PROPERTY; | ||
50 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_ORIGINATOR_TYPE_PROPERTY; | ||
51 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_TENANT_ID_PROPERTY; | ||
52 | -import static org.thingsboard.server.dao.model.ModelConstants.ALARM_TYPE_PROPERTY; | ||
53 | - | ||
54 | -@Component | ||
55 | -@Slf4j | ||
56 | -@NoSqlDao | ||
57 | -public class CassandraAlarmDao extends CassandraAbstractModelDao<AlarmEntity, Alarm> implements AlarmDao { | ||
58 | - | ||
59 | - @Autowired | ||
60 | - private RelationDao relationDao; | ||
61 | - | ||
62 | - @Override | ||
63 | - protected Class<AlarmEntity> getColumnFamilyClass() { | ||
64 | - return AlarmEntity.class; | ||
65 | - } | ||
66 | - | ||
67 | - @Override | ||
68 | - protected String getColumnFamilyName() { | ||
69 | - return ALARM_COLUMN_FAMILY_NAME; | ||
70 | - } | ||
71 | - | ||
72 | - protected boolean isDeleteOnSave() { | ||
73 | - return false; | ||
74 | - } | ||
75 | - | ||
76 | - @Override | ||
77 | - public Alarm save(TenantId tenantId, Alarm alarm) { | ||
78 | - log.debug("Save asset [{}] ", alarm); | ||
79 | - return super.save(tenantId, alarm); | ||
80 | - } | ||
81 | - | ||
82 | - @Override | ||
83 | - public Boolean deleteAlarm(TenantId tenantId, Alarm alarm) { | ||
84 | - Statement delete = QueryBuilder.delete().all().from(getColumnFamilyName()).where(eq(ModelConstants.ID_PROPERTY, alarm.getId().getId())) | ||
85 | - .and(eq(ALARM_TENANT_ID_PROPERTY, tenantId.getId())) | ||
86 | - .and(eq(ALARM_ORIGINATOR_ID_PROPERTY, alarm.getOriginator().getId())) | ||
87 | - .and(eq(ALARM_ORIGINATOR_TYPE_PROPERTY, alarm.getOriginator().getEntityType())) | ||
88 | - .and(eq(ALARM_TYPE_PROPERTY, alarm.getType())); | ||
89 | - log.debug("Remove request: {}", delete.toString()); | ||
90 | - return executeWrite(tenantId, delete).wasApplied(); | ||
91 | - } | ||
92 | - | ||
93 | - @Override | ||
94 | - public ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type) { | ||
95 | - Select select = select().from(ALARM_COLUMN_FAMILY_NAME); | ||
96 | - Select.Where query = select.where(); | ||
97 | - query.and(eq(ALARM_TENANT_ID_PROPERTY, tenantId.getId())); | ||
98 | - query.and(eq(ALARM_ORIGINATOR_ID_PROPERTY, originator.getId())); | ||
99 | - query.and(eq(ALARM_ORIGINATOR_TYPE_PROPERTY, originator.getEntityType())); | ||
100 | - query.and(eq(ALARM_TYPE_PROPERTY, type)); | ||
101 | - query.limit(1); | ||
102 | - query.orderBy(QueryBuilder.asc(ModelConstants.ALARM_TYPE_PROPERTY), QueryBuilder.desc(ModelConstants.ID_PROPERTY)); | ||
103 | - return findOneByStatementAsync(tenantId, query); | ||
104 | - } | ||
105 | - | ||
106 | - @Override | ||
107 | - public ListenableFuture<List<AlarmInfo>> findAlarms(TenantId tenantId, AlarmQuery query) { | ||
108 | - log.trace("Try to find alarms by entity [{}], searchStatus [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getSearchStatus(), query.getStatus(), query.getPageLink()); | ||
109 | - EntityId affectedEntity = query.getAffectedEntityId(); | ||
110 | - String searchStatusName; | ||
111 | - if (query.getSearchStatus() == null && query.getStatus() == null) { | ||
112 | - searchStatusName = AlarmSearchStatus.ANY.name(); | ||
113 | - } else if (query.getSearchStatus() != null) { | ||
114 | - searchStatusName = query.getSearchStatus().name(); | ||
115 | - } else { | ||
116 | - searchStatusName = query.getStatus().name(); | ||
117 | - } | ||
118 | - String relationType = BaseAlarmService.ALARM_RELATION_PREFIX + searchStatusName; | ||
119 | - ListenableFuture<List<EntityRelation>> relations = relationDao.findRelations(tenantId, affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); | ||
120 | - return Futures.transformAsync(relations, input -> { | ||
121 | - List<ListenableFuture<AlarmInfo>> alarmFutures = new ArrayList<>(input.size()); | ||
122 | - for (EntityRelation relation : input) { | ||
123 | - alarmFutures.add(Futures.transform( | ||
124 | - findAlarmByIdAsync(tenantId, relation.getTo().getId()), | ||
125 | - AlarmInfo::new)); | ||
126 | - } | ||
127 | - return Futures.successfulAsList(alarmFutures); | ||
128 | - }); | ||
129 | - } | ||
130 | - | ||
131 | - @Override | ||
132 | - public ListenableFuture<Alarm> findAlarmByIdAsync(TenantId tenantId, UUID key) { | ||
133 | - log.debug("Get alarm by id {}", key); | ||
134 | - Select.Where query = select().from(ALARM_BY_ID_VIEW_NAME).where(eq(ModelConstants.ID_PROPERTY, key)); | ||
135 | - query.limit(1); | ||
136 | - log.trace("Execute query {}", query); | ||
137 | - return findOneByStatementAsync(tenantId, query); | ||
138 | - } | ||
139 | -} |