Commit d965df8c271f0569b02908ea486922e18465543a
Merge remote-tracking branch 'origin/master' into develop/2.5
Showing
8 changed files
with
164 additions
and
69 deletions
@@ -6,6 +6,38 @@ | @@ -6,6 +6,38 @@ | ||
6 | }, | 6 | }, |
7 | "widgetTypes": [ | 7 | "widgetTypes": [ |
8 | { | 8 | { |
9 | + "alias": "attributes_card", | ||
10 | + "name": "Gateway events", | ||
11 | + "descriptor": { | ||
12 | + "type": "latest", | ||
13 | + "sizeX": 7.5, | ||
14 | + "sizeY": 8, | ||
15 | + "resources": [], | ||
16 | + "templateHtml": "", | ||
17 | + "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}", | ||
18 | + "controllerScript": "let types;\nlet eventsReg = \"eventsReg\";\n\nself.onInit = function() {\n \n self.ctx.datasourceTitleCells = [];\n self.ctx.valueCells = [];\n self.ctx.labelCells = [];\n types = self.ctx.$scope.$injector.get('types');\n \n if (self.ctx.datasources.length && self.ctx.datasources[0].type === types.datasourceType.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 attributeService = self.ctx.$scope.$injector.get('attributeService');\n if (datasource.entityId && datasource.entityType) {\n attributeService.getEntityKeys(datasource.entityType, datasource.entityId, \"\" , types.dataKeyType.timeseries).then(\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: types.dataKeyType.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: types.datasourceType.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: types.widgetType.latest.value,\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).then(\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", | ||
19 | + "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}", | ||
20 | + "dataKeySettingsSchema": "{}\n", | ||
21 | + "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\":{}}" | ||
22 | + } | ||
23 | + }, | ||
24 | + { | ||
25 | + "alias": "config_form_latest", | ||
26 | + "name": "Gateway configuration (Single device)", | ||
27 | + "descriptor": { | ||
28 | + "type": "latest", | ||
29 | + "sizeX": 7.5, | ||
30 | + "sizeY": 9, | ||
31 | + "resources": [], | ||
32 | + "templateHtml": "<tb-gateway-form\n form-id=\"formId\"\n ctx=\"ctx\"\n is-state-form=\"isStateForm\">\n</tb-gateway-form>", | ||
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": "self.onInit = function() {\n var scope = self.ctx.$scope;\n var id = self.ctx.$scope.$injector.get('utils').guid();\n scope.formId = \"form-\"+id;\n scope.ctx = self.ctx;\n scope.isStateForm = true;\n}\n\nself.onResize = function() {\n self.ctx.$scope.$broadcast('gateway-form-resize', self.ctx.$scope.formId);\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", | ||
35 | + "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", | ||
36 | + "dataKeySettingsSchema": "{}\n", | ||
37 | + "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Gateway configuration (Single device)\"}" | ||
38 | + } | ||
39 | + }, | ||
40 | + { | ||
9 | "alias": "extension_configuration_widget", | 41 | "alias": "extension_configuration_widget", |
10 | "name": "Extensions table", | 42 | "name": "Extensions table", |
11 | "descriptor": { | 43 | "descriptor": { |
@@ -1645,7 +1645,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { | @@ -1645,7 +1645,7 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { | ||
1645 | addPageLinkToParam(params, pageLink); | 1645 | addPageLinkToParam(params, pageLink); |
1646 | 1646 | ||
1647 | Map<String, List<JsonNode>> timeseries = restTemplate.exchange( | 1647 | Map<String, List<JsonNode>> timeseries = restTemplate.exchange( |
1648 | - baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParams(pageLink), | 1648 | + baseURL + "/api/plugins/telemetry/{entityType}/{entityId}/values/timeseries?keys={keys}&interval={interval}&agg={agg}&useStrictDataTypes={useStrictDataTypes}&" + getUrlParamsTs(pageLink), |
1649 | HttpMethod.GET, | 1649 | HttpMethod.GET, |
1650 | HttpEntity.EMPTY, | 1650 | HttpEntity.EMPTY, |
1651 | new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { | 1651 | new ParameterizedTypeReference<Map<String, List<JsonNode>>>() { |
@@ -1997,12 +1997,20 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { | @@ -1997,12 +1997,20 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { | ||
1997 | } | 1997 | } |
1998 | 1998 | ||
1999 | private String getUrlParams(TimePageLink pageLink) { | 1999 | private String getUrlParams(TimePageLink pageLink) { |
2000 | + return getUrlParams(pageLink, "startTime", "endTime"); | ||
2001 | + } | ||
2002 | + | ||
2003 | + private String getUrlParamsTs(TimePageLink pageLink) { | ||
2004 | + return getUrlParams(pageLink, "startTs", "endTs"); | ||
2005 | + } | ||
2006 | + | ||
2007 | + private String getUrlParams(TimePageLink pageLink, String startTime, String endTime) { | ||
2000 | String urlParams = "limit={limit}&ascOrder={ascOrder}"; | 2008 | String urlParams = "limit={limit}&ascOrder={ascOrder}"; |
2001 | if (pageLink.getStartTime() != null) { | 2009 | if (pageLink.getStartTime() != null) { |
2002 | - urlParams += "&startTime={startTime}"; | 2010 | + urlParams += "&" + startTime + "={startTime}"; |
2003 | } | 2011 | } |
2004 | if (pageLink.getEndTime() != null) { | 2012 | if (pageLink.getEndTime() != null) { |
2005 | - urlParams += "&endTime={endTime}"; | 2013 | + urlParams += "&" + endTime + "={endTime}"; |
2006 | } | 2014 | } |
2007 | if (pageLink.getIdOffset() != null) { | 2015 | if (pageLink.getIdOffset() != null) { |
2008 | urlParams += "&offset={offset}"; | 2016 | urlParams += "&offset={offset}"; |
@@ -606,13 +606,29 @@ export default angular.module('thingsboard.types', []) | @@ -606,13 +606,29 @@ export default angular.module('thingsboard.types', []) | ||
606 | value: "modbus", | 606 | value: "modbus", |
607 | name: "Modbus" | 607 | name: "Modbus" |
608 | }, | 608 | }, |
609 | - opc_ua: { | 609 | + opcua: { |
610 | value: "opcua", | 610 | value: "opcua", |
611 | name: "OPC-UA" | 611 | name: "OPC-UA" |
612 | }, | 612 | }, |
613 | ble: { | 613 | ble: { |
614 | value: "ble", | 614 | value: "ble", |
615 | name: "BLE" | 615 | name: "BLE" |
616 | + }, | ||
617 | + request: { | ||
618 | + value: "request", | ||
619 | + name: "Request" | ||
620 | + }, | ||
621 | + can: { | ||
622 | + value: "can", | ||
623 | + name: "CAN" | ||
624 | + }, | ||
625 | + bacnet: { | ||
626 | + value: "bacnet", | ||
627 | + name: "BACnet" | ||
628 | + }, | ||
629 | + custom: { | ||
630 | + value: "custom", | ||
631 | + name: "Custom" | ||
616 | } | 632 | } |
617 | }, | 633 | }, |
618 | gatewayLogLevel: { | 634 | gatewayLogLevel: { |
@@ -37,7 +37,8 @@ function GatewayConfig() { | @@ -37,7 +37,8 @@ function GatewayConfig() { | ||
37 | disabled: '=ngDisabled', | 37 | disabled: '=ngDisabled', |
38 | gatewayConfig: '=', | 38 | gatewayConfig: '=', |
39 | changeAlignment: '=', | 39 | changeAlignment: '=', |
40 | - theForm: '=' | 40 | + theForm: '=', |
41 | + isReadOnly: '=' | ||
41 | }, | 42 | }, |
42 | controller: GatewayConfigController, | 43 | controller: GatewayConfigController, |
43 | controllerAs: 'vm', | 44 | controllerAs: 'vm', |
@@ -83,6 +84,10 @@ function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, | @@ -83,6 +84,10 @@ function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, | ||
83 | multiple: true, | 84 | multiple: true, |
84 | }).then(function (config) { | 85 | }).then(function (config) { |
85 | if (config && index > -1) { | 86 | if (config && index > -1) { |
87 | + console.log(config); //eslint-disable-line | ||
88 | + if (!angular.equals(vm.gatewayConfig[index].config, config)) { | ||
89 | + $scope.gatewayConfiguration.$setDirty(); | ||
90 | + } | ||
86 | vm.gatewayConfig[index].config = config; | 91 | vm.gatewayConfig[index].config = config; |
87 | } | 92 | } |
88 | }); | 93 | }); |
@@ -18,7 +18,7 @@ | @@ -18,7 +18,7 @@ | ||
18 | <section name="gatewayConfig" layout="column" class="gateway-config"> | 18 | <section name="gatewayConfig" layout="column" class="gateway-config"> |
19 | <section layout="row" ng-form="gatewayConfig_{{$index}}" ng-repeat="connector in vm.gatewayConfig track by $index"> | 19 | <section layout="row" ng-form="gatewayConfig_{{$index}}" ng-repeat="connector in vm.gatewayConfig track by $index"> |
20 | <div layout="column" layout-align="center start" class="gateway-config-row"> | 20 | <div layout="column" layout-align="center start" class="gateway-config-row"> |
21 | - <md-switch ng-model="connector.enabled" ng-disabled="gatewayConfig_{{$index}}.$invalid || vm.validateJSON(connector.config)" | 21 | + <md-switch ng-disabled="vm.isReadOnly" ng-model="connector.enabled" ng-disabled="gatewayConfig_{{$index}}.$invalid || vm.validateJSON(connector.config)" |
22 | aria-label="{{ 'gateway.connector-enabled' | translate }}"> | 22 | aria-label="{{ 'gateway.connector-enabled' | translate }}"> |
23 | </md-switch> | 23 | </md-switch> |
24 | </div> | 24 | </div> |
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 26 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
27 | <md-input-container class="md-block" flex> | 27 | <md-input-container class="md-block" flex> |
28 | <label>{{'gateway.connector-type' | translate }}</label> | 28 | <label>{{'gateway.connector-type' | translate }}</label> |
29 | - <md-select name="connectorType" | 29 | + <md-select ng-disabled="vm.isReadOnly" name="connectorType" |
30 | ng-change="vm.changeConnectorType(connector)" | 30 | ng-change="vm.changeConnectorType(connector)" |
31 | aria-label="{{ 'gateway.gateway.connector-type' | translate }}" | 31 | aria-label="{{ 'gateway.gateway.connector-type' | translate }}" |
32 | ng-model="connector.configType" required> | 32 | ng-model="connector.configType" required> |
@@ -39,7 +39,7 @@ | @@ -39,7 +39,7 @@ | ||
39 | </div> | 39 | </div> |
40 | </md-input-container> | 40 | </md-input-container> |
41 | <md-input-container class="md-block" flex> | 41 | <md-input-container class="md-block" flex> |
42 | - <input placeholder="{{'gateway.connector-name' | translate }}" | 42 | + <input ng-disabled="vm.isReadOnly" placeholder="{{'gateway.connector-name' | translate }}" |
43 | ng-model-options="{ updateOn: 'blur' }" | 43 | ng-model-options="{ updateOn: 'blur' }" |
44 | ng-change="vm.changeConnectorName(connector, $index)" name="connectorName" ng-model="connector.name" required/> | 44 | ng-change="vm.changeConnectorName(connector, $index)" name="connectorName" ng-model="connector.name" required/> |
45 | <div ng-messages="vm.theForm.connectorName.$error"> | 45 | <div ng-messages="vm.theForm.connectorName.$error"> |
@@ -49,7 +49,7 @@ | @@ -49,7 +49,7 @@ | ||
49 | </div> | 49 | </div> |
50 | <div layout="row" layout-align="end center" class="action-buttons" | 50 | <div layout="row" layout-align="end center" class="action-buttons" |
51 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 51 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
52 | - <md-button class="md-icon-button md-mini" ng-click="vm.openConfigDialog($event, $index, connector.config, connector.name)" | 52 | + <md-button ng-disabled="vm.isReadOnly" class="md-icon-button md-mini" ng-click="vm.openConfigDialog($event, $index, connector.config, connector.name)" |
53 | aria-label="{{ 'gateway.update-config' | translate }}" | 53 | aria-label="{{ 'gateway.update-config' | translate }}" |
54 | ng-class="{'md-warn': vm.validateJSON(connector.config)}"> | 54 | ng-class="{'md-warn': vm.validateJSON(connector.config)}"> |
55 | <md-icon class="material-icons">more_horiz</md-icon> | 55 | <md-icon class="material-icons">more_horiz</md-icon> |
@@ -57,7 +57,7 @@ | @@ -57,7 +57,7 @@ | ||
57 | {{ 'gateway.update-config' | translate }} | 57 | {{ 'gateway.update-config' | translate }} |
58 | </md-tooltip> | 58 | </md-tooltip> |
59 | </md-button> | 59 | </md-button> |
60 | - <md-button class="md-icon-button md-mini" ng-click="vm.removeConnector($index)" | 60 | + <md-button ng-disabled="vm.isReadOnly" class="md-icon-button md-mini" ng-click="vm.removeConnector($index)" |
61 | aria-label="{{ 'gateway.delete' | translate }}"> | 61 | aria-label="{{ 'gateway.delete' | translate }}"> |
62 | <md-icon class="material-icons">close</md-icon> | 62 | <md-icon class="material-icons">close</md-icon> |
63 | <md-tooltip md-direction="top"> | 63 | <md-tooltip md-direction="top"> |
@@ -70,7 +70,7 @@ | @@ -70,7 +70,7 @@ | ||
70 | layout-align="center center" ng-class="{'disabled': vm.disabled}" | 70 | layout-align="center center" ng-class="{'disabled': vm.disabled}" |
71 | class="no-data-found" translate>{{'gateway.no-connectors'}}</span> | 71 | class="no-data-found" translate>{{'gateway.no-connectors'}}</span> |
72 | <div> | 72 | <div> |
73 | - <md-button class="md-raised" ng-click="vm.addNewConnector()" | 73 | + <md-button ng-show="!vm.isReadOnly" class="md-raised" ng-click="vm.addNewConnector()" |
74 | aria-label="{{ 'gateway.connector-add' | translate }}"> | 74 | aria-label="{{ 'gateway.connector-add' | translate }}"> |
75 | <md-tooltip md-direction="top"> | 75 | <md-tooltip md-direction="top"> |
76 | {{ 'gateway.connector-add' | translate }} | 76 | {{ 'gateway.connector-add' | translate }} |
@@ -31,11 +31,15 @@ function GatewayForm() { | @@ -31,11 +31,15 @@ function GatewayForm() { | ||
31 | scope: true, | 31 | scope: true, |
32 | bindToController: { | 32 | bindToController: { |
33 | formId: '=', | 33 | formId: '=', |
34 | - ctx: '=' | 34 | + ctx: '=', |
35 | + isStateForm: '=', | ||
36 | + deviceName: '=', | ||
37 | + isReadOnly: '=', | ||
38 | + isState: '=' | ||
35 | }, | 39 | }, |
36 | controller: GatewayFormController, | 40 | controller: GatewayFormController, |
37 | controllerAs: 'vm', | 41 | controllerAs: 'vm', |
38 | - templateUrl: gatewayFormTemplate | 42 | + templateUrl: gatewayFormTemplate, |
39 | }; | 43 | }; |
40 | } | 44 | } |
41 | 45 | ||
@@ -47,10 +51,11 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -47,10 +51,11 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
47 | const configurationAttribute = "configuration"; | 51 | const configurationAttribute = "configuration"; |
48 | const remoteLoggingLevelAttribute = "RemoteLoggingLevel"; | 52 | const remoteLoggingLevelAttribute = "RemoteLoggingLevel"; |
49 | 53 | ||
50 | - const templateLogsConfig = '[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"'; | 54 | + const templateLogsConfig = '[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"'; |
51 | 55 | ||
52 | vm.types = types; | 56 | vm.types = types; |
53 | - | 57 | + vm.deviceNameForm = (vm.deviceName) ? vm.deviceName : null; |
58 | + vm.idForm = Math.random().toString(36).replace(/^0\.[0-9]*/, ''); | ||
54 | vm.configurations = { | 59 | vm.configurations = { |
55 | gateway: '', | 60 | gateway: '', |
56 | host: $document[0].domain, | 61 | host: $document[0].domain, |
@@ -74,7 +79,6 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -74,7 +79,6 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
74 | let archiveFileName = ''; | 79 | let archiveFileName = ''; |
75 | let gatewayNameExists = ''; | 80 | let gatewayNameExists = ''; |
76 | let successfulSaved = ''; | 81 | let successfulSaved = ''; |
77 | - | ||
78 | vm.securityTypes = [{ | 82 | vm.securityTypes = [{ |
79 | name: 'gateway.security-types.access-token', | 83 | name: 'gateway.security-types.access-token', |
80 | value: 'accessToken' | 84 | value: 'accessToken' |
@@ -92,13 +96,18 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -92,13 +96,18 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
92 | }]; | 96 | }]; |
93 | 97 | ||
94 | $scope.$watch('vm.ctx', function () { | 98 | $scope.$watch('vm.ctx', function () { |
95 | - if (vm.ctx ) { | 99 | + if (vm.ctx) { |
100 | + vm.isStateForm = $scope.isStateForm; | ||
96 | vm.settings = vm.ctx.settings; | 101 | vm.settings = vm.ctx.settings; |
97 | vm.widgetConfig = vm.ctx.widgetConfig; | 102 | vm.widgetConfig = vm.ctx.widgetConfig; |
98 | - initializeConfig(); | 103 | + if (vm.ctx.datasources && vm.ctx.datasources.length) { |
104 | + vm.deviceNameForm = vm.ctx.datasources[0].name; | ||
105 | + } | ||
99 | } | 106 | } |
107 | + initializeConfig(); | ||
100 | }); | 108 | }); |
101 | 109 | ||
110 | + | ||
102 | $scope.$on('gateway-form-resize', function (event, formId) { | 111 | $scope.$on('gateway-form-resize', function (event, formId) { |
103 | if (vm.formId == formId) { | 112 | if (vm.formId == formId) { |
104 | updateWidgetDisplaying(); | 113 | updateWidgetDisplaying(); |
@@ -106,21 +115,34 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -106,21 +115,34 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
106 | }); | 115 | }); |
107 | 116 | ||
108 | function updateWidgetDisplaying() { | 117 | function updateWidgetDisplaying() { |
109 | - vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); | 118 | + if (vm.ctx) { |
119 | + vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); | ||
120 | + } | ||
110 | } | 121 | } |
111 | 122 | ||
112 | function initWidgetSettings() { | 123 | function initWidgetSettings() { |
113 | let widgetTitle; | 124 | let widgetTitle; |
114 | - if (vm.settings.widgetTitle && vm.settings.widgetTitle.length) { | ||
115 | - widgetTitle = utils.customTranslation(vm.settings.widgetTitle, vm.settings.widgetTitle); | 125 | + if (vm.settings) { |
126 | + vm.isReadOnlyForm = (vm.settings.readOnly) ? vm.settings.readOnly : false; | ||
127 | + if (vm.settings.gatewayTitle && vm.settings.gatewayTitle.length) { | ||
128 | + widgetTitle = utils.customTranslation(vm.settings.gatewayTitle, vm.settings.gatewayTitle); | ||
129 | + } | ||
116 | } else { | 130 | } else { |
131 | + vm.isReadOnlyForm = false; | ||
117 | widgetTitle = $translate.instant('gateway.gateway'); | 132 | widgetTitle = $translate.instant('gateway.gateway'); |
118 | } | 133 | } |
119 | - vm.ctx.widgetTitle = widgetTitle; | 134 | + if (vm.ctx) { |
135 | + vm.ctx.widgetTitle = widgetTitle; | ||
136 | + } | ||
120 | 137 | ||
121 | - archiveFileName = vm.settings.archiveFileName && vm.settings.archiveFileName.length ? vm.settings.archiveFileName : 'gatewayConfiguration'; | ||
122 | - gatewayNameExists = utils.customTranslation(vm.settings.gatewayNameExists, vm.settings.gatewayNameExists) || $translate.instant('gateway.gateway-exists'); | ||
123 | - successfulSaved = utils.customTranslation(vm.settings.successfulSave, vm.settings.successfulSave) || $translate.instant('gateway.gateway-saved'); | 138 | + archiveFileName = vm.settings && vm.settings.archiveFileName && vm.settings.archiveFileName.length ? vm.settings.archiveFileName : 'gatewayConfiguration'; |
139 | + if (vm.settings) { | ||
140 | + gatewayNameExists = utils.customTranslation(vm.settings.deviceNameExist, vm.settings.deviceNameExist) || $translate.instant('gateway.gateway-exists'); | ||
141 | + successfulSaved = utils.customTranslation(vm.settings.successfulSave, vm.settings.successfulSave) || $translate.instant('gateway.gateway-saved'); | ||
142 | + } else { | ||
143 | + gatewayNameExists = $translate.instant('gateway.gateway-exists'); | ||
144 | + successfulSaved = $translate.instant('gateway.gateway-saved'); | ||
145 | + } | ||
124 | } | 146 | } |
125 | 147 | ||
126 | function initializeConfig() { | 148 | function initializeConfig() { |
@@ -129,6 +151,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -129,6 +151,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
129 | getGatewaysList(true); | 151 | getGatewaysList(true); |
130 | } | 152 | } |
131 | 153 | ||
154 | + | ||
132 | vm.getAccessToken = (deviceId) => { | 155 | vm.getAccessToken = (deviceId) => { |
133 | if (deviceId.id) { | 156 | if (deviceId.id) { |
134 | getDeviceCredentials(deviceId.id); | 157 | getDeviceCredentials(deviceId.id); |
@@ -152,15 +175,15 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -152,15 +175,15 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
152 | deviceService.findByName(deviceObj.name, {ignoreErrors: true}) | 175 | deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
153 | .then( | 176 | .then( |
154 | function () { | 177 | function () { |
155 | - toast.showError(gatewayNameExists, angular.element('.gateway-form'),'top left'); | 178 | + toast.showError(gatewayNameExists, angular.element('.gateway-form'), 'top left'); |
156 | }, | 179 | }, |
157 | function () { | 180 | function () { |
158 | - if(vm.settings.gatewayType && vm.settings.gatewayType.length){ | 181 | + if (vm.settings.gatewayType && vm.settings.gatewayType.length) { |
159 | deviceObj.type = vm.settings.gatewayType; | 182 | deviceObj.type = vm.settings.gatewayType; |
160 | } | 183 | } |
161 | deviceService.saveDevice(deviceObj).then( | 184 | deviceService.saveDevice(deviceObj).then( |
162 | (device) => { | 185 | (device) => { |
163 | - getDeviceCredentials(device.id.id).then(() =>{ | 186 | + getDeviceCredentials(device.id.id).then(() => { |
164 | getGatewaysList(); | 187 | getGatewaysList(); |
165 | }); | 188 | }); |
166 | } | 189 | } |
@@ -173,8 +196,8 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -173,8 +196,8 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
173 | saveAttribute(configurationAttribute, $window.btoa(angular.toJson(getGatewayConfigJSON())), types.attributesScope.shared.value), | 196 | saveAttribute(configurationAttribute, $window.btoa(angular.toJson(getGatewayConfigJSON())), types.attributesScope.shared.value), |
174 | saveAttribute(configurationDraftsAttribute, $window.btoa(angular.toJson(getDraftConnectorJSON())), types.attributesScope.server.value), | 197 | saveAttribute(configurationDraftsAttribute, $window.btoa(angular.toJson(getDraftConnectorJSON())), types.attributesScope.server.value), |
175 | saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value) | 198 | saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value) |
176 | - ]).then(() =>{ | ||
177 | - toast.showSuccess(successfulSaved, 2000, angular.element('.gateway-form'),'top left'); | 199 | + ]).then(() => { |
200 | + toast.showSuccess(successfulSaved, 2000, angular.element('.gateway-form'), 'top left'); | ||
178 | }) | 201 | }) |
179 | }; | 202 | }; |
180 | 203 | ||
@@ -238,7 +261,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -238,7 +261,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
238 | config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; | 261 | config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; |
239 | } | 262 | } |
240 | config += 'connectors:\n'; | 263 | config += 'connectors:\n'; |
241 | - for(let i = 0; i < vm.configurations.connectors.length; i++){ | 264 | + for (let i = 0; i < vm.configurations.connectors.length; i++) { |
242 | if (vm.configurations.connectors[i].enabled) { | 265 | if (vm.configurations.connectors[i].enabled) { |
243 | config += ' -\n'; | 266 | config += ' -\n'; |
244 | config += ' name: ' + vm.configurations.connectors[i].name + '\n'; | 267 | config += ' name: ' + vm.configurations.connectors[i].name + '\n'; |
@@ -250,7 +273,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -250,7 +273,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
250 | } | 273 | } |
251 | 274 | ||
252 | function generateConfigConnectorFiles(fileZipAdd) { | 275 | function generateConfigConnectorFiles(fileZipAdd) { |
253 | - for(let i = 0; i < vm.configurations.connectors.length; i++){ | 276 | + for (let i = 0; i < vm.configurations.connectors.length; i++) { |
254 | if (vm.configurations.connectors[i].enabled) { | 277 | if (vm.configurations.connectors[i].enabled) { |
255 | fileZipAdd[generateFileName(vm.configurations.connectors[i].name)] = angular.toJson(vm.configurations.connectors[i].config); | 278 | fileZipAdd[generateFileName(vm.configurations.connectors[i].name)] = angular.toJson(vm.configurations.connectors[i].config); |
256 | } | 279 | } |
@@ -276,7 +299,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -276,7 +299,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
276 | 299 | ||
277 | function gatewayMainConfigJSON() { | 300 | function gatewayMainConfigJSON() { |
278 | let configuration = {}; | 301 | let configuration = {}; |
279 | - | 302 | + |
280 | let thingsBoard = {}; | 303 | let thingsBoard = {}; |
281 | thingsBoard.host = vm.configurations.host; | 304 | thingsBoard.host = vm.configurations.host; |
282 | thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; | 305 | thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; |
@@ -325,10 +348,10 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -325,10 +348,10 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
325 | } | 348 | } |
326 | 349 | ||
327 | function gatewayConnectorConfigJSON(gatewayConfiguration) { | 350 | function gatewayConnectorConfigJSON(gatewayConfiguration) { |
328 | - for(let i = 0; i < vm.configurations.connectors.length; i++){ | 351 | + for (let i = 0; i < vm.configurations.connectors.length; i++) { |
329 | if (vm.configurations.connectors[i].enabled) { | 352 | if (vm.configurations.connectors[i].enabled) { |
330 | let typeConnector = vm.configurations.connectors[i].configType; | 353 | let typeConnector = vm.configurations.connectors[i].configType; |
331 | - if(!angular.isArray(gatewayConfiguration[typeConnector])){ | 354 | + if (!angular.isArray(gatewayConfiguration[typeConnector])) { |
332 | gatewayConfiguration[typeConnector] = []; | 355 | gatewayConfiguration[typeConnector] = []; |
333 | } | 356 | } |
334 | 357 | ||
@@ -343,7 +366,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -343,7 +366,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
343 | 366 | ||
344 | function getDraftConnectorJSON() { | 367 | function getDraftConnectorJSON() { |
345 | let draftConnector = {}; | 368 | let draftConnector = {}; |
346 | - for(let i = 0; i < vm.configurations.connectors.length; i++){ | 369 | + for (let i = 0; i < vm.configurations.connectors.length; i++) { |
347 | if (!vm.configurations.connectors[i].enabled) { | 370 | if (!vm.configurations.connectors[i].enabled) { |
348 | let connector = { | 371 | let connector = { |
349 | connector: vm.configurations.connectors[i].configType, | 372 | connector: vm.configurations.connectors[i].configType, |
@@ -362,7 +385,10 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -362,7 +385,10 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
362 | const device = devices[i]; | 385 | const device = devices[i]; |
363 | if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { | 386 | if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
364 | vm.gateways.push(device); | 387 | vm.gateways.push(device); |
365 | - if (firstInit && vm.gateways.length && device.name === vm.gateways[0].name) { | 388 | + if (vm.deviceNameForm && firstInit && vm.gateways.length && device.name === vm.deviceNameForm) { |
389 | + vm.configurations.gateway = device; | ||
390 | + vm.getAccessToken(device.id); | ||
391 | + } else if (firstInit && vm.gateways.length && device.name === vm.gateways[0].name) { | ||
366 | vm.configurations.gateway = device; | 392 | vm.configurations.gateway = device; |
367 | vm.getAccessToken(device.id); | 393 | vm.getAccessToken(device.id); |
368 | } | 394 | } |
@@ -385,7 +411,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | @@ -385,7 +411,7 @@ function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, | ||
385 | for (let connectorType in keyValue) { | 411 | for (let connectorType in keyValue) { |
386 | let name = "No name"; | 412 | let name = "No name"; |
387 | if (Object.prototype.hasOwnProperty.call(keyValue[connectorType], 'name')) { | 413 | if (Object.prototype.hasOwnProperty.call(keyValue[connectorType], 'name')) { |
388 | - name = keyValue[connectorType].name ; | 414 | + name = keyValue[connectorType].name; |
389 | } | 415 | } |
390 | let connector = { | 416 | let connector = { |
391 | enabled: true, | 417 | enabled: true, |
@@ -17,30 +17,36 @@ | @@ -17,30 +17,36 @@ | ||
17 | --> | 17 | --> |
18 | <md-content md-scroll-y layout="column" class="gateway-form"> | 18 | <md-content md-scroll-y layout="column" class="gateway-form"> |
19 | <form name="gatewayConfiguration"> | 19 | <form name="gatewayConfiguration"> |
20 | - <md-expansion-panel-group> | ||
21 | - <md-expansion-panel md-component-id="thingsboardPanelId"> | 20 | + <md-expansion-panel-group> |
21 | + <md-expansion-panel md-component-id="{{vm.idForm}}thingsboardPanelId"> | ||
22 | <md-expansion-panel-collapsed> | 22 | <md-expansion-panel-collapsed> |
23 | <div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> | 23 | <div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
24 | <span flex></span> | 24 | <span flex></span> |
25 | <md-expansion-panel-icon></md-expansion-panel-icon> | 25 | <md-expansion-panel-icon></md-expansion-panel-icon> |
26 | </md-expansion-panel-collapsed> | 26 | </md-expansion-panel-collapsed> |
27 | <md-expansion-panel-expanded> | 27 | <md-expansion-panel-expanded> |
28 | - <md-expansion-panel-header ng-click="vm.collapsePanel('thingsboardPanelId')"> | 28 | + <md-expansion-panel-header ng-click="vm.collapsePanel(vm.idForm + 'thingsboardPanelId')"> |
29 | <div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> | 29 | <div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
30 | <span flex></span> | 30 | <span flex></span> |
31 | <md-expansion-panel-icon></md-expansion-panel-icon> | 31 | <md-expansion-panel-icon></md-expansion-panel-icon> |
32 | </md-expansion-panel-header> | 32 | </md-expansion-panel-header> |
33 | <md-expansion-panel-content> | 33 | <md-expansion-panel-content> |
34 | - <tb-gateway-config-select tb-required="true" | 34 | + <tb-gateway-config-select ng-if="!vm.isStateForm" |
35 | + tb-required="true" | ||
35 | ng-model="vm.configurations.gateway" | 36 | ng-model="vm.configurations.gateway" |
36 | the-form="gatewayConfiguration" | 37 | the-form="gatewayConfiguration" |
37 | gateway-list="vm.gateways" | 38 | gateway-list="vm.gateways" |
38 | get_access_token="vm.getAccessToken" | 39 | get_access_token="vm.getAccessToken" |
39 | create-device="vm.createDevice"> | 40 | create-device="vm.createDevice"> |
40 | </tb-gateway-config-select> | 41 | </tb-gateway-config-select> |
42 | + <md-input-container ng-if="vm.isStateForm" | ||
43 | + class="md-block"> | ||
44 | + <label>{{'gateway.gateway-name' | translate }}</label> | ||
45 | + <input ng-disabled="true" type="text" ng-model="vm.configurations.gateway.name" name="gatewayName"/> | ||
46 | + </md-input-container> | ||
41 | <md-input-container class="md-block"> | 47 | <md-input-container class="md-block"> |
42 | <label>{{'gateway.security-type' | translate }}</label> | 48 | <label>{{'gateway.security-type' | translate }}</label> |
43 | - <md-select name="securityType" ng-model="vm.configurations.securityType" required> | 49 | + <md-select ng-disabled="vm.isReadOnlyForm" name="securityType" ng-model="vm.configurations.securityType" required> |
44 | <md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> | 50 | <md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> |
45 | {{securityType.name | translate}} | 51 | {{securityType.name | translate}} |
46 | </md-option> | 52 | </md-option> |
@@ -50,14 +56,14 @@ | @@ -50,14 +56,14 @@ | ||
50 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 56 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
51 | <md-input-container class="md-block" flex> | 57 | <md-input-container class="md-block" flex> |
52 | <label>{{ 'gateway.thingsboard-host' | translate }}</label> | 58 | <label>{{ 'gateway.thingsboard-host' | translate }}</label> |
53 | - <input type="text" name="host" ng-model="vm.configurations.host" required> | 59 | + <input ng-disabled="vm.isReadOnlyForm" type="text" name="host" ng-model="vm.configurations.host" required> |
54 | <div ng-messages="gatewayConfiguration.host.$error"> | 60 | <div ng-messages="gatewayConfiguration.host.$error"> |
55 | <div ng-message="required" translate>gateway.thingsboard-host-required</div> | 61 | <div ng-message="required" translate>gateway.thingsboard-host-required</div> |
56 | </div> | 62 | </div> |
57 | </md-input-container> | 63 | </md-input-container> |
58 | <md-input-container class="md-block" flex> | 64 | <md-input-container class="md-block" flex> |
59 | <label>{{ 'gateway.thingsboard-port' | translate }}</label> | 65 | <label>{{ 'gateway.thingsboard-port' | translate }}</label> |
60 | - <input type="number" min="1" max="65535" ng-pattern="/^-?[0-9]+$/" name="port" | 66 | + <input ng-disabled="vm.isReadOnlyForm" type="number" min="1" max="65535" ng-pattern="/^-?[0-9]+$/" name="port" |
61 | ng-model="vm.configurations.port" required> | 67 | ng-model="vm.configurations.port" required> |
62 | <div ng-messages="gatewayConfiguration.port.$error"> | 68 | <div ng-messages="gatewayConfiguration.port.$error"> |
63 | <div ng-message="required" translate>gateway.thingsboard-port-required</div> | 69 | <div ng-message="required" translate>gateway.thingsboard-port-required</div> |
@@ -70,18 +76,18 @@ | @@ -70,18 +76,18 @@ | ||
70 | <div ng-if="vm.configurations.securityType=='tls'"> | 76 | <div ng-if="vm.configurations.securityType=='tls'"> |
71 | <md-input-container class="md-block security-type"> | 77 | <md-input-container class="md-block security-type"> |
72 | <label>{{'gateway.tls-path-ca-certificate' | translate }}</label> | 78 | <label>{{'gateway.tls-path-ca-certificate' | translate }}</label> |
73 | - <input type="text" ng-model="vm.configurations.caCertPath" name="caCertPath" /> | 79 | + <input ng-disabled="vm.isReadOnlyForm" type="text" ng-model="vm.configurations.caCertPath" name="caCertPath"/> |
74 | </md-input-container> | 80 | </md-input-container> |
75 | <md-input-container class="md-block"> | 81 | <md-input-container class="md-block"> |
76 | <label>{{'gateway.tls-path-private-key' | translate }}</label> | 82 | <label>{{'gateway.tls-path-private-key' | translate }}</label> |
77 | - <input type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath" /> | 83 | + <input ng-disabled="vm.isReadOnlyForm" type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath"/> |
78 | </md-input-container> | 84 | </md-input-container> |
79 | <md-input-container class="md-block"> | 85 | <md-input-container class="md-block"> |
80 | <label>{{'gateway.tls-path-client-certificate' | translate }}</label> | 86 | <label>{{'gateway.tls-path-client-certificate' | translate }}</label> |
81 | - <input type="text" ng-model="vm.configurations.certPath" name="certPath" /> | 87 | + <input ng-disabled="vm.isReadOnlyForm" type="text" ng-model="vm.configurations.certPath" name="certPath"/> |
82 | </md-input-container> | 88 | </md-input-container> |
83 | </div> | 89 | </div> |
84 | - <md-checkbox ng-model="vm.configurations.remoteConfiguration" | 90 | + <md-checkbox ng-show="!vm.isReadOnlyForm" ng-model="vm.configurations.remoteConfiguration" |
85 | name="remoteConfiguration" | 91 | name="remoteConfiguration" |
86 | aria-label="{{ 'gateway.remote-remote' | translate }}"> | 92 | aria-label="{{ 'gateway.remote-remote' | translate }}"> |
87 | {{ 'gateway.remote' | translate }} | 93 | {{ 'gateway.remote' | translate }} |
@@ -90,7 +96,7 @@ | @@ -90,7 +96,7 @@ | ||
90 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 96 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
91 | <md-input-container class="md-block md-select-container" flex> | 97 | <md-input-container class="md-block md-select-container" flex> |
92 | <label>{{'gateway.remote-logging-level' | translate }}</label> | 98 | <label>{{'gateway.remote-logging-level' | translate }}</label> |
93 | - <md-select name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> | 99 | + <md-select ng-disabled="vm.isReadOnlyForm" name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> |
94 | <md-option ng-repeat="logLevel in vm.types.gatewayLogLevel" | 100 | <md-option ng-repeat="logLevel in vm.types.gatewayLogLevel" |
95 | ng-value="logLevel" ng-selected="$index === 5"> | 101 | ng-value="logLevel" ng-selected="$index === 5"> |
96 | {{logLevel}} | 102 | {{logLevel}} |
@@ -99,7 +105,7 @@ | @@ -99,7 +105,7 @@ | ||
99 | </md-input-container> | 105 | </md-input-container> |
100 | <md-input-container class="md-block" flex> | 106 | <md-input-container class="md-block" flex> |
101 | <label>{{'gateway.path-logs' | translate }}</label> | 107 | <label>{{'gateway.path-logs' | translate }}</label> |
102 | - <input type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" | 108 | + <input ng-disabled="vm.isReadOnlyForm" type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" |
103 | name="remoteLoggingPathToLogs" required> | 109 | name="remoteLoggingPathToLogs" required> |
104 | <div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> | 110 | <div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> |
105 | <div ng-message="required" translate>gateway.path-logs-required</div> | 111 | <div ng-message="required" translate>gateway.path-logs-required</div> |
@@ -109,14 +115,14 @@ | @@ -109,14 +115,14 @@ | ||
109 | </md-expansion-panel-content> | 115 | </md-expansion-panel-content> |
110 | </md-expansion-panel-expanded> | 116 | </md-expansion-panel-expanded> |
111 | </md-expansion-panel> | 117 | </md-expansion-panel> |
112 | - <md-expansion-panel md-component-id="storagePanelId"> | 118 | + <md-expansion-panel md-component-id="{{vm.idForm}}storagePanelId"> |
113 | <md-expansion-panel-collapsed> | 119 | <md-expansion-panel-collapsed> |
114 | <div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> | 120 | <div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
115 | <span flex></span> | 121 | <span flex></span> |
116 | <md-expansion-panel-icon></md-expansion-panel-icon> | 122 | <md-expansion-panel-icon></md-expansion-panel-icon> |
117 | </md-expansion-panel-collapsed> | 123 | </md-expansion-panel-collapsed> |
118 | <md-expansion-panel-expanded> | 124 | <md-expansion-panel-expanded> |
119 | - <md-expansion-panel-header ng-click="vm.collapsePanel('storagePanelId')"> | 125 | + <md-expansion-panel-header ng-click="vm.collapsePanel(vm.idForm + 'storagePanelId')"> |
120 | <div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> | 126 | <div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
121 | <span flex></span> | 127 | <span flex></span> |
122 | <md-expansion-panel-icon></md-expansion-panel-icon> | 128 | <md-expansion-panel-icon></md-expansion-panel-icon> |
@@ -124,18 +130,17 @@ | @@ -124,18 +130,17 @@ | ||
124 | <md-expansion-panel-content> | 130 | <md-expansion-panel-content> |
125 | <md-input-container class="md-block" flex> | 131 | <md-input-container class="md-block" flex> |
126 | <label>{{'gateway.storage-type' | translate }}</label> | 132 | <label>{{'gateway.storage-type' | translate }}</label> |
127 | - <md-select required ng-model="vm.configurations.storageType"> | 133 | + <md-select ng-disabled="vm.isReadOnlyForm" required ng-model="vm.configurations.storageType"> |
128 | <md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> | 134 | <md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> |
129 | {{storageType.name | translate}} | 135 | {{storageType.name | translate}} |
130 | </md-option> | 136 | </md-option> |
131 | </md-select> | 137 | </md-select> |
132 | </md-input-container> | 138 | </md-input-container> |
133 | - | ||
134 | <div layout="row" class="gateway-form-row" | 139 | <div layout="row" class="gateway-form-row" |
135 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 140 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
136 | <md-input-container class="md-block" flex> | 141 | <md-input-container class="md-block" flex> |
137 | <label>{{'gateway.storage-pack-size' | translate }}</label> | 142 | <label>{{'gateway.storage-pack-size' | translate }}</label> |
138 | - <input type="number" min="1" name="readRecordsCount" ng-pattern="/^-?[0-9]+$/" | 143 | + <input ng-disabled="vm.isReadOnlyForm" type="number" min="1" name="readRecordsCount" ng-pattern="/^-?[0-9]+$/" |
139 | ng-model='vm.configurations.readRecordsCount' required/> | 144 | ng-model='vm.configurations.readRecordsCount' required/> |
140 | <div ng-messages="gatewayConfiguration.readRecordsCount.$error"> | 145 | <div ng-messages="gatewayConfiguration.readRecordsCount.$error"> |
141 | <div ng-message="required" translate>gateway.storage-pack-size-required</div> | 146 | <div ng-message="required" translate>gateway.storage-pack-size-required</div> |
@@ -143,10 +148,9 @@ | @@ -143,10 +148,9 @@ | ||
143 | <div ng-message="pattern" translate>gateway.storage-pack-size-pattern</div> | 148 | <div ng-message="pattern" translate>gateway.storage-pack-size-pattern</div> |
144 | </div> | 149 | </div> |
145 | </md-input-container> | 150 | </md-input-container> |
146 | - | ||
147 | <md-input-container class="md-block" flex> | 151 | <md-input-container class="md-block" flex> |
148 | <label translate>{{ vm.configurations.storageType !== 'fileStorage' ? 'gateway.storage-max-records' : 'gateway.storage-max-file-records' }}</label> | 152 | <label translate>{{ vm.configurations.storageType !== 'fileStorage' ? 'gateway.storage-max-records' : 'gateway.storage-max-file-records' }}</label> |
149 | - <input type="number" min="1" name="maxRecordsCount" ng-pattern="/^-?[0-9]+$/" | 153 | + <input ng-disabled="vm.isReadOnlyForm" type="number" min="1" name="maxRecordsCount" ng-pattern="/^-?[0-9]+$/" |
150 | ng-model='vm.configurations.maxRecordsCount' required/> | 154 | ng-model='vm.configurations.maxRecordsCount' required/> |
151 | <div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> | 155 | <div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> |
152 | <div ng-message="required" translate>gateway.storage-max-records-required</div> | 156 | <div ng-message="required" translate>gateway.storage-max-records-required</div> |
@@ -155,13 +159,12 @@ | @@ -155,13 +159,12 @@ | ||
155 | </div> | 159 | </div> |
156 | </md-input-container> | 160 | </md-input-container> |
157 | </div> | 161 | </div> |
158 | - | ||
159 | <div layout="row" class="gateway-form-row" | 162 | <div layout="row" class="gateway-form-row" |
160 | ng-if="vm.configurations.storageType == 'fileStorage'" | 163 | ng-if="vm.configurations.storageType == 'fileStorage'" |
161 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> | 164 | ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
162 | <md-input-container class="md-block" flex> | 165 | <md-input-container class="md-block" flex> |
163 | <label>{{'gateway.storage-max-files' | translate }}</label> | 166 | <label>{{'gateway.storage-max-files' | translate }}</label> |
164 | - <input type="number" min="1" name="maxFilesCount" ng-pattern="/^-?[0-9]+$/" | 167 | + <input ng-disabled="vm.isReadOnlyForm" type="number" min="1" name="maxFilesCount" ng-pattern="/^-?[0-9]+$/" |
165 | ng-model='vm.configurations.maxFilesCount' required/> | 168 | ng-model='vm.configurations.maxFilesCount' required/> |
166 | <div ng-messages="gatewayConfiguration.maxFilesCount.$error"> | 169 | <div ng-messages="gatewayConfiguration.maxFilesCount.$error"> |
167 | <div ng-message="required" translate>gateway.storage-max-files-required</div> | 170 | <div ng-message="required" translate>gateway.storage-max-files-required</div> |
@@ -169,10 +172,9 @@ | @@ -169,10 +172,9 @@ | ||
169 | <div ng-message="pattern" translate>gateway.storage-max-files-pattern</div> | 172 | <div ng-message="pattern" translate>gateway.storage-max-files-pattern</div> |
170 | </div> | 173 | </div> |
171 | </md-input-container> | 174 | </md-input-container> |
172 | - | ||
173 | <md-input-container class="md-block" flex> | 175 | <md-input-container class="md-block" flex> |
174 | <label>{{'gateway.storage-path' | translate }}</label> | 176 | <label>{{'gateway.storage-path' | translate }}</label> |
175 | - <input type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' | 177 | + <input ng-disabled="vm.isReadOnlyForm" type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' |
176 | required/> | 178 | required/> |
177 | <div ng-messages="gatewayConfiguration.dataFolderPath.$error"> | 179 | <div ng-messages="gatewayConfiguration.dataFolderPath.$error"> |
178 | <div ng-message="required" translate>gateway.storage-path-required</div> | 180 | <div ng-message="required" translate>gateway.storage-path-required</div> |
@@ -182,14 +184,14 @@ | @@ -182,14 +184,14 @@ | ||
182 | </md-expansion-panel-content> | 184 | </md-expansion-panel-content> |
183 | </md-expansion-panel-expanded> | 185 | </md-expansion-panel-expanded> |
184 | </md-expansion-panel> | 186 | </md-expansion-panel> |
185 | - <md-expansion-panel md-component-id="connectorsPanelId"> | 187 | + <md-expansion-panel md-component-id="{{vm.idForm}}connectorsPanelId"> |
186 | <md-expansion-panel-collapsed> | 188 | <md-expansion-panel-collapsed> |
187 | <div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> | 189 | <div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
188 | <span flex></span> | 190 | <span flex></span> |
189 | <md-expansion-panel-icon></md-expansion-panel-icon> | 191 | <md-expansion-panel-icon></md-expansion-panel-icon> |
190 | </md-expansion-panel-collapsed> | 192 | </md-expansion-panel-collapsed> |
191 | <md-expansion-panel-expanded> | 193 | <md-expansion-panel-expanded> |
192 | - <md-expansion-panel-header ng-click="vm.collapsePanel('connectorsPanelId')"> | 194 | + <md-expansion-panel-header ng-click="vm.collapsePanel(vm.idForm + 'connectorsPanelId')"> |
193 | <div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> | 195 | <div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
194 | <span flex></span> | 196 | <span flex></span> |
195 | <md-expansion-panel-icon></md-expansion-panel-icon> | 197 | <md-expansion-panel-icon></md-expansion-panel-icon> |
@@ -198,13 +200,14 @@ | @@ -198,13 +200,14 @@ | ||
198 | <tb-gateway-config | 200 | <tb-gateway-config |
199 | gateway-config="vm.configurations.connectors" | 201 | gateway-config="vm.configurations.connectors" |
200 | the-form="gatewayConfiguration" | 202 | the-form="gatewayConfiguration" |
201 | - change-alignment="vm.changeAlignment"> | 203 | + change-alignment="vm.changeAlignment" |
204 | + is-read-only="vm.isReadOnlyForm"> | ||
202 | </tb-gateway-config> | 205 | </tb-gateway-config> |
203 | </md-expansion-panel-content> | 206 | </md-expansion-panel-content> |
204 | </md-expansion-panel-expanded> | 207 | </md-expansion-panel-expanded> |
205 | </md-expansion-panel> | 208 | </md-expansion-panel> |
206 | </md-expansion-panel-group> | 209 | </md-expansion-panel-group> |
207 | - <section layout="row" layout-align="end center" class="form-action-buttons"> | 210 | + <section ng-show="!vm.isReadOnlyForm" layout="row" layout-align="end center" class="form-action-buttons"> |
208 | <md-button class="md-primary md-raised" | 211 | <md-button class="md-primary md-raised" |
209 | ng-click="vm.exportConfig()" | 212 | ng-click="vm.exportConfig()" |
210 | ng-if="!vm.configurations.remoteConfiguration" | 213 | ng-if="!vm.configurations.remoteConfiguration" |
@@ -213,14 +216,14 @@ | @@ -213,14 +216,14 @@ | ||
213 | {{'action.download' | translate }} | 216 | {{'action.download' | translate }} |
214 | <md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> | 217 | <md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> |
215 | </md-button> | 218 | </md-button> |
216 | - | ||
217 | <md-button class="md-primary md-raised" | 219 | <md-button class="md-primary md-raised" |
218 | ng-click="vm.saveAttributeConfig()" | 220 | ng-click="vm.saveAttributeConfig()" |
219 | ng-if="vm.configurations.remoteConfiguration" | 221 | ng-if="vm.configurations.remoteConfiguration" |
220 | ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" | 222 | ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
221 | aria-label="{{ 'gateway.save-tip' | translate }}"> | 223 | aria-label="{{ 'gateway.save-tip' | translate }}"> |
222 | {{'action.save' | translate }} | 224 | {{'action.save' | translate }} |
223 | - <md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }}</md-tooltip> | 225 | + <md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }} |
226 | + </md-tooltip> | ||
224 | </md-button> | 227 | </md-button> |
225 | </section> | 228 | </section> |
226 | </form> | 229 | </form> |
@@ -1201,7 +1201,12 @@ | @@ -1201,7 +1201,12 @@ | ||
1201 | "tls-path-private-key": "Path to private key on gateway", | 1201 | "tls-path-private-key": "Path to private key on gateway", |
1202 | "toggle-fullscreen": "Toggle fullscreen", | 1202 | "toggle-fullscreen": "Toggle fullscreen", |
1203 | "transformer-json-config": "Configuration JSON*", | 1203 | "transformer-json-config": "Configuration JSON*", |
1204 | - "update-config": "Add/update configuration JSON" | 1204 | + "update-config": "Add/update configuration JSON", |
1205 | + "state-title": "Gateway state", | ||
1206 | + "show-config-tip": "Show gateway configuration", | ||
1207 | + "title-show-config": "Show gateway configuration", | ||
1208 | + "read-only": "Read only", | ||
1209 | + "read-write": "" | ||
1205 | }, | 1210 | }, |
1206 | "grid": { | 1211 | "grid": { |
1207 | "delete-item-title": "Are you sure you want to delete this item?", | 1212 | "delete-item-title": "Are you sure you want to delete this item?", |