ONOS-5726: completed implementation of "showIntent" overlay support.
(note, there is still some cleanup to be done).
Change-Id: I6c805ad954b97ca261b5536240b277df7712a834
diff --git a/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js b/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js
index 5593cb0..322c69e 100644
--- a/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js
+++ b/apps/pathpainter/src/main/resources/app/view/ppTopov/ppTopovOverlay.js
@@ -17,7 +17,7 @@
// NOTE: this must match the ID defined in AppUiTopovOverlay
overlayId: 'pp-overlay',
glyphId: 'm_topo',
- tooltip: 'Path Painter Topo Overlay',
+ tooltip: 'Path Painter Overlay',
activate: function () {
$log.debug("Path painter topology overlay ACTIVATED");
@@ -122,11 +122,12 @@
hooks: {
// hook for handling escape key
- // Must return true to consume ESC, false otherwise.
+ // TODO: Must return true to consume ESC, false otherwise.
escape: function () {
selectionCallback();
pps.setSrc();
pps.setDst();
+ // FIXME: should explicitly return true or false
},
// hooks for when the selection changes...
diff --git a/web/gui/src/main/webapp/app/fw/util/prefs.js b/web/gui/src/main/webapp/app/fw/util/prefs.js
index 14bc5e2..16f2607 100644
--- a/web/gui/src/main/webapp/app/fw/util/prefs.js
+++ b/web/gui/src/main/webapp/app/fw/util/prefs.js
@@ -43,15 +43,28 @@
}
// converts string values to numbers for selected (or all) keys
- function asNumbers(obj, keys) {
+ // asNumbers(obj, ['a', 'b']) <-- convert keys .a, .b to numbers
+ // asNumbers(obj, ['a', 'b'], true) <-- convert ALL BUT keys .a, .b to numbers
+
+ function asNumbers(obj, keys, not) {
if (!obj) return null;
- if (!keys) {
+ var skip = {};
+ if (not) {
+ keys.forEach(function (k) {
+ skip[k] = 1;
+ });
+ }
+
+ if (!keys || not) {
// do them all
angular.forEach(obj, function (v, k) {
- obj[k] = Number(obj[k]);
+ if (!not || !skip[k]) {
+ obj[k] = Number(obj[k]);
+ }
});
} else {
+ // do the explicitly named keys
keys.forEach(function (k) {
obj[k] = Number(obj[k]);
});
diff --git a/web/gui/src/main/webapp/app/view/intent/intent.css b/web/gui/src/main/webapp/app/view/intent/intent.css
index 223168f..41a49c4 100644
--- a/web/gui/src/main/webapp/app/view/intent/intent.css
+++ b/web/gui/src/main/webapp/app/view/intent/intent.css
@@ -30,3 +30,29 @@
#ov-intent td.details {
padding-left: 36px;
}
+
+#ov-intent div.show-intent-btn {
+ position:relative;
+}
+
+#ov-intent .dropdown {
+ position: absolute;
+ top: 42px;
+ left: 0;
+ display: none;
+
+ border: 1px solid black;
+ background-color: #aec5dc;
+}
+
+#ov-intent .overlay-choice {
+ padding: 2px;
+ white-space: nowrap;
+ font-size: 10pt;
+
+ color: black;
+}
+
+#ov-intent .overlay-choice:hover {
+ color: white;
+}
diff --git a/web/gui/src/main/webapp/app/view/intent/intent.html b/web/gui/src/main/webapp/app/view/intent/intent.html
index 9de4c38..95fe5ca 100644
--- a/web/gui/src/main/webapp/app/view/intent/intent.html
+++ b/web/gui/src/main/webapp/app/view/intent/intent.html
@@ -27,10 +27,14 @@
<div class="separator"></div>
- <div ng-class="{active: !!selId}"
- icon icon-id="topo" icon-size="42"
- tooltip tt-msg="topoTip"
- ng-click="showIntent()"></div>
+ <div class="show-intent-btn">
+ <div ng-class="{active: !!selId}"
+ icon icon-id="topo" icon-size="42"
+ tooltip tt-msg="topoTip"
+ ng-click="showIntent()">
+ </div>
+ <div class="dropdown"></div>
+ </div>
<div ng-class="{'active': !!selId && isIntentWithdrawn()}"
icon icon-id="play" icon-size="42"
diff --git a/web/gui/src/main/webapp/app/view/intent/intent.js b/web/gui/src/main/webapp/app/view/intent/intent.js
index 559dca1..a2375ba 100644
--- a/web/gui/src/main/webapp/app/view/intent/intent.js
+++ b/web/gui/src/main/webapp/app/view/intent/intent.js
@@ -24,7 +24,8 @@
var dialogId = 'remove-intent-dialog',
dialogOpts = {
edge: 'right'
- };
+ },
+ dropdown;
angular.module('ovIntent', [])
.controller('OvIntentCtrl',
@@ -37,6 +38,9 @@
$scope.brief = true;
$scope.intentState = 'NA';
$scope.fired = false;
+ $scope.showOverlays = false;
+
+ dropdown = d3.select('div.show-intent-btn .dropdown');
function selCb($event, row) {
$log.debug('Got a click on:', row);
@@ -51,6 +55,7 @@
} : null;
$scope.intentState = row.state;
+ showDropdown(false);
}
function respCb() {
@@ -76,17 +81,67 @@
$scope.purgeTip = 'Purge selected intent';
$scope.purgeAllTip = 'Purge withdrawn intents';
- $scope.showIntent = function () {
- var d = $scope.intentData;
- if (d) {
- // TODO: if more than one overlay registered, provide dropdown
- $log.debug('SHOW-INTENT: overlay list:', tov.list());
- $log.debug('SHOW-INTENT: overlay info:', tov.list(true));
+ function showDropdown(b) {
+ dropdown.style('display', b ? 'block' : 'none');
+ }
+
+ $scope.showIntent = function () {
+ var d = $scope.intentData,
+ tovData,
+ ncb;
+
+ if (!d) {
+ // no intent selected - nothing to do
+ return;
+ }
+
+ function setOvAndNavigate(info) {
+ d.overlayId = info.id;
ns.navTo('topo', d);
}
+
+ function clickMe(data) {
+ showDropdown(false);
+ setOvAndNavigate(data);
+ }
+
+ function setUpSelection(tovData) {
+ dropdown.text(null);
+
+ tovData.forEach(function (data) {
+ var div = dropdown.append('div');
+ div.classed('overlay-choice', true);
+ div.text(data.tt);
+ div.on('click', function () {
+ clickMe(data);
+ });
+ });
+
+ showDropdown(true);
+ }
+
+ tovData = tov.listOverlaysThatShowIntents();
+ ncb = tovData.length;
+ // NOTE: ncb should be at least 1, (traffic overlay)
+
+ if (ncb === 1) {
+ setOvAndNavigate(tovData[0]);
+
+ } else if (ncb > 1) {
+ // let the user choose which overlay to invoke...
+ setUpSelection(tovData);
+
+ } else {
+ $log.error('Internal Error - no overlay configured',
+ 'to show selected intent on topology view');
+ }
};
+
+
+ // TODO: clean up the following code...
+
$scope.isIntentInstalled = function () {
return $scope.intentState === 'Installed';
};
diff --git a/web/gui/src/main/webapp/app/view/topo/topo.js b/web/gui/src/main/webapp/app/view/topo/topo.js
index 90e9411..1762cf4 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -476,7 +476,9 @@
function restoreConfigFromPrefs() {
// NOTE: toolbar will have set this for us..
- prefsState = ps.asNumbers(ps.getPrefs('topo_prefs', ttbs.defaultPrefs));
+ prefsState = ps.asNumbers(
+ ps.getPrefs('topo_prefs', ttbs.defaultPrefs), ['ovid'], true
+ );
$log.debug('TOPO- Prefs State:', prefsState);
@@ -498,7 +500,9 @@
// have opened the websocket to the server; hence this extra function
// invoked after tes.start()
function restoreSummaryFromPrefs() {
- prefsState = ps.asNumbers(ps.getPrefs('topo_prefs', ttbs.defaultPrefs));
+ prefsState = ps.asNumbers(
+ ps.getPrefs('topo_prefs', ttbs.defaultPrefs), ['ovid'], true
+ );
$log.debug('TOPO- Prefs SUMMARY State:', prefsState.summary);
flash.enable(false);
@@ -518,9 +522,6 @@
// if an intent should be shown, invoke the appropriate callback
if ($scope.intentData) {
-
- // TODO: if a specific overlay was requested, activate that first
-
tov.hooks.showIntent($scope.intentData);
}
@@ -546,7 +547,9 @@
_tds_, _t3s_, _tes_,
_tfs_, _tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_,
_ttbs_, _tms_, _tspr_, _ttip_, _tov_) {
+
var params = _$loc_.search(),
+ selOverlay = params.overlayId,
projection,
dim,
uplink = {
@@ -668,7 +671,8 @@
tps.initPanels();
restoreConfigFromPrefs();
- ttbs.setDefaultOverlay(prefsState.ovidx);
+
+ ttbs.selectOverlay(selOverlay || prefsState.ovid);
$log.debug('registered overlays...', tov.list());
$log.log('OvTopoCtrl has been created');
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index dbb1cc3..ad42470 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -108,25 +108,27 @@
$log.debug(tos + 'registered overlay: ' + id, overlay);
}
- // Returns the list of overlay identifiers. If a truthy argument is supplied,
- // returns an augmented list of overlay tokens, providing overlay ID,
- // glyph ID and overlay Tooltip text.
- function list(x) {
- var oids = d3.map(overlays).keys(),
- info = [];
+ // Returns the list of overlay identifiers.
+ function list() {
+ return d3.map(overlays).keys();
+ }
- if (!x) {
- return oids;
- }
+ // returns data on overlays that implement the showIntent callback
+ function listShowIntents() {
+ var result = [];
+ angular.forEach(overlays, function (ov) {
+ var hooks = fs.isO(ov.hooks) || {},
+ sicb = fs.isF(hooks.showintent);
- oids.forEach(function (oid) {
- var o = overlays[oid],
- ot = o.tooltip || '%' + o.overlayId + '%',
- og = o._glyphId;
-
- info.push({ id: oid, tt: ot, gid: og });
+ if (sicb) {
+ result.push({
+ id: ov.overlayId,
+ tt: ov.tooltip || '%' + ov.overlayId + '%',
+ gid: ov._glyphId
+ });
+ }
});
- return info;
+ return result;
}
// add a radio button for each registered overlay
@@ -302,7 +304,6 @@
// Request from Intent View to visualize an intent on the topo view
function showIntentHook(intentData) {
- $log.debug('^^ topoOverlay.showIntentHook(...) ^^');
var cb = _hook('showintent');
return cb && cb(intentData);
}
@@ -445,6 +446,7 @@
register: register,
setApi: setApi,
list: list,
+ listOverlaysThatShowIntents: listShowIntents,
augmentRbset: augmentRbset,
mkGlyphId: mkGlyphId,
tbSelection: tbSelection,
diff --git a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
index 6d07da7..351154c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
@@ -78,7 +78,7 @@
porthl: 1,
bg: 0,
spr: 0,
- ovidx: 1, // default to traffic overlay
+ ovid: 'traffic', // default to traffic overlay
toolbar: 0
},
prefsMap = {
@@ -104,7 +104,9 @@
}
function setInitToggleState() {
- cachedState = ps.asNumbers(ps.getPrefs(cooktag, defaultPrefsState));
+ cachedState = ps.asNumbers(
+ ps.getPrefs(cooktag, defaultPrefsState), ['ovid'], true
+ );
$log.debug('TOOLBAR---- read prefs state:', cachedState);
if (!cachedState) {
@@ -199,7 +201,7 @@
thirdRow.clear();
// persist our choice of overlay...
- persistTopoPrefs('ovidx', ovIndex[oid] || 0);
+ persistTopoPrefs('ovid', oid);
if (!order.length) {
thirdRow.setText(selOver);
@@ -277,10 +279,11 @@
persistTopoPrefs('toolbar');
}
- function setDefaultOverlay(prefsIdx) {
- var idx = ovIndex[defaultOverlay] || 0;
- if (prefsIdx >= 0 && prefsIdx < ovRset.size()) {
- idx = prefsIdx;
+ function selectOverlay(ovid) {
+ var idx = ovIndex[defaultOverlay] || 0,
+ pidx = (ovid === null) ? 0 : ovIndex[ovid] || -1;
+ if (pidx >= 0 && pidx < ovRset.size()) {
+ idx = pidx;
}
ovRset.selectedIndex(idx);
}
@@ -311,7 +314,7 @@
destroyToolbar: destroyToolbar,
keyListener: keyListener,
toggleToolbar: toggleToolbar,
- setDefaultOverlay: setDefaultOverlay,
+ selectOverlay: selectOverlay,
defaultPrefs: defaultPrefsState,
fnkey: fnkey
};
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
index 13a5f2a..312b652 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -144,9 +144,9 @@
},
// intent visualization hook
- showintent: function (intentData) {
- $log.debug('^^ trafficOverlay.showintent() ^^');
- tts.selectIntent(intentData);
+ showintent: function (info) {
+ $log.debug('^^ trafficOverlay.showintent() ^^', info);
+ tts.selectIntent(info);
}
}
};
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2.js b/web/gui/src/main/webapp/app/view/topo2/topo2.js
index e37872f..632dd14 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2.js
@@ -211,7 +211,7 @@
// tps.initPanels();
// restoreConfigFromPrefs();
- // ttbs.setDefaultOverlay(prefsState.ovidx);
+ // ttbs.setDefaultOverlay(prefsState.ovid);
// $log.debug('registered overlays...', tov.list());
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js b/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
index 690ac59..9eaf243 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2Prefs.js
@@ -29,7 +29,7 @@
porthl: 1,
bg: 0,
spr: 0,
- ovidx: 1, // default to traffic overlay
+ ovid: 'traffic', // default to traffic overlay
toolbar: 0
};