Steven Burrows
Committed by Gerrit Code Review

Grouped injected vars and shortened findNodeById

Fixed syntax in Topo2NodeModel.js
Added SubRegions to the topo2 view

Change-Id: I04c793f3a9a98808eaa11049f31bbb166cc5b66f
...@@ -171,6 +171,15 @@ ...@@ -171,6 +171,15 @@
171 fill: #454545; 171 fill: #454545;
172 } 172 }
173 173
174 +#ov-topo2 svg .node.sub-region rect {
175 + fill: #ffffff;
176 +}
177 +
178 +#ov-topo2 svg .node.sub-region use {
179 + /* NOTE: this gets overridden programatically */
180 + fill: #454545;
181 +}
182 +
174 183
175 #ov-topo2 svg .node.device.selected rect { 184 #ov-topo2 svg .node.device.selected rect {
176 stroke-width: 2.0; 185 stroke-width: 2.0;
......
...@@ -111,8 +111,8 @@ Module that contains the d3.force.layout logic ...@@ -111,8 +111,8 @@ Module that contains the d3.force.layout logic
111 } 111 }
112 } 112 }
113 113
114 - function deviceEnter(device) { 114 + function nodeEnter(node) {
115 - device.onEnter(this, device); 115 + node.onEnter(this, node);
116 } 116 }
117 117
118 function hostLabel(d) { 118 function hostLabel(d) {
...@@ -153,7 +153,7 @@ Module that contains the d3.force.layout logic ...@@ -153,7 +153,7 @@ Module that contains the d3.force.layout logic
153 153
154 return { 154 return {
155 init: init, 155 init: init,
156 - deviceEnter: deviceEnter, 156 + nodeEnter: nodeEnter,
157 hostEnter: hostEnter, 157 hostEnter: hostEnter,
158 linkEntering: linkEntering 158 linkEntering: linkEntering
159 } 159 }
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
30 30
31 // configuration 31 // configuration
32 var devIconDim = 36, 32 var devIconDim = 36,
33 - labelPad = 10,
34 hostRadius = 14, 33 hostRadius = 14,
35 badgeConfig = { 34 badgeConfig = {
36 radius: 12, 35 radius: 12,
...@@ -44,8 +43,7 @@ ...@@ -44,8 +43,7 @@
44 i: 'badgeInfo', 43 i: 'badgeInfo',
45 w: 'badgeWarn', 44 w: 'badgeWarn',
46 e: 'badgeError' 45 e: 'badgeError'
47 - }, 46 + };
48 - deviceLabelIndex = 0;
49 47
50 function createDeviceCollection(data, region) { 48 function createDeviceCollection(data, region) {
51 49
...@@ -74,24 +72,6 @@ ...@@ -74,24 +72,6 @@
74 return remappedDeviceTypes[type] || type || 'unknown'; 72 return remappedDeviceTypes[type] || type || 'unknown';
75 } 73 }
76 74
77 - function deviceLabel(d) {
78 - //TODO: Device Json is missing labels array
79 - return "";
80 - var labels = this.get('labels'),
81 - idx = (deviceLabelIndex < labels.length) ? deviceLabelIndex : 0;
82 - return labels[idx];
83 - }
84 -
85 - function trimLabel(label) {
86 - return (label && label.trim()) || '';
87 - }
88 -
89 - function computeLabelWidth() {
90 - var text = this.select('text'),
91 - box = text.node().getBBox();
92 - return box.width + labelPad * 2;
93 - }
94 -
95 function iconBox(dim, labelWidth) { 75 function iconBox(dim, labelWidth) {
96 return { 76 return {
97 x: -dim / 2, 77 x: -dim / 2,
...@@ -104,7 +84,7 @@ ...@@ -104,7 +84,7 @@
104 function deviceGlyphColor(d) { 84 function deviceGlyphColor(d) {
105 85
106 var o = this.node.online, 86 var o = this.node.online,
107 - id = "127.0.0.1", // TODO: This should be from node.master 87 + id = this.node.master, // TODO: This should be from node.master
108 otag = o ? 'online' : 'offline'; 88 otag = o ? 'online' : 'offline';
109 return o ? sus.cat7().getColor(id, 0, ts.theme()) 89 return o ? sus.cat7().getColor(id, 0, ts.theme())
110 : '#ff0000'; 90 : '#ff0000';
...@@ -134,32 +114,25 @@ ...@@ -134,32 +114,25 @@
134 this.constructor.__super__.initialize.apply(this, arguments); 114 this.constructor.__super__.initialize.apply(this, arguments);
135 }, 115 },
136 nodeType: 'device', 116 nodeType: 'device',
137 - deviceLabel: deviceLabel,
138 deviceGlyphColor: deviceGlyphColor, 117 deviceGlyphColor: deviceGlyphColor,
139 mapDeviceTypeToGlyph: mapDeviceTypeToGlyph, 118 mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
140 - trimLabel: trimLabel,
141 setDeviceColor: setDeviceColor, 119 setDeviceColor: setDeviceColor,
142 onEnter: function (el) { 120 onEnter: function (el) {
143 121
144 var node = d3.select(el), 122 var node = d3.select(el),
145 glyphId = mapDeviceTypeToGlyph(this.get('type')), 123 glyphId = mapDeviceTypeToGlyph(this.get('type')),
146 - label = trimLabel(this.deviceLabel()), 124 + label = this.trimLabel(this.label()),
147 - rect, text, glyph, labelWidth; 125 + glyph, labelWidth;
148 126
149 this.el = node; 127 this.el = node;
150 128
151 - rect = node.append('rect'); 129 + // Label
152 - 130 + var labelElements = this.addLabelElements(label);
153 - text = node.append('text').text(label) 131 + labelWidth = label ? this.computeLabelWidth(node) : 0;
154 - .attr('text-anchor', 'left') 132 + labelElements.rect.attr(iconBox(devIconDim, labelWidth));
155 - .attr('y', '0.3em')
156 - .attr('x', halfDevIcon + labelPad);
157 133
134 + // Icon
158 glyph = is.addDeviceIcon(node, glyphId, devIconDim); 135 glyph = is.addDeviceIcon(node, glyphId, devIconDim);
159 -
160 - labelWidth = label ? computeLabelWidth(node) : 0;
161 -
162 - rect.attr(iconBox(devIconDim, labelWidth));
163 glyph.attr(iconBox(devIconDim, 0)); 136 glyph.attr(iconBox(devIconDim, 0));
164 137
165 node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon)); 138 node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
......
...@@ -193,7 +193,8 @@ ...@@ -193,7 +193,8 @@
193 .transition() 193 .transition()
194 .attr('opacity', 1); 194 .attr('opacity', 1);
195 195
196 - entering.filter('.device').each(t2d3.deviceEnter); 196 + entering.filter('.device').each(t2d3.nodeEnter);
197 + entering.filter('.sub-region').each(t2d3.nodeEnter);
197 entering.filter('.host').each(t2d3.hostEnter); 198 entering.filter('.host').each(t2d3.hostEnter);
198 199
199 // operate on both existing and new nodes: 200 // operate on both existing and new nodes:
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 + var $log;
25 var Collection, Model, region, ts; 26 var Collection, Model, region, ts;
26 27
27 var widthRatio = 1.4, 28 var widthRatio = 1.4,
...@@ -55,7 +56,6 @@ ...@@ -55,7 +56,6 @@
55 function createLink() { 56 function createLink() {
56 57
57 var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB')); 58 var linkPoints = this.linkEndPoints(this.get('epA'), this.get('epB'));
58 - console.log(this);
59 59
60 var attrs = angular.extend({}, linkPoints, { 60 var attrs = angular.extend({}, linkPoints, {
61 key: this.get('id'), 61 key: this.get('id'),
...@@ -78,19 +78,14 @@ ...@@ -78,19 +78,14 @@
78 78
79 function linkEndPoints(srcId, dstId) { 79 function linkEndPoints(srcId, dstId) {
80 80
81 - var sourceNode = this.region.get('devices').get(srcId.substring(0, srcId.length -2)); 81 + var sourceNode = this.region.findNodeById(srcId)
82 - var targetNode = this.region.get('devices').get(dstId.substring(0, dstId.length -2)); 82 + var targetNode = this.region.findNodeById(dstId)
83 83
84 -// var srcNode = lu[srcId], 84 + if (!sourceNode || !targetNode) {
85 -// dstNode = lu[dstId], 85 + $log.error('Node(s) not on map for link:' + srcId + ':' + dstId);
86 -// sMiss = !srcNode ? missMsg('src', srcId) : '', 86 + //logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
87 -// dMiss = !dstNode ? missMsg('dst', dstId) : ''; 87 + return null;
88 -// 88 + }
89 -// if (sMiss || dMiss) {
90 -// $log.error('Node(s) not on map for link:' + sMiss + dMiss);
91 -// //logicError('Node(s) not on map for link:\n' + sMiss + dMiss);
92 -// return null;
93 -// }
94 89
95 this.source = sourceNode.toJSON(); 90 this.source = sourceNode.toJSON();
96 this.target = targetNode.toJSON(); 91 this.target = targetNode.toJSON();
...@@ -118,31 +113,17 @@ ...@@ -118,31 +113,17 @@
118 return true; 113 return true;
119 return both && (s && s.online) && (t && t.online); 114 return both && (s && s.online) && (t && t.online);
120 }, 115 },
121 - linkWidth: function () {
122 - var s = this.get('fromSource'),
123 - t = this.get('fromTarget'),
124 - ws = (s && s.linkWidth) || 0,
125 - wt = (t && t.linkWidth) || 0;
126 -
127 - // console.log(s);
128 - // TODO: Current json is missing linkWidth
129 - return 1.2;
130 - return this.get('position').multiLink ? 5 : Math.max(ws, wt);
131 - },
132 -
133 restyleLinkElement: function (immediate) { 116 restyleLinkElement: function (immediate) {
134 // this fn's job is to look at raw links and decide what svg classes 117 // this fn's job is to look at raw links and decide what svg classes
135 // need to be applied to the line element in the DOM 118 // need to be applied to the line element in the DOM
136 var th = ts.theme(), 119 var th = ts.theme(),
137 el = this.el, 120 el = this.el,
138 type = this.get('type'), 121 type = this.get('type'),
139 - lw = this.linkWidth(),
140 online = this.online(), 122 online = this.online(),
141 modeCls = this.expected() ? 'inactive' : 'not-permitted', 123 modeCls = this.expected() ? 'inactive' : 'not-permitted',
124 + lw = 1.2,
142 delay = immediate ? 0 : 1000; 125 delay = immediate ? 0 : 1000;
143 126
144 - console.log(type);
145 -
146 // NOTE: understand why el is sometimes undefined on addLink events... 127 // NOTE: understand why el is sometimes undefined on addLink events...
147 // Investigated: 128 // Investigated:
148 // el is undefined when it's a reverse link that is being added. 129 // el is undefined when it's a reverse link that is being added.
...@@ -185,10 +166,11 @@ ...@@ -185,10 +166,11 @@
185 166
186 angular.module('ovTopo2') 167 angular.module('ovTopo2')
187 .factory('Topo2LinkService', 168 .factory('Topo2LinkService',
188 - ['Topo2Collection', 'Topo2Model', 'ThemeService', 169 + ['$log', 'Topo2Collection', 'Topo2Model', 'ThemeService',
189 170
190 - function (_Collection_, _Model_, _ts_) { 171 + function (_$log_, _Collection_, _Model_, _ts_) {
191 172
173 + $log = _$log_;
192 ts = _ts_; 174 ts = _ts_;
193 Collection = _Collection_; 175 Collection = _Collection_;
194 Model = _Model_; 176 Model = _Model_;
......
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
29 var defaultLinkType = 'direct', 29 var defaultLinkType = 'direct',
30 nearDist = 15; 30 nearDist = 15;
31 31
32 + var devIconDim = 36,
33 + labelPad = 10,
34 + halfDevIcon = devIconDim / 2,
35 + nodeLabelIndex = 1;
36 +
32 function positionNode(node, forUpdate) { 37 function positionNode(node, forUpdate) {
33 38
34 var meta = node.metaUi, 39 var meta = node.metaUi,
...@@ -113,6 +118,36 @@ ...@@ -113,6 +118,36 @@
113 initialize: function () { 118 initialize: function () {
114 this.node = this.createNode(); 119 this.node = this.createNode();
115 }, 120 },
121 + label: function () {
122 +
123 + var props = this.get('props'),
124 + id = this.get('id'),
125 + friendlyName = props ? props.name : id,
126 + labels = ['', friendlyName, id],
127 + idx = (nodeLabelIndex < labels.length) ? nodeLabelIndex : 0;
128 +
129 + return labels[idx];
130 + },
131 + trimLabel: function(label) {
132 + return (label && label.trim()) || '';
133 + },
134 + computeLabelWidth: function(el) {
135 + var text = el.select('text'),
136 + box = text.node().getBBox();
137 + return box.width + labelPad * 2;
138 + },
139 + addLabelElements: function(label) {
140 + var rect = this.el.append('rect');
141 + var text = this.el.append('text').text(label)
142 + .attr('text-anchor', 'left')
143 + .attr('y', '0.3em')
144 + .attr('x', halfDevIcon + labelPad);
145 +
146 + return {
147 + rect: rect,
148 + text: text
149 + }
150 + },
116 svgClassName: function () { 151 svgClassName: function () {
117 return fn.classNames('node', this.nodeType, this.get('type'), { 152 return fn.classNames('node', this.nodeType, this.get('type'), {
118 online: this.get('online') 153 online: this.get('online')
......
...@@ -22,14 +22,11 @@ ...@@ -22,14 +22,11 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var $log, 25 + // Injected Services
26 - wss, 26 + var $log, wss, t2sr, t2ds, t2hs, t2ls;
27 - Model, 27 + var Collection, Model;
28 - t2sr,
29 - t2ds,
30 - t2hs,
31 - t2ls;
32 28
29 + //Internal
33 var region; 30 var region;
34 31
35 function init() { 32 function init() {
...@@ -38,9 +35,13 @@ ...@@ -38,9 +35,13 @@
38 35
39 function addRegion(data) { 36 function addRegion(data) {
40 37
41 - region = new Model({ 38 + var RegionModel = Model.extend({
39 + findNodeById: findNodeById
40 + })
41 +
42 + region = new RegionModel({
42 id: data.id, 43 id: data.id,
43 - layerOrder: data.layerOrder 44 + layerOrder: data.layerOrder,
44 }); 45 });
45 46
46 region.set({ 47 region.set({
...@@ -50,8 +51,6 @@ ...@@ -50,8 +51,6 @@
50 links: t2ls.createLinkCollection(data.links, region), 51 links: t2ls.createLinkCollection(data.links, region),
51 }); 52 });
52 53
53 - region.set('test', 2);
54 -
55 angular.forEach(region.get('links').models, function (link) { 54 angular.forEach(region.get('links').models, function (link) {
56 link.createLink(); 55 link.createLink();
57 }); 56 });
...@@ -60,9 +59,23 @@ ...@@ -60,9 +59,23 @@
60 } 59 }
61 60
62 function regionNodes() { 61 function regionNodes() {
63 - return [].concat(region.get('devices').models, region.get('hosts').models); 62 + return [].concat(
63 + region.get('devices').models,
64 + region.get('hosts').models,
65 + region.get('subregions').models
66 + );
64 } 67 }
65 68
69 + function findNodeById(id) {
70 +
71 + // Remove /{port} from id if needed
72 + var regex = new RegExp('^[^\/]*');
73 + id = regex.exec(id)[0];
74 +
75 + return region.get('devices').get(id) ||
76 + region.get('hosts').get(id) ||
77 + region.get('subregions').get(id);
78 + }
66 79
67 function regionLinks() { 80 function regionLinks() {
68 return region.get('links').models; 81 return region.get('links').models;
...@@ -71,9 +84,9 @@ ...@@ -71,9 +84,9 @@
71 angular.module('ovTopo2') 84 angular.module('ovTopo2')
72 .factory('Topo2RegionService', 85 .factory('Topo2RegionService',
73 ['$log', 'WebSocketService', 'Topo2Model', 'Topo2SubRegionService', 'Topo2DeviceService', 86 ['$log', 'WebSocketService', 'Topo2Model', 'Topo2SubRegionService', 'Topo2DeviceService',
74 - 'Topo2HostService', 'Topo2LinkService', 87 + 'Topo2HostService', 'Topo2LinkService', 'Topo2Collection',
75 88
76 - function (_$log_, _wss_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_) { 89 + function (_$log_, _wss_, _Model_, _t2sr_, _t2ds_, _t2hs_, _t2ls_, _Collection_) {
77 90
78 $log = _$log_; 91 $log = _$log_;
79 wss = _wss_; 92 wss = _wss_;
...@@ -82,6 +95,7 @@ ...@@ -82,6 +95,7 @@
82 t2ds = _t2ds_; 95 t2ds = _t2ds_;
83 t2hs = _t2hs_; 96 t2hs = _t2hs_;
84 t2ls = _t2ls_; 97 t2ls = _t2ls_;
98 + Collection = _Collection_;
85 99
86 return { 100 return {
87 init: init, 101 init: init,
......
...@@ -22,7 +22,30 @@ ...@@ -22,7 +22,30 @@
22 (function () { 22 (function () {
23 'use strict'; 23 'use strict';
24 24
25 - var Collection, Model; 25 + var Collection, Model, is, sus, ts, t2vs;
26 +
27 + var remappedDeviceTypes = {
28 + virtual: 'cord'
29 + };
30 +
31 + // configuration
32 + var devIconDim = 36,
33 + labelPad = 10,
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;
26 49
27 function createSubRegionCollection(data, region) { 50 function createSubRegionCollection(data, region) {
28 51
...@@ -33,14 +56,63 @@ ...@@ -33,14 +56,63 @@
33 return new SubRegionCollection(data); 56 return new SubRegionCollection(data);
34 } 57 }
35 58
59 + function mapDeviceTypeToGlyph(type) {
60 + return remappedDeviceTypes[type] || type || 'switch';
61 + }
62 +
63 + function iconBox(dim, labelWidth) {
64 + return {
65 + x: -dim / 2,
66 + y: -dim / 2,
67 + width: dim + labelWidth,
68 + height: dim
69 + }
70 + }
71 +
36 angular.module('ovTopo2') 72 angular.module('ovTopo2')
37 .factory('Topo2SubRegionService', 73 .factory('Topo2SubRegionService',
38 - ['Topo2Collection', 'Topo2Model', 74 + ['Topo2Collection', 'Topo2NodeModel', 'IconService', 'SvgUtilService',
75 + 'ThemeService', 'Topo2ViewService',
39 76
40 - function (_Collection_, _Model_) { 77 + function (_Collection_, _NodeModel_, _is_, _sus_, _ts_, classnames, _t2vs_) {
41 78
79 + t2vs = _t2vs_;
80 + is = _is_;
81 + sus = _sus_;
82 + ts = _ts_;
42 Collection = _Collection_; 83 Collection = _Collection_;
43 - Model = _Model_.extend({}); 84 +
85 + Model = _NodeModel_.extend({
86 + initialize: function () {
87 + this.set('weight', 0);
88 + this.constructor.__super__.initialize.apply(this, arguments);
89 + },
90 + nodeType: 'sub-region',
91 + mapDeviceTypeToGlyph: mapDeviceTypeToGlyph,
92 + onEnter: function (el) {
93 +
94 + var node = d3.select(el),
95 + glyphId = mapDeviceTypeToGlyph(this.get('type')),
96 + label = this.trimLabel(this.label()),
97 + glyph, labelWidth;
98 +
99 + this.el = node;
100 +
101 + // Label
102 + var labelElements = this.addLabelElements(label);
103 + labelWidth = label ? this.computeLabelWidth(node) : 0;
104 + labelElements.rect.attr(iconBox(devIconDim, labelWidth));
105 +
106 + // Icon
107 + glyph = is.addDeviceIcon(node, glyphId, devIconDim);
108 + glyph.attr(iconBox(devIconDim, 0));
109 +
110 + node.attr('transform', sus.translate(-halfDevIcon, -halfDevIcon));
111 + this.render();
112 + },
113 + onExit: function () {},
114 + render: function () {}
115 + });
44 116
45 return { 117 return {
46 createSubRegionCollection: createSubRegionCollection 118 createSubRegionCollection: createSubRegionCollection
......