[ONOS-3526]Web UI - Provide a 'Navigate to help page' link or button

Change-Id: I5260e625bb8890b31606dc31b43d4df84bd7eaf4
diff --git a/core/api/src/main/java/org/onosproject/ui/UiView.java b/core/api/src/main/java/org/onosproject/ui/UiView.java
index 63cd468..4234e98 100644
--- a/core/api/src/main/java/org/onosproject/ui/UiView.java
+++ b/core/api/src/main/java/org/onosproject/ui/UiView.java
@@ -24,6 +24,9 @@
  */
 public class UiView {
 
+    private static final  String DEFAULT_HELP_PAGE_URL =
+            "https://wiki.onosproject.org/display/ONOS/The+ONOS+Web+GUI";
+
     /**
      * Designates the navigation menu category.
      */
@@ -70,6 +73,7 @@
     private final String id;
     private final String label;
     private final String iconId;
+    private final String helpPageUrl;
 
     /**
      * Creates a new user interface view descriptor. The navigation item
@@ -80,7 +84,7 @@
      * @param label    view label
      */
     public UiView(Category category, String id, String label) {
-        this(category, id, label, null);
+        this(category, id, label, null, null);
     }
 
     /**
@@ -97,10 +101,31 @@
      * @param iconId   icon id
      */
     public UiView(Category category, String id, String label, String iconId) {
+        this(category, id, label, iconId, null);
+    }
+
+    /**
+     * Creates a new user interface view descriptor. The navigation item
+     * will appear in the navigation menu under the specified category,
+     * with the specified icon adornment and specified help page.
+     * <p>
+     * Note: see the {@code glyphMapping} structure in {@code icon.js} for
+     * valid icon identifiers.
+     *
+     * @param category view category
+     * @param id       view identifier
+     * @param label    view label
+     * @param iconId   icon id
+     * @param helpPageUrl help page URL
+     */
+    public UiView(Category category, String id, String label, String iconId,
+                  String helpPageUrl) {
         this.category = category;
         this.id = id;
         this.label = label;
         this.iconId = iconId;
+        this.helpPageUrl = (helpPageUrl == null) ?
+                DEFAULT_HELP_PAGE_URL : helpPageUrl;
     }
 
     /**
@@ -139,6 +164,15 @@
         return iconId;
     }
 
+    /**
+     * Returns the help page URL for a specific view.
+     *
+     * @return help page URL
+     */
+    public String helpPageUrl() {
+        return helpPageUrl;
+    }
+
     @Override
     public int hashCode() {
         return id.hashCode();
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/MainModuleResource.java b/web/gui/src/main/java/org/onosproject/ui/impl/MainModuleResource.java
index 4f54b39..242f7ba 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/MainModuleResource.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/MainModuleResource.java
@@ -41,9 +41,10 @@
 
     private static final String MAIN_JS = "onos.js";
 
-    private static final String INJECT_VIEW_IDS_START = "// {INJECTED-VIEW-IDS-START}";
-    private static final String INJECT_VIEW_IDS_END = "// {INJECTED-VIEW-IDS-END}";
+    private static final String INJECT_VIEW_IDS_START = "// {INJECTED-VIEW-DATA-START}";
+    private static final String INJECT_VIEW_IDS_END = "// {INJECTED-VIEW-DATA-END}";
     private static final String PREFIX = "        '";
+    private static final String MIDFIX = "' : '";
     private static final String SUFFIX = String.format("',%n");
 
     @GET
@@ -70,10 +71,19 @@
         StringBuilder sb = new StringBuilder("\n");
         for (UiExtension extension : service.getExtensions()) {
             for (UiView view : extension.views()) {
-                sb.append(PREFIX).append(view.id()).append(SUFFIX);
+                sb.append(PREFIX)
+                        .append(view.id())
+                        .append(MIDFIX)
+                        .append(sanitizeUrl(view.helpPageUrl()))
+                        .append(SUFFIX);
             }
         }
         return new ByteArrayInputStream(sb.toString().getBytes());
     }
 
+    private String sanitizeUrl(String url) {
+        // TODO: add logic for validating URL
+        return url;
+    }
+
 }
diff --git a/web/gui/src/main/webapp/app/fw/mast/mast.css b/web/gui/src/main/webapp/app/fw/mast/mast.css
index 4b8131e..3470f18 100644
--- a/web/gui/src/main/webapp/app/fw/mast/mast.css
+++ b/web/gui/src/main/webapp/app/fw/mast/mast.css
@@ -52,13 +52,18 @@
     line-height: 44px;
 }
 
-
 /*
     MAST HEAD DROPDOWN MENU
 */
 
+#mast-right div.ctrl-btns {
+    position: relative;
+    float: right;
+}
+
 #mast .dropdown-parent {
     position: relative;
+    float: right;
 }
 
 #mast .dropdown-parent i.dropdown-icon {
diff --git a/web/gui/src/main/webapp/app/fw/mast/mast.html b/web/gui/src/main/webapp/app/fw/mast/mast.html
index ddcc048..592f0c8 100644
--- a/web/gui/src/main/webapp/app/fw/mast/mast.html
+++ b/web/gui/src/main/webapp/app/fw/mast/mast.html
@@ -3,15 +3,19 @@
      ng-click="mastCtrl.toggleNav()"></div>
 <img class="logo" src="data/img/masthead-logo-mojo.png">
 <div id="mast-right">
-
     <nav>
         <div class="dropdown-parent">
             <a class="clickable user-menu__name">{{user}} <i class="dropdown-icon"></i></a>
-
             <div class="dropdown">
                 <a href="rs/logout">logout</a>
             </div>
         </div>
+        <div class="ctrl-btns">
+            <div class="active clickable"
+                 icon icon-size="42" icon-id="query"
+                 tooltip tt-msg="helpTip"
+                 ng-click="directTo()"></div>
+        </div>
     </nav>
 
 </div>
diff --git a/web/gui/src/main/webapp/app/fw/mast/mast.js b/web/gui/src/main/webapp/app/fw/mast/mast.js
index d43987d..4d8b5fa 100644
--- a/web/gui/src/main/webapp/app/fw/mast/mast.js
+++ b/web/gui/src/main/webapp/app/fw/mast/mast.js
@@ -33,10 +33,10 @@
 
     angular.module('onosMast', ['onosNav'])
         .controller('MastCtrl',
-        ['$log', '$scope', '$window', 'WebSocketService', 'NavService',
+        ['$log', '$scope', '$location', '$window', 'WebSocketService', 'NavService',
             'DialogService',
 
-        function ($log, $scope, $window, wss, ns, ds) {
+        function ($log, $scope, $location, $window, wss, ns, ds) {
             var self = this;
 
             function triggerRefresh(action) {
@@ -86,6 +86,14 @@
 
             // onosAuth is a global set via the index.html generated source
             $scope.user = onosAuth || '(no one)';
+            $scope.helpTip = 'Show help page for current view';
+
+            $scope.directTo = function () {
+                var curId = $location.path().replace('/', ''),
+                    viewMap = $scope.onos['viewMap'],
+                    helpUrl = viewMap[curId];
+                $window.open(helpUrl);
+            };
 
             $log.log('MastCtrl has been created');
         }])
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js
index 91b9aee..a24542f 100644
--- a/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -42,6 +42,7 @@
         topo: 'topo',
 
         refresh: 'refresh',
+        query: 'query',
         garbage: 'garbage',
 
         upArrow: 'triangleUp',
diff --git a/web/gui/src/main/webapp/onos.js b/web/gui/src/main/webapp/onos.js
index fc4683d..2e62744 100644
--- a/web/gui/src/main/webapp/onos.js
+++ b/web/gui/src/main/webapp/onos.js
@@ -35,13 +35,12 @@
         'onosWidget'
     ];
 
-    // view IDs.. injected via the servlet
-    var viewIds = [
-        // {INJECTED-VIEW-IDS-START}
-        // {INJECTED-VIEW-IDS-END}
-        // dummy entry
-        ''
-    ];
+    // view ID to help page url map.. injected via the servlet
+    var viewMap = {
+        // {INJECTED-VIEW-DATA-START}
+        // {INJECTED-VIEW-DATA-END}
+    },
+    viewIds = [];
 
     // secret sauce
     var sauce = [
@@ -63,6 +62,8 @@
     var defaultView = 'topo',
         viewDependencies = [];
 
+    viewIds = d3.map(viewMap).keys();
+
     viewIds.forEach(function (id) {
         if (id) {
             viewDependencies.push('ov' + cap(id));
@@ -102,6 +103,7 @@
 
                 // shared object inherited by all views:
                 $scope.onos = {};
+                $scope.onos['viewMap'] = viewMap;
 
                 // initialize services...
                 ts.init();