Topo2 - Update device model on status change
Change-Id: I1387c3a5296ef4a4c27908251d43cf34bef4fdf4
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js b/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
index 311c170..b49de81 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Collection.js
@@ -63,6 +63,10 @@
return this.addModel(data);
}
},
+ remove: function (model) {
+ var index = _.indexOf(this.models, model);
+ this.models.splice(index, 1);
+ },
get: function (id) {
if (!id) {
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 9b82c90..ddb9b55 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Device.js
@@ -60,11 +60,11 @@
events: {
'click': 'onClick'
},
- onChange: function () {
-
- // Update class names when the model changes
+ onChange: function (change) {
if (this.el) {
this.el.attr('class', this.svgClassName());
+ var rect = this.el.select('.icon-rect');
+ rect.style('fill', this.devGlyphColor());
}
},
nodeType: 'device',
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
index 0c1ffb7..094e169 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Force.js
@@ -150,10 +150,12 @@
function modelEvent(data) {
$log.debug('>> topo2UiModelEvent event:', data);
+
// TODO: Interpret the event and update our topo model state (if needed)
// To Decide: Can we assume that the server will only send events
// related to objects that we are currently showing?
// (e.g. filtered by subregion contents?)
+ t2rs.update(data);
}
function showMastership(masterId) {
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 2f6f0d2..596524f 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Layout.js
@@ -22,7 +22,8 @@
(function () {
'use strict';
- var instance;
+ var instance,
+ updateTimer;
// default settings for force layout
var defaultSettings = {
@@ -89,10 +90,10 @@
angular.module('ovTopo2')
.factory('Topo2LayoutService',
[
- '$log', 'WebSocketService', 'SvgUtilService', 'Topo2RegionService',
+ '$log', '$timeout', 'WebSocketService', 'SvgUtilService', 'Topo2RegionService',
'Topo2D3Service', 'Topo2ViewService', 'Topo2SelectService', 'Topo2ZoomService',
'Topo2ViewController',
- function ($log, wss, sus, t2rs, t2d3, t2vs, t2ss, t2zs,
+ function ($log, $timeout, wss, sus, t2rs, t2d3, t2vs, t2ss, t2zs,
ViewController) {
var Layout = ViewController.extend({
@@ -189,11 +190,12 @@
t2zs.panAndZoom([x, y], scale, 1000);
},
tick: function () {
+
this.link
- .attr("x1", function (d) { return d.source.x; })
- .attr("y1", function (d) { return d.source.y; })
- .attr("x2", function (d) { return d.target.x; })
- .attr("y2", function (d) { return d.target.y; });
+ .attr("x1", function (d) { return d.get('source').x; })
+ .attr("y1", function (d) { return d.get('source').y; })
+ .attr("x2", function (d) { return d.get('target').x; })
+ .attr("y2", function (d) { return d.get('target').y; });
this.node
.attr({
@@ -209,6 +211,13 @@
this.force.start();
},
update: function () {
+
+ if (updateTimer) {
+ $timeout.cancel(updateTimer);
+ }
+ updateTimer = $timeout(this._update.bind(this), 150);
+ },
+ _update: function () {
this.updateNodes();
this.updateLinks();
},
@@ -237,26 +246,13 @@
entering.filter('.device').each(t2d3.nodeEnter);
entering.filter('.sub-region').each(t2d3.nodeEnter);
entering.filter('.host').each(t2d3.hostEnter);
-
- // operate on exiting nodes:
- // Note that the node is removed after 2 seconds.
- // Sub element animations should be shorter than 2 seconds.
- // var exiting = this.node.exit()
- // .transition()
- // .duration(300)
- // .style('opacity', 0)
- // .remove();
-
- // exiting node specifics:
- // exiting.filter('.host').each(t2d3.hostExit);
- // exiting.filter('.device').each(t2d3.nodeExit);
},
updateLinks: function () {
var regionLinks = t2rs.regionLinks();
this.link = this.elements.linkG.selectAll('.link')
- .data(regionLinks);
+ .data(regionLinks, function (d) { return d.get('key'); });
// operate on entering links:
var entering = this.link.enter()
@@ -275,9 +271,13 @@
// operate on exiting links:
this.link.exit()
- .style('opacity', 1)
+ .attr('stroke-dasharray', '3 3')
+ .style('opacity', 0.5)
.transition()
- .duration(300)
+ .duration(1500)
+ .attr({
+ 'stroke-dasharray': '3 12',
+ })
.style('opacity', 0.0)
.remove();
},
@@ -336,7 +336,6 @@
d.fixed = true;
d3.select(this).classed('fixed', true);
instance.sendUpdateMeta(d);
- $log.debug(d);
t2ss.clickConsumed(true);
},
transitionDownRegion: function () {
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 73ac150..09377e9 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Link.js
@@ -59,8 +59,6 @@
var attrs = angular.extend({}, linkPoints, {
key: this.get('id'),
class: 'link',
- srcPort: this.get('srcPort'),
- tgtPort: this.get('dstPort'),
position: {
x1: 0,
y1: 0,
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 7171477..c713dc0 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -44,14 +44,6 @@
}
};
- function devGlyphColor(d) {
- var o = this.get('online'),
- id = this.get('master'),
- otag = o ? 'online' : 'offline';
- return o ? sus.cat7().getColor(id, 0, ts.theme()) :
- dColTheme[ts.theme()][otag];
- }
-
angular.module('ovTopo2')
.factory('Topo2NodeModel', [
'Topo2Model', 'FnService', 'Topo2PrefsService',
@@ -117,10 +109,10 @@
});
},
mouseoverHandler: function () {
- this.set('hovered', true);
+ this.set('hovered', true, { silent: true });
},
mouseoutHandler: function () {
- this.set('hovered', false);
+ this.set('hovered', false, { silent: true });
},
icon: function () {
return 'unknown';
@@ -146,15 +138,23 @@
box = text.node().getBBox();
return box.width + labelPad * 2;
},
+ devGlyphColor: function () {
+ var o = this.get('online'),
+ id = this.get('master'),
+ otag = o ? 'online' : 'offline';
+ return o ? sus.cat7().getColor(id, 0, ts.theme()) :
+ dColTheme[ts.theme()][otag];
+ },
addLabelElements: function (label) {
var rect = this.el.append('rect')
.attr('class', 'node-container');
var glythRect = this.el.append('rect')
+ .attr('class', 'icon-rect')
.attr('y', -halfDevIcon)
.attr('x', -halfDevIcon)
.attr('width', devIconDim)
.attr('height', devIconDim)
- .style('fill', devGlyphColor.bind(this));
+ .style('fill', this.devGlyphColor.bind(this));
var text = this.el.append('text').text(label)
.attr('text-anchor', 'left')
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 7938fd6..09c6ce7 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Region.js
@@ -104,6 +104,9 @@
getLink: function (linkId) {
return this.model.get('links').get(linkId);
},
+ getDevice: function (deviceId) {
+ return this.model.get('devices').get(deviceId);
+ },
filterRegionNodes: function (predicate) {
var nodes = this.regionNodes();
return _.filter(nodes, predicate);
@@ -144,12 +147,14 @@
},
update: function (event) {
+
if (this[event.type]) {
this[event.type](event);
- this.layout.update();
} else {
$log.error("Unhanded topology update", event);
}
+
+ this.layout.update()
},
// Topology update event handlers
@@ -162,6 +167,22 @@
LINK_REMOVED: function (event) {
var link = this.getLink(event.subject);
link.remove();
+ this.model.get('links').remove(link);
+ },
+ DEVICE_ADDED_OR_UPDATED: function (event) {
+
+ var device;
+
+ if (event.memo === 'added') {
+ device = this.model.get('devices').add(event.data);
+ $log('Added device', device)
+ } else if (event.memo === 'updated') {
+ device = this.getDevice(event.subject);
+ device.set(event.data);
+ }
+ },
+ DEVICE_REMOVED: function (event) {
+ device.remove();
}
});