Showing
4 changed files
with
1 additions
and
841 deletions
@@ -22,7 +22,6 @@ import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-wid | @@ -22,7 +22,6 @@ import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-wid | ||
22 | import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget'; | 22 | import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget'; |
23 | import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget'; | 23 | import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget'; |
24 | import thingsboardEntitiesHierarchyWidget from '../widget/lib/entities-hierarchy-widget'; | 24 | import thingsboardEntitiesHierarchyWidget from '../widget/lib/entities-hierarchy-widget'; |
25 | -import thingsboardEdgesHierarchyWidget from '../widget/lib/edges-hierarchy-widget'; | ||
26 | import thingsboardExtensionsTableWidget from '../widget/lib/extensions-table-widget'; | 25 | import thingsboardExtensionsTableWidget from '../widget/lib/extensions-table-widget'; |
27 | import thingsboardDateRangeNavigatorWidget from '../widget/lib/date-range-navigator/date-range-navigator'; | 26 | import thingsboardDateRangeNavigatorWidget from '../widget/lib/date-range-navigator/date-range-navigator'; |
28 | import thingsboardMultipleInputWidget from '../widget/lib/multiple-input-widget'; | 27 | import thingsboardMultipleInputWidget from '../widget/lib/multiple-input-widget'; |
@@ -53,7 +52,7 @@ import thingsboardUtils from '../common/utils.service'; | @@ -53,7 +52,7 @@ import thingsboardUtils from '../common/utils.service'; | ||
53 | 52 | ||
54 | export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, | 53 | export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, |
55 | thingsboardTimeseriesTableWidget, thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, | 54 | thingsboardTimeseriesTableWidget, thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, |
56 | - thingsboardEntitiesHierarchyWidget, thingsboardEdgesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardDateRangeNavigatorWidget, | 55 | + thingsboardEntitiesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardDateRangeNavigatorWidget, |
57 | thingsboardMultipleInputWidget, thingsboardWebCameraInputWidget, thingsboardRpcWidgets, thingsboardTypes, | 56 | thingsboardMultipleInputWidget, thingsboardWebCameraInputWidget, thingsboardRpcWidgets, thingsboardTypes, |
58 | thingsboardUtils, thingsboardJsonToString, TripAnimationWidget]) | 57 | thingsboardUtils, thingsboardJsonToString, TripAnimationWidget]) |
59 | .factory('widgetService', WidgetService) | 58 | .factory('widgetService', WidgetService) |
ui/src/app/widget/lib/edges-hierarchy-widget.js
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright © 2016-2020 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 './edges-hierarchy-widget.scss'; | ||
17 | - | ||
18 | -/* eslint-disable import/no-unresolved, import/default */ | ||
19 | - | ||
20 | -import edgesHierarchyWidgetTemplate from './edges-hierarchy-widget.tpl.html'; | ||
21 | - | ||
22 | -/* eslint-enable import/no-unresolved, import/default */ | ||
23 | - | ||
24 | -export default angular.module('thingsboard.widgets.edgesHierarchyWidget', []) | ||
25 | - .directive('tbEdgesHierarchyWidget', EdgesHierarchyWidget) | ||
26 | - .name; | ||
27 | -/* eslint-disable no-unused-vars */ | ||
28 | -/*@ngInject*/ | ||
29 | -function EdgesHierarchyWidget() { | ||
30 | - return { | ||
31 | - restrict: "E", | ||
32 | - scope: true, | ||
33 | - bindToController: { | ||
34 | - hierarchyId: '=', | ||
35 | - ctx: '=' | ||
36 | - }, | ||
37 | - controller: EdgesHierarchyWidgetController, | ||
38 | - controllerAs: 'vm', | ||
39 | - templateUrl: edgesHierarchyWidgetTemplate | ||
40 | - }; | ||
41 | -} | ||
42 | - | ||
43 | -/*@ngInject*/ | ||
44 | -function EdgesHierarchyWidgetController($element, $scope, $q, $timeout, toast, types, entityService, entityRelationService, | ||
45 | - assetService, deviceService, entityViewService, dashboardService, ruleChainService /*$filter, $mdMedia, $mdPanel, $document, $translate, $timeout, utils, types*/) { | ||
46 | - var vm = this; | ||
47 | - | ||
48 | - vm.showData = true; | ||
49 | - | ||
50 | - vm.nodeEditCallbacks = {}; | ||
51 | - | ||
52 | - vm.nodeIdCounter = 0; | ||
53 | - | ||
54 | - vm.nodesMap = {}; | ||
55 | - vm.pendingUpdateNodeTasks = {}; | ||
56 | - vm.edgeGroupsNodesMap = {}; | ||
57 | - | ||
58 | - vm.query = { | ||
59 | - search: null | ||
60 | - }; | ||
61 | - | ||
62 | - vm.searchAction = { | ||
63 | - name: 'action.search', | ||
64 | - show: true, | ||
65 | - onAction: function() { | ||
66 | - vm.enterFilterMode(); | ||
67 | - }, | ||
68 | - icon: 'search' | ||
69 | - }; | ||
70 | - | ||
71 | - vm.onNodesInserted = onNodesInserted; | ||
72 | - vm.onNodeSelected = onNodeSelected; | ||
73 | - vm.enterFilterMode = enterFilterMode; | ||
74 | - vm.exitFilterMode = exitFilterMode; | ||
75 | - vm.searchCallback = searchCallback; | ||
76 | - | ||
77 | - $scope.$watch('vm.ctx', function() { | ||
78 | - if (vm.ctx && vm.ctx.defaultSubscription) { | ||
79 | - vm.settings = vm.ctx.settings; | ||
80 | - vm.widgetConfig = vm.ctx.widgetConfig; | ||
81 | - vm.subscription = vm.ctx.defaultSubscription; | ||
82 | - vm.datasources = vm.subscription.datasources; | ||
83 | - initializeConfig(); | ||
84 | - updateDatasources(); | ||
85 | - } | ||
86 | - }); | ||
87 | - | ||
88 | - $scope.$watch("vm.query.search", function(newVal, prevVal) { | ||
89 | - if (!angular.equals(newVal, prevVal) && vm.query.search != null) { | ||
90 | - updateSearchNodes(); | ||
91 | - } | ||
92 | - }); | ||
93 | - | ||
94 | - $scope.$on('edges-hierarchy-data-updated', function(event, hierarchyId) { | ||
95 | - if (vm.hierarchyId == hierarchyId) { | ||
96 | - if (vm.subscription) { | ||
97 | - updateNodeData(vm.subscription.data); | ||
98 | - } | ||
99 | - } | ||
100 | - }); | ||
101 | - | ||
102 | - function initializeConfig() { | ||
103 | - | ||
104 | - vm.ctx.widgetActions = [ vm.searchAction ]; | ||
105 | - | ||
106 | - var testNodeCtx = { | ||
107 | - entity: { | ||
108 | - id: { | ||
109 | - entityType: 'DEVICE', | ||
110 | - id: '123' | ||
111 | - }, | ||
112 | - name: 'TEST DEV1' | ||
113 | - }, | ||
114 | - data: {}, | ||
115 | - level: 2 | ||
116 | - }; | ||
117 | - var parentNodeCtx = angular.copy(testNodeCtx); | ||
118 | - parentNodeCtx.level = 1; | ||
119 | - testNodeCtx.parentNodeCtx = parentNodeCtx; | ||
120 | - | ||
121 | - var nodeRelationQueryFunction = loadNodeCtxFunction(vm.settings.nodeRelationQueryFunction, 'nodeCtx', testNodeCtx); | ||
122 | - var nodeIconFunction = loadNodeCtxFunction(vm.settings.nodeIconFunction, 'nodeCtx', testNodeCtx); | ||
123 | - var nodeTextFunction = loadNodeCtxFunction(vm.settings.nodeTextFunction, 'nodeCtx', testNodeCtx); | ||
124 | - var nodeDisabledFunction = loadNodeCtxFunction(vm.settings.nodeDisabledFunction, 'nodeCtx', testNodeCtx); | ||
125 | - var nodeOpenedFunction = loadNodeCtxFunction(vm.settings.nodeOpenedFunction, 'nodeCtx', testNodeCtx); | ||
126 | - var nodeHasChildrenFunction = loadNodeCtxFunction(vm.settings.nodeHasChildrenFunction, 'nodeCtx', testNodeCtx); | ||
127 | - | ||
128 | - var testNodeCtx2 = angular.copy(testNodeCtx); | ||
129 | - testNodeCtx2.entity.name = 'TEST DEV2'; | ||
130 | - | ||
131 | - var nodesSortFunction = loadNodeCtxFunction(vm.settings.nodesSortFunction, 'nodeCtx1,nodeCtx2', testNodeCtx, testNodeCtx2); | ||
132 | - | ||
133 | - vm.nodeRelationQueryFunction = nodeRelationQueryFunction || defaultNodeRelationQueryFunction; | ||
134 | - vm.nodeIconFunction = nodeIconFunction || defaultNodeIconFunction; | ||
135 | - vm.nodeTextFunction = nodeTextFunction || ((nodeCtx) => nodeCtx.entity.name); | ||
136 | - vm.nodeDisabledFunction = nodeDisabledFunction || (() => false); | ||
137 | - vm.nodeOpenedFunction = nodeOpenedFunction || defaultNodeOpenedFunction; | ||
138 | - vm.nodeHasChildrenFunction = nodeHasChildrenFunction || (() => true); | ||
139 | - vm.nodesSortFunction = nodesSortFunction || defaultSortFunction; | ||
140 | - } | ||
141 | - | ||
142 | - function loadNodeCtxFunction(functionBody, argNames, ...args) { | ||
143 | - var nodeCtxFunction = null; | ||
144 | - if (angular.isDefined(functionBody) && functionBody.length) { | ||
145 | - try { | ||
146 | - nodeCtxFunction = new Function(argNames, functionBody); | ||
147 | - var res = nodeCtxFunction.apply(null, args); | ||
148 | - if (angular.isUndefined(res)) { | ||
149 | - nodeCtxFunction = null; | ||
150 | - } | ||
151 | - } catch (e) { | ||
152 | - nodeCtxFunction = null; | ||
153 | - } | ||
154 | - } | ||
155 | - return nodeCtxFunction; | ||
156 | - } | ||
157 | - | ||
158 | - function enterFilterMode () { | ||
159 | - vm.query.search = ''; | ||
160 | - vm.ctx.hideTitlePanel = true; | ||
161 | - $timeout(()=>{ | ||
162 | - angular.element(vm.ctx.$container).find('.searchInput').focus(); | ||
163 | - }) | ||
164 | - } | ||
165 | - | ||
166 | - function exitFilterMode () { | ||
167 | - vm.query.search = null; | ||
168 | - updateSearchNodes(); | ||
169 | - vm.ctx.hideTitlePanel = false; | ||
170 | - } | ||
171 | - | ||
172 | - function searchCallback (searchText, node) { | ||
173 | - var theNode = vm.nodesMap[node.id]; | ||
174 | - if (theNode && theNode.data.searchText) { | ||
175 | - return theNode.data.searchText.includes(searchText.toLowerCase()); | ||
176 | - } | ||
177 | - return false; | ||
178 | - } | ||
179 | - | ||
180 | - function updateDatasources() { | ||
181 | - vm.loadNodes = loadNodes; | ||
182 | - } | ||
183 | - | ||
184 | - function updateSearchNodes() { | ||
185 | - if (vm.query.search != null) { | ||
186 | - vm.nodeEditCallbacks.search(vm.query.search); | ||
187 | - } else { | ||
188 | - vm.nodeEditCallbacks.clearSearch(); | ||
189 | - } | ||
190 | - } | ||
191 | - | ||
192 | - function onNodesInserted(nodes/*, parent*/) { | ||
193 | - if (nodes) { | ||
194 | - nodes.forEach((nodeId) => { | ||
195 | - var task = vm.pendingUpdateNodeTasks[nodeId]; | ||
196 | - if (task) { | ||
197 | - task(); | ||
198 | - delete vm.pendingUpdateNodeTasks[nodeId]; | ||
199 | - } | ||
200 | - }); | ||
201 | - } | ||
202 | - } | ||
203 | - | ||
204 | - function onNodeSelected(node, event) { | ||
205 | - var nodeId; | ||
206 | - if (!node) { | ||
207 | - nodeId = -1; | ||
208 | - } else { | ||
209 | - nodeId = node.id; | ||
210 | - } | ||
211 | - if (nodeId !== -1) { | ||
212 | - var selectedNode = vm.nodesMap[nodeId]; | ||
213 | - if (selectedNode) { | ||
214 | - var descriptors = vm.ctx.actionsApi.getActionDescriptors('nodeSelected'); | ||
215 | - if (descriptors.length) { | ||
216 | - var entity = selectedNode.data.nodeCtx.entity; | ||
217 | - vm.ctx.actionsApi.handleWidgetAction(event, descriptors[0], entity.id, entity.name, { nodeCtx: selectedNode.data.nodeCtx }); | ||
218 | - } | ||
219 | - } | ||
220 | - } | ||
221 | - } | ||
222 | - | ||
223 | - function updateNodeData(subscriptionData) { | ||
224 | - var affectedNodes = []; | ||
225 | - if (subscriptionData) { | ||
226 | - for (var i=0;i<subscriptionData.length;i++) { | ||
227 | - var datasource = subscriptionData[i].datasource; | ||
228 | - if (datasource.nodeId) { | ||
229 | - var node = vm.nodesMap[datasource.nodeId]; | ||
230 | - var key = subscriptionData[i].dataKey.label; | ||
231 | - var value = undefined; | ||
232 | - if (subscriptionData[i].data && subscriptionData[i].data.length) { | ||
233 | - value = subscriptionData[i].data[0][1]; | ||
234 | - } | ||
235 | - if (node.data.nodeCtx.data[key] !== value) { | ||
236 | - if (affectedNodes.indexOf(datasource.nodeId) === -1) { | ||
237 | - affectedNodes.push(datasource.nodeId); | ||
238 | - } | ||
239 | - node.data.nodeCtx.data[key] = value; | ||
240 | - } | ||
241 | - } | ||
242 | - } | ||
243 | - } | ||
244 | - affectedNodes.forEach((nodeId) => { | ||
245 | - var node = vm.nodeEditCallbacks.getNode(nodeId); | ||
246 | - if (node) { | ||
247 | - updateNodeStyle(vm.nodesMap[nodeId]); | ||
248 | - } else { | ||
249 | - vm.pendingUpdateNodeTasks[nodeId] = () => { | ||
250 | - updateNodeStyle(vm.nodesMap[nodeId]); | ||
251 | - }; | ||
252 | - } | ||
253 | - }); | ||
254 | - } | ||
255 | - | ||
256 | - function updateNodeStyle(node) { | ||
257 | - var newText = prepareNodeText(node); | ||
258 | - if (!angular.equals(node.text, newText)) { | ||
259 | - node.text = newText; | ||
260 | - vm.nodeEditCallbacks.updateNode(node.id, node.text); | ||
261 | - } | ||
262 | - var newDisabled = vm.nodeDisabledFunction(node.data.nodeCtx); | ||
263 | - if (!angular.equals(node.state.disabled, newDisabled)) { | ||
264 | - node.state.disabled = newDisabled; | ||
265 | - if (node.state.disabled) { | ||
266 | - vm.nodeEditCallbacks.disableNode(node.id); | ||
267 | - } else { | ||
268 | - vm.nodeEditCallbacks.enableNode(node.id); | ||
269 | - } | ||
270 | - } | ||
271 | - var newHasChildren = vm.nodeHasChildrenFunction(node.data.nodeCtx); | ||
272 | - if (!angular.equals(node.children, newHasChildren)) { | ||
273 | - node.children = newHasChildren; | ||
274 | - vm.nodeEditCallbacks.setNodeHasChildren(node.id, node.children); | ||
275 | - } | ||
276 | - } | ||
277 | - | ||
278 | - function prepareNodeText(node) { | ||
279 | - var nodeIcon = prepareNodeIcon(node.data.nodeCtx); | ||
280 | - var nodeText = vm.nodeTextFunction(node.data.nodeCtx); | ||
281 | - node.data.searchText = nodeText ? nodeText.replace(/<[^>]+>/g, '').toLowerCase() : ""; | ||
282 | - return nodeIcon + nodeText; | ||
283 | - } | ||
284 | - | ||
285 | - function loadNodes(node, cb) { | ||
286 | - if (node.id === '#') { | ||
287 | - var tasks = []; | ||
288 | - for (var i=0;i<vm.datasources.length;i++) { | ||
289 | - var datasource = vm.datasources[i]; | ||
290 | - tasks.push(datasourceToNode(datasource)); | ||
291 | - } | ||
292 | - $q.all(tasks).then((nodes) => { | ||
293 | - cb(prepareNodes(nodes)); | ||
294 | - updateNodeData(vm.subscription.data); | ||
295 | - }); | ||
296 | - } else { | ||
297 | - if (node.data && node.data.nodeCtx.entity && node.data.nodeCtx.entity.id && node.data.nodeCtx.entity.id.entityType !== 'function') { | ||
298 | - if (node.data.nodeCtx.entity.id.entityType === types.entityType.edge) { | ||
299 | - /* assetService.getEdgeAssets(node.data.nodeCtx.entity.id.id, {limit: 20}, null).then( | ||
300 | - (entities) => { | ||
301 | - var tasks = []; | ||
302 | - for (var i=0;i<entities.data.length;i++) { | ||
303 | - var relation = entities.data[i]; | ||
304 | - var targetId = node.data.nodeCtx.entity.id.entityType === types.entityType.edge ? relation.id : node.data.nodeCtx.entity.id; | ||
305 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
306 | - } | ||
307 | - $q.all(tasks).then((nodes) => { | ||
308 | - cb(prepareNodes(nodes)); | ||
309 | - }); | ||
310 | - } | ||
311 | - ); | ||
312 | - deviceService.getEdgeDevices(node.data.nodeCtx.entity.id.id, {limit: 20}, null).then( | ||
313 | - (entities) => { | ||
314 | - var tasks = []; | ||
315 | - for (var i=0;i<entities.data.length;i++) { | ||
316 | - var relation = entities.data[i]; | ||
317 | - var targetId = node.data.nodeCtx.entity.id.entityType === types.entityType.edge ? relation.id : node.data.nodeCtx.entity.id; | ||
318 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
319 | - } | ||
320 | - $q.all(tasks).then((nodes) => { | ||
321 | - cb(prepareNodes(nodes)); | ||
322 | - }); | ||
323 | - } | ||
324 | - ); | ||
325 | - entityViewService.getEdgeEntityViews(node.data.nodeCtx.entity.id.id, {limit: 20}, null).then( | ||
326 | - (entities) => { | ||
327 | - var tasks = []; | ||
328 | - for (var i=0;i<entities.data.length;i++) { | ||
329 | - var relation = entities.data[i]; | ||
330 | - var targetId = node.data.nodeCtx.entity.id.entityType === types.entityType.edge ? relation.id : node.data.nodeCtx.entity.id; | ||
331 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
332 | - } | ||
333 | - $q.all(tasks).then((nodes) => { | ||
334 | - cb(prepareNodes(nodes)); | ||
335 | - }); | ||
336 | - } | ||
337 | - ); | ||
338 | - dashboardService.getEdgeDashboards(node.data.nodeCtx.entity.id.id, {limit: 20}, null).then( | ||
339 | - (entities) => { | ||
340 | - var tasks = []; | ||
341 | - for (var i=0;i<entities.data.length;i++) { | ||
342 | - var relation = entities.data[i]; | ||
343 | - var targetId = node.data.nodeCtx.entity.id.entityType === types.entityType.edge ? relation.id : node.data.nodeCtx.entity.id; | ||
344 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
345 | - } | ||
346 | - $q.all(tasks).then((nodes) => { | ||
347 | - cb(prepareNodes(nodes)); | ||
348 | - }); | ||
349 | - } | ||
350 | - ) | ||
351 | - ruleChainService.getEdgeRuleChains(node.data.nodeCtx.entity.id.id, {limit: 20}, null).then( | ||
352 | - (entities) => { | ||
353 | - var tasks = []; | ||
354 | - for (var i=0;i<entities.data.length;i++) { | ||
355 | - var relation = entities.data[i]; | ||
356 | - var targetId = node.data.nodeCtx.entity.id.entityType === types.entityType.edge ? relation.id : node.data.nodeCtx.entity.id; | ||
357 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
358 | - } | ||
359 | - $q.all(tasks).then((nodes) => { | ||
360 | - cb(prepareNodes(nodes)); | ||
361 | - }); | ||
362 | - } | ||
363 | - ) | ||
364 | - */ | ||
365 | - | ||
366 | - entityIdToNodeEdge("edgeGroup", "001", node.data.datasource, ) | ||
367 | - | ||
368 | - } else { | ||
369 | - var relationQuery = prepareNodeRelationQuery(node.data.nodeCtx); | ||
370 | - entityRelationService.findByQuery(relationQuery, {ignoreErrors: true, ignoreLoading: true}).then( | ||
371 | - (entityRelations) => { | ||
372 | - var tasks = []; | ||
373 | - for (var i=0;i<entityRelations.length;i++) { | ||
374 | - var relation = entityRelations[i]; | ||
375 | - var targetId = relationQuery.parameters.direction === types.entitySearchDirection.from ? relation.to : relation.from; | ||
376 | - tasks.push(entityIdToNode(targetId.entityType, targetId.id, node.data.datasource, node.data.nodeCtx)); | ||
377 | - } | ||
378 | - $q.all(tasks).then((nodes) => { | ||
379 | - cb(prepareNodes(nodes)); | ||
380 | - }); | ||
381 | - }, | ||
382 | - (error) => { | ||
383 | - var errorText = "Failed to get relations!"; | ||
384 | - if (error && error.status === 400) { | ||
385 | - errorText = "Invalid relations query returned by 'Node relations query function'! Please check widget configuration!"; | ||
386 | - } | ||
387 | - showError(errorText); | ||
388 | - } | ||
389 | - ); | ||
390 | - } | ||
391 | - } else { | ||
392 | - cb([]); | ||
393 | - } | ||
394 | - } | ||
395 | - } | ||
396 | - | ||
397 | - function showError(errorText) { | ||
398 | - var toastParent = angular.element('.tb-edges-hierarchy', $element); | ||
399 | - toast.showError(errorText, toastParent, 'bottom left'); | ||
400 | - } | ||
401 | - | ||
402 | - function prepareNodes(nodes) { | ||
403 | - nodes = nodes.filter((node) => node !== null); | ||
404 | - nodes.sort((node1, node2) => vm.nodesSortFunction(node1.data.nodeCtx, node2.data.nodeCtx)); | ||
405 | - return nodes; | ||
406 | - } | ||
407 | - | ||
408 | - function datasourceToNode(datasource, parentNodeCtx) { | ||
409 | - var deferred = $q.defer(); | ||
410 | - resolveEntity(datasource).then( | ||
411 | - (entity) => { | ||
412 | - if (entity != null) { | ||
413 | - var node = { | ||
414 | - id: ++vm.nodeIdCounter | ||
415 | - }; | ||
416 | - vm.nodesMap[node.id] = node; | ||
417 | - datasource.nodeId = node.id; | ||
418 | - node.icon = false; | ||
419 | - var nodeCtx = { | ||
420 | - parentNodeCtx: parentNodeCtx, | ||
421 | - entity: entity, | ||
422 | - data: {} | ||
423 | - }; | ||
424 | - nodeCtx.level = parentNodeCtx ? parentNodeCtx.level + 1 : 1; | ||
425 | - node.data = { | ||
426 | - datasource: datasource, | ||
427 | - nodeCtx: nodeCtx | ||
428 | - }; | ||
429 | - node.state = { | ||
430 | - disabled: vm.nodeDisabledFunction(node.data.nodeCtx), | ||
431 | - opened: vm.nodeOpenedFunction(node.data.nodeCtx) | ||
432 | - }; | ||
433 | - node.text = prepareNodeText(node); | ||
434 | - node.children = vm.nodeHasChildrenFunction(node.data.nodeCtx); | ||
435 | - deferred.resolve(node); | ||
436 | - } else { | ||
437 | - deferred.resolve(null); | ||
438 | - } | ||
439 | - } | ||
440 | - ); | ||
441 | - return deferred.promise; | ||
442 | - } | ||
443 | - | ||
444 | - function datasourceToNodeEdge(datasource, parentNodeCtx) { | ||
445 | - var deferred = $q.defer(); | ||
446 | - resolveEntity(datasource).then( | ||
447 | - (entity) => { | ||
448 | - if (entity != null) { | ||
449 | - var node = { | ||
450 | - id: ++vm.nodeIdCounter | ||
451 | - }; | ||
452 | - vm.nodesMap[node.id] = node; | ||
453 | - datasource.nodeId = node.id; | ||
454 | - node.icon = false; | ||
455 | - var nodeCtx = { | ||
456 | - parentNodeCtx: parentNodeCtx, | ||
457 | - entity: entity, | ||
458 | - data: {} | ||
459 | - }; | ||
460 | - nodeCtx.level = parentNodeCtx ? parentNodeCtx.level + 1 : 1; | ||
461 | - node.data = { | ||
462 | - datasource: datasource, | ||
463 | - nodeCtx: nodeCtx | ||
464 | - }; | ||
465 | - node.state = { | ||
466 | - disabled: vm.nodeDisabledFunction(node.data.nodeCtx), | ||
467 | - opened: vm.nodeOpenedFunction(node.data.nodeCtx) | ||
468 | - }; | ||
469 | - node.text = prepareNodeText(node); | ||
470 | - node.children = vm.nodeHasChildrenFunction(node.data.nodeCtx); | ||
471 | - deferred.resolve(node); | ||
472 | - } else { | ||
473 | - deferred.resolve(null); | ||
474 | - } | ||
475 | - } | ||
476 | - ); | ||
477 | - return deferred.promise; | ||
478 | - } | ||
479 | - | ||
480 | - | ||
481 | - function entityIdToNodeEdge(entityType, entityId, parentDatasource, parentNodeCtx) { | ||
482 | - var deferred = $q.defer(); | ||
483 | - var datasource = { | ||
484 | - dataKeys: parentDatasource.dataKeys, | ||
485 | - type: types.datasourceType.entity, | ||
486 | - entityType: entityType, | ||
487 | - entityId: entityId | ||
488 | - }; | ||
489 | - datasourceToNodeEdge(datasource, parentNodeCtx).then( | ||
490 | - (node) => { | ||
491 | - if (node != null) { | ||
492 | - var subscriptionOptions = { | ||
493 | - type: types.widgetType.latest.value, | ||
494 | - datasources: [datasource], | ||
495 | - callbacks: { | ||
496 | - onDataUpdated: (subscription) => { | ||
497 | - updateNodeData(subscription.data); | ||
498 | - } | ||
499 | - } | ||
500 | - }; | ||
501 | - vm.ctx.subscriptionApi.createSubscription(subscriptionOptions, true).then( | ||
502 | - (/*subscription*/) => { | ||
503 | - deferred.resolve(node); | ||
504 | - } | ||
505 | - ); | ||
506 | - } else { | ||
507 | - deferred.resolve(node); | ||
508 | - } | ||
509 | - } | ||
510 | - ); | ||
511 | - return deferred.promise; | ||
512 | - } | ||
513 | - | ||
514 | - function entityIdToNode(entityType, entityId, parentDatasource, parentNodeCtx) { | ||
515 | - var deferred = $q.defer(); | ||
516 | - var datasource = { | ||
517 | - dataKeys: parentDatasource.dataKeys, | ||
518 | - type: types.datasourceType.entity, | ||
519 | - entityType: entityType, | ||
520 | - entityId: entityId | ||
521 | - }; | ||
522 | - datasourceToNode(datasource, parentNodeCtx).then( | ||
523 | - (node) => { | ||
524 | - if (node != null) { | ||
525 | - var subscriptionOptions = { | ||
526 | - type: types.widgetType.latest.value, | ||
527 | - datasources: [datasource], | ||
528 | - callbacks: { | ||
529 | - onDataUpdated: (subscription) => { | ||
530 | - updateNodeData(subscription.data); | ||
531 | - } | ||
532 | - } | ||
533 | - }; | ||
534 | - vm.ctx.subscriptionApi.createSubscription(subscriptionOptions, true).then( | ||
535 | - (/*subscription*/) => { | ||
536 | - deferred.resolve(node); | ||
537 | - } | ||
538 | - ); | ||
539 | - } else { | ||
540 | - deferred.resolve(node); | ||
541 | - } | ||
542 | - } | ||
543 | - ); | ||
544 | - return deferred.promise; | ||
545 | - } | ||
546 | - | ||
547 | - function resolveEntity(datasource) { | ||
548 | - var deferred = $q.defer(); | ||
549 | - if (datasource.type === types.datasourceType.function) { | ||
550 | - var entity = { | ||
551 | - id: { | ||
552 | - entityType: "function" | ||
553 | - }, | ||
554 | - name: datasource.name | ||
555 | - } | ||
556 | - deferred.resolve(entity); | ||
557 | - } else { | ||
558 | - entityService.getEntity(datasource.entityType, datasource.entityId, {ignoreLoading: true}).then( | ||
559 | - (entity) => { | ||
560 | - deferred.resolve(entity); | ||
561 | - }, | ||
562 | - () => { | ||
563 | - deferred.resolve(null); | ||
564 | - } | ||
565 | - ); | ||
566 | - } | ||
567 | - return deferred.promise; | ||
568 | - } | ||
569 | - | ||
570 | - | ||
571 | - function prepareNodeRelationQuery(nodeCtx) { | ||
572 | - var relationQuery = vm.nodeRelationQueryFunction(nodeCtx); | ||
573 | - if (relationQuery && relationQuery === 'default') { | ||
574 | - relationQuery = defaultNodeRelationQueryFunction(nodeCtx); | ||
575 | - } | ||
576 | - return relationQuery; | ||
577 | - } | ||
578 | - | ||
579 | - function defaultNodeRelationQueryFunction(nodeCtx) { | ||
580 | - var entity = nodeCtx.entity; | ||
581 | - var query = { | ||
582 | - parameters: { | ||
583 | - rootId: entity.id.id, | ||
584 | - rootType: entity.id.entityType, | ||
585 | - direction: types.entitySearchDirection.from, | ||
586 | - relationTypeGroup: "COMMON", | ||
587 | - maxLevel: 1 | ||
588 | - }, | ||
589 | - filters: [ | ||
590 | - { | ||
591 | - relationType: "Contains", | ||
592 | - entityTypes: [] | ||
593 | - } | ||
594 | - ] | ||
595 | - }; | ||
596 | - return query; | ||
597 | - } | ||
598 | - | ||
599 | - function prepareNodeIcon(nodeCtx) { | ||
600 | - var iconInfo = vm.nodeIconFunction(nodeCtx); | ||
601 | - if (iconInfo && iconInfo === 'default') { | ||
602 | - iconInfo = defaultNodeIconFunction(nodeCtx); | ||
603 | - } | ||
604 | - if (iconInfo && (iconInfo.iconUrl || iconInfo.materialIcon)) { | ||
605 | - if (iconInfo.materialIcon) { | ||
606 | - return materialIconHtml(iconInfo.materialIcon); | ||
607 | - } else { | ||
608 | - return iconUrlHtml(iconInfo.iconUrl); | ||
609 | - } | ||
610 | - } else { | ||
611 | - return ""; | ||
612 | - } | ||
613 | - } | ||
614 | - | ||
615 | - function materialIconHtml(materialIcon) { | ||
616 | - return '<md-icon aria-label="'+materialIcon+'" class="node-icon material-icons" role="img" aria-hidden="false">'+materialIcon+'</md-icon>'; | ||
617 | - } | ||
618 | - | ||
619 | - function iconUrlHtml(iconUrl) { | ||
620 | - return '<div class="node-icon" style="background-image: url('+iconUrl+');"> </div>'; | ||
621 | - } | ||
622 | - | ||
623 | - function defaultNodeIconFunction(nodeCtx) { | ||
624 | - var materialIcon = 'insert_drive_file'; | ||
625 | - var entity = nodeCtx.entity; | ||
626 | - if (entity && entity.id && entity.id.entityType) { | ||
627 | - switch (entity.id.entityType) { | ||
628 | - case 'function': | ||
629 | - materialIcon = 'functions'; | ||
630 | - break; | ||
631 | - case types.entityType.device: | ||
632 | - materialIcon = 'devices_other'; | ||
633 | - break; | ||
634 | - case types.entityType.asset: | ||
635 | - materialIcon = 'domain'; | ||
636 | - break; | ||
637 | - case types.entityType.tenant: | ||
638 | - materialIcon = 'supervisor_account'; | ||
639 | - break; | ||
640 | - case types.entityType.customer: | ||
641 | - materialIcon = 'supervisor_account'; | ||
642 | - break; | ||
643 | - case types.entityType.user: | ||
644 | - materialIcon = 'account_circle'; | ||
645 | - break; | ||
646 | - case types.entityType.dashboard: | ||
647 | - materialIcon = 'dashboards'; | ||
648 | - break; | ||
649 | - case types.entityType.alarm: | ||
650 | - materialIcon = 'notifications_active'; | ||
651 | - break; | ||
652 | - case types.entityType.entityView: | ||
653 | - materialIcon = 'view_quilt'; | ||
654 | - break; | ||
655 | - case types.entityType.edge: | ||
656 | - materialIcon = 'router'; | ||
657 | - break; | ||
658 | - case types.entityType.rulechain: | ||
659 | - materialIcon = 'settings_ethernet'; | ||
660 | - break; | ||
661 | - } | ||
662 | - } | ||
663 | - return { | ||
664 | - materialIcon: materialIcon | ||
665 | - }; | ||
666 | - } | ||
667 | - | ||
668 | - function defaultNodeOpenedFunction(nodeCtx) { | ||
669 | - return nodeCtx.level <= 4; | ||
670 | - } | ||
671 | - | ||
672 | - function defaultSortFunction(nodeCtx1, nodeCtx2) { | ||
673 | - var result = nodeCtx1.entity.id.entityType.localeCompare(nodeCtx2.entity.id.entityType); | ||
674 | - if (result === 0) { | ||
675 | - result = nodeCtx1.entity.name.localeCompare(nodeCtx2.entity.name); | ||
676 | - } | ||
677 | - return result; | ||
678 | - } | ||
679 | -} |
ui/src/app/widget/lib/edges-hierarchy-widget.scss
deleted
100644 → 0
1 | -/** | ||
2 | - * Copyright © 2016-2020 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 | -.tb-has-timewindow { | ||
17 | - .tb-edges-hierarchy { | ||
18 | - md-toolbar { | ||
19 | - min-height: 60px; | ||
20 | - max-height: 60px; | ||
21 | - } | ||
22 | - } | ||
23 | -} | ||
24 | - | ||
25 | -.tb-edges-hierarchy { | ||
26 | - md-toolbar { | ||
27 | - min-height: 39px; | ||
28 | - max-height: 39px; | ||
29 | - } | ||
30 | - | ||
31 | - .tb-entities-nav-tree-panel { | ||
32 | - overflow-x: auto; | ||
33 | - overflow-y: auto; | ||
34 | - | ||
35 | - .tb-nav-tree-container { | ||
36 | - &.jstree-proton { | ||
37 | - .jstree-anchor { | ||
38 | - div.node-icon { | ||
39 | - display: inline-block; | ||
40 | - width: 22px; | ||
41 | - height: 22px; | ||
42 | - margin-right: 2px; | ||
43 | - margin-bottom: 2px; | ||
44 | - background-color: transparent; | ||
45 | - background-repeat: no-repeat; | ||
46 | - background-attachment: scroll; | ||
47 | - background-position: center center; | ||
48 | - background-size: 18px 18px; | ||
49 | - } | ||
50 | - | ||
51 | - md-icon.node-icon { | ||
52 | - width: 22px; | ||
53 | - min-width: 22px; | ||
54 | - height: 22px; | ||
55 | - min-height: 22px; | ||
56 | - margin-right: 2px; | ||
57 | - margin-bottom: 2px; | ||
58 | - color: inherit; | ||
59 | - | ||
60 | - &.material-icons { /* stylelint-disable-line selector-max-class */ | ||
61 | - font-size: 18px; | ||
62 | - line-height: 22px; | ||
63 | - text-align: center; | ||
64 | - } | ||
65 | - } | ||
66 | - | ||
67 | - &.jstree-hovered:not(.jstree-clicked), | ||
68 | - &.jstree-disabled { | ||
69 | - div.node-icon { /* stylelint-disable-line selector-max-class */ | ||
70 | - opacity: .5; | ||
71 | - } | ||
72 | - } | ||
73 | - } | ||
74 | - } | ||
75 | - } | ||
76 | - } | ||
77 | -} | ||
78 | - | ||
79 | -@media (max-width: 768px) { | ||
80 | - .tb-edges-hierarchy { | ||
81 | - .tb-entities-nav-tree-panel { | ||
82 | - .tb-nav-tree-container { | ||
83 | - &.jstree-proton-responsive { | ||
84 | - .jstree-anchor { | ||
85 | - div.node-icon { | ||
86 | - width: 40px; | ||
87 | - height: 40px; | ||
88 | - margin: 0; | ||
89 | - background-size: 24px 24px; | ||
90 | - } | ||
91 | - | ||
92 | - md-icon.node-icon { | ||
93 | - width: 40px; | ||
94 | - min-width: 40px; | ||
95 | - height: 40px; | ||
96 | - min-height: 40px; | ||
97 | - margin: 0; | ||
98 | - | ||
99 | - &.material-icons { /* stylelint-disable-line selector-max-class */ | ||
100 | - font-size: 24px; | ||
101 | - line-height: 40px; | ||
102 | - } | ||
103 | - } | ||
104 | - } | ||
105 | - } | ||
106 | - } | ||
107 | - } | ||
108 | - } | ||
109 | -} |
ui/src/app/widget/lib/edges-hierarchy-widget.tpl.html
deleted
100644 → 0
1 | -<!-- | ||
2 | - | ||
3 | - Copyright © 2016-2020 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 class="tb-absolute-fill tb-edges-hierarchy" layout="column"> | ||
19 | - <div ng-show="vm.showData" flex class="tb-absolute-fill" layout="column"> | ||
20 | - <md-toolbar class="md-table-toolbar md-default" ng-show="vm.query.search != null"> | ||
21 | - <div class="md-toolbar-tools"> | ||
22 | - <md-button class="md-icon-button" aria-label="{{ 'action.search' | translate }}"> | ||
23 | - <md-icon aria-label="{{ 'action.search' | translate }}" class="material-icons">search</md-icon> | ||
24 | - <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}"> | ||
25 | - {{'entity.search' | translate}} | ||
26 | - </md-tooltip> | ||
27 | - </md-button> | ||
28 | - <md-input-container flex> | ||
29 | - <label> </label> | ||
30 | - <input ng-model="vm.query.search" class="searchInput" placeholder="{{'entity.search' | translate}}"/> | ||
31 | - </md-input-container> | ||
32 | - <md-button class="md-icon-button" aria-label="Close" ng-click="vm.exitFilterMode()"> | ||
33 | - <md-icon aria-label="Close" class="material-icons">close</md-icon> | ||
34 | - <md-tooltip md-direction="{{vm.ctx.dashboard.isWidgetExpanded ? 'bottom' : 'top'}}"> | ||
35 | - {{ 'action.close' | translate }} | ||
36 | - </md-tooltip> | ||
37 | - </md-button> | ||
38 | - </div> | ||
39 | - </md-toolbar> | ||
40 | - <div flex class="tb-entities-nav-tree-panel"> | ||
41 | - <tb-nav-tree | ||
42 | - load-nodes="vm.loadNodes" | ||
43 | - on-node-selected="vm.onNodeSelected(node, event)" | ||
44 | - on-nodes-inserted="vm.onNodesInserted(nodes, parent)" | ||
45 | - edit-callbacks="vm.nodeEditCallbacks" | ||
46 | - enable-search="true" | ||
47 | - search-callback="vm.searchCallback(searchText, node)" | ||
48 | - ></tb-nav-tree> | ||
49 | - </div> | ||
50 | - </div> | ||
51 | -</div> |