Showing
4 changed files
with
1 additions
and
841 deletions
... | ... | @@ -22,7 +22,6 @@ import thingsboardTimeseriesTableWidget from '../widget/lib/timeseries-table-wid |
22 | 22 | import thingsboardAlarmsTableWidget from '../widget/lib/alarms-table-widget'; |
23 | 23 | import thingsboardEntitiesTableWidget from '../widget/lib/entities-table-widget'; |
24 | 24 | import thingsboardEntitiesHierarchyWidget from '../widget/lib/entities-hierarchy-widget'; |
25 | -import thingsboardEdgesHierarchyWidget from '../widget/lib/edges-hierarchy-widget'; | |
26 | 25 | import thingsboardExtensionsTableWidget from '../widget/lib/extensions-table-widget'; |
27 | 26 | import thingsboardDateRangeNavigatorWidget from '../widget/lib/date-range-navigator/date-range-navigator'; |
28 | 27 | import thingsboardMultipleInputWidget from '../widget/lib/multiple-input-widget'; |
... | ... | @@ -53,7 +52,7 @@ import thingsboardUtils from '../common/utils.service'; |
53 | 52 | |
54 | 53 | export default angular.module('thingsboard.api.widget', ['oc.lazyLoad', thingsboardLedLight, |
55 | 54 | thingsboardTimeseriesTableWidget, thingsboardAlarmsTableWidget, thingsboardEntitiesTableWidget, |
56 | - thingsboardEntitiesHierarchyWidget, thingsboardEdgesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardDateRangeNavigatorWidget, | |
55 | + thingsboardEntitiesHierarchyWidget, thingsboardExtensionsTableWidget, thingsboardDateRangeNavigatorWidget, | |
57 | 56 | thingsboardMultipleInputWidget, thingsboardWebCameraInputWidget, thingsboardRpcWidgets, thingsboardTypes, |
58 | 57 | thingsboardUtils, thingsboardJsonToString, TripAnimationWidget]) |
59 | 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> |