Flex layout replacements. Switch to tailwind.css.
This commit is contained in:
		
							parent
							
								
									a1df7ad220
								
							
						
					
					
						commit
						14b0f47b95
					
				@ -279,7 +279,7 @@
 | 
			
		||||
                "name": "Edit firmware",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit firmware {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1142,7 +1142,7 @@
 | 
			
		||||
                "name": "Edit firmware",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit firmware {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1448,7 +1448,7 @@
 | 
			
		||||
                "name": "Edit firmware",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit firmware {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1754,7 +1754,7 @@
 | 
			
		||||
                "name": "Edit firmware",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit firmware {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -2060,7 +2060,7 @@
 | 
			
		||||
                "name": "Edit firmware",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit firmware {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
 | 
			
		||||
@ -279,7 +279,7 @@
 | 
			
		||||
                "name": "Edit software",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit software {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1142,7 +1142,7 @@
 | 
			
		||||
                "name": "Edit software",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit software {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1448,7 +1448,7 @@
 | 
			
		||||
                "name": "Edit software",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit software {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1754,7 +1754,7 @@
 | 
			
		||||
                "name": "Edit software",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit software {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -2060,7 +2060,7 @@
 | 
			
		||||
                "name": "Edit software",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "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>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\"  class=\"edit-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Edit software {{entityName}}</h2>\n    <span class=\"flex-1\"></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 class=\"flex flex-col\">\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 class=\"flex flex-row items-center justify-end\">\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>",
 | 
			
		||||
                "customCss": "form {\n    min-width: 300px !important;\n}",
 | 
			
		||||
                "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}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
 | 
			
		||||
@ -160,7 +160,7 @@
 | 
			
		||||
                "name": "Add",
 | 
			
		||||
                "icon": "add",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "customHtml": "<form #addEntityForm=\"ngForm\" [formGroup]=\"addEntityFormGroup\"\n        (ngSubmit)=\"save()\" class=\"add-entity-form\">\n    <mat-toolbar color=\"primary\">\n        <h2>Add thermostat</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 mat-dialog-content fxLayout=\"column\">\n        <mat-form-field fxFlex class=\"mat-block\">\n            <mat-label>Thermostat name</mat-label>\n            <input matInput formControlName=\"entityName\" required>\n            <mat-error *ngIf=\"addEntityFormGroup.get('entityName').hasError('required')\">\n                Thermostat name is required.\n            </mat-error>\n        </mat-form-field>\n        <div formGroupName=\"attributes\" fxLayout=\"column\">\n            <mat-slide-toggle formControlName=\"temperatureAlarmFlag\">\n                High temperature alarm\n            </mat-slide-toggle>\n            <mat-form-field fxFlex class=\"mat-block\">\n                <mat-label>High temperature threshold, °C</mat-label>\n                <input type=\"number\" step=\"any\" matInput\n                    [required] = \"addEntityFormGroup.get('attributes').get('temperatureAlarmFlag').value\"\n                    formControlName=\"temperatureAlarmThreshold\">\n                <mat-error *ngIf=\"addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').hasError('required')\">\n                    High temperature threshold is required.\n                </mat-error>\n            </mat-form-field>\n        \n            <mat-slide-toggle formControlName=\"humidityAlarmFlag\">\n                Low humidity alarm\n            </mat-slide-toggle>\n                \n            <mat-form-field fxFlex class=\"mat-block\">\n                <mat-label>Low humidity threshold, %</mat-label>\n                <input type=\"number\" step=\"any\" matInput\n                    [required] = \"addEntityFormGroup.get('attributes').get('humidityAlarmFlag').value\"\n                    formControlName=\"humidityAlarmThreshold\">\n                <mat-error *ngIf=\"addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').hasError('required')\">\n                    Low humidity threshold is required.\n                </mat-error>\n            </mat-form-field>\n        </div>\n    </div>\n    <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n        <button mat-button mat-raised-button color=\"primary\"\n                type=\"submit\"\n                [disabled]=\"(isLoading$ | async) || addEntityForm.invalid || !addEntityForm.dirty\">\n            Create\n        </button>\n        <button mat-button color=\"primary\"\n                type=\"button\"\n                [disabled]=\"(isLoading$ | async)\"\n                (click)=\"cancel()\" cdkFocusInitial>\n            Cancel\n        </button>\n    </div>\n</form>",
 | 
			
		||||
                "customHtml": "<form #addEntityForm=\"ngForm\" [formGroup]=\"addEntityFormGroup\"\n      (ngSubmit)=\"save()\" class=\"add-entity-form\">\n  <mat-toolbar color=\"primary\">\n    <h2>Add thermostat</h2>\n    <span class=\"flex-1\"></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 mat-dialog-content class=\"flex flex-col\">\n    <mat-form-field class=\"mat-block flex-1\">\n      <mat-label>Thermostat name</mat-label>\n      <input matInput formControlName=\"entityName\" required>\n      <mat-error *ngIf=\"addEntityFormGroup.get('entityName').hasError('required')\">\n        Thermostat name is required.\n      </mat-error>\n    </mat-form-field>\n    <div formGroupName=\"attributes\" class=\"flex flex-col\">\n      <mat-slide-toggle formControlName=\"temperatureAlarmFlag\">\n        High temperature alarm\n      </mat-slide-toggle>\n      <mat-form-field class=\"mat-block flex-1\">\n        <mat-label>High temperature threshold, °C</mat-label>\n        <input type=\"number\" step=\"any\" matInput\n               [required] = \"addEntityFormGroup.get('attributes').get('temperatureAlarmFlag').value\"\n               formControlName=\"temperatureAlarmThreshold\">\n        <mat-error *ngIf=\"addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').hasError('required')\">\n          High temperature threshold is required.\n        </mat-error>\n      </mat-form-field>\n\n      <mat-slide-toggle formControlName=\"humidityAlarmFlag\">\n        Low humidity alarm\n      </mat-slide-toggle>\n\n      <mat-form-field class=\"mat-block flex-1\">\n        <mat-label>Low humidity threshold, %</mat-label>\n        <input type=\"number\" step=\"any\" matInput\n               [required] = \"addEntityFormGroup.get('attributes').get('humidityAlarmFlag').value\"\n               formControlName=\"humidityAlarmThreshold\">\n        <mat-error *ngIf=\"addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').hasError('required')\">\n          Low humidity threshold is required.\n        </mat-error>\n      </mat-form-field>\n    </div>\n  </div>\n  <div mat-dialog-actions class=\"flex flex-row items-center justify-end\">\n    <button mat-button mat-raised-button color=\"primary\"\n            type=\"submit\"\n            [disabled]=\"(isLoading$ | async) || addEntityForm.invalid || !addEntityForm.dirty\">\n      Create\n    </button>\n    <button mat-button color=\"primary\"\n            type=\"button\"\n            [disabled]=\"(isLoading$ | async)\"\n            (click)=\"cancel()\" cdkFocusInitial>\n      Cancel\n    </button>\n  </div>\n</form>",
 | 
			
		||||
                "customCss": ".add-entity-form{\n    width: 300px;\n}\n",
 | 
			
		||||
                "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenAddEntityDialog();\n\nfunction openAddEntityDialog() {\n    customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\n}\n\nfunction AddEntityDialogController(instance) {\n    let vm = instance;\n    \n    vm.addEntityFormGroup = vm.fb.group({\n        entityName: ['', [vm.validators.required]],\n        attributes: vm.fb.group({\n            temperatureAlarmFlag: [false],\n            temperatureAlarmThreshold: [{value: null, disabled: true}],\n            humidityAlarmFlag: [false],\n            humidityAlarmThreshold: [{value: null, disabled: true}]\n        })\n    });\n    \n    vm.addEntityFormGroup.get('attributes').get('temperatureAlarmFlag').valueChanges\n    .subscribe(activate => {\n        if (activate) {\n            vm.addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n        } else {\n            vm.addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').disable();\n        }\n    });\n    \n    vm.addEntityFormGroup.get('attributes').get('humidityAlarmFlag').valueChanges\n    .subscribe(activate => {\n        if (activate) {\n            vm.addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n        } else {\n            vm.addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').disable();\n        }\n    });\n\n    vm.save = function() {\n        vm.addEntityFormGroup.markAsPristine();\n        saveEntityObservable().subscribe(\n            function (entity) {\n                saveAttributes(entity.id).subscribe(\n                    function () {\n                        widgetContext.updateAliases();\n                        vm.dialogRef.close(null);\n                    }\n                );\n            }\n        );\n    };\n    \n    vm.cancel = function() {\n        vm.dialogRef.close(null);\n    };\n    \n    function saveEntityObservable() {\n        const formValues = vm.addEntityFormGroup.value;\n        let entity = {\n            name: formValues.entityName,\n            type: \"thermostat\"\n        };\n        return deviceService.saveDevice(entity);\n    }\n    \n    function saveAttributes(entityId) {\n        let attributes = vm.addEntityFormGroup.get('attributes').value;\n        let attributesArray = [];\n        for (let key in attributes) {\n            if(attributes[key] !== null) {\n                attributesArray.push({key: key, value: attributes[key]});\n            }\n        }\n        if (attributesArray.length > 0) {\n            return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n        } else {\n            return widgetContext.rxjs.of([]);\n        }\n    }\n}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -180,7 +180,7 @@
 | 
			
		||||
                "name": "Edit",
 | 
			
		||||
                "icon": "edit",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n    <mat-toolbar color=\"primary\">\n        <h2>Edit thermostat {{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 mat-dialog-content fxLayout=\"column\">\n        <mat-form-field fxFlex class=\"mat-block\">\n            <mat-label>Thermostat name</mat-label>\n            <input matInput formControlName=\"entityName\" readonly>\n        </mat-form-field>\n        <div formGroupName=\"attributes\" fxLayout=\"column\">\n            <mat-slide-toggle formControlName=\"temperatureAlarmFlag\">\n                High temperature alarm\n            </mat-slide-toggle>\n            <mat-form-field fxFlex class=\"mat-block\">\n                <mat-label>High temperature threshold, °C</mat-label>\n                <input type=\"number\" step=\"any\" matInput\n                        [required] = \"editEntityFormGroup.get('attributes').get('temperatureAlarmFlag').value\"\n                        formControlName=\"temperatureAlarmThreshold\">\n                <mat-error *ngIf=\"editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').hasError('required')\">\n                    High temperature threshold is required.\n                </mat-error>\n            </mat-form-field>\n\n            <mat-slide-toggle formControlName=\"humidityAlarmFlag\">\n                Low humidity alarm\n            </mat-slide-toggle>\n\n            <mat-form-field fxFlex class=\"mat-block\">\n                <mat-label>Low humidity threshold, %</mat-label>\n                <input type=\"number\" step=\"any\" matInput\n                       [required] = \"editEntityFormGroup.get('attributes').get('humidityAlarmFlag').value\"\n                       formControlName=\"humidityAlarmThreshold\">\n                <mat-error *ngIf=\"editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').hasError('required')\">\n                    Low humidity threshold is required.\n                </mat-error>\n            </mat-form-field>\n        </div>\n    </div>\n    <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n        <button mat-raised-button color=\"primary\"\n                type=\"submit\"\n                [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n            Save\n        </button>\n        <button mat-button color=\"primary\"\n                type=\"button\"\n                [disabled]=\"(isLoading$ | async)\"\n                (click)=\"cancel()\" cdkFocusInitial>\n            Cancel\n        </button>\n    </div>\n</form>",
 | 
			
		||||
                "customHtml": "<form #editEntityForm=\"ngForm\" [formGroup]=\"editEntityFormGroup\"\n      (ngSubmit)=\"save()\" class=\"edit-entity-form\">\n  <mat-toolbar color=\"primary\">\n    <h2>Edit thermostat {{entityName}}</h2>\n    <span class=\"flex-1\"></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 mat-dialog-content class=\"flex flex-col\">\n    <mat-form-field class=\"mat-block flex-1\">\n      <mat-label>Thermostat name</mat-label>\n      <input matInput formControlName=\"entityName\" readonly>\n    </mat-form-field>\n    <div formGroupName=\"attributes\" class=\"flex flex-col\">\n      <mat-slide-toggle formControlName=\"temperatureAlarmFlag\">\n        High temperature alarm\n      </mat-slide-toggle>\n      <mat-form-field class=\"mat-block flex-1\">\n        <mat-label>High temperature threshold, °C</mat-label>\n        <input type=\"number\" step=\"any\" matInput\n               [required] = \"editEntityFormGroup.get('attributes').get('temperatureAlarmFlag').value\"\n               formControlName=\"temperatureAlarmThreshold\">\n        <mat-error *ngIf=\"editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').hasError('required')\">\n          High temperature threshold is required.\n        </mat-error>\n      </mat-form-field>\n\n      <mat-slide-toggle formControlName=\"humidityAlarmFlag\">\n        Low humidity alarm\n      </mat-slide-toggle>\n\n      <mat-form-field class=\"mat-block flex-1\">\n        <mat-label>Low humidity threshold, %</mat-label>\n        <input type=\"number\" step=\"any\" matInput\n               [required] = \"editEntityFormGroup.get('attributes').get('humidityAlarmFlag').value\"\n               formControlName=\"humidityAlarmThreshold\">\n        <mat-error *ngIf=\"editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').hasError('required')\">\n          Low humidity threshold is required.\n        </mat-error>\n      </mat-form-field>\n    </div>\n  </div>\n  <div mat-dialog-actions class=\"flex flex-row items-center justify-end\">\n    <button mat-raised-button color=\"primary\"\n            type=\"submit\"\n            [disabled]=\"(isLoading$ | async) || editEntityForm.invalid || !editEntityForm.dirty\">\n      Save\n    </button>\n    <button mat-button color=\"primary\"\n            type=\"button\"\n            [disabled]=\"(isLoading$ | async)\"\n            (click)=\"cancel()\" cdkFocusInitial>\n      Cancel\n    </button>\n  </div>\n</form>",
 | 
			
		||||
                "customCss": ".edit-entity-form{\n    width: 300px;\n}",
 | 
			
		||||
                "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n    customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n    let vm = instance;\n    \n    vm.entityId = entityId;\n    vm.entityName = entityName;\n    vm.attributes = {};\n    \n    vm.editEntityFormGroup = vm.fb.group({\n        entityName: [''],\n        attributes: vm.fb.group({\n            temperatureAlarmFlag: [false],\n            temperatureAlarmThreshold: [{value: null, disabled: true}],\n            humidityAlarmFlag: [false],\n            humidityAlarmThreshold: [{value: null, disabled: true}]\n        })\n    });\n    \n    vm.editEntityFormGroup.get('attributes').get('temperatureAlarmFlag').valueChanges\n    .subscribe(activate => {\n        if (activate) {\n            vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n        } else {\n            vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').disable();\n        }\n    });\n    \n    vm.editEntityFormGroup.get('attributes').get('humidityAlarmFlag').valueChanges\n    .subscribe(activate => {\n        if (activate) {\n            vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n        } else {\n            vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').disable();\n        }\n    });\n    \n    \n    getEntityInfo();\n    \n    \n    vm.save = function() {\n        vm.editEntityFormGroup.markAsPristine();\n        saveAttributes(entityId).subscribe(\n            function () {\n                vm.dialogRef.close(null);\n            }\n        );\n    };\n    \n    vm.cancel = function() {\n        vm.dialogRef.close(null);\n    };\n    \n    function getEntityAttributes(attributes) {\n        for (var i = 0; i < attributes.length; i++) {\n            vm.attributes[attributes[i].key] = attributes[i].value;\n        }\n    }\n    \n    function getEntityInfo() {\n        attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE').subscribe(\n            function (attributes) {\n                getEntityAttributes(attributes);\n                vm.editEntityFormGroup.patchValue({\n                    entityName: vm.entityName,\n                    attributes: vm.attributes\n                });\n                // if(vm.attributes.temperatureAlarmFlag) {\n                //     vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n                // }\n                // if(vm.attributes.humidityAlarmFlag) {\n                //     vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n                // }\n            }\n        );\n    }\n    \n    function saveAttributes(entityId) {\n        let attributes = vm.editEntityFormGroup.get('attributes').value;\n        let attributesArray = [];\n        for (let key in attributes) {\n            if (attributes[key] !== vm.attributes[key]) {\n                attributesArray.push({key: key, value: attributes[key]});\n            }\n        }\n        if (attributesArray.length > 0) {\n            return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n        } else {\n            return widgetContext.rxjs.of([]);\n        }\n    }\n}",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
 | 
			
		||||
@ -186,7 +186,7 @@
 | 
			
		||||
                "useShowWidgetActionFunction": null,
 | 
			
		||||
                "showWidgetActionFunction": "return true;",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "customHtml": "<div class=\"container\">\n    <mat-toolbar fxLayout=\"row\" color=\"primary\">\n        <h2>{{ 'gateway.launch-command' | translate }}</h2>\n        <span fxFlex></span>\n        <div [tb-help]=\"'gatewayInstall'\"></div>\n        <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n            <mat-icon class=\"material-icons\">close</mat-icon>\n        </button>\n    </mat-toolbar>\n    <tb-gateway-command [deviceId]=\"entityId\"></tb-gateway-command>\n    <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n        <button mat-button color=\"primary\"\n            type=\"button\"\n            (click)=\"cancel()\" cdkFocusInitial>\n            {{ 'action.close' | translate }}\n        </button>\n    </div>\n</div>\n",
 | 
			
		||||
                "customHtml": "<div class=\"container\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>{{ 'gateway.launch-command' | translate }}</h2>\n    <span class=\"flex-1\"></span>\n    <div [tb-help]=\"'gatewayInstall'\"></div>\n    <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n      <mat-icon class=\"material-icons\">close</mat-icon>\n    </button>\n  </mat-toolbar>\n  <tb-gateway-command [deviceId]=\"entityId\"></tb-gateway-command>\n  <div mat-dialog-actions class=\"flex flex-row items-center justify-end\">\n    <button mat-button color=\"primary\"\n            type=\"button\"\n            (click)=\"cancel()\" cdkFocusInitial>\n      {{ 'action.close' | translate }}\n    </button>\n  </div>\n</div>\n",
 | 
			
		||||
                "customCss": ".container {\n    display: grid;\n    grid-template-rows: min-content minmax(auto, 1fr) min-content;\n    height: 100%;\n    max-height: 100vh;\n    width: 600px;\n    max-width: 100%;\n}",
 | 
			
		||||
                "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\n\nopenCommands();\n\nfunction openCommands() {\n    customDialog.customDialog(htmlTemplate, CommandsDialogController, {panelClass: \"test\"}).subscribe();\n}\n\nfunction CommandsDialogController(instance) {\n    let vm = instance;\n    \n    vm.entityId = entityId.id;\n\n    vm.cancel = function() {\n        vm.dialogRef.close(null);\n    };\n}\n",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -246,7 +246,7 @@
 | 
			
		||||
                "useShowWidgetActionFunction": null,
 | 
			
		||||
                "showWidgetActionFunction": "return true;",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "customHtml": "<form #addEntityForm=\"ngForm\" [formGroup]=\"addEntityFormGroup\"\r\n      (ngSubmit)=\"save($event)\" class=\"add-entity-form\">\r\n    <mat-toolbar fxLayout=\"row\" color=\"primary\">\r\n        <h2>Add gateway</h2>\r\n        <span fxFlex></span>\r\n        <button mat-icon-button (click)=\"cancel()\" type=\"button\">\r\n            <mat-icon class=\"material-icons\">close</mat-icon>\r\n        </button>\r\n    </mat-toolbar>\r\n    <mat-progress-bar color=\"warn\" mode=\"indeterminate\" *ngIf=\"isLoading$ | async\">\r\n    </mat-progress-bar>\r\n    <div style=\"height: 4px;\" *ngIf=\"!(isLoading$ | async)\"></div>\r\n    <div mat-dialog-content fxLayout=\"column\">\r\n        <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayout.xs=\"column\"  fxLayoutGap.xs=\"0\">\r\n            <mat-form-field fxFlex class=\"mat-block\">\r\n                <mat-label>Name</mat-label>\r\n                <input matInput formControlName=\"entityName\" required>\r\n                <mat-error *ngIf=\"addEntityFormGroup.get('entityName').hasError('required')\">\r\n                    Gateway name is required.\r\n                </mat-error>\r\n            </mat-form-field>\r\n        </div>\r\n        <div fxLayout=\"row\" fxLayoutGap=\"8px\" fxLayout.xs=\"column\"  fxLayoutGap.xs=\"0\">\r\n            <tb-entity-subtype-autocomplete\r\n                    fxFlex\r\n                    class=\"mat-block\"\r\n                    formControlName=\"type\"\r\n                    [required]=\"true\"\r\n                    [entityType]=\"'DEVICE'\"\r\n            ></tb-entity-subtype-autocomplete>\r\n        </div>\r\n    </div>\r\n    <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\r\n        <button mat-button color=\"primary\"\r\n                type=\"button\"\r\n                [disabled]=\"(isLoading$ | async)\"\r\n                (click)=\"cancel()\" cdkFocusInitial>\r\n            Cancel\r\n        </button>\r\n        <button mat-button mat-raised-button color=\"primary\"\r\n                type=\"submit\"\r\n                [disabled]=\"(isLoading$ | async) || addEntityForm.invalid || !addEntityForm.dirty\">\r\n            Create\r\n        </button>\r\n    </div>\r\n</form>\r\n",
 | 
			
		||||
                "customHtml": "<form #addEntityForm=\"ngForm\" [formGroup]=\"addEntityFormGroup\"\n      (ngSubmit)=\"save($event)\" class=\"add-entity-form\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>Add gateway</h2>\n    <span class=\"flex-1\"></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 mat-dialog-content class=\"flex flex-col\">\n    <div class=\"flex flex-row gap-2 xs:flex-col xs:gap-0\">\n      <mat-form-field class=\"mat-block flex-1\">\n        <mat-label>Name</mat-label>\n        <input matInput formControlName=\"entityName\" required>\n        <mat-error *ngIf=\"addEntityFormGroup.get('entityName').hasError('required')\">\n          Gateway name is required.\n        </mat-error>\n      </mat-form-field>\n    </div>\n    <div class=\"flex flex-row gap-2 xs:flex-col xs:gap-0\">\n      <tb-entity-subtype-autocomplete\n          class=\"mat-block flex-1\"\n          formControlName=\"type\"\n          [required]=\"true\"\n          [entityType]=\"'DEVICE'\"\n      ></tb-entity-subtype-autocomplete>\n    </div>\n  </div>\n  <div mat-dialog-actions class=\"flex flex-row items-center justify-end\">\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) || addEntityForm.invalid || !addEntityForm.dirty\">\n      Create\n    </button>\n  </div>\n</form>\n",
 | 
			
		||||
                "customCss": ".add-entity-form {\r\n    min-width: 400px !important;\r\n}\r\n\r\n.add-entity-form .boolean-value-input {\r\n    padding-left: 5px;\r\n}\r\n\r\n.add-entity-form .boolean-value-input .checkbox-label {\r\n    margin-bottom: 8px;\r\n    color: rgba(0,0,0,0.54);\r\n    font-size: 12px;\r\n}\r\n\r\n.relations-list .header {\r\n    padding-right: 5px;\r\n    padding-bottom: 5px;\r\n    padding-left: 5px;\r\n}\r\n\r\n.relations-list .header .cell {\r\n    padding-right: 5px;\r\n    padding-left: 5px;\r\n    font-size: 12px;\r\n    font-weight: 700;\r\n    color: rgba(0, 0, 0, .54);\r\n    white-space: nowrap;\r\n}\r\n\r\n.relations-list .mat-form-field-infix {\r\n    width: auto !important;\r\n}\r\n\r\n.relations-list .body {\r\n    padding-right: 5px;\r\n    padding-bottom: 15px;\r\n    padding-left: 5px;\r\n}\r\n\r\n.relations-list .body .row {\r\n    padding-top: 5px;\r\n}\r\n\r\n.relations-list .body .cell {\r\n    padding-right: 5px;\r\n    padding-left: 5px;\r\n}\r\n\r\n.relations-list .body .md-button {\r\n    margin: 0;\r\n}\r\n\r\n",
 | 
			
		||||
                "customFunction": "let $injector = widgetContext.$scope.$injector;\r\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\r\nlet assetService = $injector.get(widgetContext.servicesMap.get('assetService'));\r\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\r\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\r\nlet entityRelationService = $injector.get(widgetContext.servicesMap.get('entityRelationService'));\r\nlet userSettingsService = $injector.get(widgetContext.servicesMap.get('userSettingsService'));\r\n\r\nopenAddEntityDialog();\r\n\r\nfunction openAddEntityDialog() {\r\n    customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\r\n}\r\n\r\nfunction AddEntityDialogController(instance) {\r\n    let vm = instance;\r\n    let userSettings;\r\n    userSettingsService.loadUserSettings().subscribe(settings=> {\r\n        userSettings = settings;\r\n        if (!userSettings.createdGatewaysCount) userSettings.createdGatewaysCount = 0;\r\n    });\r\n    \r\n\r\n    vm.addEntityFormGroup = vm.fb.group({\r\n     entityName: ['', [vm.validators.required]],\r\n     entityType: ['DEVICE'],\r\n     entityLabel: [''],\r\n     type: ['', [vm.validators.required]],\r\n    });\r\n\r\n    vm.cancel = function() {\r\n        vm.dialogRef.close(null);\r\n    };\r\n\r\n\r\n    vm.save = function($event) {\r\n        vm.addEntityFormGroup.markAsPristine();\r\n        saveEntityObservable().subscribe(\r\n            function (device) {\r\n                widgetContext.updateAliases();\r\n                userSettingsService.putUserSettings({ createdGatewaysCount: ++userSettings.createdGatewaysCount }).subscribe(_=>{\r\n                });\r\n                vm.dialogRef.close(null);\r\n                openCommandDialog(device, $event);\r\n            }\r\n        );\r\n    };\r\n    \r\n    function openCommandDialog(device, $event) {\r\n        vm.device = device;\r\n        let openCommandAction = widgetContext.actionsApi.getActionDescriptors(\"actionCellButton\").find(action => action.name == \"Launch command\");\r\n        widgetContext.actionsApi.handleWidgetAction($event, openCommandAction, device.id, device.name, {newDevice: true});\r\n        goToConfigState();\r\n    }\r\n\r\n    \r\n    function goToConfigState() {\r\n        const stateParams = {};\r\n        stateParams.entityId = vm.device.id;\r\n        stateParams.entityName = vm.device.name;\r\n        const newStateParams = {\r\n            targetEntityParamName: 'default',\r\n            new_gateway: {\r\n                entityId: vm.device.id,\r\n                entityName: vm.device.name\r\n            }\r\n        }\r\n        const params = {...stateParams, ...newStateParams};\r\n        widgetContext.stateController.openState('gateway_details', params, false);\r\n    }\r\n\r\n    function saveEntityObservable() {\r\n        const formValues = vm.addEntityFormGroup.value;\r\n        let entity = {\r\n            name: formValues.entityName,\r\n            type: formValues.type,\r\n            label: formValues.entityLabel,\r\n            additionalInfo: {\r\n                gateway: true\r\n            }\r\n        };\r\n        return deviceService.saveDevice(entity);\r\n    }\r\n}\r\n",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -592,7 +592,7 @@
 | 
			
		||||
          "settings": {
 | 
			
		||||
            "useMarkdownTextFunction": true,
 | 
			
		||||
            "markdownTextPattern": "# Markdown/HTML card \\n - **Current entity**: **${entityName}**. \\n - **Current value**: **${Random}**.",
 | 
			
		||||
            "markdownTextFunction": "var blockData = '';\nvar connectorsIndex = ctx.actionsApi.getActionDescriptors('elementClick').findIndex(action=>action.name==\"Connectors\");\nvar logsIndex = ctx.actionsApi.getActionDescriptors('elementClick').findIndex(action=>action.name==\"Logs\");\nfunction generateMatHeader(index) {\n    if( index !== undefined && index > -1) {\n         return `<mat-card-header class='tb-home-widget-link'  (click)=\"ctx.actionsApi.handleWidgetAction($event, ctx.actionsApi.getActionDescriptors('elementClick')[${index}], ctx.datasources[0].entity.id)\">`\n    } else {\n       return \"<mat-card-header >\" \n    }\n}\nfunction createDataBlock(value, label, dividerStyle, mobile, index) {\n    blockData += `\n        <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\" class=\" ${dividerStyle}\">\n            <div class=\"divider\"></div>\n            <mat-divider vertical style=\"height:100%\"></mat-divider>\n            ${generateMatHeader(index)}\n                <mat-card-subtitle>${label}</mat-card-subtitle>\n            </mat-card-header>\n            <mat-card-content> ${value}</mat-card-content>\n        </mat-card>`;\n}\ncreateDataBlock(data[0].Status, \"Status\", data[0].Status === \"Active\"? 'divider-green' : 'divider-red');\ncreateDataBlock(data[0].Name, \"Gateway Name\", '', ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\", '');\ncreateDataBlock(\n    `<span style=\"color:rgb(25,128,56)\">${(data[1]?data[1].count:0)} </span>`\n    + \" | \" + \n    `<span style=\"color:rgb(203,37,48)\">${(data[2]?data[2][\"count 2\"]:0)} </span>`\n    , \"Devices <span class='tb-hint' style='padding-left: 0'>(Active | Inactive)</span>\", '');\ncreateDataBlock(\n    `<span style=\"color:rgb(25,128,56)\">${(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0)} </span>`\n    + \" | \" + \n    `<span style=\"color:rgb(203,37,48)\">${(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0)} </span>`\n    , \"Connectors <span class='tb-hint' style='padding-left: 0'>(Enabled | Disabled)</span>\", '', '',  connectorsIndex);\ncreateDataBlock(data[0].ALL_ERRORS_COUNT || 0, \"Errors\", (data[0].ALL_ERRORS_COUNT || 0) === 0 ? 'divider-green' : 'divider-red', '', logsIndex);\nreturn `<div fxLayout=\"row wrap\" fxLayoutGap=\"8px\" class=\"cards-container\">${blockData}</div>`;",
 | 
			
		||||
            "markdownTextFunction": "var blockData = '';\nvar connectorsIndex = ctx.actionsApi.getActionDescriptors('elementClick').findIndex(action=>action.name==\"Connectors\");\nvar logsIndex = ctx.actionsApi.getActionDescriptors('elementClick').findIndex(action=>action.name==\"Logs\");\nfunction generateMatHeader(index) {\n    if( index !== undefined && index > -1) {\n         return `<mat-card-header class='tb-home-widget-link'  (click)=\"ctx.actionsApi.handleWidgetAction($event, ctx.actionsApi.getActionDescriptors('elementClick')[${index}], ctx.datasources[0].entity.id)\">`\n    } else {\n       return \"<mat-card-header >\" \n    }\n}\nfunction createDataBlock(value, label, dividerStyle, mobile, index) {\n    blockData += `\n        <mat-card style=\"flex-grow: 1; width: ${mobile? '100%': 'auto'}; min-height: ${mobile? 'auto': '57px'}\" class=\" ${dividerStyle}\">\n            <div class=\"divider\"></div>\n            <mat-divider vertical style=\"height:100%\"></mat-divider>\n            ${generateMatHeader(index)}\n                <mat-card-subtitle>${label}</mat-card-subtitle>\n            </mat-card-header>\n            <mat-card-content> ${value}</mat-card-content>\n        </mat-card>`;\n}\ncreateDataBlock(data[0].Status, \"Status\", data[0].Status === \"Active\"? 'divider-green' : 'divider-red');\ncreateDataBlock(data[0].Name, \"Gateway Name\", '', ctx.isMobile);\ncreateDataBlock(data[0].Type, \"Gateway Type\", '');\ncreateDataBlock(\n    `<span style=\"color:rgb(25,128,56)\">${(data[1]?data[1].count:0)} </span>`\n    + \" | \" + \n    `<span style=\"color:rgb(203,37,48)\">${(data[2]?data[2][\"count 2\"]:0)} </span>`\n    , \"Devices <span class='tb-hint' style='padding-left: 0'>(Active | Inactive)</span>\", '');\ncreateDataBlock(\n    `<span style=\"color:rgb(25,128,56)\">${(data[0].active_connectors?JSON.parse(data[0].active_connectors).length:0)} </span>`\n    + \" | \" + \n    `<span style=\"color:rgb(203,37,48)\">${(data[0].inactive_connectors?JSON.parse(data[0].inactive_connectors).length:0)} </span>`\n    , \"Connectors <span class='tb-hint' style='padding-left: 0'>(Enabled | Disabled)</span>\", '', '',  connectorsIndex);\ncreateDataBlock(data[0].ALL_ERRORS_COUNT || 0, \"Errors\", (data[0].ALL_ERRORS_COUNT || 0) === 0 ? 'divider-green' : 'divider-red', '', logsIndex);\nreturn `<div class=\"cards-container flex flex-row flex-wrap gap-2\">${blockData}</div>`;",
 | 
			
		||||
            "applyDefaultMarkdownStyle": false,
 | 
			
		||||
            "markdownCss": ".divider {\n    position: absolute;\n    width: 3px;\n    top: 8px;\n    border-radius: 2px;\n    bottom: 8px;\n    border: 1px solid rgba(31, 70, 144, 1);\n    background-color: rgba(31, 70, 144, 1);\n    left: 10px;\n}\n.divider-green .divider {\n    border: 1px solid rgb(25,128,56);\n    background-color: rgb(25,128,56);\n}\n\n.divider-green .mat-mdc-card-content {\n    color: rgb(25,128,56);\n}\n\n.divider-red .divider {\n    border: 1px solid rgb(203,37,48);\n    background-color: rgb(203,37,48);\n}\n\n.divider-red .mat-mdc-card-content {\n    color: rgb(203,37,48);\n}\n\n.mdc-card {\n    position: relative;\n    padding-left: 10px;\n    margin-bottom: 1px;\n}\n\n.mat-mdc-card-subtitle {\n    font-weight: 400;\n    font-size: 12px;\n}\n\n.mat-mdc-card-header {\n    padding: 8px 16px 0;\n}\n\n.mat-mdc-card-content:last-child {\n    padding-bottom: 8px;\n    font-size: 16px;\n}\n\n.cards-container {\n    height: calc(100% - 1px);\n    justify-content: stretch;\n    align-items: center;\n    margin-bottom: 1px;\n}\n\n::ng-deep.tb-home-widget-link > div {\n    flex-grow: 1;\n    cursor: pointer;\n}\n\n .tb-home-widget-link {\n     width: 100%;\n }\n\n .tb-home-widget-link:hover::after{\n     color: inherit;\n }\n \n .tb-home-widget-link::after{\n    content: 'arrow_forward';\n    display: inline-block;\n    transform: rotate(315deg);\n    font-family: 'Material Icons';\n    font-weight: normal;\n    font-style: normal;\n    font-size: 18px;\n    color: rgba(0, 0, 0, 0.12);\n    vertical-align: bottom;\n    margin-left: 6px;\n}"
 | 
			
		||||
          },
 | 
			
		||||
@ -1916,7 +1916,7 @@
 | 
			
		||||
                "useShowWidgetActionFunction": null,
 | 
			
		||||
                "showWidgetActionFunction": "return true;",
 | 
			
		||||
                "type": "customPretty",
 | 
			
		||||
                "customHtml": "<div class=\"container\">\n    <mat-toolbar fxLayout=\"row\" color=\"primary\">\n        <h2>{{ 'gateway.launch-command' | translate }}</h2>\n        <span fxFlex></span>\n        <div [tb-help]=\"'gatewayInstall'\"></div>\n        <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n            <mat-icon class=\"material-icons\">close</mat-icon>\n        </button>\n    </mat-toolbar>\n    <tb-gateway-command [deviceId]=\"entityId\"></tb-gateway-command>\n    <div mat-dialog-actions fxLayout=\"row\" fxLayoutAlign=\"end center\">\n        <button mat-button color=\"primary\"\n            type=\"button\"\n            (click)=\"cancel()\" cdkFocusInitial>\n            {{ 'action.close' | translate }}\n        </button>\n    </div>\n</div>\n",
 | 
			
		||||
                "customHtml": "<div class=\"container\">\n  <mat-toolbar class=\"flex flex-row\" color=\"primary\">\n    <h2>{{ 'gateway.launch-command' | translate }}</h2>\n    <span class=\"flex-1\"></span>\n    <div [tb-help]=\"'gatewayInstall'\"></div>\n    <button mat-icon-button (click)=\"cancel()\" type=\"button\">\n      <mat-icon class=\"material-icons\">close</mat-icon>\n    </button>\n  </mat-toolbar>\n  <tb-gateway-command [deviceId]=\"entityId\"></tb-gateway-command>\n  <div mat-dialog-actions class=\"flex flex-row items-center justify-end\">\n    <button mat-button color=\"primary\"\n            type=\"button\"\n            (click)=\"cancel()\" cdkFocusInitial>\n      {{ 'action.close' | translate }}\n    </button>\n  </div>\n</div>\n",
 | 
			
		||||
                "customCss": ".container {\n    display: grid;\n    grid-template-rows: min-content minmax(auto, 1fr) min-content;\n    height: 100%;\n    max-height: 100vh;\n    width: 600px;\n    max-width: 100%;\n}",
 | 
			
		||||
                "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\n\nopenCommands();\n\nfunction openCommands() {\n    customDialog.customDialog(htmlTemplate, CommandsDialogController, {panelClass: \"test\"}).subscribe();\n}\n\nfunction CommandsDialogController(instance) {\n    let vm = instance;\n    \n    vm.entityId = entityId.id;\n\n    vm.cancel = function() {\n        vm.dialogRef.close(null);\n    };\n}\n",
 | 
			
		||||
                "customResources": [],
 | 
			
		||||
@ -1998,7 +1998,7 @@
 | 
			
		||||
          "padding": "8px",
 | 
			
		||||
          "settings": {
 | 
			
		||||
            "useMarkdownTextFunction": true,
 | 
			
		||||
            "markdownTextFunction": "let buttonsHtml = \"\" \nctx.actionsApi.getActionDescriptors('elementClick').forEach((btn, index)=>{\n    let disabled =false;\n    if (index == 2) {\n        disabled = data[0] && data[0].RemoteLoggingLevel ? data[0].RemoteLoggingLevel == \"NONE\" : true;\n    } else if (index == 4) {\n        const conf = data[0].general_configuration? JSON.parse(data[0].general_configuration): {};\n        disabled = !conf.remoteShell;\n    }\n    buttonsHtml += `<button mat-raised-button disabled=${disabled} color=\"primary\"(click)=\"ctx.actionsApi.handleWidgetAction($event, ctx.actionsApi.getActionDescriptors('elementClick')[${index}], ctx.datasources[0].entity.id)\" fxFlex fxflex.md=\"50\">${btn.displayName}</button>`\n});\n\nreturn `<div class=\"action-buttons-container\" fxLayout=\"columnd\" fxLayout.md=\"row wrap\" fxLayoutGap=\"5px\" >${buttonsHtml}</div>`;",
 | 
			
		||||
            "markdownTextFunction": "let buttonsHtml = \"\" \nctx.actionsApi.getActionDescriptors('elementClick').forEach((btn, index)=>{\n    let disabled =false;\n    if (index == 2) {\n        disabled = data[0] && data[0].RemoteLoggingLevel ? data[0].RemoteLoggingLevel == \"NONE\" : true;\n    } else if (index == 4) {\n        const conf = data[0].general_configuration? JSON.parse(data[0].general_configuration): {};\n        disabled = !conf.remoteShell;\n    }\n    buttonsHtml += `<button mat-raised-button disabled=${disabled} color=\"primary\"(click)=\"ctx.actionsApi.handleWidgetAction($event, ctx.actionsApi.getActionDescriptors('elementClick')[${index}], ctx.datasources[0].entity.id)\" class=\"flex-1 md:max-w-50% md:flex-full\">${btn.displayName}</button>`\n});\n\nreturn `<div class=\"action-buttons-container flex flex-col gap-1.25 md:flex-row md:flex-wrap\">${buttonsHtml}</div>`;",
 | 
			
		||||
            "applyDefaultMarkdownStyle": false,
 | 
			
		||||
            "markdownCss": ".action-buttons-container {\r\n    display: flex;\r\n    flex-wrap: wrap;\r\n    flex-direction: row;\r\n    height: 100%;\r\n    width: 100%;\r\n    align-content: start;\r\n}\r\n\r\nbutton {\r\n    flex-grow: 1;\r\n    margin: 10px;\r\n    min-width: 150px;\r\n    height: auto;\r\n}"
 | 
			
		||||
          },
 | 
			
		||||
@ -2605,7 +2605,7 @@
 | 
			
		||||
          "padding": "0px",
 | 
			
		||||
          "settings": {
 | 
			
		||||
            "useMarkdownTextFunction": false,
 | 
			
		||||
            "markdownTextPattern": "<div style=\"width: 100%; height: 100%; padding: 0;\" fxFlex fxLayout=\"column\">\n  <mat-tab-group class=devices-tabs>\n    <mat-tab label=\"All\" value=\"gateway_devices_0\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_0\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${mqttCount}\" label=\"MQTT\" value=\"gateway_devices_1\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_1\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${modbusCount}\" label=\"MODBUS\" value=\"gateway_devices_2\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_2\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${grpcCount}\" label=\"GRPC\" value=\"gateway_devices_3\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_3\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${opcuaCount}\" label=\"OPCUA\" value=\"gateway_devices_4\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_4\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${bleCount}\" label=\"BLE\" value=\"gateway_devices_6\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_6\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${requestCount}\" label=\"REQUEST\" value=\"gateway_devices_7\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_7\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${canCount}\" label=\"CAN\" value=\"gateway_devices_8\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_8\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${bacnetCount}\" label=\"BACNET\" value=\"gateway_devices_9\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_9\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${odbcCount}\" label=\"ODBC\" value=\"gateway_devices_10\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_10\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${restCount}\" label=\"REST\" value=\"gateway_devices_11\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_11\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${snmpCount}\" label=\"SNMP\" value=\"gateway_devices_12\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_12\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${ftpCount}\" label=\"FTP\" value=\"gateway_devices_13\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_13\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${socketCount}\" label=\"SOCKET\" value=\"gateway_devices_14\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_14\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${xmppCount}\" label=\"XMPP\" value=\"gateway_devices_15\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_15\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${ocppCount}\" label=\"OCPP\" value=\"gateway_devices_16\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_16\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${customCount}\" label=\"CUSTOM\" value=\"gateway_devices_17\">\n      <tb-dashboard-state [ctx]=\"ctx\" fxFlex syncParentStateParams=\"true\" stateId=\"gateway_devices_17\"></tb-dashboard-state>\n    </mat-tab>\n  </mat-tab-group>\n</div>\n",
 | 
			
		||||
            "markdownTextPattern": "<div style=\"padding: 0;\" class=\"flex size-full flex-1 flex-col\">\n  <mat-tab-group class=devices-tabs>\n    <mat-tab label=\"All\" value=\"gateway_devices_0\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_0\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${mqttCount}\" label=\"MQTT\" value=\"gateway_devices_1\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_1\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${modbusCount}\" label=\"MODBUS\" value=\"gateway_devices_2\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_2\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${grpcCount}\" label=\"GRPC\" value=\"gateway_devices_3\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_3\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${opcuaCount}\" label=\"OPCUA\" value=\"gateway_devices_4\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_4\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${bleCount}\" label=\"BLE\" value=\"gateway_devices_6\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_6\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${requestCount}\" label=\"REQUEST\" value=\"gateway_devices_7\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_7\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${canCount}\" label=\"CAN\" value=\"gateway_devices_8\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_8\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${bacnetCount}\" label=\"BACNET\" value=\"gateway_devices_9\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_9\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${odbcCount}\" label=\"ODBC\" value=\"gateway_devices_10\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_10\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${restCount}\" label=\"REST\" value=\"gateway_devices_11\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_11\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${snmpCount}\" label=\"SNMP\" value=\"gateway_devices_12\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_12\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${ftpCount}\" label=\"FTP\" value=\"gateway_devices_13\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_13\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${socketCount}\" label=\"SOCKET\" value=\"gateway_devices_14\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_14\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${xmppCount}\" label=\"XMPP\" value=\"gateway_devices_15\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_15\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${ocppCount}\" label=\"OCPP\" value=\"gateway_devices_16\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_16\"></tb-dashboard-state>\n    </mat-tab>\n    <mat-tab *ngIf=\"${customCount}\" label=\"CUSTOM\" value=\"gateway_devices_17\">\n      <tb-dashboard-state [ctx]=\"ctx\" class=\"flex-1\" syncParentStateParams=\"true\" stateId=\"gateway_devices_17\"></tb-dashboard-state>\n    </mat-tab>\n  </mat-tab-group>\n</div>\n",
 | 
			
		||||
            "applyDefaultMarkdownStyle": false,
 | 
			
		||||
            "markdownCss": ".mat-mdc-form-field-subscript-wrapper {\n    display: none !important;\n}\n\n.devices-tabs {\n    height: 100%;\n}\n\n::ng-deep .mat-mdc-tab-body-wrapper {\n  height: 100%;\n}"
 | 
			
		||||
          },
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user