Commit 37c8cd157d845f0e5298c32a34b27b02746bc787
1 parent
6a47f022
UI: Migrate gateway widgets and gateways demo dashboard to 3.0
Showing
7 changed files
with
118 additions
and
44 deletions
... | ... | @@ -128,13 +128,14 @@ |
128 | 128 | "actions": { |
129 | 129 | "headerButton": [ |
130 | 130 | { |
131 | - "id": "70837a9d-c3de-a9a7-03c5-dccd14998758", | |
132 | 131 | "name": "Add device", |
133 | 132 | "icon": "add", |
134 | 133 | "type": "customPretty", |
135 | - "customHtml": "<md-dialog aria-label=\"Add entity\" style=\"width: 480px\">\n <form name=\"addDeviceForm\" ng-submit=\"vm.save()\">\n <md-toolbar>\n <div class=\"md-toolbar-tools\">\n <h2>Add device</h2>\n <span flex></span>\n <md-button class=\"md-icon-button\" ng-click=\"vm.cancel()\">\n <ng-md-icon icon=\"close\" aria-label=\"Close\"></ng-md-icon>\n </md-button>\n </div>\n </md-toolbar>\n <md-progress-linear class=\"md-warn\" md-mode=\"indeterminate\" ng-disabled=\"!$root.loading && !vm.loading\" ng-show=\"$root.loading || vm.loading\"></md-progress-linear>\n <span style=\"min-height: 5px;\" flex=\"\" ng-show=\"!$root.loading && !vm.loading\"></span>\n <md-dialog-content>\n <div class=\"md-dialog-content\">\n <fieldset ng-disabled=\"$root.loading || vm.loading\">\n <md-input-container flex class=\"md-block\">\n <label>Device name</label>\n <input ng-model=\"vm.deviceName\" name=deviceName required>\n <div ng-messages=\"addDeviceForm.deviceName.$error\">\n <div ng-message=\"required\">Device name is required.</div>\n </div>\n </md-input-container>\n <div flex layout=\"row\">\n <md-input-container flex=\"50\" class=\"md-block\">\n <label>Latitude</label>\n <input type=\"number\" step=\"any\" name=\"latitude\" ng-model=\"vm.attributes.latitude\">\n </md-input-container>\n <md-input-container flex=\"50\" class=\"md-block\">\n <label>Longitude</label>\n <input type=\"number\" step=\"any\" name=\"longitude\" ng-model=\"vm.attributes.longitude\">\n </md-input-container>\n </div>\n <md-input-container class=\"md-block\">\n <label>Label</label>\n <input name=\"deviceLabel\" ng-model=\"vm.deviceLabel\">\n </md-input-container>\n </fieldset>\n </div>\n </md-dialog-content>\n <md-dialog-actions>\n <md-button type=\"submit\" ng-disabled=\"vm.loading || addDeviceForm.$invalid || !addDeviceForm.$dirty\" class=\"md-raised md-primary\">Create</md-button>\n <md-button ng-click=\"vm.cancel()\" class=\"md-primary\">Cancel</md-button>\n </md-dialog-actions>\n </form>\n</md-dialog>\n", | |
134 | + "customHtml": "<form #addDeviceForm=\"ngForm\" [formGroup]=\"addDeviceFormGroup\"\n (ngSubmit)=\"save()\" style=\"width: 480px;\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Add device</h2>\n <span fxFlex></span>\n <button mat-button mat-icon-button\n (click)=\"cancel()\"\n 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>\n <div class=\"mat-padding\" fxLayout=\"column\">\n <mat-form-field class=\"mat-block\">\n <mat-label>Device name</mat-label>\n <input matInput formControlName=\"deviceName\" required>\n <mat-error *ngIf=\"addDeviceFormGroup.get('deviceName').hasError('required')\">\n Device name is required.\n </mat-error>\n </mat-form-field>\n <div formGroupName=\"attributes\" fxFlex fxLayout=\"row\" fxLayoutGap=\"8px\">\n <mat-form-field fxFlex=\"50\" class=\"mat-block\">\n <mat-label>Latitude</mat-label>\n <input type=\"number\" step=\"any\" matInput formControlName=\"latitude\">\n </mat-form-field>\n <mat-form-field fxFlex=\"50\" class=\"mat-block\">\n <mat-label>Longitude</mat-label>\n <input type=\"number\" step=\"any\" matInput formControlName=\"longitude\">\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\">\n <mat-label>Label</mat-label>\n <input matInput formControlName=\"deviceLabel\">\n </mat-form-field>\n </div> \n </div>\n <div mat-dialog-actions fxLayout=\"row\">\n <span fxFlex></span>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || addDeviceForm.invalid || !addDeviceForm.dirty\">\n Create\n </button>\n <button mat-button color=\"primary\"\n style=\"margin-right: 20px;\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n </div>\n</form>\n", | |
136 | 135 | "customCss": "", |
137 | - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n $q = $injector.get('$q'),\n $rootScope = $injector.get('$rootScope'),\n types = $injector.get('types'),\n deviceService = $injector.get('deviceService'),\n attributeService = $injector.get('attributeService');\n\nopenAddDeviceDialog();\n\nfunction openAddDeviceDialog() {\n $mdDialog.show({\n controller: ['$scope', '$mdDialog',\n AddDeviceDialogController\n ],\n controllerAs: 'vm',\n template: htmlTemplate,\n parent: angular.element($document[0].body),\n targetEvent: $event,\n multiple: true,\n clickOutsideToClose: false\n });\n}\n\nfunction AddDeviceDialogController($scope, $mdDialog) {\n let vm = this;\n vm.types = types;\n vm.attributes = {};\n vm.deviceType = \"gateway\";\n\n vm.cancel = () => {\n $mdDialog.hide();\n };\n\n vm.save = () => {\n vm.loading = true;\n $scope.addDeviceForm.$setPristine();\n let device = {\n additionalInfo: {gateway: true},\n name: vm.deviceName,\n type: vm.deviceType,\n label: vm.deviceLabel\n };\n deviceService.saveDevice(device).then(\n (device) => {\n saveAttributes(device.id).then(\n () => {\n vm.loading = false;\n updateAliasData();\n $mdDialog.hide();\n }\n );\n },\n () => {\n vm.loading = false;\n }\n );\n };\n\n function saveAttributes(entityId) {\n let attributesArray = [];\n for (let key in vm.attributes) {\n attributesArray.push({\n key: key,\n value: vm.attributes[key]\n });\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(\n entityId.entityType, entityId.id,\n \"SERVER_SCOPE\", attributesArray);\n } else {\n return $q.when([]);\n }\n }\n\n function updateAliasData() {\n let aliasIds = [];\n for (let id in widgetContext.aliasController\n .resolvedAliases) {\n aliasIds.push(id);\n }\n let tasks = [];\n aliasIds.forEach((aliasId) => {\n widgetContext.aliasController\n .setAliasUnresolved(aliasId);\n tasks.push(widgetContext.aliasController\n .getAliasInfo(aliasId));\n });\n $q.all(tasks).then(() => {\n $rootScope.$broadcast(\n 'widgetForceReInit');\n });\n }\n}" | |
136 | + "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\nopenAddDeviceDialog();\n\nfunction openAddDeviceDialog() {\n customDialog.customDialog(htmlTemplate, AddDeviceDialogController).subscribe();\n}\n\nfunction AddDeviceDialogController(instance) {\n let vm = instance;\n \n vm.addDeviceFormGroup = vm.fb.group({\n deviceName: ['', [vm.validators.required]],\n deviceLabel: [''],\n attributes: vm.fb.group({\n latitude: [null],\n longitude: [null]\n }) \n });\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n vm.save = function() {\n vm.addDeviceFormGroup.markAsPristine();\n let device = {\n additionalInfo: {gateway: true},\n name: vm.addDeviceFormGroup.get('deviceName').value,\n type: 'gateway',\n label: vm.addDeviceFormGroup.get('deviceLabel').value\n };\n deviceService.saveDevice(device).subscribe(\n function (device) {\n saveAttributes(device.id).subscribe(\n function () {\n widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n }\n );\n };\n \n function saveAttributes(entityId) {\n let attributes = vm.addDeviceFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}\n", | |
137 | + "customResources": [], | |
138 | + "id": "70837a9d-c3de-a9a7-03c5-dccd14998758" | |
138 | 139 | } |
139 | 140 | ], |
140 | 141 | "actionCellButton": [ |
... | ... | @@ -156,20 +157,21 @@ |
156 | 157 | "setEntityId": true |
157 | 158 | }, |
158 | 159 | { |
159 | - "id": "242671f3-76c6-6982-7acc-6f12addf0ccc", | |
160 | 160 | "name": "Edit device", |
161 | 161 | "icon": "edit", |
162 | 162 | "type": "customPretty", |
163 | - "customHtml": "<md-dialog aria-label=\"Edit entity\" style=\"width: 480px\">\n <form name=\"editDeviceForm\" ng-submit=\"vm.save()\">\n <md-toolbar>\n <div class=\"md-toolbar-tools\">\n <h2>Edit device</h2>\n <span flex></span>\n <md-button class=\"md-icon-button\" ng-click=\"vm.cancel()\">\n <ng-md-icon icon=\"close\" aria-label=\"Close\"></ng-md-icon>\n </md-button>\n </div>\n </md-toolbar>\n <md-progress-linear class=\"md-warn\" md-mode=\"indeterminate\" ng-disabled=\"!$root.loading && !vm.loading\" ng-show=\"$root.loading || vm.loading\"></md-progress-linear>\n <span style=\"min-height: 5px;\" flex=\"\" ng-show=\"!$root.loading && !vm.loading\"></span>\n <md-dialog-content>\n <div class=\"md-dialog-content\">\n <fieldset ng-disabled=\"$root.loading || vm.loading\">\n <md-input-container flex class=\"md-block\">\n <label>Device name</label>\n <input ng-model=\"vm.device.name\" name=deviceName required>\n <div ng-messages=\"editDeviceForm.deviceName.$error\">\n <div ng-message=\"required\">Device name is required.</div>\n </div>\n </md-input-container>\n <!--<div flex layout=\"row\">-->\n <!--<tb-entity-subtype-autocomplete flex=\"50\"-->\n <!-- ng-disabled=\"true\"-->\n <!-- tb-required=\"true\"-->\n <!-- the-form=\"editDeviceForm\"-->\n <!-- ng-model=\"vm.device.type\"-->\n <!-- entity-type=\"vm.types.entityType.device\">-->\n <!--</tb-entity-subtype-autocomplete>-->\n <!-- <md-input-container flex=\"50\" class=\"md-block\">-->\n <!-- <label>Label</label>-->\n <!-- <input name=\"deviceLabel\" ng-model=\"vm.device.label\">-->\n <!-- </md-input-container>-->\n <!--</div>-->\n <div flex layout=\"row\">\n <md-input-container flex=\"50\" class=\"md-block\">\n <label>Latitude</label>\n <input type=\"number\" step=\"any\" name=\"latitude\" ng-model=\"vm.attributes.latitude\">\n </md-input-container>\n <md-input-container flex=\"50\" class=\"md-block\">\n <label>Longitude</label>\n <input type=\"number\" step=\"any\" name=\"longitude\" ng-model=\"vm.attributes.longitude\">\n </md-input-container>\n </div>\n <md-input-container class=\"md-block\">\n <label>Label</label>\n <input name=\"deviceLabel\" ng-model=\"vm.device.label\">\n </md-input-container>\n </fieldset>\n </div>\n </md-dialog-content>\n <md-dialog-actions>\n <md-button type=\"submit\" ng-disabled=\"vm.loading || editDeviceForm.$invalid || !editDeviceForm.$dirty\" class=\"md-raised md-primary\">Create</md-button>\n <md-button ng-click=\"vm.cancel()\" class=\"md-primary\">Cancel</md-button>\n </md-dialog-actions>\n </form>\n</md-dialog>", | |
163 | + "customHtml": "<form #editDeviceForm=\"ngForm\" [formGroup]=\"editDeviceFormGroup\"\n (ngSubmit)=\"save()\" style=\"width: 480px;\">\n <mat-toolbar fxLayout=\"row\" color=\"primary\">\n <h2>Edit device</h2>\n <span fxFlex></span>\n <button mat-button mat-icon-button\n (click)=\"cancel()\"\n 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>\n <div class=\"mat-padding\" fxLayout=\"column\">\n <mat-form-field class=\"mat-block\">\n <mat-label>Device name</mat-label>\n <input matInput formControlName=\"deviceName\" required>\n <mat-error *ngIf=\"editDeviceFormGroup.get('deviceName').hasError('required')\">\n Device name is required.\n </mat-error>\n </mat-form-field>\n <div formGroupName=\"attributes\" fxFlex fxLayout=\"row\" fxLayoutGap=\"8px\">\n <mat-form-field fxFlex=\"50\" class=\"mat-block\">\n <mat-label>Latitude</mat-label>\n <input type=\"number\" step=\"any\" matInput formControlName=\"latitude\">\n </mat-form-field>\n <mat-form-field fxFlex=\"50\" class=\"mat-block\">\n <mat-label>Longitude</mat-label>\n <input type=\"number\" step=\"any\" matInput formControlName=\"longitude\">\n </mat-form-field>\n </div>\n <mat-form-field class=\"mat-block\">\n <mat-label>Label</mat-label>\n <input matInput formControlName=\"deviceLabel\">\n </mat-form-field>\n </div> \n </div>\n <div mat-dialog-actions fxLayout=\"row\">\n <span fxFlex></span>\n <button mat-button mat-raised-button color=\"primary\"\n type=\"submit\"\n [disabled]=\"(isLoading$ | async) || editDeviceForm.invalid || !editDeviceForm.dirty\">\n Update\n </button>\n <button mat-button color=\"primary\"\n style=\"margin-right: 20px;\"\n type=\"button\"\n [disabled]=\"(isLoading$ | async)\"\n (click)=\"cancel()\" cdkFocusInitial>\n Cancel\n </button>\n </div>\n</form>\n", | |
164 | 164 | "customCss": "/*=======================================================================*/\n/*========== There are two examples: for edit and add entity ==========*/\n/*=======================================================================*/\n/*======================== Edit entity example ========================*/\n/*=======================================================================*/\n/*\n.edit-entity-form md-input-container {\n padding-right: 10px;\n}\n\n.edit-entity-form .boolean-value-input {\n padding-left: 5px;\n}\n\n.edit-entity-form .boolean-value-input .checkbox-label {\n margin-bottom: 8px;\n color: rgba(0,0,0,0.54);\n font-size: 12px;\n}\n\n.relations-list .header {\n padding-right: 5px;\n padding-bottom: 5px;\n padding-left: 5px;\n}\n\n.relations-list .header .cell {\n padding-right: 5px;\n padding-left: 5px;\n font-size: 12px;\n font-weight: 700;\n color: rgba(0, 0, 0, .54);\n white-space: nowrap;\n}\n\n.relations-list .body {\n padding-right: 5px;\n padding-bottom: 15px;\n padding-left: 5px;\n}\n\n.relations-list .body .row {\n padding-top: 5px;\n}\n\n.relations-list .body .cell {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.relations-list .body md-autocomplete-wrap md-input-container {\n height: 30px;\n}\n\n.relations-list .body .md-button {\n margin: 0;\n}\n\n.relations-list.old-relations tb-entity-select tb-entity-autocomplete button {\n display: none;\n} \n*/\n/*========================================================================*/\n/*========================= Add entity example =========================*/\n/*========================================================================*/\n/*\n.add-entity-form md-input-container {\n padding-right: 10px;\n}\n\n.add-entity-form .boolean-value-input {\n padding-left: 5px;\n}\n\n.add-entity-form .boolean-value-input .checkbox-label {\n margin-bottom: 8px;\n color: rgba(0,0,0,0.54);\n font-size: 12px;\n}\n\n.relations-list .header {\n padding-right: 5px;\n padding-bottom: 5px;\n padding-left: 5px;\n}\n\n.relations-list .header .cell {\n padding-right: 5px;\n padding-left: 5px;\n font-size: 12px;\n font-weight: 700;\n color: rgba(0, 0, 0, .54);\n white-space: nowrap;\n}\n\n.relations-list .body {\n padding-right: 5px;\n padding-bottom: 15px;\n padding-left: 5px;\n}\n\n.relations-list .body .row {\n padding-top: 5px;\n}\n\n.relations-list .body .cell {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.relations-list .body md-autocomplete-wrap md-input-container {\n height: 30px;\n}\n\n.relations-list .body .md-button {\n margin: 0;\n}\n*/\n", |
165 | - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n $q = $injector.get('$q'),\n $rootScope = $injector.get('$rootScope'),\n types = $injector.get('types'),\n deviceService = $injector.get('deviceService'),\n attributeService = $injector.get('attributeService');\n \nopenEditDeviceDialog();\n\nfunction openEditDeviceDialog() {\n $mdDialog.show({\n controller: ['$scope','$mdDialog', EditDeviceDialogController],\n controllerAs: 'vm',\n template: htmlTemplate,\n parent: angular.element($document[0].body),\n targetEvent: $event,\n multiple: true,\n clickOutsideToClose: false\n });\n}\n\nfunction EditDeviceDialogController($scope,$mdDialog) {\n let vm = this;\n vm.types = types;\n vm.loading = false;\n vm.attributes = {};\n \n getEntityInfo();\n \n function getEntityInfo() {\n vm.loading = true;\n deviceService.getDevice(entityId.id).then(\n (device) => {\n attributeService.getEntityAttributesValues(entityId.entityType, entityId.id, 'SERVER_SCOPE').then(\n (data) => {\n if (data.length) {\n getEntityAttributes(data);\n }\n vm.device = device;\n vm.loading = false;\n } \n );\n }\n )\n }\n \n vm.cancel = function() {\n $mdDialog.hide();\n };\n \n vm.save = () => {\n vm.loading = true;\n $scope.editDeviceForm.$setPristine();\n deviceService.saveDevice(vm.device).then(\n () => {\n saveAttributes().then(\n () => {\n updateAliasData();\n vm.loading = false;\n $mdDialog.hide();\n }\n );\n },\n () => {\n vm.loading = false;\n }\n );\n }\n \n function getEntityAttributes(attributes) {\n for (let i = 0; i < attributes.length; i++) {\n vm.attributes[attributes[i].key] = attributes[i].value; \n }\n }\n \n function saveAttributes() {\n let attributesArray = [];\n for (let key in vm.attributes) {\n attributesArray.push({key: key, value: vm.attributes[key]});\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId.entityType, entityId.id, \"SERVER_SCOPE\", attributesArray);\n } else {\n return $q.when([]);\n }\n }\n \n function updateAliasData() {\n let aliasIds = [];\n for (let id in widgetContext.aliasController.resolvedAliases) {\n aliasIds.push(id);\n }\n let tasks = [];\n aliasIds.forEach((aliasId) => {\n widgetContext.aliasController.setAliasUnresolved(aliasId);\n tasks.push(widgetContext.aliasController.getAliasInfo(aliasId));\n });\n console.log(widgetContext);\n $q.all(tasks).then(() => {\n $rootScope.$broadcast('widgetForceReInit');\n });\n }\n}\n" | |
165 | + "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\nopenEditDeviceDialog();\n\nfunction openEditDeviceDialog() {\n customDialog.customDialog(htmlTemplate, EditDeviceDialogController).subscribe();\n}\n\nfunction EditDeviceDialogController(instance) {\n let vm = instance;\n \n vm.device = null;\n vm.attributes = {};\n \n vm.editDeviceFormGroup = vm.fb.group({\n deviceName: ['', [vm.validators.required]],\n deviceLabel: [''],\n attributes: vm.fb.group({\n latitude: [null],\n longitude: [null]\n }) \n });\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n vm.save = function() {\n vm.editDeviceFormGroup.markAsPristine();\n vm.device.name = vm.editDeviceFormGroup.get('deviceName').value;\n vm.device.label = vm.editDeviceFormGroup.get('deviceLabel').value;\n deviceService.saveDevice(vm.device).subscribe(\n function () {\n saveAttributes().subscribe(\n function () {\n widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n }\n );\n };\n \n getEntityInfo();\n \n function getEntityInfo() {\n deviceService.getDevice(entityId.id).subscribe(\n function (device) {\n attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE',\n ['latitude', 'longitude']).subscribe(\n function (attributes) {\n for (let i = 0; i < attributes.length; i++) {\n vm.attributes[attributes[i].key] = attributes[i].value; \n }\n vm.device = device;\n vm.editDeviceFormGroup.patchValue(\n {\n deviceName: vm.device.name,\n deviceLabel: vm.device.label,\n attributes: {\n latitude: vm.attributes.latitude,\n longitude: vm.attributes.longitude\n }\n }, {emitEvent: false}\n );\n } \n );\n }\n ); \n }\n \n function saveAttributes() {\n let attributes = vm.editDeviceFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, 'SERVER_SCOPE', attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}\n", | |
166 | + "customResources": [], | |
167 | + "id": "242671f3-76c6-6982-7acc-6f12addf0ccc" | |
166 | 168 | }, |
167 | 169 | { |
168 | - "id": "862ec2b7-fbcf-376e-f85f-b77c07f36efa", | |
169 | 170 | "name": "Delete device", |
170 | 171 | "icon": "delete", |
171 | 172 | "type": "custom", |
172 | - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n types = $injector.get('types'),\n deviceService = $injector.get('deviceService'),\n $rootScope = $injector.get('$rootScope'),\n $q = $injector.get('$q');\n\nopenDeleteDeviceDialog();\n\nfunction openDeleteDeviceDialog() {\n let title = \"Are you sure you want to delete the device \" + entityName + \"?\";\n let content = \"Be careful, after the confirmation, the device and all related data will become unrecoverable!\";\n let confirm = $mdDialog.confirm()\n .targetEvent($event)\n .title(title)\n .htmlContent(content)\n .ariaLabel(title)\n .cancel('Cancel')\n .ok('Delete');\n $mdDialog.show(confirm).then(() => {\n deleteDevice();\n })\n}\n\nfunction deleteDevice() {\n deviceService.deleteDevice(entityId.id).then(\n () => {\n updateAliasData();\n }\n );\n}\n\nfunction updateAliasData() {\n let aliasIds = [];\n for (let id in widgetContext.aliasController.resolvedAliases) {\n aliasIds.push(id);\n }\n let tasks = [];\n aliasIds.forEach((aliasId) => {\n widgetContext.aliasController.setAliasUnresolved(aliasId);\n tasks.push(widgetContext.aliasController.getAliasInfo(aliasId));\n });\n $q.all(tasks).then(() => {\n $rootScope.$broadcast('entityAliasesChanged', aliasIds);\n });\n}" | |
173 | + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet dialogs = $injector.get(widgetContext.servicesMap.get('dialogs'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\n\nopenDeleteDeviceDialog();\n\nfunction openDeleteDeviceDialog() {\n let title = \"Are you sure you want to delete the device \" + entityName + \"?\";\n let content = \"Be careful, after the confirmation, the device and all related data will become unrecoverable!\";\n dialogs.confirm(title, content, 'Cancel', 'Delete').subscribe(\n function (result) {\n if (result) {\n deleteDevice();\n }\n }\n );\n}\n\nfunction deleteDevice() {\n deviceService.deleteDevice(entityId.id).subscribe(\n function () {\n widgetContext.updateAliases();\n }\n );\n}\n", | |
174 | + "id": "862ec2b7-fbcf-376e-f85f-b77c07f36efa" | |
173 | 175 | } |
174 | 176 | ], |
175 | 177 | "rowClick": [ |
... | ... | @@ -1102,14 +1104,11 @@ |
1102 | 1104 | "backgroundColor": "#eeeeee", |
1103 | 1105 | "color": "rgba(0,0,0,0.870588)", |
1104 | 1106 | "columns": 24, |
1105 | - "margins": [ | |
1106 | - 10, | |
1107 | - 10 | |
1108 | - ], | |
1109 | 1107 | "backgroundSizeMode": "100%", |
1110 | 1108 | "autoFillHeight": true, |
1111 | 1109 | "mobileAutoFillHeight": false, |
1112 | - "mobileRowHeight": 70 | |
1110 | + "mobileRowHeight": 70, | |
1111 | + "margin": 10 | |
1113 | 1112 | } |
1114 | 1113 | } |
1115 | 1114 | } |
... | ... | @@ -1155,14 +1154,11 @@ |
1155 | 1154 | "backgroundColor": "#eeeeee", |
1156 | 1155 | "color": "rgba(0,0,0,0.870588)", |
1157 | 1156 | "columns": 24, |
1158 | - "margins": [ | |
1159 | - 10, | |
1160 | - 10 | |
1161 | - ], | |
1162 | 1157 | "backgroundSizeMode": "100%", |
1163 | 1158 | "autoFillHeight": true, |
1164 | 1159 | "mobileAutoFillHeight": false, |
1165 | - "mobileRowHeight": 70 | |
1160 | + "mobileRowHeight": 70, | |
1161 | + "margin": 10 | |
1166 | 1162 | } |
1167 | 1163 | } |
1168 | 1164 | } |
... | ... | @@ -1211,14 +1207,11 @@ |
1211 | 1207 | "backgroundColor": "#eeeeee", |
1212 | 1208 | "color": "rgba(0,0,0,0.870588)", |
1213 | 1209 | "columns": 24, |
1214 | - "margins": [ | |
1215 | - 10, | |
1216 | - 10 | |
1217 | - ], | |
1218 | 1210 | "backgroundSizeMode": "auto 100%", |
1219 | 1211 | "autoFillHeight": true, |
1220 | 1212 | "mobileAutoFillHeight": true, |
1221 | - "mobileRowHeight": 70 | |
1213 | + "mobileRowHeight": 70, | |
1214 | + "margin": 10 | |
1222 | 1215 | } |
1223 | 1216 | } |
1224 | 1217 | } | ... | ... |
... | ... | @@ -20,6 +20,38 @@ |
20 | 20 | "dataKeySettingsSchema": "{}\n", |
21 | 21 | "defaultConfig": "{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"widgetTitle\":\"Gateway Configuration\",\"archiveFileName\":\"configurationGateway\"},\"title\":\"Gateway Configuration\",\"dropShadow\":true,\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}" |
22 | 22 | } |
23 | + }, | |
24 | + { | |
25 | + "alias": "attributes_card", | |
26 | + "name": "Gateway events", | |
27 | + "descriptor": { | |
28 | + "type": "latest", | |
29 | + "sizeX": 7.5, | |
30 | + "sizeY": 8, | |
31 | + "resources": [], | |
32 | + "templateHtml": "", | |
33 | + "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}", | |
34 | + "controllerScript": "let types;\nlet eventsReg = \"eventsReg\";\n\nself.onInit = function() {\n \n self.ctx.datasourceTitleCells = [];\n self.ctx.valueCells = [];\n self.ctx.labelCells = [];\n\n if (self.ctx.datasources.length && self.ctx.datasources[0].type === 'entity') {\n getDatasourceKeys(self.ctx.datasources[0]);\n } else {\n processDatasources(self.ctx.datasources);\n }\n}\n\nself.onDataUpdated = function() {\n for (var i = 0; i < self.ctx.valueCells.length; i++) {\n var cellData = self.ctx.data[i];\n if (cellData && cellData.data && cellData.data.length > 0) {\n var tvPair = cellData.data[cellData.data.length -\n 1];\n var value = tvPair[1];\n var textValue;\n //toDo -> + IsNumber\n \n if (isNumber(value)) {\n var decimals = self.ctx.decimals;\n var units = self.ctx.units;\n if (cellData.dataKey.decimals || cellData.dataKey.decimals === 0) {\n decimals = cellData.dataKey.decimals;\n }\n if (cellData.dataKey.units) {\n units = cellData.dataKey.units;\n }\n txtValue = self.ctx.utils.formatValue(value, decimals, units, false);\n }\n else {\n txtValue = value;\n }\n self.ctx.valueCells[i].html(txtValue);\n }\n }\n \n function isNumber(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n}\n\nself.onResize = function() {\n var datasourceTitleFontSize = self.ctx.height/8;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n datasourceTitleFontSize = self.ctx.width/12;\n }\n datasourceTitleFontSize = Math.min(datasourceTitleFontSize, 20);\n for (var i = 0; i < self.ctx.datasourceTitleCells.length; i++) {\n self.ctx.datasourceTitleCells[i].css('font-size', datasourceTitleFontSize+'px');\n }\n var valueFontSize = self.ctx.height/9;\n var labelFontSize = self.ctx.height/9;\n if (self.ctx.width/self.ctx.height <= 1.5) {\n valueFontSize = self.ctx.width/15;\n labelFontSize = self.ctx.width/15;\n }\n valueFontSize = Math.min(valueFontSize, 18);\n labelFontSize = Math.min(labelFontSize, 18);\n\n for (i = 0; i < self.ctx.valueCells; i++) {\n self.ctx.valueCells[i].css('font-size', valueFontSize+'px');\n self.ctx.valueCells[i].css('height', valueFontSize*2.5+'px');\n self.ctx.valueCells[i].css('padding', '0px ' + valueFontSize + 'px');\n self.ctx.labelCells[i].css('font-size', labelFontSize+'px');\n self.ctx.labelCells[i].css('height', labelFontSize*2.5+'px');\n self.ctx.labelCells[i].css('padding', '0px ' + labelFontSize + 'px');\n } \n}\n\nfunction processDatasources(datasources) {\n var i = 0;\n var tbDatasource = datasources[i];\n var datasourceId = 'tbDatasource' + i;\n self.ctx.$container.append(\n \"<div id='\" + datasourceId +\n \"' class='tbDatasource-container'></div>\"\n );\n\n var datasourceContainer = $('#' + datasourceId,\n self.ctx.$container);\n\n datasourceContainer.append(\n \"<div class='tbDatasource-title'>\" +\n tbDatasource.name + \"</div>\"\n );\n \n var datasourceTitleCell = $('.tbDatasource-title', datasourceContainer);\n self.ctx.datasourceTitleCells.push(datasourceTitleCell);\n \n var tableId = 'table' + i;\n datasourceContainer.append(\n \"<table id='\" + tableId +\n \"' class='tbDatasource-table'><col width='30%'><col width='70%'></table>\"\n );\n var table = $('#' + tableId, self.ctx.$container);\n\n for (var a = 0; a < tbDatasource.dataKeys.length; a++) {\n var dataKey = tbDatasource.dataKeys[a];\n var labelCellId = 'labelCell' + a;\n var cellId = 'cell' + a;\n table.append(\"<tr><td id='\" + labelCellId + \"'>\" + dataKey.label +\n \"</td><td id='\" + cellId +\n \"'></td></tr>\");\n var labelCell = $('#' + labelCellId, table);\n self.ctx.labelCells.push(labelCell);\n var valueCell = $('#' + cellId, table);\n self.ctx.valueCells.push(valueCell);\n }\n self.onResize();\n}\n\nfunction getDatasourceKeys (datasource) {\n let entityService = self.ctx.$scope.$injector.get(self.ctx.servicesMap.get('entityService'));\n if (datasource.entityId && datasource.entityType) {\n entityService.getEntityKeys({entityType: datasource.entityType, id: datasource.entityId}, '', 'timeseries').subscribe(\n function(data){\n if (data.length) {\n subscribeForKeys (datasource, data);\n }\n });\n }\n}\n\nfunction subscribeForKeys (datasource, data) {\n let eventsRegVals = self.ctx.settings[eventsReg];\n if (eventsRegVals && eventsRegVals.length > 0) {\n var dataKeys = [];\n data.sort();\n data.forEach(dataValue => {eventsRegVals.forEach(event => {\n if (dataValue.toLowerCase().includes(event.toLowerCase())) {\n var dataKey = {\n type: 'timeseries',\n name: dataValue,\n label: dataValue,\n settings: {},\n _hash: Math.random()\n };\n dataKeys.push(dataKey);\n }\n })});\n\n if (dataKeys.length) {\n updateSubscription (datasource, dataKeys);\n }\n }\n}\n\nfunction updateSubscription (datasource, dataKeys) {\n var datasources = [\n {\n type: 'entity',\n name: datasource.aliasName,\n aliasName: datasource.aliasName,\n entityAliasId: datasource.entityAliasId,\n dataKeys: dataKeys\n }\n ];\n \n var subscriptionOptions = {\n datasources: datasources,\n useDashboardTimewindow: false,\n type: 'latest',\n callbacks: {\n onDataUpdated: (subscription) => {\n self.ctx.data = subscription.data;\n self.onDataUpdated();\n }\n }\n };\n \n processDatasources(datasources);\n self.ctx.subscriptionApi.createSubscription(subscriptionOptions, true).subscribe(\n (subscription) => {\n self.ctx.defaultSubscription = subscription;\n }\n );\n}\n\nself.onDestroy = function() {\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\t\n dataKeysOptional: true\n };\n}\n\n", | |
35 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"GatewayEventsForm\",\n \"properties\": {\n \"eventsTitle\": {\n \"title\": \"Gateway events form title\",\n \"type\": \"string\",\n \"default\": \"Gateway Events Form\"\n },\n \"eventsReg\": {\n \"title\": \"Events filten.\",\n \"type\": \"array\",\n \"items\": {\n \"title\": \"Event key contains\",\n \"type\": \"string\"\n }\n }\n }\n },\n \"form\": [\n \"eventsTitle\",\n \"eventsReg\"\n ]\n}", | |
36 | + "dataKeySettingsSchema": "{}\n", | |
37 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Function Math.round\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.826503672916844,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"eventsTitle\":\"Gateway Events Form\",\"eventsReg\":[]},\"title\":\"Gateway events\",\"showTitleIcon\":false,\"titleIcon\":\"more_horiz\",\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"titleTooltip\":\"\",\"dropShadow\":true,\"enableFullscreen\":true,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"displayTimewindow\":true,\"showLegend\":false,\"actions\":{}}" | |
38 | + } | |
39 | + }, | |
40 | + { | |
41 | + "alias": "config_form_latest", | |
42 | + "name": "Gateway configuration (Single device)", | |
43 | + "descriptor": { | |
44 | + "type": "latest", | |
45 | + "sizeX": 7.5, | |
46 | + "sizeY": 9, | |
47 | + "resources": [], | |
48 | + "templateHtml": "<tb-gateway-form\n [ctx]=\"ctx\"\n [isStateForm]=\"true\">\n</tb-gateway-form>", | |
49 | + "templateCss": "#container {\n overflow: auto;\n}\n\n.tbDatasource-container {\n margin: 5px;\n padding: 8px;\n}\n\n.tbDatasource-title {\n font-size: 1.200rem;\n font-weight: 500;\n padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n width: 100%;\n box-shadow: 0 0 10px #ccc;\n border-collapse: collapse;\n white-space: nowrap;\n font-size: 1.000rem;\n color: #757575;\n}\n\n.tbDatasource-table td {\n position: relative;\n border-top: 1px solid rgba(0, 0, 0, 0.12);\n border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n padding: 0px 18px;\n box-sizing: border-box;\n}", | |
50 | + "controllerScript": "self.onInit = function() {\n}\n\n\nself.onDestroy = function() {\n}\n\nself.typeParameters = function() {\n return {\n maxDatasources: 1,\t\t\t\n dataKeysOptional: true\t\t\n };\n}\n\n", | |
51 | + "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"GatewayConfigForm\",\n \"properties\": {\n \"gatewayTitle\": {\n \"title\": \"Gateway form\",\n \"type\": \"string\",\n \"default\": \"Gateway configuration (Single device)\"\n },\n \"readOnly\": {\n \"title\": \"Read Only\",\n \"type\": \"boolean\",\n \"default\": false\n }\n }\n },\n \"form\": [\n \"gatewayTitle\",\n \"readOnly\"\n ]\n}\n", | |
52 | + "dataKeySettingsSchema": "{}\n", | |
53 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"gatewayTitle\":\"Gateway configuration (Single device)\"},\"title\":\"Gateway configuration (Single device)\"}" | |
54 | + } | |
23 | 55 | } |
24 | 56 | ] |
25 | -} | |
57 | +} | |
\ No newline at end of file | ... | ... |
... | ... | @@ -28,6 +28,8 @@ |
28 | 28 | </mat-expansion-panel-header> |
29 | 29 | <tb-entity-gateway-select |
30 | 30 | formControlName="gateway" |
31 | + [deviceName]="deviceNameForm" | |
32 | + [isStateForm]="isStateForm" | |
31 | 33 | [newGatewayType]="gatewayType" |
32 | 34 | (gatewayNameExist)="gatewayExist()" |
33 | 35 | required |
... | ... | @@ -218,13 +220,14 @@ |
218 | 220 | </div> |
219 | 221 | <div [fxLayout]="alignment" [fxLayoutGap]="layoutGap" |
220 | 222 | fxLayoutAlign="{{alignment == 'row' ? 'end center' : 'space-evenly center'}}" class="action-buttons"> |
221 | - <button mat-icon-button (click)="openConfigDialog($event, i, connector.get('config').value, connector.get('name').value)" | |
223 | + <button [disabled]="isReadOnlyForm" mat-icon-button (click)="openConfigDialog($event, i, connector.get('config').value, connector.get('name').value)" | |
222 | 224 | matTooltip="{{ 'gateway.update-config' | translate }}" |
223 | 225 | matTooltipPosition="above" |
224 | 226 | [ngClass]="{'mat-warn': connector.get('config').invalid}"> |
225 | 227 | <mat-icon>more_horiz</mat-icon> |
226 | 228 | </button> |
227 | - <button mat-icon-button (click)="removeConnector(i)" | |
229 | + <button [disabled]="isReadOnlyForm" | |
230 | + mat-icon-button (click)="removeConnector(i)" | |
228 | 231 | matTooltip="{{ 'gateway.delete' | translate }}" |
229 | 232 | matTooltipPosition="above"> |
230 | 233 | <mat-icon>close</mat-icon> |
... | ... | @@ -234,7 +237,7 @@ |
234 | 237 | </section> |
235 | 238 | <span [fxShow]="!connectors.length" fxLayoutAlign="center center" class="no-data-found">{{'gateway.no-connectors' | translate}}</span> |
236 | 239 | <div> |
237 | - <button mat-raised-button type="button" (click)="addNewConnector()" | |
240 | + <button [fxShow]="!isReadOnlyForm" mat-raised-button type="button" (click)="addNewConnector()" | |
238 | 241 | matTooltip="{{ 'gateway.connector-add' | translate }}" |
239 | 242 | matTooltipPosition="above"> |
240 | 243 | {{ 'action.add' | translate }} |
... | ... | @@ -243,7 +246,8 @@ |
243 | 246 | </div > |
244 | 247 | </mat-expansion-panel> |
245 | 248 | </mat-accordion> |
246 | - <section fxLayout="row" fxLayoutAlign="end center" class="form-action-buttons"> | |
249 | + <section [fxShow]="!isReadOnlyForm" | |
250 | + fxLayout="row" fxLayoutAlign="end center" class="form-action-buttons"> | |
247 | 251 | <button mat-raised-button color="primary" type="button" |
248 | 252 | (click)="exportConfig()" |
249 | 253 | *ngIf="!gatewayConfigurationGroup.get('remoteConfiguration').value" | ... | ... |
... | ... | @@ -112,8 +112,17 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes |
112 | 112 | @Input() |
113 | 113 | ctx: WidgetContext; |
114 | 114 | |
115 | + @Input() | |
116 | + isStateForm: boolean; | |
117 | + | |
118 | + isReadOnlyForm = false; | |
119 | + deviceNameForm: string; | |
120 | + | |
115 | 121 | ngOnInit(): void { |
116 | 122 | this.initWidgetSettings(this.ctx.settings); |
123 | + if (this.ctx.datasources && this.ctx.datasources.length) { | |
124 | + this.deviceNameForm = this.ctx.datasources[0].name; | |
125 | + } | |
117 | 126 | |
118 | 127 | this.buildForm(); |
119 | 128 | this.ctx.updateWidgetParams(); |
... | ... | @@ -133,12 +142,13 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes |
133 | 142 | |
134 | 143 | private initWidgetSettings(settings: WidgetSetting): void { |
135 | 144 | let widgetTitle; |
136 | - if (settings.widgetTitle && settings.widgetTitle.length) { | |
137 | - widgetTitle = this.utils.customTranslation(settings.widgetTitle, settings.widgetTitle); | |
145 | + if (settings.gatewayTitle && settings.gatewayTitle.length) { | |
146 | + widgetTitle = this.utils.customTranslation(settings.gatewayTitle, settings.gatewayTitle); | |
138 | 147 | } else { |
139 | 148 | widgetTitle = this.translate.instant('gateway.gateway'); |
140 | 149 | } |
141 | 150 | this.ctx.widgetTitle = widgetTitle; |
151 | + this.isReadOnlyForm = (settings.readOnly) ? settings.readOnly : false; | |
142 | 152 | |
143 | 153 | this.archiveFileName = settings.archiveFileName?.length ? settings.archiveFileName : 'gatewayConfiguration'; |
144 | 154 | this.gatewayType = settings.gatewayType?.length ? settings.gatewayType : 'Gateway'; |
... | ... | @@ -189,7 +199,7 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes |
189 | 199 | |
190 | 200 | private buildForm(): void { |
191 | 201 | this.gatewayConfigurationGroup = this.fb.group({ |
192 | - gateway: [null], | |
202 | + gateway: [null, []], | |
193 | 203 | accessToken: [null, [Validators.required]], |
194 | 204 | securityType: [SecurityType.accessToken], |
195 | 205 | host: [this.window.location.hostname, [Validators.required]], |
... | ... | @@ -208,6 +218,10 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes |
208 | 218 | connectors: this.fb.array([]) |
209 | 219 | }); |
210 | 220 | |
221 | + if (this.isReadOnlyForm) { | |
222 | + this.gatewayConfigurationGroup.disable({emitEvent: false}); | |
223 | + } | |
224 | + | |
211 | 225 | this.subscribeStorageType$ = this.getFormField('storageType').valueChanges.subscribe((value: StorageType) => { |
212 | 226 | if (value === StorageType.memory) { |
213 | 227 | this.getFormField('maxFilesCount').disable(); |
... | ... | @@ -342,6 +356,9 @@ export class GatewayFormComponent extends PageComponent implements OnInit, OnDes |
342 | 356 | tap(([currentConfig, draftConfig]) => { |
343 | 357 | this.setFormGatewaySettings(currentConfig); |
344 | 358 | this.setFormConnectorsDraft(draftConfig); |
359 | + if (this.isReadOnlyForm) { | |
360 | + this.gatewayConfigurationGroup.disable({emitEvent: false}); | |
361 | + } | |
345 | 362 | }) |
346 | 363 | ) |
347 | 364 | ); | ... | ... |
... | ... | @@ -25,6 +25,8 @@ export enum SecurityType { |
25 | 25 | |
26 | 26 | export interface WidgetSetting { |
27 | 27 | widgetTitle: string; |
28 | + gatewayTitle?: string; | |
29 | + readOnly?: boolean; | |
28 | 30 | archiveFileName: string; |
29 | 31 | gatewayType: string; |
30 | 32 | successfulSave: string; |
... | ... | @@ -177,7 +179,7 @@ export function ValidateJSON(control: AbstractControl): ValidationErrors | null |
177 | 179 | return null; |
178 | 180 | } |
179 | 181 | |
180 | -const TEMPLATE_LOGS_CONFIG = '[loggers]}}keys=root, service, connector, converter, tb_connection, storage, extension}}[handlers]}}keys=consoleHandler, serviceHandler, connectorHandler, converterHandler, tb_connectionHandler, storageHandler, extensionHandler}}[formatters]}}keys=LogFormatter}}[logger_root]}}level=ERROR}}handlers=consoleHandler}}[logger_connector]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=connector}}[logger_storage]}}level={ERROR}}}handlers=storageHandler}}formatter=LogFormatter}}qualname=storage}}[logger_tb_connection]}}level={ERROR}}}handlers=tb_connectionHandler}}formatter=LogFormatter}}qualname=tb_connection}}[logger_service]}}level={ERROR}}}handlers=serviceHandler}}formatter=LogFormatter}}qualname=service}}[logger_converter]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=converter}}[logger_extension]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=extension}}[handler_consoleHandler]}}class=StreamHandler}}level={ERROR}}}formatter=LogFormatter}}args=(sys.stdout,)}}[handler_connectorHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}connector.log", "d", 1, 7,)}}[handler_storageHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}storage.log", "d", 1, 7,)}}[handler_serviceHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}service.log", "d", 1, 7,)}}[handler_converterHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}converter.log", "d", 1, 3,)}}[handler_extensionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}extension.log", "d", 1, 3,)}}[handler_tb_connectionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}tb_connection.log", "d", 1, 3,)}}[formatter_LogFormatter]}}format="%(asctime)s - %(levelname)s - [%(filename)s] - %(module)s - %(lineno)d - %(message)s" }}datefmt="%Y-%m-%d %H:%M:%S"'; | |
182 | +const TEMPLATE_LOGS_CONFIG = '[loggers]}}keys=root, service, connector, converter, tb_connection, storage, extension}}[handlers]}}keys=consoleHandler, serviceHandler, connectorHandler, converterHandler, tb_connectionHandler, storageHandler, extensionHandler}}[formatters]}}keys=LogFormatter}}[logger_root]}}level=ERROR}}handlers=consoleHandler}}[logger_connector]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=connector}}[logger_storage]}}level={ERROR}}}handlers=storageHandler}}formatter=LogFormatter}}qualname=storage}}[logger_tb_connection]}}level={ERROR}}}handlers=tb_connectionHandler}}formatter=LogFormatter}}qualname=tb_connection}}[logger_service]}}level={ERROR}}}handlers=serviceHandler}}formatter=LogFormatter}}qualname=service}}[logger_converter]}}level={ERROR}}}handlers=converterHandler}}formatter=LogFormatter}}qualname=converter}}[logger_extension]}}level={ERROR}}}handlers=connectorHandler}}formatter=LogFormatter}}qualname=extension}}[handler_consoleHandler]}}class=StreamHandler}}level={ERROR}}}formatter=LogFormatter}}args=(sys.stdout,)}}[handler_connectorHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}connector.log", "d", 1, 7,)}}[handler_storageHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}storage.log", "d", 1, 7,)}}[handler_serviceHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}service.log", "d", 1, 7,)}}[handler_converterHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}converter.log", "d", 1, 3,)}}[handler_extensionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}extension.log", "d", 1, 3,)}}[handler_tb_connectionHandler]}}level={ERROR}}}class=logging.handlers.TimedRotatingFileHandler}}formatter=LogFormatter}}args=("{./logs/}tb_connection.log", "d", 1, 3,)}}[formatter_LogFormatter]}}format="%(asctime)s - %(levelname)s - [%(filename)s] - %(module)s - %(lineno)d - %(message)s" }}datefmt="%Y-%m-%d %H:%M:%S"'; | |
181 | 183 | |
182 | 184 | export function generateYAMLConfigFile(gatewaySetting: GatewayFormModels): string { |
183 | 185 | let config; | ... | ... |
... | ... | @@ -24,7 +24,7 @@ |
24 | 24 | (keypress)="gatewayNameEnter($event)" |
25 | 25 | [matAutocomplete]="gatewayAutocomplete" |
26 | 26 | > |
27 | - <button *ngIf="selectDeviceGatewayFormGroup.get('gateway').value" (click)="clear()" | |
27 | + <button *ngIf="selectDeviceGatewayFormGroup.get('gateway').value && !isStateForm" (click)="clear()" | |
28 | 28 | type="button" matSuffix mat-icon-button aria-label="Clear"> |
29 | 29 | <mat-icon class="material-icons">close</mat-icon> |
30 | 30 | </button> | ... | ... |
... | ... | @@ -28,6 +28,8 @@ import { Device } from '@shared/models/device.models'; |
28 | 28 | import { DialogService } from '@core/services/dialog.service'; |
29 | 29 | import { TranslateService } from '@ngx-translate/core'; |
30 | 30 | import { DeviceService } from '@core/http/device.service'; |
31 | +import { getCurrentAuthUser } from '@core/auth/auth.selectors'; | |
32 | +import { Authority } from '@shared/models/authority.enum'; | |
31 | 33 | |
32 | 34 | @Component({ |
33 | 35 | selector: 'tb-entity-gateway-select', |
... | ... | @@ -55,6 +57,12 @@ export class EntityGatewaySelectComponent implements ControlValueAccessor, OnIni |
55 | 57 | this.gatewayType = value; |
56 | 58 | } |
57 | 59 | |
60 | + @Input() | |
61 | + deviceName: string; | |
62 | + | |
63 | + @Input() | |
64 | + isStateForm: boolean; | |
65 | + | |
58 | 66 | @Output() |
59 | 67 | private gatewayNameExist = new EventEmitter(); |
60 | 68 | |
... | ... | @@ -64,10 +72,6 @@ export class EntityGatewaySelectComponent implements ControlValueAccessor, OnIni |
64 | 72 | private deviceService: DeviceService, |
65 | 73 | private translate: TranslateService, |
66 | 74 | private fb: FormBuilder) { |
67 | - this.loadGatewayList(); | |
68 | - this.selectDeviceGatewayFormGroup = this.fb.group({ | |
69 | - gateway: [null] | |
70 | - }); | |
71 | 75 | } |
72 | 76 | |
73 | 77 | private gatewayType = 'Gateway'; |
... | ... | @@ -91,6 +95,10 @@ export class EntityGatewaySelectComponent implements ControlValueAccessor, OnIni |
91 | 95 | } |
92 | 96 | |
93 | 97 | ngOnInit() { |
98 | + this.selectDeviceGatewayFormGroup = this.fb.group({ | |
99 | + gateway: this.fb.control({value: null, disabled: this.isStateForm}) | |
100 | + }); | |
101 | + this.loadGatewayList(); | |
94 | 102 | this.filteredGateways = this.selectDeviceGatewayFormGroup.get('gateway').valueChanges |
95 | 103 | .pipe( |
96 | 104 | tap(value => { |
... | ... | @@ -204,15 +212,33 @@ export class EntityGatewaySelectComponent implements ControlValueAccessor, OnIni |
204 | 212 | }) |
205 | 213 | } |
206 | 214 | |
207 | - private loadGatewayList(): void{ | |
208 | - this.entityService.getEntitiesByNameFilter(EntityType.DEVICE, '', -1).pipe( | |
209 | - switchMap(results => results), | |
210 | - filter((device) => (device as Device)?.additionalInfo?.gateway), | |
211 | - reduce((acc, val) => acc.concat(val), []) | |
215 | + private loadGatewayList(): void { | |
216 | + let listObservable: Observable<any[]>; | |
217 | + if (getCurrentAuthUser(this.store).authority === Authority.SYS_ADMIN) { | |
218 | + listObservable = of([]); | |
219 | + } else { | |
220 | + const entityNameFilter = this.isStateForm && this.deviceName ? this.deviceName : ''; | |
221 | + listObservable = this.entityService.getEntitiesByNameFilter(EntityType.DEVICE, entityNameFilter, | |
222 | + -1, '', {ignoreLoading: true}); | |
223 | + } | |
224 | + listObservable.pipe( | |
225 | + map((devices) => devices ? devices.filter((device) => | |
226 | + (device as Device)?.additionalInfo?.gateway): []), | |
212 | 227 | ).subscribe((devices) => { |
213 | 228 | this.gatewayList = devices; |
214 | - if(!this.searchText && this.gatewayList.length){ | |
215 | - this.selectDeviceGatewayFormGroup.get('gateway').patchValue(this.gatewayList[0], {emitEvent: true}); | |
229 | + if (!this.searchText) { | |
230 | + if (this.gatewayList.length) { | |
231 | + let foundGateway: Device = null; | |
232 | + if (this.deviceName) { | |
233 | + foundGateway = this.gatewayList.find((gateway) => gateway.name === this.deviceName); | |
234 | + } | |
235 | + if (!foundGateway) { | |
236 | + foundGateway = this.gatewayList[0]; | |
237 | + } | |
238 | + if (foundGateway) { | |
239 | + this.selectDeviceGatewayFormGroup.get('gateway').patchValue(foundGateway, {emitEvent: true}); | |
240 | + } | |
241 | + } | |
216 | 242 | } |
217 | 243 | }) |
218 | 244 | } | ... | ... |