Steven Burrows

CSS Added fill-mode for nodes

Amends based on Simons Comments
ESLinted The whole project
Topo2Link - Added Labels for PortA and PortB on mouseover
Updated breadcrumbs
Topo2.js - commented out a line causing error on panning
Topo2 Navigation between regions

Change-Id: I9cc0f4499ab68a14e246bba192f6528258471b35
1 +module.exports = {
2 + "extends": "google",
3 + "installedESLint": true,
4 + "globals": {
5 + "angular": true,
6 + "d3": true
7 + },
8 + "rules": {
9 + "brace-style": 0,
10 + "no-void": 0,
11 + "require-jsdoc": 0,
12 + "padded-blocks": 0,
13 + "quote-props": 0,
14 + "no-warning-comments": 0,
15 + "object-curly-spacing": ["error", "always"],
16 + "indent": ["error", 4],
17 + "one-var": 0,
18 + "space-before-function-paren": ["error", { "anonymous": "always", "named": "never" }]
19 + }
20 +};
1 +{
2 + "name": "topo2",
3 + "version": "1.0.0",
4 + "description": "ONOS Topo2",
5 + "main": "topo2.js",
6 + "scripts": {
7 + "test": "echo \"Error: no test specified\" && exit 1",
8 + "lint": "./node_modules/.bin/eslint ./**/*.js"
9 + },
10 + "author": "",
11 + "license": "ISC",
12 + "devDependencies": {
13 + "eslint": "^3.4.0",
14 + "eslint-config-google": "^0.6.0"
15 + }
16 +}
...@@ -66,3 +66,10 @@ ...@@ -66,3 +66,10 @@
66 .floatpanel { 66 .floatpanel {
67 top: 104px; 67 top: 104px;
68 } 68 }
69 +
70 +
71 +/* -- Base Device Styles -- */
72 +#ov-topo2 svg .node {
73 + cursor: pointer;
74 + fill-rule: evenodd;
75 +}
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -24,18 +24,14 @@ ...@@ -24,18 +24,14 @@
24 'use strict'; 24 'use strict';
25 25
26 // references to injected services 26 // references to injected services
27 - var $scope, $log, $loc, 27 + var $scope, $log, fs, mast, ks, zs,
28 - fs, mast, ks, zs, 28 + gs, sus, ps, t2es, t2fs, t2is, t2bcs;
29 - gs, ms, sus, flash,
30 - wss, ps, th,
31 - t2es, t2fs, t2is, t2bcs;
32 29
33 // DOM elements 30 // DOM elements
34 - var ovtopo2, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer; 31 + var ovtopo2, svg, defs, zoomLayer, forceG;
35 32
36 // Internal state 33 // Internal state
37 - var zoomer, actionMap; 34 + var zoomer;
38 -
39 35
40 // --- Glyphs, Icons, and the like ----------------------------------- 36 // --- Glyphs, Icons, and the like -----------------------------------
41 37
...@@ -66,10 +62,10 @@ ...@@ -66,10 +62,10 @@
66 var sc = zoomer.scale(), 62 var sc = zoomer.scale(),
67 tr = zoomer.translate(); 63 tr = zoomer.translate();
68 64
69 - ps.setPrefs('topo_zoom', {tx:tr[0], ty:tr[1], sc:sc}); 65 + ps.setPrefs('topo_zoom', { tx: tr[0], ty: tr[1], sc: sc });
70 66
71 // keep the map lines constant width while zooming 67 // keep the map lines constant width while zooming
72 - mapG.style('stroke-width', (2.0 / sc) + 'px'); 68 + // mapG.style('stroke-width', (2.0 / sc) + 'px');
73 } 69 }
74 70
75 function setUpZoom() { 71 function setUpZoom() {
...@@ -82,7 +78,6 @@ ...@@ -82,7 +78,6 @@
82 }); 78 });
83 } 79 }
84 80
85 -
86 // === Controller Definition ----------------------------------------- 81 // === Controller Definition -----------------------------------------
87 82
88 angular.module('ovTopo2', ['onosUtil', 'onosSvg', 'onosRemote']) 83 angular.module('ovTopo2', ['onosUtil', 'onosSvg', 'onosRemote'])
...@@ -101,7 +96,6 @@ ...@@ -101,7 +96,6 @@
101 _t2es_, _t2fs_, _t2is_, _t2bcs_) { 96 _t2es_, _t2fs_, _t2is_, _t2bcs_) {
102 97
103 var params = _$loc_.search(), 98 var params = _$loc_.search(),
104 - projection,
105 dim, 99 dim,
106 wh, 100 wh,
107 uplink = { 101 uplink = {
...@@ -109,14 +103,13 @@ ...@@ -109,14 +103,13 @@
109 // showNoDevs: showNoDevs, 103 // showNoDevs: showNoDevs,
110 // projection: function () { return projection; }, 104 // projection: function () { return projection; },
111 zoomLayer: function () { return zoomLayer; }, 105 zoomLayer: function () { return zoomLayer; },
112 - zoomer: function () { return zoomer; }, 106 + zoomer: function () { return zoomer; }
113 // opacifyMap: opacifyMap, 107 // opacifyMap: opacifyMap,
114 // topoStartDone: topoStartDone 108 // topoStartDone: topoStartDone
115 }; 109 };
116 110
117 $scope = _$scope_; 111 $scope = _$scope_;
118 $log = _$log_; 112 $log = _$log_;
119 - $loc = _$loc_;
120 113
121 fs = _fs_; 114 fs = _fs_;
122 mast = _mast_; 115 mast = _mast_;
...@@ -124,13 +117,9 @@ ...@@ -124,13 +117,9 @@
124 zs = _zs_; 117 zs = _zs_;
125 118
126 gs = _gs_; 119 gs = _gs_;
127 - ms = _ms_;
128 sus = _sus_; 120 sus = _sus_;
129 - flash = _flash_;
130 121
131 - wss = _wss_;
132 ps = _ps_; 122 ps = _ps_;
133 - th = _th_;
134 123
135 t2es = _t2es_; 124 t2es = _t2es_;
136 t2fs = _t2fs_; 125 t2fs = _t2fs_;
...@@ -140,7 +129,10 @@ ...@@ -140,7 +129,10 @@
140 // capture selected intent parameters (if they are set in the 129 // capture selected intent parameters (if they are set in the
141 // query string) so that the traffic overlay can highlight 130 // query string) so that the traffic overlay can highlight
142 // the path for that intent 131 // the path for that intent
143 - if (params.intentKey && params.intentAppId && params.intentAppName) { 132 + if (params.intentKey &&
133 + params.intentAppId &&
134 + params.intentAppName) {
135 +
144 $scope.intentData = { 136 $scope.intentData = {
145 key: params.intentKey, 137 key: params.intentKey,
146 appId: params.intentAppId, 138 appId: params.intentAppId,
...@@ -169,7 +161,6 @@ ...@@ -169,7 +161,6 @@
169 svg.attr(wh); 161 svg.attr(wh);
170 dim = [wh.width, wh.height]; 162 dim = [wh.width, wh.height];
171 163
172 -
173 // set up our keyboard shortcut bindings 164 // set up our keyboard shortcut bindings
174 setUpKeys(); 165 setUpKeys();
175 setUpZoom(); 166 setUpZoom();
...@@ -183,7 +174,6 @@ ...@@ -183,7 +174,6 @@
183 t2fs.init(svg, forceG, uplink, dim); 174 t2fs.init(svg, forceG, uplink, dim);
184 t2bcs.init(); 175 t2bcs.init();
185 176
186 -
187 // =-=-=-=-=-=-=-=- 177 // =-=-=-=-=-=-=-=-
188 // TODO: in future, we will load background map data 178 // TODO: in future, we will load background map data
189 // asynchronously (hence the promise) and then chain off 179 // asynchronously (hence the promise) and then chain off
...@@ -191,12 +181,8 @@ ...@@ -191,12 +181,8 @@
191 // For now, we'll send the event inline... 181 // For now, we'll send the event inline...
192 t2es.start(); 182 t2es.start();
193 183
194 -
195 -
196 t2is.initInst({ showMastership: t2fs.showMastership }); 184 t2is.initInst({ showMastership: t2fs.showMastership });
197 185
198 -
199 -
200 // === ORIGINAL CODE === 186 // === ORIGINAL CODE ===
201 187
202 // setUpKeys(); 188 // setUpKeys();
...@@ -242,4 +228,4 @@ ...@@ -242,4 +228,4 @@
242 228
243 $log.log('OvTopo2Ctrl has been created'); 229 $log.log('OvTopo2Ctrl has been created');
244 }]); 230 }]);
245 -}()); 231 +})();
......
...@@ -19,16 +19,18 @@ ...@@ -19,16 +19,18 @@
19 Module that renders the breadcrumbs for regions 19 Module that renders the breadcrumbs for regions
20 */ 20 */
21 21
22 - (function () { 22 +(function () {
23 +
23 'use strict'; 24 'use strict';
24 25
25 var $log, wss; 26 var $log, wss;
26 27
28 + // Internal
27 var breadcrumbContainer, 29 var breadcrumbContainer,
28 breadcrumbs; 30 breadcrumbs;
29 31
30 function init() { 32 function init() {
31 - 33 + $log.debug("Topo2BreadcrumbService Initiated");
32 breadcrumbs = []; 34 breadcrumbs = [];
33 breadcrumbContainer = d3.select('#breadcrumbs'); 35 breadcrumbContainer = d3.select('#breadcrumbs');
34 render(); 36 render();
...@@ -36,13 +38,8 @@ ...@@ -36,13 +38,8 @@
36 38
37 function addBreadcrumb(crumbs) { 39 function addBreadcrumb(crumbs) {
38 40
39 - // If `crumbs` is an array, merge with breadcrumbs; 41 + breadcrumbContainer.selectAll('.breadcrumb').remove();
40 - if (crumbs.length) { 42 + breadcrumbs = crumbs.reverse();
41 - breadcrumbs = breadcrumbs.concat(crumbs);
42 - } else {
43 - breadcrumbs.push(crumbs);
44 - }
45 -
46 render(); 43 render();
47 } 44 }
48 45
......
...@@ -26,12 +26,14 @@ ...@@ -26,12 +26,14 @@
26 26
27 function Collection(models, options) { 27 function Collection(models, options) {
28 28
29 - options || (options = {}); 29 + var opts = options || (options = {});
30 30
31 this.models = []; 31 this.models = [];
32 this._reset(); 32 this._reset();
33 33
34 - if (options.comparator !== void 0) this.comparator = options.comparator; 34 + if (opts.comparator) {
35 + this.comparator = opts.comparator;
36 + }
35 37
36 if (models) { 38 if (models) {
37 this.add(models); 39 this.add(models);
...@@ -48,7 +50,8 @@ ...@@ -48,7 +50,8 @@
48 50
49 data.forEach(function (d) { 51 data.forEach(function (d) {
50 52
51 - var model = new _this.model(d); 53 + var CollectionModel = _this.model;
54 + var model = new CollectionModel(d);
52 model.collection = _this; 55 model.collection = _this;
53 56
54 _this.models.push(model); 57 _this.models.push(model);
...@@ -57,9 +60,11 @@ ...@@ -57,9 +60,11 @@
57 } 60 }
58 }, 61 },
59 get: function (id) { 62 get: function (id) {
63 +
60 if (!id) { 64 if (!id) {
61 - return void 0; 65 + return null;
62 } 66 }
67 +
63 return this._byId[id] || null; 68 return this._byId[id] || null;
64 }, 69 },
65 sort: function () { 70 sort: function () {
...@@ -76,9 +81,11 @@ ...@@ -76,9 +81,11 @@
76 this._byId = []; 81 this._byId = [];
77 this.models = []; 82 this.models = [];
78 }, 83 },
79 - toJSON: function(options) { 84 + toJSON: function (options) {
80 - return this.models.map(function(model) { return model.toJSON(options); }); 85 + return this.models.map(function (model) {
81 - }, 86 + return model.toJSON(options);
87 + });
88 + }
82 }; 89 };
83 90
84 Collection.extend = function (protoProps, staticProps) { 91 Collection.extend = function (protoProps, staticProps) {
......
...@@ -22,99 +22,21 @@ Module that contains the d3.force.layout logic ...@@ -22,99 +22,21 @@ Module that contains the d3.force.layout logic
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var sus, is, ts; 25 + var is;
26 -
27 - // internal state
28 - var deviceLabelIndex = 0,
29 - hostLabelIndex = 0;
30 -
31 - // configuration
32 - var devIconDim = 36,
33 - labelPad = 4,
34 - hostRadius = 14,
35 - badgeConfig = {
36 - radius: 12,
37 - yoff: 5,
38 - gdelta: 10
39 - },
40 - halfDevIcon = devIconDim / 2,
41 - devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
42 - hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
43 - status = {
44 - i: 'badgeInfo',
45 - w: 'badgeWarn',
46 - e: 'badgeError'
47 - };
48 26
49 - // note: these are the device icon colors without affinity (no master) 27 + // Configuration
50 - var dColTheme = { 28 + var hostRadius = 14;
51 - light: {
52 - online: '#444444',
53 - offline: '#cccccc'
54 - },
55 - dark: {
56 - // TODO: theme
57 - online: '#444444',
58 - offline: '#cccccc'
59 - }
60 - };
61 29
62 function init() {} 30 function init() {}
63 31
64 - function renderBadge(node, bdg, boff) {
65 - var bsel,
66 - bcr = badgeConfig.radius,
67 - bcgd = badgeConfig.gdelta;
68 -
69 - node.select('g.badge').remove();
70 -
71 - bsel = node.append('g')
72 - .classed('badge', true)
73 - .classed(badgeStatus(bdg), true)
74 - .attr('transform', sus.translate(boff.dx, boff.dy));
75 -
76 - bsel.append('circle')
77 - .attr('r', bcr);
78 -
79 - if (bdg.txt) {
80 - bsel.append('text')
81 - .attr('dy', badgeConfig.yoff)
82 - .attr('text-anchor', 'middle')
83 - .text(bdg.txt);
84 - } else if (bdg.gid) {
85 - bsel.append('use')
86 - .attr({
87 - width: bcgd * 2,
88 - height: bcgd * 2,
89 - transform: sus.translate(-bcgd, -bcgd),
90 - 'xlink:href': '#' + bdg.gid
91 - });
92 - }
93 - }
94 -
95 - // TODO: Move to Device Model when working on the Exit Devices
96 - function updateDeviceRendering(d) {
97 - var node = d.el,
98 - bdg = d.badge,
99 - label = trimLabel(deviceLabel(d)),
100 - labelWidth;
101 -
102 - node.select('text').text(label);
103 - labelWidth = label ? computeLabelWidth(node) : 0;
104 -
105 - node.select('rect')
106 - .transition()
107 - .attr(iconBox(devIconDim, labelWidth));
108 -
109 - if (bdg) {
110 - renderBadge(node, bdg, devBadgeOff);
111 - }
112 - }
113 -
114 function nodeEnter(node) { 32 function nodeEnter(node) {
115 node.onEnter(this, node); 33 node.onEnter(this, node);
116 } 34 }
117 35
36 + function nodeExit(node) {
37 + node.onExit(this, node);
38 + }
39 +
118 function hostLabel(d) { 40 function hostLabel(d) {
119 return d.get('id'); 41 return d.get('id');
120 42
...@@ -144,19 +66,18 @@ Module that contains the d3.force.layout logic ...@@ -144,19 +66,18 @@ Module that contains the d3.force.layout logic
144 66
145 angular.module('ovTopo2') 67 angular.module('ovTopo2')
146 .factory('Topo2D3Service', 68 .factory('Topo2D3Service',
147 - ['SvgUtilService', 'IconService', 'ThemeService', 69 + ['IconService',
148 70
149 - function (_sus_, _is_, _ts_) { 71 + function (_is_) {
150 - sus = _sus_;
151 is = _is_; 72 is = _is_;
152 - ts = _ts_;
153 73
154 return { 74 return {
155 init: init, 75 init: init,
156 nodeEnter: nodeEnter, 76 nodeEnter: nodeEnter,
77 + nodeExit: nodeExit,
157 hostEnter: hostEnter, 78 hostEnter: hostEnter,
158 linkEntering: linkEntering 79 linkEntering: linkEntering
159 - } 80 + };
160 } 81 }
161 ] 82 ]
162 ); 83 );
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var Collection, Model, is, sus, ts, t2vs; 25 + var Collection, Model, is, sus, ts;
26 26
27 var remappedDeviceTypes = { 27 var remappedDeviceTypes = {
28 virtual: 'cord' 28 virtual: 'cord'
...@@ -30,30 +30,17 @@ ...@@ -30,30 +30,17 @@
30 30
31 // configuration 31 // configuration
32 var devIconDim = 36, 32 var devIconDim = 36,
33 - labelPad = 10, 33 + halfDevIcon = devIconDim / 2;
34 - hostRadius = 14,
35 - badgeConfig = {
36 - radius: 12,
37 - yoff: 5,
38 - gdelta: 10
39 - },
40 - halfDevIcon = devIconDim / 2,
41 - devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
42 - hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
43 - status = {
44 - i: 'badgeInfo',
45 - w: 'badgeWarn',
46 - e: 'badgeError'
47 - },
48 - deviceLabelIndex = 0;
49 34
50 function createDeviceCollection(data, region) { 35 function createDeviceCollection(data, region) {
51 36
52 var DeviceCollection = Collection.extend({ 37 var DeviceCollection = Collection.extend({
53 model: Model, 38 model: Model,
54 - comparator: function(a, b) { 39 + comparator: function (a, b) {
55 - var order = region.get('layerOrder'); 40 + var order = region.get('layerOrder'),
56 - return order.indexOf(a.get('layer')) - order.indexOf(b.get('layer')); 41 + aLayer = a.get('layer'),
42 + bLayer = b.get('layer');
43 + return order.indexOf(aLayer - order.indexOf(bLayer));
57 } 44 }
58 }); 45 });
59 46
...@@ -80,7 +67,7 @@ ...@@ -80,7 +67,7 @@
80 y: -dim / 2, 67 y: -dim / 2,
81 width: dim + labelWidth, 68 width: dim + labelWidth,
82 height: dim 69 height: dim
83 - } 70 + };
84 } 71 }
85 72
86 // note: these are the device icon colors without affinity (no master) 73 // note: these are the device icon colors without affinity (no master)
...@@ -100,8 +87,9 @@ ...@@ -100,8 +87,9 @@
100 var o = this.node.online, 87 var o = this.node.online,
101 id = this.node.master, // TODO: This should be from node.master 88 id = this.node.master, // TODO: This should be from node.master
102 otag = o ? 'online' : 'offline'; 89 otag = o ? 'online' : 'offline';
103 - return o ? sus.cat7().getColor(id, 0, ts.theme()) 90 +
104 - : dColTheme[ts.theme()][otag]; 91 + return o ? sus.cat7().getColor(id, 0, ts.theme()) :
92 + dColTheme[ts.theme()][otag];
105 } 93 }
106 94
107 function setDeviceColor() { 95 function setDeviceColor() {
...@@ -111,18 +99,17 @@ ...@@ -111,18 +99,17 @@
111 99
112 angular.module('ovTopo2') 100 angular.module('ovTopo2')
113 .factory('Topo2DeviceService', 101 .factory('Topo2DeviceService',
114 - ['Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService', 102 + ['Topo2Collection', 'Topo2NodeModel', 'IconService',
115 - 'ThemeService', 'Topo2ViewService', 103 + 'SvgUtilService', 'ThemeService',
116 104
117 - function (_Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) { 105 + function (_c_, _nm_, _is_, _sus_, _ts_, classnames) {
118 106
119 - t2vs = _t2vs_;
120 is = _is_; 107 is = _is_;
121 sus = _sus_; 108 sus = _sus_;
122 ts = _ts_; 109 ts = _ts_;
123 - Collection = _Collection_; 110 + Collection = _c_;
124 111
125 - Model = _NodeModel_.extend({ 112 + Model = _nm_.extend({
126 initialize: function () { 113 initialize: function () {
127 this.set('weight', 0); 114 this.set('weight', 0);
128 this.constructor.__super__.initialize.apply(this, arguments); 115 this.constructor.__super__.initialize.apply(this, arguments);
...@@ -152,7 +139,19 @@ ...@@ -152,7 +139,19 @@
152 node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon)); 139 node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
153 this.render(); 140 this.render();
154 }, 141 },
155 - onExit: function () {}, 142 + onExit: function () {
143 + var node = this.el;
144 + node.select('use')
145 + .style('opacity', 0.5)
146 + .transition()
147 + .duration(800)
148 + .style('opacity', 0);
149 +
150 + node.selectAll('rect')
151 + .style('stroke-fill', '#555')
152 + .style('fill', '#888')
153 + .style('opacity', 0.5);
154 + },
156 render: function () { 155 render: function () {
157 this.setDeviceColor(); 156 this.setDeviceColor();
158 } 157 }
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
34 openListener; 34 openListener;
35 35
36 // TODO: only add heartbeat timer etc. if we really need to be doing that.. 36 // TODO: only add heartbeat timer etc. if we really need to be doing that..
37 -
38 // ========================== Helper Functions 37 // ========================== Helper Functions
39 38
40 function createHandlerMap() { 39 function createHandlerMap() {
...@@ -100,4 +99,4 @@ ...@@ -100,4 +99,4 @@
100 stop: stop 99 stop: stop
101 }; 100 };
102 }]); 101 }]);
103 -}()); 102 +})();
......
...@@ -26,43 +26,12 @@ ...@@ -26,43 +26,12 @@
26 var $log, 26 var $log,
27 wss; 27 wss;
28 28
29 - // SVG elements; 29 + var t2is, t2rs, t2ls, t2vs, t2bcs;
30 - var linkG,
31 - linkLabelG,
32 - numLinkLblsG,
33 - portLabelG,
34 - nodeG;
35 -
36 - // internal state
37 - var settings, // merged default settings and options
38 - force, // force layout object
39 - drag, // drag behavior handler
40 - network = {
41 - nodes: [],
42 - links: [],
43 - linksByDevice: {},
44 - lookup: {},
45 - revLinkToKey: {}
46 - },
47 - lu, // shorthand for lookup
48 - rlk, // shorthand for revLinktoKey
49 - showHosts = false, // whether hosts are displayed
50 - showOffline = true, // whether offline devices are displayed
51 - nodeLock = false, // whether nodes can be dragged or not (locked)
52 - fTimer, // timer for delayed force layout
53 - fNodesTimer, // timer for delayed nodes update
54 - fLinksTimer, // timer for delayed links update
55 - dim, // the dimensions of the force layout [w,h]
56 - linkNums = []; // array of link number labels
57 -
58 - // D3 selections;
59 - var link,
60 - linkLabel,
61 - node;
62 -
63 - var $log, wss, t2is, t2rs, t2ls, t2vs, t2bcs;
64 var svg, forceG, uplink, dim, opts; 30 var svg, forceG, uplink, dim, opts;
65 31
32 + // D3 Selections
33 + var node;
34 +
66 // ========================== Helper Functions 35 // ========================== Helper Functions
67 36
68 function init(_svg_, _forceG_, _uplink_, _dim_, _opts_) { 37 function init(_svg_, _forceG_, _uplink_, _dim_, _opts_) {
...@@ -70,7 +39,9 @@ ...@@ -70,7 +39,9 @@
70 forceG = _forceG_; 39 forceG = _forceG_;
71 uplink = _uplink_; 40 uplink = _uplink_;
72 dim = _dim_; 41 dim = _dim_;
73 - opts = _opts_ 42 + opts = _opts_;
43 +
44 + t2ls.init(svg, forceG, uplink, dim, opts);
74 } 45 }
75 46
76 function destroy() { 47 function destroy() {
...@@ -91,7 +62,7 @@ ...@@ -91,7 +62,7 @@
91 var parentRegion = data.parent; 62 var parentRegion = data.parent;
92 var span = topdiv.select('.parentRegion').select('span'); 63 var span = topdiv.select('.parentRegion').select('span');
93 span.text(parentRegion || '[no parent]'); 64 span.text(parentRegion || '[no parent]');
94 - span.classed('nav-me', !!parentRegion); 65 + span.classed('nav-me', Boolean(parentRegion));
95 } 66 }
96 67
97 function doTmpCurrentRegion(data) { 68 function doTmpCurrentRegion(data) {
...@@ -162,30 +133,23 @@ ...@@ -162,30 +133,23 @@
162 $log.debug('>> topo2CurrentRegion event:', data); 133 $log.debug('>> topo2CurrentRegion event:', data);
163 doTmpCurrentRegion(data); 134 doTmpCurrentRegion(data);
164 t2rs.addRegion(data); 135 t2rs.addRegion(data);
165 - t2ls.init(svg, forceG, uplink, dim, opts); 136 + t2ls.createForceLayout();
166 - t2ls.update();
167 - t2ls.start();
168 } 137 }
169 138
170 function topo2PeerRegions(data) { 139 function topo2PeerRegions(data) {
171 - $log.debug('>> topo2PeerRegions event:', data) 140 + $log.debug('>> topo2PeerRegions event:', data);
172 doTmpPeerRegions(data); 141 doTmpPeerRegions(data);
173 } 142 }
174 143
175 - function topo2PeerRegions(data) {
176 - $log.debug('>> topo2PeerRegions event:', data)
177 - }
178 -
179 function startDone(data) { 144 function startDone(data) {
180 $log.debug('>> topo2StartDone event:', data); 145 $log.debug('>> topo2StartDone event:', data);
181 } 146 }
182 147
183 -
184 function showMastership(masterId) { 148 function showMastership(masterId) {
185 - if (!masterId) { 149 + if (masterId) {
186 - restoreLayerState();
187 - } else {
188 showMastershipFor(masterId); 150 showMastershipFor(masterId);
151 + } else {
152 + restoreLayerState();
189 } 153 }
190 } 154 }
191 155
...@@ -224,10 +188,6 @@ ...@@ -224,10 +188,6 @@
224 t2ls.setDimensions(); 188 t2ls.setDimensions();
225 } 189 }
226 190
227 - function getDim() {
228 - return dim;
229 - }
230 -
231 // ========================== Main Service Definition 191 // ========================== Main Service Definition
232 192
233 angular.module('ovTopo2') 193 angular.module('ovTopo2')
...@@ -259,4 +219,4 @@ ...@@ -259,4 +219,4 @@
259 topo2PeerRegions: topo2PeerRegions 219 topo2PeerRegions: topo2PeerRegions
260 }; 220 };
261 }]); 221 }]);
262 -}()); 222 +})();
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var Collection, Model, t2vs; 25 + var Collection, Model;
26 26
27 function createHostCollection(data, region) { 27 function createHostCollection(data, region) {
28 28
...@@ -41,12 +41,10 @@ ...@@ -41,12 +41,10 @@
41 } 41 }
42 42
43 angular.module('ovTopo2') 43 angular.module('ovTopo2')
44 - .factory('Topo2HostService', 44 + .factory('Topo2HostService', [
45 - [
46 'Topo2Collection', 'Topo2NodeModel', 'Topo2ViewService', 45 'Topo2Collection', 'Topo2NodeModel', 'Topo2ViewService',
47 function (_Collection_, _NodeModel_, classnames, _t2vs_) { 46 function (_Collection_, _NodeModel_, classnames, _t2vs_) {
48 47
49 - t2vs = _t2vs_;
50 Collection = _Collection_; 48 Collection = _Collection_;
51 49
52 Model = _NodeModel_.extend({ 50 Model = _NodeModel_.extend({
......
...@@ -2,13 +2,7 @@ ...@@ -2,13 +2,7 @@
2 'use strict'; 2 'use strict';
3 3
4 // injected refs 4 // injected refs
5 - var $log, 5 + var $log, ps, sus, gs, ts;
6 - ps,
7 - sus,
8 - gs,
9 - ts,
10 - fs,
11 - flash;
12 6
13 // api from topo 7 // api from topo
14 var api; 8 var api;
...@@ -24,10 +18,8 @@ ...@@ -24,10 +18,8 @@
24 // internal state 18 // internal state
25 var onosInstances, 19 var onosInstances,
26 onosOrder, 20 onosOrder,
27 - oiShowMaster,
28 oiBox; 21 oiBox;
29 22
30 -
31 function addInstance(data) { 23 function addInstance(data) {
32 var id = data.id; 24 var id = data.id;
33 25
...@@ -51,30 +43,15 @@ ...@@ -51,30 +43,15 @@
51 } 43 }
52 } 44 }
53 45
54 - function removeInstance(data) {
55 - var id = data.id,
56 - d = onosInstances[id];
57 - if (d) {
58 - var idx = fs.find(id, onosOrder);
59 - if (idx >= 0) {
60 - onosOrder.splice(idx, 1);
61 - }
62 - delete onosInstances[id];
63 - updateInstances();
64 - } else {
65 - logicError('removeInstance lookup fail. ID = "' + id + '"');
66 - }
67 - }
68 -
69 // ========================== 46 // ==========================
70 47
71 function clickInst(d) { 48 function clickInst(d) {
72 var el = d3.select(this), 49 var el = d3.select(this),
73 aff = el.classed('affinity'); 50 aff = el.classed('affinity');
74 - if (!aff) { 51 + if (aff) {
75 - setAffinity(el, d);
76 - } else {
77 cancelAffinity(); 52 cancelAffinity();
53 + } else {
54 + setAffinity(el, d);
78 } 55 }
79 } 56 }
80 57
...@@ -86,7 +63,6 @@ ...@@ -86,7 +63,6 @@
86 63
87 // suppress all elements except nodes whose master is this instance 64 // suppress all elements except nodes whose master is this instance
88 api.showMastership(d.id); 65 api.showMastership(d.id);
89 - oiShowMaster = true;
90 } 66 }
91 67
92 function cancelAffinity() { 68 function cancelAffinity() {
...@@ -94,7 +70,6 @@ ...@@ -94,7 +70,6 @@
94 .classed('mastership affinity', false); 70 .classed('mastership affinity', false);
95 71
96 api.showMastership(null); 72 api.showMastership(null);
97 - oiShowMaster = false;
98 } 73 }
99 74
100 function attachUiBadge(svg) { 75 function attachUiBadge(svg) {
...@@ -173,7 +148,6 @@ ...@@ -173,7 +148,6 @@
173 updAttr('ns', nSw(d.switches)); 148 updAttr('ns', nSw(d.switches));
174 }); 149 });
175 150
176 -
177 // operate on new onos instances 151 // operate on new onos instances
178 var entering = onoses.enter() 152 var entering = onoses.enter()
179 .append('div') 153 .append('div')
...@@ -235,9 +209,7 @@ ...@@ -235,9 +209,7 @@
235 onoses.exit().remove(); 209 onoses.exit().remove();
236 } 210 }
237 211
238 -
239 // ========================== 212 // ==========================
240 -
241 function logicError(msg) { 213 function logicError(msg) {
242 if (showLogicErrors) { 214 if (showLogicErrors) {
243 $log.warn('TopoInstService: ' + msg); 215 $log.warn('TopoInstService: ' + msg);
...@@ -251,23 +223,11 @@ ...@@ -251,23 +223,11 @@
251 223
252 onosInstances = {}; 224 onosInstances = {};
253 onosOrder = []; 225 onosOrder = [];
254 - oiShowMaster = false;
255 226
256 // we want to update the instances, each time the theme changes 227 // we want to update the instances, each time the theme changes
257 ts.addListener(updateInstances); 228 ts.addListener(updateInstances);
258 } 229 }
259 230
260 - function destroyInst() {
261 - ts.removeListener(updateInstances);
262 -
263 - ps.destroyPanel(idIns);
264 - oiBox = null;
265 -
266 - onosInstances = {};
267 - onosOrder = [];
268 - oiShowMaster = false;
269 - }
270 -
271 function allInstances(data) { 231 function allInstances(data) {
272 $log.debug('Update all instances', data); 232 $log.debug('Update all instances', data);
273 233
...@@ -281,16 +241,14 @@ ...@@ -281,16 +241,14 @@
281 angular.module('ovTopo2') 241 angular.module('ovTopo2')
282 .factory('Topo2InstanceService', 242 .factory('Topo2InstanceService',
283 ['$log', 'PanelService', 'SvgUtilService', 'GlyphService', 243 ['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
284 - 'ThemeService', 'FnService', 'FlashService', 244 + 'ThemeService',
285 245
286 - function (_$log_, _ps_, _sus_, _gs_, _ts_, _fs_, _flash_) { 246 + function (_$log_, _ps_, _sus_, _gs_, _ts_) {
287 $log = _$log_; 247 $log = _$log_;
288 ps = _ps_; 248 ps = _ps_;
289 sus = _sus_; 249 sus = _sus_;
290 gs = _gs_; 250 gs = _gs_;
291 ts = _ts_; 251 ts = _ts_;
292 - fs = _fs_;
293 - flash = _flash_;
294 252
295 return { 253 return {
296 initInst: initInst, 254 initInst: initInst,
...@@ -298,4 +256,4 @@ ...@@ -298,4 +256,4 @@
298 }; 256 };
299 }]); 257 }]);
300 258
301 -}()); 259 +})();
......
...@@ -24,12 +24,10 @@ ...@@ -24,12 +24,10 @@
24 24
25 var $log, sus, t2rs, t2d3, t2vs, t2ss; 25 var $log, sus, t2rs, t2d3, t2vs, t2ss;
26 26
27 - var uplink, linkG, linkLabelG, numLinkLabelsG, nodeG, portLabelG; 27 + var uplink, linkG, linkLabelG, nodeG;
28 - var link, linkLabel, node; 28 + var link, node;
29 29
30 - var nodes, links, highlightedLink; 30 + var highlightedLink;
31 -
32 - var force;
33 31
34 // default settings for force layout 32 // default settings for force layout
35 var defaultSettings = { 33 var defaultSettings = {
...@@ -51,9 +49,9 @@ ...@@ -51,9 +49,9 @@
51 linkStrength: { 49 linkStrength: {
52 // note: key is link.type 50 // note: key is link.type
53 // range: {0.0 ... 1.0} 51 // range: {0.0 ... 1.0}
54 - //direct: 1.0, 52 + direct: 1.0,
55 - //optical: 1.0, 53 + optical: 1.0,
56 - //hostLink: 1.0, 54 + hostLink: 1.0,
57 _def_: 1.0 55 _def_: 1.0
58 } 56 }
59 }; 57 };
...@@ -79,23 +77,7 @@ ...@@ -79,23 +77,7 @@
79 var settings, // merged default settings and options 77 var settings, // merged default settings and options
80 force, // force layout object 78 force, // force layout object
81 drag, // drag behavior handler 79 drag, // drag behavior handler
82 - network = { 80 + nodeLock = false; // whether nodes can be dragged or not (locked)
83 - nodes: [],
84 - links: [],
85 - linksByDevice: {},
86 - lookup: {},
87 - revLinkToKey: {}
88 - },
89 - lu, // shorthand for lookup
90 - rlk, // shorthand for revLinktoKey
91 - showHosts = false, // whether hosts are displayed
92 - showOffline = true, // whether offline devices are displayed
93 - nodeLock = false, // whether nodes can be dragged or not (locked)
94 - fTimer, // timer for delayed force layout
95 - fNodesTimer, // timer for delayed nodes update
96 - fLinksTimer, // timer for delayed links update
97 - dim, // the dimensions of the force layout [w,h]
98 - linkNums = []; // array of link number labels
99 81
100 var tickStuff = { 82 var tickStuff = {
101 nodeAttr: { 83 nodeAttr: {
...@@ -110,14 +92,6 @@ ...@@ -110,14 +92,6 @@
110 y1: function (d) { return d.get('position').y1; }, 92 y1: function (d) { return d.get('position').y1; },
111 x2: function (d) { return d.get('position').x2; }, 93 x2: function (d) { return d.get('position').x2; },
112 y2: function (d) { return d.get('position').y2; } 94 y2: function (d) { return d.get('position').y2; }
113 - },
114 - linkLabelAttr: {
115 - transform: function (d) {
116 - var lnk = tms.findLinkById(d.get('key'));
117 - if (lnk) {
118 - return t2d3.transformLabel(lnk.get('position'));
119 - }
120 - }
121 } 95 }
122 }; 96 };
123 97
...@@ -129,14 +103,19 @@ ...@@ -129,14 +103,19 @@
129 103
130 linkG = forceG.append('g').attr('id', 'topo-links'); 104 linkG = forceG.append('g').attr('id', 'topo-links');
131 linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels'); 105 linkLabelG = forceG.append('g').attr('id', 'topo-linkLabels');
132 - numLinkLabelsG = forceG.append('g').attr('id', 'topo-numLinkLabels'); 106 + forceG.append('g').attr('id', 'topo-numLinkLabels');
133 nodeG = forceG.append('g').attr('id', 'topo-nodes'); 107 nodeG = forceG.append('g').attr('id', 'topo-nodes');
134 - portLabelG = forceG.append('g').attr('id', 'topo-portLabels'); 108 + forceG.append('g').attr('id', 'topo-portLabels');
135 109
136 link = linkG.selectAll('.link'); 110 link = linkG.selectAll('.link');
137 - linkLabel = linkLabelG.selectAll('.linkLabel'); 111 + linkLabelG.selectAll('.linkLabel');
138 node = nodeG.selectAll('.node'); 112 node = nodeG.selectAll('.node');
139 113
114 + _svg_.on('mousemove', mouseMoveHandler);
115 + }
116 +
117 + function createForceLayout() {
118 +
140 force = d3.layout.force() 119 force = d3.layout.force()
141 .size(t2vs.getDimensions()) 120 .size(t2vs.getDimensions())
142 .nodes(t2rs.regionNodes()) 121 .nodes(t2rs.regionNodes())
...@@ -151,7 +130,8 @@ ...@@ -151,7 +130,8 @@
151 drag = sus.createDragBehavior(force, 130 drag = sus.createDragBehavior(force,
152 t2ss.selectObject, atDragEnd, dragEnabled, clickEnabled); 131 t2ss.selectObject, atDragEnd, dragEnabled, clickEnabled);
153 132
154 - _svg_.on('mousemove', mouseMoveHandler) 133 + start();
134 + update();
155 } 135 }
156 136
157 function zoomingOrPanning(ev) { 137 function zoomingOrPanning(ev) {
...@@ -188,9 +168,6 @@ ...@@ -188,9 +168,6 @@
188 .attr(tickStuff.linkAttr); 168 .attr(tickStuff.linkAttr);
189 // t2d3.applyNumLinkLabels(linkNums, numLinkLabelsG); 169 // t2d3.applyNumLinkLabels(linkNums, numLinkLabelsG);
190 } 170 }
191 - if (linkLabel && linkLabel.size()) {
192 - linkLabel.attr(tickStuff.linkLabelAttr);
193 - }
194 } 171 }
195 172
196 function update() { 173 function update() {
...@@ -210,7 +187,7 @@ ...@@ -210,7 +187,7 @@
210 .append('g') 187 .append('g')
211 .attr({ 188 .attr({
212 id: function (d) { return sus.safeId(d.get('id')); }, 189 id: function (d) { return sus.safeId(d.get('id')); },
213 - class: function (d) { return d.svgClassName() }, 190 + class: function (d) { return d.svgClassName(); },
214 transform: function (d) { 191 transform: function (d) {
215 // Need to guard against NaN here ?? 192 // Need to guard against NaN here ??
216 return sus.translate(d.node.x, d.node.y); 193 return sus.translate(d.node.x, d.node.y);
...@@ -227,10 +204,18 @@ ...@@ -227,10 +204,18 @@
227 entering.filter('.sub-region').each(t2d3.nodeEnter); 204 entering.filter('.sub-region').each(t2d3.nodeEnter);
228 entering.filter('.host').each(t2d3.hostEnter); 205 entering.filter('.host').each(t2d3.hostEnter);
229 206
230 - // operate on both existing and new nodes: 207 + // operate on exiting nodes:
231 - // node.filter('.device').each(function (device) { 208 + // Note that the node is removed after 2 seconds.
232 - // t2d3.updateDeviceColors(device); 209 + // Sub element animations should be shorter than 2 seconds.
233 - // }); 210 + var exiting = node.exit()
211 + .transition()
212 + .duration(2000)
213 + .style('opacity', 0)
214 + .remove();
215 +
216 + // exiting node specifics:
217 + // exiting.filter('.host').each(t2d3.hostExit);
218 + exiting.filter('.device').each(t2d3.nodeExit);
234 } 219 }
235 220
236 function _updateLinks() { 221 function _updateLinks() {
...@@ -241,16 +226,6 @@ ...@@ -241,16 +226,6 @@
241 link = linkG.selectAll('.link') 226 link = linkG.selectAll('.link')
242 .data(regionLinks, function (d) { return d.get('key'); }); 227 .data(regionLinks, function (d) { return d.get('key'); });
243 228
244 - // operate on existing links:
245 - link.each(function (d) {
246 - // this is supposed to be an existing link, but we have observed
247 - // occasions (where links are deleted and added rapidly?) where
248 - // the DOM element has not been defined. So protect against that...
249 - if (d.el) {
250 - restyleLinkElement(d, true);
251 - }
252 - });
253 -
254 // operate on entering links: 229 // operate on entering links:
255 var entering = link.enter() 230 var entering = link.enter()
256 .append('line') 231 .append('line')
...@@ -260,14 +235,14 @@ ...@@ -260,14 +235,14 @@
260 y1: function (d) { return d.get('position').y1; }, 235 y1: function (d) { return d.get('position').y1; },
261 x2: function (d) { return d.get('position').x2; }, 236 x2: function (d) { return d.get('position').x2; },
262 y2: function (d) { return d.get('position').y2; }, 237 y2: function (d) { return d.get('position').y2; },
263 - stroke: linkConfig['light'].inColor, 238 + stroke: linkConfig.light.inColor,
264 'stroke-width': linkConfig.inWidth 239 'stroke-width': linkConfig.inWidth
265 }); 240 });
266 241
267 entering.each(t2d3.linkEntering); 242 entering.each(t2d3.linkEntering);
268 243
269 // operate on both existing and new links: 244 // operate on both existing and new links:
270 - //link.each(...) 245 + // link.each(...)
271 246
272 // add labels for how many links are in a thick line 247 // add labels for how many links are in a thick line
273 // t2d3.applyNumLinkLabels(linkNums, numLinkLabelsG); 248 // t2d3.applyNumLinkLabels(linkNums, numLinkLabelsG);
...@@ -278,7 +253,7 @@ ...@@ -278,7 +253,7 @@
278 // operate on exiting links: 253 // operate on exiting links:
279 link.exit() 254 link.exit()
280 .attr('stroke-dasharray', '3 3') 255 .attr('stroke-dasharray', '3 3')
281 - .attr('stroke', linkConfig['light'].outColor) 256 + .attr('stroke', linkConfig.light.outColor)
282 .style('opacity', 0.5) 257 .style('opacity', 0.5)
283 .transition() 258 .transition()
284 .duration(1500) 259 .duration(1500)
...@@ -291,9 +266,7 @@ ...@@ -291,9 +266,7 @@
291 } 266 }
292 267
293 function calcPosition() { 268 function calcPosition() {
294 - var lines = this, 269 + var lines = this;
295 - linkSrcId,
296 - linkNums = [];
297 270
298 lines.each(function (d) { 271 lines.each(function (d) {
299 if (d.get('type') === 'hostLink') { 272 if (d.get('type') === 'hostLink') {
...@@ -301,17 +274,6 @@ ...@@ -301,17 +274,6 @@
301 } 274 }
302 }); 275 });
303 276
304 - function normalizeLinkSrc(link) {
305 - // ensure source device is consistent across set of links
306 - // temporary measure until link modeling is refactored
307 - if (!linkSrcId) {
308 - linkSrcId = link.source.id;
309 - return false;
310 - }
311 -
312 - return link.source.id !== linkSrcId;
313 - }
314 -
315 lines.each(function (d) { 277 lines.each(function (d) {
316 d.set('position', getDefaultPos(d)); 278 d.set('position', getDefaultPos(d));
317 }); 279 });
...@@ -333,7 +295,6 @@ ...@@ -333,7 +295,6 @@
333 } 295 }
334 } 296 }
335 297
336 -
337 function start() { 298 function start() {
338 force.start(); 299 force.start();
339 } 300 }
...@@ -343,7 +304,6 @@ ...@@ -343,7 +304,6 @@
343 var mp = getLogicalMousePosition(this), 304 var mp = getLogicalMousePosition(this),
344 link = computeNearestLink(mp); 305 link = computeNearestLink(mp);
345 306
346 -
347 if (highlightedLink) { 307 if (highlightedLink) {
348 highlightedLink.unenhance(); 308 highlightedLink.unenhance();
349 highlightedLink = null; 309 highlightedLink = null;
...@@ -363,11 +323,12 @@ ...@@ -363,11 +323,12 @@
363 tr = uplink.zoomer().translate(), 323 tr = uplink.zoomer().translate(),
364 mx = (m[0] - tr[0]) / sc, 324 mx = (m[0] - tr[0]) / sc,
365 my = (m[1] - tr[1]) / sc; 325 my = (m[1] - tr[1]) / sc;
366 - return {x: mx, y: my}; 326 + return { x: mx, y: my };
367 } 327 }
368 328
369 - 329 + function sq(x) {
370 - function sq(x) { return x * x; } 330 + return x * x;
331 + }
371 332
372 function mdist(p, m) { 333 function mdist(p, m) {
373 return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y)); 334 return Math.sqrt(sq(p.x - m.x) + sq(p.y - m.y));
...@@ -377,33 +338,6 @@ ...@@ -377,33 +338,6 @@
377 return dist / uplink.zoomer().scale(); 338 return dist / uplink.zoomer().scale();
378 } 339 }
379 340
380 - function computeNearestNode(mouse) {
381 - var proximity = prox(30),
382 - nearest = null,
383 - minDist,
384 - regionNodes = t2rs.regionNodes();
385 -
386 - if (regionNodes.length) {
387 - minDist = proximity * 2;
388 -
389 - regionNodes.forEach(function (d) {
390 - var dist;
391 -
392 - if (!api.showHosts() && d.class === 'host') {
393 - return; // skip hidden hosts
394 - }
395 -
396 - dist = mdist({x: d.x, y: d.y}, mouse);
397 - if (dist < minDist && dist < proximity) {
398 - minDist = dist;
399 - nearest = d;
400 - }
401 - });
402 - }
403 - return nearest;
404 - }
405 -
406 -
407 function computeNearestLink(mouse) { 341 function computeNearestLink(mouse) {
408 var proximity = prox(30), 342 var proximity = prox(30),
409 nearest = null, 343 nearest = null,
...@@ -418,11 +352,11 @@ ...@@ -418,11 +352,11 @@
418 y2 = line.y2, 352 y2 = line.y2,
419 x3 = mouse.x, 353 x3 = mouse.x,
420 y3 = mouse.y, 354 y3 = mouse.y,
421 - k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / 355 + k = ((y2 - y1) * (x3 - x1) - (x2 - x1) * (y3 - y1)) /
422 - (sq(y2-y1) + sq(x2-x1)), 356 + (sq(y2 - y1) + sq(x2 - x1)),
423 - x4 = x3 - k * (y2-y1), 357 + x4 = x3 - k * (y2 - y1),
424 - y4 = y3 + k * (x2-x1); 358 + y4 = y3 + k * (x2 - x1);
425 - return {x:x4, y:y4}; 359 + return { x: x4, y: y4 };
426 } 360 }
427 361
428 function lineHit(line, p, m) { 362 function lineHit(line, p, m) {
...@@ -476,11 +410,12 @@ ...@@ -476,11 +410,12 @@
476 410
477 return { 411 return {
478 init: init, 412 init: init,
413 + createForceLayout: createForceLayout,
479 update: update, 414 update: update,
480 start: start, 415 start: start,
481 416
482 setDimensions: setDimensions 417 setDimensions: setDimensions
483 - } 418 + };
484 } 419 }
485 ] 420 ]
486 ); 421 );
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
23 'use strict'; 23 'use strict';
24 24
25 var $log; 25 var $log;
26 - var Collection, Model, region, ts, sus; 26 + var Collection, Model, ts, sus;
27 27
28 var linkLabelOffset = '0.35em'; 28 var linkLabelOffset = '0.35em';
29 29
...@@ -52,9 +52,6 @@ ...@@ -52,9 +52,6 @@
52 outWidth: 10 52 outWidth: 10
53 }; 53 };
54 54
55 - var defaultLinkType = 'direct',
56 - nearDist = 15;
57 -
58 function createLink() { 55 function createLink() {
59 56
60 var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB')); 57 var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB'));
...@@ -92,14 +89,18 @@ ...@@ -92,14 +89,18 @@
92 return box; 89 return box;
93 } 90 }
94 91
92 + function isLinkOnline(node) {
93 + return (node.get('nodeType') === 'region') ? true : node.get('online');
94 + }
95 +
95 function linkEndPoints(srcId, dstId) { 96 function linkEndPoints(srcId, dstId) {
96 97
97 - var sourceNode = this.region.findNodeById(srcId) 98 + var sourceNode = this.region.findNodeById(srcId);
98 - var targetNode = this.region.findNodeById(dstId) 99 + var targetNode = this.region.findNodeById(dstId);
99 100
100 if (!sourceNode || !targetNode) { 101 if (!sourceNode || !targetNode) {
101 $log.error('Node(s) not on map for link:' + srcId + ':' + dstId); 102 $log.error('Node(s) not on map for link:' + srcId + ':' + dstId);
102 - //logicError('Node(s) not on map for link:\n' + sMiss + dMiss); 103 + // logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
103 return null; 104 return null;
104 } 105 }
105 106
...@@ -126,10 +127,13 @@ ...@@ -126,10 +127,13 @@
126 return true; 127 return true;
127 }, 128 },
128 online: function () { 129 online: function () {
129 - // TODO: remove next line
130 - return true;
131 130
132 - return both && (s && s.online) && (t && t.online); 131 + var source = this.get('source'),
132 + target = this.get('target'),
133 + sourceOnline = isLinkOnline(source),
134 + targetOnline = isLinkOnline(target);
135 +
136 + return (sourceOnline) && (targetOnline);
133 }, 137 },
134 enhance: function () { 138 enhance: function () {
135 var data = [], 139 var data = [],
...@@ -147,7 +151,17 @@ ...@@ -147,7 +151,17 @@
147 }); 151 });
148 data.push(point); 152 data.push(point);
149 153
150 - var entering = d3.select('#topo-portLabels').selectAll('.portLabel') 154 + if (this.get('portA')) {
155 + point = this.locatePortLabel(1);
156 + angular.extend(point, {
157 + id: 'topo-port-src',
158 + num: this.get('portA')
159 + });
160 + data.push(point);
161 + }
162 +
163 + var entering = d3.select('#topo-portLabels')
164 + .selectAll('.portLabel')
151 .data(data).enter().append('g') 165 .data(data).enter().append('g')
152 .classed('portLabel', true) 166 .classed('portLabel', true)
153 .attr('id', function (d) { return d.id; }); 167 .attr('id', function (d) { return d.id; });
...@@ -171,7 +185,7 @@ ...@@ -171,7 +185,7 @@
171 this.el.classed('enhanced', false); 185 this.el.classed('enhanced', false);
172 d3.select('#topo-portLabels').selectAll('.portLabel').remove(); 186 d3.select('#topo-portLabels').selectAll('.portLabel').remove();
173 }, 187 },
174 - locatePortLabel: function (link, src) { 188 + locatePortLabel: function (src) {
175 var offset = 32, 189 var offset = 32,
176 pos = this.get('position'), 190 pos = this.get('position'),
177 nearX = src ? pos.x1 : pos.x2, 191 nearX = src ? pos.x1 : pos.x2,
...@@ -179,13 +193,15 @@ ...@@ -179,13 +193,15 @@
179 farX = src ? pos.x2 : pos.x1, 193 farX = src ? pos.x2 : pos.x1,
180 farY = src ? pos.y2 : pos.y1; 194 farY = src ? pos.y2 : pos.y1;
181 195
182 - function dist(x, y) { return Math.sqrt(x*x + y*y); } 196 + function dist(x, y) {
197 + return Math.sqrt(x * x + y * y);
198 + }
183 199
184 var dx = farX - nearX, 200 var dx = farX - nearX,
185 dy = farY - nearY, 201 dy = farY - nearY,
186 k = offset / dist(dx, dy); 202 k = offset / dist(dx, dy);
187 203
188 - return {x: k * dx + nearX, y: k * dy + nearY}; 204 + return { x: k * dx + nearX, y: k * dy + nearY };
189 }, 205 },
190 restyleLinkElement: function (immediate) { 206 restyleLinkElement: function (immediate) {
191 // this fn's job is to look at raw links and decide what svg classes 207 // this fn's job is to look at raw links and decide what svg classes
...@@ -219,21 +235,19 @@ ...@@ -219,21 +235,19 @@
219 } 235 }
220 }, 236 },
221 onEnter: function (el) { 237 onEnter: function (el) {
222 - var _this = this, 238 + var link = d3.select(el);
223 - link = d3.select(el);
224 239
225 this.el = link; 240 this.el = link;
226 -
227 this.restyleLinkElement(); 241 this.restyleLinkElement();
228 242
229 if (this.get('type') === 'hostLink') { 243 if (this.get('type') === 'hostLink') {
230 - sus.visible(link, api.showHosts()); 244 + // sus.visible(link, api.showHosts());
231 } 245 }
232 } 246 }
233 }); 247 });
234 248
235 var LinkCollection = Collection.extend({ 249 var LinkCollection = Collection.extend({
236 - model: LinkModel, 250 + model: LinkModel
237 }); 251 });
238 252
239 return new LinkCollection(data); 253 return new LinkCollection(data);
...@@ -241,7 +255,8 @@ ...@@ -241,7 +255,8 @@
241 255
242 angular.module('ovTopo2') 256 angular.module('ovTopo2')
243 .factory('Topo2LinkService', 257 .factory('Topo2LinkService',
244 - ['$log', 'Topo2Collection', 'Topo2Model', 'ThemeService', 'SvgUtilService', 258 + ['$log', 'Topo2Collection', 'Topo2Model',
259 + 'ThemeService', 'SvgUtilService',
245 260
246 function (_$log_, _Collection_, _Model_, _ts_, _sus_) { 261 function (_$log_, _Collection_, _Model_, _ts_, _sus_) {
247 262
......
...@@ -42,7 +42,7 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout. ...@@ -42,7 +42,7 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout.
42 return this.attributes[attr]; 42 return this.attributes[attr];
43 }, 43 },
44 44
45 - set: function(key, val, options) { 45 + set: function (key, val, options) {
46 46
47 if (!key) { 47 if (!key) {
48 return this; 48 return this;
...@@ -56,10 +56,10 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout. ...@@ -56,10 +56,10 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout.
56 (attributes = {})[key] = val; 56 (attributes = {})[key] = val;
57 } 57 }
58 58
59 - options || (options = {}); 59 + var opts = options || (options = {});
60 60
61 - var unset = options.unset, 61 + var unset = opts.unset,
62 - silent = options.silent, 62 + silent = opts.silent,
63 changes = [], 63 changes = [],
64 changing = this._changing; 64 changing = this._changing;
65 65
...@@ -68,7 +68,9 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout. ...@@ -68,7 +68,9 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout.
68 if (!changing) { 68 if (!changing) {
69 69
70 // NOTE: angular.copy causes issues in chrome 70 // NOTE: angular.copy causes issues in chrome
71 - this._previousAttributes = Object.create(Object.getPrototypeOf(this.attributes)); 71 + this._previousAttributes = Object.create(
72 + Object.getPrototypeOf(this.attributes)
73 + );
72 this.changed = {}; 74 this.changed = {};
73 } 75 }
74 76
...@@ -84,34 +86,38 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout. ...@@ -84,34 +86,38 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout.
84 changes.push(index); 86 changes.push(index);
85 } 87 }
86 88
87 - if (!angular.equals(previous[index], val)) { 89 + if (angular.equals(previous[index], val)) {
88 - changed[index] = val;
89 - } else {
90 delete changed[index]; 90 delete changed[index];
91 + } else {
92 + changed[index] = val;
91 } 93 }
92 94
93 - unset ? delete current[index] : current[index] = val; 95 + if (unset) {
96 + delete current[index];
97 + } else {
98 + current[index] = val;
99 + }
94 }); 100 });
95 101
96 // Trigger all relevant attribute changes. 102 // Trigger all relevant attribute changes.
97 if (!silent) { 103 if (!silent) {
98 if (changes.length) { 104 if (changes.length) {
99 - this._pending = options; 105 + this._pending = opts;
100 } 106 }
101 for (var i = 0; i < changes.length; i++) { 107 for (var i = 0; i < changes.length; i++) {
102 - this.onChange(changes[i], this, current[changes[i]], options); 108 + this.onChange(changes[i], this,
109 + current[changes[i]], opts);
103 } 110 }
104 } 111 }
105 112
106 this._changing = false; 113 this._changing = false;
107 return this; 114 return this;
108 }, 115 },
109 - toJSON: function(options) { 116 + toJSON: function (options) {
110 - return angular.copy(this.attributes) 117 + return angular.copy(this.attributes);
111 - }, 118 + }
112 }; 119 };
113 120
114 -
115 Model.extend = function (protoProps, staticProps) { 121 Model.extend = function (protoProps, staticProps) {
116 122
117 var parent = this; 123 var parent = this;
...@@ -136,8 +142,7 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout. ...@@ -136,8 +142,7 @@ Visualization of the topology in an SVG layer, using a D3 Force Layout.
136 }; 142 };
137 143
138 angular.module('ovTopo2') 144 angular.module('ovTopo2')
139 - .factory('Topo2Model', 145 + .factory('Topo2Model', [
140 - [
141 function () { 146 function () {
142 return Model; 147 return Model;
143 } 148 }
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
25 var randomService; 25 var randomService;
26 var fn; 26 var fn;
27 27
28 - //internal state; 28 + // Internal state;
29 - var defaultLinkType = 'direct', 29 + var nearDist = 15;
30 - nearDist = 15;
31 30
32 var devIconDim = 36, 31 var devIconDim = 36,
33 labelPad = 10, 32 labelPad = 10,
...@@ -42,9 +41,9 @@ ...@@ -42,9 +41,9 @@
42 dim = [800, 600], 41 dim = [800, 600],
43 xy; 42 xy;
44 43
45 - // if the device contains explicit LONG/LAT data, use that to position 44 + // If the device contains explicit LONG/LAT data, use that to position
46 if (setLongLat(node)) { 45 if (setLongLat(node)) {
47 - //indicate we want to update cached meta data... 46 + // Indicate we want to update cached meta data...
48 return true; 47 return true;
49 } 48 }
50 49
...@@ -118,25 +117,28 @@ ...@@ -118,25 +117,28 @@
118 initialize: function () { 117 initialize: function () {
119 this.node = this.createNode(); 118 this.node = this.createNode();
120 }, 119 },
120 + onEnter: function () {}, // To be overridden by sub-class
121 + onExit: function () {}, // To be overridden by sub-class
121 label: function () { 122 label: function () {
122 123
123 var props = this.get('props'), 124 var props = this.get('props'),
124 id = this.get('id'), 125 id = this.get('id'),
125 friendlyName = props ? props.name : id, 126 friendlyName = props ? props.name : id,
126 labels = ['', friendlyName, id], 127 labels = ['', friendlyName, id],
127 - idx = (nodeLabelIndex < labels.length) ? nodeLabelIndex : 0; 128 + nli = nodeLabelIndex,
129 + idx = (nli < labels.length) ? nli : 0;
128 130
129 return labels[idx]; 131 return labels[idx];
130 }, 132 },
131 - trimLabel: function(label) { 133 + trimLabel: function (label) {
132 return (label && label.trim()) || ''; 134 return (label && label.trim()) || '';
133 }, 135 },
134 - computeLabelWidth: function(el) { 136 + computeLabelWidth: function (el) {
135 var text = el.select('text'), 137 var text = el.select('text'),
136 box = text.node().getBBox(); 138 box = text.node().getBBox();
137 return box.width + labelPad * 2; 139 return box.width + labelPad * 2;
138 }, 140 },
139 - addLabelElements: function(label) { 141 + addLabelElements: function (label) {
140 var rect = this.el.append('rect'); 142 var rect = this.el.append('rect');
141 var text = this.el.append('text').text(label) 143 var text = this.el.append('text').text(label)
142 .attr('text-anchor', 'left') 144 .attr('text-anchor', 'left')
...@@ -146,12 +148,16 @@ ...@@ -146,12 +148,16 @@
146 return { 148 return {
147 rect: rect, 149 rect: rect,
148 text: text 150 text: text
149 - } 151 + };
150 }, 152 },
151 svgClassName: function () { 153 svgClassName: function () {
152 - return fn.classNames('node', this.nodeType, this.get('type'), { 154 + return fn.classNames('node',
155 + this.nodeType,
156 + this.get('type'),
157 + {
153 online: this.get('online') 158 online: this.get('online')
154 - }); 159 + }
160 + );
155 }, 161 },
156 createNode: function () { 162 createNode: function () {
157 163
......
...@@ -23,32 +23,30 @@ ...@@ -23,32 +23,30 @@
23 'use strict'; 23 'use strict';
24 24
25 // Injected Services 25 // Injected Services
26 - var $log, wss, t2sr, t2ds, t2hs, t2ls; 26 + var $log, t2sr, t2ds, t2hs, t2ls;
27 - var Collection, Model; 27 + var Model;
28 28
29 - //Internal 29 + // Internal
30 var region; 30 var region;
31 31
32 - function init() { 32 + function init() {}
33 - regions = {};
34 - }
35 33
36 function addRegion(data) { 34 function addRegion(data) {
37 35
38 var RegionModel = Model.extend({ 36 var RegionModel = Model.extend({
39 findNodeById: findNodeById 37 findNodeById: findNodeById
40 - }) 38 + });
41 39
42 region = new RegionModel({ 40 region = new RegionModel({
43 id: data.id, 41 id: data.id,
44 - layerOrder: data.layerOrder, 42 + layerOrder: data.layerOrder
45 }); 43 });
46 44
47 region.set({ 45 region.set({
48 subregions: t2sr.createSubRegionCollection(data.subregions, region), 46 subregions: t2sr.createSubRegionCollection(data.subregions, region),
49 devices: t2ds.createDeviceCollection(data.devices, region), 47 devices: t2ds.createDeviceCollection(data.devices, region),
50 hosts: t2hs.createHostCollection(data.hosts, region), 48 hosts: t2hs.createHostCollection(data.hosts, region),
51 - links: t2ls.createLinkCollection(data.links, region), 49 + links: t2ls.createLinkCollection(data.links, region)
52 }); 50 });
53 51
54 angular.forEach(region.get('links').models, function (link) { 52 angular.forEach(region.get('links').models, function (link) {
...@@ -58,18 +56,10 @@ ...@@ -58,18 +56,10 @@
58 $log.debug('Region: ', region); 56 $log.debug('Region: ', region);
59 } 57 }
60 58
61 - function regionNodes() {
62 - return [].concat(
63 - region.get('devices').models,
64 - region.get('hosts').models,
65 - region.get('subregions').models
66 - );
67 - }
68 -
69 function findNodeById(id) { 59 function findNodeById(id) {
70 60
71 // Remove /{port} from id if needed 61 // Remove /{port} from id if needed
72 - var regex = new RegExp('^[^\/]*'); 62 + var regex = new RegExp('^[^/]*');
73 id = regex.exec(id)[0]; 63 id = regex.exec(id)[0];
74 64
75 return region.get('devices').get(id) || 65 return region.get('devices').get(id) ||
...@@ -77,25 +67,37 @@ ...@@ -77,25 +67,37 @@
77 region.get('subregions').get(id); 67 region.get('subregions').get(id);
78 } 68 }
79 69
70 + function regionNodes() {
71 +
72 + if (region) {
73 + return [].concat(
74 + region.get('devices').models,
75 + region.get('hosts').models,
76 + region.get('subregions').models
77 + );
78 + }
79 +
80 + return [];
81 + }
82 +
80 function regionLinks() { 83 function regionLinks() {
81 - return region.get('links').models; 84 + return (region) ? region.get('links').models : [];
82 } 85 }
83 86
84 angular.module('ovTopo2') 87 angular.module('ovTopo2')
85 .factory('Topo2RegionService', 88 .factory('Topo2RegionService',
86 - ['$log', 'WebSocketService', 'Topo2Model', 'Topo2SubRegionService', 'Topo2DeviceService', 89 + ['$log', 'Topo2Model',
87 - 'Topo2HostService', 'Topo2LinkService', 'Topo2Collection', 90 + 'Topo2SubRegionService', 'Topo2DeviceService',
91 + 'Topo2HostService', 'Topo2LinkService',
88 92
89 - function (_$log_, _wss_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_, _Collection_) { 93 + function (_$log_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_) {
90 94
91 $log = _$log_; 95 $log = _$log_;
92 - wss = _wss_; 96 + Model = _Model_;
93 - Model = _Model_
94 t2sr = _t2sr_; 97 t2sr = _t2sr_;
95 t2ds = _t2ds_; 98 t2ds = _t2ds_;
96 t2hs = _t2hs_; 99 t2hs = _t2hs_;
97 t2ls = _t2ls_; 100 t2ls = _t2ls_;
98 - Collection = _Collection_;
99 101
100 return { 102 return {
101 init: init, 103 init: init,
......
...@@ -22,26 +22,18 @@ ...@@ -22,26 +22,18 @@
22 'use strict'; 22 'use strict';
23 23
24 // internal state 24 // internal state
25 - var hovered, selections, selectOrder, consumeClick; 25 + var consumeClick;
26 26
27 - function selectObject(obj) { 27 + function selectObject(obj) {}
28 - var el = this,
29 - nodeEv = el && el.tagName === 'g',
30 - ev = d3.event.sourceEvent || {},
31 - n;
32 -
33 - console.log(el, nodeEv, ev, n);
34 - }
35 28
36 function clickConsumed(x) { 29 function clickConsumed(x) {
37 var cc = consumeClick; 30 var cc = consumeClick;
38 - consumeClick = !!x; 31 + consumeClick = Boolean(x);
39 return cc; 32 return cc;
40 } 33 }
41 34
42 angular.module('ovTopo2') 35 angular.module('ovTopo2')
43 - .factory('Topo2SelectService', 36 + .factory('Topo2SelectService', [
44 - [
45 function () { 37 function () {
46 38
47 return { 39 return {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var wss, is, sus, ts, t2vs; 25 + var wss, is, sus;
26 var Collection, Model; 26 var Collection, Model;
27 27
28 var remappedDeviceTypes = { 28 var remappedDeviceTypes = {
...@@ -31,22 +31,7 @@ ...@@ -31,22 +31,7 @@
31 31
32 // configuration 32 // configuration
33 var devIconDim = 36, 33 var devIconDim = 36,
34 - labelPad = 10, 34 + halfDevIcon = devIconDim / 2;
35 - hostRadius = 14,
36 - badgeConfig = {
37 - radius: 12,
38 - yoff: 5,
39 - gdelta: 10
40 - },
41 - halfDevIcon = devIconDim / 2,
42 - devBadgeOff = { dx: -halfDevIcon, dy: -halfDevIcon },
43 - hostBadgeOff = { dx: -hostRadius, dy: -hostRadius },
44 - status = {
45 - i: 'badgeInfo',
46 - w: 'badgeWarn',
47 - e: 'badgeError'
48 - },
49 - deviceLabelIndex = 0;
50 35
51 function createSubRegionCollection(data, region) { 36 function createSubRegionCollection(data, region) {
52 37
...@@ -67,22 +52,20 @@ ...@@ -67,22 +52,20 @@
67 y: -dim / 2, 52 y: -dim / 2,
68 width: dim + labelWidth, 53 width: dim + labelWidth,
69 height: dim 54 height: dim
70 - } 55 + };
71 } 56 }
72 57
73 angular.module('ovTopo2') 58 angular.module('ovTopo2')
74 .factory('Topo2SubRegionService', 59 .factory('Topo2SubRegionService',
75 - ['WebSocketService', 'Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService', 60 + ['WebSocketService', 'Topo2Collection', 'Topo2NodeModel',
76 - 'ThemeService', 'Topo2ViewService', 61 + 'IconService', 'SvgUtilService', 'ThemeService', 'Topo2ViewService',
77 62
78 - function (_wss_, _Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) { 63 + function (_wss_, _c_, _NodeModel_, _is_, _sus_, _ts_, _t2vs_) {
79 64
80 wss = _wss_; 65 wss = _wss_;
81 - t2vs = _t2vs_;
82 is = _is_; 66 is = _is_;
83 sus = _sus_; 67 sus = _sus_;
84 - ts = _ts_; 68 + Collection = _c_;
85 - Collection = _Collection_;
86 69
87 Model = _NodeModel_.extend({ 70 Model = _NodeModel_.extend({
88 initialize: function () { 71 initialize: function () {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
39 return { 39 return {
40 newDim: newDim, 40 newDim: newDim,
41 getDimensions: getDimensions 41 getDimensions: getDimensions
42 - } 42 + };
43 } 43 }
44 ] 44 ]
45 ); 45 );
......
...@@ -15,8 +15,10 @@ ...@@ -15,8 +15,10 @@
15 "license": "Apache 2.0", 15 "license": "Apache 2.0",
16 "devDependencies": { 16 "devDependencies": {
17 "browser-sync": "^2.12.8", 17 "browser-sync": "^2.12.8",
18 + "eslint": "^3.4.0",
19 + "eslint-config-google": "^0.6.0",
20 + "express": "^4.14.0",
18 "parallelshell": "^2.0.0", 21 "parallelshell": "^2.0.0",
19 - "serve-static": "^1.10.2", 22 + "serve-static": "^1.10.2"
20 - "express": "^4.14.0"
21 } 23 }
22 } 24 }
......