Skip to content
Snippets Groups Projects
Commit cf9ff7fb authored by abat's avatar abat
Browse files

Merge into master from pull request #195:

The Web UI now has icons and stuff (https://github.com/floodlight/floodlight/pull/195)
parents bff1a6e1 a903fcf9
No related branches found
No related tags found
No related merge requests found
File added
src/main/images/Floodlight Icons.sketch/QuickLook/Preview.png

2.93 KiB

src/main/images/Floodlight Icons.sketch/QuickLook/Thumbnail.png

28.7 KiB

These icons were created with Sketch, available at http://www.bohemiancoding.com/sketch/
src/main/resources/web/img/server.png

442 B

src/main/resources/web/img/switch.png

2.62 KiB

...@@ -19,84 +19,92 @@ window.TopologyView = Backbone.View.extend({ ...@@ -19,84 +19,92 @@ window.TopologyView = Backbone.View.extend({
this.template = _.template(tpl.get('topology')); this.template = _.template(tpl.get('topology'));
this.model.bind("change", this.render, this); this.model.bind("change", this.render, this);
this.hosts = this.options.hosts.models; this.hosts = this.options.hosts.models;
this.host_links = new Array(); this.host_links = [];
}, },
render:function (eventName) { render:function (eventName) {
$(this.el).html(this.template()); $(this.el).html(this.template());
// code from D3 force-directed graph example since there's no other docs
var width = 900, var width = 900,
height = 600; // might as well make it square height = 600;
var color = d3.scale.category20(); var color = d3.scale.category20();
var force = d3.layout.force() var force = d3.layout.force()
.charge(-240) .charge(-500)
.linkDistance(100) .linkDistance(200)
.size([width, height]); .size([width, height]);
var svg = d3.select("#topology-graph").append("svg") var svg = d3.select("#topology-graph").append("svg")
.attr("width", width) .attr("width", width)
.attr("height", height); .attr("height", height);
if(this.model.nodes) { if(this.model.nodes) {
for (var i = 0; i < this.model.nodes.length; i++) { for (var i = 0; i < this.model.nodes.length; i++) {
this.model.nodes[i].group = 1; this.model.nodes[i].group = 1;
this.model.nodes[i].id = this.model.nodes[i].name; this.model.nodes[i].id = this.model.nodes[i].name;
}
for (var i = 0; i < this.hosts.length; i++) {
host = this.hosts[i];
if (host.attributes['ipv4'].length > 0) {
host.name = host.attributes['ipv4'][0] + "\n" + host.id;
} else {
host.name = host.id;
} }
host.group = 2;
//console.log(host); for (var i = 0; i < this.hosts.length; i++) {
} host = this.hosts[i];
if (host.attributes['ipv4'].length > 0) {
var all_nodes = this.model.nodes.concat(this.hosts); host.name = host.attributes['ipv4'][0] + "\n" + host.id;
} else {
var all_nodes_map = new Array(); host.name = host.id;
}
_.each(all_nodes, function(n) { host.group = 2;
all_nodes_map[n.id] = n; //console.log(host);
});
for (var i = 0; i < this.hosts.length; i++) {
host = this.hosts[i];
for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) {
var link = {source:all_nodes_map[host.id],
target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']],
value:10};
//console.log(link);
if ( link.source && link.target) {
this.host_links.push(link);
} else {
console.log("Error: skipping link with undefined stuff!")
}
} }
}
var all_nodes = this.model.nodes.concat(this.hosts);
var all_links = this.model.links.concat(this.host_links);
var all_nodes_map = [];
force.nodes(all_nodes).links(all_links).start();
var link = svg.selectAll("line.link").data(all_links).enter() _.each(all_nodes, function(n) {
.append("line").attr("class", "link") all_nodes_map[n.id] = n;
.style("stroke", function (d) { return "black"; }); });
var node = svg.selectAll("circle.node").data(all_nodes)
.enter().append("circle") for (var i = 0; i < this.hosts.length; i++) {
.attr("class", "node") host = this.hosts[i];
.attr("r", 20) //for (var j = 0; j < host.attributes['attachmentPoint'].length; j++) {
.style("fill", function(d) { return color(d.group); }) for (var j = 0; j < 1; j++) { // FIXME hack to ignore multiple APs
.call(force.drag); var link = {source:all_nodes_map[host.id],
node.append("title").text(function(d) { return d.name; }); target:all_nodes_map[host.attributes['attachmentPoint'][j]['switchDPID']],
force.on("tick", function() { value:10};
link.attr("x1", function(d) { return d.source.x; }) //console.log(link);
.attr("y1", function(d) { return d.source.y; }) if ( link.source && link.target) {
.attr("x2", function(d) { return d.target.x; }) this.host_links.push(link);
.attr("y2", function(d) { return d.target.y; }); } else {
console.log("Error: skipping link with undefined stuff!")
node.attr("cx", function(d) { return d.x; }) }
.attr("cy", function(d) { return d.y; }); }
}); }
var all_links = this.model.links.concat(this.host_links);
force.nodes(all_nodes).links(all_links).start();
var link = svg.selectAll("line.link").data(all_links).enter()
.append("line").attr("class", "link")
.style("stroke", function (d) { return "black"; });
var node = svg.selectAll(".node").data(all_nodes)
.enter().append("g")
.attr("class", "node")
.call(force.drag);
node.append("image")
.attr("xlink:href", function (d) {return d.group==1 ? "/ui/img/switch.png" : "/ui/img/server.png"})
.attr("x", -16).attr("y", -16)
.attr("width", 32).attr("height", 32);
node.append("text").attr("dx", 20).attr("dy", ".35em")
.text(function(d) { return d.name });
node.on("click", function (d) {
// TODO we could add some functionality here
console.log('clicked '+d.name);
});
node.append("title").text(function(d) { return d.name; });
force.on("tick", function() {
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; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
});
} }
return this; return this;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment