16 changed files with 1590 additions and 1 deletions
@ -0,0 +1,237 @@ |
|||
/* |
|||
* 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 thingsboardTypes from '../common/types.constant'; |
|||
|
|||
export default angular.module('thingsboard.api.entityView', [thingsboardTypes]) |
|||
.factory('entityViewService', EntityViewService) |
|||
.name; |
|||
|
|||
/*@ngInject*/ |
|||
function EntityViewService($http, $q, $window, userService, attributeService, customerService, types) { |
|||
|
|||
var service = { |
|||
assignEntityViewToCustomer: assignEntityViewToCustomer, |
|||
deleteEntityView: deleteEntityView, |
|||
getCustomerEntityViews: getCustomerEntityViews, |
|||
getEntityView: getEntityView, |
|||
getEntityViews: getEntityViews, |
|||
getTenantEntityViews: getTenantEntityViews, |
|||
saveEntityView: saveEntityView, |
|||
unassignEntityViewFromCustomer: unassignEntityViewFromCustomer, |
|||
getEntityViewAttributes: getEntityViewAttributes, |
|||
subscribeForEntityViewAttributes: subscribeForEntityViewAttributes, |
|||
unsubscribeForEntityViewAttributes: unsubscribeForEntityViewAttributes, |
|||
findByQuery: findByQuery, |
|||
getEntityViewTypes: getEntityViewTypes |
|||
} |
|||
|
|||
return service; |
|||
|
|||
function getTenantEntityViews(pageLink, applyCustomersInfo, config, type) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/tenant/entityViews?limit=' + pageLink.limit; |
|||
if (angular.isDefined(pageLink.textSearch)) { |
|||
url += '&textSearch=' + pageLink.textSearch; |
|||
} |
|||
if (angular.isDefined(pageLink.idOffset)) { |
|||
url += '&idOffset=' + pageLink.idOffset; |
|||
} |
|||
if (angular.isDefined(pageLink.textOffset)) { |
|||
url += '&textOffset=' + pageLink.textOffset; |
|||
} |
|||
if (angular.isDefined(type) && type.length) { |
|||
url += '&type=' + type; |
|||
} |
|||
$http.get(url, config).then(function success(response) { |
|||
if (applyCustomersInfo) { |
|||
customerService.applyAssignedCustomersInfo(response.data.data).then( |
|||
function success(data) { |
|||
response.data.data = data; |
|||
deferred.resolve(response.data); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
} else { |
|||
deferred.resolve(response.data); |
|||
} |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getCustomerEntityViews(customerId, pageLink, applyCustomersInfo, config, type) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/customer/' + customerId + '/entityViews?limit=' + pageLink.limit; |
|||
if (angular.isDefined(pageLink.textSearch)) { |
|||
url += '&textSearch=' + pageLink.textSearch; |
|||
} |
|||
if (angular.isDefined(pageLink.idOffset)) { |
|||
url += '&idOffset=' + pageLink.idOffset; |
|||
} |
|||
if (angular.isDefined(pageLink.textOffset)) { |
|||
url += '&textOffset=' + pageLink.textOffset; |
|||
} |
|||
if (angular.isDefined(type) && type.length) { |
|||
url += '&type=' + type; |
|||
} |
|||
$http.get(url, config).then(function success(response) { |
|||
if (applyCustomersInfo) { |
|||
customerService.applyAssignedCustomerInfo(response.data.data, customerId).then( |
|||
function success(data) { |
|||
response.data.data = data; |
|||
deferred.resolve(response.data); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
} else { |
|||
deferred.resolve(response.data); |
|||
} |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
|
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEntityView(entityViewId, ignoreErrors, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/entityView/' + entityViewId; |
|||
if (!config) { |
|||
config = {}; |
|||
} |
|||
config = Object.assign(config, { ignoreErrors: ignoreErrors }); |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEntityViews(entityViewIds, config) { |
|||
var deferred = $q.defer(); |
|||
var ids = ''; |
|||
for (var i=0;i<entityViewIds.length;i++) { |
|||
if (i>0) { |
|||
ids += ','; |
|||
} |
|||
ids += entityViewIds[i]; |
|||
} |
|||
var url = '/api/entityViews?entityViewIds=' + ids; |
|||
$http.get(url, config).then(function success(response) { |
|||
var entityViews = response.data; |
|||
entityViews.sort(function (entityView1, entityView2) { |
|||
var id1 = entityView1.id.id; |
|||
var id2 = entityView2.id.id; |
|||
var index1 = entityViewIds.indexOf(id1); |
|||
var index2 = entityViewIds.indexOf(id2); |
|||
return index1 - index2; |
|||
}); |
|||
deferred.resolve(entityViews); |
|||
}, function fail(response) { |
|||
deferred.reject(response.data); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function saveEntityView(entityView) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/entityView'; |
|||
$http.post(url, entityView).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function deleteEntityView(entityViewId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/entityView/' + entityViewId; |
|||
$http.delete(url).then(function success() { |
|||
deferred.resolve(); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function assignEntityViewToCustomer(customerId, entityViewId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/customer/' + customerId + '/entityView/' + entityViewId; |
|||
$http.post(url, null).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function unassignEntityViewFromCustomer(entityViewId) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/customer/entityView/' + entityViewId; |
|||
$http.delete(url).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEntityViewAttributes(entityViewId, attributeScope, query, successCallback, config) { |
|||
return attributeService.getEntityAttributes(types.entityType.entityView, entityViewId, attributeScope, query, successCallback, config); |
|||
} |
|||
|
|||
function subscribeForEntityViewAttributes(entityViewId, attributeScope) { |
|||
return attributeService.subscribeForEntityAttributes(types.entityType.entityView, entityViewId, attributeScope); |
|||
} |
|||
|
|||
function unsubscribeForEntityViewAttributes(subscriptionId) { |
|||
attributeService.unsubscribeForEntityAttributes(subscriptionId); |
|||
} |
|||
|
|||
function findByQuery(query, ignoreErrors, config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/entityViews'; |
|||
if (!config) { |
|||
config = {}; |
|||
} |
|||
config = Object.assign(config, { ignoreErrors: ignoreErrors }); |
|||
$http.post(url, query, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function getEntityViewTypes(config) { |
|||
var deferred = $q.defer(); |
|||
var url = '/api/entityView/types'; |
|||
$http.get(url, config).then(function success(response) { |
|||
deferred.resolve(response.data); |
|||
}, function fail() { |
|||
deferred.reject(); |
|||
}); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
<!-- |
|||
|
|||
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="{{ 'entity-view.add' | translate }}" tb-help="'entityViews'" help-container-id="help-container"> |
|||
<form name="theForm" ng-submit="vm.add()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>entity-view.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-entity-view entity-view="vm.item" is-edit="true" the-form="theForm"></tb-entity-view> |
|||
</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> |
|||
@ -0,0 +1,123 @@ |
|||
/* |
|||
* 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 AddEntityViewsToCustomerController(entityViewService, $mdDialog, $q, customerId, entityViews) { |
|||
|
|||
var vm = this; |
|||
|
|||
vm.entityViews = entityViews; |
|||
vm.searchText = ''; |
|||
|
|||
vm.assign = assign; |
|||
vm.cancel = cancel; |
|||
vm.hasData = hasData; |
|||
vm.noData = noData; |
|||
vm.searchEntityViewTextUpdated = searchEntityViewTextUpdated; |
|||
vm.toggleEntityViewSelection = toggleEntityViewSelection; |
|||
|
|||
vm.theEntityViews = { |
|||
getItemAtIndex: function (index) { |
|||
if (index > vm.entityViews.data.length) { |
|||
vm.theEntityViews.fetchMoreItems_(index); |
|||
return null; |
|||
} |
|||
var item = vm.entityViews.data[index]; |
|||
if (item) { |
|||
item.indexNumber = index + 1; |
|||
} |
|||
return item; |
|||
}, |
|||
|
|||
getLength: function () { |
|||
if (vm.entityViews.hasNext) { |
|||
return vm.entityViews.data.length + vm.entityViews.nextPageLink.limit; |
|||
} else { |
|||
return vm.entityViews.data.length; |
|||
} |
|||
}, |
|||
|
|||
fetchMoreItems_: function () { |
|||
if (vm.entityViews.hasNext && !vm.entityViews.pending) { |
|||
vm.entityViews.pending = true; |
|||
entityViewService.getTenantEntityViews(vm.entityViews.nextPageLink, false).then( |
|||
function success(entityViews) { |
|||
vm.entityViews.data = vm.entityViews.data.concat(entityViews.data); |
|||
vm.entityViews.nextPageLink = entityViews.nextPageLink; |
|||
vm.entityViews.hasNext = entityViews.hasNext; |
|||
if (vm.entityViews.hasNext) { |
|||
vm.entityViews.nextPageLink.limit = vm.entityViews.pageSize; |
|||
} |
|||
vm.entityViews.pending = false; |
|||
}, |
|||
function fail() { |
|||
vm.entityViews.hasNext = false; |
|||
vm.entityViews.pending = false; |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function cancel () { |
|||
$mdDialog.cancel(); |
|||
} |
|||
|
|||
function assign() { |
|||
var tasks = []; |
|||
for (var entityViewId in vm.entityViews.selections) { |
|||
tasks.push(entityViewService.assignEntityViewToCustomer(customerId, entityViewId)); |
|||
} |
|||
$q.all(tasks).then(function () { |
|||
$mdDialog.hide(); |
|||
}); |
|||
} |
|||
|
|||
function noData() { |
|||
return vm.entityViews.data.length == 0 && !vm.entityViews.hasNext; |
|||
} |
|||
|
|||
function hasData() { |
|||
return vm.entityViews.data.length > 0; |
|||
} |
|||
|
|||
function toggleEntityViewSelection($event, entityView) { |
|||
$event.stopPropagation(); |
|||
var selected = angular.isDefined(entityView.selected) && entityView.selected; |
|||
entityView.selected = !selected; |
|||
if (entityView.selected) { |
|||
vm.entityViews.selections[entityView.id.id] = true; |
|||
vm.entityViews.selectedCount++; |
|||
} else { |
|||
delete vm.entityViews.selections[entityView.id.id]; |
|||
vm.entityViews.selectedCount--; |
|||
} |
|||
} |
|||
|
|||
function searchEntityViewTextUpdated() { |
|||
vm.entityViews = { |
|||
pageSize: vm.entityViews.pageSize, |
|||
data: [], |
|||
nextPageLink: { |
|||
limit: vm.entityViews.pageSize, |
|||
textSearch: vm.searchText |
|||
}, |
|||
selections: {}, |
|||
selectedCount: 0, |
|||
hasNext: true, |
|||
pending: false |
|||
}; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,77 @@ |
|||
<!-- |
|||
|
|||
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="{{ 'entity-view.assign-to-customer' | translate }}"> |
|||
<form name="theForm" ng-submit="vm.assign()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>entity-view.assign-entity-view-to-customer</h2> |
|||
<span flex></span> |
|||
<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"> |
|||
<fieldset> |
|||
<span translate>entity-view.assign-entity-view-to-customer-text</span> |
|||
<md-input-container class="md-block" style='margin-bottom: 0px;'> |
|||
<label> </label> |
|||
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons"> |
|||
search |
|||
</md-icon> |
|||
<input id="entity-view-search" autofocus ng-model="vm.searchText" |
|||
ng-change="vm.searchEntityViewTextUpdated()" |
|||
placeholder="{{ 'common.enter-search' | translate }}"/> |
|||
</md-input-container> |
|||
<div style='min-height: 150px;'> |
|||
<span translate layout-align="center center" |
|||
style="text-transform: uppercase; display: flex; height: 150px;" |
|||
class="md-subhead" |
|||
ng-show="vm.noData()">entity-view.no-entity-views-text</span> |
|||
<md-virtual-repeat-container ng-show="vm.hasData()" |
|||
tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex |
|||
style='min-height: 150px; width: 100%;'> |
|||
<md-list> |
|||
<md-list-item md-virtual-repeat="entityView in vm.theEntityViews" md-on-demand |
|||
class="repeated-item" flex> |
|||
<md-checkbox ng-click="vm.toggleEntityViewSelection($event, entityView)" |
|||
aria-label="{{ 'item.selected' | translate }}" |
|||
ng-checked="entityView.selected"></md-checkbox> |
|||
<span> {{ entityView.name }} </span> |
|||
</md-list-item> |
|||
</md-list> |
|||
</md-virtual-repeat-container> |
|||
</div> |
|||
</fieldset> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-disabled="$root.loading || vm.entityViews.selectedCount == 0" type="submit" |
|||
class="md-raised md-primary"> |
|||
{{ 'action.assign' | 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> |
|||
@ -0,0 +1,123 @@ |
|||
/* |
|||
* 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 AssignEntityViewToCustomerController(customerService, entityViewService, $mdDialog, $q, entityViewIds, customers) { |
|||
|
|||
var vm = this; |
|||
|
|||
vm.customers = customers; |
|||
vm.searchText = ''; |
|||
|
|||
vm.assign = assign; |
|||
vm.cancel = cancel; |
|||
vm.isCustomerSelected = isCustomerSelected; |
|||
vm.hasData = hasData; |
|||
vm.noData = noData; |
|||
vm.searchCustomerTextUpdated = searchCustomerTextUpdated; |
|||
vm.toggleCustomerSelection = toggleCustomerSelection; |
|||
|
|||
vm.theCustomers = { |
|||
getItemAtIndex: function (index) { |
|||
if (index > vm.customers.data.length) { |
|||
vm.theCustomers.fetchMoreItems_(index); |
|||
return null; |
|||
} |
|||
var item = vm.customers.data[index]; |
|||
if (item) { |
|||
item.indexNumber = index + 1; |
|||
} |
|||
return item; |
|||
}, |
|||
|
|||
getLength: function () { |
|||
if (vm.customers.hasNext) { |
|||
return vm.customers.data.length + vm.customers.nextPageLink.limit; |
|||
} else { |
|||
return vm.customers.data.length; |
|||
} |
|||
}, |
|||
|
|||
fetchMoreItems_: function () { |
|||
if (vm.customers.hasNext && !vm.customers.pending) { |
|||
vm.customers.pending = true; |
|||
customerService.getCustomers(vm.customers.nextPageLink).then( |
|||
function success(customers) { |
|||
vm.customers.data = vm.customers.data.concat(customers.data); |
|||
vm.customers.nextPageLink = customers.nextPageLink; |
|||
vm.customers.hasNext = customers.hasNext; |
|||
if (vm.customers.hasNext) { |
|||
vm.customers.nextPageLink.limit = vm.customers.pageSize; |
|||
} |
|||
vm.customers.pending = false; |
|||
}, |
|||
function fail() { |
|||
vm.customers.hasNext = false; |
|||
vm.customers.pending = false; |
|||
}); |
|||
} |
|||
} |
|||
}; |
|||
|
|||
function cancel() { |
|||
$mdDialog.cancel(); |
|||
} |
|||
|
|||
function assign() { |
|||
var tasks = []; |
|||
for (var i=0; i < entityViewIds.length;i++) { |
|||
tasks.push(entityViewService.assignEntityViewToCustomer(vm.customers.selection.id.id, entityViewIds[i])); |
|||
} |
|||
$q.all(tasks).then(function () { |
|||
$mdDialog.hide(); |
|||
}); |
|||
} |
|||
|
|||
function noData() { |
|||
return vm.customers.data.length == 0 && !vm.customers.hasNext; |
|||
} |
|||
|
|||
function hasData() { |
|||
return vm.customers.data.length > 0; |
|||
} |
|||
|
|||
function toggleCustomerSelection($event, customer) { |
|||
$event.stopPropagation(); |
|||
if (vm.isCustomerSelected(customer)) { |
|||
vm.customers.selection = null; |
|||
} else { |
|||
vm.customers.selection = customer; |
|||
} |
|||
} |
|||
|
|||
function isCustomerSelected(customer) { |
|||
return vm.customers.selection != null && customer && |
|||
customer.id.id === vm.customers.selection.id.id; |
|||
} |
|||
|
|||
function searchCustomerTextUpdated() { |
|||
vm.customers = { |
|||
pageSize: vm.customers.pageSize, |
|||
data: [], |
|||
nextPageLink: { |
|||
limit: vm.customers.pageSize, |
|||
textSearch: vm.searchText |
|||
}, |
|||
selection: null, |
|||
hasNext: true, |
|||
pending: false |
|||
}; |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
<!-- |
|||
|
|||
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="{{ 'entity-view.assign-entity-view-to-customer' | translate }}"> |
|||
<form name="theForm" ng-submit="vm.assign()"> |
|||
<md-toolbar> |
|||
<div class="md-toolbar-tools"> |
|||
<h2 translate>entity-view.assign-entity-view-to-customer</h2> |
|||
<span flex></span> |
|||
<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"> |
|||
<fieldset> |
|||
<span translate>entity-view.assign-to-customer-text</span> |
|||
<md-input-container class="md-block" style='margin-bottom: 0px;'> |
|||
<label> </label> |
|||
<md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons"> |
|||
search |
|||
</md-icon> |
|||
<input id="customer-search" autofocus ng-model="vm.searchText" |
|||
ng-change="vm.searchCustomerTextUpdated()" |
|||
placeholder="{{ 'common.enter-search' | translate }}"/> |
|||
</md-input-container> |
|||
<div style='min-height: 150px;'> |
|||
<span translate layout-align="center center" |
|||
style="text-transform: uppercase; display: flex; height: 150px;" |
|||
class="md-subhead" |
|||
ng-show="vm.noData()">customer.no-customers-text</span> |
|||
<md-virtual-repeat-container ng-show="vm.hasData()" |
|||
tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex |
|||
style='min-height: 150px; width: 100%;'> |
|||
<md-list> |
|||
<md-list-item md-virtual-repeat="customer in vm.theCustomers" md-on-demand |
|||
class="repeated-item" flex> |
|||
<md-checkbox ng-click="vm.toggleCustomerSelection($event, customer)" |
|||
aria-label="{{ 'item.selected' | translate }}" |
|||
ng-checked="vm.isCustomerSelected(customer)"></md-checkbox> |
|||
<span> {{ customer.title }} </span> |
|||
</md-list-item> |
|||
</md-list> |
|||
</md-virtual-repeat-container> |
|||
</div> |
|||
</fieldset> |
|||
</div> |
|||
</md-dialog-content> |
|||
<md-dialog-actions layout="row"> |
|||
<span flex></span> |
|||
<md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> |
|||
{{ 'action.assign' | 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> |
|||
@ -0,0 +1,22 @@ |
|||
<!-- |
|||
|
|||
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 flex layout="column" style="margin-top: -10px;"> |
|||
<div style="text-transform: uppercase; padding-bottom: 5px;">{{vm.item.type}}</div> |
|||
<div class="tb-card-description">{{vm.item.additionalInfo.description}}</div> |
|||
<div style="padding-top: 5px;" class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'entity-view.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div> |
|||
</div> |
|||
@ -0,0 +1,64 @@ |
|||
<!-- |
|||
|
|||
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="onAssignToCustomer({event: $event})" |
|||
ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer" |
|||
class="md-raised md-primary">{{ 'entity-view.assign-to-customer' | translate }}</md-button> |
|||
<md-button ng-click="onUnassignFromCustomer({event: $event})" |
|||
ng-show="!isEdit && (entityViewScope === 'customer' || entityViewScope === 'tenant') && isAssignedToCustomer" |
|||
class="md-raised md-primary">{{'entity-view.unassign-from-customer' | translate }}</md-button> |
|||
<md-button ng-click="onDeleteEntityView({event: $event})" |
|||
ng-show="!isEdit && entityViewScope === 'tenant'" |
|||
class="md-raised md-primary">{{ 'entity-view.delete' | translate }}</md-button> |
|||
|
|||
<div layout="row"> |
|||
<md-button ngclipboard data-clipboard-action="copy" |
|||
ngclipboard-success="onEntityViewIdCopied(e)" |
|||
data-clipboard-text="{{entityView.id.id}}" ng-show="!isEdit" |
|||
class="md-raised"> |
|||
<md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon> |
|||
<span translate>entity-view.copyId</span> |
|||
</md-button> |
|||
</div> |
|||
|
|||
<md-content class="md-padding" layout="column"> |
|||
<md-input-container class="md-block" |
|||
ng-show="!isEdit && isAssignedToCustomer && entityViewScope === 'tenant'"> |
|||
<label translate>entity-view.assignedToCustomer</label> |
|||
<input ng-model="assignedCustomer.title" disabled> |
|||
</md-input-container> |
|||
<fieldset ng-disabled="$root.loading || !isEdit"> |
|||
<md-input-container class="md-block"> |
|||
<label translate>entity-view.name</label> |
|||
<input required name="name" ng-model="entityView.name"> |
|||
<div ng-messages="theForm.name.$error"> |
|||
<div translate ng-message="required">entity-view.name-required</div> |
|||
</div> |
|||
</md-input-container> |
|||
<tb-entity-subtype-autocomplete |
|||
ng-disabled="$root.loading || !isEdit" |
|||
tb-required="true" |
|||
the-form="theForm" |
|||
ng-model="entityView.type" |
|||
entity-type="types.entityType.entityview"> |
|||
</tb-entity-subtype-autocomplete> |
|||
<md-input-container class="md-block"> |
|||
<label translate>entity-view.description</label> |
|||
<textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea> |
|||
</md-input-container> |
|||
</fieldset> |
|||
</md-content> |
|||
@ -0,0 +1,483 @@ |
|||
/* |
|||
* 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 addEntityViewTemplate from './add-entity-view.tpl.html'; |
|||
import entityViewCard from './entity-view-card.tpl.html'; |
|||
import assignToCustomerTemplate from './assign-to-customer.tpl.html'; |
|||
import addEntityViewsToCustomerTemplate from './add-entity-views-to-customer.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export function EntityViewCardController(types) { |
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.isAssignedToCustomer = function() { |
|||
if (vm.item && vm.item.customerId && vm.parentCtl.entityViewsScope === 'tenant' && |
|||
vm.item.customerId.id != vm.types.id.nullUid && !vm.item.assignedCustomer.isPublic) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
vm.isPublic = function() { |
|||
if (vm.item && vm.item.assignedCustomer && vm.parentCtl.entityViewsScope === 'tenant' && vm.item.assignedCustomer.isPublic) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
|
|||
/*@ngInject*/ |
|||
export function EntityViewController($rootScope, userService, entityViewService, customerService, $state, $stateParams, |
|||
$document, $mdDialog, $q, $translate, types) { |
|||
|
|||
var customerId = $stateParams.customerId; |
|||
|
|||
var entityViewActionsList = []; |
|||
|
|||
var entityViewGroupActionsList = []; |
|||
|
|||
var vm = this; |
|||
|
|||
vm.types = types; |
|||
|
|||
vm.entityViewGridConfig = { |
|||
deleteItemTitleFunc: deleteEntityViewTitle, |
|||
deleteItemContentFunc: deleteEntityViewText, |
|||
deleteItemsTitleFunc: deleteEntityViewsTitle, |
|||
deleteItemsActionTitleFunc: deleteEntityViewsActionTitle, |
|||
deleteItemsContentFunc: deleteEntityViewsText, |
|||
|
|||
saveItemFunc: saveEntityView, |
|||
|
|||
getItemTitleFunc: getEntityViewTitle, |
|||
|
|||
itemCardController: 'EntityViewCardController', |
|||
itemCardTemplateUrl: entityViewCard, |
|||
parentCtl: vm, |
|||
|
|||
actionsList: entityViewActionsList, |
|||
groupActionsList: entityViewGroupActionsList, |
|||
|
|||
onGridInited: gridInited, |
|||
|
|||
addItemTemplateUrl: addEntityViewTemplate, |
|||
|
|||
addItemText: function() { return $translate.instant('entity-view.add-entity-view-text') }, |
|||
noItemsText: function() { return $translate.instant('entity-view.no-entity-views-text') }, |
|||
itemDetailsText: function() { return $translate.instant('entity-view.entity-view-details') }, |
|||
isDetailsReadOnly: isCustomerUser, |
|||
isSelectionEnabled: function () { |
|||
return !isCustomerUser(); |
|||
} |
|||
}; |
|||
|
|||
if (angular.isDefined($stateParams.items) && $stateParams.items !== null) { |
|||
vm.entityViewGridConfig.items = $stateParams.items; |
|||
} |
|||
|
|||
if (angular.isDefined($stateParams.topIndex) && $stateParams.topIndex > 0) { |
|||
vm.entityViewGridConfig.topIndex = $stateParams.topIndex; |
|||
} |
|||
|
|||
vm.entityViewsScope = $state.$current.data.entityViewsType; |
|||
|
|||
vm.assignToCustomer = assignToCustomer; |
|||
vm.makePublic = makePublic; |
|||
vm.unassignFromCustomer = unassignFromCustomer; |
|||
|
|||
initController(); |
|||
|
|||
function initController() { |
|||
var fetchEntityViewsFunction = null; |
|||
var deleteEntityViewFunction = null; |
|||
var refreshEntityViewsParamsFunction = null; |
|||
|
|||
var user = userService.getCurrentUser(); |
|||
|
|||
if (user.authority === 'CUSTOMER_USER') { |
|||
vm.entityViewsScope = 'customer_user'; |
|||
customerId = user.customerId; |
|||
} |
|||
if (customerId) { |
|||
vm.customerEntityViewsTitle = $translate.instant('customer.entity-views'); |
|||
customerService.getShortCustomerInfo(customerId).then( |
|||
function success(info) { |
|||
if (info.isPublic) { |
|||
vm.customerEntityViewsTitle = $translate.instant('customer.public-entity-views'); |
|||
} |
|||
} |
|||
); |
|||
} |
|||
|
|||
if (vm.entityViewsScope === 'tenant') { |
|||
fetchEntityViewsFunction = function (pageLink, entityViewType) { |
|||
return entityViewService.getTenantEntityViews(pageLink, true, null, entityViewType); |
|||
}; |
|||
deleteEntityViewFunction = function (entityViewId) { |
|||
return entityViewService.deleteEntityView(entityViewId); |
|||
}; |
|||
refreshEntityViewsParamsFunction = function() { |
|||
return {"topIndex": vm.topIndex}; |
|||
}; |
|||
|
|||
entityViewActionsList.push( |
|||
{ |
|||
onAction: function ($event, item) { |
|||
assignToCustomer($event, [ item.id.id ]); |
|||
}, |
|||
name: function() { return $translate.instant('action.assign') }, |
|||
details: function() { return $translate.instant('entity-view.assign-to-customer') }, |
|||
icon: "assignment_ind", |
|||
isEnabled: function(entityView) { |
|||
return entityView && (!entityView.customerId || entityView.customerId.id === types.id.nullUid); |
|||
} |
|||
} |
|||
); |
|||
|
|||
entityViewActionsList.push( |
|||
{ |
|||
onAction: function ($event, item) { |
|||
unassignFromCustomer($event, item, false); |
|||
}, |
|||
name: function() { return $translate.instant('action.unassign') }, |
|||
details: function() { return $translate.instant('entity-view.unassign-from-customer') }, |
|||
icon: "assignment_return", |
|||
isEnabled: function(entityView) { |
|||
return entityView && entityView.customerId && entityView.customerId.id !== types.id.nullUid && !entityView.assignedCustomer.isPublic; |
|||
} |
|||
} |
|||
); |
|||
|
|||
entityViewActionsList.push({ |
|||
onAction: function ($event, item) { |
|||
unassignFromCustomer($event, item, true); |
|||
}, |
|||
name: function() { return $translate.instant('action.make-private') }, |
|||
details: function() { return $translate.instant('entity-view.make-private') }, |
|||
icon: "reply", |
|||
isEnabled: function(entityView) { |
|||
return entityView && entityView.customerId && entityView.customerId.id !== types.id.nullUid && entityView.assignedCustomer.isPublic; |
|||
} |
|||
}); |
|||
|
|||
entityViewActionsList.push( |
|||
{ |
|||
onAction: function ($event, item) { |
|||
vm.grid.deleteItem($event, item); |
|||
}, |
|||
name: function() { return $translate.instant('action.delete') }, |
|||
details: function() { return $translate.instant('entity-view.delete') }, |
|||
icon: "delete" |
|||
} |
|||
); |
|||
|
|||
entityViewGroupActionsList.push( |
|||
{ |
|||
onAction: function ($event, items) { |
|||
assignEntiyViewsToCustomer($event, items); |
|||
}, |
|||
name: function() { return $translate.instant('entity-view.assign-entity-views') }, |
|||
details: function(selectedCount) { |
|||
return $translate.instant('entity-view.assign-entity-views-text', {count: selectedCount}, "messageformat"); |
|||
}, |
|||
icon: "assignment_ind" |
|||
} |
|||
); |
|||
|
|||
entityViewGroupActionsList.push( |
|||
{ |
|||
onAction: function ($event) { |
|||
vm.grid.deleteItems($event); |
|||
}, |
|||
name: function() { return $translate.instant('entity-view.delete-entity-views') }, |
|||
details: deleteEntityViewsActionTitle, |
|||
icon: "delete" |
|||
} |
|||
); |
|||
|
|||
|
|||
|
|||
} else if (vm.entityViewsScope === 'customer' || vm.entityViewsScope === 'customer_user') { |
|||
fetchEntityViewsFunction = function (pageLink, entityViewType) { |
|||
return entityViewService.getCustomerEntityViews(customerId, pageLink, true, null, entityViewType); |
|||
}; |
|||
deleteentityViewFunction = function (entityViewId) { |
|||
return entityViewService.unassignEntityViewFromCustomer(entityViewId); |
|||
}; |
|||
refreshentityViewsParamsFunction = function () { |
|||
return {"customerId": customerId, "topIndex": vm.topIndex}; |
|||
}; |
|||
|
|||
if (vm.entityViewsScope === 'customer') { |
|||
entityViewActionsList.push( |
|||
{ |
|||
onAction: function ($event, item) { |
|||
unassignFromCustomer($event, item, false); |
|||
}, |
|||
name: function() { return $translate.instant('action.unassign') }, |
|||
details: function() { return $translate.instant('entity-view.unassign-from-customer') }, |
|||
icon: "assignment_return", |
|||
isEnabled: function(entityView) { |
|||
return entityView && !entityView.assignedCustomer.isPublic; |
|||
} |
|||
} |
|||
); |
|||
|
|||
entityViewGroupActionsList.push( |
|||
{ |
|||
onAction: function ($event, items) { |
|||
unassignEntityViewsFromCustomer($event, items); |
|||
}, |
|||
name: function() { return $translate.instant('entity-view.unassign-entity-views') }, |
|||
details: function(selectedCount) { |
|||
return $translate.instant('entity-view.unassign-entity-views-action-title', {count: selectedCount}, "messageformat"); |
|||
}, |
|||
icon: "assignment_return" |
|||
} |
|||
); |
|||
|
|||
vm.entityViewGridConfig.addItemAction = { |
|||
onAction: function ($event) { |
|||
addEntityViewsToCustomer($event); |
|||
}, |
|||
name: function() { return $translate.instant('entity-view.assign-entity-views') }, |
|||
details: function() { return $translate.instant('entity-view.assign-new-entity-view') }, |
|||
icon: "add" |
|||
}; |
|||
|
|||
|
|||
} else if (vm.entityViewsScope === 'customer_user') { |
|||
vm.entityViewGridConfig.addItemAction = {}; |
|||
} |
|||
} |
|||
|
|||
vm.entityViewGridConfig.refreshParamsFunc = refreshentityViewsParamsFunction; |
|||
vm.entityViewGridConfig.fetchItemsFunc = fetchentityViewsFunction; |
|||
vm.entityViewGridConfig.deleteItemFunc = deleteentityViewFunction; |
|||
|
|||
} |
|||
|
|||
function deleteEntityViewTitle(entityView) { |
|||
return $translate.instant('entity-view.delete-entity-view-title', {entityViewName: entityView.name}); |
|||
} |
|||
|
|||
function deleteEntityViewText() { |
|||
return $translate.instant('entity-view.delete-entity-view-text'); |
|||
} |
|||
|
|||
function deleteEntityViewsTitle(selectedCount) { |
|||
return $translate.instant('entity-view.delete-entity-views-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteEntityViewsActionTitle(selectedCount) { |
|||
return $translate.instant('entity-view.delete-entity-views-action-title', {count: selectedCount}, 'messageformat'); |
|||
} |
|||
|
|||
function deleteEntityViewsText () { |
|||
return $translate.instant('entity-view.delete-entity-views-text'); |
|||
} |
|||
|
|||
function gridInited(grid) { |
|||
vm.grid = grid; |
|||
} |
|||
|
|||
function getEntityViewTitle(entityView) { |
|||
return entityView ? entityView.name : ''; |
|||
} |
|||
|
|||
function saveEntityView(entityView) { |
|||
var deferred = $q.defer(); |
|||
entityViewService.saveEntityView(entityView).then( |
|||
function success(savedEntityView) { |
|||
$rootScope.$broadcast('entityViewSaved'); |
|||
var entityViews = [ savedEntityView ]; |
|||
customerService.applyAssignedCustomersInfo(entityViews).then( |
|||
function success(items) { |
|||
if (items && items.length == 1) { |
|||
deferred.resolve(items[0]); |
|||
} else { |
|||
deferred.reject(); |
|||
} |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
}, |
|||
function fail() { |
|||
deferred.reject(); |
|||
} |
|||
); |
|||
return deferred.promise; |
|||
} |
|||
|
|||
function isCustomerUser() { |
|||
return vm.entityViewsScope === 'customer_user'; |
|||
} |
|||
|
|||
function assignToCustomer($event, entityViewIds) { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
var pageSize = 10; |
|||
customerService.getCustomers({limit: pageSize, textSearch: ''}).then( |
|||
function success(_customers) { |
|||
var customers = { |
|||
pageSize: pageSize, |
|||
data: _customers.data, |
|||
nextPageLink: _customers.nextPageLink, |
|||
selection: null, |
|||
hasNext: _customers.hasNext, |
|||
pending: false |
|||
}; |
|||
if (customers.hasNext) { |
|||
customers.nextPageLink.limit = pageSize; |
|||
} |
|||
$mdDialog.show({ |
|||
controller: 'AssignEntityViewToCustomerController', |
|||
controllerAs: 'vm', |
|||
templateUrl: assignToCustomerTemplate, |
|||
locals: {entityViewIds: entityViewIds, customers: customers}, |
|||
parent: angular.element($document[0].body), |
|||
fullscreen: true, |
|||
targetEvent: $event |
|||
}).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
}, |
|||
function fail() { |
|||
}); |
|||
} |
|||
|
|||
function addEntityViewsToCustomer($event) { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
var pageSize = 10; |
|||
entityViewService.getTenantEntityViews({limit: pageSize, textSearch: ''}, false).then( |
|||
function success(_entityViews) { |
|||
var entityViews = { |
|||
pageSize: pageSize, |
|||
data: _entityViews.data, |
|||
nextPageLink: _entityViews.nextPageLink, |
|||
selections: {}, |
|||
selectedCount: 0, |
|||
hasNext: _entityViews.hasNext, |
|||
pending: false |
|||
}; |
|||
if (entityViews.hasNext) { |
|||
entityViews.nextPageLink.limit = pageSize; |
|||
} |
|||
$mdDialog.show({ |
|||
controller: 'AddEntityViewsToCustomerController', |
|||
controllerAs: 'vm', |
|||
templateUrl: addEntityViewsToCustomerTemplate, |
|||
locals: {customerId: customerId, entityViews: entityViews}, |
|||
parent: angular.element($document[0].body), |
|||
fullscreen: true, |
|||
targetEvent: $event |
|||
}).then(function () { |
|||
vm.grid.refreshList(); |
|||
}, function () { |
|||
}); |
|||
}, |
|||
function fail() { |
|||
}); |
|||
} |
|||
|
|||
function assignEntityViewsToCustomer($event, items) { |
|||
var entityViewIds = []; |
|||
for (var id in items.selections) { |
|||
entityViewIds.push(id); |
|||
} |
|||
assignToCustomer($event, entityViewIds); |
|||
} |
|||
|
|||
function unassignFromCustomer($event, entityView, isPublic) { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
var title; |
|||
var content; |
|||
var label; |
|||
if (isPublic) { |
|||
title = $translate.instant('entity-view.make-private-entity-view-title', {entityViewName: entityView.name}); |
|||
content = $translate.instant('entity-view.make-private-entity-view-text'); |
|||
label = $translate.instant('entity-view.make-private'); |
|||
} else { |
|||
title = $translate.instant('entity-view.unassign-entity-view-title', {entityViewName: entityView.name}); |
|||
content = $translate.instant('entity-view.unassign-entity-view-text'); |
|||
label = $translate.instant('entity-view.unassign-entity-view'); |
|||
} |
|||
var confirm = $mdDialog.confirm() |
|||
.targetEvent($event) |
|||
.title(title) |
|||
.htmlContent(content) |
|||
.ariaLabel(label) |
|||
.cancel($translate.instant('action.no')) |
|||
.ok($translate.instant('action.yes')); |
|||
$mdDialog.show(confirm).then(function () { |
|||
entityViewService.unassignEntityViewFromCustomer(entityView.id.id).then(function success() { |
|||
vm.grid.refreshList(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
function unassignEntityViewsFromCustomer($event, items) { |
|||
var confirm = $mdDialog.confirm() |
|||
.targetEvent($event) |
|||
.title($translate.instant('entity-view.unassign-entity-views-title', {count: items.selectedCount}, 'messageformat')) |
|||
.htmlContent($translate.instant('entity-view.unassign-entity-views-text')) |
|||
.ariaLabel($translate.instant('entity-view.unassign-entity-view')) |
|||
.cancel($translate.instant('action.no')) |
|||
.ok($translate.instant('action.yes')); |
|||
$mdDialog.show(confirm).then(function () { |
|||
var tasks = []; |
|||
for (var id in items.selections) { |
|||
tasks.push(entityViewService.unassignEntityViewFromCustomer(id)); |
|||
} |
|||
$q.all(tasks).then(function () { |
|||
vm.grid.refreshList(); |
|||
}); |
|||
}); |
|||
} |
|||
|
|||
function makePublic($event, entityView) { |
|||
if ($event) { |
|||
$event.stopPropagation(); |
|||
} |
|||
var confirm = $mdDialog.confirm() |
|||
.targetEvent($event) |
|||
.title($translate.instant('entity-view.make-public-entity-view-title', {entityViewName: entityView.name})) |
|||
.htmlContent($translate.instant('entity-view.make-public-entity-view-text')) |
|||
.ariaLabel($translate.instant('entity-view.make-public')) |
|||
.cancel($translate.instant('action.no')) |
|||
.ok($translate.instant('action.yes')); |
|||
$mdDialog.show(confirm).then(function () { |
|||
entityViewService.makeEntityViewPublic(entityView.id.id).then(function success() { |
|||
vm.grid.refreshList(); |
|||
}); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
/* |
|||
* 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 entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function EntityViewDirective($compile, $templateCache, toast, $translate, types, clipboardService, entityViewService, customerService) { |
|||
var linker = function (scope, element) { |
|||
var template = $templateCache.get(entityViewFieldsetTemplate); |
|||
element.html(template); |
|||
|
|||
scope.types = types; |
|||
scope.isAssignedToCustomer = false; |
|||
scope.assignedCustomer = null; |
|||
|
|||
scope.$watch('entityView', function(newVal) { |
|||
if (newVal) { |
|||
if (scope.entityView.customerId && scope.entityView.customerId.id !== types.id.nullUid) { |
|||
scope.isAssignedToCustomer = true; |
|||
customerService.getShortCustomerInfo(scope.entityView.customerId.id).then( |
|||
function success(customer) { |
|||
scope.assignedCustomer = customer; |
|||
} |
|||
); |
|||
} else { |
|||
scope.isAssignedToCustomer = false; |
|||
scope.assignedCustomer = null; |
|||
} |
|||
} |
|||
}); |
|||
|
|||
scope.onEntityViewIdCopied = function() { |
|||
toast.showSuccess($translate.instant('entity-view.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); |
|||
}; |
|||
|
|||
$compile(element.contents())(scope); |
|||
} |
|||
return { |
|||
restrict: "E", |
|||
link: linker, |
|||
scope: { |
|||
entityView: '=', |
|||
isEdit: '=', |
|||
entityViewScope: '=', |
|||
theForm: '=', |
|||
onAssignToCustomer: '&', |
|||
onUnassignFromCustomer: '&', |
|||
onDeleteEntityView: '&' |
|||
} |
|||
}; |
|||
} |
|||
@ -0,0 +1,72 @@ |
|||
/* |
|||
* 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 entityViewsTemplate from './entity-views.tpl.html'; |
|||
|
|||
/* eslint-enable import/no-unresolved, import/default */ |
|||
|
|||
/*@ngInject*/ |
|||
export default function EntityViewRoutes($stateProvider, types) { |
|||
$stateProvider |
|||
.state('home.entityViews', { |
|||
url: '/entityViews', |
|||
params: {'topIndex': 0}, |
|||
module: 'private', |
|||
auth: ['TENANT_ADMIN', 'CUSTOMER_USER'], |
|||
views: { |
|||
"content@home": { |
|||
templateUrl: entityViewsTemplate, |
|||
controller: 'EntityViewController', |
|||
controllerAs: 'vm' |
|||
} |
|||
}, |
|||
data: { |
|||
entityViewsTypes: 'tenant', |
|||
searchEnabled: true, |
|||
searchByEntitySubtype: true, |
|||
searchEntityType: types.entityType.entityview, |
|||
pageTitle: 'entity-views.entity-views' |
|||
}, |
|||
ncyBreadcrumb: { |
|||
label: '{"icon": "devices_other", "label": "entity-view.entity-views"}' |
|||
} |
|||
}) |
|||
.state('home.customers.entityViews', { |
|||
url: '/:customerId/entityViews', |
|||
params: {'topIndex': 0}, |
|||
module: 'private', |
|||
auth: ['TENANT_ADMIN'], |
|||
views: { |
|||
"content@home": { |
|||
templateUrl: entityViewsTemplate, |
|||
controllerAs: 'vm', |
|||
controller: 'EntityViewController' |
|||
} |
|||
}, |
|||
data: { |
|||
entityViewsTypes: 'customer', |
|||
searchEnabled: true, |
|||
searchByEntitySubtype: true, |
|||
searchEntityType: types.entityType.entityview, |
|||
pageTitle: 'customer.entity-views' |
|||
}, |
|||
ncyBreadcrumb: { |
|||
label: '{"icon": "devices_other", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}' |
|||
} |
|||
}); |
|||
|
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
<!-- |
|||
|
|||
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.entityViewGridConfig"> |
|||
<details-buttons tb-help="'entityViews'" help-container-id="help-container"> |
|||
<div id="help-container"></div> |
|||
</details-buttons> |
|||
<md-tabs ng-class="{'tb-headless': vm.grid.detailsConfig.isDetailsEditMode}" |
|||
id="tabs" md-border-bottom flex class="tb-absolute-fill"> |
|||
<md-tab label="{{ 'entity-view.details' | translate }}"> |
|||
<tb-entity-view entity-view="vm.grid.operatingItem()" |
|||
is-edit="vm.grid.detailsConfig.isDetailsEditMode" |
|||
entity-view-scope="vm.entityViewsScope" |
|||
the-form="vm.grid.detailsForm" |
|||
on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])" |
|||
on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)" |
|||
on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)" |
|||
on-manage-credentials="vm.manageCredentials(event, vm.grid.detailsConfig.currentItem)" |
|||
on-delete-entity-view="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-entity-view> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" 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.entityview}}" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
default-attribute-scope="{{vm.types.attributesScope.client.value}}"> |
|||
</tb-attribute-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" 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.entityview}}" |
|||
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" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> |
|||
<tb-alarm-table flex entity-type="vm.types.entityType.entityview" |
|||
entity-id="vm.grid.operatingItem().id.id"> |
|||
</tb-alarm-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'entity-view.events' | translate }}"> |
|||
<tb-event-table flex entity-type="vm.types.entityType.entityview" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
tenant-id="vm.grid.operatingItem().tenantId.id" |
|||
default-event-type="{{vm.types.eventType.error.value}}"> |
|||
</tb-event-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" 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.entityview}}"> |
|||
</tb-relation-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.operatingItem().additionalInfo.gateway" md-on-select="vm.grid.triggerResize()" label="{{ 'extension.extensions' | translate }}"> |
|||
<tb-extension-table flex |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
entity-name="vm.grid.operatingItem().name" |
|||
entity-type="{{vm.types.entityType.entityview}}"> |
|||
</tb-extension-table> |
|||
</md-tab> |
|||
<md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && 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.entityview" |
|||
entity-id="vm.grid.operatingItem().id.id" |
|||
audit-log-mode="{{vm.types.auditLogMode.entity}}"> |
|||
</tb-audit-log-table> |
|||
</md-tab> |
|||
</tb-grid> |
|||
@ -0,0 +1,41 @@ |
|||
/* |
|||
* 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 thingsboardApiUser from '../api/user.service'; |
|||
import thingsboardApiEntityView from '../api/entity-view.service'; |
|||
import thingsboardApiCustomer from '../api/customer.service'; |
|||
|
|||
import EntityViewRoutes from './entity-view.routes'; |
|||
import EntityViewCardController from './entity-view.controller'; |
|||
import AssignEntityViewToCustomerController from './assign-to-customer.controller'; |
|||
import AddEntityViewsToCustomerController from './add-entity-views-to-customer.controller'; |
|||
import EntityViewDirective from './entity-view.directive'; |
|||
|
|||
export default angular.module('thingsboard.entityView', [ |
|||
uiRouter, |
|||
thingsboardGrid, |
|||
thingsboardApiUser, |
|||
thingsboardApiEntityView, |
|||
thingsboardApiCustomer |
|||
]) |
|||
.config(EntityViewRoutes) |
|||
.controller('EntityViewController', EntityViewCardController) |
|||
.controller('EntityViewCardController', EntityViewCardController) |
|||
.controller('AssignEntityViewToCustomerController', AssignEntityViewToCustomerController) |
|||
.controller('AddEntityViewsToCustomerController', AddEntityViewsToCustomerController) |
|||
.directive('tbEntityView', EntityViewDirective) |
|||
.name; |
|||
Loading…
Reference in new issue