Simon Hunt

GUI --Handle multi-selections (re-purpose the details pane);

 - W = requestTraffic
 - Z = requestPath
 - X = cancelMonitor (not implemented yet)

Change-Id: Ic5f60d19a249b1224f20f90a3e5ce946a90625c0
1 +{
2 + "event": "showPath",
3 + "sid": 3,
4 + "payload": {
5 + "ids": [
6 + "of:0000000000000007"
7 + ],
8 + "traffic": true
9 + }
10 +}
11 +// what is the client supposed to do with this?
1 +{
2 + "event": "requestTraffic",
3 + "sid": 6,
4 + "payload": {
5 + "ids": [
6 + "of:0000000000000007",
7 + "of:000000000000000c",
8 + "of:000000000000000a"
9 + ]
10 + }
11 +}
1 +{
2 + "event": "requestTraffic",
3 + "sid": 12,
4 + "payload": {
5 + "ids": [
6 + "86:C3:7B:90:79:CD/-1",
7 + "22:BA:28:81:FD:45/-1",
8 + "BA:91:F6:8E:B6:B6/-1",
9 + "06:E2:E6:F7:03:12/-1"
10 + ]
11 + }
12 +}
1 +{
2 + "event": "requestTraffic",
3 + "sid": 18,
4 + "payload": {
5 + "ids": [
6 + "of:0000000000000001",
7 + "86:C3:7B:90:79:CD/-1",
8 + "7E:D2:EE:0F:12:4A/-1",
9 + "of:000000000000000c"
10 + ]
11 + }
12 +}
...@@ -115,7 +115,6 @@ ...@@ -115,7 +115,6 @@
115 } 115 }
116 116
117 function doError(msg) { 117 function doError(msg) {
118 - errorCount++;
119 console.error(msg); 118 console.error(msg);
120 doAlert(msg); 119 doAlert(msg);
121 } 120 }
......
...@@ -139,6 +139,8 @@ ...@@ -139,6 +139,8 @@
139 #topo-detail td.value { 139 #topo-detail td.value {
140 } 140 }
141 141
142 +
143 +
142 #topo-detail hr { 144 #topo-detail hr {
143 height: 1px; 145 height: 1px;
144 color: #ccc; 146 color: #ccc;
......
...@@ -127,7 +127,8 @@ ...@@ -127,7 +127,8 @@
127 P: togglePorts, 127 P: togglePorts,
128 U: unpin, 128 U: unpin,
129 129
130 - Z: requestPath, 130 + W: requestTraffic, // bag of selections
131 + Z: requestPath, // host-to-host intent (and monitor)
131 X: cancelMonitor 132 X: cancelMonitor
132 }; 133 };
133 134
...@@ -199,7 +200,7 @@ ...@@ -199,7 +200,7 @@
199 200
200 function abortIfLive() { 201 function abortIfLive() {
201 if (config.useLiveData) { 202 if (config.useLiveData) {
202 - scenario.view.alert("Sorry, currently using live data.."); 203 + network.view.alert("Sorry, currently using live data..");
203 return true; 204 return true;
204 } 205 }
205 return false; 206 return false;
...@@ -342,14 +343,18 @@ ...@@ -342,14 +343,18 @@
342 addDevice: addDevice, 343 addDevice: addDevice,
343 addLink: addLink, 344 addLink: addLink,
344 addHost: addHost, 345 addHost: addHost,
346 +
345 updateDevice: updateDevice, 347 updateDevice: updateDevice,
346 updateLink: updateLink, 348 updateLink: updateLink,
347 updateHost: updateHost, 349 updateHost: updateHost,
350 +
348 removeDevice: stillToImplement, 351 removeDevice: stillToImplement,
349 removeLink: removeLink, 352 removeLink: removeLink,
350 removeHost: removeHost, 353 removeHost: removeHost,
354 +
351 showDetails: showDetails, 355 showDetails: showDetails,
352 - showPath: showPath 356 + showPath: showPath,
357 + showTraffic: showTraffic
353 }; 358 };
354 359
355 function addDevice(data) { 360 function addDevice(data) {
...@@ -462,6 +467,7 @@ ...@@ -462,6 +467,7 @@
462 function showDetails(data) { 467 function showDetails(data) {
463 fnTrace('showDetails', data.payload.id); 468 fnTrace('showDetails', data.payload.id);
464 populateDetails(data.payload); 469 populateDetails(data.payload);
470 + // TODO: Add single-select actions ...
465 detailPane.show(); 471 detailPane.show();
466 } 472 }
467 473
...@@ -484,6 +490,10 @@ ...@@ -484,6 +490,10 @@
484 // TODO: add selection-highlite lines to links 490 // TODO: add selection-highlite lines to links
485 } 491 }
486 492
493 + function showTraffic(data) {
494 + network.view.alert("showTraffic() -- TODO")
495 + }
496 +
487 // ............................... 497 // ...............................
488 498
489 function stillToImplement(data) { 499 function stillToImplement(data) {
...@@ -504,24 +514,58 @@ ...@@ -504,24 +514,58 @@
504 // ============================== 514 // ==============================
505 // Out-going messages... 515 // Out-going messages...
506 516
517 + function userFeedback(msg) {
518 + // for now, use the alert pane as is. Maybe different alert style in
519 + // the future (centered on view; dismiss button?)
520 + network.view.alert(msg);
521 + }
522 +
523 + function nSel() {
524 + return selectOrder.length;
525 + }
507 function getSel(idx) { 526 function getSel(idx) {
508 return selections[selectOrder[idx]]; 527 return selections[selectOrder[idx]];
509 } 528 }
529 + function getSelId(idx) {
530 + return getSel(idx).obj.id;
531 + }
532 + function allSelectionsClass(cls) {
533 + for (var i=0, n=nSel(); i<n; i++) {
534 + if (getSel(i).obj.class !== cls) {
535 + return false;
536 + }
537 + }
538 + return true;
539 + }
540 +
541 + function requestTraffic() {
542 + if (nSel() > 0) {
543 + sendMessage('requestTraffic', {
544 + ids: selectOrder
545 + });
546 + } else {
547 + userFeedback('Request-Traffic requires one or\n' +
548 + 'more items to be selected.');
549 + }
550 + }
510 551
511 - // for now, just a host-to-host intent, (and implicit start-monitoring)
512 function requestPath() { 552 function requestPath() {
513 - var payload = { 553 + if (nSel() === 2 && allSelectionsClass('host')) {
514 - one: getSel(0).obj.id, 554 + sendMessage('requestPath', {
515 - two: getSel(1).obj.id 555 + one: getSelId(0),
516 - }; 556 + two: getSelId(1)
517 - sendMessage('requestPath', payload); 557 + });
558 + } else {
559 + userFeedback('Request-Path requires two\n' +
560 + 'hosts to be selected.');
561 + }
518 } 562 }
519 563
520 function cancelMonitor() { 564 function cancelMonitor() {
521 - var payload = { 565 + // FIXME: from where do we get the intent id(s) to send to the server?
522 - id: "need_the_intent_id" // FIXME: where are we storing this? 566 + sendMessage('cancelMonitor', {
523 - }; 567 + ids: ["need_the_intent_id"]
524 - sendMessage('cancelMonitor', payload); 568 + });
525 } 569 }
526 570
527 // request details for the selected element 571 // request details for the selected element
...@@ -1200,12 +1244,43 @@ ...@@ -1200,12 +1244,43 @@
1200 1244
1201 function singleSelect() { 1245 function singleSelect() {
1202 requestDetails(); 1246 requestDetails();
1203 - // NOTE: detail pane will be shown from showDetails event. 1247 + // NOTE: detail pane will be shown from showDetails event callback
1204 } 1248 }
1205 1249
1206 function multiSelect() { 1250 function multiSelect() {
1207 - // TODO: use detail pane for multi-select view. 1251 + populateMultiSelect();
1208 - //detailPane.show(); 1252 + // TODO: Add multi-select actions ...
1253 + }
1254 +
1255 + function addSep(tbody) {
1256 + var tr = tbody.append('tr');
1257 + $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
1258 + }
1259 +
1260 + function addProp(tbody, label, value) {
1261 + var tr = tbody.append('tr');
1262 +
1263 + tr.append('td')
1264 + .attr('class', 'label')
1265 + .text(label + ' :');
1266 +
1267 + tr.append('td')
1268 + .attr('class', 'value')
1269 + .text(value);
1270 + }
1271 +
1272 + function populateMultiSelect() {
1273 + detailPane.empty();
1274 +
1275 + var title = detailPane.append("h2"),
1276 + table = detailPane.append("table"),
1277 + tbody = table.append("tbody");
1278 +
1279 + title.text('Multi-Select...');
1280 +
1281 + selectOrder.forEach(function (d, i) {
1282 + addProp(tbody, i+1, d);
1283 + });
1209 } 1284 }
1210 1285
1211 function populateDetails(data) { 1286 function populateDetails(data) {
...@@ -1225,23 +1300,6 @@ ...@@ -1225,23 +1300,6 @@
1225 addProp(tbody, p, data.props[p]); 1300 addProp(tbody, p, data.props[p]);
1226 } 1301 }
1227 }); 1302 });
1228 -
1229 - function addSep(tbody) {
1230 - var tr = tbody.append('tr');
1231 - $('<hr>').appendTo(tr.append('td').attr('colspan', 2));
1232 - }
1233 -
1234 - function addProp(tbody, label, value) {
1235 - var tr = tbody.append('tr');
1236 -
1237 - tr.append('td')
1238 - .attr('class', 'label')
1239 - .text(label + ' :');
1240 -
1241 - tr.append('td')
1242 - .attr('class', 'value')
1243 - .text(value);
1244 - }
1245 } 1303 }
1246 1304
1247 // ============================== 1305 // ==============================
......