Commit 00a40e63ba0cbb974fc9dd4ea034d27da0bba83d

Authored by deaflynx
1 parent b1011f43

Deleted edges hierarchy widget

@@ -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)
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+');">&nbsp;</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 -}  
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 -}  
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>&nbsp;</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>