Browse Source
* Change translate, layout and clear code * Refactoring code * Refactoring code * Refactoring code * Code refactoringpull/2397/head
committed by
GitHub
18 changed files with 1078 additions and 1248 deletions
@ -1,317 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import './gateway-config.scss'; |
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import gatewayTemplate from './gateway-config.tpl.html'; |
|||
import gatewayDialogTemplate from './gateway-config-dialog.tpl.html'; |
|||
import beautify from "js-beautify"; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
const js_beautify = beautify.js; |
|||
|
|||
export default angular.module('thingsboard.directives.gatewayConfig', []) |
|||
.directive('tbGatewayConfig', GatewayConfig) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayConfig() { |
|||
return { |
|||
restrict: "E", |
|||
scope: true, |
|||
bindToController: { |
|||
disabled: '=ngDisabled', |
|||
titleText: '@?', |
|||
keyPlaceholderText: '@?', |
|||
valuePlaceholderText: '@?', |
|||
noDataText: '@?', |
|||
gatewayConfig: '=', |
|||
changeAlignment: '=' |
|||
}, |
|||
controller: GatewayConfigController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayTemplate |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, types, toast, $timeout, $compile, $translate) { //eslint-disable-line
|
|||
|
|||
let vm = this; |
|||
|
|||
vm.kvList = []; |
|||
vm.types = types; |
|||
$scope.$watch('vm.gatewayConfig', () => { |
|||
vm.stopWatchKvList(); |
|||
vm.kvList.length = 0; |
|||
if (vm.gatewayConfig) { |
|||
for (var property in vm.gatewayConfig) { |
|||
if (Object.prototype.hasOwnProperty.call(vm.gatewayConfig, property)) { |
|||
vm.kvList.push( |
|||
{ |
|||
enabled: vm.gatewayConfig[property].enabled, |
|||
key: property + '', |
|||
value: vm.gatewayConfig[property].connector + '', |
|||
config: js_beautify(vm.gatewayConfig[property].config + '', {indent_size: 4}) |
|||
} |
|||
); |
|||
} |
|||
} |
|||
} |
|||
$mdUtil.nextTick(() => { |
|||
vm.watchKvList(); |
|||
}); |
|||
}); |
|||
|
|||
vm.watchKvList = () => { |
|||
$scope.kvListWatcher = $scope.$watch('vm.kvList', () => { |
|||
if (!vm.gatewayConfig) { |
|||
return; |
|||
} |
|||
for (let property in vm.gatewayConfig) { |
|||
if (Object.prototype.hasOwnProperty.call(vm.gatewayConfig, property)) { |
|||
delete vm.gatewayConfig[property]; |
|||
} |
|||
} |
|||
for (let i = 0; i < vm.kvList.length; i++) { |
|||
let entry = vm.kvList[i]; |
|||
if (entry.key && entry.value) { |
|||
let connectorJSON = angular.toJson({ |
|||
enabled: entry.enabled, |
|||
connector: entry.value, |
|||
config: angular.fromJson(entry.config) |
|||
}); |
|||
vm.gatewayConfig [entry.key] = angular.fromJson(connectorJSON); |
|||
} |
|||
} |
|||
}, true); |
|||
}; |
|||
|
|||
vm.stopWatchKvList = () => { |
|||
if ($scope.kvListWatcher) { |
|||
$scope.kvListWatcher(); |
|||
$scope.kvListWatcher = null; |
|||
} |
|||
}; |
|||
|
|||
vm.removeKeyVal = (index) => { |
|||
if (index > -1) { |
|||
vm.kvList.splice(index, 1); |
|||
} |
|||
}; |
|||
|
|||
vm.addKeyVal = () => { |
|||
if (!vm.kvList) { |
|||
vm.kvList = []; |
|||
} |
|||
vm.kvList.push( |
|||
{ |
|||
enabled: false, |
|||
key: '', |
|||
value: '', |
|||
config: '{}' |
|||
} |
|||
); |
|||
} |
|||
|
|||
vm.openConfigDialog = ($event, index, config, typeName) => { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
$mdDialog.show({ |
|||
controller: GatewayDialogController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayDialogTemplate, |
|||
parent: angular.element($document[0].body), |
|||
locals: { |
|||
config: config, |
|||
typeName: typeName |
|||
}, |
|||
targetEvent: $event, |
|||
fullscreen: true, |
|||
multiple: true, |
|||
}).then(function (config) { |
|||
if (config) { |
|||
if (index > -1) { |
|||
vm.kvList[index].config = config; |
|||
} |
|||
} |
|||
}, function () { |
|||
}); |
|||
|
|||
}; |
|||
|
|||
vm.configTypeChange = (keyVal) => { |
|||
for (let prop in types.gatewayConfigType) { |
|||
if (types.gatewayConfigType[prop].value === keyVal.value) { |
|||
if (!keyVal.key) { |
|||
keyVal.key = vm.configTypeChangeValid(types.gatewayConfigType[prop].name, 0); |
|||
} |
|||
} |
|||
} |
|||
vm.checkboxValid(keyVal); |
|||
}; |
|||
|
|||
vm.keyValChange = (keyVal, indexKey) => { |
|||
keyVal.key = vm.keyValChangeValid(keyVal.key, 0, indexKey); |
|||
vm.checkboxValid(keyVal); |
|||
}; |
|||
|
|||
vm.configTypeChangeValid = (name, index) => { |
|||
let newKeyName = index ? name + index : name; |
|||
let indexRes = vm.kvList.findIndex((element) => element.key === newKeyName); |
|||
return indexRes === -1 ? newKeyName : vm.configTypeChangeValid(name, ++index); |
|||
}; |
|||
|
|||
vm.keyValChangeValid = (name, index, indexKey) => { |
|||
angular.forEach(vm.kvList, function (value, key) { |
|||
let nameEq = (index === 0) ? name : name + index; |
|||
if (key !== indexKey && value.key && value.key === nameEq) { |
|||
index++; |
|||
vm.keyValChangeValid(name, index, indexKey); |
|||
} |
|||
|
|||
}); |
|||
return (index === 0) ? name : name + index; |
|||
}; |
|||
|
|||
vm.buttonValid = (config) => { |
|||
return (angular.equals("{}", config)) ? "md-warn" : "md-primary"; |
|||
}; |
|||
|
|||
vm.checkboxValid = (keyVal) => { |
|||
if (!keyVal.key || angular.equals("", keyVal.key) |
|||
|| !keyVal.value || angular.equals("", keyVal.value) |
|||
|| angular.equals("{}", keyVal.config)) { |
|||
return keyVal.enabled = false; |
|||
} |
|||
return true; |
|||
}; |
|||
vm.checkboxValidMouseover = ($event, keyVal) => { |
|||
console.log($event, keyVal); //eslint-disable-line
|
|||
vm.checkboxValidClick ($event, keyVal); |
|||
}; |
|||
|
|||
vm.checkboxValidClick = ($event, keyVal) => { |
|||
if (!vm.checkboxValid(keyVal)) { |
|||
let errTxt = ""; |
|||
if (!keyVal.key || angular.equals("", keyVal.key)) { |
|||
errTxt = $translate.instant('gateway.keyval-name-err'); |
|||
} |
|||
|
|||
if (!keyVal.value || angular.equals("", keyVal.value)) { |
|||
errTxt += '<div>' + $translate.instant('gateway.keyval-type-err') + '</div>'; |
|||
} |
|||
|
|||
if (angular.equals("{}", keyVal.config)) { |
|||
errTxt += '<div>' + $translate.instant('gateway.keyval-config-err') + '</div>'; |
|||
} |
|||
if (!angular.equals("", errTxt)) { |
|||
displayTooltip($event, '<div class="tb-rule-node-tooltip tb-lib-tooltip">' + |
|||
'<div id="tb-node-content" layout="column">' + |
|||
'<div class="tb-node-title">' + $translate.instant('gateway.keyval-save-err') + '</div>' + |
|||
'<div class="tb-node-details">' + errTxt + '</div>' + |
|||
'</div>' + |
|||
'</div>'); |
|||
} |
|||
} |
|||
else { |
|||
destroyTooltips(); |
|||
} |
|||
}; |
|||
|
|||
|
|||
function displayTooltip(event, content) { |
|||
destroyTooltips(); |
|||
vm.tooltipTimeout = $timeout(() => { |
|||
var element = angular.element(event.target); |
|||
element.tooltipster( |
|||
{ |
|||
theme: 'tooltipster-shadow', |
|||
delay: 10, |
|||
animation: 'grow', |
|||
side: 'right' |
|||
} |
|||
); |
|||
var contentElement = angular.element(content); |
|||
$compile(contentElement)($scope); |
|||
var tooltip = element.tooltipster('instance'); |
|||
tooltip.content(contentElement); |
|||
tooltip.open(); |
|||
}, 500); |
|||
} |
|||
|
|||
function destroyTooltips() { |
|||
if (vm.tooltipTimeout) { |
|||
$timeout.cancel(vm.tooltipTimeout); |
|||
vm.tooltipTimeout = null; |
|||
} |
|||
var instances = angular.element.tooltipster.instances(); |
|||
instances.forEach((instance) => { |
|||
if (!instance.isErrorTooltip) { |
|||
instance.destroy(); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayDialogController($scope, $mdDialog, $document, $window, config, typeName) { |
|||
let vm = this; |
|||
vm.doc = $document[0]; |
|||
vm.config = angular.copy(config); |
|||
vm.typeName = "" + typeName; |
|||
vm.configAreaOptions = { |
|||
useWrapMode: false, |
|||
mode: 'json', |
|||
showGutter: true, |
|||
showPrintMargin: true, |
|||
theme: 'github', |
|||
advanced: { |
|||
enableSnippets: true, |
|||
enableBasicAutocompletion: true, |
|||
enableLiveAutocompletion: true |
|||
}, |
|||
onLoad: function (_ace) { |
|||
_ace.$blockScrolling = 1; |
|||
} |
|||
}; |
|||
|
|||
vm.validateConfig = (model, editorName) => { |
|||
if (model && model.length) { |
|||
try { |
|||
angular.fromJson(model); |
|||
$scope.theForm[editorName].$setValidity('configJSON', true); |
|||
} catch (e) { |
|||
$scope.theForm[editorName].$setValidity('configJSON', false); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.save = () => { |
|||
$mdDialog.hide(vm.config); |
|||
}; |
|||
|
|||
vm.cancel = () => { |
|||
$mdDialog.hide(); |
|||
}; |
|||
|
|||
vm.beautifyJson = () => { |
|||
vm.config = js_beautify(vm.config, {indent_size: 4}); |
|||
}; |
|||
} |
|||
|
|||
@ -1,94 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<form name="gatewayConfig" flex layout="column" class="gateway-config"> |
|||
<div layout="row" id="section-row" ng-repeat="keyVal in vm.kvList track by $index"> |
|||
<div layout="column" layout-align="center center" class="gateway-config-row"> |
|||
<md-input-container class="md-block"> |
|||
<md-checkbox ng-model="keyVal.enabled" |
|||
aria-label="{{ 'gateway.enabled' | translate }}" |
|||
ng-change="vm.checkboxValid(keyVal)" |
|||
ng-click="vm.checkboxValidClick($event, keyVal)" |
|||
ng-mouseover="vm.checkboxValidMouseover($event, keyVal)"> |
|||
</md-checkbox> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.enabled' | translate }} |
|||
</md-tooltip> |
|||
</md-input-container> |
|||
</div> |
|||
<div layout="row" flex class="gateway-config-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.connector-type' | translate }}</label> |
|||
<md-select name="configType" ng-change="vm.configTypeChange(keyVal)" ng-model="keyVal.value" required> |
|||
<md-option ng-repeat="configType in vm.types.gatewayConfigType" ng-value="configType.value"> |
|||
{{configType.value}} |
|||
</md-option> |
|||
</md-select> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.connector-type' | translate }} |
|||
</md-tooltip> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<input placeholder="{{ (vm.keyPlaceholderText ? vm.keyPlaceholderText : 'gateway.name') | translate }}" |
|||
ng-model-options="{ updateOn: 'blur' }" |
|||
ng-change="vm.keyValChange(keyVal, $index)" name="key" ng-model="keyVal.key" required/> |
|||
<div ng-messages="gatewayConfig.key.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.name' | translate }} |
|||
</md-tooltip> |
|||
</md-input-container> |
|||
</div> |
|||
<div layout="row" layout-align="end center" class="action-buttons" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-button class="md-icon-button md-fab md-mini" |
|||
name="updateconf" |
|||
ng-click="vm.openConfigDialog($event, $index, keyVal.config, keyVal.key)" |
|||
aria-label="{{ 'gateway.update-config' | translate }}" |
|||
ng-class="vm.buttonValid(keyVal.config)" required> |
|||
<md-icon class="material-icons">settings_ethernet</md-icon> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.update-config' | translate }} |
|||
</md-tooltip> |
|||
</md-button> |
|||
<md-button ng-show="!vm.disabled" ng-disabled="$root.loading" |
|||
class="md-icon-button md-fab md-mini md-primary" |
|||
ng-click="vm.removeKeyVal($index)" |
|||
aria-label="{{ 'gateway.delete' | translate }}"> |
|||
<md-icon class="material-icons">close</md-icon> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.delete' | translate }} |
|||
</md-tooltip> |
|||
</md-button> |
|||
</div> |
|||
</div> |
|||
<span ng-show="!vm.kvList.length" |
|||
layout-align="center center" ng-class="{'disabled': vm.disabled}" |
|||
class="no-data-found" translate>{{vm.noDataText ? vm.noDataText : 'gateway.no-connectors'}}</span> |
|||
<div> |
|||
<md-button ng-show="!vm.disabled" ng-disabled="$root.loading" class="md-raised" |
|||
ng-click="vm.addKeyVal()" |
|||
aria-label="{{ 'gateway.add-connectors' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.add-connectors' | translate }} |
|||
</md-tooltip> |
|||
<span translate>action.add</span> |
|||
</md-button> |
|||
</div> |
|||
</form > |
|||
@ -1,498 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import './gateway-form.scss'; |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import gatewayFormTemplate from './gateway-form.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
export default angular.module('thingsboard.directives.gatewayForm', []) |
|||
.directive('tbGatewayForm', GatewayForm) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayForm() { |
|||
return { |
|||
restrict: "E", |
|||
scope: true, |
|||
bindToController: { |
|||
disabled: '=ngDisabled', |
|||
keyPlaceholderText: '@?', |
|||
valuePlaceholderText: '@?', |
|||
noDataText: '@?', |
|||
formId: '=', |
|||
ctx: '=', |
|||
gatewayFormConfig: '=', |
|||
theForm: '=' |
|||
}, |
|||
controller: GatewayFormController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayFormTemplate |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, toast, importExport, attributeService, deviceService, userService, $mdDialog, $mdUtil, types, $window, $q) { |
|||
$scope.$mdExpansionPanel = $mdExpansionPanel; |
|||
let vm = this; |
|||
const attributeNameClinet = "current_configuration"; |
|||
const attributeNameServer = "configuration_drafts"; |
|||
const attributeNameShared = "configuration"; |
|||
const attributeNameLogShared = "RemoteLoggingLevel"; |
|||
vm.remoteLoggingConfig = '[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"'; |
|||
vm.types = types; |
|||
|
|||
vm.configurations = { |
|||
singleSelect: '', |
|||
host: $document[0].domain, |
|||
port: 1883, |
|||
remoteConfiguration: true, |
|||
accessToken: '', |
|||
entityType: '', |
|||
entityId: '', |
|||
storageType: "memoryStorage", // "memoryStorage"; fileStorage
|
|||
readRecordsCount: 100, |
|||
maxRecordsCount: 10000, |
|||
dataFolderPath: './data/', |
|||
maxFilesCount: 5, |
|||
securityType: "accessToken", // "accessToken", "tls"
|
|||
caCertPath: '/etc/thingsboard-gateway/ca.pem', |
|||
privateKeyPath: '/etc/thingsboard-gateway/privateKey.pem', |
|||
certPath: '/etc/thingsboard-gateway/certificate.pem', |
|||
connectors: {}, |
|||
remoteLoggingLevel: "DEBUG", // level login
|
|||
remoteLoggingPathToLogs: './logs/' |
|||
}; |
|||
getGatewaysListByUser(true); |
|||
|
|||
vm.securityTypes = [{ |
|||
name: 'Access Token', |
|||
value: 'accessToken' |
|||
}, { |
|||
name: 'TLS', |
|||
value: 'tls' |
|||
}]; |
|||
|
|||
vm.storageTypes = [{ |
|||
name: 'Memory storage', |
|||
value: 'memoryStorage' |
|||
}, { |
|||
name: 'File storage', |
|||
value: 'fileStorage' |
|||
}]; |
|||
|
|||
$scope.$on('gateway-form-resize', function (event, formId) { |
|||
if (vm.formId == formId) { |
|||
updateWidgetDisplaying(); |
|||
} |
|||
}); |
|||
|
|||
function updateWidgetDisplaying() { |
|||
if (vm.ctx && vm.ctx.$container) { |
|||
vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); |
|||
} |
|||
} |
|||
|
|||
updateWidgetDisplaying(); |
|||
|
|||
vm.getAccessToken = (deviceObj) => { |
|||
if (deviceObj.name) { |
|||
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
|||
.then( |
|||
function (device) { |
|||
getDeviceCredential(device.id.id); |
|||
} |
|||
) |
|||
} |
|||
}; |
|||
|
|||
function getDeviceCredential(deviceId) { |
|||
return deviceService.getDeviceCredentials(deviceId).then( |
|||
(deviceCredentials) => { |
|||
vm.configurations.accessToken = deviceCredentials.credentialsId; |
|||
vm.configurations.entityType = deviceCredentials.deviceId.entityType; |
|||
vm.configurations.entityId = deviceCredentials.deviceId.id; |
|||
vm.getAttributeStart(); |
|||
} |
|||
); |
|||
} |
|||
|
|||
vm.createDevice = (deviceObj) => { |
|||
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
|||
.then( |
|||
function (device) { |
|||
getDeviceCredential(device.id.id).then(() => { |
|||
getGatewaysListByUser(); |
|||
}); |
|||
}, |
|||
function () { |
|||
deviceService.saveDevice(deviceObj).then( |
|||
(device) => { |
|||
deviceService.getDeviceCredentials(device.id.id).then( |
|||
(data) => { |
|||
vm.configurations.accessToken = data.credentialsId; |
|||
vm.configurations.entityType = device.id.entityType; |
|||
vm.configurations.entityId = device.id.id; |
|||
vm.getAttributeStart(); |
|||
getGatewaysListByUser(); |
|||
} |
|||
); |
|||
} |
|||
); |
|||
}); |
|||
}; |
|||
|
|||
vm.saveAttributeConfig = () => { |
|||
vm.setAttribute(attributeNameShared, $window.btoa(angular.toJson(vm.getConfigAllByAttributeJSON())), types.attributesScope.shared.value); |
|||
vm.setAttribute(attributeNameServer, $window.btoa(angular.toJson(vm.getConfigByAttributeTmpJSON())), types.attributesScope.server.value); |
|||
vm.setAttribute(attributeNameLogShared, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
|||
}; |
|||
|
|||
vm.getAttributeStart = () => { |
|||
let initResps = []; |
|||
vm.configurations.connectors = {}; |
|||
initResps.push(vm.getAttributeConfig(attributeNameClinet, types.attributesScope.client.value)); |
|||
initResps.push(vm.getAttributeConfig(attributeNameServer, types.attributesScope.server.value)); |
|||
initResps.push(vm.getAttributeConfig(attributeNameLogShared, types.attributesScope.shared.value)); |
|||
$q.all(initResps).then((resp) => { |
|||
vm.getAttributeInitFromClient(resp[0]); |
|||
vm.getAttributeInitFromServer(resp[1]); |
|||
vm.getAttributeInitFromShared(resp[2]); |
|||
}, (err) => { |
|||
console.log("getAttribute_error", err); //eslint-disable-line
|
|||
}); |
|||
}; |
|||
|
|||
vm.getAttributeConfig = (attributeName, typeValue) => { |
|||
let keys = [attributeName]; |
|||
return attributeService.getEntityAttributesValues(vm.configurations.entityType, vm.configurations.entityId, typeValue, keys); |
|||
}; |
|||
|
|||
vm.setAttribute = (attributeName, attributeConfig, typeValue) => { |
|||
let attributes = [ |
|||
{ |
|||
key: attributeName, |
|||
value: attributeConfig |
|||
} |
|||
]; |
|||
attributeService.saveEntityAttributes(vm.configurations.entityType, vm.configurations.entityId, typeValue, attributes).then(() => { |
|||
}, (err) => { |
|||
console.log("setAttribute_", err); //eslint-disable-line
|
|||
}); |
|||
}; |
|||
|
|||
vm.exportConfig = () => { |
|||
let fileZip = {}; |
|||
fileZip["tb_gateway.yaml"] = vm.getConfig(); |
|||
vm.createConfigByExport(fileZip); |
|||
vm.getLogsConfigByExport(fileZip); |
|||
importExport.exportJSZip(fileZip, 'config'); |
|||
vm.setAttribute(attributeNameLogShared, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
|||
}; |
|||
|
|||
vm.getConfig = () => { |
|||
let config; |
|||
config = 'thingsboard:\n'; |
|||
config += ' host: ' + vm.configurations.host + '\n'; |
|||
config += ' remoteConfiguration: ' + vm.configurations.remoteConfiguration + '\n'; |
|||
config += ' port: ' + vm.configurations.port + '\n'; |
|||
config += ' security:\n'; |
|||
if (vm.configurations.securityType === 'accessToken') { |
|||
config += ' access-token: ' + vm.configurations.accessToken + '\n'; |
|||
} else if (vm.configurations.securityType === 'tls') { |
|||
config += ' ca_cert: ' + vm.configurations.caCertPath + '\n'; |
|||
config += ' privateKey: ' + vm.configurations.privateKeyPath + '\n'; |
|||
config += ' cert: ' + vm.configurations.certPath + '\n'; |
|||
} |
|||
config += 'storage:\n'; |
|||
if (vm.configurations.storageType === 'memoryStorage') { |
|||
config += ' type: memory\n'; |
|||
config += ' read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|||
config += ' max_records_count: ' + vm.configurations.maxRecordsCount + '\n'; |
|||
} else if (vm.configurations.storageType === 'fileStorage') { |
|||
config += ' type: file\n'; |
|||
config += ' data_folder_path: ' + vm.configurations.dataFolderPath + '\n'; |
|||
config += ' max_file_count: ' + vm.configurations.maxFilesCount + '\n'; |
|||
config += ' max_read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|||
config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; |
|||
} |
|||
config += 'connectors:\n'; |
|||
for (let connector in vm.configurations.connectors) { |
|||
if (vm.configurations.connectors[connector].enabled) { |
|||
config += ' -\n'; |
|||
config += ' name: ' + connector + ' Connector\n'; |
|||
config += ' type: ' + vm.configurations.connectors[connector].connector + '\n'; |
|||
config += ' configuration: ' + vm.validFileName(connector) + ".json" + '\n'; |
|||
} |
|||
} |
|||
return config; |
|||
}; |
|||
|
|||
vm.createConfigByExport = (fileZipAdd) => { |
|||
for (let connector in vm.configurations.connectors) { |
|||
if (vm.configurations.connectors[connector].enabled) { |
|||
fileZipAdd[vm.validFileName(connector) + ".json"] = angular.toJson(vm.configurations.connectors[connector].config); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.getLogsConfigByExport = (fileZipAdd) => { |
|||
fileZipAdd["logs.conf"] = vm.getLogsConfig(); |
|||
}; |
|||
|
|||
vm.getLogsConfig = () => { |
|||
return vm.remoteLoggingConfig |
|||
.replace(/{ERROR}/g, vm.configurations.remoteLoggingLevel) |
|||
.replace(/{.\/logs\/}/g, vm.configurations.remoteLoggingPathToLogs); |
|||
}; |
|||
|
|||
vm.getConfigAllByAttributeJSON = () => { |
|||
let thingsBoardAll = {}; |
|||
thingsBoardAll["thingsboard"] = vm.getConfigMainByAttributeJSON(); |
|||
vm.getConfigByAttributeJSON(thingsBoardAll); |
|||
return thingsBoardAll; |
|||
}; |
|||
|
|||
vm.getConfigMainByAttributeJSON = () => { |
|||
let configMain = {}; |
|||
let thingsBoard = {}; |
|||
thingsBoard.host = vm.configurations.host; |
|||
thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; |
|||
thingsBoard.port = vm.configurations.port; |
|||
let security = {}; |
|||
if (vm.configurations.securityType === 'accessToken') { |
|||
security.accessToken = (vm.configurations.accessToken) ? vm.configurations.accessToken : "" |
|||
} else { |
|||
security.caCert = vm.configurations.caCertPath; |
|||
security.privateKey = vm.configurations.privateKeyPath; |
|||
security.cert = vm.configurations.certPath; |
|||
} |
|||
thingsBoard.security = security; |
|||
configMain.thingsboard = thingsBoard; |
|||
|
|||
let storage = {}; |
|||
if (vm.configurations.storageType === 'memoryStorage') { |
|||
storage.type = "memory"; |
|||
storage.read_records_count = vm.configurations.readRecordsCount; |
|||
storage.max_records_count = vm.configurations.maxRecordsCount; |
|||
} else if (vm.configurations.storageType === 'fileStorage') { |
|||
storage.type = "file"; |
|||
storage.data_folder_path = vm.configurations.dataFolderPath; |
|||
storage.max_file_count = vm.configurations.maxFilesCount; |
|||
storage.max_read_records_count = vm.configurations.readRecordsCount; |
|||
storage.max_records_per_file = vm.configurations.maxRecordsCount; |
|||
} |
|||
configMain.storage = storage; |
|||
|
|||
let conn = []; |
|||
for (let connector in vm.configurations.connectors) { |
|||
if (vm.configurations.connectors[connector].enabled) { |
|||
let connect = {}; |
|||
connect.configuration = vm.validFileName(connector) + ".json"; |
|||
connect.name = connector; |
|||
connect.type = vm.configurations.connectors[connector].connector; |
|||
conn.push(connect); |
|||
} |
|||
} |
|||
configMain.connectors = conn; |
|||
|
|||
configMain.logs = $window.btoa(vm.getLogsConfig()); |
|||
|
|||
return configMain; |
|||
}; |
|||
|
|||
vm.getConfigByAttributeJSON = (thingsBoardBy) => { |
|||
for (let connector in vm.configurations.connectors) { |
|||
if (vm.configurations.connectors[connector].enabled) { |
|||
let typeAr = vm.configurations.connectors[connector].connector; |
|||
let objTypeAll = []; |
|||
for (let conn in vm.configurations.connectors) { |
|||
if (typeAr === vm.configurations.connectors[conn].connector && vm.configurations.connectors[conn].enabled) { |
|||
let objType = {}; |
|||
objType["name"] = conn; |
|||
objType["config"] = vm.configurations.connectors[conn].config; |
|||
objTypeAll.push(objType); |
|||
} |
|||
} |
|||
if (objTypeAll.length > 0) { |
|||
thingsBoardBy[typeAr] = objTypeAll; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.getConfigByAttributeTmpJSON = () => { |
|||
let connects = {}; |
|||
for (let connector in vm.configurations.connectors) { |
|||
if (!vm.configurations.connectors[connector].enabled && Object.keys(vm.configurations.connectors[connector].config).length !== 0) { |
|||
let conn = {}; |
|||
conn["connector"] = vm.configurations.connectors[connector].connector; |
|||
conn["config"] = vm.configurations.connectors[connector].config; |
|||
connects[connector] = conn; |
|||
} |
|||
} |
|||
return connects; |
|||
}; |
|||
|
|||
function getGatewaysListByUser(firstInit) { |
|||
vm.gateways = []; |
|||
vm.currentUser = userService.getCurrentUser(); |
|||
if (vm.currentUser.authority === 'TENANT_ADMIN') { |
|||
deviceService.getTenantDevices({limit: 500}).then( |
|||
(devices) => { |
|||
if (devices.data.length > 0) { |
|||
devices.data.forEach((device) => { |
|||
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
|||
vm.gateways.push(device.name); |
|||
if (firstInit && vm.gateways.length && device.name === vm.gateways[0]) { |
|||
vm.configurations.singleSelect = vm.gateways[0]; |
|||
let deviceObj = { |
|||
"name": vm.configurations.singleSelect, |
|||
"type": "Gateway", |
|||
"additionalInfo": { |
|||
"gateway": true |
|||
} |
|||
}; |
|||
vm.getAccessToken(deviceObj); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
); |
|||
} else if (vm.currentUser.authority === 'CUSTOMER_USER') { |
|||
deviceService.getCustomerDevices(vm.currentUser.customerId, {limit: 500}).then( |
|||
(devices) => { |
|||
if (devices.data.length > 0) { |
|||
devices.data.forEach((device) => { |
|||
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
|||
vm.gateways.push(device.name); |
|||
if (firstInit && vm.gateways.length) { |
|||
vm.configurations.singleSelect = vm.gateways[0]; |
|||
let deviceObj = { |
|||
"name": vm.configurations.singleSelect, |
|||
"type": "Gateway", |
|||
"additionalInfo": { |
|||
"gateway": true |
|||
} |
|||
}; |
|||
vm.getAccessToken(deviceObj); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
); |
|||
} |
|||
} |
|||
|
|||
vm.getAttributeInitFromClient = (resp) => { |
|||
if (resp.length > 0) { |
|||
vm.configurations.connectors = {}; |
|||
let attribute = angular.fromJson($window.atob(resp[0].value)); |
|||
for (var type in attribute) { |
|||
let keyVal = attribute[type]; |
|||
if (type === "thingsboard") { |
|||
if (keyVal !== null && Object.keys(keyVal).length > 0) { |
|||
vm.setConfigMain(keyVal); |
|||
} |
|||
} else { |
|||
for (let typeVal in keyVal) { |
|||
let typeName = ''; |
|||
if (Object.prototype.hasOwnProperty.call(keyVal[typeVal], 'name')) { |
|||
typeName = 'name'; |
|||
} |
|||
let key = ""; |
|||
key = (typeName === "") ? "No name" : ((typeName === 'name') ? keyVal[typeVal].name : keyVal[typeVal][typeName].name); |
|||
let conn = {}; |
|||
conn["enabled"] = true; |
|||
conn["connector"] = type; |
|||
conn["config"] = angular.toJson(keyVal[typeVal].config); |
|||
vm.configurations.connectors[key] = conn; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.getAttributeInitFromServer = (resp) => { |
|||
if (resp.length > 0) { |
|||
let attribute = angular.fromJson($window.atob(resp[0].value)); |
|||
for (let key in attribute) { |
|||
let conn = {}; |
|||
conn["enabled"] = false; |
|||
conn["connector"] = attribute[key].connector; |
|||
conn["config"] = angular.toJson(attribute[key].config); |
|||
vm.configurations.connectors[key] = conn; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.getAttributeInitFromShared = (resp) => { |
|||
if (resp.length > 0) { |
|||
if (vm.types.gatewayLogLevel[resp[0].value.toLowerCase()]) { |
|||
vm.configurations.remoteLoggingLevel = resp[0].value.toUpperCase(); |
|||
} |
|||
} else { |
|||
vm.configurations.remoteLoggingLevel = vm.types.gatewayLogLevel.debug; |
|||
} |
|||
}; |
|||
|
|||
vm.setConfigMain = (keyVal) => { |
|||
if (Object.prototype.hasOwnProperty.call(keyVal, 'thingsboard')) { |
|||
vm.configurations.host = keyVal.thingsboard.host; |
|||
vm.configurations.port = keyVal.thingsboard.port; |
|||
vm.configurations.remoteConfiguration = keyVal.thingsboard.remoteConfiguration; |
|||
if (Object.prototype.hasOwnProperty.call(keyVal.thingsboard.security, 'accessToken')) { |
|||
vm.configurations.securityType = 'accessToken'; |
|||
vm.configurations.accessToken = keyVal.thingsboard.security.accessToken; |
|||
} else { |
|||
vm.configurations.securityType = 'tls'; |
|||
vm.configurations.caCertPath = keyVal.thingsboard.security.caCert; |
|||
vm.configurations.privateKeyPath = keyVal.thingsboard.security.private_key; |
|||
vm.configurations.certPath = keyVal.thingsboard.security.cert; |
|||
} |
|||
} |
|||
if (Object.prototype.hasOwnProperty.call(keyVal, 'storage') && Object.prototype.hasOwnProperty.call(keyVal.storage, 'type')) { |
|||
if (keyVal.storage.type === 'memory') { |
|||
vm.configurations.storageType = 'memoryStorage'; |
|||
vm.configurations.readRecordsCount = keyVal.storage.read_records_count; |
|||
vm.configurations.maxRecordsCount = keyVal.storage.max_records_count; |
|||
} else if (keyVal.storage.type === 'file') { |
|||
vm.configurations.storageType = 'fileStorage'; |
|||
vm.configurations.dataFolderPath = keyVal.storage.data_folder_path; |
|||
vm.configurations.maxFilesCount = keyVal.storage.max_file_count; |
|||
vm.configurations.readRecordsCount = keyVal.storage.read_records_count; |
|||
vm.configurations.maxRecordsCount = keyVal.storage.max_records_count; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.setSaveTypeConfig = (itemVal) => { |
|||
vm.configurations.remoteConfiguration = itemVal.item; |
|||
}; |
|||
|
|||
vm.validFileName = (fileName) => { |
|||
let fileName1 = fileName.replace("_", ""); |
|||
let fileName2 = fileName1.replace("-", ""); |
|||
let fileName3 = fileName2.replace(/^\s+|\s+$/g, ''); |
|||
let fileName4 = fileName3.toLowerCase(); |
|||
return fileName4; |
|||
}; |
|||
} |
|||
|
|||
|
|||
@ -1,219 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<form name="gatewayConfiguration" class="gateway-form"> |
|||
<md-expansion-panel-group> |
|||
<md-expansion-panel md-component-id="thingsboardPanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="$mdExpansionPanel('thingsboardPanelId').collapse()"> |
|||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<tb-gateway-config-select tb-required="true" |
|||
ng-model="vm.configurations.singleSelect" |
|||
the-form="gatewayConfiguration" |
|||
gateway-list="vm.gateways" |
|||
get_access_token="vm.getAccessToken" |
|||
create-device="vm.createDevice"> |
|||
</tb-gateway-config-select> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.security-type' | translate }}</label> |
|||
<md-select name="securityType" ng-model="vm.configurations.securityType"> |
|||
<md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> |
|||
{{securityType.name}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{ 'gateway.thingsboard-host' | translate }}</label> |
|||
<input type="text" name="host" ng-model="vm.configurations.host" required> |
|||
<div ng-messages="gatewayConfiguration.host.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{ 'gateway.thingsboard-port' | translate }}</label> |
|||
<input type="number" min="1" max="65535" step="1" name="port" |
|||
ng-model="vm.configurations.port" required> |
|||
<div ng-messages="gatewayConfiguration.port.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
<div ng-message="max" translate>max</div> |
|||
<div ng-message="min" translate>min</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
<div ng-if="vm.configurations.securityType=='tls'"> |
|||
<md-input-container class="md-block security-type"> |
|||
<label>{{'gateway.tls-path-ca-certificate' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.caCertPath" name="caCertPath"/> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.tls-path-private-key' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath"/> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.tls-path-client-certificate' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.certPath" name="certPath"/> |
|||
</md-input-container> |
|||
</div> |
|||
<md-checkbox ng-model="vm.configurations.remoteConfiguration" |
|||
name="remoteConfiguration" |
|||
ng-click="vm.setSaveTypeConfig({item: vm.configurations.remoteConfiguration})" |
|||
aria-label="{{ 'gateway.remote-tip' | translate }}"> |
|||
{{ 'gateway.remote' | translate }} |
|||
<md-tooltip md-direction="right">{{'gateway.remote-tip' | translate }}</md-tooltip> |
|||
</md-checkbox> |
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block md-select-container" flex> |
|||
<label>{{'gateway.remote-logging-level' | translate }}</label> |
|||
<md-select name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> |
|||
<md-option ng-repeat="loggingLevel in vm.types.gatewayLogLevel" |
|||
ng-value="loggingLevel" ng-selected="$index === 5"> |
|||
{{loggingLevel}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.remote-logging-path-logs' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" |
|||
name="remoteLoggingPathToLogs" required> |
|||
<div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
<md-expansion-panel md-component-id="storagePanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="$mdExpansionPanel('storagePanelId').collapse()"> |
|||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-type' | translate }}</label> |
|||
<md-select required ng-model="vm.configurations.storageType"> |
|||
<md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> |
|||
{{storageType.name}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
|
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-read-time' | translate }}</label> |
|||
<input type="number" min="1" name="readRecordsCount" |
|||
ng-model='vm.configurations.readRecordsCount' required/> |
|||
<div ng-messages="gatewayConfiguration.readRecordsCount.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
|
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-max-time' | translate }}</label> |
|||
<input type="number" min="1" name="maxRecordsCount" |
|||
ng-model='vm.configurations.maxRecordsCount' required/> |
|||
<div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
|
|||
<div layout="row" class="gateway-form-row" |
|||
ng-if="vm.configurations.storageType == 'fileStorage'" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-max-files' | translate }}</label> |
|||
<input type="number" min="1" name="maxFilesCount" ng-model='vm.configurations.maxFilesCount' |
|||
required/> |
|||
<div ng-messages="gatewayConfiguration.maxFilesCount.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
|
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-data-path' | translate }}</label> |
|||
<input type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' |
|||
required/> |
|||
<div ng-messages="gatewayConfiguration.dataFolderPath.$error"> |
|||
<div ng-message="required" translate>extension.field-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
<md-expansion-panel md-component-id="connectorsPanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="$mdExpansionPanel('connectorsPanelId').collapse()"> |
|||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<tb-gateway-config |
|||
gateway-config="vm.configurations.connectors" |
|||
change-alignment="vm.changeAlignment"> |
|||
</tb-gateway-config> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
</md-expansion-panel-group> |
|||
<section layout="row" layout-align="end center" class="form-action-buttons"> |
|||
<md-button class="md-primary md-raised" |
|||
ng-click="vm.exportConfig()" |
|||
ng-if="!vm.configurations.remoteConfiguration" |
|||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|||
aria-label="{{ 'gateway.download-tip' | translate }}"> |
|||
{{'action.download' | translate }} |
|||
<md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> |
|||
</md-button> |
|||
|
|||
<md-button class="md-primary md-raised" |
|||
ng-click="vm.saveAttributeConfig()" |
|||
ng-if="vm.configurations.remoteConfiguration" |
|||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|||
aria-label="{{ 'gateway.save-tip' | translate }}"> |
|||
{{'action.save' | translate }} |
|||
<md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }}</md-tooltip> |
|||
</md-button> |
|||
</section> |
|||
</form> |
|||
@ -0,0 +1,170 @@ |
|||
/* |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import './gateway-config.scss'; |
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import gatewayConfigTemplate from './gateway-config.tpl.html'; |
|||
import gatewayConfigDialogTemplate from './gateway-config-dialog.tpl.html'; |
|||
import beautify from "js-beautify"; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
const js_beautify = beautify.js; |
|||
|
|||
export default angular.module('thingsboard.directives.gatewayConfig', []) |
|||
.directive('tbGatewayConfig', GatewayConfig) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayConfig() { |
|||
return { |
|||
restrict: "E", |
|||
scope: true, |
|||
bindToController: { |
|||
disabled: '=ngDisabled', |
|||
gatewayConfig: '=', |
|||
changeAlignment: '=', |
|||
theForm: '=' |
|||
}, |
|||
controller: GatewayConfigController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayConfigTemplate |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayConfigController($scope, $document, $mdDialog, $mdUtil, $window, types) { |
|||
let vm = this; |
|||
vm.types = types; |
|||
|
|||
vm.removeConnector = (index) => { |
|||
if (index > -1) { |
|||
vm.gatewayConfig.splice(index, 1); |
|||
} |
|||
}; |
|||
|
|||
vm.addNewConnector = () => { |
|||
vm.gatewayConfig.push({ |
|||
enabled: false, |
|||
configType: '', |
|||
config: {}, |
|||
name: '' |
|||
}); |
|||
}; |
|||
|
|||
vm.openConfigDialog = ($event, index, config, typeName) => { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
$mdDialog.show({ |
|||
controller: GatewayDialogController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayConfigDialogTemplate, |
|||
parent: angular.element($document[0].body), |
|||
locals: { |
|||
config: config, |
|||
typeName: typeName |
|||
}, |
|||
targetEvent: $event, |
|||
fullscreen: true, |
|||
multiple: true, |
|||
}).then(function (config) { |
|||
if (config && index > -1) { |
|||
vm.gatewayConfig[index].config = config; |
|||
} |
|||
}); |
|||
|
|||
}; |
|||
|
|||
vm.changeConnectorType = (connector) => { |
|||
for (let gatewayConfigTypeKey in types.gatewayConfigType) { |
|||
if (types.gatewayConfigType[gatewayConfigTypeKey].value === connector.configType) { |
|||
if (!connector.name) { |
|||
connector.name = generateConnectorName(types.gatewayConfigType[gatewayConfigTypeKey].name, 0); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.changeConnectorName = (connector, currentConnectorIndex) => { |
|||
connector.name = validateConnectorName(connector.name, 0, currentConnectorIndex); |
|||
}; |
|||
|
|||
function generateConnectorName(name, index) { |
|||
let newKeyName = index ? name + index : name; |
|||
let indexRes = vm.gatewayConfig.findIndex((element) => element.name === newKeyName); |
|||
return indexRes === -1 ? newKeyName : generateConnectorName(name, ++index); |
|||
} |
|||
|
|||
function validateConnectorName(name, index, currentConnectorIndex) { |
|||
for (let i = 0; i < vm.gatewayConfig.length; i++) { |
|||
let nameEq = (index === 0) ? name : name + index; |
|||
if (i !== currentConnectorIndex && vm.gatewayConfig[i].name === nameEq) { |
|||
index++; |
|||
validateConnectorName(name, index, currentConnectorIndex); |
|||
} |
|||
} |
|||
return (index === 0) ? name : name + index; |
|||
} |
|||
|
|||
vm.validateJSON = (config) => { |
|||
return angular.equals({}, config); |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayDialogController($scope, $mdDialog, $document, $window, config, typeName) { |
|||
let vm = this; |
|||
vm.config = js_beautify(angular.toJson(config), {indent_size: 4}); |
|||
vm.typeName = typeName; |
|||
vm.configAreaOptions = { |
|||
useWrapMode: true, |
|||
mode: 'json', |
|||
advanced: { |
|||
enableSnippets: true, |
|||
enableBasicAutocompletion: true, |
|||
enableLiveAutocompletion: true |
|||
}, |
|||
onLoad: function (_ace) { |
|||
_ace.$blockScrolling = 1; |
|||
} |
|||
}; |
|||
|
|||
vm.validateConfig = (model, editorName) => { |
|||
if (model && model.length) { |
|||
try { |
|||
angular.fromJson(model); |
|||
$scope.theForm[editorName].$setValidity('config', true); |
|||
} catch (e) { |
|||
$scope.theForm[editorName].$setValidity('config', false); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
vm.save = () => { |
|||
$mdDialog.hide(angular.fromJson(vm.config)); |
|||
}; |
|||
|
|||
vm.cancel = () => { |
|||
$mdDialog.hide(); |
|||
}; |
|||
|
|||
vm.beautifyJson = () => { |
|||
vm.config = js_beautify(vm.config, {indent_size: 4}); |
|||
}; |
|||
} |
|||
|
|||
@ -0,0 +1,81 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<section name="gatewayConfig" layout="column" class="gateway-config"> |
|||
<section layout="row" ng-form="gatewayConfig_{{$index}}" ng-repeat="connector in vm.gatewayConfig track by $index"> |
|||
<div layout="column" layout-align="center start" class="gateway-config-row"> |
|||
<md-switch ng-model="connector.enabled" ng-disabled="gatewayConfig_{{$index}}.$invalid || vm.validateJSON(connector.config)" |
|||
aria-label="{{ 'gateway.connector-enabled' | translate }}"> |
|||
</md-switch> |
|||
</div> |
|||
<div layout="row" flex class="gateway-config-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.connector-type' | translate }}</label> |
|||
<md-select name="connectorType" |
|||
ng-change="vm.changeConnectorType(connector)" |
|||
aria-label="{{ 'gateway.gateway.connector-type' | translate }}" |
|||
ng-model="connector.configType" required> |
|||
<md-option ng-repeat="configType in vm.types.gatewayConfigType" ng-value="configType.value"> |
|||
{{configType.value}} |
|||
</md-option> |
|||
</md-select> |
|||
<div ng-messages="vm.theForm.connectorType.$error"> |
|||
<div ng-message="required" translate>gateway.connector-type-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<input placeholder="{{'gateway.connector-name' | translate }}" |
|||
ng-model-options="{ updateOn: 'blur' }" |
|||
ng-change="vm.changeConnectorName(connector, $index)" name="connectorName" ng-model="connector.name" required/> |
|||
<div ng-messages="vm.theForm.connectorName.$error"> |
|||
<div ng-message="required" translate>gateway.connector-name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
<div layout="row" layout-align="end center" class="action-buttons" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-button class="md-icon-button md-mini" ng-click="vm.openConfigDialog($event, $index, connector.config, connector.name)" |
|||
aria-label="{{ 'gateway.update-config' | translate }}" |
|||
ng-class="{'md-warn': vm.validateJSON(connector.config)}"> |
|||
<md-icon class="material-icons">more_horiz</md-icon> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.update-config' | translate }} |
|||
</md-tooltip> |
|||
</md-button> |
|||
<md-button class="md-icon-button md-mini" ng-click="vm.removeConnector($index)" |
|||
aria-label="{{ 'gateway.delete' | translate }}"> |
|||
<md-icon class="material-icons">close</md-icon> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.delete' | translate }} |
|||
</md-tooltip> |
|||
</md-button> |
|||
</div> |
|||
</section> |
|||
<span ng-show="!vm.gatewayConfig.length" |
|||
layout-align="center center" ng-class="{'disabled': vm.disabled}" |
|||
class="no-data-found" translate>{{'gateway.no-connectors'}}</span> |
|||
<div> |
|||
<md-button class="md-raised" ng-click="vm.addNewConnector()" |
|||
aria-label="{{ 'gateway.connector-add' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'gateway.connector-add' | translate }} |
|||
</md-tooltip> |
|||
<span translate>action.add</span> |
|||
</md-button> |
|||
</div> |
|||
</section > |
|||
@ -0,0 +1,467 @@ |
|||
/* |
|||
* Copyright © 2016-2020 The Thingsboard Authors |
|||
* |
|||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|||
* you may not use this file except in compliance with the License. |
|||
* You may obtain a copy of the License at |
|||
* |
|||
* http://www.apache.org/licenses/LICENSE-2.0
|
|||
* |
|||
* Unless required by applicable law or agreed to in writing, software |
|||
* distributed under the License is distributed on an "AS IS" BASIS, |
|||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
* See the License for the specific language governing permissions and |
|||
* limitations under the License. |
|||
*/ |
|||
import './gateway-form.scss'; |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import gatewayFormTemplate from './gateway-form.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
export default angular.module('thingsboard.directives.gatewayForm', []) |
|||
.directive('tbGatewayForm', GatewayForm) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayForm() { |
|||
return { |
|||
restrict: "E", |
|||
scope: true, |
|||
bindToController: { |
|||
formId: '=', |
|||
ctx: '=' |
|||
}, |
|||
controller: GatewayFormController, |
|||
controllerAs: 'vm', |
|||
templateUrl: gatewayFormTemplate |
|||
}; |
|||
} |
|||
|
|||
/*@ngInject*/ |
|||
function GatewayFormController($scope, $injector, $document, $mdExpansionPanel, toast, importExport, attributeService, deviceService, userService, $mdDialog, $mdUtil, types, $window, $q, entityService, utils, $translate) { |
|||
let vm = this; |
|||
const currentConfigurationAttribute = "current_configuration"; |
|||
const configurationDraftsAttribute = "configuration_drafts"; |
|||
const configurationAttribute = "configuration"; |
|||
const remoteLoggingLevelAttribute = "RemoteLoggingLevel"; |
|||
|
|||
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"'; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.configurations = { |
|||
gateway: '', |
|||
host: $document[0].domain, |
|||
port: 1883, |
|||
remoteConfiguration: true, |
|||
accessToken: '', |
|||
storageType: "memoryStorage", |
|||
readRecordsCount: 100, |
|||
maxRecordsCount: 10000, |
|||
dataFolderPath: './data/', |
|||
maxFilesCount: 5, |
|||
securityType: "accessToken", |
|||
caCertPath: '/etc/thingsboard-gateway/ca.pem', |
|||
privateKeyPath: '/etc/thingsboard-gateway/privateKey.pem', |
|||
certPath: '/etc/thingsboard-gateway/certificate.pem', |
|||
connectors: [], |
|||
remoteLoggingLevel: "DEBUG", |
|||
remoteLoggingPathToLogs: './logs/' |
|||
}; |
|||
|
|||
let archiveFileName = ''; |
|||
let gatewayNameExists = ''; |
|||
let successfulSaved = ''; |
|||
|
|||
vm.securityTypes = [{ |
|||
name: 'gateway.security-types.access-token', |
|||
value: 'accessToken' |
|||
}, { |
|||
name: 'gateway.security-types.tls', |
|||
value: 'tls' |
|||
}]; |
|||
|
|||
vm.storageTypes = [{ |
|||
name: 'gateway.storage-types.memory-storage', |
|||
value: 'memoryStorage' |
|||
}, { |
|||
name: 'gateway.storage-types.file-storage', |
|||
value: 'fileStorage' |
|||
}]; |
|||
|
|||
$scope.$watch('vm.ctx', function () { |
|||
if (vm.ctx ) { |
|||
vm.settings = vm.ctx.settings; |
|||
vm.widgetConfig = vm.ctx.widgetConfig; |
|||
initializeConfig(); |
|||
} |
|||
}); |
|||
|
|||
$scope.$on('gateway-form-resize', function (event, formId) { |
|||
if (vm.formId == formId) { |
|||
updateWidgetDisplaying(); |
|||
} |
|||
}); |
|||
|
|||
function updateWidgetDisplaying() { |
|||
vm.changeAlignment = (vm.ctx.$container[0].offsetWidth <= 425); |
|||
} |
|||
|
|||
function initWidgetSettings() { |
|||
let widgetTitle; |
|||
if (vm.settings.widgetTitle && vm.settings.widgetTitle.length) { |
|||
widgetTitle = utils.customTranslation(vm.settings.widgetTitle, vm.settings.widgetTitle); |
|||
} else { |
|||
widgetTitle = $translate.instant('gateway.gateway'); |
|||
} |
|||
vm.ctx.widgetTitle = widgetTitle; |
|||
|
|||
archiveFileName = vm.settings.archiveFileName && vm.settings.archiveFileName.length ? vm.settings.archiveFileName : 'gatewayConfiguration'; |
|||
gatewayNameExists = utils.customTranslation(vm.settings.deviceNameExist, vm.settings.deviceNameExist) || $translate.instant('gateway.gateway-exists'); |
|||
successfulSaved = utils.customTranslation(vm.settings.successfulSave, vm.settings.successfulSave) || $translate.instant('gateway.gateway-saved'); |
|||
} |
|||
|
|||
function initializeConfig() { |
|||
updateWidgetDisplaying(); |
|||
initWidgetSettings(); |
|||
getGatewaysList(true); |
|||
} |
|||
|
|||
vm.getAccessToken = (deviceId) => { |
|||
if (deviceId.id) { |
|||
getDeviceCredentials(deviceId.id); |
|||
} |
|||
}; |
|||
|
|||
vm.collapsePanel = function (panelId) { |
|||
$mdExpansionPanel(panelId).collapse(); |
|||
}; |
|||
|
|||
function getDeviceCredentials(deviceId) { |
|||
return deviceService.getDeviceCredentials(deviceId).then( |
|||
(deviceCredentials) => { |
|||
vm.configurations.accessToken = deviceCredentials.credentialsId; |
|||
getAttributes(); |
|||
} |
|||
); |
|||
} |
|||
|
|||
vm.createDevice = (deviceObj) => { |
|||
deviceService.findByName(deviceObj.name, {ignoreErrors: true}) |
|||
.then( |
|||
function () { |
|||
toast.showError(gatewayNameExists, angular.element('.gateway-form'),'top left'); |
|||
}, |
|||
function () { |
|||
if(vm.settings.gatewayType && vm.settings.gatewayType.length){ |
|||
deviceObj.type = vm.settings.gatewayType; |
|||
} |
|||
deviceService.saveDevice(deviceObj).then( |
|||
(device) => { |
|||
getDeviceCredentials(device.id.id).then(() =>{ |
|||
getGatewaysList(); |
|||
}); |
|||
} |
|||
); |
|||
}); |
|||
}; |
|||
|
|||
vm.saveAttributeConfig = () => { |
|||
$q.all([ |
|||
saveAttribute(configurationAttribute, $window.btoa(angular.toJson(getGatewayConfigJSON())), types.attributesScope.shared.value), |
|||
saveAttribute(configurationDraftsAttribute, $window.btoa(angular.toJson(getDraftConnectorJSON())), types.attributesScope.server.value), |
|||
saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value) |
|||
]).then(() =>{ |
|||
toast.showSuccess(successfulSaved, 2000, angular.element('.gateway-form'),'top left'); |
|||
}) |
|||
}; |
|||
|
|||
function getAttributes() { |
|||
let promises = []; |
|||
promises.push(getAttribute(currentConfigurationAttribute, types.attributesScope.client.value)); |
|||
promises.push(getAttribute(configurationDraftsAttribute, types.attributesScope.server.value)); |
|||
promises.push(getAttribute(remoteLoggingLevelAttribute, types.attributesScope.shared.value)); |
|||
$q.all(promises).then((response) => { |
|||
processCurrentConfiguration(response[0]); |
|||
processConfigurationDrafts(response[1]); |
|||
processLoggingLevel(response[2]); |
|||
}); |
|||
} |
|||
|
|||
function getAttribute(attributeName, attributeScope) { |
|||
return attributeService.getEntityAttributesValues(vm.configurations.gateway.id.entityType, vm.configurations.gateway.id.id, attributeScope, attributeName); |
|||
} |
|||
|
|||
function saveAttribute(attributeName, attributeValue, attributeScope) { |
|||
let attributes = [{ |
|||
key: attributeName, |
|||
value: attributeValue |
|||
}]; |
|||
return attributeService.saveEntityAttributes(vm.configurations.gateway.id.entityType, vm.configurations.gateway.id.id, attributeScope, attributes); |
|||
} |
|||
|
|||
vm.exportConfig = () => { |
|||
let filesZip = {}; |
|||
filesZip["tb_gateway.yaml"] = generateYAMLConfigurationFile(); |
|||
generateConfigConnectorFiles(filesZip); |
|||
generateLogConfigFile(filesZip); |
|||
importExport.exportJSZip(filesZip, archiveFileName); |
|||
saveAttribute(remoteLoggingLevelAttribute, vm.configurations.remoteLoggingLevel.toUpperCase(), types.attributesScope.shared.value); |
|||
}; |
|||
|
|||
function generateYAMLConfigurationFile() { |
|||
let config; |
|||
config = 'thingsboard:\n'; |
|||
config += ' host: ' + vm.configurations.host + '\n'; |
|||
config += ' remoteConfiguration: ' + vm.configurations.remoteConfiguration + '\n'; |
|||
config += ' port: ' + vm.configurations.port + '\n'; |
|||
config += ' security:\n'; |
|||
if (vm.configurations.securityType === 'accessToken') { |
|||
config += ' access-token: ' + vm.configurations.accessToken + '\n'; |
|||
} else if (vm.configurations.securityType === 'tls') { |
|||
config += ' ca_cert: ' + vm.configurations.caCertPath + '\n'; |
|||
config += ' privateKey: ' + vm.configurations.privateKeyPath + '\n'; |
|||
config += ' cert: ' + vm.configurations.certPath + '\n'; |
|||
} |
|||
config += 'storage:\n'; |
|||
if (vm.configurations.storageType === 'memoryStorage') { |
|||
config += ' type: memory\n'; |
|||
config += ' read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|||
config += ' max_records_count: ' + vm.configurations.maxRecordsCount + '\n'; |
|||
} else if (vm.configurations.storageType === 'fileStorage') { |
|||
config += ' type: file\n'; |
|||
config += ' data_folder_path: ' + vm.configurations.dataFolderPath + '\n'; |
|||
config += ' max_file_count: ' + vm.configurations.maxFilesCount + '\n'; |
|||
config += ' max_read_records_count: ' + vm.configurations.readRecordsCount + '\n'; |
|||
config += ' max_records_per_file: ' + vm.configurations.maxRecordsCount + '\n'; |
|||
} |
|||
config += 'connectors:\n'; |
|||
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
|||
if (vm.configurations.connectors[i].enabled) { |
|||
config += ' -\n'; |
|||
config += ' name: ' + vm.configurations.connectors[i].name + '\n'; |
|||
config += ' type: ' + vm.configurations.connectors[i].configType + '\n'; |
|||
config += ' configuration: ' + generateFileName(vm.configurations.connectors[i].name) + '\n'; |
|||
} |
|||
} |
|||
return config; |
|||
} |
|||
|
|||
function generateConfigConnectorFiles(fileZipAdd) { |
|||
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
|||
if (vm.configurations.connectors[i].enabled) { |
|||
fileZipAdd[generateFileName(vm.configurations.connectors[i].name)] = angular.toJson(vm.configurations.connectors[i].config); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function generateLogConfigFile(fileZipAdd) { |
|||
fileZipAdd["logs.conf"] = getLogsConfig(); |
|||
} |
|||
|
|||
function getLogsConfig() { |
|||
return templateLogsConfig |
|||
.replace(/{ERROR}/g, vm.configurations.remoteLoggingLevel) |
|||
.replace(/{.\/logs\/}/g, vm.configurations.remoteLoggingPathToLogs); |
|||
} |
|||
|
|||
function getGatewayConfigJSON() { |
|||
let gatewayConfig = {}; |
|||
gatewayConfig["thingsboard"] = gatewayMainConfigJSON(); |
|||
gatewayConnectorConfigJSON(gatewayConfig); |
|||
return gatewayConfig; |
|||
} |
|||
|
|||
function gatewayMainConfigJSON() { |
|||
let configuration = {}; |
|||
|
|||
let thingsBoard = {}; |
|||
thingsBoard.host = vm.configurations.host; |
|||
thingsBoard.remoteConfiguration = vm.configurations.remoteConfiguration; |
|||
thingsBoard.port = vm.configurations.port; |
|||
let security = {}; |
|||
if (vm.configurations.securityType === 'accessToken') { |
|||
security.accessToken = (vm.configurations.accessToken) ? vm.configurations.accessToken : "" |
|||
} else { |
|||
security.caCert = vm.configurations.caCertPath; |
|||
security.privateKey = vm.configurations.privateKeyPath; |
|||
security.cert = vm.configurations.certPath; |
|||
} |
|||
thingsBoard.security = security; |
|||
configuration.thingsboard = thingsBoard; |
|||
|
|||
let storage = {}; |
|||
if (vm.configurations.storageType === 'memoryStorage') { |
|||
storage.type = "memory"; |
|||
storage.read_records_count = vm.configurations.readRecordsCount; |
|||
storage.max_records_count = vm.configurations.maxRecordsCount; |
|||
} else if (vm.configurations.storageType === 'fileStorage') { |
|||
storage.type = "file"; |
|||
storage.data_folder_path = vm.configurations.dataFolderPath; |
|||
storage.max_file_count = vm.configurations.maxFilesCount; |
|||
storage.max_read_records_count = vm.configurations.readRecordsCount; |
|||
storage.max_records_per_file = vm.configurations.maxRecordsCount; |
|||
} |
|||
configuration.storage = storage; |
|||
|
|||
let connectors = []; |
|||
for (let i = 0; i < vm.configurations.connectors.length; i++) { |
|||
if (vm.configurations.connectors[i].enabled) { |
|||
let connector = { |
|||
configuration: generateFileName(vm.configurations.connectors[i].name), |
|||
name: vm.configurations.connectors[i].name, |
|||
type: vm.configurations.connectors[i].configType |
|||
}; |
|||
connectors.push(connector); |
|||
} |
|||
} |
|||
configuration.connectors = connectors; |
|||
|
|||
configuration.logs = $window.btoa(getLogsConfig()); |
|||
|
|||
return configuration; |
|||
} |
|||
|
|||
function gatewayConnectorConfigJSON(gatewayConfiguration) { |
|||
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
|||
if (vm.configurations.connectors[i].enabled) { |
|||
let typeConnector = vm.configurations.connectors[i].configType; |
|||
if(!angular.isArray(gatewayConfiguration[typeConnector])){ |
|||
gatewayConfiguration[typeConnector] = []; |
|||
} |
|||
|
|||
let connectorConfig = { |
|||
name: vm.configurations.connectors[i].name, |
|||
config: vm.configurations.connectors[i].config |
|||
}; |
|||
gatewayConfiguration[typeConnector].push(connectorConfig); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function getDraftConnectorJSON() { |
|||
let draftConnector = {}; |
|||
for(let i = 0; i < vm.configurations.connectors.length; i++){ |
|||
if (!vm.configurations.connectors[i].enabled) { |
|||
let connector = { |
|||
connector: vm.configurations.connectors[i].configType, |
|||
config: vm.configurations.connectors[i].config |
|||
}; |
|||
draftConnector[vm.configurations.connectors[i].name] = connector; |
|||
} |
|||
} |
|||
return draftConnector; |
|||
} |
|||
|
|||
function getGatewaysList(firstInit) { |
|||
vm.gateways = []; |
|||
entityService.getEntitiesByNameFilter(types.entityType.device, "", -1).then((devices) => { |
|||
for (let i = 0; i < devices.length; i++) { |
|||
const device = devices[i]; |
|||
if (device.additionalInfo !== null && device.additionalInfo.gateway === true) { |
|||
vm.gateways.push(device); |
|||
if (firstInit && vm.gateways.length && device.name === vm.gateways[0].name) { |
|||
vm.configurations.gateway = device; |
|||
vm.getAccessToken(device.id); |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
function processCurrentConfiguration(response) { |
|||
if (response.length > 0) { |
|||
vm.configurations.connectors = []; |
|||
let attribute = angular.fromJson($window.atob(response[0].value)); |
|||
for (var attributeKey in attribute) { |
|||
let keyValue = attribute[attributeKey]; |
|||
if (attributeKey === "thingsboard") { |
|||
if (keyValue !== null && Object.keys(keyValue).length > 0) { |
|||
setConfigGateway(keyValue); |
|||
} |
|||
} else { |
|||
for (let connectorType in keyValue) { |
|||
let name = "No name"; |
|||
if (Object.prototype.hasOwnProperty.call(keyValue[connectorType], 'name')) { |
|||
name = keyValue[connectorType].name ; |
|||
} |
|||
let connector = { |
|||
enabled: true, |
|||
configType: attributeKey, |
|||
config: keyValue[connectorType].config, |
|||
name: name |
|||
}; |
|||
vm.configurations.connectors.push(connector); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function processConfigurationDrafts(response) { |
|||
if (response.length > 0) { |
|||
let attribute = angular.fromJson($window.atob(response[0].value)); |
|||
for (let key in attribute) { |
|||
let connector = { |
|||
enabled: false, |
|||
configType: attribute[key].connector, |
|||
config: attribute[key].config, |
|||
name: key |
|||
}; |
|||
vm.configurations.connectors.push(connector); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function processLoggingLevel(response) { |
|||
if (response.length > 0) { |
|||
if (vm.types.gatewayLogLevel[response[0].value.toLowerCase()]) { |
|||
vm.configurations.remoteLoggingLevel = response[0].value.toUpperCase(); |
|||
} |
|||
} else { |
|||
vm.configurations.remoteLoggingLevel = vm.types.gatewayLogLevel.debug; |
|||
} |
|||
} |
|||
|
|||
function setConfigGateway(keyValue) { |
|||
if (Object.prototype.hasOwnProperty.call(keyValue, 'thingsboard')) { |
|||
vm.configurations.host = keyValue.thingsboard.host; |
|||
vm.configurations.port = keyValue.thingsboard.port; |
|||
vm.configurations.remoteConfiguration = keyValue.thingsboard.remoteConfiguration; |
|||
if (Object.prototype.hasOwnProperty.call(keyValue.thingsboard.security, 'accessToken')) { |
|||
vm.configurations.securityType = 'accessToken'; |
|||
vm.configurations.accessToken = keyValue.thingsboard.security.accessToken; |
|||
} else { |
|||
vm.configurations.securityType = 'tls'; |
|||
vm.configurations.caCertPath = keyValue.thingsboard.security.caCert; |
|||
vm.configurations.privateKeyPath = keyValue.thingsboard.security.private_key; |
|||
vm.configurations.certPath = keyValue.thingsboard.security.cert; |
|||
} |
|||
} |
|||
|
|||
if (Object.prototype.hasOwnProperty.call(keyValue, 'storage') && Object.prototype.hasOwnProperty.call(keyValue.storage, 'type')) { |
|||
if (keyValue.storage.type === 'memory') { |
|||
vm.configurations.storageType = 'memoryStorage'; |
|||
vm.configurations.readRecordsCount = keyValue.storage.read_records_count; |
|||
vm.configurations.maxRecordsCount = keyValue.storage.max_records_count; |
|||
} else if (keyValue.storage.type === 'file') { |
|||
vm.configurations.storageType = 'fileStorage'; |
|||
vm.configurations.dataFolderPath = keyValue.storage.data_folder_path; |
|||
vm.configurations.maxFilesCount = keyValue.storage.max_file_count; |
|||
vm.configurations.readRecordsCount = keyValue.storage.read_records_count; |
|||
vm.configurations.maxRecordsCount = keyValue.storage.max_records_count; |
|||
} |
|||
} |
|||
} |
|||
|
|||
function generateFileName(fileName) { |
|||
return fileName.replace("_", "") |
|||
.replace("-", "") |
|||
.replace(/^\s+|\s+/g, '') |
|||
.toLowerCase() + '.json'; |
|||
} |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,227 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2020 The Thingsboard Authors |
|||
|
|||
Licensed under the Apache License, Version 2.0 (the "License"); |
|||
you may not use this file except in compliance with the License. |
|||
You may obtain a copy of the License at |
|||
|
|||
http://www.apache.org/licenses/LICENSE-2.0 |
|||
|
|||
Unless required by applicable law or agreed to in writing, software |
|||
distributed under the License is distributed on an "AS IS" BASIS, |
|||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
See the License for the specific language governing permissions and |
|||
limitations under the License. |
|||
|
|||
--> |
|||
<md-content md-scroll-y layout="column" class="gateway-form"> |
|||
<form name="gatewayConfiguration"> |
|||
<md-expansion-panel-group> |
|||
<md-expansion-panel md-component-id="thingsboardPanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="vm.collapsePanel('thingsboardPanelId')"> |
|||
<div class="tb-panel-title">{{ 'gateway.thingsboard' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<tb-gateway-config-select tb-required="true" |
|||
ng-model="vm.configurations.gateway" |
|||
the-form="gatewayConfiguration" |
|||
gateway-list="vm.gateways" |
|||
get_access_token="vm.getAccessToken" |
|||
create-device="vm.createDevice"> |
|||
</tb-gateway-config-select> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.security-type' | translate }}</label> |
|||
<md-select name="securityType" ng-model="vm.configurations.securityType" required> |
|||
<md-option ng-repeat="securityType in vm.securityTypes" ng-value="securityType.value"> |
|||
{{securityType.name | translate}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{ 'gateway.thingsboard-host' | translate }}</label> |
|||
<input type="text" name="host" ng-model="vm.configurations.host" required> |
|||
<div ng-messages="gatewayConfiguration.host.$error"> |
|||
<div ng-message="required" translate>gateway.thingsboard-host-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{ 'gateway.thingsboard-port' | translate }}</label> |
|||
<input type="number" min="1" max="65535" ng-pattern="/^-?[0-9]+$/" name="port" |
|||
ng-model="vm.configurations.port" required> |
|||
<div ng-messages="gatewayConfiguration.port.$error"> |
|||
<div ng-message="required" translate>gateway.thingsboard-port-required</div> |
|||
<div ng-message="max" translate>gateway.thingsboard-port-max</div> |
|||
<div ng-message="min" translate>gateway.thingsboard-port-min</div> |
|||
<div ng-message="pattern" translate>gateway.thingsboard-port-pattern</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
<div ng-if="vm.configurations.securityType=='tls'"> |
|||
<md-input-container class="md-block security-type"> |
|||
<label>{{'gateway.tls-path-ca-certificate' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.caCertPath" name="caCertPath" /> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.tls-path-private-key' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.privateKeyPath" name="privateKeyPath" /> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label>{{'gateway.tls-path-client-certificate' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.certPath" name="certPath" /> |
|||
</md-input-container> |
|||
</div> |
|||
<md-checkbox ng-model="vm.configurations.remoteConfiguration" |
|||
name="remoteConfiguration" |
|||
aria-label="{{ 'gateway.remote-remote' | translate }}"> |
|||
{{ 'gateway.remote' | translate }} |
|||
</md-checkbox> |
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block md-select-container" flex> |
|||
<label>{{'gateway.remote-logging-level' | translate }}</label> |
|||
<md-select name="loggingLevel" ng-model="vm.configurations.remoteLoggingLevel"> |
|||
<md-option ng-repeat="logLevel in vm.types.gatewayLogLevel" |
|||
ng-value="logLevel" ng-selected="$index === 5"> |
|||
{{logLevel}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.path-logs' | translate }}</label> |
|||
<input type="text" ng-model="vm.configurations.remoteLoggingPathToLogs" |
|||
name="remoteLoggingPathToLogs" required> |
|||
<div ng-messages="gatewayConfiguration.remoteLoggingPathToLogs.$error"> |
|||
<div ng-message="required" translate>gateway.path-logs-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
<md-expansion-panel md-component-id="storagePanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="vm.collapsePanel('storagePanelId')"> |
|||
<div class="tb-panel-title">{{ 'gateway.storage' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-type' | translate }}</label> |
|||
<md-select required ng-model="vm.configurations.storageType"> |
|||
<md-option ng-repeat="storageType in vm.storageTypes" ng-value="storageType.value"> |
|||
{{storageType.name | translate}} |
|||
</md-option> |
|||
</md-select> |
|||
</md-input-container> |
|||
|
|||
<div layout="row" class="gateway-form-row" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-pack-size' | translate }}</label> |
|||
<input type="number" min="1" name="readRecordsCount" ng-pattern="/^-?[0-9]+$/" |
|||
ng-model='vm.configurations.readRecordsCount' required/> |
|||
<div ng-messages="gatewayConfiguration.readRecordsCount.$error"> |
|||
<div ng-message="required" translate>gateway.storage-pack-size-required</div> |
|||
<div ng-message="min" translate>gateway.storage-pack-size-min</div> |
|||
<div ng-message="pattern" translate>gateway.storage-pack-size-pattern</div> |
|||
</div> |
|||
</md-input-container> |
|||
|
|||
<md-input-container class="md-block" flex> |
|||
<label translate>{{ vm.configurations.storageType !== 'fileStorage' ? 'gateway.storage-max-records' : 'gateway.storage-max-file-records' }}</label> |
|||
<input type="number" min="1" name="maxRecordsCount" ng-pattern="/^-?[0-9]+$/" |
|||
ng-model='vm.configurations.maxRecordsCount' required/> |
|||
<div ng-messages="gatewayConfiguration.maxRecordsCount.$error"> |
|||
<div ng-message="required" translate>gateway.storage-max-records-required</div> |
|||
<div ng-message="min" translate>gateway.storage-max-records-min</div> |
|||
<div ng-message="pattern" translate>gateway.storage-max-records-pattern</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
|
|||
<div layout="row" class="gateway-form-row" |
|||
ng-if="vm.configurations.storageType == 'fileStorage'" |
|||
ng-class="{'gateway-config-row-vertical': vm.changeAlignment}"> |
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-max-files' | translate }}</label> |
|||
<input type="number" min="1" name="maxFilesCount" ng-pattern="/^-?[0-9]+$/" |
|||
ng-model='vm.configurations.maxFilesCount' required/> |
|||
<div ng-messages="gatewayConfiguration.maxFilesCount.$error"> |
|||
<div ng-message="required" translate>gateway.storage-max-files-required</div> |
|||
<div ng-message="min" translate>gateway.storage-max-files-min</div> |
|||
<div ng-message="pattern" translate>gateway.storage-max-files-pattern</div> |
|||
</div> |
|||
</md-input-container> |
|||
|
|||
<md-input-container class="md-block" flex> |
|||
<label>{{'gateway.storage-path' | translate }}</label> |
|||
<input type="text" name="dataFolderPath" ng-model='vm.configurations.dataFolderPath' |
|||
required/> |
|||
<div ng-messages="gatewayConfiguration.dataFolderPath.$error"> |
|||
<div ng-message="required" translate>gateway.storage-path-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</div> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
<md-expansion-panel md-component-id="connectorsPanelId"> |
|||
<md-expansion-panel-collapsed> |
|||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-collapsed> |
|||
<md-expansion-panel-expanded> |
|||
<md-expansion-panel-header ng-click="vm.collapsePanel('connectorsPanelId')"> |
|||
<div class="tb-panel-title">{{ 'gateway.connectors' | translate | uppercase }}</div> |
|||
<span flex></span> |
|||
<md-expansion-panel-icon></md-expansion-panel-icon> |
|||
</md-expansion-panel-header> |
|||
<md-expansion-panel-content> |
|||
<tb-gateway-config |
|||
gateway-config="vm.configurations.connectors" |
|||
the-form="gatewayConfiguration" |
|||
change-alignment="vm.changeAlignment"> |
|||
</tb-gateway-config> |
|||
</md-expansion-panel-content> |
|||
</md-expansion-panel-expanded> |
|||
</md-expansion-panel> |
|||
</md-expansion-panel-group> |
|||
<section layout="row" layout-align="end center" class="form-action-buttons"> |
|||
<md-button class="md-primary md-raised" |
|||
ng-click="vm.exportConfig()" |
|||
ng-if="!vm.configurations.remoteConfiguration" |
|||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|||
aria-label="{{ 'gateway.download-tip' | translate }}"> |
|||
{{'action.download' | translate }} |
|||
<md-tooltip>{{'gateway.download-tip' | translate }}</md-tooltip> |
|||
</md-button> |
|||
|
|||
<md-button class="md-primary md-raised" |
|||
ng-click="vm.saveAttributeConfig()" |
|||
ng-if="vm.configurations.remoteConfiguration" |
|||
ng-disabled="gatewayConfiguration.$invalid || !gatewayConfiguration.$dirty" |
|||
aria-label="{{ 'gateway.save-tip' | translate }}"> |
|||
{{'action.save' | translate }} |
|||
<md-tooltip ng-if="vm.configurations.remoteConfiguration">{{'gateway.save-tip' | translate }}</md-tooltip> |
|||
</md-button> |
|||
</section> |
|||
</form> |
|||
</md-content> |
|||
Loading…
Reference in new issue