Commit e73690f60d1ce85f13b0934afdb910b82d2dbd6b

Authored by Vladyslav_Prykhodko
Committed by Andrew Shvayka
1 parent 1e5be4d8

Add new demo dashboard software; Updated demo dashboard firmware

... ... @@ -223,6 +223,27 @@
223 223 "funcBody": null,
224 224 "usePostProcessing": null,
225 225 "postFuncBody": null
  226 + },
  227 + {
  228 + "name": "fw_url",
  229 + "type": "attribute",
  230 + "label": "fw_url",
  231 + "color": "#e91e63",
  232 + "settings": {
  233 + "columnWidth": "0px",
  234 + "useCellStyleFunction": false,
  235 + "cellStyleFunction": "",
  236 + "useCellContentFunction": false,
  237 + "cellContentFunction": "",
  238 + "defaultColumnVisibility": "hidden",
  239 + "columnSelectionToDisplay": "disabled"
  240 + },
  241 + "_hash": 0.4204673738685043,
  242 + "units": null,
  243 + "decimals": null,
  244 + "funcBody": null,
  245 + "usePostProcessing": null,
  246 + "postFuncBody": null
226 247 }
227 248 ]
228 249 }
... ... @@ -249,23 +270,23 @@
249 270 "icon": "edit",
250 271 "type": "customPretty",
251 272 "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
252   - "customCss": "",
  273 + "customCss": "form {\n min-width: 300px !important;\n}",
253 274 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
254 275 "customResources": [],
255 276 "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
256 277 },
257 278 {
258   - "name": "Download firware",
  279 + "name": "Download firmware",
259 280 "icon": "file_download",
260 281 "type": "custom",
261   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  282 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
262 283 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
263 284 },
264 285 {
265   - "name": "Copy checksum",
  286 + "name": "Copy checksum/URL",
266 287 "icon": "content_copy",
267 288 "type": "custom",
268   - "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n}",
  289 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Firmware direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
269 290 "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
270 291 }
271 292 ]
... ... @@ -997,6 +1018,27 @@
997 1018 "funcBody": null,
998 1019 "usePostProcessing": null,
999 1020 "postFuncBody": null
  1021 + },
  1022 + {
  1023 + "name": "fw_url",
  1024 + "type": "attribute",
  1025 + "label": "fw_url",
  1026 + "color": "#e91e63",
  1027 + "settings": {
  1028 + "columnWidth": "0px",
  1029 + "useCellStyleFunction": false,
  1030 + "cellStyleFunction": "",
  1031 + "useCellContentFunction": false,
  1032 + "cellContentFunction": "",
  1033 + "defaultColumnVisibility": "hidden",
  1034 + "columnSelectionToDisplay": "disabled"
  1035 + },
  1036 + "_hash": 0.4204673738685043,
  1037 + "units": null,
  1038 + "decimals": null,
  1039 + "funcBody": null,
  1040 + "usePostProcessing": null,
  1041 + "postFuncBody": null
1000 1042 }
1001 1043 ]
1002 1044 }
... ... @@ -1023,23 +1065,23 @@
1023 1065 "icon": "edit",
1024 1066 "type": "customPretty",
1025 1067 "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1026   - "customCss": "",
  1068 + "customCss": "form {\n min-width: 300px !important;\n}",
1027 1069 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1028 1070 "customResources": [],
1029 1071 "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
1030 1072 },
1031 1073 {
1032   - "name": "Download firware",
  1074 + "name": "Download firmware",
1033 1075 "icon": "file_download",
1034 1076 "type": "custom",
1035   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1077 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1036 1078 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1037 1079 },
1038 1080 {
1039   - "name": "Copy checksum",
  1081 + "name": "Copy checksum/URL",
1040 1082 "icon": "content_copy",
1041 1083 "type": "custom",
1042   - "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n}",
  1084 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Firmware direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1043 1085 "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
1044 1086 }
1045 1087 ]
... ... @@ -1273,6 +1315,27 @@
1273 1315 "funcBody": null,
1274 1316 "usePostProcessing": null,
1275 1317 "postFuncBody": null
  1318 + },
  1319 + {
  1320 + "name": "fw_url",
  1321 + "type": "attribute",
  1322 + "label": "fw_url",
  1323 + "color": "#e91e63",
  1324 + "settings": {
  1325 + "columnWidth": "0px",
  1326 + "useCellStyleFunction": false,
  1327 + "cellStyleFunction": "",
  1328 + "useCellContentFunction": false,
  1329 + "cellContentFunction": "",
  1330 + "defaultColumnVisibility": "hidden",
  1331 + "columnSelectionToDisplay": "disabled"
  1332 + },
  1333 + "_hash": 0.4204673738685043,
  1334 + "units": null,
  1335 + "decimals": null,
  1336 + "funcBody": null,
  1337 + "usePostProcessing": null,
  1338 + "postFuncBody": null
1276 1339 }
1277 1340 ]
1278 1341 }
... ... @@ -1299,23 +1362,23 @@
1299 1362 "icon": "edit",
1300 1363 "type": "customPretty",
1301 1364 "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1302   - "customCss": "",
  1365 + "customCss": "form {\n min-width: 300px !important;\n}",
1303 1366 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1304 1367 "customResources": [],
1305 1368 "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
1306 1369 },
1307 1370 {
1308   - "name": "Download firware",
  1371 + "name": "Download firmware",
1309 1372 "icon": "file_download",
1310 1373 "type": "custom",
1311   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1374 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1312 1375 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1313 1376 },
1314 1377 {
1315   - "name": "Copy checksum",
  1378 + "name": "Copy checksum/URL",
1316 1379 "icon": "content_copy",
1317 1380 "type": "custom",
1318   - "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n}",
  1381 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Firmware direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1319 1382 "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
1320 1383 }
1321 1384 ]
... ... @@ -1549,6 +1612,27 @@
1549 1612 "funcBody": null,
1550 1613 "usePostProcessing": null,
1551 1614 "postFuncBody": null
  1615 + },
  1616 + {
  1617 + "name": "fw_url",
  1618 + "type": "attribute",
  1619 + "label": "fw_url",
  1620 + "color": "#e91e63",
  1621 + "settings": {
  1622 + "columnWidth": "0px",
  1623 + "useCellStyleFunction": false,
  1624 + "cellStyleFunction": "",
  1625 + "useCellContentFunction": false,
  1626 + "cellContentFunction": "",
  1627 + "defaultColumnVisibility": "hidden",
  1628 + "columnSelectionToDisplay": "disabled"
  1629 + },
  1630 + "_hash": 0.4204673738685043,
  1631 + "units": null,
  1632 + "decimals": null,
  1633 + "funcBody": null,
  1634 + "usePostProcessing": null,
  1635 + "postFuncBody": null
1552 1636 }
1553 1637 ]
1554 1638 }
... ... @@ -1575,23 +1659,23 @@
1575 1659 "icon": "edit",
1576 1660 "type": "customPretty",
1577 1661 "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1578   - "customCss": "",
  1662 + "customCss": "form {\n min-width: 300px !important;\n}",
1579 1663 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1580 1664 "customResources": [],
1581 1665 "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
1582 1666 },
1583 1667 {
1584   - "name": "Download firware",
  1668 + "name": "Download firmware",
1585 1669 "icon": "file_download",
1586 1670 "type": "custom",
1587   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1671 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1588 1672 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1589 1673 },
1590 1674 {
1591   - "name": "Copy checksum",
  1675 + "name": "Copy checksum/URL",
1592 1676 "icon": "content_copy",
1593 1677 "type": "custom",
1594   - "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n}",
  1678 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Firmware direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1595 1679 "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
1596 1680 }
1597 1681 ]
... ... @@ -1825,6 +1909,27 @@
1825 1909 "funcBody": null,
1826 1910 "usePostProcessing": null,
1827 1911 "postFuncBody": null
  1912 + },
  1913 + {
  1914 + "name": "fw_url",
  1915 + "type": "attribute",
  1916 + "label": "fw_url",
  1917 + "color": "#e91e63",
  1918 + "settings": {
  1919 + "columnWidth": "0px",
  1920 + "useCellStyleFunction": false,
  1921 + "cellStyleFunction": "",
  1922 + "useCellContentFunction": false,
  1923 + "cellContentFunction": "",
  1924 + "defaultColumnVisibility": "hidden",
  1925 + "columnSelectionToDisplay": "disabled"
  1926 + },
  1927 + "_hash": 0.4204673738685043,
  1928 + "units": null,
  1929 + "decimals": null,
  1930 + "funcBody": null,
  1931 + "usePostProcessing": null,
  1932 + "postFuncBody": null
1828 1933 }
1829 1934 ]
1830 1935 }
... ... @@ -1851,23 +1956,23 @@
1851 1956 "icon": "edit",
1852 1957 "type": "customPretty",
1853 1958 "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit firmware {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"firmwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
1854   - "customCss": "",
  1959 + "customCss": "form {\n min-width: 300px !important;\n}",
1855 1960 "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n firmwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n firmwareId: vm.entity.firmwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.firmwareId = formValues.firmwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
1856 1961 "customResources": [],
1857 1962 "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
1858 1963 },
1859 1964 {
1860   - "name": "Download firware",
  1965 + "name": "Download firmware",
1861 1966 "icon": "file_download",
1862 1967 "type": "custom",
1863   - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n\n }\n });\n }\n }\n );\n}",
  1968 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceFirmware();\n\nfunction getDeviceFirmware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(data.firmwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.firmwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.firmwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1864 1969 "id": "12533058-42f6-e75f-620c-219c48d01ec0"
1865 1970 },
1866 1971 {
1867   - "name": "Copy checksum",
  1972 + "name": "Copy checksum/URL",
1868 1973 "icon": "content_copy",
1869 1974 "type": "custom",
1870   - "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n}",
  1975 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_checksum');\nvar checksum = data.data[0][1];\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Firmware checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'fw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Firmware direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not firmware set.', 2000, 'top');\n }\n}",
1871 1976 "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
1872 1977 }
1873 1978 ]
... ... @@ -1936,7 +2041,7 @@
1936 2041 }
1937 2042 },
1938 2043 "device_firmware_history": {
1939   - "name": "Device Firmware history",
  2044 + "name": "Firmware history: ${entityName}",
1940 2045 "root": false,
1941 2046 "layouts": {
1942 2047 "main": {
... ... @@ -2379,7 +2484,8 @@
2379 2484 "titleColor": "rgba(0,0,0,0.870588)",
2380 2485 "showFilters": true,
2381 2486 "showDashboardLogo": false,
2382   - "dashboardLogoUrl": null
  2487 + "dashboardLogoUrl": null,
  2488 + "showUpdateDashboardImage": false
2383 2489 }
2384 2490 },
2385 2491 "name": "Firmware"
... ...
  1 +{
  2 + "title": "Software",
  3 + "image": null,
  4 + "configuration": {
  5 + "description": "",
  6 + "widgets": {
  7 + "cd03188e-cd9d-9601-fd57-da4cb95fc016": {
  8 + "isSystemType": true,
  9 + "bundleAlias": "cards",
  10 + "typeAlias": "entities_table",
  11 + "type": "latest",
  12 + "title": "New widget",
  13 + "image": null,
  14 + "description": null,
  15 + "sizeX": 7.5,
  16 + "sizeY": 6.5,
  17 + "config": {
  18 + "timewindow": {
  19 + "realtime": {
  20 + "interval": 1000,
  21 + "timewindowMs": 86400000
  22 + },
  23 + "aggregation": {
  24 + "type": "NONE",
  25 + "limit": 200
  26 + }
  27 + },
  28 + "showTitle": true,
  29 + "backgroundColor": "rgb(255, 255, 255)",
  30 + "color": "rgba(0, 0, 0, 0.87)",
  31 + "padding": "4px",
  32 + "settings": {
  33 + "enableSearch": true,
  34 + "displayPagination": true,
  35 + "defaultPageSize": 10,
  36 + "defaultSortOrder": "entityLabel",
  37 + "displayEntityName": false,
  38 + "displayEntityType": false,
  39 + "enableSelectColumnDisplay": false,
  40 + "enableStickyHeader": true,
  41 + "enableStickyAction": false,
  42 + "entitiesTitle": "Devices",
  43 + "displayEntityLabel": true,
  44 + "entityLabelColumnTitle": "Device"
  45 + },
  46 + "title": "New Entities table",
  47 + "dropShadow": true,
  48 + "enableFullscreen": true,
  49 + "titleStyle": {
  50 + "fontSize": "16px",
  51 + "fontWeight": 400,
  52 + "padding": "5px 10px 5px 10px"
  53 + },
  54 + "useDashboardTimewindow": false,
  55 + "showLegend": false,
  56 + "datasources": [
  57 + {
  58 + "type": "entity",
  59 + "name": null,
  60 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  61 + "filterId": "8fdb88d0-50ac-2232-fdb7-69c30c16544e",
  62 + "dataKeys": [
  63 + {
  64 + "name": "current_sw_title",
  65 + "type": "timeseries",
  66 + "label": "Current SW title",
  67 + "color": "#2196f3",
  68 + "settings": {
  69 + "columnWidth": "0px",
  70 + "useCellStyleFunction": false,
  71 + "cellStyleFunction": "",
  72 + "useCellContentFunction": false,
  73 + "defaultColumnVisibility": "visible",
  74 + "columnSelectionToDisplay": "enabled"
  75 + },
  76 + "_hash": 0.09545533885166413,
  77 + "units": null,
  78 + "decimals": null,
  79 + "funcBody": null,
  80 + "usePostProcessing": null,
  81 + "postFuncBody": null
  82 + },
  83 + {
  84 + "name": "current_sw_version",
  85 + "type": "timeseries",
  86 + "label": "Current SW version",
  87 + "color": "#4caf50",
  88 + "settings": {
  89 + "columnWidth": "0px",
  90 + "useCellStyleFunction": false,
  91 + "cellStyleFunction": "",
  92 + "useCellContentFunction": false,
  93 + "defaultColumnVisibility": "visible",
  94 + "columnSelectionToDisplay": "enabled"
  95 + },
  96 + "_hash": 0.7206056602328659,
  97 + "units": null,
  98 + "decimals": null,
  99 + "funcBody": null,
  100 + "usePostProcessing": null,
  101 + "postFuncBody": null
  102 + },
  103 + {
  104 + "name": "target_sw_title",
  105 + "type": "timeseries",
  106 + "label": "Target SW title",
  107 + "color": "#ffc107",
  108 + "settings": {
  109 + "columnWidth": "0px",
  110 + "useCellStyleFunction": false,
  111 + "cellStyleFunction": "",
  112 + "useCellContentFunction": false,
  113 + "defaultColumnVisibility": "visible",
  114 + "columnSelectionToDisplay": "enabled"
  115 + },
  116 + "_hash": 0.9934225682766313,
  117 + "units": null,
  118 + "decimals": null,
  119 + "funcBody": null,
  120 + "usePostProcessing": null,
  121 + "postFuncBody": null
  122 + },
  123 + {
  124 + "name": "target_sw_version",
  125 + "type": "timeseries",
  126 + "label": "Target SW version",
  127 + "color": "#607d8b",
  128 + "settings": {
  129 + "columnWidth": "0px",
  130 + "useCellStyleFunction": false,
  131 + "cellStyleFunction": "",
  132 + "useCellContentFunction": false,
  133 + "cellContentFunction": "",
  134 + "defaultColumnVisibility": "visible",
  135 + "columnSelectionToDisplay": "enabled"
  136 + },
  137 + "_hash": 0.5251724416842531,
  138 + "units": null,
  139 + "decimals": null,
  140 + "funcBody": null,
  141 + "usePostProcessing": null,
  142 + "postFuncBody": null
  143 + },
  144 + {
  145 + "name": "target_sw_ts",
  146 + "type": "timeseries",
  147 + "label": "Target SW set time",
  148 + "color": "#e91e63",
  149 + "settings": {
  150 + "columnWidth": "0px",
  151 + "useCellStyleFunction": false,
  152 + "cellStyleFunction": "",
  153 + "useCellContentFunction": true,
  154 + "defaultColumnVisibility": "visible",
  155 + "columnSelectionToDisplay": "enabled",
  156 + "cellContentFunction": "if (value !== '') {\n return ctx.date.transform(value, 'yyyy-MM-dd HH:mm:ss');\n}\nreturn '';"
  157 + },
  158 + "_hash": 0.31823244858578237,
  159 + "units": null,
  160 + "decimals": null,
  161 + "funcBody": null,
  162 + "usePostProcessing": null,
  163 + "postFuncBody": null
  164 + },
  165 + {
  166 + "name": "sw_state",
  167 + "type": "timeseries",
  168 + "label": "Progress",
  169 + "color": "#9c27b0",
  170 + "settings": {
  171 + "columnWidth": "30%",
  172 + "useCellStyleFunction": true,
  173 + "useCellContentFunction": true,
  174 + "defaultColumnVisibility": "visible",
  175 + "columnSelectionToDisplay": "enabled",
  176 + "cellStyleFunction": "return {\n 'padding-right': '30px'\n}",
  177 + "cellContentFunction": "if (value !== '') {\n var mapProgress = {\n 'QUEUED': 0,\n 'INITIATED': 5,\n 'DOWNLOADING': 10,\n 'DOWNLOADED': 55,\n 'VERIFIED': 60,\n 'UPDATING': 70,\n 'FAILED': 99,\n 'UPDATED': 100\n }\n var color = 'mat-primary';\n var progress = mapProgress[value];\n if (value == 'FAILED') {\n color = 'mat-accent';\n }\n return `<mat-progress-bar style=\"height: 8px\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" tabindex=\"-1\" mode=\"determinate\" value=\"${progress}\" class=\"mat-progress-bar ${color}\" aria-valuenow=\"${progress}\"><div aria-hidden=\"true\"><svg width=\"100%\" height=\"8\" focusable=\"false\" class=\"mat-progress-bar-background mat-progress-bar-element\"><defs><pattern x=\"4\" y=\"0\" width=\"8\" height=\"4\" patternUnits=\"userSpaceOnUse\" id=\"mat-progress-bar-0\"><circle cx=\"2\" cy=\"2\" r=\"2\"></circle></pattern></defs><rect width=\"100%\" height=\"100%\" fill=\"url(\"/components/progress-bar/overview#mat-progress-bar-0\")\"></rect></svg><div class=\"mat-progress-bar-buffer mat-progress-bar-element\"></div><div class=\"mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element\" style=\"transform: scale3d(${progress / 100}, 1, 1);\"></div><div class=\"mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element\"></div></div></mat-progress-bar>`;\n}"
  178 + },
  179 + "_hash": 0.8174211757846257,
  180 + "units": null,
  181 + "decimals": null,
  182 + "funcBody": null,
  183 + "usePostProcessing": null,
  184 + "postFuncBody": null
  185 + },
  186 + {
  187 + "name": "sw_state",
  188 + "type": "timeseries",
  189 + "label": "Status",
  190 + "color": "#f44336",
  191 + "settings": {
  192 + "columnWidth": "130px",
  193 + "useCellStyleFunction": true,
  194 + "useCellContentFunction": true,
  195 + "defaultColumnVisibility": "visible",
  196 + "columnSelectionToDisplay": "enabled",
  197 + "cellStyleFunction": "if (value == 'FAILED') {\n return {'color' : '#D93025'};\n}\nreturn {};",
  198 + "cellContentFunction": "function icon(value) {\n if (value == 'QUEUED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000;\"><svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z\" /></svg></mat-icon>';\n }\n if (value == 'INITIATED' || value == 'DOWNLOADING' || value == 'DOWNLOADED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.74 2.1951C11.63 1.2876 10.2575 0.687598 8.75 0.537598V2.0526C9.845 2.1876 10.8425 2.6226 11.675 3.2676L12.74 2.1951ZM13.9475 7.2501H15.4625C15.3125 5.7426 14.7125 4.3701 13.805 3.2601L12.7325 4.3251C13.3775 5.1576 13.8125 6.1551 13.9475 7.2501ZM12.7325 11.6751L13.805 12.7476C14.7125 11.6376 15.3125 10.2576 15.4625 8.7576H13.9475C13.8125 9.8451 13.3775 10.8426 12.7325 11.6751ZM8.75 13.9476V15.4626C10.2575 15.3126 11.63 14.7126 12.74 13.8051L11.6675 12.7326C10.8425 13.3776 9.845 13.8126 8.75 13.9476ZM8.75 8.0001V4.2501H7.25V8.0001H4.25L8 11.7501L11.75 8.0001H8.75ZM7.25 13.9476V15.4626C3.4625 15.0876 0.5 11.8926 0.5 8.0001C0.5 4.1076 3.4625 0.912598 7.25 0.537598V2.0526C4.2875 2.4201 2 4.9401 2 8.0001C2 11.0601 4.2875 13.5801 7.25 13.9476Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'VERIFIED' || value == 'UPDATING' ) {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\">update</mat-icon>';\n }\n if (value == 'UPDATED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg style=\"width:22px;height:22px\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/><path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'FAILED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #D93025\">warning</mat-icon>';\n }\n return '';\n}\nfunction capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nreturn icon(value) + '<span style=\"vertical-align: super;padding-left: 8px;\">' + capitalize(value) + '</span>';"
  199 + },
  200 + "_hash": 0.7764426948615217,
  201 + "units": null,
  202 + "decimals": null,
  203 + "funcBody": null,
  204 + "usePostProcessing": null,
  205 + "postFuncBody": null
  206 + },
  207 + {
  208 + "name": "sw_checksum",
  209 + "type": "attribute",
  210 + "label": "sw_checksum",
  211 + "color": "#3f51b5",
  212 + "settings": {
  213 + "columnWidth": "0px",
  214 + "useCellStyleFunction": false,
  215 + "cellStyleFunction": "",
  216 + "useCellContentFunction": false,
  217 + "defaultColumnVisibility": "hidden",
  218 + "columnSelectionToDisplay": "disabled"
  219 + },
  220 + "_hash": 0.5594087842471693,
  221 + "units": null,
  222 + "decimals": null,
  223 + "funcBody": null,
  224 + "usePostProcessing": null,
  225 + "postFuncBody": null
  226 + },
  227 + {
  228 + "name": "sw_url",
  229 + "type": "attribute",
  230 + "label": "sw_url",
  231 + "color": "#e91e63",
  232 + "settings": {
  233 + "columnWidth": "0px",
  234 + "useCellStyleFunction": false,
  235 + "cellStyleFunction": "",
  236 + "useCellContentFunction": false,
  237 + "cellContentFunction": "",
  238 + "defaultColumnVisibility": "hidden",
  239 + "columnSelectionToDisplay": "disabled"
  240 + },
  241 + "_hash": 0.3355829384124256,
  242 + "units": null,
  243 + "decimals": null,
  244 + "funcBody": null,
  245 + "usePostProcessing": null,
  246 + "postFuncBody": null
  247 + }
  248 + ]
  249 + }
  250 + ],
  251 + "actions": {
  252 + "actionCellButton": [
  253 + {
  254 + "name": "History software update",
  255 + "icon": "history",
  256 + "type": "openDashboardState",
  257 + "targetDashboardStateId": "device_software_history",
  258 + "setEntityId": true,
  259 + "stateEntityParamName": null,
  260 + "openInSeparateDialog": false,
  261 + "dialogTitle": "",
  262 + "dialogHideDashboardToolbar": true,
  263 + "dialogWidth": null,
  264 + "dialogHeight": null,
  265 + "openRightLayout": false,
  266 + "id": "98a1406c-3301-bc2f-2c5d-d637ce3b663b"
  267 + },
  268 + {
  269 + "name": "Edit software",
  270 + "icon": "edit",
  271 + "type": "customPretty",
  272 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit software {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n type=\"SOFTWARE\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"softwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  273 + "customCss": "form {\n min-width: 300px !important;\n}",
  274 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n softwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n softwareId: vm.entity.softwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.softwareId = formValues.softwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
  275 + "customResources": [],
  276 + "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
  277 + },
  278 + {
  279 + "name": "Download software",
  280 + "icon": "file_download",
  281 + "type": "custom",
  282 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceSoftware();\n\nfunction getDeviceSoftware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.softwareId !== null) {\n otaPackageService.downloadOtaPackage(data.softwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.softwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.softwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  283 + "id": "12533058-42f6-e75f-620c-219c48d01ec0"
  284 + },
  285 + {
  286 + "name": "Copy checksum/URL",
  287 + "icon": "content_copy",
  288 + "type": "custom",
  289 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_checksum');\nvar checksum = data.data[0][1];\nconsole.log(checksum);\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Software checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Software direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  290 + "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
  291 + }
  292 + ]
  293 + },
  294 + "showTitleIcon": false,
  295 + "iconColor": "rgba(0, 0, 0, 0.87)",
  296 + "iconSize": "24px",
  297 + "titleTooltip": "",
  298 + "widgetStyle": {}
  299 + },
  300 + "row": 0,
  301 + "col": 0,
  302 + "id": "cd03188e-cd9d-9601-fd57-da4cb95fc016"
  303 + },
  304 + "100b756c-0082-6505-3ae1-3603e6deea48": {
  305 + "isSystemType": true,
  306 + "bundleAlias": "cards",
  307 + "typeAlias": "timeseries_table",
  308 + "type": "timeseries",
  309 + "title": "New widget",
  310 + "image": null,
  311 + "description": null,
  312 + "sizeX": 8,
  313 + "sizeY": 6.5,
  314 + "config": {
  315 + "datasources": [
  316 + {
  317 + "type": "entity",
  318 + "name": null,
  319 + "entityAliasId": "19f41c21-d9af-e666-8f50-e1748778f955",
  320 + "filterId": null,
  321 + "dataKeys": [
  322 + {
  323 + "name": "current_sw_title",
  324 + "type": "timeseries",
  325 + "label": "Current software title",
  326 + "color": "#2196f3",
  327 + "settings": {
  328 + "useCellStyleFunction": false,
  329 + "cellStyleFunction": "",
  330 + "useCellContentFunction": false,
  331 + "cellContentFunction": ""
  332 + },
  333 + "_hash": 0.5978079905579401,
  334 + "units": null,
  335 + "decimals": null,
  336 + "funcBody": null,
  337 + "usePostProcessing": null,
  338 + "postFuncBody": null
  339 + },
  340 + {
  341 + "name": "current_sw_version",
  342 + "type": "timeseries",
  343 + "label": "Current software version",
  344 + "color": "#4caf50",
  345 + "settings": {
  346 + "useCellStyleFunction": false,
  347 + "cellStyleFunction": "",
  348 + "useCellContentFunction": false,
  349 + "cellContentFunction": ""
  350 + },
  351 + "_hash": 0.027392025058568192,
  352 + "units": null,
  353 + "decimals": null,
  354 + "funcBody": null,
  355 + "usePostProcessing": null,
  356 + "postFuncBody": null
  357 + },
  358 + {
  359 + "name": "target_sw_title",
  360 + "type": "timeseries",
  361 + "label": "Target software title",
  362 + "color": "#f44336",
  363 + "settings": {
  364 + "useCellStyleFunction": false,
  365 + "cellStyleFunction": "",
  366 + "useCellContentFunction": false,
  367 + "cellContentFunction": ""
  368 + },
  369 + "_hash": 0.9496350796287059,
  370 + "units": null,
  371 + "decimals": null,
  372 + "funcBody": null,
  373 + "usePostProcessing": null,
  374 + "postFuncBody": null
  375 + },
  376 + {
  377 + "name": "target_sw_version",
  378 + "type": "timeseries",
  379 + "label": "Target software version",
  380 + "color": "#ffc107",
  381 + "settings": {
  382 + "useCellStyleFunction": false,
  383 + "cellStyleFunction": "",
  384 + "useCellContentFunction": false,
  385 + "cellContentFunction": ""
  386 + },
  387 + "_hash": 0.6734152252264187,
  388 + "units": null,
  389 + "decimals": null,
  390 + "funcBody": null,
  391 + "usePostProcessing": null,
  392 + "postFuncBody": null
  393 + },
  394 + {
  395 + "name": "sw_state",
  396 + "type": "timeseries",
  397 + "label": "Status",
  398 + "color": "#607d8b",
  399 + "settings": {
  400 + "useCellStyleFunction": false,
  401 + "cellStyleFunction": "",
  402 + "useCellContentFunction": false,
  403 + "cellContentFunction": ""
  404 + },
  405 + "_hash": 0.2983399718643074,
  406 + "units": null,
  407 + "decimals": null,
  408 + "funcBody": null,
  409 + "usePostProcessing": true,
  410 + "postFuncBody": "function capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\nif (value !== '') {\n return capitalize(value);\n}\nreturn value;"
  411 + }
  412 + ]
  413 + }
  414 + ],
  415 + "timewindow": {
  416 + "hideInterval": false,
  417 + "hideAggregation": false,
  418 + "hideAggInterval": false,
  419 + "hideTimezone": false,
  420 + "selectedTab": 0,
  421 + "realtime": {
  422 + "realtimeType": 0,
  423 + "timewindowMs": 2592000000,
  424 + "quickInterval": "CURRENT_DAY",
  425 + "interval": 1000
  426 + },
  427 + "aggregation": {
  428 + "type": "NONE",
  429 + "limit": 200
  430 + }
  431 + },
  432 + "showTitle": false,
  433 + "backgroundColor": "rgb(255, 255, 255)",
  434 + "color": "rgba(0, 0, 0, 0.87)",
  435 + "padding": "8px",
  436 + "settings": {
  437 + "showTimestamp": true,
  438 + "displayPagination": true,
  439 + "defaultPageSize": 10,
  440 + "enableSearch": true,
  441 + "enableStickyHeader": true,
  442 + "enableStickyAction": true
  443 + },
  444 + "title": "Software history",
  445 + "dropShadow": false,
  446 + "enableFullscreen": false,
  447 + "titleStyle": {
  448 + "fontSize": "16px",
  449 + "fontWeight": 400,
  450 + "padding": "5px 10px 5px 10px"
  451 + },
  452 + "useDashboardTimewindow": false,
  453 + "showLegend": false,
  454 + "widgetStyle": {},
  455 + "actions": {},
  456 + "showTitleIcon": false,
  457 + "iconColor": "rgba(0, 0, 0, 0.87)",
  458 + "iconSize": "24px",
  459 + "displayTimewindow": true,
  460 + "titleTooltip": ""
  461 + },
  462 + "row": 0,
  463 + "col": 0,
  464 + "id": "100b756c-0082-6505-3ae1-3603e6deea48"
  465 + },
  466 + "17543c57-af4a-2c1e-bf12-53a7b46791e6": {
  467 + "isSystemType": true,
  468 + "bundleAlias": "cards",
  469 + "typeAlias": "html_value_card",
  470 + "type": "latest",
  471 + "title": "New widget",
  472 + "sizeX": 8,
  473 + "sizeY": 3,
  474 + "config": {
  475 + "datasources": [
  476 + {
  477 + "type": "entityCount",
  478 + "name": "",
  479 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  480 + "filterId": "19a0ad1c-b31d-4a29-9d7b-5d87e2a8ea6e",
  481 + "dataKeys": [
  482 + {
  483 + "name": "count",
  484 + "type": "count",
  485 + "label": "waitingDevicesNumber",
  486 + "color": "#4caf50",
  487 + "settings": {},
  488 + "_hash": 0.7404827038869322,
  489 + "units": null,
  490 + "decimals": null,
  491 + "funcBody": null,
  492 + "usePostProcessing": null,
  493 + "postFuncBody": null
  494 + }
  495 + ]
  496 + }
  497 + ],
  498 + "timewindow": {
  499 + "realtime": {
  500 + "timewindowMs": 60000
  501 + }
  502 + },
  503 + "showTitle": false,
  504 + "backgroundColor": "#fff",
  505 + "color": "rgba(0, 0, 0, 0.87)",
  506 + "padding": "0px",
  507 + "settings": {
  508 + "cardHtml": "<div class='card' id=\"activeDevices\">\n <div class='content' id=\"activeDevices\">\n <img id=\"activeDevices\" src='data:image/svg+xml;utf8,<svg width=\"24\" height=\"40\" viewBox=\"0 0 24 40\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M0 0V12H0.0200005L0 12.02L8 20L0 28L0.0200005 28.02H0V40H24V28.02H23.98L24 28L16 20L24 12.02L23.98 12H24V0H0ZM20 29V36H4V29L12 21L20 29ZM12 19L4 11V4H20V11L12 19Z\" fill=\"black\"/>\n</svg>\n'>\n <div class='value' id=\"activeDevices\">\n ${waitingDevicesNumber:0}\n </div> \n <div class='description' id=\"activeDevices\">\n Device Waiting\n </div>\n </div>\n</div>",
  509 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n border: 1px solid #E0E0E0;\n box-sizing: border-box;\n}\n\n.card .content {\n padding: 20px 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n box-sizing: border-box;\n}\n\n.card .value {\n margin: 18px 0 5px;\n font-weight: 500;\n font-size: 3em;\n line-height: 1.1em;\n text-align: center;\n letter-spacing: -0.02em;\n color: #333333;\n}\n\n.card .description {\n font-size: 1em;\n line-height: 1.1em;\n color: #000000;\n opacity: 0.6;\n text-align: center;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 960px) and (max-width: 1200px) {\n .card .content img {\n height: 28px; \n }\n \n .card .value {\n margin: 12px 0 5px;\n font-size: 2em;\n line-height: 1;\n }\n \n .card .description {\n font-size: 0.8em;\n line-height: 1;\n }\n}"
  510 + },
  511 + "title": "New HTML Value Card",
  512 + "dropShadow": true,
  513 + "enableFullscreen": false,
  514 + "widgetStyle": {},
  515 + "titleStyle": {
  516 + "fontSize": "16px",
  517 + "fontWeight": 400
  518 + },
  519 + "useDashboardTimewindow": true,
  520 + "showLegend": false,
  521 + "actions": {
  522 + "elementClick": [
  523 + {
  524 + "name": "activeDevices",
  525 + "icon": "more_horiz",
  526 + "type": "openDashboardState",
  527 + "targetDashboardStateId": "device_waiting",
  528 + "setEntityId": false,
  529 + "stateEntityParamName": null,
  530 + "openInSeparateDialog": false,
  531 + "dialogTitle": "",
  532 + "dialogHideDashboardToolbar": true,
  533 + "dialogWidth": null,
  534 + "dialogHeight": null,
  535 + "openRightLayout": false,
  536 + "id": "4d9a77a2-f0a5-690c-a83b-b0e940be788c"
  537 + }
  538 + ]
  539 + },
  540 + "showTitleIcon": false,
  541 + "titleIcon": null,
  542 + "iconColor": "rgba(0, 0, 0, 0.87)",
  543 + "iconSize": "24px",
  544 + "titleTooltip": "",
  545 + "enableDataExport": false,
  546 + "displayTimewindow": true
  547 + },
  548 + "id": "17543c57-af4a-2c1e-bf12-53a7b46791e6"
  549 + },
  550 + "6c1c4e1a-bce0-f5ad-ff8b-ba1dfc5a4ec6": {
  551 + "isSystemType": true,
  552 + "bundleAlias": "cards",
  553 + "typeAlias": "html_value_card",
  554 + "type": "latest",
  555 + "title": "New widget",
  556 + "sizeX": 8,
  557 + "sizeY": 3,
  558 + "config": {
  559 + "datasources": [
  560 + {
  561 + "type": "entityCount",
  562 + "name": "",
  563 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  564 + "filterId": "579f0468-9ce9-7e3e-b34c-88dd3de59897",
  565 + "dataKeys": [
  566 + {
  567 + "name": "count",
  568 + "type": "count",
  569 + "label": "updatingDevicesNumber",
  570 + "color": "#4caf50",
  571 + "settings": {},
  572 + "_hash": 0.7404827038869322,
  573 + "units": null,
  574 + "decimals": null,
  575 + "funcBody": null,
  576 + "usePostProcessing": null,
  577 + "postFuncBody": null
  578 + }
  579 + ]
  580 + }
  581 + ],
  582 + "timewindow": {
  583 + "realtime": {
  584 + "timewindowMs": 60000
  585 + }
  586 + },
  587 + "showTitle": false,
  588 + "backgroundColor": "#fff",
  589 + "color": "rgba(0, 0, 0, 0.87)",
  590 + "padding": "0px",
  591 + "settings": {
  592 + "cardHtml": "<div class='card' id=\"activeDevices\">\n <div class='content' id=\"activeDevices\">\n <img id=\"activeDevices\" src='data:image/svg+xml;utf8,<svg width=\"36\" height=\"36\" viewBox=\"0 0 36 36\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M36 14.24H22.44L27.92 8.6C22.46 3.2 13.62 3 8.16001 8.4C2.70001 13.82 2.70001 22.56 8.16001 27.98C13.62 33.4 22.46 33.4 27.92 27.98C30.64 25.3 32 22.16 32 18.2H36C36 22.16 34.24 27.3 30.72 30.78C23.7 37.74 12.3 37.74 5.28001 30.78C-1.71999 23.84 -1.77999 12.56 5.24001 5.62C12.26 -1.32 23.52 -1.32 30.54 5.62L36 0V14.24ZM19 10V18.5L26 22.66L24.56 25.08L16 20V10H19Z\" fill=\"black\"/>\n</svg>'>\n <div class='value' id=\"activeDevices\">\n ${updatingDevicesNumber:0}\n </div> \n <div class='description' id=\"activeDevices\">\n Device Updating\n </div>\n </div>\n</div>",
  593 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n border: 1px solid #E0E0E0;\n box-sizing: border-box;\n}\n\n.card .content {\n padding: 20px 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n box-sizing: border-box;\n}\n\n.card .value {\n margin: 18px 0 5px;\n font-weight: 500;\n font-size: 3em;\n line-height: 1.1em;\n text-align: center;\n letter-spacing: -0.02em;\n color: #333333;\n}\n\n.card .description {\n font-size: 1em;\n line-height: 1.1em;\n color: #000000;\n opacity: 0.6;\n text-align: center;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 960px) and (max-width: 1200px) {\n .card .content img {\n height: 28px; \n }\n \n .card .value {\n margin: 12px 0 5px;\n font-size: 2em;\n line-height: 1;\n }\n \n .card .description {\n font-size: 0.8em;\n line-height: 1;\n }\n}"
  594 + },
  595 + "title": "New HTML Value Card",
  596 + "dropShadow": true,
  597 + "enableFullscreen": false,
  598 + "widgetStyle": {},
  599 + "titleStyle": {
  600 + "fontSize": "16px",
  601 + "fontWeight": 400
  602 + },
  603 + "useDashboardTimewindow": true,
  604 + "showLegend": false,
  605 + "actions": {
  606 + "elementClick": [
  607 + {
  608 + "name": "activeDevices",
  609 + "icon": "more_horiz",
  610 + "type": "openDashboardState",
  611 + "targetDashboardStateId": "device_updating",
  612 + "setEntityId": false,
  613 + "stateEntityParamName": null,
  614 + "openInSeparateDialog": false,
  615 + "dialogTitle": "",
  616 + "dialogHideDashboardToolbar": true,
  617 + "dialogWidth": null,
  618 + "dialogHeight": null,
  619 + "openRightLayout": false,
  620 + "id": "57d39904-2350-b29b-78ed-56b8268814cb"
  621 + }
  622 + ]
  623 + },
  624 + "showTitleIcon": false,
  625 + "titleIcon": null,
  626 + "iconColor": "rgba(0, 0, 0, 0.87)",
  627 + "iconSize": "24px",
  628 + "titleTooltip": "",
  629 + "enableDataExport": false,
  630 + "displayTimewindow": true
  631 + },
  632 + "id": "6c1c4e1a-bce0-f5ad-ff8b-ba1dfc5a4ec6"
  633 + },
  634 + "e6674227-9cf3-a2f6-ecac-5ccfc38a3c81": {
  635 + "isSystemType": true,
  636 + "bundleAlias": "cards",
  637 + "typeAlias": "html_value_card",
  638 + "type": "latest",
  639 + "title": "New widget",
  640 + "sizeX": 8,
  641 + "sizeY": 3,
  642 + "config": {
  643 + "datasources": [
  644 + {
  645 + "type": "entityCount",
  646 + "name": "",
  647 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  648 + "filterId": "6044e198-df64-cd76-f339-696f220c4943",
  649 + "dataKeys": [
  650 + {
  651 + "name": "count",
  652 + "type": "count",
  653 + "label": "updatedDevicesNumber",
  654 + "color": "#4caf50",
  655 + "settings": {},
  656 + "_hash": 0.7404827038869322,
  657 + "units": null,
  658 + "decimals": null,
  659 + "funcBody": null,
  660 + "usePostProcessing": null,
  661 + "postFuncBody": null
  662 + }
  663 + ]
  664 + }
  665 + ],
  666 + "timewindow": {
  667 + "realtime": {
  668 + "timewindowMs": 60000
  669 + }
  670 + },
  671 + "showTitle": false,
  672 + "backgroundColor": "#fff",
  673 + "color": "rgba(0, 0, 0, 0.87)",
  674 + "padding": "0px",
  675 + "settings": {
  676 + "cardHtml": "<div class='card' id=\"activeDevices\">\n <div class='content' id=\"activeDevices\">\n <img id=\"activeDevices\" src='data:image/svg+xml;utf8,<svg width=\"34\" height=\"32\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/>\n<path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/>\n</svg>'>\n <div class='value' id=\"activeDevices\">\n ${updatedDevicesNumber:0}\n </div> \n <div class='description' id=\"activeDevices\">\n Device Updated\n </div>\n </div>\n</div>",
  677 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n border: 1px solid #E0E0E0;\n box-sizing: border-box;\n}\n\n.card .content {\n padding: 20px 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n box-sizing: border-box;\n}\n\n.card .value {\n margin: 18px 0 5px;\n font-weight: 500;\n font-size: 3em;\n line-height: 1.1em;\n text-align: center;\n letter-spacing: -0.02em;\n color: #333333;\n}\n\n.card .description {\n font-size: 1em;\n line-height: 1.1em;\n color: #000000;\n opacity: 0.6;\n text-align: center;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 960px) and (max-width: 1200px) {\n .card .content img {\n height: 28px; \n }\n \n .card .value {\n margin: 12px 0 5px;\n font-size: 2em;\n line-height: 1;\n }\n \n .card .description {\n font-size: 0.8em;\n line-height: 1;\n }\n}"
  678 + },
  679 + "title": "New HTML Value Card",
  680 + "dropShadow": true,
  681 + "enableFullscreen": false,
  682 + "widgetStyle": {},
  683 + "titleStyle": {
  684 + "fontSize": "16px",
  685 + "fontWeight": 400
  686 + },
  687 + "useDashboardTimewindow": true,
  688 + "showLegend": false,
  689 + "actions": {
  690 + "elementClick": [
  691 + {
  692 + "name": "activeDevices",
  693 + "icon": "more_horiz",
  694 + "type": "openDashboardState",
  695 + "targetDashboardStateId": "device_updated",
  696 + "setEntityId": false,
  697 + "stateEntityParamName": null,
  698 + "openInSeparateDialog": false,
  699 + "dialogTitle": "",
  700 + "dialogHideDashboardToolbar": true,
  701 + "dialogWidth": null,
  702 + "dialogHeight": null,
  703 + "openRightLayout": false,
  704 + "id": "d787c212-8c56-34f0-349a-5aae2ffd1eae"
  705 + }
  706 + ]
  707 + },
  708 + "showTitleIcon": false,
  709 + "titleIcon": null,
  710 + "iconColor": "rgba(0, 0, 0, 0.87)",
  711 + "iconSize": "24px",
  712 + "titleTooltip": "",
  713 + "enableDataExport": false,
  714 + "displayTimewindow": true
  715 + },
  716 + "id": "e6674227-9cf3-a2f6-ecac-5ccfc38a3c81"
  717 + },
  718 + "77b10144-b904-edd5-8c7c-8fb75616c6d8": {
  719 + "isSystemType": true,
  720 + "bundleAlias": "cards",
  721 + "typeAlias": "html_value_card",
  722 + "type": "latest",
  723 + "title": "New widget",
  724 + "sizeX": 8,
  725 + "sizeY": 3,
  726 + "config": {
  727 + "datasources": [
  728 + {
  729 + "type": "entityCount",
  730 + "name": "",
  731 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  732 + "filterId": "bdbc6ea1-95a7-3912-341a-58dc7704a00f",
  733 + "dataKeys": [
  734 + {
  735 + "name": "count",
  736 + "type": "count",
  737 + "label": "updatingDevicesNumber",
  738 + "color": "#4caf50",
  739 + "settings": {},
  740 + "_hash": 0.7404827038869322,
  741 + "units": null,
  742 + "decimals": null,
  743 + "funcBody": null,
  744 + "usePostProcessing": null,
  745 + "postFuncBody": null
  746 + }
  747 + ]
  748 + }
  749 + ],
  750 + "timewindow": {
  751 + "realtime": {
  752 + "timewindowMs": 60000
  753 + }
  754 + },
  755 + "showTitle": false,
  756 + "backgroundColor": "#fff",
  757 + "color": "rgba(0, 0, 0, 0.87)",
  758 + "padding": "0px",
  759 + "settings": {
  760 + "cardHtml": "<div class='card' id=\"activeDevices\">\n <div class='content' id=\"activeDevices\">\n <div class=\"container-svg\" id=\"activeDevices\">\n <svg viewBox=\"0 0 24 24\" id=\"activeDevices\">\n <path id=\"activeDevices\" fill=\"currentColor\" d=\"M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z\" />\n </svg>\n </div>\n <div class='value error_software_failed_count' id=\"activeDevices\">\n ${updatingDevicesNumber:0}\n </div> \n <script type=\"text/javascript\">\n function init() {\n var counter = $('.error_software_failed_count');\n var value = +counter.text();\n if(value) {\n counter.css('color', '#D93025');\n }\n };\n init();\n </script>\n <div class='description' id=\"activeDevices\">\n Device Failed\n </div>\n </div>\n</div>",
  761 + "cardCss": ".card {\n width: 100%;\n height: 100%;\n border: 1px solid #E0E0E0;\n box-sizing: border-box;\n}\n\n.card .content {\n padding: 20px 10px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n box-sizing: border-box;\n}\n\n.card .container-svg {\n height: 40px;\n width: 40px;\n}\n\n.card .value {\n margin: 18px 0 5px;\n font-weight: 500;\n font-size: 3em;\n line-height: 1.1em;\n text-align: center;\n letter-spacing: -0.02em;\n color: #333333;\n}\n\n.card .description {\n font-size: 1em;\n line-height: 1.1em;\n color: #000000;\n opacity: 0.6;\n text-align: center;\n letter-spacing: -0.02em;\n}\n\n@media (min-width: 960px) and (max-width: 1200px) {\n .card .container-svg {\n height: 28px;\n width: 28px;\n }\n \n .card .value {\n margin: 12px 0 5px;\n font-size: 2em;\n line-height: 1;\n }\n \n .card .description {\n font-size: 0.8em;\n line-height: 1;\n }\n}"
  762 + },
  763 + "title": "New HTML Value Card",
  764 + "dropShadow": true,
  765 + "enableFullscreen": false,
  766 + "widgetStyle": {},
  767 + "titleStyle": {
  768 + "fontSize": "16px",
  769 + "fontWeight": 400
  770 + },
  771 + "useDashboardTimewindow": true,
  772 + "showLegend": false,
  773 + "actions": {
  774 + "elementClick": [
  775 + {
  776 + "name": "activeDevices",
  777 + "icon": "more_horiz",
  778 + "type": "openDashboardState",
  779 + "targetDashboardStateId": "device_error",
  780 + "setEntityId": false,
  781 + "stateEntityParamName": null,
  782 + "openInSeparateDialog": false,
  783 + "dialogTitle": "",
  784 + "dialogHideDashboardToolbar": true,
  785 + "dialogWidth": null,
  786 + "dialogHeight": null,
  787 + "openRightLayout": false,
  788 + "id": "0b3d2887-9929-84d5-3795-0763dca15cba"
  789 + }
  790 + ]
  791 + },
  792 + "showTitleIcon": false,
  793 + "titleIcon": null,
  794 + "iconColor": "rgba(0, 0, 0, 0.87)",
  795 + "iconSize": "24px",
  796 + "titleTooltip": "",
  797 + "enableDataExport": false,
  798 + "displayTimewindow": true
  799 + },
  800 + "id": "77b10144-b904-edd5-8c7c-8fb75616c6d8"
  801 + },
  802 + "21be08bb-ec90-f760-ad6f-e7678f12c401": {
  803 + "isSystemType": true,
  804 + "bundleAlias": "cards",
  805 + "typeAlias": "entities_table",
  806 + "type": "latest",
  807 + "title": "New widget",
  808 + "image": null,
  809 + "description": null,
  810 + "sizeX": 7.5,
  811 + "sizeY": 6.5,
  812 + "config": {
  813 + "timewindow": {
  814 + "realtime": {
  815 + "interval": 1000,
  816 + "timewindowMs": 86400000
  817 + },
  818 + "aggregation": {
  819 + "type": "NONE",
  820 + "limit": 200
  821 + }
  822 + },
  823 + "showTitle": true,
  824 + "backgroundColor": "rgb(255, 255, 255)",
  825 + "color": "rgba(0, 0, 0, 0.87)",
  826 + "padding": "4px",
  827 + "settings": {
  828 + "enableSearch": true,
  829 + "displayPagination": true,
  830 + "defaultPageSize": 10,
  831 + "defaultSortOrder": "entityLabel",
  832 + "displayEntityName": false,
  833 + "displayEntityType": false,
  834 + "enableSelectColumnDisplay": false,
  835 + "enableStickyHeader": true,
  836 + "enableStickyAction": true,
  837 + "entitiesTitle": "Devices",
  838 + "displayEntityLabel": true,
  839 + "entityLabelColumnTitle": "Device"
  840 + },
  841 + "title": "New Entities table",
  842 + "dropShadow": true,
  843 + "enableFullscreen": true,
  844 + "titleStyle": {
  845 + "fontSize": "16px",
  846 + "fontWeight": 400,
  847 + "padding": "5px 10px 5px 10px"
  848 + },
  849 + "useDashboardTimewindow": false,
  850 + "showLegend": false,
  851 + "datasources": [
  852 + {
  853 + "type": "entity",
  854 + "name": null,
  855 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  856 + "filterId": "19a0ad1c-b31d-4a29-9d7b-5d87e2a8ea6e",
  857 + "dataKeys": [
  858 + {
  859 + "name": "current_sw_title",
  860 + "type": "timeseries",
  861 + "label": "Current SW title",
  862 + "color": "#2196f3",
  863 + "settings": {
  864 + "columnWidth": "0px",
  865 + "useCellStyleFunction": false,
  866 + "cellStyleFunction": "",
  867 + "useCellContentFunction": false,
  868 + "defaultColumnVisibility": "visible",
  869 + "columnSelectionToDisplay": "enabled"
  870 + },
  871 + "_hash": 0.09545533885166413,
  872 + "units": null,
  873 + "decimals": null,
  874 + "funcBody": null,
  875 + "usePostProcessing": null,
  876 + "postFuncBody": null
  877 + },
  878 + {
  879 + "name": "current_sw_version",
  880 + "type": "timeseries",
  881 + "label": "Current SW version",
  882 + "color": "#4caf50",
  883 + "settings": {
  884 + "columnWidth": "0px",
  885 + "useCellStyleFunction": false,
  886 + "cellStyleFunction": "",
  887 + "useCellContentFunction": false,
  888 + "defaultColumnVisibility": "visible",
  889 + "columnSelectionToDisplay": "enabled"
  890 + },
  891 + "_hash": 0.7206056602328659,
  892 + "units": null,
  893 + "decimals": null,
  894 + "funcBody": null,
  895 + "usePostProcessing": null,
  896 + "postFuncBody": null
  897 + },
  898 + {
  899 + "name": "target_sw_title",
  900 + "type": "timeseries",
  901 + "label": "Target SW title",
  902 + "color": "#ffc107",
  903 + "settings": {
  904 + "columnWidth": "0px",
  905 + "useCellStyleFunction": false,
  906 + "cellStyleFunction": "",
  907 + "useCellContentFunction": false,
  908 + "defaultColumnVisibility": "visible",
  909 + "columnSelectionToDisplay": "enabled"
  910 + },
  911 + "_hash": 0.9934225682766313,
  912 + "units": null,
  913 + "decimals": null,
  914 + "funcBody": null,
  915 + "usePostProcessing": null,
  916 + "postFuncBody": null
  917 + },
  918 + {
  919 + "name": "target_sw_version",
  920 + "type": "timeseries",
  921 + "label": "Target SW version",
  922 + "color": "#607d8b",
  923 + "settings": {
  924 + "columnWidth": "0px",
  925 + "useCellStyleFunction": false,
  926 + "cellStyleFunction": "",
  927 + "useCellContentFunction": false,
  928 + "cellContentFunction": "",
  929 + "defaultColumnVisibility": "visible",
  930 + "columnSelectionToDisplay": "enabled"
  931 + },
  932 + "_hash": 0.5251724416842531,
  933 + "units": null,
  934 + "decimals": null,
  935 + "funcBody": null,
  936 + "usePostProcessing": null,
  937 + "postFuncBody": null
  938 + },
  939 + {
  940 + "name": "target_sw_ts",
  941 + "type": "timeseries",
  942 + "label": "Target SW set time",
  943 + "color": "#e91e63",
  944 + "settings": {
  945 + "columnWidth": "0px",
  946 + "useCellStyleFunction": false,
  947 + "cellStyleFunction": "",
  948 + "useCellContentFunction": true,
  949 + "defaultColumnVisibility": "visible",
  950 + "columnSelectionToDisplay": "enabled",
  951 + "cellContentFunction": "if (value !== '') {\n return ctx.date.transform(value, 'yyyy-MM-dd HH:mm:ss');\n}\nreturn '';"
  952 + },
  953 + "_hash": 0.31823244858578237,
  954 + "units": null,
  955 + "decimals": null,
  956 + "funcBody": null,
  957 + "usePostProcessing": null,
  958 + "postFuncBody": null
  959 + },
  960 + {
  961 + "name": "sw_state",
  962 + "type": "timeseries",
  963 + "label": "Progress",
  964 + "color": "#9c27b0",
  965 + "settings": {
  966 + "columnWidth": "30%",
  967 + "useCellStyleFunction": true,
  968 + "useCellContentFunction": true,
  969 + "defaultColumnVisibility": "visible",
  970 + "columnSelectionToDisplay": "enabled",
  971 + "cellStyleFunction": "return {\n 'padding-right': '30px'\n}",
  972 + "cellContentFunction": "if (value !== '') {\n var mapProgress = {\n 'QUEUED': 0,\n 'INITIATED': 5,\n 'DOWNLOADING': 10,\n 'DOWNLOADED': 55,\n 'VERIFIED': 60,\n 'UPDATING': 70,\n 'FAILED': 99,\n 'UPDATED': 100\n }\n var color = 'mat-primary';\n var progress = mapProgress[value];\n if (value == 'FAILED') {\n color = 'mat-accent';\n }\n return `<mat-progress-bar style=\"height: 8px\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" tabindex=\"-1\" mode=\"determinate\" value=\"${progress}\" class=\"mat-progress-bar ${color}\" aria-valuenow=\"${progress}\"><div aria-hidden=\"true\"><svg width=\"100%\" height=\"8\" focusable=\"false\" class=\"mat-progress-bar-background mat-progress-bar-element\"><defs><pattern x=\"4\" y=\"0\" width=\"8\" height=\"4\" patternUnits=\"userSpaceOnUse\" id=\"mat-progress-bar-0\"><circle cx=\"2\" cy=\"2\" r=\"2\"></circle></pattern></defs><rect width=\"100%\" height=\"100%\" fill=\"url(\"/components/progress-bar/overview#mat-progress-bar-0\")\"></rect></svg><div class=\"mat-progress-bar-buffer mat-progress-bar-element\"></div><div class=\"mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element\" style=\"transform: scale3d(${progress / 100}, 1, 1);\"></div><div class=\"mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element\"></div></div></mat-progress-bar>`;\n}"
  973 + },
  974 + "_hash": 0.8174211757846257,
  975 + "units": null,
  976 + "decimals": null,
  977 + "funcBody": null,
  978 + "usePostProcessing": null,
  979 + "postFuncBody": null
  980 + },
  981 + {
  982 + "name": "sw_state",
  983 + "type": "timeseries",
  984 + "label": "Status",
  985 + "color": "#f44336",
  986 + "settings": {
  987 + "columnWidth": "130px",
  988 + "useCellStyleFunction": true,
  989 + "useCellContentFunction": true,
  990 + "defaultColumnVisibility": "visible",
  991 + "columnSelectionToDisplay": "enabled",
  992 + "cellStyleFunction": "if (value == 'FAILED') {\n return {'color' : '#D93025'};\n}\nreturn {};",
  993 + "cellContentFunction": "function icon(value) {\n if (value == 'QUEUED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000;\"><svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z\" /></svg></mat-icon>';\n }\n if (value == 'INITIATED' || value == 'DOWNLOADING' || value == 'DOWNLOADED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.74 2.1951C11.63 1.2876 10.2575 0.687598 8.75 0.537598V2.0526C9.845 2.1876 10.8425 2.6226 11.675 3.2676L12.74 2.1951ZM13.9475 7.2501H15.4625C15.3125 5.7426 14.7125 4.3701 13.805 3.2601L12.7325 4.3251C13.3775 5.1576 13.8125 6.1551 13.9475 7.2501ZM12.7325 11.6751L13.805 12.7476C14.7125 11.6376 15.3125 10.2576 15.4625 8.7576H13.9475C13.8125 9.8451 13.3775 10.8426 12.7325 11.6751ZM8.75 13.9476V15.4626C10.2575 15.3126 11.63 14.7126 12.74 13.8051L11.6675 12.7326C10.8425 13.3776 9.845 13.8126 8.75 13.9476ZM8.75 8.0001V4.2501H7.25V8.0001H4.25L8 11.7501L11.75 8.0001H8.75ZM7.25 13.9476V15.4626C3.4625 15.0876 0.5 11.8926 0.5 8.0001C0.5 4.1076 3.4625 0.912598 7.25 0.537598V2.0526C4.2875 2.4201 2 4.9401 2 8.0001C2 11.0601 4.2875 13.5801 7.25 13.9476Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'VERIFIED' || value == 'UPDATING' ) {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\">update</mat-icon>';\n }\n if (value == 'UPDATED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg style=\"width:22px;height:22px\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/><path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'FAILED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #D93025\">warning</mat-icon>';\n }\n return '';\n}\nfunction capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nreturn icon(value) + '<span style=\"vertical-align: super;padding-left: 8px;\">' + capitalize(value) + '</span>';"
  994 + },
  995 + "_hash": 0.7764426948615217,
  996 + "units": null,
  997 + "decimals": null,
  998 + "funcBody": null,
  999 + "usePostProcessing": null,
  1000 + "postFuncBody": null
  1001 + },
  1002 + {
  1003 + "name": "sw_checksum",
  1004 + "type": "attribute",
  1005 + "label": "sw_checksum",
  1006 + "color": "#3f51b5",
  1007 + "settings": {
  1008 + "columnWidth": "0px",
  1009 + "useCellStyleFunction": false,
  1010 + "cellStyleFunction": "",
  1011 + "useCellContentFunction": false,
  1012 + "defaultColumnVisibility": "hidden",
  1013 + "columnSelectionToDisplay": "disabled"
  1014 + },
  1015 + "_hash": 0.5594087842471693,
  1016 + "units": null,
  1017 + "decimals": null,
  1018 + "funcBody": null,
  1019 + "usePostProcessing": null,
  1020 + "postFuncBody": null
  1021 + },
  1022 + {
  1023 + "name": "sw_url",
  1024 + "type": "attribute",
  1025 + "label": "sw_url",
  1026 + "color": "#e91e63",
  1027 + "settings": {
  1028 + "columnWidth": "0px",
  1029 + "useCellStyleFunction": false,
  1030 + "cellStyleFunction": "",
  1031 + "useCellContentFunction": false,
  1032 + "cellContentFunction": "",
  1033 + "defaultColumnVisibility": "hidden",
  1034 + "columnSelectionToDisplay": "disabled"
  1035 + },
  1036 + "_hash": 0.3355829384124256,
  1037 + "units": null,
  1038 + "decimals": null,
  1039 + "funcBody": null,
  1040 + "usePostProcessing": null,
  1041 + "postFuncBody": null
  1042 + }
  1043 + ]
  1044 + }
  1045 + ],
  1046 + "actions": {
  1047 + "actionCellButton": [
  1048 + {
  1049 + "name": "History software update",
  1050 + "icon": "history",
  1051 + "type": "openDashboardState",
  1052 + "targetDashboardStateId": "device_software_history",
  1053 + "setEntityId": true,
  1054 + "stateEntityParamName": null,
  1055 + "openInSeparateDialog": false,
  1056 + "dialogTitle": "",
  1057 + "dialogHideDashboardToolbar": true,
  1058 + "dialogWidth": null,
  1059 + "dialogHeight": null,
  1060 + "openRightLayout": false,
  1061 + "id": "98a1406c-3301-bc2f-2c5d-d637ce3b663b"
  1062 + },
  1063 + {
  1064 + "name": "Edit software",
  1065 + "icon": "edit",
  1066 + "type": "customPretty",
  1067 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit software {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n type=\"SOFTWARE\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"softwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1068 + "customCss": "form {\n min-width: 300px !important;\n}",
  1069 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n softwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n softwareId: vm.entity.softwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.softwareId = formValues.softwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
  1070 + "customResources": [],
  1071 + "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
  1072 + },
  1073 + {
  1074 + "name": "Download software",
  1075 + "icon": "file_download",
  1076 + "type": "custom",
  1077 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceSoftware();\n\nfunction getDeviceSoftware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.softwareId !== null) {\n otaPackageService.downloadOtaPackage(data.softwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.softwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.softwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1078 + "id": "12533058-42f6-e75f-620c-219c48d01ec0"
  1079 + },
  1080 + {
  1081 + "name": "Copy checksum/URL",
  1082 + "icon": "content_copy",
  1083 + "type": "custom",
  1084 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_checksum');\nvar checksum = data.data[0][1];\nconsole.log(checksum);\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Software checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Software direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1085 + "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
  1086 + }
  1087 + ]
  1088 + },
  1089 + "showTitleIcon": false,
  1090 + "iconColor": "rgba(0, 0, 0, 0.87)",
  1091 + "iconSize": "24px",
  1092 + "titleTooltip": "",
  1093 + "widgetStyle": {}
  1094 + },
  1095 + "row": 0,
  1096 + "col": 0,
  1097 + "id": "21be08bb-ec90-f760-ad6f-e7678f12c401"
  1098 + },
  1099 + "e8280043-d3dc-7acb-c2ff-a4522972ff91": {
  1100 + "isSystemType": true,
  1101 + "bundleAlias": "cards",
  1102 + "typeAlias": "entities_table",
  1103 + "type": "latest",
  1104 + "title": "New widget",
  1105 + "image": null,
  1106 + "description": null,
  1107 + "sizeX": 7.5,
  1108 + "sizeY": 6.5,
  1109 + "config": {
  1110 + "timewindow": {
  1111 + "realtime": {
  1112 + "interval": 1000,
  1113 + "timewindowMs": 86400000
  1114 + },
  1115 + "aggregation": {
  1116 + "type": "NONE",
  1117 + "limit": 200
  1118 + }
  1119 + },
  1120 + "showTitle": true,
  1121 + "backgroundColor": "rgb(255, 255, 255)",
  1122 + "color": "rgba(0, 0, 0, 0.87)",
  1123 + "padding": "4px",
  1124 + "settings": {
  1125 + "enableSearch": true,
  1126 + "displayPagination": true,
  1127 + "defaultPageSize": 10,
  1128 + "defaultSortOrder": "entityLabel",
  1129 + "displayEntityName": false,
  1130 + "displayEntityType": false,
  1131 + "enableSelectColumnDisplay": false,
  1132 + "enableStickyHeader": true,
  1133 + "enableStickyAction": true,
  1134 + "entitiesTitle": "Devices",
  1135 + "displayEntityLabel": true,
  1136 + "entityLabelColumnTitle": "Device"
  1137 + },
  1138 + "title": "New Entities table",
  1139 + "dropShadow": true,
  1140 + "enableFullscreen": true,
  1141 + "titleStyle": {
  1142 + "fontSize": "16px",
  1143 + "fontWeight": 400,
  1144 + "padding": "5px 10px 5px 10px"
  1145 + },
  1146 + "useDashboardTimewindow": false,
  1147 + "showLegend": false,
  1148 + "datasources": [
  1149 + {
  1150 + "type": "entity",
  1151 + "name": null,
  1152 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  1153 + "filterId": "579f0468-9ce9-7e3e-b34c-88dd3de59897",
  1154 + "dataKeys": [
  1155 + {
  1156 + "name": "current_sw_title",
  1157 + "type": "timeseries",
  1158 + "label": "Current SW title",
  1159 + "color": "#2196f3",
  1160 + "settings": {
  1161 + "columnWidth": "0px",
  1162 + "useCellStyleFunction": false,
  1163 + "cellStyleFunction": "",
  1164 + "useCellContentFunction": false,
  1165 + "defaultColumnVisibility": "visible",
  1166 + "columnSelectionToDisplay": "enabled"
  1167 + },
  1168 + "_hash": 0.09545533885166413,
  1169 + "units": null,
  1170 + "decimals": null,
  1171 + "funcBody": null,
  1172 + "usePostProcessing": null,
  1173 + "postFuncBody": null
  1174 + },
  1175 + {
  1176 + "name": "current_sw_version",
  1177 + "type": "timeseries",
  1178 + "label": "Current SW version",
  1179 + "color": "#4caf50",
  1180 + "settings": {
  1181 + "columnWidth": "0px",
  1182 + "useCellStyleFunction": false,
  1183 + "cellStyleFunction": "",
  1184 + "useCellContentFunction": false,
  1185 + "defaultColumnVisibility": "visible",
  1186 + "columnSelectionToDisplay": "enabled"
  1187 + },
  1188 + "_hash": 0.7206056602328659,
  1189 + "units": null,
  1190 + "decimals": null,
  1191 + "funcBody": null,
  1192 + "usePostProcessing": null,
  1193 + "postFuncBody": null
  1194 + },
  1195 + {
  1196 + "name": "target_sw_title",
  1197 + "type": "timeseries",
  1198 + "label": "Target SW title",
  1199 + "color": "#ffc107",
  1200 + "settings": {
  1201 + "columnWidth": "0px",
  1202 + "useCellStyleFunction": false,
  1203 + "cellStyleFunction": "",
  1204 + "useCellContentFunction": false,
  1205 + "defaultColumnVisibility": "visible",
  1206 + "columnSelectionToDisplay": "enabled"
  1207 + },
  1208 + "_hash": 0.9934225682766313,
  1209 + "units": null,
  1210 + "decimals": null,
  1211 + "funcBody": null,
  1212 + "usePostProcessing": null,
  1213 + "postFuncBody": null
  1214 + },
  1215 + {
  1216 + "name": "target_sw_version",
  1217 + "type": "timeseries",
  1218 + "label": "Target SW version",
  1219 + "color": "#607d8b",
  1220 + "settings": {
  1221 + "columnWidth": "0px",
  1222 + "useCellStyleFunction": false,
  1223 + "cellStyleFunction": "",
  1224 + "useCellContentFunction": false,
  1225 + "cellContentFunction": "",
  1226 + "defaultColumnVisibility": "visible",
  1227 + "columnSelectionToDisplay": "enabled"
  1228 + },
  1229 + "_hash": 0.5251724416842531,
  1230 + "units": null,
  1231 + "decimals": null,
  1232 + "funcBody": null,
  1233 + "usePostProcessing": null,
  1234 + "postFuncBody": null
  1235 + },
  1236 + {
  1237 + "name": "target_sw_ts",
  1238 + "type": "timeseries",
  1239 + "label": "Target SW set time",
  1240 + "color": "#e91e63",
  1241 + "settings": {
  1242 + "columnWidth": "0px",
  1243 + "useCellStyleFunction": false,
  1244 + "cellStyleFunction": "",
  1245 + "useCellContentFunction": true,
  1246 + "defaultColumnVisibility": "visible",
  1247 + "columnSelectionToDisplay": "enabled",
  1248 + "cellContentFunction": "if (value !== '') {\n return ctx.date.transform(value, 'yyyy-MM-dd HH:mm:ss');\n}\nreturn '';"
  1249 + },
  1250 + "_hash": 0.31823244858578237,
  1251 + "units": null,
  1252 + "decimals": null,
  1253 + "funcBody": null,
  1254 + "usePostProcessing": null,
  1255 + "postFuncBody": null
  1256 + },
  1257 + {
  1258 + "name": "sw_state",
  1259 + "type": "timeseries",
  1260 + "label": "Progress",
  1261 + "color": "#9c27b0",
  1262 + "settings": {
  1263 + "columnWidth": "30%",
  1264 + "useCellStyleFunction": true,
  1265 + "useCellContentFunction": true,
  1266 + "defaultColumnVisibility": "visible",
  1267 + "columnSelectionToDisplay": "enabled",
  1268 + "cellStyleFunction": "return {\n 'padding-right': '30px'\n}",
  1269 + "cellContentFunction": "if (value !== '') {\n var mapProgress = {\n 'QUEUED': 0,\n 'INITIATED': 5,\n 'DOWNLOADING': 10,\n 'DOWNLOADED': 55,\n 'VERIFIED': 60,\n 'UPDATING': 70,\n 'FAILED': 99,\n 'UPDATED': 100\n }\n var color = 'mat-primary';\n var progress = mapProgress[value];\n if (value == 'FAILED') {\n color = 'mat-accent';\n }\n return `<mat-progress-bar style=\"height: 8px\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" tabindex=\"-1\" mode=\"determinate\" value=\"${progress}\" class=\"mat-progress-bar ${color}\" aria-valuenow=\"${progress}\"><div aria-hidden=\"true\"><svg width=\"100%\" height=\"8\" focusable=\"false\" class=\"mat-progress-bar-background mat-progress-bar-element\"><defs><pattern x=\"4\" y=\"0\" width=\"8\" height=\"4\" patternUnits=\"userSpaceOnUse\" id=\"mat-progress-bar-0\"><circle cx=\"2\" cy=\"2\" r=\"2\"></circle></pattern></defs><rect width=\"100%\" height=\"100%\" fill=\"url(\"/components/progress-bar/overview#mat-progress-bar-0\")\"></rect></svg><div class=\"mat-progress-bar-buffer mat-progress-bar-element\"></div><div class=\"mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element\" style=\"transform: scale3d(${progress / 100}, 1, 1);\"></div><div class=\"mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element\"></div></div></mat-progress-bar>`;\n}"
  1270 + },
  1271 + "_hash": 0.8174211757846257,
  1272 + "units": null,
  1273 + "decimals": null,
  1274 + "funcBody": null,
  1275 + "usePostProcessing": null,
  1276 + "postFuncBody": null
  1277 + },
  1278 + {
  1279 + "name": "sw_state",
  1280 + "type": "timeseries",
  1281 + "label": "Status",
  1282 + "color": "#f44336",
  1283 + "settings": {
  1284 + "columnWidth": "130px",
  1285 + "useCellStyleFunction": true,
  1286 + "useCellContentFunction": true,
  1287 + "defaultColumnVisibility": "visible",
  1288 + "columnSelectionToDisplay": "enabled",
  1289 + "cellStyleFunction": "if (value == 'FAILED') {\n return {'color' : '#D93025'};\n}\nreturn {};",
  1290 + "cellContentFunction": "function icon(value) {\n if (value == 'QUEUED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000;\"><svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z\" /></svg></mat-icon>';\n }\n if (value == 'INITIATED' || value == 'DOWNLOADING' || value == 'DOWNLOADED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.74 2.1951C11.63 1.2876 10.2575 0.687598 8.75 0.537598V2.0526C9.845 2.1876 10.8425 2.6226 11.675 3.2676L12.74 2.1951ZM13.9475 7.2501H15.4625C15.3125 5.7426 14.7125 4.3701 13.805 3.2601L12.7325 4.3251C13.3775 5.1576 13.8125 6.1551 13.9475 7.2501ZM12.7325 11.6751L13.805 12.7476C14.7125 11.6376 15.3125 10.2576 15.4625 8.7576H13.9475C13.8125 9.8451 13.3775 10.8426 12.7325 11.6751ZM8.75 13.9476V15.4626C10.2575 15.3126 11.63 14.7126 12.74 13.8051L11.6675 12.7326C10.8425 13.3776 9.845 13.8126 8.75 13.9476ZM8.75 8.0001V4.2501H7.25V8.0001H4.25L8 11.7501L11.75 8.0001H8.75ZM7.25 13.9476V15.4626C3.4625 15.0876 0.5 11.8926 0.5 8.0001C0.5 4.1076 3.4625 0.912598 7.25 0.537598V2.0526C4.2875 2.4201 2 4.9401 2 8.0001C2 11.0601 4.2875 13.5801 7.25 13.9476Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'VERIFIED' || value == 'UPDATING' ) {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\">update</mat-icon>';\n }\n if (value == 'UPDATED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg style=\"width:22px;height:22px\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/><path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'FAILED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #D93025\">warning</mat-icon>';\n }\n return '';\n}\nfunction capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nreturn icon(value) + '<span style=\"vertical-align: super;padding-left: 8px;\">' + capitalize(value) + '</span>';"
  1291 + },
  1292 + "_hash": 0.7764426948615217,
  1293 + "units": null,
  1294 + "decimals": null,
  1295 + "funcBody": null,
  1296 + "usePostProcessing": null,
  1297 + "postFuncBody": null
  1298 + },
  1299 + {
  1300 + "name": "sw_checksum",
  1301 + "type": "attribute",
  1302 + "label": "sw_checksum",
  1303 + "color": "#3f51b5",
  1304 + "settings": {
  1305 + "columnWidth": "0px",
  1306 + "useCellStyleFunction": false,
  1307 + "cellStyleFunction": "",
  1308 + "useCellContentFunction": false,
  1309 + "defaultColumnVisibility": "hidden",
  1310 + "columnSelectionToDisplay": "disabled"
  1311 + },
  1312 + "_hash": 0.5594087842471693,
  1313 + "units": null,
  1314 + "decimals": null,
  1315 + "funcBody": null,
  1316 + "usePostProcessing": null,
  1317 + "postFuncBody": null
  1318 + },
  1319 + {
  1320 + "name": "sw_url",
  1321 + "type": "attribute",
  1322 + "label": "sw_url",
  1323 + "color": "#e91e63",
  1324 + "settings": {
  1325 + "columnWidth": "0px",
  1326 + "useCellStyleFunction": false,
  1327 + "cellStyleFunction": "",
  1328 + "useCellContentFunction": false,
  1329 + "cellContentFunction": "",
  1330 + "defaultColumnVisibility": "hidden",
  1331 + "columnSelectionToDisplay": "disabled"
  1332 + },
  1333 + "_hash": 0.3355829384124256,
  1334 + "units": null,
  1335 + "decimals": null,
  1336 + "funcBody": null,
  1337 + "usePostProcessing": null,
  1338 + "postFuncBody": null
  1339 + }
  1340 + ]
  1341 + }
  1342 + ],
  1343 + "actions": {
  1344 + "actionCellButton": [
  1345 + {
  1346 + "name": "History software update",
  1347 + "icon": "history",
  1348 + "type": "openDashboardState",
  1349 + "targetDashboardStateId": "device_software_history",
  1350 + "setEntityId": true,
  1351 + "stateEntityParamName": null,
  1352 + "openInSeparateDialog": false,
  1353 + "dialogTitle": "",
  1354 + "dialogHideDashboardToolbar": true,
  1355 + "dialogWidth": null,
  1356 + "dialogHeight": null,
  1357 + "openRightLayout": false,
  1358 + "id": "98a1406c-3301-bc2f-2c5d-d637ce3b663b"
  1359 + },
  1360 + {
  1361 + "name": "Edit software",
  1362 + "icon": "edit",
  1363 + "type": "customPretty",
  1364 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit software {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n type=\"SOFTWARE\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"softwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1365 + "customCss": "form {\n min-width: 300px !important;\n}",
  1366 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n softwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n softwareId: vm.entity.softwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.softwareId = formValues.softwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
  1367 + "customResources": [],
  1368 + "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
  1369 + },
  1370 + {
  1371 + "name": "Download software",
  1372 + "icon": "file_download",
  1373 + "type": "custom",
  1374 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceSoftware();\n\nfunction getDeviceSoftware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.softwareId !== null) {\n otaPackageService.downloadOtaPackage(data.softwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.softwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.softwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1375 + "id": "12533058-42f6-e75f-620c-219c48d01ec0"
  1376 + },
  1377 + {
  1378 + "name": "Copy checksum/URL",
  1379 + "icon": "content_copy",
  1380 + "type": "custom",
  1381 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_checksum');\nvar checksum = data.data[0][1];\nconsole.log(checksum);\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Software checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Software direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1382 + "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
  1383 + }
  1384 + ]
  1385 + },
  1386 + "showTitleIcon": false,
  1387 + "iconColor": "rgba(0, 0, 0, 0.87)",
  1388 + "iconSize": "24px",
  1389 + "titleTooltip": "",
  1390 + "widgetStyle": {}
  1391 + },
  1392 + "row": 0,
  1393 + "col": 0,
  1394 + "id": "e8280043-d3dc-7acb-c2ff-a4522972ff91"
  1395 + },
  1396 + "3624013b-378c-f110-5eba-ae95c25a4dcc": {
  1397 + "isSystemType": true,
  1398 + "bundleAlias": "cards",
  1399 + "typeAlias": "entities_table",
  1400 + "type": "latest",
  1401 + "title": "New widget",
  1402 + "image": null,
  1403 + "description": null,
  1404 + "sizeX": 7.5,
  1405 + "sizeY": 6.5,
  1406 + "config": {
  1407 + "timewindow": {
  1408 + "realtime": {
  1409 + "interval": 1000,
  1410 + "timewindowMs": 86400000
  1411 + },
  1412 + "aggregation": {
  1413 + "type": "NONE",
  1414 + "limit": 200
  1415 + }
  1416 + },
  1417 + "showTitle": true,
  1418 + "backgroundColor": "rgb(255, 255, 255)",
  1419 + "color": "rgba(0, 0, 0, 0.87)",
  1420 + "padding": "4px",
  1421 + "settings": {
  1422 + "enableSearch": true,
  1423 + "displayPagination": true,
  1424 + "defaultPageSize": 10,
  1425 + "defaultSortOrder": "entityLabel",
  1426 + "displayEntityName": false,
  1427 + "displayEntityType": false,
  1428 + "enableSelectColumnDisplay": false,
  1429 + "enableStickyHeader": true,
  1430 + "enableStickyAction": true,
  1431 + "entitiesTitle": "Devices",
  1432 + "displayEntityLabel": true,
  1433 + "entityLabelColumnTitle": "Device"
  1434 + },
  1435 + "title": "New Entities table",
  1436 + "dropShadow": true,
  1437 + "enableFullscreen": true,
  1438 + "titleStyle": {
  1439 + "fontSize": "16px",
  1440 + "fontWeight": 400,
  1441 + "padding": "5px 10px 5px 10px"
  1442 + },
  1443 + "useDashboardTimewindow": false,
  1444 + "showLegend": false,
  1445 + "datasources": [
  1446 + {
  1447 + "type": "entity",
  1448 + "name": null,
  1449 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  1450 + "filterId": "bdbc6ea1-95a7-3912-341a-58dc7704a00f",
  1451 + "dataKeys": [
  1452 + {
  1453 + "name": "current_sw_title",
  1454 + "type": "timeseries",
  1455 + "label": "Current SW title",
  1456 + "color": "#2196f3",
  1457 + "settings": {
  1458 + "columnWidth": "0px",
  1459 + "useCellStyleFunction": false,
  1460 + "cellStyleFunction": "",
  1461 + "useCellContentFunction": false,
  1462 + "defaultColumnVisibility": "visible",
  1463 + "columnSelectionToDisplay": "enabled"
  1464 + },
  1465 + "_hash": 0.09545533885166413,
  1466 + "units": null,
  1467 + "decimals": null,
  1468 + "funcBody": null,
  1469 + "usePostProcessing": null,
  1470 + "postFuncBody": null
  1471 + },
  1472 + {
  1473 + "name": "current_sw_version",
  1474 + "type": "timeseries",
  1475 + "label": "Current SW version",
  1476 + "color": "#4caf50",
  1477 + "settings": {
  1478 + "columnWidth": "0px",
  1479 + "useCellStyleFunction": false,
  1480 + "cellStyleFunction": "",
  1481 + "useCellContentFunction": false,
  1482 + "defaultColumnVisibility": "visible",
  1483 + "columnSelectionToDisplay": "enabled"
  1484 + },
  1485 + "_hash": 0.7206056602328659,
  1486 + "units": null,
  1487 + "decimals": null,
  1488 + "funcBody": null,
  1489 + "usePostProcessing": null,
  1490 + "postFuncBody": null
  1491 + },
  1492 + {
  1493 + "name": "target_sw_title",
  1494 + "type": "timeseries",
  1495 + "label": "Target SW title",
  1496 + "color": "#ffc107",
  1497 + "settings": {
  1498 + "columnWidth": "0px",
  1499 + "useCellStyleFunction": false,
  1500 + "cellStyleFunction": "",
  1501 + "useCellContentFunction": false,
  1502 + "defaultColumnVisibility": "visible",
  1503 + "columnSelectionToDisplay": "enabled"
  1504 + },
  1505 + "_hash": 0.9934225682766313,
  1506 + "units": null,
  1507 + "decimals": null,
  1508 + "funcBody": null,
  1509 + "usePostProcessing": null,
  1510 + "postFuncBody": null
  1511 + },
  1512 + {
  1513 + "name": "target_sw_version",
  1514 + "type": "timeseries",
  1515 + "label": "Target SW version",
  1516 + "color": "#607d8b",
  1517 + "settings": {
  1518 + "columnWidth": "0px",
  1519 + "useCellStyleFunction": false,
  1520 + "cellStyleFunction": "",
  1521 + "useCellContentFunction": false,
  1522 + "cellContentFunction": "",
  1523 + "defaultColumnVisibility": "visible",
  1524 + "columnSelectionToDisplay": "enabled"
  1525 + },
  1526 + "_hash": 0.5251724416842531,
  1527 + "units": null,
  1528 + "decimals": null,
  1529 + "funcBody": null,
  1530 + "usePostProcessing": null,
  1531 + "postFuncBody": null
  1532 + },
  1533 + {
  1534 + "name": "target_sw_ts",
  1535 + "type": "timeseries",
  1536 + "label": "Target SW set time",
  1537 + "color": "#e91e63",
  1538 + "settings": {
  1539 + "columnWidth": "0px",
  1540 + "useCellStyleFunction": false,
  1541 + "cellStyleFunction": "",
  1542 + "useCellContentFunction": true,
  1543 + "defaultColumnVisibility": "visible",
  1544 + "columnSelectionToDisplay": "enabled",
  1545 + "cellContentFunction": "if (value !== '') {\n return ctx.date.transform(value, 'yyyy-MM-dd HH:mm:ss');\n}\nreturn '';"
  1546 + },
  1547 + "_hash": 0.31823244858578237,
  1548 + "units": null,
  1549 + "decimals": null,
  1550 + "funcBody": null,
  1551 + "usePostProcessing": null,
  1552 + "postFuncBody": null
  1553 + },
  1554 + {
  1555 + "name": "sw_state",
  1556 + "type": "timeseries",
  1557 + "label": "Progress",
  1558 + "color": "#9c27b0",
  1559 + "settings": {
  1560 + "columnWidth": "30%",
  1561 + "useCellStyleFunction": true,
  1562 + "useCellContentFunction": true,
  1563 + "defaultColumnVisibility": "visible",
  1564 + "columnSelectionToDisplay": "enabled",
  1565 + "cellStyleFunction": "return {\n 'padding-right': '30px'\n}",
  1566 + "cellContentFunction": "if (value !== '') {\n var mapProgress = {\n 'QUEUED': 0,\n 'INITIATED': 5,\n 'DOWNLOADING': 10,\n 'DOWNLOADED': 55,\n 'VERIFIED': 60,\n 'UPDATING': 70,\n 'FAILED': 99,\n 'UPDATED': 100\n }\n var color = 'mat-primary';\n var progress = mapProgress[value];\n if (value == 'FAILED') {\n color = 'mat-accent';\n }\n return `<mat-progress-bar style=\"height: 8px\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" tabindex=\"-1\" mode=\"determinate\" value=\"${progress}\" class=\"mat-progress-bar ${color}\" aria-valuenow=\"${progress}\"><div aria-hidden=\"true\"><svg width=\"100%\" height=\"8\" focusable=\"false\" class=\"mat-progress-bar-background mat-progress-bar-element\"><defs><pattern x=\"4\" y=\"0\" width=\"8\" height=\"4\" patternUnits=\"userSpaceOnUse\" id=\"mat-progress-bar-0\"><circle cx=\"2\" cy=\"2\" r=\"2\"></circle></pattern></defs><rect width=\"100%\" height=\"100%\" fill=\"url(\"/components/progress-bar/overview#mat-progress-bar-0\")\"></rect></svg><div class=\"mat-progress-bar-buffer mat-progress-bar-element\"></div><div class=\"mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element\" style=\"transform: scale3d(${progress / 100}, 1, 1);\"></div><div class=\"mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element\"></div></div></mat-progress-bar>`;\n}"
  1567 + },
  1568 + "_hash": 0.8174211757846257,
  1569 + "units": null,
  1570 + "decimals": null,
  1571 + "funcBody": null,
  1572 + "usePostProcessing": null,
  1573 + "postFuncBody": null
  1574 + },
  1575 + {
  1576 + "name": "sw_state",
  1577 + "type": "timeseries",
  1578 + "label": "Status",
  1579 + "color": "#f44336",
  1580 + "settings": {
  1581 + "columnWidth": "130px",
  1582 + "useCellStyleFunction": true,
  1583 + "useCellContentFunction": true,
  1584 + "defaultColumnVisibility": "visible",
  1585 + "columnSelectionToDisplay": "enabled",
  1586 + "cellStyleFunction": "if (value == 'FAILED') {\n return {'color' : '#D93025'};\n}\nreturn {};",
  1587 + "cellContentFunction": "function icon(value) {\n if (value == 'QUEUED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000;\"><svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z\" /></svg></mat-icon>';\n }\n if (value == 'INITIATED' || value == 'DOWNLOADING' || value == 'DOWNLOADED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.74 2.1951C11.63 1.2876 10.2575 0.687598 8.75 0.537598V2.0526C9.845 2.1876 10.8425 2.6226 11.675 3.2676L12.74 2.1951ZM13.9475 7.2501H15.4625C15.3125 5.7426 14.7125 4.3701 13.805 3.2601L12.7325 4.3251C13.3775 5.1576 13.8125 6.1551 13.9475 7.2501ZM12.7325 11.6751L13.805 12.7476C14.7125 11.6376 15.3125 10.2576 15.4625 8.7576H13.9475C13.8125 9.8451 13.3775 10.8426 12.7325 11.6751ZM8.75 13.9476V15.4626C10.2575 15.3126 11.63 14.7126 12.74 13.8051L11.6675 12.7326C10.8425 13.3776 9.845 13.8126 8.75 13.9476ZM8.75 8.0001V4.2501H7.25V8.0001H4.25L8 11.7501L11.75 8.0001H8.75ZM7.25 13.9476V15.4626C3.4625 15.0876 0.5 11.8926 0.5 8.0001C0.5 4.1076 3.4625 0.912598 7.25 0.537598V2.0526C4.2875 2.4201 2 4.9401 2 8.0001C2 11.0601 4.2875 13.5801 7.25 13.9476Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'VERIFIED' || value == 'UPDATING' ) {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\">update</mat-icon>';\n }\n if (value == 'UPDATED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg style=\"width:22px;height:22px\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/><path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'FAILED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #D93025\">warning</mat-icon>';\n }\n return '';\n}\nfunction capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nreturn icon(value) + '<span style=\"vertical-align: super;padding-left: 8px;\">' + capitalize(value) + '</span>';"
  1588 + },
  1589 + "_hash": 0.7764426948615217,
  1590 + "units": null,
  1591 + "decimals": null,
  1592 + "funcBody": null,
  1593 + "usePostProcessing": null,
  1594 + "postFuncBody": null
  1595 + },
  1596 + {
  1597 + "name": "sw_checksum",
  1598 + "type": "attribute",
  1599 + "label": "sw_checksum",
  1600 + "color": "#3f51b5",
  1601 + "settings": {
  1602 + "columnWidth": "0px",
  1603 + "useCellStyleFunction": false,
  1604 + "cellStyleFunction": "",
  1605 + "useCellContentFunction": false,
  1606 + "defaultColumnVisibility": "hidden",
  1607 + "columnSelectionToDisplay": "disabled"
  1608 + },
  1609 + "_hash": 0.5594087842471693,
  1610 + "units": null,
  1611 + "decimals": null,
  1612 + "funcBody": null,
  1613 + "usePostProcessing": null,
  1614 + "postFuncBody": null
  1615 + },
  1616 + {
  1617 + "name": "sw_url",
  1618 + "type": "attribute",
  1619 + "label": "sw_url",
  1620 + "color": "#e91e63",
  1621 + "settings": {
  1622 + "columnWidth": "0px",
  1623 + "useCellStyleFunction": false,
  1624 + "cellStyleFunction": "",
  1625 + "useCellContentFunction": false,
  1626 + "cellContentFunction": "",
  1627 + "defaultColumnVisibility": "hidden",
  1628 + "columnSelectionToDisplay": "disabled"
  1629 + },
  1630 + "_hash": 0.3355829384124256,
  1631 + "units": null,
  1632 + "decimals": null,
  1633 + "funcBody": null,
  1634 + "usePostProcessing": null,
  1635 + "postFuncBody": null
  1636 + }
  1637 + ]
  1638 + }
  1639 + ],
  1640 + "actions": {
  1641 + "actionCellButton": [
  1642 + {
  1643 + "name": "History software update",
  1644 + "icon": "history",
  1645 + "type": "openDashboardState",
  1646 + "targetDashboardStateId": "device_software_history",
  1647 + "setEntityId": true,
  1648 + "stateEntityParamName": null,
  1649 + "openInSeparateDialog": false,
  1650 + "dialogTitle": "",
  1651 + "dialogHideDashboardToolbar": true,
  1652 + "dialogWidth": null,
  1653 + "dialogHeight": null,
  1654 + "openRightLayout": false,
  1655 + "id": "98a1406c-3301-bc2f-2c5d-d637ce3b663b"
  1656 + },
  1657 + {
  1658 + "name": "Edit software",
  1659 + "icon": "edit",
  1660 + "type": "customPretty",
  1661 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit software {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n type=\"SOFTWARE\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"softwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1662 + "customCss": "form {\n min-width: 300px !important;\n}",
  1663 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n softwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n softwareId: vm.entity.softwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.softwareId = formValues.softwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
  1664 + "customResources": [],
  1665 + "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
  1666 + },
  1667 + {
  1668 + "name": "Download software",
  1669 + "icon": "file_download",
  1670 + "type": "custom",
  1671 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceSoftware();\n\nfunction getDeviceSoftware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.softwareId !== null) {\n otaPackageService.downloadOtaPackage(data.softwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.softwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.softwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1672 + "id": "12533058-42f6-e75f-620c-219c48d01ec0"
  1673 + },
  1674 + {
  1675 + "name": "Copy checksum/URL",
  1676 + "icon": "content_copy",
  1677 + "type": "custom",
  1678 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_checksum');\nvar checksum = data.data[0][1];\nconsole.log(checksum);\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Software checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Software direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1679 + "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
  1680 + }
  1681 + ]
  1682 + },
  1683 + "showTitleIcon": false,
  1684 + "iconColor": "rgba(0, 0, 0, 0.87)",
  1685 + "iconSize": "24px",
  1686 + "titleTooltip": "",
  1687 + "widgetStyle": {}
  1688 + },
  1689 + "row": 0,
  1690 + "col": 0,
  1691 + "id": "3624013b-378c-f110-5eba-ae95c25a4dcc"
  1692 + },
  1693 + "d2d13e0d-4e71-889f-9343-ad2f0af9f176": {
  1694 + "isSystemType": true,
  1695 + "bundleAlias": "cards",
  1696 + "typeAlias": "entities_table",
  1697 + "type": "latest",
  1698 + "title": "New widget",
  1699 + "image": null,
  1700 + "description": null,
  1701 + "sizeX": 7.5,
  1702 + "sizeY": 6.5,
  1703 + "config": {
  1704 + "timewindow": {
  1705 + "realtime": {
  1706 + "interval": 1000,
  1707 + "timewindowMs": 86400000
  1708 + },
  1709 + "aggregation": {
  1710 + "type": "NONE",
  1711 + "limit": 200
  1712 + }
  1713 + },
  1714 + "showTitle": true,
  1715 + "backgroundColor": "rgb(255, 255, 255)",
  1716 + "color": "rgba(0, 0, 0, 0.87)",
  1717 + "padding": "4px",
  1718 + "settings": {
  1719 + "enableSearch": true,
  1720 + "displayPagination": true,
  1721 + "defaultPageSize": 10,
  1722 + "defaultSortOrder": "entityLabel",
  1723 + "displayEntityName": false,
  1724 + "displayEntityType": false,
  1725 + "enableSelectColumnDisplay": false,
  1726 + "enableStickyHeader": true,
  1727 + "enableStickyAction": true,
  1728 + "entitiesTitle": "Devices",
  1729 + "displayEntityLabel": true,
  1730 + "entityLabelColumnTitle": "Device"
  1731 + },
  1732 + "title": "New Entities table",
  1733 + "dropShadow": true,
  1734 + "enableFullscreen": true,
  1735 + "titleStyle": {
  1736 + "fontSize": "16px",
  1737 + "fontWeight": 400,
  1738 + "padding": "5px 10px 5px 10px"
  1739 + },
  1740 + "useDashboardTimewindow": false,
  1741 + "showLegend": false,
  1742 + "datasources": [
  1743 + {
  1744 + "type": "entity",
  1745 + "name": null,
  1746 + "entityAliasId": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  1747 + "filterId": "6044e198-df64-cd76-f339-696f220c4943",
  1748 + "dataKeys": [
  1749 + {
  1750 + "name": "current_sw_title",
  1751 + "type": "timeseries",
  1752 + "label": "Current SW title",
  1753 + "color": "#2196f3",
  1754 + "settings": {
  1755 + "columnWidth": "0px",
  1756 + "useCellStyleFunction": false,
  1757 + "cellStyleFunction": "",
  1758 + "useCellContentFunction": false,
  1759 + "defaultColumnVisibility": "visible",
  1760 + "columnSelectionToDisplay": "enabled"
  1761 + },
  1762 + "_hash": 0.09545533885166413,
  1763 + "units": null,
  1764 + "decimals": null,
  1765 + "funcBody": null,
  1766 + "usePostProcessing": null,
  1767 + "postFuncBody": null
  1768 + },
  1769 + {
  1770 + "name": "current_sw_version",
  1771 + "type": "timeseries",
  1772 + "label": "Current SW version",
  1773 + "color": "#4caf50",
  1774 + "settings": {
  1775 + "columnWidth": "0px",
  1776 + "useCellStyleFunction": false,
  1777 + "cellStyleFunction": "",
  1778 + "useCellContentFunction": false,
  1779 + "defaultColumnVisibility": "visible",
  1780 + "columnSelectionToDisplay": "enabled"
  1781 + },
  1782 + "_hash": 0.7206056602328659,
  1783 + "units": null,
  1784 + "decimals": null,
  1785 + "funcBody": null,
  1786 + "usePostProcessing": null,
  1787 + "postFuncBody": null
  1788 + },
  1789 + {
  1790 + "name": "target_sw_title",
  1791 + "type": "timeseries",
  1792 + "label": "Target SW title",
  1793 + "color": "#ffc107",
  1794 + "settings": {
  1795 + "columnWidth": "0px",
  1796 + "useCellStyleFunction": false,
  1797 + "cellStyleFunction": "",
  1798 + "useCellContentFunction": false,
  1799 + "defaultColumnVisibility": "visible",
  1800 + "columnSelectionToDisplay": "enabled"
  1801 + },
  1802 + "_hash": 0.9934225682766313,
  1803 + "units": null,
  1804 + "decimals": null,
  1805 + "funcBody": null,
  1806 + "usePostProcessing": null,
  1807 + "postFuncBody": null
  1808 + },
  1809 + {
  1810 + "name": "target_sw_version",
  1811 + "type": "timeseries",
  1812 + "label": "Target SW version",
  1813 + "color": "#607d8b",
  1814 + "settings": {
  1815 + "columnWidth": "0px",
  1816 + "useCellStyleFunction": false,
  1817 + "cellStyleFunction": "",
  1818 + "useCellContentFunction": false,
  1819 + "cellContentFunction": "",
  1820 + "defaultColumnVisibility": "visible",
  1821 + "columnSelectionToDisplay": "enabled"
  1822 + },
  1823 + "_hash": 0.5251724416842531,
  1824 + "units": null,
  1825 + "decimals": null,
  1826 + "funcBody": null,
  1827 + "usePostProcessing": null,
  1828 + "postFuncBody": null
  1829 + },
  1830 + {
  1831 + "name": "target_sw_ts",
  1832 + "type": "timeseries",
  1833 + "label": "Target SW set time",
  1834 + "color": "#e91e63",
  1835 + "settings": {
  1836 + "columnWidth": "0px",
  1837 + "useCellStyleFunction": false,
  1838 + "cellStyleFunction": "",
  1839 + "useCellContentFunction": true,
  1840 + "defaultColumnVisibility": "visible",
  1841 + "columnSelectionToDisplay": "enabled",
  1842 + "cellContentFunction": "if (value !== '') {\n return ctx.date.transform(value, 'yyyy-MM-dd HH:mm:ss');\n}\nreturn '';"
  1843 + },
  1844 + "_hash": 0.31823244858578237,
  1845 + "units": null,
  1846 + "decimals": null,
  1847 + "funcBody": null,
  1848 + "usePostProcessing": null,
  1849 + "postFuncBody": null
  1850 + },
  1851 + {
  1852 + "name": "sw_state",
  1853 + "type": "timeseries",
  1854 + "label": "Progress",
  1855 + "color": "#9c27b0",
  1856 + "settings": {
  1857 + "columnWidth": "30%",
  1858 + "useCellStyleFunction": true,
  1859 + "useCellContentFunction": true,
  1860 + "defaultColumnVisibility": "visible",
  1861 + "columnSelectionToDisplay": "enabled",
  1862 + "cellStyleFunction": "return {\n 'padding-right': '30px'\n}",
  1863 + "cellContentFunction": "if (value !== '') {\n var mapProgress = {\n 'QUEUED': 0,\n 'INITIATED': 5,\n 'DOWNLOADING': 10,\n 'DOWNLOADED': 55,\n 'VERIFIED': 60,\n 'UPDATING': 70,\n 'FAILED': 99,\n 'UPDATED': 100\n }\n var color = 'mat-primary';\n var progress = mapProgress[value];\n if (value == 'FAILED') {\n color = 'mat-accent';\n }\n return `<mat-progress-bar style=\"height: 8px\" role=\"progressbar\" aria-valuemin=\"0\" aria-valuemax=\"100\" tabindex=\"-1\" mode=\"determinate\" value=\"${progress}\" class=\"mat-progress-bar ${color}\" aria-valuenow=\"${progress}\"><div aria-hidden=\"true\"><svg width=\"100%\" height=\"8\" focusable=\"false\" class=\"mat-progress-bar-background mat-progress-bar-element\"><defs><pattern x=\"4\" y=\"0\" width=\"8\" height=\"4\" patternUnits=\"userSpaceOnUse\" id=\"mat-progress-bar-0\"><circle cx=\"2\" cy=\"2\" r=\"2\"></circle></pattern></defs><rect width=\"100%\" height=\"100%\" fill=\"url(\"/components/progress-bar/overview#mat-progress-bar-0\")\"></rect></svg><div class=\"mat-progress-bar-buffer mat-progress-bar-element\"></div><div class=\"mat-progress-bar-primary mat-progress-bar-fill mat-progress-bar-element\" style=\"transform: scale3d(${progress / 100}, 1, 1);\"></div><div class=\"mat-progress-bar-secondary mat-progress-bar-fill mat-progress-bar-element\"></div></div></mat-progress-bar>`;\n}"
  1864 + },
  1865 + "_hash": 0.8174211757846257,
  1866 + "units": null,
  1867 + "decimals": null,
  1868 + "funcBody": null,
  1869 + "usePostProcessing": null,
  1870 + "postFuncBody": null
  1871 + },
  1872 + {
  1873 + "name": "sw_state",
  1874 + "type": "timeseries",
  1875 + "label": "Status",
  1876 + "color": "#f44336",
  1877 + "settings": {
  1878 + "columnWidth": "130px",
  1879 + "useCellStyleFunction": true,
  1880 + "useCellContentFunction": true,
  1881 + "defaultColumnVisibility": "visible",
  1882 + "columnSelectionToDisplay": "enabled",
  1883 + "cellStyleFunction": "if (value == 'FAILED') {\n return {'color' : '#D93025'};\n}\nreturn {};",
  1884 + "cellContentFunction": "function icon(value) {\n if (value == 'QUEUED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000;\"><svg style=\"width:24px;height:24px\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z\" /></svg></mat-icon>';\n }\n if (value == 'INITIATED' || value == 'DOWNLOADING' || value == 'DOWNLOADED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.74 2.1951C11.63 1.2876 10.2575 0.687598 8.75 0.537598V2.0526C9.845 2.1876 10.8425 2.6226 11.675 3.2676L12.74 2.1951ZM13.9475 7.2501H15.4625C15.3125 5.7426 14.7125 4.3701 13.805 3.2601L12.7325 4.3251C13.3775 5.1576 13.8125 6.1551 13.9475 7.2501ZM12.7325 11.6751L13.805 12.7476C14.7125 11.6376 15.3125 10.2576 15.4625 8.7576H13.9475C13.8125 9.8451 13.3775 10.8426 12.7325 11.6751ZM8.75 13.9476V15.4626C10.2575 15.3126 11.63 14.7126 12.74 13.8051L11.6675 12.7326C10.8425 13.3776 9.845 13.8126 8.75 13.9476ZM8.75 8.0001V4.2501H7.25V8.0001H4.25L8 11.7501L11.75 8.0001H8.75ZM7.25 13.9476V15.4626C3.4625 15.0876 0.5 11.8926 0.5 8.0001C0.5 4.1076 3.4625 0.912598 7.25 0.537598V2.0526C4.2875 2.4201 2 4.9401 2 8.0001C2 11.0601 4.2875 13.5801 7.25 13.9476Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'VERIFIED' || value == 'UPDATING' ) {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\">update</mat-icon>';\n }\n if (value == 'UPDATED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #000\"><svg style=\"width:22px;height:22px\" viewBox=\"0 0 34 32\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M33.26 2.82L30.44 0L12.06 18.38L3.55999 9.9L0.73999 12.72L12.06 24.04L33.26 2.82Z\" fill=\"black\"/><path d=\"M31 28H3V32H31V28Z\" fill=\"black\"/></svg></mat-icon>';\n }\n if (value == 'FAILED') {\n return '<mat-icon _role=\"img\" class=\"mat-icon notranslate material-icons mat-icon-no-color\" aria-hidden=\"true\" data-mat-icon-type=\"font\" style=\"color: #D93025\">warning</mat-icon>';\n }\n return '';\n}\nfunction capitalize (s) {\n if (typeof s !== 'string') return '';\n return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();\n}\n\nreturn icon(value) + '<span style=\"vertical-align: super;padding-left: 8px;\">' + capitalize(value) + '</span>';"
  1885 + },
  1886 + "_hash": 0.7764426948615217,
  1887 + "units": null,
  1888 + "decimals": null,
  1889 + "funcBody": null,
  1890 + "usePostProcessing": null,
  1891 + "postFuncBody": null
  1892 + },
  1893 + {
  1894 + "name": "sw_checksum",
  1895 + "type": "attribute",
  1896 + "label": "sw_checksum",
  1897 + "color": "#3f51b5",
  1898 + "settings": {
  1899 + "columnWidth": "0px",
  1900 + "useCellStyleFunction": false,
  1901 + "cellStyleFunction": "",
  1902 + "useCellContentFunction": false,
  1903 + "defaultColumnVisibility": "hidden",
  1904 + "columnSelectionToDisplay": "disabled"
  1905 + },
  1906 + "_hash": 0.5594087842471693,
  1907 + "units": null,
  1908 + "decimals": null,
  1909 + "funcBody": null,
  1910 + "usePostProcessing": null,
  1911 + "postFuncBody": null
  1912 + },
  1913 + {
  1914 + "name": "sw_url",
  1915 + "type": "attribute",
  1916 + "label": "sw_url",
  1917 + "color": "#e91e63",
  1918 + "settings": {
  1919 + "columnWidth": "0px",
  1920 + "useCellStyleFunction": false,
  1921 + "cellStyleFunction": "",
  1922 + "useCellContentFunction": false,
  1923 + "cellContentFunction": "",
  1924 + "defaultColumnVisibility": "hidden",
  1925 + "columnSelectionToDisplay": "disabled"
  1926 + },
  1927 + "_hash": 0.3355829384124256,
  1928 + "units": null,
  1929 + "decimals": null,
  1930 + "funcBody": null,
  1931 + "usePostProcessing": null,
  1932 + "postFuncBody": null
  1933 + }
  1934 + ]
  1935 + }
  1936 + ],
  1937 + "actions": {
  1938 + "actionCellButton": [
  1939 + {
  1940 + "name": "History software update",
  1941 + "icon": "history",
  1942 + "type": "openDashboardState",
  1943 + "targetDashboardStateId": "device_software_history",
  1944 + "setEntityId": true,
  1945 + "stateEntityParamName": null,
  1946 + "openInSeparateDialog": false,
  1947 + "dialogTitle": "",
  1948 + "dialogHideDashboardToolbar": true,
  1949 + "dialogWidth": null,
  1950 + "dialogHeight": null,
  1951 + "openRightLayout": false,
  1952 + "id": "98a1406c-3301-bc2f-2c5d-d637ce3b663b"
  1953 + },
  1954 + {
  1955 + "name": "Edit software",
  1956 + "icon": "edit",
  1957 + "type": "customPretty",
  1958 + "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit software {{entityName}}</h2>\n <span fxFlex></span>\n <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n <mat-icon class=\"material-icons\">close</mat-icon>\n </button>\n </mat-toolbar>\n <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\n </mat-progress-bar>\n <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\n <div *ngIf=\"entity.deviceProfileId\" mat-dialog-content fxLayout=\"column\">\n <tb-ota-package-autocomplete\n [useFullEntityId]=\"true\"\n type=\"SOFTWARE\"\n [deviceProfileId]=\"entity.deviceProfileId.id\"\n formControlName=\"softwareId\">\n </tb-ota-package-autocomplete>\n </div>\n <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n <button mat-button color=\"primary\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n Save\n </button>\n </div>\n</form>",
  1959 + "customCss": "form {\n min-width: 300px !important;\n}",
  1960 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n\n vm.entityName = entityName;\n vm.entity = {};\n\n vm.editEntityFormGroup = vm.fb.group({\n softwareId: [null]\n });\n\n getEntityInfo();\n\n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n\n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveEntity().subscribe(\n function () {\n // widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n };\n\n\n function getEntityInfo() {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n vm.entity = data;\n vm.editEntityFormGroup.patchValue({\n softwareId: vm.entity.softwareId\n }, {emitEvent: false});\n }\n );\n }\n\n function saveEntity() {\n const formValues = vm.editEntityFormGroup.value;\n vm.entity.softwareId = formValues.softwareId;\n return deviceService.saveDevice(vm.entity);\n }\n}",
  1961 + "customResources": [],
  1962 + "id": "23099c1d-454b-25dc-8bc0-7cf33c21c5d5"
  1963 + },
  1964 + {
  1965 + "name": "Download software",
  1966 + "icon": "file_download",
  1967 + "type": "custom",
  1968 + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet entityService = $injector.get(widgetContext.servicesMap.get('entityService'));\nlet otaPackageService = $injector.get(widgetContext.servicesMap.get('otaPackageService'));\nlet deviceProfileService = $injector.get(widgetContext.servicesMap.get('deviceProfileService'));\n\ngetDeviceSoftware();\n\nfunction getDeviceSoftware() {\n var entityIdValue = entityId.id;\n var data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url === '') {\n entityService.getEntity(entityId.entityType, entityId.id).subscribe(\n function (data) {\n if (data.softwareId !== null) {\n otaPackageService.downloadOtaPackage(data.softwareId.id).subscribe(); \n } else {\n deviceProfileService.getDeviceProfile(data.deviceProfileId.id).subscribe(\n function (deviceProfile) {\n if (deviceProfile.softwareId !== null) {\n otaPackageService.downloadOtaPackage(deviceProfile.softwareId.id).subscribe();\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n });\n }\n }\n );\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1969 + "id": "12533058-42f6-e75f-620c-219c48d01ec0"
  1970 + },
  1971 + {
  1972 + "name": "Copy checksum/URL",
  1973 + "icon": "content_copy",
  1974 + "type": "custom",
  1975 + "customFunction": "function copyToClipboard(text) {\n if (window.clipboardData && window.clipboardData.setData) {\n return window.clipboardData.setData(\"Text\", text);\n\n }\n else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n var textarea = document.createElement(\"textarea\");\n textarea.textContent = text;\n textarea.style.position = \"fixed\";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand(\"copy\");\n }\n catch (ex) {\n console.warn(\"Copy to clipboard failed.\", ex);\n return false;\n }\n document.body.removeChild(textarea);\n }\n}\nvar entityIdValue = entityId.id;\nvar data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_checksum');\nvar checksum = data.data[0][1];\nconsole.log(checksum);\nif (checksum !== '') {\n copyToClipboard(checksum);\n widgetContext.showSuccessToast('Software checksum has been copied to clipboard', 2000, 'top');\n} else {\n data = widgetContext.data.find((el) => el.datasource.entityId === entityIdValue && el.dataKey.name === 'sw_url');\n var url = data.data[0][1];\n if (url !== '') {\n copyToClipboard(url);\n widgetContext.showSuccessToast('Software direct URL has been copied to clipboard', 2000, 'top');\n } else {\n widgetContext.showToast('warn', 'Device ' + entityName +' has not software set.', 2000, 'top');\n }\n}",
  1976 + "id": "09323079-7111-87f7-90d1-c62cd7d85dc7"
  1977 + }
  1978 + ]
  1979 + },
  1980 + "showTitleIcon": false,
  1981 + "iconColor": "rgba(0, 0, 0, 0.87)",
  1982 + "iconSize": "24px",
  1983 + "titleTooltip": "",
  1984 + "widgetStyle": {}
  1985 + },
  1986 + "row": 0,
  1987 + "col": 0,
  1988 + "id": "d2d13e0d-4e71-889f-9343-ad2f0af9f176"
  1989 + }
  1990 + },
  1991 + "states": {
  1992 + "default": {
  1993 + "name": "Device list",
  1994 + "root": true,
  1995 + "layouts": {
  1996 + "main": {
  1997 + "widgets": {
  1998 + "cd03188e-cd9d-9601-fd57-da4cb95fc016": {
  1999 + "sizeX": 19,
  2000 + "sizeY": 12,
  2001 + "row": 0,
  2002 + "col": 0
  2003 + },
  2004 + "17543c57-af4a-2c1e-bf12-53a7b46791e6": {
  2005 + "sizeX": 5,
  2006 + "sizeY": 3,
  2007 + "row": 0,
  2008 + "col": 19
  2009 + },
  2010 + "6c1c4e1a-bce0-f5ad-ff8b-ba1dfc5a4ec6": {
  2011 + "sizeX": 5,
  2012 + "sizeY": 3,
  2013 + "row": 3,
  2014 + "col": 19
  2015 + },
  2016 + "e6674227-9cf3-a2f6-ecac-5ccfc38a3c81": {
  2017 + "sizeX": 5,
  2018 + "sizeY": 3,
  2019 + "row": 9,
  2020 + "col": 19
  2021 + },
  2022 + "77b10144-b904-edd5-8c7c-8fb75616c6d8": {
  2023 + "sizeX": 5,
  2024 + "sizeY": 3,
  2025 + "row": 6,
  2026 + "col": 19
  2027 + }
  2028 + },
  2029 + "gridSettings": {
  2030 + "backgroundColor": "#eeeeee",
  2031 + "color": "rgba(0,0,0,0.870588)",
  2032 + "columns": 24,
  2033 + "margin": 12,
  2034 + "backgroundSizeMode": "100%",
  2035 + "autoFillHeight": true,
  2036 + "backgroundImageUrl": null,
  2037 + "mobileAutoFillHeight": true,
  2038 + "mobileRowHeight": 70
  2039 + }
  2040 + }
  2041 + }
  2042 + },
  2043 + "device_software_history": {
  2044 + "name": "Software history: ${entityName}",
  2045 + "root": false,
  2046 + "layouts": {
  2047 + "main": {
  2048 + "widgets": {
  2049 + "100b756c-0082-6505-3ae1-3603e6deea48": {
  2050 + "sizeX": 24,
  2051 + "sizeY": 12,
  2052 + "row": 0,
  2053 + "col": 0
  2054 + }
  2055 + },
  2056 + "gridSettings": {
  2057 + "backgroundColor": "#eeeeee",
  2058 + "color": "rgba(0,0,0,0.870588)",
  2059 + "columns": 24,
  2060 + "margin": 10,
  2061 + "backgroundSizeMode": "100%",
  2062 + "autoFillHeight": true,
  2063 + "backgroundImageUrl": null,
  2064 + "mobileAutoFillHeight": false,
  2065 + "mobileRowHeight": 70
  2066 + }
  2067 + }
  2068 + }
  2069 + },
  2070 + "device_waiting": {
  2071 + "name": "Device waiting",
  2072 + "root": false,
  2073 + "layouts": {
  2074 + "main": {
  2075 + "widgets": {
  2076 + "21be08bb-ec90-f760-ad6f-e7678f12c401": {
  2077 + "sizeX": 24,
  2078 + "sizeY": 12,
  2079 + "row": 0,
  2080 + "col": 0
  2081 + }
  2082 + },
  2083 + "gridSettings": {
  2084 + "backgroundColor": "#eeeeee",
  2085 + "color": "rgba(0,0,0,0.870588)",
  2086 + "columns": 24,
  2087 + "margin": 10,
  2088 + "backgroundSizeMode": "100%",
  2089 + "autoFillHeight": true,
  2090 + "backgroundImageUrl": null,
  2091 + "mobileAutoFillHeight": false,
  2092 + "mobileRowHeight": 70
  2093 + }
  2094 + }
  2095 + }
  2096 + },
  2097 + "device_updating": {
  2098 + "name": "Device updating",
  2099 + "root": false,
  2100 + "layouts": {
  2101 + "main": {
  2102 + "widgets": {
  2103 + "e8280043-d3dc-7acb-c2ff-a4522972ff91": {
  2104 + "sizeX": 24,
  2105 + "sizeY": 12,
  2106 + "row": 0,
  2107 + "col": 0
  2108 + }
  2109 + },
  2110 + "gridSettings": {
  2111 + "backgroundColor": "#eeeeee",
  2112 + "color": "rgba(0,0,0,0.870588)",
  2113 + "columns": 24,
  2114 + "margin": 10,
  2115 + "backgroundSizeMode": "100%",
  2116 + "autoFillHeight": true,
  2117 + "backgroundImageUrl": null,
  2118 + "mobileAutoFillHeight": false,
  2119 + "mobileRowHeight": 70
  2120 + }
  2121 + }
  2122 + }
  2123 + },
  2124 + "device_updated": {
  2125 + "name": "Device updated",
  2126 + "root": false,
  2127 + "layouts": {
  2128 + "main": {
  2129 + "widgets": {
  2130 + "d2d13e0d-4e71-889f-9343-ad2f0af9f176": {
  2131 + "sizeX": 27,
  2132 + "sizeY": 12,
  2133 + "row": 0,
  2134 + "col": 0
  2135 + }
  2136 + },
  2137 + "gridSettings": {
  2138 + "backgroundColor": "#eeeeee",
  2139 + "color": "rgba(0,0,0,0.870588)",
  2140 + "columns": 24,
  2141 + "margin": 10,
  2142 + "backgroundSizeMode": "100%",
  2143 + "autoFillHeight": true,
  2144 + "backgroundImageUrl": null,
  2145 + "mobileAutoFillHeight": false,
  2146 + "mobileRowHeight": 70
  2147 + }
  2148 + }
  2149 + }
  2150 + },
  2151 + "device_error": {
  2152 + "name": "Device failed",
  2153 + "root": false,
  2154 + "layouts": {
  2155 + "main": {
  2156 + "widgets": {
  2157 + "3624013b-378c-f110-5eba-ae95c25a4dcc": {
  2158 + "sizeX": 24,
  2159 + "sizeY": 12,
  2160 + "row": 0,
  2161 + "col": 0
  2162 + }
  2163 + },
  2164 + "gridSettings": {
  2165 + "backgroundColor": "#eeeeee",
  2166 + "color": "rgba(0,0,0,0.870588)",
  2167 + "columns": 24,
  2168 + "margin": 10,
  2169 + "backgroundSizeMode": "100%",
  2170 + "autoFillHeight": true,
  2171 + "backgroundImageUrl": null,
  2172 + "mobileAutoFillHeight": false,
  2173 + "mobileRowHeight": 70
  2174 + }
  2175 + }
  2176 + }
  2177 + }
  2178 + },
  2179 + "entityAliases": {
  2180 + "639da5b4-31f0-0151-6282-c37a3897b7e8": {
  2181 + "id": "639da5b4-31f0-0151-6282-c37a3897b7e8",
  2182 + "alias": "All devices",
  2183 + "filter": {
  2184 + "type": "entityType",
  2185 + "resolveMultiple": true,
  2186 + "entityType": "DEVICE"
  2187 + }
  2188 + },
  2189 + "19f41c21-d9af-e666-8f50-e1748778f955": {
  2190 + "id": "19f41c21-d9af-e666-8f50-e1748778f955",
  2191 + "alias": "State entity",
  2192 + "filter": {
  2193 + "type": "stateEntity",
  2194 + "resolveMultiple": false,
  2195 + "stateEntityParamName": null,
  2196 + "defaultStateEntity": null
  2197 + }
  2198 + }
  2199 + },
  2200 + "filters": {
  2201 + "19a0ad1c-b31d-4a29-9d7b-5d87e2a8ea6e": {
  2202 + "id": "19a0ad1c-b31d-4a29-9d7b-5d87e2a8ea6e",
  2203 + "filter": "WaitingDevicesFilter",
  2204 + "keyFilters": [
  2205 + {
  2206 + "key": {
  2207 + "type": "TIME_SERIES",
  2208 + "key": "sw_state"
  2209 + },
  2210 + "valueType": "STRING",
  2211 + "predicates": [
  2212 + {
  2213 + "keyFilterPredicate": {
  2214 + "operation": "EQUAL",
  2215 + "value": {
  2216 + "defaultValue": "QUEUED",
  2217 + "dynamicValue": null
  2218 + },
  2219 + "ignoreCase": false,
  2220 + "type": "STRING"
  2221 + },
  2222 + "userInfo": {
  2223 + "editable": true,
  2224 + "label": "",
  2225 + "autogeneratedLabel": true,
  2226 + "order": 0
  2227 + }
  2228 + }
  2229 + ]
  2230 + }
  2231 + ],
  2232 + "editable": false
  2233 + },
  2234 + "579f0468-9ce9-7e3e-b34c-88dd3de59897": {
  2235 + "id": "579f0468-9ce9-7e3e-b34c-88dd3de59897",
  2236 + "filter": "UpdatingDevicesFilter",
  2237 + "keyFilters": [
  2238 + {
  2239 + "key": {
  2240 + "type": "TIME_SERIES",
  2241 + "key": "sw_state"
  2242 + },
  2243 + "valueType": "STRING",
  2244 + "predicates": [
  2245 + {
  2246 + "keyFilterPredicate": {
  2247 + "operation": "OR",
  2248 + "predicates": [
  2249 + {
  2250 + "keyFilterPredicate": {
  2251 + "operation": "EQUAL",
  2252 + "value": {
  2253 + "defaultValue": "INITIATED",
  2254 + "dynamicValue": null
  2255 + },
  2256 + "ignoreCase": false,
  2257 + "type": "STRING"
  2258 + },
  2259 + "userInfo": {
  2260 + "editable": false,
  2261 + "label": "sw_state equel",
  2262 + "autogeneratedLabel": true,
  2263 + "order": 0
  2264 + }
  2265 + },
  2266 + {
  2267 + "keyFilterPredicate": {
  2268 + "operation": "EQUAL",
  2269 + "value": {
  2270 + "defaultValue": "DOWNLOADING",
  2271 + "dynamicValue": null
  2272 + },
  2273 + "ignoreCase": false,
  2274 + "type": "STRING"
  2275 + },
  2276 + "userInfo": {
  2277 + "editable": false,
  2278 + "label": "sw_state equal",
  2279 + "autogeneratedLabel": true,
  2280 + "order": 0
  2281 + }
  2282 + },
  2283 + {
  2284 + "keyFilterPredicate": {
  2285 + "operation": "EQUAL",
  2286 + "value": {
  2287 + "defaultValue": "DOWNLOADED",
  2288 + "dynamicValue": null
  2289 + },
  2290 + "ignoreCase": false,
  2291 + "type": "STRING"
  2292 + },
  2293 + "userInfo": {
  2294 + "editable": false,
  2295 + "label": "sw_state equal",
  2296 + "autogeneratedLabel": true,
  2297 + "order": 0
  2298 + }
  2299 + },
  2300 + {
  2301 + "keyFilterPredicate": {
  2302 + "operation": "EQUAL",
  2303 + "value": {
  2304 + "defaultValue": "VERIFIED",
  2305 + "dynamicValue": null
  2306 + },
  2307 + "ignoreCase": false,
  2308 + "type": "STRING"
  2309 + },
  2310 + "userInfo": {
  2311 + "editable": false,
  2312 + "label": "sw_state equal",
  2313 + "autogeneratedLabel": true,
  2314 + "order": 0
  2315 + }
  2316 + },
  2317 + {
  2318 + "keyFilterPredicate": {
  2319 + "operation": "EQUAL",
  2320 + "value": {
  2321 + "defaultValue": "UPDATING",
  2322 + "dynamicValue": null
  2323 + },
  2324 + "ignoreCase": false,
  2325 + "type": "STRING"
  2326 + },
  2327 + "userInfo": {
  2328 + "editable": false,
  2329 + "label": "sw_state equal",
  2330 + "autogeneratedLabel": true,
  2331 + "order": 0
  2332 + }
  2333 + }
  2334 + ],
  2335 + "type": "COMPLEX"
  2336 + },
  2337 + "userInfo": {
  2338 + "editable": true,
  2339 + "label": "",
  2340 + "autogeneratedLabel": true,
  2341 + "order": 0
  2342 + }
  2343 + }
  2344 + ]
  2345 + }
  2346 + ],
  2347 + "editable": false
  2348 + },
  2349 + "6044e198-df64-cd76-f339-696f220c4943": {
  2350 + "id": "6044e198-df64-cd76-f339-696f220c4943",
  2351 + "filter": "UpdetedDevicesFilter",
  2352 + "keyFilters": [
  2353 + {
  2354 + "key": {
  2355 + "type": "TIME_SERIES",
  2356 + "key": "sw_state"
  2357 + },
  2358 + "valueType": "STRING",
  2359 + "predicates": [
  2360 + {
  2361 + "keyFilterPredicate": {
  2362 + "operation": "EQUAL",
  2363 + "value": {
  2364 + "defaultValue": "UPDATED",
  2365 + "dynamicValue": null
  2366 + },
  2367 + "ignoreCase": false,
  2368 + "type": "STRING"
  2369 + },
  2370 + "userInfo": {
  2371 + "editable": true,
  2372 + "label": "",
  2373 + "autogeneratedLabel": true,
  2374 + "order": 0
  2375 + }
  2376 + }
  2377 + ]
  2378 + }
  2379 + ],
  2380 + "editable": false
  2381 + },
  2382 + "bdbc6ea1-95a7-3912-341a-58dc7704a00f": {
  2383 + "id": "bdbc6ea1-95a7-3912-341a-58dc7704a00f",
  2384 + "filter": "FailedDevicesFilter",
  2385 + "keyFilters": [
  2386 + {
  2387 + "key": {
  2388 + "type": "TIME_SERIES",
  2389 + "key": "sw_state"
  2390 + },
  2391 + "valueType": "STRING",
  2392 + "predicates": [
  2393 + {
  2394 + "keyFilterPredicate": {
  2395 + "operation": "EQUAL",
  2396 + "value": {
  2397 + "defaultValue": "FAILED",
  2398 + "dynamicValue": null
  2399 + },
  2400 + "ignoreCase": false,
  2401 + "type": "STRING"
  2402 + },
  2403 + "userInfo": {
  2404 + "editable": true,
  2405 + "label": "",
  2406 + "autogeneratedLabel": true,
  2407 + "order": 0
  2408 + }
  2409 + }
  2410 + ]
  2411 + }
  2412 + ],
  2413 + "editable": false
  2414 + },
  2415 + "8fdb88d0-50ac-2232-fdb7-69c30c16544e": {
  2416 + "id": "8fdb88d0-50ac-2232-fdb7-69c30c16544e",
  2417 + "filter": "DeviceSearch",
  2418 + "keyFilters": [
  2419 + {
  2420 + "key": {
  2421 + "type": "ENTITY_FIELD",
  2422 + "key": "name"
  2423 + },
  2424 + "valueType": "STRING",
  2425 + "predicates": [
  2426 + {
  2427 + "keyFilterPredicate": {
  2428 + "operation": "CONTAINS",
  2429 + "value": {
  2430 + "defaultValue": ""
  2431 + },
  2432 + "ignoreCase": true,
  2433 + "type": "STRING"
  2434 + },
  2435 + "userInfo": {
  2436 + "editable": true,
  2437 + "label": "Device name",
  2438 + "autogeneratedLabel": false,
  2439 + "order": 0
  2440 + }
  2441 + }
  2442 + ]
  2443 + }
  2444 + ],
  2445 + "editable": true
  2446 + }
  2447 + },
  2448 + "timewindow": {
  2449 + "displayValue": "",
  2450 + "hideInterval": false,
  2451 + "hideAggregation": false,
  2452 + "hideAggInterval": false,
  2453 + "hideTimezone": false,
  2454 + "selectedTab": 0,
  2455 + "realtime": {
  2456 + "realtimeType": 0,
  2457 + "interval": 1000,
  2458 + "timewindowMs": 60000,
  2459 + "quickInterval": "CURRENT_DAY"
  2460 + },
  2461 + "history": {
  2462 + "historyType": 0,
  2463 + "interval": 1000,
  2464 + "timewindowMs": 60000,
  2465 + "fixedTimewindow": {
  2466 + "startTimeMs": 1618998609030,
  2467 + "endTimeMs": 1619085009030
  2468 + },
  2469 + "quickInterval": "CURRENT_DAY"
  2470 + },
  2471 + "aggregation": {
  2472 + "type": "AVG",
  2473 + "limit": 25000
  2474 + }
  2475 + },
  2476 + "settings": {
  2477 + "stateControllerId": "entity",
  2478 + "showTitle": false,
  2479 + "showDashboardsSelect": false,
  2480 + "showEntitiesSelect": false,
  2481 + "showDashboardTimewindow": true,
  2482 + "showDashboardExport": false,
  2483 + "toolbarAlwaysOpen": true,
  2484 + "titleColor": "rgba(0,0,0,0.870588)",
  2485 + "showFilters": true,
  2486 + "showDashboardLogo": false,
  2487 + "dashboardLogoUrl": null,
  2488 + "showUpdateDashboardImage": false
  2489 + }
  2490 + },
  2491 + "name": "Software"
  2492 +}
\ No newline at end of file
... ...