Showing
16 changed files
with
1590 additions
and
1 deletions
ui/src/app/api/entity-view.service.js
0 → 100644
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +import thingsboardTypes from '../common/types.constant'; | |
17 | + | |
18 | +export default angular.module('thingsboard.api.entityView', [thingsboardTypes]) | |
19 | + .factory('entityViewService', EntityViewService) | |
20 | + .name; | |
21 | + | |
22 | +/*@ngInject*/ | |
23 | +function EntityViewService($http, $q, $window, userService, attributeService, customerService, types) { | |
24 | + | |
25 | + var service = { | |
26 | + assignEntityViewToCustomer: assignEntityViewToCustomer, | |
27 | + deleteEntityView: deleteEntityView, | |
28 | + getCustomerEntityViews: getCustomerEntityViews, | |
29 | + getEntityView: getEntityView, | |
30 | + getEntityViews: getEntityViews, | |
31 | + getTenantEntityViews: getTenantEntityViews, | |
32 | + saveEntityView: saveEntityView, | |
33 | + unassignEntityViewFromCustomer: unassignEntityViewFromCustomer, | |
34 | + getEntityViewAttributes: getEntityViewAttributes, | |
35 | + subscribeForEntityViewAttributes: subscribeForEntityViewAttributes, | |
36 | + unsubscribeForEntityViewAttributes: unsubscribeForEntityViewAttributes, | |
37 | + findByQuery: findByQuery, | |
38 | + getEntityViewTypes: getEntityViewTypes | |
39 | + } | |
40 | + | |
41 | + return service; | |
42 | + | |
43 | + function getTenantEntityViews(pageLink, applyCustomersInfo, config, type) { | |
44 | + var deferred = $q.defer(); | |
45 | + var url = '/api/tenant/entityViews?limit=' + pageLink.limit; | |
46 | + if (angular.isDefined(pageLink.textSearch)) { | |
47 | + url += '&textSearch=' + pageLink.textSearch; | |
48 | + } | |
49 | + if (angular.isDefined(pageLink.idOffset)) { | |
50 | + url += '&idOffset=' + pageLink.idOffset; | |
51 | + } | |
52 | + if (angular.isDefined(pageLink.textOffset)) { | |
53 | + url += '&textOffset=' + pageLink.textOffset; | |
54 | + } | |
55 | + if (angular.isDefined(type) && type.length) { | |
56 | + url += '&type=' + type; | |
57 | + } | |
58 | + $http.get(url, config).then(function success(response) { | |
59 | + if (applyCustomersInfo) { | |
60 | + customerService.applyAssignedCustomersInfo(response.data.data).then( | |
61 | + function success(data) { | |
62 | + response.data.data = data; | |
63 | + deferred.resolve(response.data); | |
64 | + }, | |
65 | + function fail() { | |
66 | + deferred.reject(); | |
67 | + } | |
68 | + ); | |
69 | + } else { | |
70 | + deferred.resolve(response.data); | |
71 | + } | |
72 | + }, function fail() { | |
73 | + deferred.reject(); | |
74 | + }); | |
75 | + return deferred.promise; | |
76 | + } | |
77 | + | |
78 | + function getCustomerEntityViews(customerId, pageLink, applyCustomersInfo, config, type) { | |
79 | + var deferred = $q.defer(); | |
80 | + var url = '/api/customer/' + customerId + '/entityViews?limit=' + pageLink.limit; | |
81 | + if (angular.isDefined(pageLink.textSearch)) { | |
82 | + url += '&textSearch=' + pageLink.textSearch; | |
83 | + } | |
84 | + if (angular.isDefined(pageLink.idOffset)) { | |
85 | + url += '&idOffset=' + pageLink.idOffset; | |
86 | + } | |
87 | + if (angular.isDefined(pageLink.textOffset)) { | |
88 | + url += '&textOffset=' + pageLink.textOffset; | |
89 | + } | |
90 | + if (angular.isDefined(type) && type.length) { | |
91 | + url += '&type=' + type; | |
92 | + } | |
93 | + $http.get(url, config).then(function success(response) { | |
94 | + if (applyCustomersInfo) { | |
95 | + customerService.applyAssignedCustomerInfo(response.data.data, customerId).then( | |
96 | + function success(data) { | |
97 | + response.data.data = data; | |
98 | + deferred.resolve(response.data); | |
99 | + }, | |
100 | + function fail() { | |
101 | + deferred.reject(); | |
102 | + } | |
103 | + ); | |
104 | + } else { | |
105 | + deferred.resolve(response.data); | |
106 | + } | |
107 | + }, function fail() { | |
108 | + deferred.reject(); | |
109 | + }); | |
110 | + | |
111 | + return deferred.promise; | |
112 | + } | |
113 | + | |
114 | + function getEntityView(entityViewId, ignoreErrors, config) { | |
115 | + var deferred = $q.defer(); | |
116 | + var url = '/api/entityView/' + entityViewId; | |
117 | + if (!config) { | |
118 | + config = {}; | |
119 | + } | |
120 | + config = Object.assign(config, { ignoreErrors: ignoreErrors }); | |
121 | + $http.get(url, config).then(function success(response) { | |
122 | + deferred.resolve(response.data); | |
123 | + }, function fail(response) { | |
124 | + deferred.reject(response.data); | |
125 | + }); | |
126 | + return deferred.promise; | |
127 | + } | |
128 | + | |
129 | + function getEntityViews(entityViewIds, config) { | |
130 | + var deferred = $q.defer(); | |
131 | + var ids = ''; | |
132 | + for (var i=0;i<entityViewIds.length;i++) { | |
133 | + if (i>0) { | |
134 | + ids += ','; | |
135 | + } | |
136 | + ids += entityViewIds[i]; | |
137 | + } | |
138 | + var url = '/api/entityViews?entityViewIds=' + ids; | |
139 | + $http.get(url, config).then(function success(response) { | |
140 | + var entityViews = response.data; | |
141 | + entityViews.sort(function (entityView1, entityView2) { | |
142 | + var id1 = entityView1.id.id; | |
143 | + var id2 = entityView2.id.id; | |
144 | + var index1 = entityViewIds.indexOf(id1); | |
145 | + var index2 = entityViewIds.indexOf(id2); | |
146 | + return index1 - index2; | |
147 | + }); | |
148 | + deferred.resolve(entityViews); | |
149 | + }, function fail(response) { | |
150 | + deferred.reject(response.data); | |
151 | + }); | |
152 | + return deferred.promise; | |
153 | + } | |
154 | + | |
155 | + function saveEntityView(entityView) { | |
156 | + var deferred = $q.defer(); | |
157 | + var url = '/api/entityView'; | |
158 | + $http.post(url, entityView).then(function success(response) { | |
159 | + deferred.resolve(response.data); | |
160 | + }, function fail() { | |
161 | + deferred.reject(); | |
162 | + }); | |
163 | + return deferred.promise; | |
164 | + } | |
165 | + | |
166 | + function deleteEntityView(entityViewId) { | |
167 | + var deferred = $q.defer(); | |
168 | + var url = '/api/entityView/' + entityViewId; | |
169 | + $http.delete(url).then(function success() { | |
170 | + deferred.resolve(); | |
171 | + }, function fail() { | |
172 | + deferred.reject(); | |
173 | + }); | |
174 | + return deferred.promise; | |
175 | + } | |
176 | + | |
177 | + function assignEntityViewToCustomer(customerId, entityViewId) { | |
178 | + var deferred = $q.defer(); | |
179 | + var url = '/api/customer/' + customerId + '/entityView/' + entityViewId; | |
180 | + $http.post(url, null).then(function success(response) { | |
181 | + deferred.resolve(response.data); | |
182 | + }, function fail() { | |
183 | + deferred.reject(); | |
184 | + }); | |
185 | + return deferred.promise; | |
186 | + } | |
187 | + | |
188 | + function unassignEntityViewFromCustomer(entityViewId) { | |
189 | + var deferred = $q.defer(); | |
190 | + var url = '/api/customer/entityView/' + entityViewId; | |
191 | + $http.delete(url).then(function success(response) { | |
192 | + deferred.resolve(response.data); | |
193 | + }, function fail() { | |
194 | + deferred.reject(); | |
195 | + }); | |
196 | + return deferred.promise; | |
197 | + } | |
198 | + | |
199 | + function getEntityViewAttributes(entityViewId, attributeScope, query, successCallback, config) { | |
200 | + return attributeService.getEntityAttributes(types.entityType.entityView, entityViewId, attributeScope, query, successCallback, config); | |
201 | + } | |
202 | + | |
203 | + function subscribeForEntityViewAttributes(entityViewId, attributeScope) { | |
204 | + return attributeService.subscribeForEntityAttributes(types.entityType.entityView, entityViewId, attributeScope); | |
205 | + } | |
206 | + | |
207 | + function unsubscribeForEntityViewAttributes(subscriptionId) { | |
208 | + attributeService.unsubscribeForEntityAttributes(subscriptionId); | |
209 | + } | |
210 | + | |
211 | + function findByQuery(query, ignoreErrors, config) { | |
212 | + var deferred = $q.defer(); | |
213 | + var url = '/api/entityViews'; | |
214 | + if (!config) { | |
215 | + config = {}; | |
216 | + } | |
217 | + config = Object.assign(config, { ignoreErrors: ignoreErrors }); | |
218 | + $http.post(url, query, config).then(function success(response) { | |
219 | + deferred.resolve(response.data); | |
220 | + }, function fail() { | |
221 | + deferred.reject(); | |
222 | + }); | |
223 | + return deferred.promise; | |
224 | + } | |
225 | + | |
226 | + function getEntityViewTypes(config) { | |
227 | + var deferred = $q.defer(); | |
228 | + var url = '/api/entityView/types'; | |
229 | + $http.get(url, config).then(function success(response) { | |
230 | + deferred.resolve(response.data); | |
231 | + }, function fail() { | |
232 | + deferred.reject(); | |
233 | + }); | |
234 | + return deferred.promise; | |
235 | + } | |
236 | + | |
237 | +} | ... | ... |
... | ... | @@ -67,6 +67,7 @@ import thingsboardClipboard from './services/clipboard.service'; |
67 | 67 | import thingsboardHome from './layout'; |
68 | 68 | import thingsboardApiLogin from './api/login.service'; |
69 | 69 | import thingsboardApiDevice from './api/device.service'; |
70 | +import thingsboardApiEntityView from './api/entity-view.service'; | |
70 | 71 | import thingsboardApiUser from './api/user.service'; |
71 | 72 | import thingsboardApiEntityRelation from './api/entity-relation.service'; |
72 | 73 | import thingsboardApiAsset from './api/asset.service'; |
... | ... | @@ -133,6 +134,7 @@ angular.module('thingsboard', [ |
133 | 134 | thingsboardHome, |
134 | 135 | thingsboardApiLogin, |
135 | 136 | thingsboardApiDevice, |
137 | + thingsboardApiEntityView, | |
136 | 138 | thingsboardApiUser, |
137 | 139 | thingsboardApiEntityRelation, |
138 | 140 | thingsboardApiAsset, | ... | ... |
... | ... | @@ -327,7 +327,8 @@ export default angular.module('thingsboard.types', []) |
327 | 327 | dashboard: "DASHBOARD", |
328 | 328 | alarm: "ALARM", |
329 | 329 | rulechain: "RULE_CHAIN", |
330 | - rulenode: "RULE_NODE" | |
330 | + rulenode: "RULE_NODE", | |
331 | + entityview: "ENTITY_VIEW" | |
331 | 332 | }, |
332 | 333 | aliasEntityType: { |
333 | 334 | current_customer: "CURRENT_CUSTOMER" | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<md-dialog aria-label="{{ 'entity-view.add' | translate }}" tb-help="'entityViews'" help-container-id="help-container"> | |
19 | + <form name="theForm" ng-submit="vm.add()"> | |
20 | + <md-toolbar> | |
21 | + <div class="md-toolbar-tools"> | |
22 | + <h2 translate>entity-view.add</h2> | |
23 | + <span flex></span> | |
24 | + <div id="help-container"></div> | |
25 | + <md-button class="md-icon-button" ng-click="vm.cancel()"> | |
26 | + <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> | |
27 | + </md-button> | |
28 | + </div> | |
29 | + </md-toolbar> | |
30 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
31 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
32 | + <md-dialog-content> | |
33 | + <div class="md-dialog-content"> | |
34 | + <tb-entity-view entity-view="vm.item" is-edit="true" the-form="theForm"></tb-entity-view> | |
35 | + </div> | |
36 | + </md-dialog-content> | |
37 | + <md-dialog-actions layout="row"> | |
38 | + <span flex></span> | |
39 | + <md-button ng-disabled="$root.loading || theForm.$invalid || !theForm.$dirty" type="submit" class="md-raised md-primary"> | |
40 | + {{ 'action.add' | translate }} | |
41 | + </md-button> | |
42 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | translate }}</md-button> | |
43 | + </md-dialog-actions> | |
44 | + </form> | |
45 | +</md-dialog> | |
\ No newline at end of file | ... | ... |
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +/*@ngInject*/ | |
17 | +export default function AddEntityViewsToCustomerController(entityViewService, $mdDialog, $q, customerId, entityViews) { | |
18 | + | |
19 | + var vm = this; | |
20 | + | |
21 | + vm.entityViews = entityViews; | |
22 | + vm.searchText = ''; | |
23 | + | |
24 | + vm.assign = assign; | |
25 | + vm.cancel = cancel; | |
26 | + vm.hasData = hasData; | |
27 | + vm.noData = noData; | |
28 | + vm.searchEntityViewTextUpdated = searchEntityViewTextUpdated; | |
29 | + vm.toggleEntityViewSelection = toggleEntityViewSelection; | |
30 | + | |
31 | + vm.theEntityViews = { | |
32 | + getItemAtIndex: function (index) { | |
33 | + if (index > vm.entityViews.data.length) { | |
34 | + vm.theEntityViews.fetchMoreItems_(index); | |
35 | + return null; | |
36 | + } | |
37 | + var item = vm.entityViews.data[index]; | |
38 | + if (item) { | |
39 | + item.indexNumber = index + 1; | |
40 | + } | |
41 | + return item; | |
42 | + }, | |
43 | + | |
44 | + getLength: function () { | |
45 | + if (vm.entityViews.hasNext) { | |
46 | + return vm.entityViews.data.length + vm.entityViews.nextPageLink.limit; | |
47 | + } else { | |
48 | + return vm.entityViews.data.length; | |
49 | + } | |
50 | + }, | |
51 | + | |
52 | + fetchMoreItems_: function () { | |
53 | + if (vm.entityViews.hasNext && !vm.entityViews.pending) { | |
54 | + vm.entityViews.pending = true; | |
55 | + entityViewService.getTenantEntityViews(vm.entityViews.nextPageLink, false).then( | |
56 | + function success(entityViews) { | |
57 | + vm.entityViews.data = vm.entityViews.data.concat(entityViews.data); | |
58 | + vm.entityViews.nextPageLink = entityViews.nextPageLink; | |
59 | + vm.entityViews.hasNext = entityViews.hasNext; | |
60 | + if (vm.entityViews.hasNext) { | |
61 | + vm.entityViews.nextPageLink.limit = vm.entityViews.pageSize; | |
62 | + } | |
63 | + vm.entityViews.pending = false; | |
64 | + }, | |
65 | + function fail() { | |
66 | + vm.entityViews.hasNext = false; | |
67 | + vm.entityViews.pending = false; | |
68 | + }); | |
69 | + } | |
70 | + } | |
71 | + }; | |
72 | + | |
73 | + function cancel () { | |
74 | + $mdDialog.cancel(); | |
75 | + } | |
76 | + | |
77 | + function assign() { | |
78 | + var tasks = []; | |
79 | + for (var entityViewId in vm.entityViews.selections) { | |
80 | + tasks.push(entityViewService.assignEntityViewToCustomer(customerId, entityViewId)); | |
81 | + } | |
82 | + $q.all(tasks).then(function () { | |
83 | + $mdDialog.hide(); | |
84 | + }); | |
85 | + } | |
86 | + | |
87 | + function noData() { | |
88 | + return vm.entityViews.data.length == 0 && !vm.entityViews.hasNext; | |
89 | + } | |
90 | + | |
91 | + function hasData() { | |
92 | + return vm.entityViews.data.length > 0; | |
93 | + } | |
94 | + | |
95 | + function toggleEntityViewSelection($event, entityView) { | |
96 | + $event.stopPropagation(); | |
97 | + var selected = angular.isDefined(entityView.selected) && entityView.selected; | |
98 | + entityView.selected = !selected; | |
99 | + if (entityView.selected) { | |
100 | + vm.entityViews.selections[entityView.id.id] = true; | |
101 | + vm.entityViews.selectedCount++; | |
102 | + } else { | |
103 | + delete vm.entityViews.selections[entityView.id.id]; | |
104 | + vm.entityViews.selectedCount--; | |
105 | + } | |
106 | + } | |
107 | + | |
108 | + function searchEntityViewTextUpdated() { | |
109 | + vm.entityViews = { | |
110 | + pageSize: vm.entityViews.pageSize, | |
111 | + data: [], | |
112 | + nextPageLink: { | |
113 | + limit: vm.entityViews.pageSize, | |
114 | + textSearch: vm.searchText | |
115 | + }, | |
116 | + selections: {}, | |
117 | + selectedCount: 0, | |
118 | + hasNext: true, | |
119 | + pending: false | |
120 | + }; | |
121 | + } | |
122 | + | |
123 | +} | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<md-dialog aria-label="{{ 'entity-view.assign-to-customer' | translate }}"> | |
19 | + <form name="theForm" ng-submit="vm.assign()"> | |
20 | + <md-toolbar> | |
21 | + <div class="md-toolbar-tools"> | |
22 | + <h2 translate>entity-view.assign-entity-view-to-customer</h2> | |
23 | + <span flex></span> | |
24 | + <md-button class="md-icon-button" ng-click="vm.cancel()"> | |
25 | + <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> | |
26 | + </md-button> | |
27 | + </div> | |
28 | + </md-toolbar> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | + <md-dialog-content> | |
32 | + <div class="md-dialog-content"> | |
33 | + <fieldset> | |
34 | + <span translate>entity-view.assign-entity-view-to-customer-text</span> | |
35 | + <md-input-container class="md-block" style='margin-bottom: 0px;'> | |
36 | + <label> </label> | |
37 | + <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons"> | |
38 | + search | |
39 | + </md-icon> | |
40 | + <input id="entity-view-search" autofocus ng-model="vm.searchText" | |
41 | + ng-change="vm.searchEntityViewTextUpdated()" | |
42 | + placeholder="{{ 'common.enter-search' | translate }}"/> | |
43 | + </md-input-container> | |
44 | + <div style='min-height: 150px;'> | |
45 | + <span translate layout-align="center center" | |
46 | + style="text-transform: uppercase; display: flex; height: 150px;" | |
47 | + class="md-subhead" | |
48 | + ng-show="vm.noData()">entity-view.no-entity-views-text</span> | |
49 | + <md-virtual-repeat-container ng-show="vm.hasData()" | |
50 | + tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex | |
51 | + style='min-height: 150px; width: 100%;'> | |
52 | + <md-list> | |
53 | + <md-list-item md-virtual-repeat="entityView in vm.theEntityViews" md-on-demand | |
54 | + class="repeated-item" flex> | |
55 | + <md-checkbox ng-click="vm.toggleEntityViewSelection($event, entityView)" | |
56 | + aria-label="{{ 'item.selected' | translate }}" | |
57 | + ng-checked="entityView.selected"></md-checkbox> | |
58 | + <span> {{ entityView.name }} </span> | |
59 | + </md-list-item> | |
60 | + </md-list> | |
61 | + </md-virtual-repeat-container> | |
62 | + </div> | |
63 | + </fieldset> | |
64 | + </div> | |
65 | + </md-dialog-content> | |
66 | + <md-dialog-actions layout="row"> | |
67 | + <span flex></span> | |
68 | + <md-button ng-disabled="$root.loading || vm.entityViews.selectedCount == 0" type="submit" | |
69 | + class="md-raised md-primary"> | |
70 | + {{ 'action.assign' | translate }} | |
71 | + </md-button> | |
72 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
73 | + translate }} | |
74 | + </md-button> | |
75 | + </md-dialog-actions> | |
76 | + </form> | |
77 | +</md-dialog> | |
\ No newline at end of file | ... | ... |
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +/*@ngInject*/ | |
17 | +export default function AssignEntityViewToCustomerController(customerService, entityViewService, $mdDialog, $q, entityViewIds, customers) { | |
18 | + | |
19 | + var vm = this; | |
20 | + | |
21 | + vm.customers = customers; | |
22 | + vm.searchText = ''; | |
23 | + | |
24 | + vm.assign = assign; | |
25 | + vm.cancel = cancel; | |
26 | + vm.isCustomerSelected = isCustomerSelected; | |
27 | + vm.hasData = hasData; | |
28 | + vm.noData = noData; | |
29 | + vm.searchCustomerTextUpdated = searchCustomerTextUpdated; | |
30 | + vm.toggleCustomerSelection = toggleCustomerSelection; | |
31 | + | |
32 | + vm.theCustomers = { | |
33 | + getItemAtIndex: function (index) { | |
34 | + if (index > vm.customers.data.length) { | |
35 | + vm.theCustomers.fetchMoreItems_(index); | |
36 | + return null; | |
37 | + } | |
38 | + var item = vm.customers.data[index]; | |
39 | + if (item) { | |
40 | + item.indexNumber = index + 1; | |
41 | + } | |
42 | + return item; | |
43 | + }, | |
44 | + | |
45 | + getLength: function () { | |
46 | + if (vm.customers.hasNext) { | |
47 | + return vm.customers.data.length + vm.customers.nextPageLink.limit; | |
48 | + } else { | |
49 | + return vm.customers.data.length; | |
50 | + } | |
51 | + }, | |
52 | + | |
53 | + fetchMoreItems_: function () { | |
54 | + if (vm.customers.hasNext && !vm.customers.pending) { | |
55 | + vm.customers.pending = true; | |
56 | + customerService.getCustomers(vm.customers.nextPageLink).then( | |
57 | + function success(customers) { | |
58 | + vm.customers.data = vm.customers.data.concat(customers.data); | |
59 | + vm.customers.nextPageLink = customers.nextPageLink; | |
60 | + vm.customers.hasNext = customers.hasNext; | |
61 | + if (vm.customers.hasNext) { | |
62 | + vm.customers.nextPageLink.limit = vm.customers.pageSize; | |
63 | + } | |
64 | + vm.customers.pending = false; | |
65 | + }, | |
66 | + function fail() { | |
67 | + vm.customers.hasNext = false; | |
68 | + vm.customers.pending = false; | |
69 | + }); | |
70 | + } | |
71 | + } | |
72 | + }; | |
73 | + | |
74 | + function cancel() { | |
75 | + $mdDialog.cancel(); | |
76 | + } | |
77 | + | |
78 | + function assign() { | |
79 | + var tasks = []; | |
80 | + for (var i=0; i < entityViewIds.length;i++) { | |
81 | + tasks.push(entityViewService.assignEntityViewToCustomer(vm.customers.selection.id.id, entityViewIds[i])); | |
82 | + } | |
83 | + $q.all(tasks).then(function () { | |
84 | + $mdDialog.hide(); | |
85 | + }); | |
86 | + } | |
87 | + | |
88 | + function noData() { | |
89 | + return vm.customers.data.length == 0 && !vm.customers.hasNext; | |
90 | + } | |
91 | + | |
92 | + function hasData() { | |
93 | + return vm.customers.data.length > 0; | |
94 | + } | |
95 | + | |
96 | + function toggleCustomerSelection($event, customer) { | |
97 | + $event.stopPropagation(); | |
98 | + if (vm.isCustomerSelected(customer)) { | |
99 | + vm.customers.selection = null; | |
100 | + } else { | |
101 | + vm.customers.selection = customer; | |
102 | + } | |
103 | + } | |
104 | + | |
105 | + function isCustomerSelected(customer) { | |
106 | + return vm.customers.selection != null && customer && | |
107 | + customer.id.id === vm.customers.selection.id.id; | |
108 | + } | |
109 | + | |
110 | + function searchCustomerTextUpdated() { | |
111 | + vm.customers = { | |
112 | + pageSize: vm.customers.pageSize, | |
113 | + data: [], | |
114 | + nextPageLink: { | |
115 | + limit: vm.customers.pageSize, | |
116 | + textSearch: vm.searchText | |
117 | + }, | |
118 | + selection: null, | |
119 | + hasNext: true, | |
120 | + pending: false | |
121 | + }; | |
122 | + } | |
123 | +} | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<md-dialog aria-label="{{ 'entity-view.assign-entity-view-to-customer' | translate }}"> | |
19 | + <form name="theForm" ng-submit="vm.assign()"> | |
20 | + <md-toolbar> | |
21 | + <div class="md-toolbar-tools"> | |
22 | + <h2 translate>entity-view.assign-entity-view-to-customer</h2> | |
23 | + <span flex></span> | |
24 | + <md-button class="md-icon-button" ng-click="vm.cancel()"> | |
25 | + <ng-md-icon icon="close" aria-label="{{ 'dialog.close' | translate }}"></ng-md-icon> | |
26 | + </md-button> | |
27 | + </div> | |
28 | + </md-toolbar> | |
29 | + <md-progress-linear class="md-warn" md-mode="indeterminate" ng-disabled="!$root.loading" ng-show="$root.loading"></md-progress-linear> | |
30 | + <span style="min-height: 5px;" flex="" ng-show="!$root.loading"></span> | |
31 | + <md-dialog-content> | |
32 | + <div class="md-dialog-content"> | |
33 | + <fieldset> | |
34 | + <span translate>entity-view.assign-to-customer-text</span> | |
35 | + <md-input-container class="md-block" style='margin-bottom: 0px;'> | |
36 | + <label> </label> | |
37 | + <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons"> | |
38 | + search | |
39 | + </md-icon> | |
40 | + <input id="customer-search" autofocus ng-model="vm.searchText" | |
41 | + ng-change="vm.searchCustomerTextUpdated()" | |
42 | + placeholder="{{ 'common.enter-search' | translate }}"/> | |
43 | + </md-input-container> | |
44 | + <div style='min-height: 150px;'> | |
45 | + <span translate layout-align="center center" | |
46 | + style="text-transform: uppercase; display: flex; height: 150px;" | |
47 | + class="md-subhead" | |
48 | + ng-show="vm.noData()">customer.no-customers-text</span> | |
49 | + <md-virtual-repeat-container ng-show="vm.hasData()" | |
50 | + tb-scope-element="repeatContainer" md-top-index="vm.topIndex" flex | |
51 | + style='min-height: 150px; width: 100%;'> | |
52 | + <md-list> | |
53 | + <md-list-item md-virtual-repeat="customer in vm.theCustomers" md-on-demand | |
54 | + class="repeated-item" flex> | |
55 | + <md-checkbox ng-click="vm.toggleCustomerSelection($event, customer)" | |
56 | + aria-label="{{ 'item.selected' | translate }}" | |
57 | + ng-checked="vm.isCustomerSelected(customer)"></md-checkbox> | |
58 | + <span> {{ customer.title }} </span> | |
59 | + </md-list-item> | |
60 | + </md-list> | |
61 | + </md-virtual-repeat-container> | |
62 | + </div> | |
63 | + </fieldset> | |
64 | + </div> | |
65 | + </md-dialog-content> | |
66 | + <md-dialog-actions layout="row"> | |
67 | + <span flex></span> | |
68 | + <md-button ng-disabled="$root.loading || vm.customers.selection==null" type="submit" class="md-raised md-primary"> | |
69 | + {{ 'action.assign' | translate }} | |
70 | + </md-button> | |
71 | + <md-button ng-disabled="$root.loading" ng-click="vm.cancel()" style="margin-right:20px;">{{ 'action.cancel' | | |
72 | + translate }} | |
73 | + </md-button> | |
74 | + </md-dialog-actions> | |
75 | + </form> | |
76 | +</md-dialog> | |
\ No newline at end of file | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<div flex layout="column" style="margin-top: -10px;"> | |
19 | + <div style="text-transform: uppercase; padding-bottom: 5px;">{{vm.item.type}}</div> | |
20 | + <div class="tb-card-description">{{vm.item.additionalInfo.description}}</div> | |
21 | + <div style="padding-top: 5px;" class="tb-small" ng-show="vm.isAssignedToCustomer()">{{'entity-view.assignedToCustomer' | translate}} '{{vm.item.assignedCustomer.title}}'</div> | |
22 | +</div> | ... | ... |
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<md-button ng-click="onAssignToCustomer({event: $event})" | |
19 | + ng-show="!isEdit && entityViewScope === 'tenant' && !isAssignedToCustomer" | |
20 | + class="md-raised md-primary">{{ 'entity-view.assign-to-customer' | translate }}</md-button> | |
21 | +<md-button ng-click="onUnassignFromCustomer({event: $event})" | |
22 | + ng-show="!isEdit && (entityViewScope === 'customer' || entityViewScope === 'tenant') && isAssignedToCustomer" | |
23 | + class="md-raised md-primary">{{'entity-view.unassign-from-customer' | translate }}</md-button> | |
24 | +<md-button ng-click="onDeleteEntityView({event: $event})" | |
25 | + ng-show="!isEdit && entityViewScope === 'tenant'" | |
26 | + class="md-raised md-primary">{{ 'entity-view.delete' | translate }}</md-button> | |
27 | + | |
28 | +<div layout="row"> | |
29 | + <md-button ngclipboard data-clipboard-action="copy" | |
30 | + ngclipboard-success="onEntityViewIdCopied(e)" | |
31 | + data-clipboard-text="{{entityView.id.id}}" ng-show="!isEdit" | |
32 | + class="md-raised"> | |
33 | + <md-icon md-svg-icon="mdi:clipboard-arrow-left"></md-icon> | |
34 | + <span translate>entity-view.copyId</span> | |
35 | + </md-button> | |
36 | +</div> | |
37 | + | |
38 | +<md-content class="md-padding" layout="column"> | |
39 | + <md-input-container class="md-block" | |
40 | + ng-show="!isEdit && isAssignedToCustomer && entityViewScope === 'tenant'"> | |
41 | + <label translate>entity-view.assignedToCustomer</label> | |
42 | + <input ng-model="assignedCustomer.title" disabled> | |
43 | + </md-input-container> | |
44 | + <fieldset ng-disabled="$root.loading || !isEdit"> | |
45 | + <md-input-container class="md-block"> | |
46 | + <label translate>entity-view.name</label> | |
47 | + <input required name="name" ng-model="entityView.name"> | |
48 | + <div ng-messages="theForm.name.$error"> | |
49 | + <div translate ng-message="required">entity-view.name-required</div> | |
50 | + </div> | |
51 | + </md-input-container> | |
52 | + <tb-entity-subtype-autocomplete | |
53 | + ng-disabled="$root.loading || !isEdit" | |
54 | + tb-required="true" | |
55 | + the-form="theForm" | |
56 | + ng-model="entityView.type" | |
57 | + entity-type="types.entityType.entityview"> | |
58 | + </tb-entity-subtype-autocomplete> | |
59 | + <md-input-container class="md-block"> | |
60 | + <label translate>entity-view.description</label> | |
61 | + <textarea ng-model="entityView.additionalInfo.description" rows="2"></textarea> | |
62 | + </md-input-container> | |
63 | + </fieldset> | |
64 | +</md-content> | ... | ... |
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +/* eslint-disable import/no-unresolved, import/default */ | |
17 | + | |
18 | +import addEntityViewTemplate from './add-entity-view.tpl.html'; | |
19 | +import entityViewCard from './entity-view-card.tpl.html'; | |
20 | +import assignToCustomerTemplate from './assign-to-customer.tpl.html'; | |
21 | +import addEntityViewsToCustomerTemplate from './add-entity-views-to-customer.tpl.html'; | |
22 | + | |
23 | +/* eslint-enable import/no-unresolved, import/default */ | |
24 | + | |
25 | +/*@ngInject*/ | |
26 | +export function EntityViewCardController(types) { | |
27 | + | |
28 | + var vm = this; | |
29 | + | |
30 | + vm.types = types; | |
31 | + | |
32 | + vm.isAssignedToCustomer = function() { | |
33 | + if (vm.item && vm.item.customerId && vm.parentCtl.entityViewsScope === 'tenant' && | |
34 | + vm.item.customerId.id != vm.types.id.nullUid && !vm.item.assignedCustomer.isPublic) { | |
35 | + return true; | |
36 | + } | |
37 | + return false; | |
38 | + } | |
39 | + | |
40 | + vm.isPublic = function() { | |
41 | + if (vm.item && vm.item.assignedCustomer && vm.parentCtl.entityViewsScope === 'tenant' && vm.item.assignedCustomer.isPublic) { | |
42 | + return true; | |
43 | + } | |
44 | + return false; | |
45 | + } | |
46 | +} | |
47 | + | |
48 | + | |
49 | +/*@ngInject*/ | |
50 | +export function EntityViewController($rootScope, userService, entityViewService, customerService, $state, $stateParams, | |
51 | + $document, $mdDialog, $q, $translate, types) { | |
52 | + | |
53 | + var customerId = $stateParams.customerId; | |
54 | + | |
55 | + var entityViewActionsList = []; | |
56 | + | |
57 | + var entityViewGroupActionsList = []; | |
58 | + | |
59 | + var vm = this; | |
60 | + | |
61 | + vm.types = types; | |
62 | + | |
63 | + vm.entityViewGridConfig = { | |
64 | + deleteItemTitleFunc: deleteEntityViewTitle, | |
65 | + deleteItemContentFunc: deleteEntityViewText, | |
66 | + deleteItemsTitleFunc: deleteEntityViewsTitle, | |
67 | + deleteItemsActionTitleFunc: deleteEntityViewsActionTitle, | |
68 | + deleteItemsContentFunc: deleteEntityViewsText, | |
69 | + | |
70 | + saveItemFunc: saveEntityView, | |
71 | + | |
72 | + getItemTitleFunc: getEntityViewTitle, | |
73 | + | |
74 | + itemCardController: 'EntityViewCardController', | |
75 | + itemCardTemplateUrl: entityViewCard, | |
76 | + parentCtl: vm, | |
77 | + | |
78 | + actionsList: entityViewActionsList, | |
79 | + groupActionsList: entityViewGroupActionsList, | |
80 | + | |
81 | + onGridInited: gridInited, | |
82 | + | |
83 | + addItemTemplateUrl: addEntityViewTemplate, | |
84 | + | |
85 | + addItemText: function() { return $translate.instant('entity-view.add-entity-view-text') }, | |
86 | + noItemsText: function() { return $translate.instant('entity-view.no-entity-views-text') }, | |
87 | + itemDetailsText: function() { return $translate.instant('entity-view.entity-view-details') }, | |
88 | + isDetailsReadOnly: isCustomerUser, | |
89 | + isSelectionEnabled: function () { | |
90 | + return !isCustomerUser(); | |
91 | + } | |
92 | + }; | |
93 | + | |
94 | + if (angular.isDefined($stateParams.items) && $stateParams.items !== null) { | |
95 | + vm.entityViewGridConfig.items = $stateParams.items; | |
96 | + } | |
97 | + | |
98 | + if (angular.isDefined($stateParams.topIndex) && $stateParams.topIndex > 0) { | |
99 | + vm.entityViewGridConfig.topIndex = $stateParams.topIndex; | |
100 | + } | |
101 | + | |
102 | + vm.entityViewsScope = $state.$current.data.entityViewsType; | |
103 | + | |
104 | + vm.assignToCustomer = assignToCustomer; | |
105 | + vm.makePublic = makePublic; | |
106 | + vm.unassignFromCustomer = unassignFromCustomer; | |
107 | + | |
108 | + initController(); | |
109 | + | |
110 | + function initController() { | |
111 | + var fetchEntityViewsFunction = null; | |
112 | + var deleteEntityViewFunction = null; | |
113 | + var refreshEntityViewsParamsFunction = null; | |
114 | + | |
115 | + var user = userService.getCurrentUser(); | |
116 | + | |
117 | + if (user.authority === 'CUSTOMER_USER') { | |
118 | + vm.entityViewsScope = 'customer_user'; | |
119 | + customerId = user.customerId; | |
120 | + } | |
121 | + if (customerId) { | |
122 | + vm.customerEntityViewsTitle = $translate.instant('customer.entity-views'); | |
123 | + customerService.getShortCustomerInfo(customerId).then( | |
124 | + function success(info) { | |
125 | + if (info.isPublic) { | |
126 | + vm.customerEntityViewsTitle = $translate.instant('customer.public-entity-views'); | |
127 | + } | |
128 | + } | |
129 | + ); | |
130 | + } | |
131 | + | |
132 | + if (vm.entityViewsScope === 'tenant') { | |
133 | + fetchEntityViewsFunction = function (pageLink, entityViewType) { | |
134 | + return entityViewService.getTenantEntityViews(pageLink, true, null, entityViewType); | |
135 | + }; | |
136 | + deleteEntityViewFunction = function (entityViewId) { | |
137 | + return entityViewService.deleteEntityView(entityViewId); | |
138 | + }; | |
139 | + refreshEntityViewsParamsFunction = function() { | |
140 | + return {"topIndex": vm.topIndex}; | |
141 | + }; | |
142 | + | |
143 | + entityViewActionsList.push( | |
144 | + { | |
145 | + onAction: function ($event, item) { | |
146 | + assignToCustomer($event, [ item.id.id ]); | |
147 | + }, | |
148 | + name: function() { return $translate.instant('action.assign') }, | |
149 | + details: function() { return $translate.instant('entity-view.assign-to-customer') }, | |
150 | + icon: "assignment_ind", | |
151 | + isEnabled: function(entityView) { | |
152 | + return entityView && (!entityView.customerId || entityView.customerId.id === types.id.nullUid); | |
153 | + } | |
154 | + } | |
155 | + ); | |
156 | + | |
157 | + entityViewActionsList.push( | |
158 | + { | |
159 | + onAction: function ($event, item) { | |
160 | + unassignFromCustomer($event, item, false); | |
161 | + }, | |
162 | + name: function() { return $translate.instant('action.unassign') }, | |
163 | + details: function() { return $translate.instant('entity-view.unassign-from-customer') }, | |
164 | + icon: "assignment_return", | |
165 | + isEnabled: function(entityView) { | |
166 | + return entityView && entityView.customerId && entityView.customerId.id !== types.id.nullUid && !entityView.assignedCustomer.isPublic; | |
167 | + } | |
168 | + } | |
169 | + ); | |
170 | + | |
171 | + entityViewActionsList.push({ | |
172 | + onAction: function ($event, item) { | |
173 | + unassignFromCustomer($event, item, true); | |
174 | + }, | |
175 | + name: function() { return $translate.instant('action.make-private') }, | |
176 | + details: function() { return $translate.instant('entity-view.make-private') }, | |
177 | + icon: "reply", | |
178 | + isEnabled: function(entityView) { | |
179 | + return entityView && entityView.customerId && entityView.customerId.id !== types.id.nullUid && entityView.assignedCustomer.isPublic; | |
180 | + } | |
181 | + }); | |
182 | + | |
183 | + entityViewActionsList.push( | |
184 | + { | |
185 | + onAction: function ($event, item) { | |
186 | + vm.grid.deleteItem($event, item); | |
187 | + }, | |
188 | + name: function() { return $translate.instant('action.delete') }, | |
189 | + details: function() { return $translate.instant('entity-view.delete') }, | |
190 | + icon: "delete" | |
191 | + } | |
192 | + ); | |
193 | + | |
194 | + entityViewGroupActionsList.push( | |
195 | + { | |
196 | + onAction: function ($event, items) { | |
197 | + assignEntiyViewsToCustomer($event, items); | |
198 | + }, | |
199 | + name: function() { return $translate.instant('entity-view.assign-entity-views') }, | |
200 | + details: function(selectedCount) { | |
201 | + return $translate.instant('entity-view.assign-entity-views-text', {count: selectedCount}, "messageformat"); | |
202 | + }, | |
203 | + icon: "assignment_ind" | |
204 | + } | |
205 | + ); | |
206 | + | |
207 | + entityViewGroupActionsList.push( | |
208 | + { | |
209 | + onAction: function ($event) { | |
210 | + vm.grid.deleteItems($event); | |
211 | + }, | |
212 | + name: function() { return $translate.instant('entity-view.delete-entity-views') }, | |
213 | + details: deleteEntityViewsActionTitle, | |
214 | + icon: "delete" | |
215 | + } | |
216 | + ); | |
217 | + | |
218 | + | |
219 | + | |
220 | + } else if (vm.entityViewsScope === 'customer' || vm.entityViewsScope === 'customer_user') { | |
221 | + fetchEntityViewsFunction = function (pageLink, entityViewType) { | |
222 | + return entityViewService.getCustomerEntityViews(customerId, pageLink, true, null, entityViewType); | |
223 | + }; | |
224 | + deleteentityViewFunction = function (entityViewId) { | |
225 | + return entityViewService.unassignEntityViewFromCustomer(entityViewId); | |
226 | + }; | |
227 | + refreshentityViewsParamsFunction = function () { | |
228 | + return {"customerId": customerId, "topIndex": vm.topIndex}; | |
229 | + }; | |
230 | + | |
231 | + if (vm.entityViewsScope === 'customer') { | |
232 | + entityViewActionsList.push( | |
233 | + { | |
234 | + onAction: function ($event, item) { | |
235 | + unassignFromCustomer($event, item, false); | |
236 | + }, | |
237 | + name: function() { return $translate.instant('action.unassign') }, | |
238 | + details: function() { return $translate.instant('entity-view.unassign-from-customer') }, | |
239 | + icon: "assignment_return", | |
240 | + isEnabled: function(entityView) { | |
241 | + return entityView && !entityView.assignedCustomer.isPublic; | |
242 | + } | |
243 | + } | |
244 | + ); | |
245 | + | |
246 | + entityViewGroupActionsList.push( | |
247 | + { | |
248 | + onAction: function ($event, items) { | |
249 | + unassignEntityViewsFromCustomer($event, items); | |
250 | + }, | |
251 | + name: function() { return $translate.instant('entity-view.unassign-entity-views') }, | |
252 | + details: function(selectedCount) { | |
253 | + return $translate.instant('entity-view.unassign-entity-views-action-title', {count: selectedCount}, "messageformat"); | |
254 | + }, | |
255 | + icon: "assignment_return" | |
256 | + } | |
257 | + ); | |
258 | + | |
259 | + vm.entityViewGridConfig.addItemAction = { | |
260 | + onAction: function ($event) { | |
261 | + addEntityViewsToCustomer($event); | |
262 | + }, | |
263 | + name: function() { return $translate.instant('entity-view.assign-entity-views') }, | |
264 | + details: function() { return $translate.instant('entity-view.assign-new-entity-view') }, | |
265 | + icon: "add" | |
266 | + }; | |
267 | + | |
268 | + | |
269 | + } else if (vm.entityViewsScope === 'customer_user') { | |
270 | + vm.entityViewGridConfig.addItemAction = {}; | |
271 | + } | |
272 | + } | |
273 | + | |
274 | + vm.entityViewGridConfig.refreshParamsFunc = refreshentityViewsParamsFunction; | |
275 | + vm.entityViewGridConfig.fetchItemsFunc = fetchentityViewsFunction; | |
276 | + vm.entityViewGridConfig.deleteItemFunc = deleteentityViewFunction; | |
277 | + | |
278 | + } | |
279 | + | |
280 | + function deleteEntityViewTitle(entityView) { | |
281 | + return $translate.instant('entity-view.delete-entity-view-title', {entityViewName: entityView.name}); | |
282 | + } | |
283 | + | |
284 | + function deleteEntityViewText() { | |
285 | + return $translate.instant('entity-view.delete-entity-view-text'); | |
286 | + } | |
287 | + | |
288 | + function deleteEntityViewsTitle(selectedCount) { | |
289 | + return $translate.instant('entity-view.delete-entity-views-title', {count: selectedCount}, 'messageformat'); | |
290 | + } | |
291 | + | |
292 | + function deleteEntityViewsActionTitle(selectedCount) { | |
293 | + return $translate.instant('entity-view.delete-entity-views-action-title', {count: selectedCount}, 'messageformat'); | |
294 | + } | |
295 | + | |
296 | + function deleteEntityViewsText () { | |
297 | + return $translate.instant('entity-view.delete-entity-views-text'); | |
298 | + } | |
299 | + | |
300 | + function gridInited(grid) { | |
301 | + vm.grid = grid; | |
302 | + } | |
303 | + | |
304 | + function getEntityViewTitle(entityView) { | |
305 | + return entityView ? entityView.name : ''; | |
306 | + } | |
307 | + | |
308 | + function saveEntityView(entityView) { | |
309 | + var deferred = $q.defer(); | |
310 | + entityViewService.saveEntityView(entityView).then( | |
311 | + function success(savedEntityView) { | |
312 | + $rootScope.$broadcast('entityViewSaved'); | |
313 | + var entityViews = [ savedEntityView ]; | |
314 | + customerService.applyAssignedCustomersInfo(entityViews).then( | |
315 | + function success(items) { | |
316 | + if (items && items.length == 1) { | |
317 | + deferred.resolve(items[0]); | |
318 | + } else { | |
319 | + deferred.reject(); | |
320 | + } | |
321 | + }, | |
322 | + function fail() { | |
323 | + deferred.reject(); | |
324 | + } | |
325 | + ); | |
326 | + }, | |
327 | + function fail() { | |
328 | + deferred.reject(); | |
329 | + } | |
330 | + ); | |
331 | + return deferred.promise; | |
332 | + } | |
333 | + | |
334 | + function isCustomerUser() { | |
335 | + return vm.entityViewsScope === 'customer_user'; | |
336 | + } | |
337 | + | |
338 | + function assignToCustomer($event, entityViewIds) { | |
339 | + if ($event) { | |
340 | + $event.stopPropagation(); | |
341 | + } | |
342 | + var pageSize = 10; | |
343 | + customerService.getCustomers({limit: pageSize, textSearch: ''}).then( | |
344 | + function success(_customers) { | |
345 | + var customers = { | |
346 | + pageSize: pageSize, | |
347 | + data: _customers.data, | |
348 | + nextPageLink: _customers.nextPageLink, | |
349 | + selection: null, | |
350 | + hasNext: _customers.hasNext, | |
351 | + pending: false | |
352 | + }; | |
353 | + if (customers.hasNext) { | |
354 | + customers.nextPageLink.limit = pageSize; | |
355 | + } | |
356 | + $mdDialog.show({ | |
357 | + controller: 'AssignEntityViewToCustomerController', | |
358 | + controllerAs: 'vm', | |
359 | + templateUrl: assignToCustomerTemplate, | |
360 | + locals: {entityViewIds: entityViewIds, customers: customers}, | |
361 | + parent: angular.element($document[0].body), | |
362 | + fullscreen: true, | |
363 | + targetEvent: $event | |
364 | + }).then(function () { | |
365 | + vm.grid.refreshList(); | |
366 | + }, function () { | |
367 | + }); | |
368 | + }, | |
369 | + function fail() { | |
370 | + }); | |
371 | + } | |
372 | + | |
373 | + function addEntityViewsToCustomer($event) { | |
374 | + if ($event) { | |
375 | + $event.stopPropagation(); | |
376 | + } | |
377 | + var pageSize = 10; | |
378 | + entityViewService.getTenantEntityViews({limit: pageSize, textSearch: ''}, false).then( | |
379 | + function success(_entityViews) { | |
380 | + var entityViews = { | |
381 | + pageSize: pageSize, | |
382 | + data: _entityViews.data, | |
383 | + nextPageLink: _entityViews.nextPageLink, | |
384 | + selections: {}, | |
385 | + selectedCount: 0, | |
386 | + hasNext: _entityViews.hasNext, | |
387 | + pending: false | |
388 | + }; | |
389 | + if (entityViews.hasNext) { | |
390 | + entityViews.nextPageLink.limit = pageSize; | |
391 | + } | |
392 | + $mdDialog.show({ | |
393 | + controller: 'AddEntityViewsToCustomerController', | |
394 | + controllerAs: 'vm', | |
395 | + templateUrl: addEntityViewsToCustomerTemplate, | |
396 | + locals: {customerId: customerId, entityViews: entityViews}, | |
397 | + parent: angular.element($document[0].body), | |
398 | + fullscreen: true, | |
399 | + targetEvent: $event | |
400 | + }).then(function () { | |
401 | + vm.grid.refreshList(); | |
402 | + }, function () { | |
403 | + }); | |
404 | + }, | |
405 | + function fail() { | |
406 | + }); | |
407 | + } | |
408 | + | |
409 | + function assignEntityViewsToCustomer($event, items) { | |
410 | + var entityViewIds = []; | |
411 | + for (var id in items.selections) { | |
412 | + entityViewIds.push(id); | |
413 | + } | |
414 | + assignToCustomer($event, entityViewIds); | |
415 | + } | |
416 | + | |
417 | + function unassignFromCustomer($event, entityView, isPublic) { | |
418 | + if ($event) { | |
419 | + $event.stopPropagation(); | |
420 | + } | |
421 | + var title; | |
422 | + var content; | |
423 | + var label; | |
424 | + if (isPublic) { | |
425 | + title = $translate.instant('entity-view.make-private-entity-view-title', {entityViewName: entityView.name}); | |
426 | + content = $translate.instant('entity-view.make-private-entity-view-text'); | |
427 | + label = $translate.instant('entity-view.make-private'); | |
428 | + } else { | |
429 | + title = $translate.instant('entity-view.unassign-entity-view-title', {entityViewName: entityView.name}); | |
430 | + content = $translate.instant('entity-view.unassign-entity-view-text'); | |
431 | + label = $translate.instant('entity-view.unassign-entity-view'); | |
432 | + } | |
433 | + var confirm = $mdDialog.confirm() | |
434 | + .targetEvent($event) | |
435 | + .title(title) | |
436 | + .htmlContent(content) | |
437 | + .ariaLabel(label) | |
438 | + .cancel($translate.instant('action.no')) | |
439 | + .ok($translate.instant('action.yes')); | |
440 | + $mdDialog.show(confirm).then(function () { | |
441 | + entityViewService.unassignEntityViewFromCustomer(entityView.id.id).then(function success() { | |
442 | + vm.grid.refreshList(); | |
443 | + }); | |
444 | + }); | |
445 | + } | |
446 | + | |
447 | + function unassignEntityViewsFromCustomer($event, items) { | |
448 | + var confirm = $mdDialog.confirm() | |
449 | + .targetEvent($event) | |
450 | + .title($translate.instant('entity-view.unassign-entity-views-title', {count: items.selectedCount}, 'messageformat')) | |
451 | + .htmlContent($translate.instant('entity-view.unassign-entity-views-text')) | |
452 | + .ariaLabel($translate.instant('entity-view.unassign-entity-view')) | |
453 | + .cancel($translate.instant('action.no')) | |
454 | + .ok($translate.instant('action.yes')); | |
455 | + $mdDialog.show(confirm).then(function () { | |
456 | + var tasks = []; | |
457 | + for (var id in items.selections) { | |
458 | + tasks.push(entityViewService.unassignEntityViewFromCustomer(id)); | |
459 | + } | |
460 | + $q.all(tasks).then(function () { | |
461 | + vm.grid.refreshList(); | |
462 | + }); | |
463 | + }); | |
464 | + } | |
465 | + | |
466 | + function makePublic($event, entityView) { | |
467 | + if ($event) { | |
468 | + $event.stopPropagation(); | |
469 | + } | |
470 | + var confirm = $mdDialog.confirm() | |
471 | + .targetEvent($event) | |
472 | + .title($translate.instant('entity-view.make-public-entity-view-title', {entityViewName: entityView.name})) | |
473 | + .htmlContent($translate.instant('entity-view.make-public-entity-view-text')) | |
474 | + .ariaLabel($translate.instant('entity-view.make-public')) | |
475 | + .cancel($translate.instant('action.no')) | |
476 | + .ok($translate.instant('action.yes')); | |
477 | + $mdDialog.show(confirm).then(function () { | |
478 | + entityViewService.makeEntityViewPublic(entityView.id.id).then(function success() { | |
479 | + vm.grid.refreshList(); | |
480 | + }); | |
481 | + }); | |
482 | + } | |
483 | +} | ... | ... |
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +/* eslint-disable import/no-unresolved, import/default */ | |
17 | + | |
18 | +import entityViewFieldsetTemplate from './entity-view-fieldset.tpl.html'; | |
19 | + | |
20 | +/* eslint-enable import/no-unresolved, import/default */ | |
21 | + | |
22 | +/*@ngInject*/ | |
23 | +export default function EntityViewDirective($compile, $templateCache, toast, $translate, types, clipboardService, entityViewService, customerService) { | |
24 | + var linker = function (scope, element) { | |
25 | + var template = $templateCache.get(entityViewFieldsetTemplate); | |
26 | + element.html(template); | |
27 | + | |
28 | + scope.types = types; | |
29 | + scope.isAssignedToCustomer = false; | |
30 | + scope.assignedCustomer = null; | |
31 | + | |
32 | + scope.$watch('entityView', function(newVal) { | |
33 | + if (newVal) { | |
34 | + if (scope.entityView.customerId && scope.entityView.customerId.id !== types.id.nullUid) { | |
35 | + scope.isAssignedToCustomer = true; | |
36 | + customerService.getShortCustomerInfo(scope.entityView.customerId.id).then( | |
37 | + function success(customer) { | |
38 | + scope.assignedCustomer = customer; | |
39 | + } | |
40 | + ); | |
41 | + } else { | |
42 | + scope.isAssignedToCustomer = false; | |
43 | + scope.assignedCustomer = null; | |
44 | + } | |
45 | + } | |
46 | + }); | |
47 | + | |
48 | + scope.onEntityViewIdCopied = function() { | |
49 | + toast.showSuccess($translate.instant('entity-view.idCopiedMessage'), 750, angular.element(element).parent().parent(), 'bottom left'); | |
50 | + }; | |
51 | + | |
52 | + $compile(element.contents())(scope); | |
53 | + } | |
54 | + return { | |
55 | + restrict: "E", | |
56 | + link: linker, | |
57 | + scope: { | |
58 | + entityView: '=', | |
59 | + isEdit: '=', | |
60 | + entityViewScope: '=', | |
61 | + theForm: '=', | |
62 | + onAssignToCustomer: '&', | |
63 | + onUnassignFromCustomer: '&', | |
64 | + onDeleteEntityView: '&' | |
65 | + } | |
66 | + }; | |
67 | +} | ... | ... |
ui/src/app/entity-view/entity-view.routes.js
0 → 100644
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +/* eslint-disable import/no-unresolved, import/default */ | |
17 | + | |
18 | +import entityViewsTemplate from './entity-views.tpl.html'; | |
19 | + | |
20 | +/* eslint-enable import/no-unresolved, import/default */ | |
21 | + | |
22 | +/*@ngInject*/ | |
23 | +export default function EntityViewRoutes($stateProvider, types) { | |
24 | + $stateProvider | |
25 | + .state('home.entityViews', { | |
26 | + url: '/entityViews', | |
27 | + params: {'topIndex': 0}, | |
28 | + module: 'private', | |
29 | + auth: ['TENANT_ADMIN', 'CUSTOMER_USER'], | |
30 | + views: { | |
31 | + "content@home": { | |
32 | + templateUrl: entityViewsTemplate, | |
33 | + controller: 'EntityViewController', | |
34 | + controllerAs: 'vm' | |
35 | + } | |
36 | + }, | |
37 | + data: { | |
38 | + entityViewsTypes: 'tenant', | |
39 | + searchEnabled: true, | |
40 | + searchByEntitySubtype: true, | |
41 | + searchEntityType: types.entityType.entityview, | |
42 | + pageTitle: 'entity-views.entity-views' | |
43 | + }, | |
44 | + ncyBreadcrumb: { | |
45 | + label: '{"icon": "devices_other", "label": "entity-view.entity-views"}' | |
46 | + } | |
47 | + }) | |
48 | + .state('home.customers.entityViews', { | |
49 | + url: '/:customerId/entityViews', | |
50 | + params: {'topIndex': 0}, | |
51 | + module: 'private', | |
52 | + auth: ['TENANT_ADMIN'], | |
53 | + views: { | |
54 | + "content@home": { | |
55 | + templateUrl: entityViewsTemplate, | |
56 | + controllerAs: 'vm', | |
57 | + controller: 'EntityViewController' | |
58 | + } | |
59 | + }, | |
60 | + data: { | |
61 | + entityViewsTypes: 'customer', | |
62 | + searchEnabled: true, | |
63 | + searchByEntitySubtype: true, | |
64 | + searchEntityType: types.entityType.entityview, | |
65 | + pageTitle: 'customer.entity-views' | |
66 | + }, | |
67 | + ncyBreadcrumb: { | |
68 | + label: '{"icon": "devices_other", "label": "{{ vm.customerEntityViewsTitle }}", "translate": "false"}' | |
69 | + } | |
70 | + }); | |
71 | + | |
72 | +} | ... | ... |
ui/src/app/entity-view/entity-views.tpl.html
0 → 100644
1 | +<!-- | |
2 | + | |
3 | + Copyright © 2016-2018 The Thingsboard Authors | |
4 | + | |
5 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | + you may not use this file except in compliance with the License. | |
7 | + You may obtain a copy of the License at | |
8 | + | |
9 | + http://www.apache.org/licenses/LICENSE-2.0 | |
10 | + | |
11 | + Unless required by applicable law or agreed to in writing, software | |
12 | + distributed under the License is distributed on an "AS IS" BASIS, | |
13 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | + See the License for the specific language governing permissions and | |
15 | + limitations under the License. | |
16 | + | |
17 | +--> | |
18 | +<tb-grid grid-configuration="vm.entityViewGridConfig"> | |
19 | + <details-buttons tb-help="'entityViews'" help-container-id="help-container"> | |
20 | + <div id="help-container"></div> | |
21 | + </details-buttons> | |
22 | + <md-tabs ng-class="{'tb-headless': vm.grid.detailsConfig.isDetailsEditMode}" | |
23 | + id="tabs" md-border-bottom flex class="tb-absolute-fill"> | |
24 | + <md-tab label="{{ 'entity-view.details' | translate }}"> | |
25 | + <tb-entity-view entity-view="vm.grid.operatingItem()" | |
26 | + is-edit="vm.grid.detailsConfig.isDetailsEditMode" | |
27 | + entity-view-scope="vm.entityViewsScope" | |
28 | + the-form="vm.grid.detailsForm" | |
29 | + on-assign-to-customer="vm.assignToCustomer(event, [ vm.grid.detailsConfig.currentItem.id.id ])" | |
30 | + on-make-public="vm.makePublic(event, vm.grid.detailsConfig.currentItem)" | |
31 | + on-unassign-from-customer="vm.unassignFromCustomer(event, vm.grid.detailsConfig.currentItem, isPublic)" | |
32 | + on-manage-credentials="vm.manageCredentials(event, vm.grid.detailsConfig.currentItem)" | |
33 | + on-delete-entity-view="vm.grid.deleteItem(event, vm.grid.detailsConfig.currentItem)"></tb-entity-view> | |
34 | + </md-tab> | |
35 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.attributes' | translate }}"> | |
36 | + <tb-attribute-table flex | |
37 | + entity-id="vm.grid.operatingItem().id.id" | |
38 | + entity-type="{{vm.types.entityType.entityview}}" | |
39 | + entity-name="vm.grid.operatingItem().name" | |
40 | + default-attribute-scope="{{vm.types.attributesScope.client.value}}"> | |
41 | + </tb-attribute-table> | |
42 | + </md-tab> | |
43 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'attribute.latest-telemetry' | translate }}"> | |
44 | + <tb-attribute-table flex | |
45 | + entity-id="vm.grid.operatingItem().id.id" | |
46 | + entity-type="{{vm.types.entityType.entityview}}" | |
47 | + entity-name="vm.grid.operatingItem().name" | |
48 | + default-attribute-scope="{{vm.types.latestTelemetry.value}}" | |
49 | + disable-attribute-scope-selection="true"> | |
50 | + </tb-attribute-table> | |
51 | + </md-tab> | |
52 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'alarm.alarms' | translate }}"> | |
53 | + <tb-alarm-table flex entity-type="vm.types.entityType.entityview" | |
54 | + entity-id="vm.grid.operatingItem().id.id"> | |
55 | + </tb-alarm-table> | |
56 | + </md-tab> | |
57 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'entity-view.events' | translate }}"> | |
58 | + <tb-event-table flex entity-type="vm.types.entityType.entityview" | |
59 | + entity-id="vm.grid.operatingItem().id.id" | |
60 | + tenant-id="vm.grid.operatingItem().tenantId.id" | |
61 | + default-event-type="{{vm.types.eventType.error.value}}"> | |
62 | + </tb-event-table> | |
63 | + </md-tab> | |
64 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode" md-on-select="vm.grid.triggerResize()" label="{{ 'relation.relations' | translate }}"> | |
65 | + <tb-relation-table flex | |
66 | + entity-id="vm.grid.operatingItem().id.id" | |
67 | + entity-type="{{vm.types.entityType.entityview}}"> | |
68 | + </tb-relation-table> | |
69 | + </md-tab> | |
70 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.operatingItem().additionalInfo.gateway" md-on-select="vm.grid.triggerResize()" label="{{ 'extension.extensions' | translate }}"> | |
71 | + <tb-extension-table flex | |
72 | + entity-id="vm.grid.operatingItem().id.id" | |
73 | + entity-name="vm.grid.operatingItem().name" | |
74 | + entity-type="{{vm.types.entityType.entityview}}"> | |
75 | + </tb-extension-table> | |
76 | + </md-tab> | |
77 | + <md-tab ng-if="!vm.grid.detailsConfig.isDetailsEditMode && vm.grid.isTenantAdmin()" md-on-select="vm.grid.triggerResize()" label="{{ 'audit-log.audit-logs' | translate }}"> | |
78 | + <tb-audit-log-table flex entity-type="vm.types.entityType.entityview" | |
79 | + entity-id="vm.grid.operatingItem().id.id" | |
80 | + audit-log-mode="{{vm.types.auditLogMode.entity}}"> | |
81 | + </tb-audit-log-table> | |
82 | + </md-tab> | |
83 | +</tb-grid> | ... | ... |
ui/src/app/entity-view/index.js
0 → 100644
1 | +/* | |
2 | + * Copyright © 2016-2018 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +import uiRouter from 'angular-ui-router'; | |
17 | +import thingsboardGrid from '../components/grid.directive'; | |
18 | +import thingsboardApiUser from '../api/user.service'; | |
19 | +import thingsboardApiEntityView from '../api/entity-view.service'; | |
20 | +import thingsboardApiCustomer from '../api/customer.service'; | |
21 | + | |
22 | +import EntityViewRoutes from './entity-view.routes'; | |
23 | +import EntityViewCardController from './entity-view.controller'; | |
24 | +import AssignEntityViewToCustomerController from './assign-to-customer.controller'; | |
25 | +import AddEntityViewsToCustomerController from './add-entity-views-to-customer.controller'; | |
26 | +import EntityViewDirective from './entity-view.directive'; | |
27 | + | |
28 | +export default angular.module('thingsboard.entityView', [ | |
29 | + uiRouter, | |
30 | + thingsboardGrid, | |
31 | + thingsboardApiUser, | |
32 | + thingsboardApiEntityView, | |
33 | + thingsboardApiCustomer | |
34 | +]) | |
35 | + .config(EntityViewRoutes) | |
36 | + .controller('EntityViewController', EntityViewCardController) | |
37 | + .controller('EntityViewCardController', EntityViewCardController) | |
38 | + .controller('AssignEntityViewToCustomerController', AssignEntityViewToCustomerController) | |
39 | + .controller('AddEntityViewsToCustomerController', AddEntityViewsToCustomerController) | |
40 | + .directive('tbEntityView', EntityViewDirective) | |
41 | + .name; | ... | ... |
... | ... | @@ -338,10 +338,12 @@ |
338 | 338 | "dashboard": "Customer Dashboard", |
339 | 339 | "dashboards": "Customer Dashboards", |
340 | 340 | "devices": "Customer Devices", |
341 | + "entity-views": "Customer Entity Views", | |
341 | 342 | "assets": "Customer Assets", |
342 | 343 | "public-dashboards": "Public Dashboards", |
343 | 344 | "public-devices": "Public Devices", |
344 | 345 | "public-assets": "Public Assets", |
346 | + "public-entity-views": "Public Entity Views", | |
345 | 347 | "add": "Add Customer", |
346 | 348 | "delete": "Delete customer", |
347 | 349 | "manage-customer-users": "Manage customer users", |
... | ... | @@ -750,6 +752,77 @@ |
750 | 752 | "no-entities-prompt": "No entities found", |
751 | 753 | "no-data": "No data to display" |
752 | 754 | }, |
755 | + "entity-view": { | |
756 | + "entity-view": "Entity View", | |
757 | + "entity-views": "Entity Views", | |
758 | + "management": "Entity View management", | |
759 | + "view-entity-views": "View Entity Views", | |
760 | + "entity-view-alias": "Entity View alias", | |
761 | + "aliases": "Entity View aliases", | |
762 | + "no-alias-matching": "'{{alias}}' not found.", | |
763 | + "no-aliases-found": "No aliases found.", | |
764 | + "no-key-matching": "'{{key}}' not found.", | |
765 | + "no-keys-found": "No keys found.", | |
766 | + "create-new-alias": "Create a new one!", | |
767 | + "create-new-key": "Create a new one!", | |
768 | + "duplicate-alias-error": "Duplicate alias found '{{alias}}'.<br>Entity View aliases must be unique whithin the dashboard.", | |
769 | + "configure-alias": "Configure '{{alias}}' alias", | |
770 | + "no-entity-views-matching": "No entity views matching '{{entity}}' were found.", | |
771 | + "alias": "Alias", | |
772 | + "alias-required": "Entity View alias is required.", | |
773 | + "remove-alias": "Remove entity view alias", | |
774 | + "add-alias": "Add entity view alias", | |
775 | + "name-starts-with": "Entity View name starts with", | |
776 | + "entity-view-list": "Entity View list", | |
777 | + "use-entity-view-name-filter": "Use filter", | |
778 | + "entity-view-list-empty": "No entity views selected.", | |
779 | + "entity-view-name-filter-required": "Entity view name filter is required.", | |
780 | + "entity-view-name-filter-no-entity-view-matched": "No entity views starting with '{{entityView}}' were found.", | |
781 | + "add": "Add Entity View", | |
782 | + "assign-to-customer": "Assign to customer", | |
783 | + "assign-entity-view-to-customer": "Assign Entity View(s) To Customer", | |
784 | + "assign-entity-view-to-customer-text": "Please select the entity views to assign to the customer", | |
785 | + "no-entity-views-text": "No entity views found", | |
786 | + "assign-to-customer-text": "Please select the customer to assign the entity view(s)", | |
787 | + "entity-view-details": "Entity view details", | |
788 | + "add-entity-view-text": "Add new entity view", | |
789 | + "delete": "Delete entity view", | |
790 | + "assign-entity-views": "Assign entity views", | |
791 | + "assign-entity-views-text": "Assign { count, plural, 1 {1 entityView} other {# entityViews} } to customer", | |
792 | + "delete-entity-views": "Delete entity views", | |
793 | + "unassign-from-customer": "Unassign from customer", | |
794 | + "unassign-entity-views": "Unassign entity views", | |
795 | + "unassign-entity-views-action-title": "Unassign { count, plural, 1 {1 entityView} other {# entityViews} } from customer", | |
796 | + "assign-new-entity-view": "Assign new entity view", | |
797 | + "delete-entity-view-title": "Are you sure you want to delete the entity view '{{entityViewName}}'?", | |
798 | + "delete-entity-view-text": "Be careful, after the confirmation the entity view and all related data will become unrecoverable.", | |
799 | + "delete-entity-views-title": "Are you sure you want to entity view { count, plural, 1 {1 entityView} other {# entityViews} }?", | |
800 | + "delete-entity-views-action-title": "Delete { count, plural, 1 {1 entityView} other {# entityViews} }", | |
801 | + "delete-entity-views-text": "Be careful, after the confirmation all selected entity views will be removed and all related data will become unrecoverable.", | |
802 | + "unassign-entity-view-title": "Are you sure you want to unassign the entity view '{{entityViewName}}'?", | |
803 | + "unassign-entity-view-text": "After the confirmation the entity view will be unassigned and won't be accessible by the customer.", | |
804 | + "unassign-entity-view": "Unassign entity view", | |
805 | + "unassign-entity-views-title": "Are you sure you want to unassign { count, plural, 1 {1 entityView} other {# entityViews} }?", | |
806 | + "unassign-entity-views-text": "After the confirmation all selected entity views will be unassigned and won't be accessible by the customer.", | |
807 | + "entity-view-type": "Entity View type", | |
808 | + "entity-view-type-required": "Entity View type is required.", | |
809 | + "select-entity-view-type": "Select entity view type", | |
810 | + "enter-entity-view-type": "Enter entity view type", | |
811 | + "any-entity-view": "Any entity view", | |
812 | + "no-entity-view-types-matching": "No entity view types matching '{{entitySubtype}}' were found.", | |
813 | + "entity-view-type-list-empty": "No entity view types selected.", | |
814 | + "entity-view-types": "Entity View types", | |
815 | + "name": "Name", | |
816 | + "name-required": "Name is required.", | |
817 | + "description": "Description", | |
818 | + "events": "Events", | |
819 | + "details": "Details", | |
820 | + "copyId": "Copy entity view Id", | |
821 | + "assignedToCustomer": "Assigned to customer", | |
822 | + "unable-entity-view-device-alias-title": "Unable to delete entity view alias", | |
823 | + "unable-entity-view-device-alias-text": "Device alias '{{entityViewAlias}}' can't be deleted as it used by the following widget(s):<br/>{{widgetsList}}", | |
824 | + "select-entity-view": "Select entity view" | |
825 | + }, | |
753 | 826 | "event": { |
754 | 827 | "event-type": "Event type", |
755 | 828 | "type-error": "Error", | ... | ... |