Grouped injected vars and shortened findNodeById
Fixed syntax in Topo2NodeModel.js
Added SubRegions to the topo2 view
Change-Id: I04c793f3a9a98808eaa11049f31bbb166cc5b66f
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css b/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
index 3bdb8b2..e1551e4 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2-theme.css
@@ -171,6 +171,15 @@
fill: #454545;
}
+#ov-topo2 svg .node.sub-region rect {
+ fill: #ffffff;
+}
+
+#ov-topo2 svg .node.sub-region use {
+ /* NOTE: this gets overridden programatically */
+ fill: #454545;
+}
+
#ov-topo2 svg .node.device.selected rect {
stroke-width: 2.0;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2D3.js b/web/gui/src/main/webapp/app/view/topo2/topo2D3.js
index 604c907..2cd4ba7 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2D3.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2D3.js
@@ -111,8 +111,8 @@
}
}
- function deviceEnter(device) {
- device.onEnter(this, device);
+ function nodeEnter(node) {
+ node.onEnter(this, node);
}
function hostLabel(d) {
@@ -153,7 +153,7 @@
return {
init: init,
- deviceEnter: deviceEnter,
+ nodeEnter: nodeEnter,
hostEnter: hostEnter,
linkEntering: linkEntering
}
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Device.js b/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
index 5a4b528..c8478cf 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
@@ -30,7 +30,6 @@
// configuration
var devIconDim = 36,
- labelPad = 10,
hostRadius = 14,
badgeConfig = {
radius: 12,
@@ -44,8 +43,7 @@
i: 'badgeInfo',
w: 'badgeWarn',
e: 'badgeError'
- },
- deviceLabelIndex = 0;
+ };
function createDeviceCollection(data, region) {
@@ -74,24 +72,6 @@
return remappedDeviceTypes[type] || type || 'unknown';
}
- function deviceLabel(d) {
- //TODO: Device Json is missing labels array
- return "";
- var labels = this.get('labels'),
- idx = (deviceLabelIndex < labels.length) ? deviceLabelIndex : 0;
- return labels[idx];
- }
-
- function trimLabel(label) {
- return (label && label.trim()) || '';
- }
-
- function computeLabelWidth() {
- var text = this.select('text'),
- box = text.node().getBBox();
- return box.width + labelPad * 2;
- }
-
function iconBox(dim, labelWidth) {
return {
x: -dim / 2,
@@ -104,7 +84,7 @@
function deviceGlyphColor(d) {
var o = this.node.online,
- id = "127.0.0.1", // TODO: This should be from node.master
+ id = this.node.master, // TODO: This should be from node.master
otag = o ? 'online' : 'offline';
return o ? sus.cat7().getColor(id, 0, ts.theme())
: '#ff0000';
@@ -134,32 +114,25 @@
this.constructor.__super__.initialize.apply(this, arguments);
},
nodeType: 'device',
- deviceLabel: deviceLabel,
deviceGlyphColor: deviceGlyphColor,
mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
- trimLabel: trimLabel,
setDeviceColor: setDeviceColor,
onEnter: function (el) {
var node = d3.select(el),
glyphId = mapDeviceTypeToGlyph(this.get('type')),
- label = trimLabel(this.deviceLabel()),
- rect, text, glyph, labelWidth;
+ label = this.trimLabel(this.label()),
+ glyph, labelWidth;
this.el = node;
- rect = node.append('rect');
+ // Label
+ var labelElements = this.addLabelElements(label);
+ labelWidth = label ? this.computeLabelWidth(node) : 0;
+ labelElements.rect.attr(iconBox(devIconDim, labelWidth));
- text = node.append('text').text(label)
- .attr('text-anchor', 'left')
- .attr('y', '0.3em')
- .attr('x', halfDevIcon + labelPad);
-
+ // Icon
glyph = is.addDeviceIcon(node, glyphId, devIconDim);
-
- labelWidth = label ? computeLabelWidth(node) : 0;
-
- rect.attr(iconBox(devIconDim, labelWidth));
glyph.attr(iconBox(devIconDim, 0));
node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
index 8cfaadf..d2a49ea 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -193,7 +193,8 @@
.transition()
.attr('opacity', 1);
- entering.filter('.device').each(t2d3.deviceEnter);
+ entering.filter('.device').each(t2d3.nodeEnter);
+ entering.filter('.sub-region').each(t2d3.nodeEnter);
entering.filter('.host').each(t2d3.hostEnter);
// operate on both existing and new nodes:
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
index 44c5ec9..b7c3ea6 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
@@ -22,6 +22,7 @@
(function () {
'use strict';
+ var $log;
var Collection, Model, region, ts;
var widthRatio = 1.4,
@@ -55,7 +56,6 @@
function createLink() {
var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB'));
- console.log(this);
var attrs = angular.extend({}, linkPoints, {
key: this.get('id'),
@@ -78,19 +78,14 @@
function linkEndPoints(srcId, dstId) {
- var sourceNode = this.region.get('devices').get(srcId.substring(0, srcId.length -2));
- var targetNode = this.region.get('devices').get(dstId.substring(0, dstId.length -2));
+ var sourceNode = this.region.findNodeById(srcId)
+ var targetNode = this.region.findNodeById(dstId)
-// var srcNode = lu[srcId],
-// dstNode = lu[dstId],
-// sMiss = !srcNode ? missMsg('src', srcId) : '',
-// dMiss = !dstNode ? missMsg('dst', dstId) : '';
-//
-// if (sMiss || dMiss) {
-// $log.error('Node(s) not on map for link:' + sMiss + dMiss);
-// //logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
-// return null;
-// }
+ if (!sourceNode || !targetNode) {
+ $log.error('Node(s) not on map for link:' + srcId + ':' + dstId);
+ //logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
+ return null;
+ }
this.source = sourceNode.toJSON();
this.target = targetNode.toJSON();
@@ -118,31 +113,17 @@
return true;
return both && (s && s.online) && (t && t.online);
},
- linkWidth: function () {
- var s = this.get('fromSource'),
- t = this.get('fromTarget'),
- ws = (s && s.linkWidth) || 0,
- wt = (t && t.linkWidth) || 0;
-
- // console.log(s);
- // TODO: Current json is missing linkWidth
- return 1.2;
- return this.get('position').multiLink ? 5 : Math.max(ws, wt);
- },
-
restyleLinkElement: function (immediate) {
// this fn's job is to look at raw links and decide what svg classes
// need to be applied to the line element in the DOM
var th = ts.theme(),
el = this.el,
type = this.get('type'),
- lw = this.linkWidth(),
online = this.online(),
modeCls = this.expected() ? 'inactive' : 'not-permitted',
+ lw = 1.2,
delay = immediate ? 0 : 1000;
- console.log(type);
-
// NOTE: understand why el is sometimes undefined on addLink events...
// Investigated:
// el is undefined when it's a reverse link that is being added.
@@ -185,10 +166,11 @@
angular.module('ovTopo2')
.factory('Topo2LinkService',
- ['Topo2Collection', 'Topo2Model', 'ThemeService',
+ ['$log', 'Topo2Collection', 'Topo2Model', 'ThemeService',
- function (_Collection_, _Model_, _ts_) {
+ function (_$log_, _Collection_, _Model_, _ts_) {
+ $log = _$log_;
ts = _ts_;
Collection = _Collection_;
Model = _Model_;
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 54a2748..0e617dd 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -29,6 +29,11 @@
var defaultLinkType = 'direct',
nearDist = 15;
+ var devIconDim = 36,
+ labelPad = 10,
+ halfDevIcon = devIconDim / 2,
+ nodeLabelIndex = 1;
+
function positionNode(node, forUpdate) {
var meta = node.metaUi,
@@ -113,6 +118,36 @@
initialize: function () {
this.node = this.createNode();
},
+ label: function () {
+
+ var props = this.get('props'),
+ id = this.get('id'),
+ friendlyName = props ? props.name : id,
+ labels = ['', friendlyName, id],
+ idx = (nodeLabelIndex < labels.length) ? nodeLabelIndex : 0;
+
+ return labels[idx];
+ },
+ trimLabel: function(label) {
+ return (label && label.trim()) || '';
+ },
+ computeLabelWidth: function(el) {
+ var text = el.select('text'),
+ box = text.node().getBBox();
+ return box.width + labelPad * 2;
+ },
+ addLabelElements: function(label) {
+ var rect = this.el.append('rect');
+ var text = this.el.append('text').text(label)
+ .attr('text-anchor', 'left')
+ .attr('y', '0.3em')
+ .attr('x', halfDevIcon + labelPad);
+
+ return {
+ rect: rect,
+ text: text
+ }
+ },
svgClassName: function () {
return fn.classNames('node', this.nodeType, this.get('type'), {
online: this.get('online')
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
index 45c2652..67fec91 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
@@ -22,14 +22,11 @@
(function () {
'use strict';
- var $log,
- wss,
- Model,
- t2sr,
- t2ds,
- t2hs,
- t2ls;
+ // Injected Services
+ var $log, wss, t2sr, t2ds, t2hs, t2ls;
+ var Collection, Model;
+ //Internal
var region;
function init() {
@@ -38,9 +35,13 @@
function addRegion(data) {
- region = new Model({
+ var RegionModel = Model.extend({
+ findNodeById: findNodeById
+ })
+
+ region = new RegionModel({
id: data.id,
- layerOrder: data.layerOrder
+ layerOrder: data.layerOrder,
});
region.set({
@@ -50,8 +51,6 @@
links: t2ls.createLinkCollection(data.links, region),
});
- region.set('test', 2);
-
angular.forEach(region.get('links').models, function (link) {
link.createLink();
});
@@ -60,9 +59,23 @@
}
function regionNodes() {
- return [].concat(region.get('devices').models, region.get('hosts').models);
+ return [].concat(
+ region.get('devices').models,
+ region.get('hosts').models,
+ region.get('subregions').models
+ );
}
+ function findNodeById(id) {
+
+ // Remove /{port} from id if needed
+ var regex = new RegExp('^[^\/]*');
+ id = regex.exec(id)[0];
+
+ return region.get('devices').get(id) ||
+ region.get('hosts').get(id) ||
+ region.get('subregions').get(id);
+ }
function regionLinks() {
return region.get('links').models;
@@ -71,9 +84,9 @@
angular.module('ovTopo2')
.factory('Topo2RegionService',
['$log', 'WebSocketService', 'Topo2Model', 'Topo2SubRegionService', 'Topo2DeviceService',
- 'Topo2HostService', 'Topo2LinkService',
+ 'Topo2HostService', 'Topo2LinkService', 'Topo2Collection',
- function (_$log_, _wss_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_) {
+ function (_$log_, _wss_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_, _Collection_) {
$log = _$log_;
wss = _wss_;
@@ -82,6 +95,7 @@
t2ds = _t2ds_;
t2hs = _t2hs_;
t2ls = _t2ls_;
+ Collection = _Collection_;
return {
init: init,
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
index 421f57d..016c7b4 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2SubRegion.js
@@ -22,7 +22,30 @@
(function () {
'use strict';
- var Collection, Model;
+ var Collection, Model, is, sus, ts, t2vs;
+
+ var remappedDeviceTypes = {
+ virtual: 'cord'
+ };
+
+ // configuration
+ var devIconDim = 36,
+ labelPad = 10,
+ hostRadius = 14,
+ badgeConfig = {
+ radius: 12,
+ yoff: 5,
+ gdelta: 10
+ },
+ halfDevIcon = devIconDim / 2,
+ devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
+ hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
+ status = {
+ i: 'badgeInfo',
+ w: 'badgeWarn',
+ e: 'badgeError'
+ },
+ deviceLabelIndex = 0;
function createSubRegionCollection(data, region) {
@@ -33,14 +56,63 @@
return new SubRegionCollection(data);
}
+ function mapDeviceTypeToGlyph(type) {
+ return remappedDeviceTypes[type] || type || 'switch';
+ }
+
+ function iconBox(dim, labelWidth) {
+ return {
+ x: -dim / 2,
+ y: -dim / 2,
+ width: dim + labelWidth,
+ height: dim
+ }
+ }
+
angular.module('ovTopo2')
.factory('Topo2SubRegionService',
- ['Topo2Collection', 'Topo2Model',
+ ['Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService',
+ 'ThemeService', 'Topo2ViewService',
- function (_Collection_, _Model_) {
+ function (_Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) {
+ t2vs = _t2vs_;
+ is = _is_;
+ sus = _sus_;
+ ts = _ts_;
Collection = _Collection_;
- Model = _Model_.extend({});
+
+ Model = _NodeModel_.extend({
+ initialize: function () {
+ this.set('weight', 0);
+ this.constructor.__super__.initialize.apply(this, arguments);
+ },
+ nodeType: 'sub-region',
+ mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
+ onEnter: function (el) {
+
+ var node = d3.select(el),
+ glyphId = mapDeviceTypeToGlyph(this.get('type')),
+ label = this.trimLabel(this.label()),
+ glyph, labelWidth;
+
+ this.el = node;
+
+ // Label
+ var labelElements = this.addLabelElements(label);
+ labelWidth = label ? this.computeLabelWidth(node) : 0;
+ labelElements.rect.attr(iconBox(devIconDim, labelWidth));
+
+ // Icon
+ glyph = is.addDeviceIcon(node, glyphId, devIconDim);
+ glyph.attr(iconBox(devIconDim, 0));
+
+ node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
+ this.render();
+ },
+ onExit: function () {},
+ render: function () {}
+ });
return {
createSubRegionCollection: createSubRegionCollection