Entity graph hightlight and pin-all
Change-Id: Ia9e653c221243cd0d28cfc1e9ae4c5d6718a6766
This commit is contained in:
parent
ef9a39e23b
commit
9eac15598f
@ -7,6 +7,7 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<hz-entities-info item="vm.selectedItem"></hz-entities-info>
|
||||
<hz-entities-toolbox></hz-entities-toolbox>
|
||||
<hz-entities-graph data="vm.graphData" selected="vm.model.selected" item-selected="vm.setSelected"></hz-entities-graph>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
.entities {
|
||||
.panel-body {
|
||||
padding: 3px;
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
|
@ -24,14 +24,34 @@ function hzEntitiesGraph() {
|
||||
linkWidth = 1,
|
||||
circleRadius = 14,
|
||||
circlePadding = 1,
|
||||
pinned = horizon.cookies.get('pinned') || [],
|
||||
zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]),
|
||||
ellipsisWidth = 80,
|
||||
hightlightDepth = 2,
|
||||
heightOffset,
|
||||
pinned,
|
||||
graphCreated,
|
||||
node,
|
||||
link,
|
||||
linksMap,
|
||||
content;
|
||||
|
||||
(function() {
|
||||
var p = $('.panel.panel-primary');
|
||||
heightOffset = (p.length ? p.offset().top : 180) + 75;
|
||||
|
||||
pinned = horizon.cookies.get('pinned') || [];
|
||||
if (_.isString(pinned)) {
|
||||
try {
|
||||
pinned = JSON.parse(pinned);
|
||||
}
|
||||
catch(ex) {
|
||||
pinned = [];
|
||||
console.error('Failed to parse the pinned cookie');
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
scope.$watch('data.ts', function(newVal, oldVal) {
|
||||
if (newVal) {
|
||||
prepareData();
|
||||
@ -44,6 +64,22 @@ function hzEntitiesGraph() {
|
||||
}
|
||||
});
|
||||
|
||||
scope.$on('toolbox-pin', function () {
|
||||
pinAll();
|
||||
});
|
||||
|
||||
scope.$on('toolbox-unpin', function () {
|
||||
unpinAll();
|
||||
})
|
||||
|
||||
scope.$on('toolbox-zoom-to-fit', function () {
|
||||
console.log('on toolbox-pin', arguments)
|
||||
});
|
||||
|
||||
scope.$on('toolbox-toggle-fullscreen', function () {
|
||||
console.log('on toolbox-unpin', arguments)
|
||||
})
|
||||
|
||||
scope.isEmpty = function() {
|
||||
return scope.data && scope.data.nodes && scope.data.nodes.length === 0;
|
||||
};
|
||||
@ -90,7 +126,7 @@ function hzEntitiesGraph() {
|
||||
d3.select(window).on('resize', resize);
|
||||
|
||||
function resize() {
|
||||
svg.attr('height', window.innerHeight - 168 + 'px')
|
||||
svg.attr('height', window.innerHeight - heightOffset + 'px')
|
||||
force.size([angular.element(svg[0]).width(),
|
||||
angular.element(svg[0]).height()])
|
||||
.resume();
|
||||
@ -108,6 +144,11 @@ function hzEntitiesGraph() {
|
||||
node.y = pin.y;
|
||||
}
|
||||
})
|
||||
|
||||
linksMap = {};
|
||||
_.each(scope.data.links, function(link) {
|
||||
linksMap[link.source.id + ',' + link.target.id] = true;
|
||||
});
|
||||
}
|
||||
|
||||
function createGraph() {
|
||||
@ -228,6 +269,7 @@ function hzEntitiesGraph() {
|
||||
}
|
||||
|
||||
window.drawGraph = drawGraph;
|
||||
window.dforce = force;
|
||||
|
||||
function drawGraph() {
|
||||
link = link.data(force.links(), function(d) { return d.source.id + '-' + d.target.id; });
|
||||
@ -275,28 +317,47 @@ function hzEntitiesGraph() {
|
||||
.attr('dominant-baseline', 'central')
|
||||
.attr('transform', 'scale(1)')
|
||||
.attr('class', function(d) {
|
||||
var cls = '';
|
||||
var severity = d.operational_severity;
|
||||
if (severity) {
|
||||
switch (severity.toLowerCase()) {
|
||||
case 'critical':
|
||||
cls = 'red';
|
||||
break;
|
||||
case 'severe':
|
||||
cls = 'orange';
|
||||
break;
|
||||
case 'warning':
|
||||
cls = 'yellow';
|
||||
break;
|
||||
case 'ok':
|
||||
cls = 'green';
|
||||
break;
|
||||
case 'n/a':
|
||||
cls = 'gray';
|
||||
break;
|
||||
default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
|
||||
cls = 'gray';
|
||||
break;
|
||||
var category = d.category,
|
||||
cls = '';
|
||||
|
||||
if (category && category.toLowerCase() === 'alarm') {
|
||||
var severity = d.operational_severity;
|
||||
if (severity) {
|
||||
switch (severity.toLowerCase()) {
|
||||
case 'critical':
|
||||
cls = 'red';
|
||||
break;
|
||||
case 'severe':
|
||||
cls = 'orange';
|
||||
break;
|
||||
case 'warning':
|
||||
cls = 'yellow';
|
||||
break;
|
||||
case 'ok':
|
||||
cls = 'green';
|
||||
break;
|
||||
case 'n/a':
|
||||
cls = 'gray';
|
||||
break;
|
||||
default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
|
||||
cls = 'gray';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var state = d.operational_state;
|
||||
if (state) {
|
||||
switch (state.toLowerCase()) {
|
||||
case 'error':
|
||||
cls = 'red';
|
||||
break;
|
||||
case 'suboptimal':
|
||||
cls = 'yellow';
|
||||
break;
|
||||
case 'n/a':
|
||||
cls = 'gray';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cls;
|
||||
@ -440,15 +501,48 @@ function hzEntitiesGraph() {
|
||||
|
||||
|
||||
if ($(this).is('.node')) {
|
||||
d3.select(this).classed('selected', true);
|
||||
//d3.select(this).classed('selected', true);
|
||||
|
||||
findHighlight(d);
|
||||
}
|
||||
}
|
||||
|
||||
function findHighlight(rootNode) {
|
||||
|
||||
_.each(scope.data.nodes, function(node) {
|
||||
node.high = false;
|
||||
})
|
||||
|
||||
var depth = hightlightDepth;
|
||||
|
||||
findNodes(rootNode, depth, scope.data.nodes, linksMap);
|
||||
|
||||
_.each(scope.data.links, function(link) {
|
||||
link.high = false;
|
||||
})
|
||||
|
||||
svg_g.selectAll('.node')
|
||||
.classed('selected', function(d) {
|
||||
return d.high;
|
||||
})
|
||||
.select('circle')
|
||||
.style('stroke-width', function(d) {
|
||||
return d.high ? (Math.max(d.highDepth + 1, 1) * 2) : null;
|
||||
})
|
||||
|
||||
svg_g.selectAll('.link').classed('selected', function(d) {
|
||||
return d.source.high && d.target.high;
|
||||
})
|
||||
}
|
||||
|
||||
function selectNone(d) {
|
||||
nodeClick(null);
|
||||
}
|
||||
|
||||
function pinNode(d) {
|
||||
d3.event.stopImmediatePropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
var node;
|
||||
|
||||
if ($(this).is('.node')) {
|
||||
@ -463,9 +557,6 @@ function hzEntitiesGraph() {
|
||||
updatePinnedCookie(d);
|
||||
}
|
||||
|
||||
d3.event.stopImmediatePropagation();
|
||||
d3.event.preventDefault();
|
||||
|
||||
//fixing some bug with unpinning
|
||||
/*setTimeout(function() {
|
||||
force.resume()
|
||||
@ -476,7 +567,7 @@ function hzEntitiesGraph() {
|
||||
var pinIndex = -1;
|
||||
pinned.forEach(function(pin, i) {
|
||||
if (pin.id === d.id) {
|
||||
pinIndex = i
|
||||
pinIndex = i;
|
||||
}
|
||||
})
|
||||
|
||||
@ -488,7 +579,7 @@ function hzEntitiesGraph() {
|
||||
pinned.push({id: d.id, x: d.x, y: d.y});
|
||||
}
|
||||
|
||||
horizon.cookies.put('pinned', pinned);
|
||||
horizon.cookies.put('pinned', JSON.stringify(pinned));
|
||||
}
|
||||
|
||||
function nodeDragend(d) {
|
||||
@ -497,6 +588,39 @@ function hzEntitiesGraph() {
|
||||
}
|
||||
}
|
||||
|
||||
function pinAll() {
|
||||
pinned = [];
|
||||
|
||||
svg_g.selectAll('.node')
|
||||
.classed('pinned', true)
|
||||
.each(function(d) {
|
||||
d.fixed = true;
|
||||
pinned.push({id: d.id, x: d.x, y: d.y});
|
||||
})
|
||||
|
||||
horizon.cookies.put('pinned', JSON.stringify(pinned));
|
||||
}
|
||||
|
||||
function unpinAll() {
|
||||
pinned = [];
|
||||
|
||||
svg_g.selectAll('.node')
|
||||
.classed('pinned', false)
|
||||
.each(function(d) {
|
||||
d.fixed = false;
|
||||
})
|
||||
|
||||
horizon.cookies.put('pinned', JSON.stringify([]));
|
||||
|
||||
setTimeout(function() {
|
||||
force.resume()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
function pinAllNodes(isPin) {
|
||||
|
||||
}
|
||||
|
||||
function setEllipsis(el, text, width) {
|
||||
|
||||
el.textContent = text;
|
||||
@ -516,6 +640,30 @@ function hzEntitiesGraph() {
|
||||
}
|
||||
};
|
||||
|
||||
function findNodes(rootNode, depth, allNodes, linksMap) {
|
||||
if (rootNode) {
|
||||
rootNode.high = true;
|
||||
rootNode.highDepth = depth;
|
||||
depth--;
|
||||
|
||||
_.each(allNodes, function(node) {
|
||||
if (linksMap[node.id + ',' + rootNode.id] || linksMap[rootNode.id + ',' + node.id]) {
|
||||
|
||||
if (depth > -1 && !node.high) {
|
||||
findNodes(node, depth, allNodes, linksMap);
|
||||
} else if (depth <= -1) {
|
||||
//Always find 'depth' + alarms & (sdns + alarms)
|
||||
if (node.category.toLowerCase() === 'alarm') {
|
||||
node.high = true;
|
||||
node.highDepth = 0;
|
||||
} else if (!node.high && node.type && node.type.toLowerCase() === 'sdn_controller') {
|
||||
findNodes(node, depth, allNodes, linksMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*function nodeDragstart(d) {
|
||||
d3.select(this).classed('pinned', d.fixed = true);
|
||||
|
@ -27,6 +27,11 @@ $dark_gray: darkgray;
|
||||
|
||||
.link {
|
||||
stroke-opacity: 0.8;
|
||||
|
||||
&.selected {
|
||||
stroke: $blue;
|
||||
stroke-width: 2 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.node {
|
||||
|
@ -0,0 +1,24 @@
|
||||
angular
|
||||
.module('horizon.dashboard.project.vitrage')
|
||||
.directive('hzEntitiesToolbox', hzEntitiesToolbox);
|
||||
|
||||
hzEntitiesToolbox.$inject = ['$rootScope'];
|
||||
|
||||
function hzEntitiesToolbox($rootScope) {
|
||||
var directive = {
|
||||
link: link,
|
||||
templateUrl: STATIC_URL + 'dashboard/project/entities/toolbox/entities-toolbox.html',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
item: '='
|
||||
}
|
||||
};
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attrs) {
|
||||
scope.broadcast = function(event) {
|
||||
console.log('click', event);
|
||||
$rootScope.$broadcast('toolbox-' + event);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
<div class="entities-toolbox">
|
||||
<div class="btn-group btn-group-xs" role="group">
|
||||
<a href="#" class="btn btn-default" ng-click="broadcast('pin')"><span class="fa fa-thumb-tack"></span> Pin</a>
|
||||
<a href="#" class="btn btn-default" ng-click="broadcast('unpin')">Unpin</a>
|
||||
</div>
|
||||
<!--<div class="btn-group btn-group-xs" role="group">
|
||||
<a href="#" class="btn btn-default" ng-click="broadcast('zoom-to-fit')"><span class="fa fa-expand"></span> Zoom to fit</a>
|
||||
</div>
|
||||
<div class="btn-group btn-group-xs" role="group">
|
||||
<a href="#" class="btn btn-default" ng-click="broadcast('toggle-fullscreen')"><span class="fa fa-square-o"></span> Toggle fullscreen</a>
|
||||
</div>-->
|
||||
</div>
|
@ -0,0 +1,17 @@
|
||||
.entities-toolbox {
|
||||
position: absolute;
|
||||
right: 18px;
|
||||
margin: 12px;
|
||||
padding:8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
|
||||
.btn-group {
|
||||
margin-right: 6px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
@import 'components/information/information';
|
||||
@import 'entities/graph/entities-graph.scss';
|
||||
@import 'entities/info/entities-info.scss';
|
||||
@import 'entities/toolbox/entities-toolbox.scss';
|
||||
@import 'entities/entities.scss';
|
||||
|
||||
.red {
|
||||
|
Loading…
x
Reference in New Issue
Block a user