ONOS-293 Added summary pane and related keyboard shortcuts; also tweaked key help sizes and dropped instances toggle from mast. Fixed ONOS-295 bug.
Change-Id: I694901957451cf88df06e6fca3a8d71de144f68e
diff --git a/web/gui/src/main/webapp/feedback.css b/web/gui/src/main/webapp/feedback.css
index 952688d..06716bb 100644
--- a/web/gui/src/main/webapp/feedback.css
+++ b/web/gui/src/main/webapp/feedback.css
@@ -23,7 +23,7 @@
#feedback svg {
position: absolute;
bottom: 0;
- opacity: 0.5;
+ opacity: 0.8;
}
#feedback svg g.feedbackItem {
@@ -31,14 +31,11 @@
}
#feedback svg g.feedbackItem rect {
- fill: #888;
- stroke: #666;
- stroke-width: 3;
- opacity: 0.5
+ fill: #ccc;
}
#feedback svg g.feedbackItem text {
- fill: #000;
+ fill: #333;
stroke: none;
text-anchor: middle;
alignment-baseline: middle;
diff --git a/web/gui/src/main/webapp/feedback.js b/web/gui/src/main/webapp/feedback.js
index 10f87c9..644202e 100644
--- a/web/gui/src/main/webapp/feedback.js
+++ b/web/gui/src/main/webapp/feedback.js
@@ -33,7 +33,7 @@
var w = '100%',
h = 200,
fade = 200,
- showFor = 500,
+ showFor = 1200,
vb = '-200 -' + (h/2) + ' 400 ' + h,
xpad = 20,
ypad = 10;
diff --git a/web/gui/src/main/webapp/floatPanel.css b/web/gui/src/main/webapp/floatPanel.css
index bacf29e..2a9b8a2 100644
--- a/web/gui/src/main/webapp/floatPanel.css
+++ b/web/gui/src/main/webapp/floatPanel.css
@@ -24,8 +24,8 @@
position: absolute;
z-index: 100;
display: block;
- top: 10%;
- width: 280px;
+ top: 64px;
+ width: 260px;
right: -300px;
opacity: 0;
background-color: rgba(255,255,255,0.8);
diff --git a/web/gui/src/main/webapp/keymap.css b/web/gui/src/main/webapp/keymap.css
index 7e6ade0..e6b9715 100644
--- a/web/gui/src/main/webapp/keymap.css
+++ b/web/gui/src/main/webapp/keymap.css
@@ -31,10 +31,10 @@
}
#keymap svg text.title {
- font-size: 12pt;
+ font-size: 10pt;
font-style: italic;
text-anchor: middle;
- fill: #444;
+ fill: #999;
}
#keymap svg g.keyItem {
@@ -47,17 +47,17 @@
}
#keymap svg text {
- font-size: 10pt;
+ font-size: 7pt;
alignment-baseline: middle;
}
#keymap svg text.key {
- font-size: 10pt;
- fill: #8aa;
+ font-size: 7pt;
+ fill: #add;
}
#keymap svg text.desc {
- font-size: 10pt;
- fill: #888;
+ font-size: 7pt;
+ fill: #aaa;
}
diff --git a/web/gui/src/main/webapp/keymap.js b/web/gui/src/main/webapp/keymap.js
index 85f2539..3d96a56 100644
--- a/web/gui/src/main/webapp/keymap.js
+++ b/web/gui/src/main/webapp/keymap.js
@@ -35,9 +35,9 @@
fade = 500,
vb = '-220 -220 440 440',
paneW = 400,
- paneH = 340,
+ paneH = 280,
offy = 65,
- dy = 20,
+ dy = 14,
offKey = 40,
offDesc = offKey + 50,
lineW = paneW - (2*offKey);
diff --git a/web/gui/src/main/webapp/onos2.js b/web/gui/src/main/webapp/onos2.js
index d2a7baa..a9cb1b0 100644
--- a/web/gui/src/main/webapp/onos2.js
+++ b/web/gui/src/main/webapp/onos2.js
@@ -763,7 +763,8 @@
var pos = position || 'TR',
cfg = fpConfig[pos],
el,
- fp;
+ fp,
+ on = false;
if (fpanels[id]) {
buildError('Float panel with id "' + id + '" already exists.');
@@ -792,15 +793,20 @@
id: id,
el: el,
pos: pos,
+ isVisible: function () {
+ return on;
+ },
show: function () {
console.log('show pane: ' + id);
+ on = true;
el.transition().duration(750)
.style(cfg.side, pxShow())
.style('opacity', 1);
},
hide: function () {
console.log('hide pane: ' + id);
+ on = false;
el.transition().duration(750)
.style(cfg.side, pxHide())
.style('opacity', 0);
diff --git a/web/gui/src/main/webapp/topo2.css b/web/gui/src/main/webapp/topo2.css
index 809458d..d982ee2 100644
--- a/web/gui/src/main/webapp/topo2.css
+++ b/web/gui/src/main/webapp/topo2.css
@@ -177,10 +177,66 @@
font-size: 9pt;
}
+/* Fly-in summary pane */
+
+#topo-summary {
+ /* gets base CSS from .fpanel in floatPanel.css */
+ top: 64px;
+}
+
+#topo-summary svg {
+ display: inline-block;
+ width: 42px;
+ height: 42px;
+}
+
+#topo-summary svg .glyphIcon {
+ fill: black;
+ stroke: none;
+ fill-rule: evenodd;
+}
+
+#topo-summary h2 {
+ position: absolute;
+ margin: 0px 4px;
+ top: 20px;
+ left: 50px;
+ color: black;
+}
+
+#topo-summary h3 {
+ margin: 0px 4px;
+ top: 20px;
+ left: 50px;
+ color: black;
+}
+
+#topo-summary p, table {
+ margin: 4px 4px;
+}
+
+#topo-summary td.label {
+ font-style: italic;
+ color: #777;
+ padding-right: 12px;
+}
+
+#topo-summary td.value {
+}
+
+#topo-summary hr {
+ height: 1px;
+ color: #ccc;
+ background-color: #ccc;
+ border: 0;
+}
+
/* Fly-in details pane */
#topo-detail {
-/* gets base CSS from .fpanel in floatPanel.css */
+ /* gets base CSS from .fpanel in floatPanel.css */
+ top: 320px;
+
}
#topo-detail svg {
diff --git a/web/gui/src/main/webapp/topo2.js b/web/gui/src/main/webapp/topo2.js
index 9db6461..44b90f0 100644
--- a/web/gui/src/main/webapp/topo2.js
+++ b/web/gui/src/main/webapp/topo2.js
@@ -141,6 +141,8 @@
S: injectStartupEvents,
space: injectTestEvent,
+ O: [toggleSummary, 'Toggle ONOS summary pane'],
+ I: [toggleInstances, 'Toggle ONOS instances pane'],
B: [toggleBg, 'Toggle background image'],
L: [cycleLabels, 'Cycle Device labels'],
P: togglePorts,
@@ -182,6 +184,7 @@
selections = {},
selectOrder = [],
hovered = null,
+ summaryPane,
detailPane,
antTimer = null,
onosInstances = {},
@@ -329,7 +332,7 @@
if (hoverMode === hoverModes.length) {
hoverMode = 0;
}
- view.flash('Hover Mode: ' + hoverModes[hoverMode]);
+ view.flash('Mode: ' + hoverModes[hoverMode]);
}
function togglePorts(view) {
@@ -347,8 +350,12 @@
function handleEscape(view) {
if (oiShowMaster) {
cancelAffinity();
- } else {
+ } else if (detailPane.isVisible()) {
deselectAll();
+ } else if (oiBox.isVisible()) {
+ oiBox.hide();
+ } else if (summaryPane.isVisible()) {
+ cancelSummary();
}
}
@@ -585,6 +592,7 @@
removeHost: removeHost,
showDetails: showDetails,
+ showSummary: showSummary,
showTraffic: showTraffic
};
@@ -737,6 +745,12 @@
}
}
+ function showSummary(data) {
+ evTrace(data);
+ populateSummary(data.payload);
+ summaryPane.show();
+ }
+
function showDetails(data) {
evTrace(data);
populateDetails(data.payload);
@@ -824,6 +838,33 @@
return true;
}
+
+ function toggleInstances() {
+ if (!oiBox.isVisible()) {
+ oiBox.show();
+ } else {
+ oiBox.hide();
+ }
+ }
+
+ function toggleSummary() {
+ if (!summaryPane.isVisible()) {
+ requestSummary();
+ } else {
+ cancelSummary();
+ }
+ }
+
+ // request overall summary data
+ function requestSummary() {
+ sendMessage('requestSummary', {});
+ }
+
+ function cancelSummary() {
+ sendMessage('cancelSummary', {});
+ summaryPane.hide();
+ }
+
// request details for the selected element
// invoked from selection of a single node.
function requestDetails() {
@@ -845,16 +886,20 @@
}
function showTrafficAction() {
- // force intents hover mode
+ cancelTraffic();
hoverMode = 1;
showSelectTraffic();
network.view.flash('Related Traffic');
}
+ function cancelTraffic() {
+ sendMessage('cancelTraffic', {});
+ }
+
function showSelectTraffic() {
// if nothing is hovered over, and nothing selected, send cancel request
if (!hovered && nSel() === 0) {
- sendMessage('cancelTraffic', {});
+ cancelTraffic();
return;
}
@@ -870,12 +915,13 @@
}
function showAllTrafficAction() {
+ cancelTraffic();
sendMessage('requestAllTraffic', {});
network.view.flash('All Traffic');
}
function showDeviceLinkFlowsAction() {
- // force intents hover mode
+ cancelTraffic();
hoverMode = 2;
showDeviceLinkFlows();
network.view.flash('Device Flows');
@@ -884,7 +930,7 @@
function showDeviceLinkFlows() {
// if nothing is hovered over, and nothing selected, send cancel request
if (!hovered && nSel() === 0) {
- sendMessage('cancelTraffic', {});
+ cancelTraffic();
return;
}
var hoverId = (flowsHover() && hovered && hovered.class === 'device') ?
@@ -907,7 +953,6 @@
'xlink:href': iid,
width: dim,
height: dim
-
});
}
@@ -940,6 +985,15 @@
});
var dim = 30;
appendGlyph(svg, 2, 2, 30, '#node');
+ svg.append('use')
+ .attr({
+ class: 'birdBadge',
+ transform: translate(8,10),
+ 'xlink:href': '#bird',
+ width: 18,
+ height: 18,
+ fill: '#fff'
+ });
$('<div>').attr('class', 'onosTitle').text(d.id).appendTo(el);
@@ -1720,6 +1774,8 @@
webSock.ws.onopen = function() {
noWebSock(false);
+ requestSummary();
+ oiBox.show();
};
webSock.ws.onmessage = function(m) {
@@ -1881,12 +1937,17 @@
updateDetailPane();
}
+ // update the state of the sumary pane
+ function updateSummaryPane() {
+
+ }
+
// update the state of the detail pane, based on current selections
function updateDetailPane() {
var nSel = selectOrder.length;
if (!nSel) {
detailPane.hide();
- showTrafficAction(); // sends cancelTraffic event
+ cancelTraffic();
} else if (nSel === 1) {
singleSelect();
} else {
@@ -1936,6 +1997,40 @@
addMultiSelectActions();
}
+ // TODO: refactor to consolidate with populateDetails
+ function populateSummary(data) {
+ summaryPane.empty();
+
+ var svg = summaryPane.append('svg'),
+ iid = iconGlyphUrl(data);
+
+ var title = summaryPane.append('h2'),
+ table = summaryPane.append('table'),
+ tbody = table.append('tbody');
+
+ appendGlyph(svg, 0, 0, 40, iid);
+
+ svg.append('use')
+ .attr({
+ class: 'birdBadge',
+ transform: translate(8,12),
+ 'xlink:href': '#bird',
+ width: 24,
+ height: 24,
+ fill: '#fff'
+ });
+
+ title.text('ONOS Summary');
+
+ data.propOrder.forEach(function(p) {
+ if (p === '-') {
+ addSep(tbody);
+ } else {
+ addProp(tbody, p, data.props[p]);
+ }
+ });
+ }
+
function populateDetails(data) {
detailPane.empty();
@@ -2056,7 +2151,7 @@
// TODO: toggle button (and other widgets in the masthead) should be provided
// by the framework; not generated by the view.
- var showInstances;
+ //var showInstances;
function addButtonBar(view) {
var bb = d3.select('#mast')
@@ -2069,20 +2164,20 @@
.on('click', cb);
}
- showInstances = mkTogBtn('Show Instances', toggleInst);
+ //showInstances = mkTogBtn('Show Instances', toggleInst);
}
- function instShown() {
- return showInstances.classed('active');
- }
- function toggleInst() {
- showInstances.classed('active', !instShown());
- if (instShown()) {
- oiBox.show();
- } else {
- oiBox.hide();
- }
- }
+ //function instShown() {
+ // return showInstances.classed('active');
+ //}
+ //function toggleInst() {
+ // showInstances.classed('active', !instShown());
+ // if (instShown()) {
+ // oiBox.show();
+ // } else {
+ // oiBox.hide();
+ // }
+ //}
function panZoom() {
return false;
@@ -2370,6 +2465,7 @@
resize: resize
});
+ summaryPane = onos.ui.addFloatingPanel('topo-summary');
detailPane = onos.ui.addFloatingPanel('topo-detail');
oiBox = onos.ui.addFloatingPanel('topo-oibox', 'TL');