GUI -- Added TopoPanelService to encapsulate summary, detail and instance panels.
- Rudimentary handling of 'showSummary' event implemented.
- Fixed resize behavior of topo SVG.
- Created 'migrate' mock-server scenario.
- Added 'restart' command to mock-server.

Change-Id: I90ac93dbc9efb8f17ef95825d3159030145267a2
diff --git a/web/gui/src/main/webapp/app/index.html b/web/gui/src/main/webapp/app/index.html
index 853db93..92b1712 100644
--- a/web/gui/src/main/webapp/app/index.html
+++ b/web/gui/src/main/webapp/app/index.html
@@ -76,6 +76,7 @@
     <script src="view/topo/topo.js"></script>
     <script src="view/topo/topoEvent.js"></script>
     <script src="view/topo/topoForce.js"></script>
+    <script src="view/topo/topoPanel.js"></script>
     <script src="view/device/device.js"></script>
     <!-- TODO: inject javascript refs server-side -->
 
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 a22e7ba..05ddb66 100644
--- a/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -28,7 +28,7 @@
     ];
 
     // references to injected services etc.
-    var $log, fs, ks, zs, gs, ms, ps, tes, tfs;
+    var $log, fs, ks, zs, gs, ms, tes, tfs, tps;
 
     // DOM elements
     var ovtopo, svg, defs, zoomLayer, mapG, forceG;
@@ -101,9 +101,9 @@
 
 
     // callback invoked when the SVG view has been resized..
-    function svgResized(w, h) {
-        $log.debug('TopoView just resized... ' + w + 'x' + h);
-        tfs.resize(w, h);
+    function svgResized(dim) {
+        //$log.debug('TopoView just resized... ', dim);
+        tfs.resize(dim);
     }
 
     // --- Background Map ------------------------------------------------
@@ -137,6 +137,10 @@
         tfs.initForce(forceG, svg.attr('width'), svg.attr('height'));
     }
 
+    function setUpPanels() {
+        tps.initPanels();
+    }
+
 
     // --- Controller Definition -----------------------------------------
 
@@ -146,10 +150,10 @@
             '$scope', '$log', '$location', '$timeout',
             'FnService', 'MastService',
             'KeyService', 'ZoomService', 'GlyphService', 'MapService',
-            'PanelService', 'TopoEventService', 'TopoForceService',
+            'TopoEventService', 'TopoForceService', 'TopoPanelService',
 
         function ($scope, _$log_, $loc, $timeout, _fs_, mast,
-                  _ks_, _zs_, _gs_, _ms_, _ps_, _tes_, _tfs_) {
+                  _ks_, _zs_, _gs_, _ms_, _tes_, _tfs_, _tps_) {
             var self = this;
             $log = _$log_;
             fs = _fs_;
@@ -157,12 +161,12 @@
             zs = _zs_;
             gs = _gs_;
             ms = _ms_;
-            ps = _ps_;
             tes = _tes_;
             tfs = _tfs_;
+            tps = _tps_;
 
             self.notifyResize = function () {
-                svgResized(svg.attr('width'), svg.attr('height'));
+                svgResized(fs.windowSize(mast.mastHeight()));
             };
 
             // Cleanup on destroyed scope..
@@ -186,16 +190,11 @@
             setUpZoom();
             setUpMap();
             setUpForce();
+            setUpPanels();
 
             // open up a connection to the server...
             tes.openSock();
 
-            // TODO: remove this temporary code....
-            var p = ps.createPanel('topo-p-summary');
-            p.append('h1').text('Hello World');
-            p.show();
-            $timeout(function () { p.hide(); }, 2000);
-
             $log.log('OvTopoCtrl has been created');
         }]);
 }());
diff --git a/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
index 5533e16..009c048 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -23,7 +23,7 @@
     'use strict';
 
     // injected refs
-    var $log, wss, wes;
+    var $log, wss, wes, tps;
 
     // internal state
     var wsock;
@@ -42,11 +42,12 @@
     // === Event Handlers ===
 
     function showSummary(ev) {
-        $log.log('  **** Show Summary ****  ', ev.payload);
+        $log.debug('  **** Show Summary ****  ', ev.payload);
+        tps.showSummary(ev.payload);
     }
 
     function addInstance(ev) {
-        $log.log(' *** We got an ADD INSTANCE event: ', ev);
+        $log.debug(' *** We got an ADD INSTANCE event: ', ev);
     }
 
     // ==========================
@@ -86,11 +87,13 @@
     angular.module('ovTopo')
     .factory('TopoEventService',
         ['$log', '$location', 'WebSocketService', 'WsEventService',
+            'TopoPanelService',
 
-        function (_$log_, $loc, _wss_, _wes_) {
+        function (_$log_, $loc, _wss_, _wes_, _tps_) {
             $log = _$log_;
             wss = _wss_;
             wes = _wes_;
+            tps = _tps_;
 
             function bindDispatcher(TopoDomElementsPassedHere) {
                 // TODO: store refs to topo DOM elements...
diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js
index 196188c..3a0791c 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -124,8 +124,8 @@
                     selectCb, atDragEnd, dragEnabled, clickEnabled);
             }
 
-            function resize(w, h) {
-                force.size([w, h]);
+            function resize(dim) {
+                force.size([dim.width, dim.height]);
                 // Review -- do we need to nudge the layout ?
 
             }
diff --git a/web/gui/src/main/webapp/app/view/topo/topoPanel.js b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
new file mode 100644
index 0000000..e513b1f
--- /dev/null
+++ b/web/gui/src/main/webapp/app/view/topo/topoPanel.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Topology Panel Module.
+ Defines functions for manipulating the summary, detail, and instance panels.
+ */
+
+(function () {
+    'use strict';
+
+    // injected refs
+    var $log, ps;
+
+    // internal state
+    var settings;
+
+
+    // SVG elements;
+    var fooPane;
+
+    // D3 selections;
+    var summaryPanel,
+        detailPanel,
+        instancePanel;
+
+    // default settings for force layout
+    var defaultSettings = {
+        foo: 2
+    };
+
+
+    // ==========================
+
+    angular.module('ovTopo')
+    .factory('TopoPanelService',
+        ['$log', 'PanelService',
+
+        function (_$log_, _ps_) {
+            $log = _$log_;
+            ps = _ps_;
+
+            function initPanels() {
+                summaryPanel = ps.createPanel('topo-p-summary');
+                // TODO: set up detail and instance panels..
+            }
+
+            function showSummary(payload) {
+                summaryPanel.empty();
+                summaryPanel.append('h2').text(payload.id);
+                // TODO: complete the formatting...
+
+                summaryPanel.show();
+            }
+
+            return {
+                initPanels: initPanels,
+                showSummary: showSummary
+            };
+        }]);
+}());
diff --git a/web/gui/src/main/webapp/tests/app/view/topo/topoEvent-spec.js b/web/gui/src/main/webapp/tests/app/view/topo/topoEvent-spec.js
index 1fd1572..8cd6d25 100644
--- a/web/gui/src/main/webapp/tests/app/view/topo/topoEvent-spec.js
+++ b/web/gui/src/main/webapp/tests/app/view/topo/topoEvent-spec.js
@@ -20,7 +20,7 @@
 describe('factory: view/topo/topoEvent.js', function() {
     var $log, fs, tes;
 
-    beforeEach(module('ovTopo', 'onosUtil'));
+    beforeEach(module('ovTopo', 'onosUtil', 'onosLayer'));
 
     beforeEach(inject(function (_$log_, FnService, TopoEventService) {
         $log = _$log_;
diff --git a/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js b/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js
new file mode 100644
index 0000000..4564d1e
--- /dev/null
+++ b/web/gui/src/main/webapp/tests/app/view/topo/topoPanel-spec.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ ONOS GUI -- Topo View -- Topo Panel Service - Unit Tests
+ */
+describe('factory: view/topo/topoPanel.js', function() {
+    var $log, fs, tps;
+
+    beforeEach(module('ovTopo', 'onosUtil', 'onosLayer'));
+
+    beforeEach(inject(function (_$log_, FnService, TopoPanelService) {
+        $log = _$log_;
+        fs = FnService;
+        tps = TopoPanelService;
+    }));
+
+    it('should define TopoPanelService', function () {
+        expect(tps).toBeDefined();
+    });
+
+    it('should define api functions', function () {
+        expect(fs.areFunctions(tps, [
+            'initPanels'
+        ])).toBeTruthy();
+    });
+
+    // TODO: more tests...
+});
diff --git a/web/gui/src/test/_karma/ev/migrate/ev_1_onos.json b/web/gui/src/test/_karma/ev/migrate/ev_1_onos.json
new file mode 100644
index 0000000..a08504e
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/migrate/ev_1_onos.json
@@ -0,0 +1,28 @@
+{
+  "event": "showSummary",
+  "sid": 1,
+  "payload": {
+    "id": "ONOS Summary",
+    "type": "node",
+    "propOrder": [
+      "Devices",
+      "Links",
+      "Hosts",
+      "Topology SCCs",
+      "-",
+      "Intents",
+      "Flows",
+      "Version"
+    ],
+    "props": {
+      "Devices": "25",
+      "Links": "112",
+      "Hosts": "0",
+      "Topology SCCs": "1",
+      "-": "",
+      "Intents": "0",
+      "Flows": "125",
+      "Version": "1.0.0*"
+    }
+  }
+}
diff --git a/web/gui/src/test/_karma/ev/migrate/scenario.json b/web/gui/src/test/_karma/ev/migrate/scenario.json
new file mode 100644
index 0000000..5ba2520
--- /dev/null
+++ b/web/gui/src/test/_karma/ev/migrate/scenario.json
@@ -0,0 +1,12 @@
+{
+  "comments": [
+    "Used during the migration of old GUI (topo.js==3.1KLOC) to Angular"
+  ],
+  "title": "Migration Helper",
+  "params": {
+    "lastAuto": 0
+  },
+  "description": [
+    "Do what you need to..."
+  ]
+}
diff --git a/web/gui/src/test/_karma/wssrv.js b/web/gui/src/test/_karma/wssrv.js
index b99cb6d..58eae91 100644
--- a/web/gui/src/test/_karma/wssrv.js
+++ b/web/gui/src/test/_karma/wssrv.js
@@ -34,7 +34,7 @@
 });
 
 server.on('listening', function () {
-    console.log('ok, server is running');
+    console.log('OK, server is running');
 });
 
 var wsServer = new WebSocketServer({
@@ -110,6 +110,7 @@
             case 'm': customMessage(str); break;
             case 's': setScenario(str); break;
             case 'n': nextEvent(); break;
+            case 'r': restartScenario(); break;
             case 'q': quit(); break;
             case '?': showHelp(); break;
             default: console.log('Say what?!  (? for help)'); break;
@@ -126,10 +127,11 @@
 var helptext = '\n' +
         'c        - show connection status\n' +
         'm {text} - send custom message to client\n' +
-        's {id}   - set scenario\n' +
+        's {id}   - load scenario {id}\n' +
         's        - show scenario staus\n' +
         //'a        - auto-send events\n' +
         'n        - send next event\n' +
+        'r        - restart the scenario\n' +
         'q        - exit the server\n' +
         '?        - display this help text\n';
 
@@ -146,13 +148,13 @@
 }
 
 function quit() {
-    console.log('quitting...');
+    console.log('Quitting...');
     process.exit(0);
 }
 
 function customMessage(m) {
     if (connection) {
-        console.log('sending message: ' + m);
+        console.log('Sending message: ' + m);
         connection.sendUTF(m);
     } else {
         console.warn('No current connection.');
@@ -162,7 +164,7 @@
 function showScenarioStatus() {
     var msg;
     if (!scenario) {
-        console.log('No scenario selected.');
+        console.log('No scenario loaded.');
     } else {
         msg = 'Scenario: "' + scenario + '", ' +
                 (scdone ? 'DONE' : 'next event: ' + evno);
@@ -189,7 +191,7 @@
         } else {
             evdata = JSON.parse(data);
             console.log(); // get past prompt
-            console.log('setting scenario to "' + id + '"');
+            console.log('Loading scenario "' + id + '"');
             console.log(evdata.title);
             evdata.description.forEach(function (d) {
                 console.log('  ' + d);
@@ -201,11 +203,27 @@
     });
 }
 
+function restartScenario() {
+    if (!scenario) {
+        console.log('No scenario loaded.');
+    } else {
+        console.log();
+        console.log('Restarting scenario "' + scenario + '"');
+        console.log(evdata.title);
+        evdata.description.forEach(function (d) {
+            console.log('  ' + d);
+        });
+        evno = 1;
+        scdone = false;
+    }
+    rl.prompt();
+}
+
 function nextEvent() {
     var path;
 
     if (!scenario) {
-        console.log('No scenario selected.');
+        console.log('No scenario loaded.');
         rl.prompt();
     } else if (!connection) {
         console.warn('No current connection.');
@@ -220,7 +238,7 @@
             } else {
                 evdata = JSON.parse(data);
                 console.log(); // get past prompt
-                console.log('sending event #' + evno + ' [' + evdata.event + ']');
+                console.log('Sending event #' + evno + ' [' + evdata.event + ']');
                 connection.sendUTF(data);
                 evno++;
             }