Tweaked GUI files to clean-up the look and feel and to add a few enhancements.
Default for network.js is now to use live data.
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
index e8f147d..4b2e93c 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
@@ -94,14 +94,18 @@
DeviceService deviceService = get(DeviceService.class);
Device device = deviceService.getDevice(deviceId);
Annotations annot = device.annotations();
+ int portCount = deviceService.getPorts(deviceId).size();
ObjectNode r = json(deviceId.toString(),
+ device.type().toString().toLowerCase(),
new Prop("Name", annot.value("name")),
new Prop("Vendor", device.manufacturer()),
new Prop("H/W Version", device.hwVersion()),
new Prop("S/W Version", device.swVersion()),
new Prop("S/W Version", device.serialNumber()),
+ new Separator(),
new Prop("Latitude", annot.value("latitude")),
- new Prop("Longitude", annot.value("longitude")));
+ new Prop("Longitude", annot.value("longitude")),
+ new Prop("Ports", Integer.toString(portCount)));
return Response.ok(r.toString()).build();
}
@@ -110,18 +114,20 @@
HostService hostService = get(HostService.class);
Host host = hostService.getHost(hostId);
Annotations annot = host.annotations();
- ObjectNode r = json(hostId.toString(),
+ ObjectNode r = json(hostId.toString(), "host",
new Prop("MAC", host.mac().toString()),
new Prop("IP", host.ipAddresses().toString()),
+ new Separator(),
new Prop("Latitude", annot.value("latitude")),
new Prop("Longitude", annot.value("longitude")));
return Response.ok(r.toString()).build();
}
// Produces JSON property details.
- private ObjectNode json(String id, Prop... props) {
+ private ObjectNode json(String id, String type, Prop... props) {
ObjectMapper mapper = new ObjectMapper();
- ObjectNode result = mapper.createObjectNode().put("id", id);
+ ObjectNode result = mapper.createObjectNode()
+ .put("id", id).put("type", type);
ObjectNode pnode = mapper.createObjectNode();
ArrayNode porder = mapper.createArrayNode();
for (Prop p : props) {
@@ -273,13 +279,19 @@
}
// Auxiliary key/value carrier.
- private final class Prop {
+ private class Prop {
private final String key;
private final String value;
- private Prop(String key, String value) {
+ protected Prop(String key, String value) {
this.key = key;
this.value = value;
}
}
+
+ private class Separator extends Prop {
+ protected Separator() {
+ super("-", "");
+ }
+ }
}
diff --git a/web/gui/src/main/webapp/img/onos-logo.png b/web/gui/src/main/webapp/img/onos-logo.png
index 5e0e5a8..b8e0651 100644
--- a/web/gui/src/main/webapp/img/onos-logo.png
+++ b/web/gui/src/main/webapp/img/onos-logo.png
Binary files differ
diff --git a/web/gui/src/main/webapp/img/roadm.png b/web/gui/src/main/webapp/img/roadm.png
new file mode 100644
index 0000000..75ff527
--- /dev/null
+++ b/web/gui/src/main/webapp/img/roadm.png
Binary files differ
diff --git a/web/gui/src/main/webapp/img/switch.png b/web/gui/src/main/webapp/img/switch.png
new file mode 100644
index 0000000..d608153
--- /dev/null
+++ b/web/gui/src/main/webapp/img/switch.png
Binary files differ
diff --git a/web/gui/src/main/webapp/index.html b/web/gui/src/main/webapp/index.html
index 9e91669..337eca7 100644
--- a/web/gui/src/main/webapp/index.html
+++ b/web/gui/src/main/webapp/index.html
@@ -39,7 +39,7 @@
<body>
<div id="frame">
<div id="mast">
- <img id="logo" src="img/onos-logo.png" width="60" height="38">
+ <img id="logo" src="img/onos-logo.png">
<span class="title">Open Network Operating System</span>
<span id="displayModes" class="right">
<span id="showAll" class="radio active">All Layers</span>
diff --git a/web/gui/src/main/webapp/json/of_0000000000000001.json b/web/gui/src/main/webapp/json/of_0000000000000001.json
index c484812..719af80 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000001.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000001.json
@@ -1,13 +1,13 @@
{
"comment": "sample device properties",
"id": "of:0000000000000001",
- "propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
+ "type": "roadm",
+ "propOrder": [ "name", "type", "-", "dpid", "latitude", "longitude", "allowed" ],
"props": {
"allowed": true,
"latitude": 37.6,
"longitude": 122.3,
"name": "SFO-W10",
- "dpid": "00:00:00:00:00:00:00:01",
- "type": "Roadm"
+ "dpid": "00:00:00:00:00:00:00:01"
}
}
diff --git a/web/gui/src/main/webapp/json/of_0000000000000002.json b/web/gui/src/main/webapp/json/of_0000000000000002.json
index 049329d..a6b0e7c 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000002.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000002.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000002",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
"props": {
"allowed": true,
diff --git a/web/gui/src/main/webapp/json/of_0000000000000003.json b/web/gui/src/main/webapp/json/of_0000000000000003.json
index 8561cf4..9fd2790 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000003.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000003.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000003",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
"props": {
"allowed": true,
diff --git a/web/gui/src/main/webapp/json/of_0000000000000004.json b/web/gui/src/main/webapp/json/of_0000000000000004.json
index eb03114..f3f2132 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000004.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000004.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000004",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "latitude", "longitude", "allowed" ],
"props": {
"allowed": true,
diff --git a/web/gui/src/main/webapp/json/of_0000000000000011.json b/web/gui/src/main/webapp/json/of_0000000000000011.json
index 0e73a57..5792dab 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000011.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000011.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000011",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "optLink" ],
"props": {
"name": "SFO-pkt",
diff --git a/web/gui/src/main/webapp/json/of_0000000000000012.json b/web/gui/src/main/webapp/json/of_0000000000000012.json
index 2a00e0c..b65163e 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000012.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000012.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000012",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "optLink" ],
"props": {
"name": "SJC-pkt",
diff --git a/web/gui/src/main/webapp/json/of_0000000000000013.json b/web/gui/src/main/webapp/json/of_0000000000000013.json
index b71738a..ba96b07 100644
--- a/web/gui/src/main/webapp/json/of_0000000000000013.json
+++ b/web/gui/src/main/webapp/json/of_0000000000000013.json
@@ -1,6 +1,7 @@
{
"comment": "sample device properties",
"id": "of:0000000000000013",
+ "type": "switch",
"propOrder": [ "name", "type", "dpid", "optLink" ],
"props": {
"name": "LAX-pkt",
diff --git a/web/gui/src/main/webapp/network.js b/web/gui/src/main/webapp/network.js
index 3c7507a..578aa3a 100644
--- a/web/gui/src/main/webapp/network.js
+++ b/web/gui/src/main/webapp/network.js
@@ -37,10 +37,10 @@
layering: true,
collisionPrevention: true
},
- XjsonUrl: 'rs/topology/graph',
- XjsonPrefix: '',
- jsonUrl: 'json/network.json',
- jsonPrefix: 'json/',
+ jsonUrl: 'rs/topology/graph',
+ jsonPrefix: '',
+ XjsonUrl: 'json/network.json',
+ XjsonPrefix: 'json/',
iconUrl: {
device: 'img/device.png',
host: 'img/host.png',
@@ -239,6 +239,9 @@
function processKeyEvent() {
var code = d3.event.keyCode;
switch (code) {
+ case 71: // G
+ cycleLayout();
+ break;
case 76: // L
cycleLabels();
break;
@@ -252,6 +255,11 @@
}
+ function cycleLayout() {
+ config.options.layering = !config.options.layering;
+ network.force.resume();
+ }
+
function cycleLabels() {
console.log('Cycle Labels - context = ' + contextLabel());
}
@@ -689,7 +697,8 @@
}
function iconUrl(d) {
- return config.iconUrl[d.icon];
+ return 'img/' + d.type + '.png';
+// return config.iconUrl[d.icon];
}
function translate(x, y) {
@@ -928,17 +937,29 @@
function displayDetails(data, pane) {
$('#flyout').empty();
- pane.append('h2').text(data.id);
-
- var table = pane.append("table"),
+ var title = pane.append("h2"),
+ table = pane.append("table"),
tbody = table.append("tbody");
+ $('<img src="img/' + data.type + '.png">').appendTo(title);
+ $('<span>').attr('class', 'icon').text(data.id).appendTo(title);
+
+
// TODO: consider using d3 data bind to TR/TD
data.propOrder.forEach(function(p) {
- addProp(tbody, p, data.props[p]);
+ if (p === '-') {
+ addSep(tbody);
+ } else {
+ addProp(tbody, p, data.props[p]);
+ }
});
+ function addSep(tbody) {
+ var tr = tbody.append('tr');
+ $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
+ }
+
function addProp(tbody, label, value) {
var tr = tbody.append('tr');
diff --git a/web/gui/src/main/webapp/onos.css b/web/gui/src/main/webapp/onos.css
index 06e5b63..3c1fb07 100644
--- a/web/gui/src/main/webapp/onos.css
+++ b/web/gui/src/main/webapp/onos.css
@@ -28,11 +28,17 @@
* Classes
*/
+img#logo {
+ height: 38px;
+ padding-left: 8px;
+ padding-right: 8px;
+}
+
span.title {
- color: #37b;
+ color: #369;
font-size: 14pt;
font-style: italic;
- vertical-align: 10px;
+ vertical-align: 12px;
}
span.radio {
@@ -41,6 +47,8 @@
}
span.right {
+ padding-top: 8px;
+ padding-right: 16px;
float: right;
}
@@ -89,14 +97,13 @@
}
svg .link.host {
- stroke: #6a6;
- stroke-dasharray: 3,3;
+ stroke: #666;
+ stroke-width: 1px;
+ Xstroke-dasharray: 3,3;
}
svg .node.device rect {
- stroke-width: 3.0px;
- stroke: white;
- stroke-dasharray: 2,2;
+ stroke-width: 1.5px;
transition: opacity 250ms;
-webkit-transition: opacity 250ms;
@@ -104,19 +111,21 @@
}
svg .node.device.fixed rect {
- stroke-width: 0;
+ stroke-width: 1.5;
+ stroke: #ccc;
+ Xstroke-dasharray: 4,2;
}
svg .node.device.roadm rect {
- fill: #229;
+ fill: #03c;
}
svg .node.device.switch rect {
- fill: #55f;
+ fill: #06f;
}
svg .node.host circle {
- fill: #898;
+ fill: #c96;
stroke: #000;
}
@@ -148,7 +157,7 @@
svg .node.inactive circle,
svg .node.inactive text,
svg .node.inactive image {
- opacity: .05;
+ opacity: .1;
}
svg .node.inactive.selected rect,
@@ -199,8 +208,9 @@
#mast {
height: 36px;
padding: 4px;
- background-color: #ccc;
+ background-color: #bbb;
vertical-align: baseline;
+ box-shadow: 0px 2px 8px #777;
}
#frame {
@@ -214,19 +224,27 @@
z-index: 100;
display: block;
top: 10%;
- width: 300px;
- height: 80%;
- right: -320px;
+ width: 280px;
+ right: -300px;
opacity: 0;
- background-color: rgba(0,0,0,0.5);
+ background-color: rgba(255,255,255,0.5);
+
padding: 10px;
- color: white;
+ color: black;
font-size: 10pt;
+ box-shadow: 2px 2px 16px #777;
}
#flyout h2 {
margin: 8px 4px;
- color: yellow;
+ color: black;
+ vertical-align: middle;
+}
+
+#flyout h2 img {
+ height: 32px;
+ padding-right: 8px;
+ vertical-align: middle;
}
#flyout p, table {
@@ -235,7 +253,7 @@
#flyout td.label {
font-style: italic;
- color: #ccf;
+ color: #777;
padding-right: 12px;
}
@@ -243,3 +261,10 @@
}
+#flyout hr {
+ height: 1px;
+ color: #ccc;
+ background-color: #ccc;
+ border: 0;
+}
+