36 changed files with 7 additions and 2805 deletions
@ -1,218 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
export default angular.module('thingsboard.api.plugin', []) |
|||
.factory('pluginService', PluginService).name; |
|||
|
|||
/*@ngInject*/ |
|||
function PluginService($http, $q, $rootScope, $filter, componentDescriptorService, types, utils) { |
|||
|
|||
var allPlugins = undefined; |
|||
var allActionPlugins = undefined; |
|||
var systemPlugins = undefined; |
|||
var tenantPlugins = undefined; |
|||
|
|||
$rootScope.pluginServiceStateChangeStartHandle = $rootScope.$on('$stateChangeStart', function () { |
|||
invalidatePluginsCache(); |
|||
}); |
|||
|
|||
var service = { |
|||
getSystemPlugins: getSystemPlugins, |
|||
getTenantPlugins: getTenantPlugins, |
|||
getAllPlugins: getAllPlugins, |
|||
getAllActionPlugins: getAllActionPlugins, |
|||
getPluginByToken: getPluginByToken, |
|||
getPlugin: getPlugin, |
|||
deletePlugin: deletePlugin, |
|||
savePlugin: savePlugin, |
|||
activatePlugin: activatePlugin, |
|||
suspendPlugin: suspendPlugin |
|||
} |
|||
|
|||
return service; |
|||
|
|||
function invalidatePluginsCache() { |
|||
allPlugins = undefined; |
|||
allActionPlugins = undefined; |
|||
systemPlugins = undefined; |
|||
tenantPlugins = undefined; |
|||
} |
|||
|
|||
function loadPluginsCache(config) { |
|||
var deferred = $q.defer(); |
|||
if (!allPlugins) { |
|||
var url = '/api/plugins'; |
|||
$http.get(url, config).then(function success(response) { |
|||
componentDescriptorService.getComponentDescriptorsByType(types.componentType.plugin).then( |
|||
function success(pluginComponents) { |
|||
allPlugins = response.data; |
|||
allActionPlugins = []; |
|||
systemPlugins = []; |
|||
tenantPlugins = []; |
|||
allPlugins = $filter('orderBy')(allPlugins, ['+name', '-createdTime']); |
|||
var pluginHasActionsByClazz = {}; |
|||
for (var index in pluginComponents) { |
|||
pluginHasActionsByClazz[pluginComponents[index].clazz] = |
|||
(pluginComponents[index].actions != null && pluginComponents[index].actions.length > 0); |
|||
} |
|||
for (var i = 0; i < allPlugins.length; i++) { |
|||
var plugin = allPlugins[i]; |
|||
if (pluginHasActionsByClazz[plugin.clazz] === true) { |
|||
allActionPlugins.push(plugin); |
|||
} |
|||
if (plugin.tenantId.id === types.id.nullUid) { |
|||
systemPlugins.push(plugin); |
|||
} else { |
|||
tenantPlugins.push(plugin); |
|||
} |
|||
} |
|||
deferred.resolve(); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
} else { |
|||
deferred.resolve(); |
|||
} |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getSystemPlugins(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
loadPluginsCache(config).then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(systemPlugins, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getTenantPlugins(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
loadPluginsCache(config).then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(tenantPlugins, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getAllActionPlugins(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
loadPluginsCache(config).then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(allActionPlugins, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getAllPlugins(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
loadPluginsCache(config).then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(allPlugins, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getPluginByToken(pluginToken) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin/token/' + pluginToken; |
|||
$http.get(url, null).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getPlugin(pluginId, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin/' + pluginId; |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function savePlugin(plugin) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin'; |
|||
$http.post(url, plugin).then(function success(response) { |
|||
invalidatePluginsCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function deletePlugin(pluginId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin/' + pluginId; |
|||
$http.delete(url).then(function success() { |
|||
invalidatePluginsCache(); |
|||
deferred.resolve(); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function activatePlugin(pluginId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin/' + pluginId + '/activate'; |
|||
$http.post(url, null).then(function success(response) { |
|||
invalidatePluginsCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function suspendPlugin(pluginId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/plugin/' + pluginId + '/suspend'; |
|||
$http.post(url, null).then(function success(response) { |
|||
invalidatePluginsCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
} |
|||
@ -1,186 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
export default angular.module('thingsboard.api.rule', []) |
|||
.factory('ruleService', RuleService).name; |
|||
|
|||
/*@ngInject*/ |
|||
function RuleService($http, $q, $rootScope, $filter, types, utils) { |
|||
|
|||
var allRules = undefined; |
|||
var systemRules = undefined; |
|||
var tenantRules = undefined; |
|||
|
|||
$rootScope.ruleServiceStateChangeStartHandle = $rootScope.$on('$stateChangeStart', function () { |
|||
invalidateRulesCache(); |
|||
}); |
|||
|
|||
var service = { |
|||
getSystemRules: getSystemRules, |
|||
getTenantRules: getTenantRules, |
|||
getAllRules: getAllRules, |
|||
getRulesByPluginToken: getRulesByPluginToken, |
|||
getRule: getRule, |
|||
deleteRule: deleteRule, |
|||
saveRule: saveRule, |
|||
activateRule: activateRule, |
|||
suspendRule: suspendRule |
|||
} |
|||
|
|||
return service; |
|||
|
|||
function invalidateRulesCache() { |
|||
allRules = undefined; |
|||
systemRules = undefined; |
|||
tenantRules = undefined; |
|||
} |
|||
|
|||
function loadRulesCache(config) { |
|||
var deferred = $q.defer(); |
|||
if (!allRules) { |
|||
var url = '/api/rules'; |
|||
$http.get(url, config).then(function success(response) { |
|||
allRules = response.data; |
|||
systemRules = []; |
|||
tenantRules = []; |
|||
allRules = $filter('orderBy')(allRules, ['+name', '-createdTime']); |
|||
for (var i = 0; i < allRules.length; i++) { |
|||
var rule = allRules[i]; |
|||
if (rule.tenantId.id === types.id.nullUid) { |
|||
systemRules.push(rule); |
|||
} else { |
|||
tenantRules.push(rule); |
|||
} |
|||
} |
|||
deferred.resolve(); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
} else { |
|||
deferred.resolve(); |
|||
} |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getSystemRules(pageLink) { |
|||
var deferred = $q.defer(); |
|||
loadRulesCache().then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(systemRules, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getTenantRules(pageLink) { |
|||
var deferred = $q.defer(); |
|||
loadRulesCache().then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(tenantRules, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getAllRules(pageLink, config) { |
|||
var deferred = $q.defer(); |
|||
loadRulesCache(config).then( |
|||
function success() { |
|||
utils.filterSearchTextEntities(allRules, 'name', pageLink, deferred); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getRulesByPluginToken(pluginToken) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule/token/' + pluginToken; |
|||
$http.get(url, null).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getRule(ruleId, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule/' + ruleId; |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function saveRule(rule) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule'; |
|||
$http.post(url, rule).then(function success(response) { |
|||
invalidateRulesCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function deleteRule(ruleId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule/' + ruleId; |
|||
$http.delete(url).then(function success() { |
|||
invalidateRulesCache(); |
|||
deferred.resolve(); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function activateRule(ruleId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule/' + ruleId + '/activate'; |
|||
$http.post(url, null).then(function success(response) { |
|||
invalidateRulesCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function suspendRule(ruleId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/rule/' + ruleId + '/suspend'; |
|||
$http.post(url, null).then(function success(response) { |
|||
invalidateRulesCache(); |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
} |
|||
@ -1,105 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/*@ngInject*/ |
|||
export default function ComponentDialogController($mdDialog, $q, $scope, componentDescriptorService, types, utils, helpLinks, isAdd, isReadOnly, componentInfo) { |
|||
|
|||
var vm = this; |
|||
|
|||
vm.isReadOnly = isReadOnly; |
|||
vm.isAdd = isAdd; |
|||
vm.componentInfo = componentInfo; |
|||
if (isAdd) { |
|||
vm.componentInfo.component = {}; |
|||
} |
|||
|
|||
vm.componentHasSchema = false; |
|||
vm.componentDescriptors = []; |
|||
|
|||
if (vm.componentInfo.component && !vm.componentInfo.component.configuration) { |
|||
vm.componentInfo.component.configuration = {}; |
|||
} |
|||
|
|||
vm.helpLinkIdForComponent = helpLinkIdForComponent; |
|||
vm.save = save; |
|||
vm.cancel = cancel; |
|||
|
|||
$scope.$watch("vm.componentInfo.component.clazz", function (newValue, prevValue) { |
|||
if (newValue != prevValue) { |
|||
if (newValue && prevValue) { |
|||
vm.componentInfo.component.configuration = {}; |
|||
} |
|||
loadComponentDescriptor(); |
|||
} |
|||
}); |
|||
|
|||
var componentDescriptorsPromise = |
|||
vm.componentInfo.type === types.componentType.action |
|||
? componentDescriptorService.getPluginActionsByPluginClazz(vm.componentInfo.pluginClazz) |
|||
: componentDescriptorService.getComponentDescriptorsByType(vm.componentInfo.type); |
|||
|
|||
componentDescriptorsPromise.then( |
|||
function success(componentDescriptors) { |
|||
vm.componentDescriptors = componentDescriptors; |
|||
if (vm.componentDescriptors.length === 1 && isAdd && !vm.componentInfo.component.clazz) { |
|||
vm.componentInfo.component.clazz = vm.componentDescriptors[0].clazz; |
|||
} |
|||
}, |
|||
function fail() { |
|||
} |
|||
); |
|||
|
|||
loadComponentDescriptor(); |
|||
|
|||
function loadComponentDescriptor () { |
|||
if (vm.componentInfo.component.clazz) { |
|||
componentDescriptorService.getComponentDescriptorByClazz(vm.componentInfo.component.clazz).then( |
|||
function success(componentDescriptor) { |
|||
vm.componentDescriptor = componentDescriptor; |
|||
vm.componentHasSchema = utils.isDescriptorSchemaNotEmpty(vm.componentDescriptor.configurationDescriptor); |
|||
}, |
|||
function fail() { |
|||
} |
|||
); |
|||
} else { |
|||
vm.componentHasSchema = false; |
|||
} |
|||
} |
|||
|
|||
function helpLinkIdForComponent() { |
|||
switch (vm.componentInfo.type) { |
|||
case types.componentType.filter: { |
|||
return helpLinks.getFilterLink(vm.componentInfo.component); |
|||
} |
|||
case types.componentType.processor: { |
|||
return helpLinks.getProcessorLink(vm.componentInfo.component); |
|||
} |
|||
case types.componentType.action: { |
|||
return helpLinks.getPluginActionLink(vm.componentInfo.component); |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
|
|||
function cancel () { |
|||
$mdDialog.cancel(); |
|||
} |
|||
|
|||
function save () { |
|||
$mdDialog.hide(vm.componentInfo.component); |
|||
} |
|||
|
|||
} |
|||
@ -1,60 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import componentDialogTemplate from './component-dialog.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function ComponentDialogService($mdDialog, $document, $q) { |
|||
|
|||
var service = { |
|||
openComponentDialog: openComponentDialog |
|||
} |
|||
|
|||
return service; |
|||
|
|||
function openComponentDialog($event, isAdd, readOnly, title, type, pluginClazz, component) { |
|||
var deferred = $q.defer(); |
|||
var componentInfo = { |
|||
title: title, |
|||
type: type, |
|||
pluginClazz: pluginClazz |
|||
}; |
|||
if (component) { |
|||
componentInfo.component = angular.copy(component); |
|||
} |
|||
$mdDialog.show({ |
|||
controller: 'ComponentDialogController', |
|||
controllerAs: 'vm', |
|||
templateUrl: componentDialogTemplate, |
|||
locals: {isAdd: isAdd, |
|||
isReadOnly: readOnly, |
|||
componentInfo: componentInfo}, |
|||
parent: angular.element($document[0].body), |
|||
fullscreen: true, |
|||
targetEvent: $event, |
|||
skipHide: true |
|||
}).then(function (component) { |
|||
deferred.resolve(component); |
|||
}, function () { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
} |
|||
@ -1,79 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-dialog aria-label="{{ vm.componentInfo.title | translate }}" tb-help="vm.helpLinkIdForComponent()" help-container-id="help-container"> |
|||
<form name="theForm" ng-submit="vm.save()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>{{ vm.componentInfo.title }}</h2> |
|||
<span flex></span> |
|||
<div id="help-container"></div> |
|||
<md-button class="md-icon-button" ng-click="vm.cancel()"> |
|||
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> |
|||
</md-button> |
|||
</div> |
|||
</md-toolbar> |
|||
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> |
|||
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
|||
<md-dialog-content> |
|||
<div class="md-dialog-content tb-filter"> |
|||
<fieldset ng-disabled="$root.loading || vm.isReadOnly"> |
|||
<section flex layout="row"> |
|||
<md-input-container flex class="md-block"> |
|||
<label translate>rule.component-name</label> |
|||
<input required name="componentName" ng-model="vm.componentInfo.component.name"> |
|||
<div ng-messages="theForm.componentName.$error"> |
|||
<div translate ng-message="required">rule.component-name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container flex class="md-block"> |
|||
<label translate>rule.component-type</label> |
|||
<md-select required name="componentType" ng-model="vm.componentInfo.component.clazz" ng-disabled="$root.loading || vm.isReadOnly"> |
|||
<md-option ng-repeat="componentDescriptor in vm.componentDescriptors" ng-value="componentDescriptor.clazz"> |
|||
{{componentDescriptor.name}} |
|||
</md-option> |
|||
</md-select> |
|||
<div ng-messages="theForm.componentType.$error"> |
|||
<div translate ng-message="required">rule.component-type-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</section> |
|||
<md-card flex class="plugin-config" ng-if="vm.componentHasSchema"> |
|||
<md-card-content> |
|||
<tb-json-form schema="vm.componentDescriptor.configurationDescriptor.schema" |
|||
form="vm.componentDescriptor.configurationDescriptor.form" |
|||
model="vm.componentInfo.component.configuration" |
|||
readonly="$root.loading || vm.isReadOnly" |
|||
form-control="theForm"> |
|||
</tb-json-form> |
|||
</md-card-content> |
|||
</md-card> |
|||
</fieldset> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-if="!vm.isReadOnly" ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" |
|||
class="md-raised md-primary"> |
|||
{{ (vm.isAdd ? 'action.add' : 'action.save') | translate }} |
|||
</md-button> |
|||
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | |
|||
translate }} |
|||
</md-button> |
|||
</md-dialog-actions> |
|||
</form> |
|||
</md-dialog> |
|||
@ -1,75 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import componentTemplate from './component.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function ComponentDirective($compile, $templateCache, $document, $mdDialog, componentDialogService, componentDescriptorService) { |
|||
|
|||
var linker = function (scope, element) { |
|||
|
|||
var template = $templateCache.get(componentTemplate); |
|||
|
|||
element.html(template); |
|||
|
|||
scope.componentTypeName = ''; |
|||
|
|||
scope.loadComponentTypeName = function () { |
|||
componentDescriptorService.getComponentDescriptorByClazz(scope.component.clazz).then( |
|||
function success(component) { |
|||
scope.componentTypeName = component.name; |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} |
|||
|
|||
scope.$watch('component', function(newVal) { |
|||
if (newVal) { |
|||
scope.loadComponentTypeName(); |
|||
} |
|||
} |
|||
); |
|||
|
|||
scope.openComponent = function($event) { |
|||
componentDialogService.openComponentDialog($event, false, |
|||
scope.readOnly, scope.title, scope.type, scope.pluginClazz, |
|||
angular.copy(scope.component)).then( |
|||
function success(component) { |
|||
scope.component = component; |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} |
|||
|
|||
$compile(element.contents())(scope); |
|||
} |
|||
|
|||
return { |
|||
restrict: "E", |
|||
link: linker, |
|||
scope: { |
|||
component: '=', |
|||
type: '=', |
|||
pluginClazz: '=', |
|||
title: '@', |
|||
readOnly: '=', |
|||
onRemoveComponent: '&' |
|||
} |
|||
}; |
|||
} |
|||
@ -1,58 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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. |
|||
|
|||
--> |
|||
<div class="md-whiteframe-4dp" flex layout="row" layout-align="start center" |
|||
style="padding: 0 0 0 10px; margin: 5px;"> |
|||
<span flex="50"> |
|||
{{ component.name }} |
|||
</span> |
|||
<span flex="50"> |
|||
{{ componentTypeName }} |
|||
</span> |
|||
<span ng-if="readOnly" style="min-width: 40px; min-height: 40px; margin: 0 6px;"></br></span> |
|||
<md-button ng-disabled="$root.loading" class="md-icon-button md-primary" |
|||
style="min-width: 40px;" |
|||
ng-click="openComponent($event)" |
|||
aria-label="{{ (readOnly ? 'action.view' : 'action.edit') | translate }}"> |
|||
<md-tooltip ng-if="readOnly" md-direction="top"> |
|||
{{ 'action.view' | translate }} |
|||
</md-tooltip> |
|||
<md-tooltip ng-if="!readOnly" md-direction="top"> |
|||
{{ 'action.edit' | translate }} |
|||
</md-tooltip> |
|||
<md-icon ng-if="readOnly" aria-label="{{ 'action.view' | translate }}" |
|||
class="material-icons"> |
|||
more_horiz |
|||
</md-icon> |
|||
<md-icon ng-if="!readOnly" aria-label="{{ 'action.edit' | translate }}" |
|||
class="material-icons"> |
|||
edit |
|||
</md-icon> |
|||
</md-button> |
|||
<md-button ng-if="!readOnly" ng-disabled="$root.loading" class="md-icon-button md-primary" |
|||
style="min-width: 40px;" |
|||
ng-click="onRemoveComponent({event: $event})" |
|||
aria-label="{{ 'action.remove' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'action.remove' | translate }} |
|||
</md-tooltip> |
|||
<md-icon aria-label="{{ 'action.delete' | translate }}" |
|||
class="material-icons"> |
|||
close |
|||
</md-icon> |
|||
</md-button> |
|||
</div> |
|||
@ -1,28 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 thingsboardApiComponentDescriptor from '../api/component-descriptor.service'; |
|||
|
|||
import ComponentDialogService from './component-dialog.service'; |
|||
import ComponentDialogController from './component-dialog.controller'; |
|||
import ComponentDirective from './component.directive'; |
|||
|
|||
export default angular.module('thingsboard.component', [ |
|||
thingsboardApiComponentDescriptor |
|||
]) |
|||
.factory('componentDialogService', ComponentDialogService) |
|||
.controller('ComponentDialogController', ComponentDialogController) |
|||
.directive('tbComponent', ComponentDirective) |
|||
.name; |
|||
@ -1,115 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 './plugin-select.scss'; |
|||
|
|||
import thingsboardApiPlugin from '../api/plugin.service'; |
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import pluginSelectTemplate from './plugin-select.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
|
|||
export default angular.module('thingsboard.directives.pluginSelect', [thingsboardApiPlugin]) |
|||
.directive('tbPluginSelect', PluginSelect) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function PluginSelect($compile, $templateCache, $q, pluginService, types) { |
|||
|
|||
var linker = function (scope, element, attrs, ngModelCtrl) { |
|||
var template = $templateCache.get(pluginSelectTemplate); |
|||
element.html(template); |
|||
|
|||
scope.tbRequired = angular.isDefined(scope.tbRequired) ? scope.tbRequired : false; |
|||
scope.plugin = null; |
|||
scope.pluginSearchText = ''; |
|||
scope.searchTextChanged = false; |
|||
|
|||
scope.pluginFetchFunction = pluginService.getAllPlugins; |
|||
if (angular.isDefined(scope.pluginsScope)) { |
|||
if (scope.pluginsScope === 'action') { |
|||
scope.pluginFetchFunction = pluginService.getAllActionPlugins; |
|||
} else if (scope.pluginsScope === 'system') { |
|||
scope.pluginFetchFunction = pluginService.getSystemPlugins; |
|||
} else if (scope.pluginsScope === 'tenant') { |
|||
scope.pluginFetchFunction = pluginService.getTenantPlugins; |
|||
} |
|||
} |
|||
|
|||
scope.fetchPlugins = function(searchText) { |
|||
var pageLink = {limit: 10, textSearch: searchText}; |
|||
|
|||
var deferred = $q.defer(); |
|||
|
|||
scope.pluginFetchFunction(pageLink, {ignoreLoading: true}).then(function success(result) { |
|||
deferred.resolve(result.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
|
|||
return deferred.promise; |
|||
} |
|||
|
|||
scope.pluginSearchTextChanged = function() { |
|||
scope.searchTextChanged = true; |
|||
} |
|||
|
|||
scope.isSystem = function(item) { |
|||
return item && item.tenantId.id === types.id.nullUid; |
|||
} |
|||
|
|||
scope.updateView = function () { |
|||
ngModelCtrl.$setViewValue(scope.plugin); |
|||
} |
|||
|
|||
ngModelCtrl.$render = function () { |
|||
if (ngModelCtrl.$viewValue) { |
|||
scope.plugin = ngModelCtrl.$viewValue; |
|||
} |
|||
} |
|||
|
|||
scope.$watch('plugin', function () { |
|||
scope.updateView(); |
|||
}) |
|||
|
|||
if (scope.selectFirstPlugin) { |
|||
var pageLink = {limit: 1, textSearch: ''}; |
|||
scope.pluginFetchFunction(pageLink, {ignoreLoading: true}).then(function success(result) { |
|||
var plugins = result.data; |
|||
if (plugins.length > 0) { |
|||
scope.plugin = plugins[0]; |
|||
} |
|||
}, function fail() { |
|||
}); |
|||
} |
|||
|
|||
$compile(element.contents())(scope); |
|||
} |
|||
|
|||
return { |
|||
restrict: "E", |
|||
require: "^ngModel", |
|||
link: linker, |
|||
scope: { |
|||
pluginsScope: '@', |
|||
theForm: '=?', |
|||
tbRequired: '=?', |
|||
selectFirstPlugin: '=' |
|||
} |
|||
}; |
|||
} |
|||
@ -1,37 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 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 "../../scss/mixins"; |
|||
|
|||
.tb-plugin-autocomplete { |
|||
.tb-not-found { |
|||
display: block; |
|||
line-height: 1.5; |
|||
height: 48px; |
|||
} |
|||
.tb-plugin-item { |
|||
display: block; |
|||
height: 48px; |
|||
.tb-plugin-system { |
|||
font-size: 0.8rem; |
|||
opacity: 0.8; |
|||
float: right; |
|||
} |
|||
} |
|||
li { |
|||
height: auto !important; |
|||
white-space: normal !important; |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-autocomplete ng-required="tbRequired" |
|||
md-input-name="plugin" |
|||
ng-model="plugin" |
|||
md-selected-item="plugin" |
|||
md-search-text="pluginSearchText" |
|||
md-search-text-change="pluginSearchTextChanged()" |
|||
md-items="item in fetchPlugins(pluginSearchText)" |
|||
md-item-text="item.name" |
|||
md-min-length="0" |
|||
placeholder="{{ 'plugin.select-plugin' | translate }}" |
|||
md-menu-class="tb-plugin-autocomplete"> |
|||
<md-item-template> |
|||
<div class="tb-plugin-item"> |
|||
<span md-highlight-text="pluginSearchText" md-highlight-flags="^i">{{item.name}}</span> |
|||
<span translate class="tb-plugin-system" ng-if="isSystem(item)">plugin.system</span> |
|||
</div> |
|||
</md-item-template> |
|||
<md-not-found> |
|||
<div class="tb-not-found"> |
|||
<span translate translate-values='{ entity: pluginSearchText }'>plugin.no-plugins-matching</span> |
|||
</div> |
|||
</md-not-found> |
|||
</md-autocomplete> |
|||
<div ng-if="searchTextChanged" class="tb-error-messages" ng-messages="theForm.plugin.$error" role="alert"> |
|||
<div translate ng-message="required" class="tb-error-message">plugin.plugin-required</div> |
|||
<div translate ng-message="md-require-match" class="tb-error-message">plugin.plugin-require-match</div> |
|||
</div> |
|||
@ -1,48 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-dialog aria-label="{{ 'plugin.add' | translate }}" tb-help="vm.helpLinks.getPluginLink(vm.item)" help-container-id="help-container"> |
|||
<form name="theForm" ng-submit="vm.add()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>plugin.add</h2> |
|||
<span flex></span> |
|||
<div id="help-container"></div> |
|||
<md-button class="md-icon-button" ng-click="vm.cancel()"> |
|||
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> |
|||
</md-button> |
|||
</div> |
|||
</md-toolbar> |
|||
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> |
|||
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
|||
<md-dialog-content> |
|||
<div class="md-dialog-content"> |
|||
<tb-plugin plugin="vm.item" is-edit="true" the-form="theForm"></tb-plugin> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" |
|||
class="md-raised md-primary"> |
|||
{{ 'action.add' | translate }} |
|||
</md-button> |
|||
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | |
|||
translate }} |
|||
</md-button> |
|||
</md-dialog-actions> |
|||
</form> |
|||
</md-dialog> |
|||
@ -1,36 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 uiRouter from 'angular-ui-router'; |
|||
import thingsboardGrid from '../components/grid.directive'; |
|||
import thingsboardJsonForm from '../components/json-form.directive'; |
|||
import thingsboardApiPlugin from '../api/plugin.service'; |
|||
import thingsboardApiComponentDescriptor from '../api/component-descriptor.service'; |
|||
|
|||
import PluginRoutes from './plugin.routes'; |
|||
import PluginController from './plugin.controller'; |
|||
import PluginDirective from './plugin.directive'; |
|||
|
|||
export default angular.module('thingsboard.plugin', [ |
|||
uiRouter, |
|||
thingsboardGrid, |
|||
thingsboardJsonForm, |
|||
thingsboardApiPlugin, |
|||
thingsboardApiComponentDescriptor |
|||
]) |
|||
.config(PluginRoutes) |
|||
.controller('PluginController', PluginController) |
|||
.directive('tbPlugin', PluginDirective) |
|||
.name; |
|||
@ -1,19 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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. |
|||
|
|||
--> |
|||
<div class="tb-uppercase" ng-if="item && parentCtl.types.id.nullUid === item.tenantId.id" translate>plugin.system</div> |
|||
<div class="tb-uppercase" translate>{{item && item.state === 'ACTIVE' ? 'plugin.active' : 'plugin.suspended'}}</div> |
|||
@ -1,90 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-button ng-click="onActivatePlugin({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly && plugin.state === 'SUSPENDED'" |
|||
class="md-raised md-primary">{{ 'plugin.activate' | translate }}</md-button> |
|||
<md-button ng-click="onSuspendPlugin({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly && plugin.state === 'ACTIVE'" |
|||
class="md-raised md-primary">{{ 'plugin.suspend' | translate }}</md-button> |
|||
<md-button ng-click="onExportPlugin({event: $event})" |
|||
ng-show="!isEdit" |
|||
class="md-raised md-primary">{{ 'plugin.export' | translate }}</md-button> |
|||
<md-button ng-click="onDeletePlugin({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly" |
|||
class="md-raised md-primary">{{ 'plugin.delete' | translate }}</md-button> |
|||
|
|||
<div layout="row"> |
|||
<md-button ngclipboard data-clipboard-action="copy" |
|||
ngclipboard-success="onPluginIdCopied(e)" |
|||
data-clipboard-text="{{plugin.id.id}}" ng-show="!isEdit" |
|||
class="md-raised"> |
|||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon> |
|||
<span translate>plugin.copyId</span> |
|||
</md-button> |
|||
</div> |
|||
|
|||
<md-content class="md-padding" layout="column" style="overflow-x: hidden"> |
|||
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> |
|||
<md-input-container class="md-block"> |
|||
<label translate>plugin.name</label> |
|||
<input required name="name" ng-model="plugin.name"> |
|||
<div ng-messages="theForm.name.$error"> |
|||
<div translate ng-message="required">plugin.name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label translate>plugin.description</label> |
|||
<textarea ng-model="plugin.additionalInfo.description" rows="2"></textarea> |
|||
</md-input-container> |
|||
<section flex layout="row"> |
|||
<md-input-container flex class="md-block"> |
|||
<label translate>plugin.api-token</label> |
|||
<input required name="apiToken" ng-model="plugin.apiToken"> |
|||
<div ng-messages="theForm.apiToken.$error"> |
|||
<div translate ng-message="required">plugin.api-token-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container flex class="md-block"> |
|||
<label translate>plugin.type</label> |
|||
<md-select required name="pluginType" ng-model="plugin.clazz" ng-disabled="$root.loading || !isEdit"> |
|||
<md-option ng-repeat="component in pluginComponents" ng-value="component.clazz"> |
|||
{{component.name}} |
|||
</md-option> |
|||
</md-select> |
|||
<div ng-messages="theForm.pluginType.$error"> |
|||
<div translate ng-message="required">plugin.type-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
</section> |
|||
<md-card flex class="plugin-config" ng-if="showPluginConfig"> |
|||
<md-card-title> |
|||
<md-card-title-text> |
|||
<span translate class="md-headline" ng-class="{'tb-readonly-label' : ($root.loading || !isEdit || isReadOnly)}">plugin.configuration</span> |
|||
</md-card-title-text> |
|||
</md-card-title> |
|||
<md-card-content> |
|||
<tb-json-form schema="pluginComponent.configurationDescriptor.schema" |
|||
form="pluginComponent.configurationDescriptor.form" |
|||
model="pluginConfiguration.data" |
|||
readonly="$root.loading || !isEdit || isReadOnly" |
|||
form-control="theForm"> |
|||
</tb-json-form> |
|||
</md-card-content> |
|||
</md-card> |
|||
</fieldset> |
|||
</md-content> |
|||
@ -1,218 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import addPluginTemplate from './add-plugin.tpl.html'; |
|||
import pluginCard from './plugin-card.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function PluginController(pluginService, userService, importExport, $state, $stateParams, $filter, $translate, types, helpLinks) { |
|||
|
|||
var pluginActionsList = [ |
|||
{ |
|||
onAction: function ($event, item) { |
|||
exportPlugin($event, item); |
|||
}, |
|||
name: function() { $translate.instant('action.export') }, |
|||
details: function() { return $translate.instant('plugin.export') }, |
|||
icon: "file_download" |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
activatePlugin($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.activate') }, |
|||
details: function() { return $translate.instant('plugin.activate') }, |
|||
icon: "play_arrow", |
|||
isEnabled: function(plugin) { |
|||
return isPluginEditable(plugin) && plugin && plugin.state === 'SUSPENDED'; |
|||
} |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
suspendPlugin($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.suspend') }, |
|||
details: function() { return $translate.instant('plugin.suspend') }, |
|||
icon: "pause", |
|||
isEnabled: function(plugin) { |
|||
return isPluginEditable(plugin) && plugin && plugin.state === 'ACTIVE'; |
|||
} |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
vm.grid.deleteItem($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.delete') }, |
|||
details: function() { return $translate.instant('plugin.delete') }, |
|||
icon: "delete", |
|||
isEnabled: isPluginEditable |
|||
} |
|||
]; |
|||
|
|||
var pluginAddItemActionsList = [ |
|||
{ |
|||
onAction: function ($event) { |
|||
vm.grid.addItem($event); |
|||
}, |
|||
name: function() { return $translate.instant('action.create') }, |
|||
details: function() { return $translate.instant('plugin.create-new-plugin') }, |
|||
icon: "insert_drive_file" |
|||
}, |
|||
{ |
|||
onAction: function ($event) { |
|||
importExport.importPlugin($event).then( |
|||
function() { |
|||
vm.grid.refreshList(); |
|||
} |
|||
); |
|||
}, |
|||
name: function() { return $translate.instant('action.import') }, |
|||
details: function() { return $translate.instant('plugin.import') }, |
|||
icon: "file_upload" |
|||
} |
|||
]; |
|||
|
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.helpLinkIdForPlugin = helpLinkIdForPlugin; |
|||
|
|||
vm.pluginGridConfig = { |
|||
|
|||
refreshParamsFunc: null, |
|||
|
|||
deleteItemTitleFunc: deletePluginTitle, |
|||
deleteItemContentFunc: deletePluginText, |
|||
deleteItemsTitleFunc: deletePluginsTitle, |
|||
deleteItemsActionTitleFunc: deletePluginsActionTitle, |
|||
deleteItemsContentFunc: deletePluginsText, |
|||
|
|||
fetchItemsFunc: fetchPlugins, |
|||
saveItemFunc: savePlugin, |
|||
deleteItemFunc: deletePlugin, |
|||
|
|||
getItemTitleFunc: getPluginTitle, |
|||
itemCardTemplateUrl: pluginCard, |
|||
parentCtl: vm, |
|||
|
|||
actionsList: pluginActionsList, |
|||
addItemActions: pluginAddItemActionsList, |
|||
|
|||
onGridInited: gridInited, |
|||
|
|||
addItemTemplateUrl: addPluginTemplate, |
|||
|
|||
addItemText: function() { return $translate.instant('plugin.add-plugin-text') }, |
|||
noItemsText: function() { return $translate.instant('plugin.no-plugins-text') }, |
|||
itemDetailsText: function() { return $translate.instant('plugin.plugin-details') }, |
|||
isSelectionEnabled: isPluginEditable, |
|||
isDetailsReadOnly: function(plugin) { |
|||
return !isPluginEditable(plugin); |
|||
} |
|||
|
|||
}; |
|||
|
|||
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) { |
|||
vm.pluginGridConfig.items = $stateParams.items; |
|||
} |
|||
|
|||
if (angular.isDefined($stateParams.topIndex) && $stateParams.topIndex > 0) { |
|||
vm.pluginGridConfig.topIndex = $stateParams.topIndex; |
|||
} |
|||
|
|||
vm.isPluginEditable = isPluginEditable; |
|||
|
|||
vm.activatePlugin = activatePlugin; |
|||
vm.suspendPlugin = suspendPlugin; |
|||
vm.exportPlugin = exportPlugin; |
|||
|
|||
function helpLinkIdForPlugin() { |
|||
return helpLinks.getPluginLink(vm.grid.operatingItem()); |
|||
} |
|||
|
|||
function deletePluginTitle(plugin) { |
|||
return $translate.instant('plugin.delete-plugin-title', {pluginName: plugin.name}); |
|||
} |
|||
|
|||
function deletePluginText() { |
|||
return $translate.instant('plugin.delete-plugin-text'); |
|||
} |
|||
|
|||
function deletePluginsTitle(selectedCount) { |
|||
return $translate.instant('plugin.delete-plugins-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deletePluginsActionTitle(selectedCount) { |
|||
return $translate.instant('plugin.delete-plugins-action-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deletePluginsText() { |
|||
return $translate.instant('plugin.delete-plugins-text'); |
|||
} |
|||
|
|||
function gridInited(grid) { |
|||
vm.grid = grid; |
|||
} |
|||
|
|||
function fetchPlugins(pageLink) { |
|||
return pluginService.getAllPlugins(pageLink); |
|||
} |
|||
|
|||
function savePlugin(plugin) { |
|||
return pluginService.savePlugin(plugin); |
|||
} |
|||
|
|||
function deletePlugin(pluginId) { |
|||
return pluginService.deletePlugin(pluginId); |
|||
} |
|||
|
|||
function getPluginTitle(plugin) { |
|||
return plugin ? plugin.name : ''; |
|||
} |
|||
|
|||
function isPluginEditable(plugin) { |
|||
if (userService.getAuthority() === 'TENANT_ADMIN') { |
|||
return plugin && plugin.tenantId.id != types.id.nullUid; |
|||
} else { |
|||
return userService.getAuthority() === 'SYS_ADMIN'; |
|||
} |
|||
} |
|||
|
|||
function exportPlugin($event, plugin) { |
|||
$event.stopPropagation(); |
|||
importExport.exportPlugin(plugin.id.id); |
|||
} |
|||
|
|||
function activatePlugin(event, plugin) { |
|||
pluginService.activatePlugin(plugin.id.id).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
} |
|||
|
|||
function suspendPlugin(event, plugin) { |
|||
pluginService.suspendPlugin(plugin.id.id).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
} |
|||
|
|||
} |
|||
@ -1,94 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 './plugin.scss'; |
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import pluginFieldsetTemplate from './plugin-fieldset.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function PluginDirective($compile, $templateCache, $translate, types, toast, utils, userService, componentDescriptorService) { |
|||
var linker = function (scope, element) { |
|||
var template = $templateCache.get(pluginFieldsetTemplate); |
|||
element.html(template); |
|||
|
|||
scope.showPluginConfig = false; |
|||
|
|||
scope.pluginConfiguration = { |
|||
data: null |
|||
}; |
|||
|
|||
if (scope.plugin && !scope.plugin.configuration) { |
|||
scope.plugin.configuration = {}; |
|||
} |
|||
|
|||
scope.$watch("plugin.clazz", function (newValue, prevValue) { |
|||
if (newValue != prevValue) { |
|||
scope.pluginConfiguration.data = null; |
|||
if (scope.plugin) { |
|||
componentDescriptorService.getComponentDescriptorByClazz(scope.plugin.clazz).then( |
|||
function success(component) { |
|||
scope.pluginComponent = component; |
|||
scope.showPluginConfig = !(userService.getAuthority() === 'TENANT_ADMIN' |
|||
&& scope.plugin.tenantId |
|||
&& scope.plugin.tenantId.id === types.id.nullUid) |
|||
&& utils.isDescriptorSchemaNotEmpty(scope.pluginComponent.configurationDescriptor); |
|||
scope.pluginConfiguration.data = angular.copy(scope.plugin.configuration); |
|||
}, |
|||
function fail() { |
|||
} |
|||
); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
scope.$watch("pluginConfiguration.data", function (newValue, prevValue) { |
|||
if (newValue && !angular.equals(newValue, prevValue)) { |
|||
scope.plugin.configuration = angular.copy(scope.pluginConfiguration.data); |
|||
} |
|||
}, true); |
|||
|
|||
scope.onPluginIdCopied = function() { |
|||
toast.showSuccess($translate.instant('plugin.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); |
|||
}; |
|||
|
|||
componentDescriptorService.getComponentDescriptorsByType(types.componentType.plugin).then( |
|||
function success(components) { |
|||
scope.pluginComponents = components; |
|||
}, |
|||
function fail() { |
|||
} |
|||
); |
|||
|
|||
$compile(element.contents())(scope); |
|||
} |
|||
return { |
|||
restrict: "E", |
|||
link: linker, |
|||
scope: { |
|||
plugin: '=', |
|||
isEdit: '=', |
|||
isReadOnly: '=', |
|||
theForm: '=', |
|||
onActivatePlugin: '&', |
|||
onSuspendPlugin: '&', |
|||
onExportPlugin: '&', |
|||
onDeletePlugin: '&' |
|||
} |
|||
}; |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import pluginsTemplate from './plugins.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function PluginRoutes($stateProvider) { |
|||
|
|||
$stateProvider |
|||
.state('home.plugins', { |
|||
url: '/plugins', |
|||
params: {'topIndex': 0}, |
|||
module: 'private', |
|||
auth: ['SYS_ADMIN', 'TENANT_ADMIN'], |
|||
views: { |
|||
"content@home": { |
|||
templateUrl: pluginsTemplate, |
|||
controllerAs: 'vm', |
|||
controller: 'PluginController' |
|||
} |
|||
}, |
|||
data: { |
|||
searchEnabled: true, |
|||
pageTitle: 'plugin.plugins' |
|||
}, |
|||
ncyBreadcrumb: { |
|||
label: '{"icon": "extension", "label": "plugin.plugins"}' |
|||
} |
|||
}); |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
.plugin-config { |
|||
min-width: 500px; |
|||
} |
|||
@ -1,77 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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. |
|||
|
|||
--> |
|||
<tb-grid grid-configuration="vm.pluginGridConfig"> |
|||
<details-buttons tb-help="vm.helpLinkIdForPlugin()" help-container-id="help-container"> |
|||
<div id="help-container"></div> |
|||
</details-buttons> |
|||
<md-tabs ng-class="{'tb-headless': (vm.grid.detailsConfig.isDetailsEditMode || !vm.isPluginEditable(vm.grid.operatingItem()))}" |
|||
id="tabs" md-border-bottom flex class="tb-absolute-fill"> |
|||
<md-tab label="{{ 'plugin.details' | translate }}"> |
|||
<tb-plugin plugin="vm.grid.operatingItem()" |
|||
is-edit="vm.grid.detailsConfig.isDetailsEditMode" |
|||
is-read-only="vm.grid.isDetailsReadOnly(vm.grid.operatingItem())" |
|||
the-form="vm.grid.detailsForm" |
|||
on-activate-plugin="vm.activatePlugin(event, vm.grid.detailsConfig.currentItem)" |
|||
on-suspend-plugin="vm.suspendPlugin(event, vm.grid.detailsConfig.currentItem)" |
|||
on-export-plugin="vm.exportPlugin(event, vm.grid.detailsConfig.currentItem)" |
|||
on-delete-plugin="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-plugin> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> |
|||
<tb-attribute-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.plugin}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.attributesScope.server.value}}"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}"> |
|||
<tb-attribute-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.plugin}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.latestTelemetry.value}}" |
|||
disable-attribute-scope-selection="true"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> |
|||
<tb-alarm-table flex entity-type="vm.types.entityType.plugin" |
|||
entity-id="vm.grid.operatingItem().id.id"> |
|||
</tb-alarm-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'plugin.events' | translate }}"> |
|||
<tb-event-table flex entity-type="vm.types.entityType.plugin" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
tenant-id="vm.grid.operatingItem().tenantId.id" |
|||
default-event-type="{{vm.types.eventType.lcEvent.value}}"> |
|||
</tb-event-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> |
|||
<tb-relation-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.plugin}}"> |
|||
</tb-relation-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isPluginEditable(vm.grid.operatingItem()) && vm.grid.isTenantAdmin()" |
|||
md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}"> |
|||
<tb-audit-log-table flex entity-type="vm.types.entityType.plugin" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
audit-log-mode="{{vm.types.auditLogMode.entity}}"> |
|||
</tb-audit-log-table> |
|||
</md-tab> |
|||
</md-tabs> |
|||
</tb-grid> |
|||
@ -1,48 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-dialog aria-label="{{ 'rule.add' | translate }}" tb-help="'rules'" help-container-id="help-container"> |
|||
<form name="theForm" ng-submit="vm.add()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>rule.add</h2> |
|||
<span flex></span> |
|||
<div id="help-container"></div> |
|||
<md-button class="md-icon-button" ng-click="vm.cancel()"> |
|||
<ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> |
|||
</md-button> |
|||
</div> |
|||
</md-toolbar> |
|||
<md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> |
|||
<span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> |
|||
<md-dialog-content> |
|||
<div class="md-dialog-content"> |
|||
<tb-rule rule="vm.item" is-edit="true" the-form="theForm"></tb-rule> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" |
|||
class="md-raised md-primary"> |
|||
{{ 'action.add' | translate }} |
|||
</md-button> |
|||
<md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | |
|||
translate }} |
|||
</md-button> |
|||
</md-dialog-actions> |
|||
</form> |
|||
</md-dialog> |
|||
@ -1,40 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 uiRouter from 'angular-ui-router'; |
|||
import thingsboardGrid from '../components/grid.directive'; |
|||
import thingsboardPluginSelect from '../components/plugin-select.directive'; |
|||
import thingsboardComponent from '../component'; |
|||
import thingsboardApiRule from '../api/rule.service'; |
|||
import thingsboardApiPlugin from '../api/plugin.service'; |
|||
import thingsboardApiComponentDescriptor from '../api/component-descriptor.service'; |
|||
|
|||
import RuleRoutes from './rule.routes'; |
|||
import RuleController from './rule.controller'; |
|||
import RuleDirective from './rule.directive'; |
|||
|
|||
export default angular.module('thingsboard.rule', [ |
|||
uiRouter, |
|||
thingsboardGrid, |
|||
thingsboardPluginSelect, |
|||
thingsboardComponent, |
|||
thingsboardApiRule, |
|||
thingsboardApiPlugin, |
|||
thingsboardApiComponentDescriptor |
|||
]) |
|||
.config(RuleRoutes) |
|||
.controller('RuleController', RuleController) |
|||
.directive('tbRule', RuleDirective) |
|||
.name; |
|||
@ -1,19 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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. |
|||
|
|||
--> |
|||
<div class="tb-uppercase" ng-if="item && parentCtl.types.id.nullUid === item.tenantId.id" translate>rule.system</div> |
|||
<div class="tb-uppercase" translate>{{item && item.state === 'ACTIVE' ? 'rule.active' : 'rule.suspended'}}</div> |
|||
@ -1,219 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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-button ng-click="onActivateRule({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly && rule.state === 'SUSPENDED'" |
|||
class="md-raised md-primary">{{ 'rule.activate' | translate }}</md-button> |
|||
<md-button ng-click="onSuspendRule({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly && rule.state === 'ACTIVE'" |
|||
class="md-raised md-primary">{{ 'rule.suspend' | translate }}</md-button> |
|||
<md-button ng-click="onExportRule({event: $event})" |
|||
ng-show="!isEdit" |
|||
class="md-raised md-primary">{{ 'rule.export' | translate }}</md-button> |
|||
<md-button ng-click="onDeleteRule({event: $event})" |
|||
ng-show="!isEdit && !isReadOnly" |
|||
class="md-raised md-primary">{{ 'rule.delete' | translate }}</md-button> |
|||
|
|||
<div layout="row"> |
|||
<md-button ngclipboard data-clipboard-action="copy" |
|||
ngclipboard-success="onRuleIdCopied(e)" |
|||
data-clipboard-text="{{rule.id.id}}" ng-show="!isEdit" |
|||
class="md-raised"> |
|||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon> |
|||
<span translate>rule.copyId</span> |
|||
</md-button> |
|||
</div> |
|||
|
|||
<md-content class="md-padding tb-rule" layout="column"> |
|||
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> |
|||
<md-input-container class="md-block"> |
|||
<label translate>rule.name</label> |
|||
<input required name="name" ng-model="rule.name"> |
|||
<div ng-messages="theForm.name.$error"> |
|||
<div translate ng-message="required">rule.name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<md-input-container class="md-block"> |
|||
<label translate>rule.description</label> |
|||
<textarea ng-model="rule.additionalInfo.description" rows="2"></textarea> |
|||
</md-input-container> |
|||
</fieldset> |
|||
<v-accordion id="filters-accordion" class="vAccordion--default" |
|||
ng-class="{'tb-readonly-label' : (!isEdit || isReadOnly)}"> |
|||
<v-pane id="filters-pane" expanded="true"> |
|||
<v-pane-header> |
|||
{{ 'rule.filters' | translate }} |
|||
</v-pane-header> |
|||
<v-pane-content> |
|||
<div ng-if="rule.filters.length === 0"> |
|||
<span translate layout-align="center center" |
|||
class="tb-prompt">rule.add-filter-prompt</span> |
|||
</div> |
|||
<div ng-if="rule.filters.length > 0"> |
|||
<div flex layout="row" layout-align="start center"> |
|||
<span ng-if="isEdit && !isReadOnly" style="min-width: 40px; margin: 0 6px;"></br></span> |
|||
<span flex="5"></span> |
|||
<div flex layout="row" layout-align="start center" |
|||
style="padding: 0 0 0 10px; margin: 5px;"> |
|||
<span translate flex="50">rule.filter-name</span> |
|||
<span translate flex="50">rule.filter-type</span> |
|||
<span style="min-width: 80px; margin: 0 12px;"></br></span> |
|||
</div> |
|||
</div> |
|||
<div class="tb-filters" style="max-height: 300px; overflow: auto; padding-bottom: 15px;"> |
|||
<ul dnd-list="filters" dnd-disable-if="!isEdit || isReadOnly"> |
|||
<li ng-repeat="filter in filters" |
|||
dnd-draggable="filter" |
|||
dnd-moved="filters.splice($index, 1)" |
|||
dnd-disable-if="!isEdit || isReadOnly" |
|||
dnd-effect-allowed="move"> |
|||
<div flex layout="row" layout-align="start center"> |
|||
<md-button ng-if="isEdit && !isReadOnly" dnd-handle class="md-icon-button md-primary handle" |
|||
style="min-width: 40px;" |
|||
aria-label="{{ 'action.drag' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'action.drag' | translate }} |
|||
</md-tooltip> |
|||
<md-icon aria-label="{{ 'action.drag' | translate }}" |
|||
class="material-icons"> |
|||
drag_handle |
|||
</md-icon> |
|||
</md-button> |
|||
<dnd-nodrag flex layout="row" layout-align="start center"> |
|||
<span flex="5">{{$index + 1}}.</span> |
|||
<tb-component flex |
|||
component="filter.value" |
|||
type="types.componentType.filter" |
|||
title="rule.filter" |
|||
read-only="!isEdit || isReadOnly" |
|||
on-remove-component="removeFilter(event, filter)"> |
|||
</tb-component> |
|||
</dnd-nodrag> |
|||
</div> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
<div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
|||
<md-button ng-disabled="$root.loading" class="md-primary md-raised" |
|||
ng-click="addFilter($event)" aria-label="{{ 'action.add' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'rule.add-filter' | translate }} |
|||
</md-tooltip> |
|||
<md-icon class="material-icons">add</md-icon> |
|||
<span translate>action.add</span> |
|||
</md-button> |
|||
</div> |
|||
</v-pane-content> |
|||
</v-pane> |
|||
</v-accordion> |
|||
<v-accordion id="processor-accordion" class="vAccordion--default" |
|||
ng-class="{'tb-readonly-label' : (!isEdit || isReadOnly)}"> |
|||
<v-pane id="processor-pane" expanded="true"> |
|||
<v-pane-header> |
|||
{{ 'rule.processor' | translate }} |
|||
</v-pane-header> |
|||
<v-pane-content> |
|||
<div ng-if="rule.processor && rule.processor != null"> |
|||
<div flex layout="row" layout-align="start center" |
|||
style="padding: 0 0 0 10px; margin: 5px;"> |
|||
<span translate flex="50">rule.processor-name</span> |
|||
<span translate flex="50">rule.processor-type</span> |
|||
<span style="min-width: 80px; margin: 0 12px;"></br></span> |
|||
</div> |
|||
<div flex layout="row" layout-align="start center" style="padding-bottom: 15px;"> |
|||
<tb-component flex |
|||
component="rule.processor" |
|||
type="types.componentType.processor" |
|||
title="rule.processor" |
|||
read-only="!isEdit || isReadOnly" |
|||
on-remove-component="removeProcessor(event)"> |
|||
</tb-component> |
|||
</div> |
|||
</div> |
|||
<div ng-if="!rule.processor || rule.processor == null"> |
|||
<span ng-if="!isEdit || isReadOnly" translate layout-align="center center" |
|||
class="tb-prompt">rule.no-processor-configured</span> |
|||
<div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
|||
<md-button ng-disabled="$root.loading" class="md-primary md-raised" |
|||
ng-click="addProcessor($event)" aria-label="{{ 'action.create' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'rule.create-processor' | translate }} |
|||
</md-tooltip> |
|||
<md-icon class="material-icons">add</md-icon> |
|||
<span translate>action.create</span> |
|||
</md-button> |
|||
</div> |
|||
</div> |
|||
</v-pane-content> |
|||
</v-pane> |
|||
</v-accordion> |
|||
<fieldset ng-disabled="$root.loading || !isEdit || isReadOnly"> |
|||
<md-input-container ng-if="!isEdit || isReadOnly" flex class="md-block"> |
|||
<label translate>plugin.plugin</label> |
|||
<input name="name" ng-model="plugin.name"> |
|||
</md-input-container> |
|||
<tb-plugin-select ng-show="isEdit && !isReadOnly" flex |
|||
ng-model="plugin" |
|||
tb-required="false" |
|||
the-form="theForm" |
|||
plugins-scope="action"> |
|||
</tb-plugin-select> |
|||
</fieldset> |
|||
<v-accordion ng-if="plugin != null" id="plugin-action-accordion" class="vAccordion--default" |
|||
ng-class="{'tb-readonly-label' : (!isEdit || isReadOnly)}"> |
|||
<v-pane id="plugin-action-pane" expanded="true"> |
|||
<v-pane-header> |
|||
{{ 'rule.plugin-action' | translate }} |
|||
</v-pane-header> |
|||
<v-pane-content> |
|||
<div ng-if="rule.action && rule.action != null"> |
|||
<div flex layout="row" layout-align="start center" |
|||
style="padding: 0 0 0 10px; margin: 5px;"> |
|||
<span translate flex="50">rule.action-name</span> |
|||
<span translate flex="50">rule.action-type</span> |
|||
<span style="min-width: 80px; margin: 0 12px;"></br></span> |
|||
</div> |
|||
<div flex layout="row" layout-align="start center" style="padding-bottom: 15px;"> |
|||
<tb-component flex |
|||
component="rule.action" |
|||
type="types.componentType.action" |
|||
plugin-clazz="plugin.clazz" |
|||
title="rule.plugin-action" |
|||
read-only="!isEdit || isReadOnly" |
|||
on-remove-component="removeAction(event)"> |
|||
</tb-component> |
|||
</div> |
|||
</div> |
|||
<div ng-if="!rule.action || rule.action == null"> |
|||
<span translate layout-align="center center" |
|||
class="tb-prompt">rule.create-action-prompt</span> |
|||
<div ng-if="isEdit && !isReadOnly" flex layout="row" layout-align="start center"> |
|||
<md-button ng-disabled="$root.loading" class="md-primary md-raised" |
|||
ng-click="addAction($event)" aria-label="{{ 'action.create' | translate }}"> |
|||
<md-tooltip md-direction="top"> |
|||
{{ 'rule.create-action' | translate }} |
|||
</md-tooltip> |
|||
<md-icon class="material-icons">add</md-icon> |
|||
<span translate>action.create</span> |
|||
</md-button> |
|||
</div> |
|||
</div> |
|||
</v-pane-content> |
|||
</v-pane> |
|||
</v-accordion> |
|||
</md-content> |
|||
@ -1,210 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import addRuleTemplate from './add-rule.tpl.html'; |
|||
import ruleCard from './rule-card.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function RuleController(ruleService, userService, importExport, $state, $stateParams, $filter, $translate, types) { |
|||
|
|||
var ruleActionsList = [ |
|||
{ |
|||
onAction: function ($event, item) { |
|||
exportRule($event, item); |
|||
}, |
|||
name: function() { $translate.instant('action.export') }, |
|||
details: function() { return $translate.instant('rule.export') }, |
|||
icon: "file_download" |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
activateRule($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.activate') }, |
|||
details: function() { return $translate.instant('rule.activate') }, |
|||
icon: "play_arrow", |
|||
isEnabled: function(rule) { |
|||
return isRuleEditable(rule) && rule && rule.state === 'SUSPENDED'; |
|||
} |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
suspendRule($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.suspend') }, |
|||
details: function() { return $translate.instant('rule.suspend') }, |
|||
icon: "pause", |
|||
isEnabled: function(rule) { |
|||
return isRuleEditable(rule) && rule.state === 'ACTIVE'; |
|||
} |
|||
}, |
|||
{ |
|||
onAction: function ($event, item) { |
|||
vm.grid.deleteItem($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.delete') }, |
|||
details: function() { return $translate.instant('rule.delete') }, |
|||
icon: "delete", |
|||
isEnabled: isRuleEditable |
|||
} |
|||
]; |
|||
|
|||
var ruleAddItemActionsList = [ |
|||
{ |
|||
onAction: function ($event) { |
|||
vm.grid.addItem($event); |
|||
}, |
|||
name: function() { return $translate.instant('action.create') }, |
|||
details: function() { return $translate.instant('rule.create-new-rule') }, |
|||
icon: "insert_drive_file" |
|||
}, |
|||
{ |
|||
onAction: function ($event) { |
|||
importExport.importRule($event).then( |
|||
function() { |
|||
vm.grid.refreshList(); |
|||
} |
|||
); |
|||
}, |
|||
name: function() { return $translate.instant('action.import') }, |
|||
details: function() { return $translate.instant('rule.import') }, |
|||
icon: "file_upload" |
|||
} |
|||
]; |
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.ruleGridConfig = { |
|||
|
|||
refreshParamsFunc: null, |
|||
|
|||
deleteItemTitleFunc: deleteRuleTitle, |
|||
deleteItemContentFunc: deleteRuleText, |
|||
deleteItemsTitleFunc: deleteRulesTitle, |
|||
deleteItemsActionTitleFunc: deleteRulesActionTitle, |
|||
deleteItemsContentFunc: deleteRulesText, |
|||
|
|||
fetchItemsFunc: fetchRules, |
|||
saveItemFunc: saveRule, |
|||
deleteItemFunc: deleteRule, |
|||
|
|||
getItemTitleFunc: getRuleTitle, |
|||
itemCardTemplateUrl: ruleCard, |
|||
parentCtl: vm, |
|||
|
|||
actionsList: ruleActionsList, |
|||
addItemActions: ruleAddItemActionsList, |
|||
|
|||
onGridInited: gridInited, |
|||
|
|||
addItemTemplateUrl: addRuleTemplate, |
|||
|
|||
addItemText: function() { return $translate.instant('rule.add-rule-text') }, |
|||
noItemsText: function() { return $translate.instant('rule.no-rules-text') }, |
|||
itemDetailsText: function() { return $translate.instant('rule.rule-details') }, |
|||
isSelectionEnabled: isRuleEditable, |
|||
isDetailsReadOnly: function(rule) { |
|||
return !isRuleEditable(rule); |
|||
} |
|||
}; |
|||
|
|||
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) { |
|||
vm.ruleGridConfig.items = $stateParams.items; |
|||
} |
|||
|
|||
if (angular.isDefined($stateParams.topIndex) && $stateParams.topIndex > 0) { |
|||
vm.ruleGridConfig.topIndex = $stateParams.topIndex; |
|||
} |
|||
|
|||
vm.isRuleEditable = isRuleEditable; |
|||
|
|||
vm.activateRule = activateRule; |
|||
vm.suspendRule = suspendRule; |
|||
vm.exportRule = exportRule; |
|||
|
|||
function deleteRuleTitle(rule) { |
|||
return $translate.instant('rule.delete-rule-title', {ruleName: rule.name}); |
|||
} |
|||
|
|||
function deleteRuleText() { |
|||
return $translate.instant('rule.delete-rule-text'); |
|||
} |
|||
|
|||
function deleteRulesTitle(selectedCount) { |
|||
return $translate.instant('rule.delete-rules-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteRulesActionTitle(selectedCount) { |
|||
return $translate.instant('rule.delete-rules-action-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteRulesText() { |
|||
return $translate.instant('rule.delete-rules-text'); |
|||
} |
|||
|
|||
function gridInited(grid) { |
|||
vm.grid = grid; |
|||
} |
|||
|
|||
function fetchRules(pageLink) { |
|||
return ruleService.getAllRules(pageLink); |
|||
} |
|||
|
|||
function saveRule(rule) { |
|||
return ruleService.saveRule(rule); |
|||
} |
|||
|
|||
function deleteRule(ruleId) { |
|||
return ruleService.deleteRule(ruleId); |
|||
} |
|||
|
|||
function getRuleTitle(rule) { |
|||
return rule ? rule.name : ''; |
|||
} |
|||
|
|||
function isRuleEditable(rule) { |
|||
if (userService.getAuthority() === 'TENANT_ADMIN') { |
|||
return rule && rule.tenantId.id != types.id.nullUid; |
|||
} else { |
|||
return userService.getAuthority() === 'SYS_ADMIN'; |
|||
} |
|||
} |
|||
|
|||
function exportRule($event, rule) { |
|||
$event.stopPropagation(); |
|||
importExport.exportRule(rule.id.id); |
|||
} |
|||
|
|||
function activateRule(event, rule) { |
|||
ruleService.activateRule(rule.id.id).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
} |
|||
|
|||
function suspendRule(event, rule) { |
|||
ruleService.suspendRule(rule.id.id).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
} |
|||
|
|||
} |
|||
@ -1,191 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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 './rule.scss'; |
|||
|
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import ruleFieldsetTemplate from './rule-fieldset.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function RuleDirective($compile, $templateCache, $mdDialog, $document, $q, $translate, pluginService, |
|||
componentDialogService, componentDescriptorService, types, toast) { |
|||
var linker = function (scope, element) { |
|||
var template = $templateCache.get(ruleFieldsetTemplate); |
|||
element.html(template); |
|||
|
|||
scope.plugin = null; |
|||
scope.types = types; |
|||
scope.filters = []; |
|||
|
|||
scope.addFilter = function($event) { |
|||
componentDialogService.openComponentDialog($event, true, false, |
|||
'rule.filter', types.componentType.filter).then( |
|||
function success(filter) { |
|||
scope.filters.push({ value: filter }); |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} |
|||
|
|||
scope.removeFilter = function ($event, filter) { |
|||
var index = scope.filters.indexOf(filter); |
|||
if (index > -1) { |
|||
scope.filters.splice(index, 1); |
|||
} |
|||
}; |
|||
|
|||
scope.addProcessor = function($event) { |
|||
componentDialogService.openComponentDialog($event, true, false, |
|||
'rule.processor', types.componentType.processor).then( |
|||
function success(processor) { |
|||
scope.rule.processor = processor; |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} |
|||
|
|||
scope.removeProcessor = function() { |
|||
if (scope.rule.processor) { |
|||
scope.rule.processor = null; |
|||
} |
|||
} |
|||
|
|||
scope.addAction = function($event) { |
|||
componentDialogService.openComponentDialog($event, true, false, |
|||
'rule.plugin-action', types.componentType.action, scope.plugin.clazz).then( |
|||
function success(action) { |
|||
scope.rule.action = action; |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} |
|||
|
|||
scope.removeAction = function() { |
|||
if (scope.rule.action) { |
|||
scope.rule.action = null; |
|||
} |
|||
} |
|||
|
|||
scope.updateValidity = function () { |
|||
if (scope.rule) { |
|||
var valid = scope.rule.filters && scope.rule.filters.length > 0; |
|||
scope.theForm.$setValidity('filters', valid); |
|||
var processorDefined = angular.isDefined(scope.rule.processor) && scope.rule.processor != null; |
|||
var pluginDefined = angular.isDefined(scope.rule.pluginToken) && scope.rule.pluginToken != null; |
|||
var pluginActionDefined = angular.isDefined(scope.rule.action) && scope.rule.action != null; |
|||
valid = processorDefined && !pluginDefined || (pluginDefined && pluginActionDefined); |
|||
scope.theForm.$setValidity('processorOrPlugin', valid); |
|||
} |
|||
}; |
|||
|
|||
scope.onRuleIdCopied = function() { |
|||
toast.showSuccess($translate.instant('rule.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); |
|||
}; |
|||
|
|||
scope.$watch('rule', function(newVal, prevVal) { |
|||
if (newVal) { |
|||
if (!scope.rule.filters) { |
|||
scope.rule.filters = []; |
|||
} |
|||
if (!angular.equals(newVal, prevVal)) { |
|||
if (scope.rule.pluginToken) { |
|||
pluginService.getPluginByToken(scope.rule.pluginToken).then( |
|||
function success(plugin) { |
|||
scope.plugin = plugin; |
|||
}, |
|||
function fail() {} |
|||
); |
|||
} else { |
|||
scope.plugin = null; |
|||
} |
|||
if (scope.filters) { |
|||
scope.filters.splice(0, scope.filters.length); |
|||
} else { |
|||
scope.filters = []; |
|||
} |
|||
if (scope.rule.filters) { |
|||
for (var i in scope.rule.filters) { |
|||
scope.filters.push({value: scope.rule.filters[i]}); |
|||
} |
|||
} |
|||
} |
|||
scope.updateValidity(); |
|||
} |
|||
} |
|||
); |
|||
|
|||
scope.$watch('filters', function (newVal, prevVal) { |
|||
if (scope.rule && scope.isEdit && !angular.equals(newVal, prevVal)) { |
|||
if (scope.rule.filters) { |
|||
scope.rule.filters.splice(0, scope.rule.filters.length); |
|||
} else { |
|||
scope.rule.filters = []; |
|||
} |
|||
if (scope.filters) { |
|||
for (var i in scope.filters) { |
|||
scope.rule.filters.push(scope.filters[i].value); |
|||
} |
|||
} |
|||
scope.theForm.$setDirty(); |
|||
scope.updateValidity(); |
|||
} |
|||
}, true); |
|||
|
|||
scope.$watch('plugin', function(newVal, prevVal) { |
|||
if (scope.rule && scope.isEdit && !angular.equals(newVal, prevVal)) { |
|||
if (newVal) { |
|||
scope.rule.pluginToken = scope.plugin.apiToken; |
|||
} else { |
|||
scope.rule.pluginToken = null; |
|||
} |
|||
scope.rule.action = null; |
|||
scope.updateValidity(); |
|||
} |
|||
}, true); |
|||
|
|||
scope.$watch('rule.processor', function(newVal, prevVal) { |
|||
if (scope.rule && scope.isEdit && !angular.equals(newVal, prevVal)) { |
|||
scope.theForm.$setDirty(); |
|||
scope.updateValidity(); |
|||
} |
|||
}, true); |
|||
|
|||
scope.$watch('rule.action', function(newVal, prevVal) { |
|||
if (scope.rule && scope.isEdit && !angular.equals(newVal, prevVal)) { |
|||
scope.theForm.$setDirty(); |
|||
scope.updateValidity(); |
|||
} |
|||
}, true); |
|||
|
|||
$compile(element.contents())(scope); |
|||
} |
|||
return { |
|||
restrict: "E", |
|||
link: linker, |
|||
scope: { |
|||
rule: '=', |
|||
isEdit: '=', |
|||
isReadOnly: '=', |
|||
theForm: '=', |
|||
onActivateRule: '&', |
|||
onSuspendRule: '&', |
|||
onExportRule: '&', |
|||
onDeleteRule: '&' |
|||
} |
|||
}; |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
/* |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
/* eslint-disable import/no-unresolved, import/default */ |
|||
|
|||
import rulesTemplate from './rules.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function RuleRoutes($stateProvider) { |
|||
|
|||
$stateProvider |
|||
.state('home.rules', { |
|||
url: '/rules', |
|||
params: {'topIndex': 0}, |
|||
module: 'private', |
|||
auth: ['SYS_ADMIN', 'TENANT_ADMIN'], |
|||
views: { |
|||
"content@home": { |
|||
templateUrl: rulesTemplate, |
|||
controllerAs: 'vm', |
|||
controller: 'RuleController' |
|||
} |
|||
}, |
|||
data: { |
|||
searchEnabled: true, |
|||
pageTitle: 'rule.rules' |
|||
}, |
|||
ncyBreadcrumb: { |
|||
label: '{"icon": "settings_ethernet", "label": "rule.rules"}' |
|||
} |
|||
}); |
|||
} |
|||
@ -1,55 +0,0 @@ |
|||
/** |
|||
* Copyright © 2016-2018 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. |
|||
*/ |
|||
.tb-rule { |
|||
min-width: 600px; |
|||
tb-plugin-select { |
|||
padding: 2px; |
|||
margin: 18px 0; |
|||
} |
|||
} |
|||
|
|||
.tb-filter { |
|||
min-width: 500px; |
|||
min-height: 300px; |
|||
} |
|||
|
|||
.tb-filters ul[dnd-list], |
|||
.tb-filters ul[dnd-list] > li { |
|||
position: relative; |
|||
} |
|||
|
|||
.tb-filters ul[dnd-list] { |
|||
min-height: 42px; |
|||
padding-left: 0px; |
|||
} |
|||
|
|||
.tb-filters ul[dnd-list] .dndDraggingSource { |
|||
display: none; |
|||
} |
|||
|
|||
.tb-filters ul[dnd-list] .dndPlaceholder { |
|||
display: block; |
|||
background-color: #ddd; |
|||
min-height: 42px; |
|||
} |
|||
|
|||
.tb-filters ul[dnd-list] li { |
|||
display: block; |
|||
} |
|||
|
|||
.tb-filters .handle { |
|||
cursor: move; |
|||
} |
|||
@ -1,77 +0,0 @@ |
|||
<!-- |
|||
|
|||
Copyright © 2016-2018 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. |
|||
|
|||
--> |
|||
<tb-grid grid-configuration="vm.ruleGridConfig"> |
|||
<details-buttons tb-help="'rules'" help-container-id="help-container"> |
|||
<div id="help-container"></div> |
|||
</details-buttons> |
|||
<md-tabs ng-class="{'tb-headless': (vm.grid.detailsConfig.isDetailsEditMode || !vm.isRuleEditable(vm.grid.operatingItem()))}" |
|||
id="tabs" md-border-bottom flex class="tb-absolute-fill"> |
|||
<md-tab label="{{ 'rule.details' | translate }}"> |
|||
<tb-rule rule="vm.grid.operatingItem()" |
|||
is-edit="vm.grid.detailsConfig.isDetailsEditMode" |
|||
is-read-only="vm.grid.isDetailsReadOnly(vm.grid.operatingItem())" |
|||
the-form="vm.grid.detailsForm" |
|||
on-activate-rule="vm.activateRule(event, vm.grid.detailsConfig.currentItem)" |
|||
on-suspend-rule="vm.suspendRule(event, vm.grid.detailsConfig.currentItem)" |
|||
on-export-rule="vm.exportRule(event, vm.grid.detailsConfig.currentItem)" |
|||
on-delete-rule="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-rule> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> |
|||
<tb-attribute-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.rule}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.attributesScope.server.value}}"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}"> |
|||
<tb-attribute-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.rule}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.latestTelemetry.value}}" |
|||
disable-attribute-scope-selection="true"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> |
|||
<tb-alarm-table flex entity-type="vm.types.entityType.rule" |
|||
entity-id="vm.grid.operatingItem().id.id"> |
|||
</tb-alarm-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'rule.events' | translate }}"> |
|||
<tb-event-table flex entity-type="vm.types.entityType.rule" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
tenant-id="vm.grid.operatingItem().tenantId.id" |
|||
default-event-type="{{vm.types.eventType.lcEvent.value}}"> |
|||
</tb-event-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem())" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> |
|||
<tb-relation-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-type="{{vm.types.entityType.rule}}"> |
|||
</tb-relation-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.isRuleEditable(vm.grid.operatingItem()) && vm.grid.isTenantAdmin()" |
|||
md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}"> |
|||
<tb-audit-log-table flex entity-type="vm.types.entityType.rule" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
audit-log-mode="{{vm.types.auditLogMode.entity}}"> |
|||
</tb-audit-log-table> |
|||
</md-tab> |
|||
</md-tabs> |
|||
</tb-grid> |
|||
Loading…
Reference in new issue