Display plugin source URL when hovering the source badge

Change-Id: Ie9e9f99229d20fa6b9630fd067a30e73646e1d15
diff --git a/jenkins-docker/server/plugin-manager/css/style.css b/jenkins-docker/server/plugin-manager/css/style.css
index 87e26a8..07ae516 100644
--- a/jenkins-docker/server/plugin-manager/css/style.css
+++ b/jenkins-docker/server/plugin-manager/css/style.css
@@ -72,3 +72,17 @@
   background-color: RGBA(13, 110, 253, 1);
   color: #fff!important;
 }
+
+div.repo-status-popup {
+  position: absolute;
+  z-index: 9999;
+  padding:8px;
+  border-radius: 4px;
+  background: white;
+  box-shadow: 0 2px 8px 0 rgba(195, 195, 195, 0.12);
+  border: 1px solid #cfd8e0;
+}
+
+.plugin-heading {
+  position: relative;
+}
diff --git a/jenkins-docker/server/plugin-manager/index.html b/jenkins-docker/server/plugin-manager/index.html
index 4dbd229..04d5c81 100644
--- a/jenkins-docker/server/plugin-manager/index.html
+++ b/jenkins-docker/server/plugin-manager/index.html
@@ -59,7 +59,21 @@
         </thead>
         <tbody>
           <tr ng-repeat="prop in plugins.list | filter:searchPlugin">
-            <td><h4>{{prop.id}} <span class="badge {{prop.css}}">{{prop.source}}</span><br/><small>{{prop.description.split('.')[0]}}</small></h4></td>
+            <td>
+              <h4 class="plugin-heading">
+                {{prop.id}}
+                <span
+                  ng-mouseover="showRepoStatus($event, prop.id, prop.jobUrl)"
+                  ng-mouseout="hideRepoStatus(prop.id)"
+                  class="badge {{prop.css}}">{{prop.source}}
+                  <div id="repo-status-popup-{{prop.id}}" style="display: none;" class="repo-status-popup">
+                    <a id="repo-status-popup-a-{{prop.id}}" target="_blank">Source Code</a>
+                  </div>
+                </span>
+                <br/>
+                <small>{{prop.description.split('.')[0]}}</small>
+              </h4>
+            </td>
             <td>
               <p>{{prop.version}}</p>
               <div ng-if="prop.update_version">
diff --git a/jenkins-docker/server/plugin-manager/js/plugin-manager.js b/jenkins-docker/server/plugin-manager/js/plugin-manager.js
index c6fb6e2..e35c769 100644
--- a/jenkins-docker/server/plugin-manager/js/plugin-manager.js
+++ b/jenkins-docker/server/plugin-manager/js/plugin-manager.js
@@ -81,6 +81,7 @@
                       currPlugin.sha1 = plugin.sha1;
                       var uiPluginRegex = /(ui-plugin-)(.*)-bazel.*/;
                       var fileEnding = plugin.name.match(uiPluginRegex) ? '.js' : '.jar';
+                      currPlugin.jobUrl = $scope.getBaseUrl() + '/job/' + plugin.name;
                       currPlugin.url = $scope.getBaseUrl() + '/job/' + plugin.name + '/lastSuccessfulBuild/artifact/bazel-bin/plugins/' + pluginName + '/' + pluginName + fileEnding;
                       currPlugin.description = pluginResponse.data.description;
                       currPlugin.source = source;
@@ -98,6 +99,7 @@
                     });
                   });
                 }, function errorCallback(response) {
+                  console.error('Failed to fetch plugin build data for ' + pluginId, response);
                 });
       }
 
@@ -105,6 +107,41 @@
         $window.location.href = 'https://gerrit-ci.gerritforge.com/securityRealm/commenceLogin?from=%2F';
       };
 
+      $scope.showRepoStatus = function(e, pluginId, pluginJobUrl) {
+        setTimeout(function() {
+          $http.get(pluginJobUrl + '/lastSuccessfulBuild/api/json', plugins.httpConfig)
+            .then(
+              function successCallback(response) {
+                var repoStatusPopup = document.getElementById('repo-status-popup-' + pluginId);
+                var repoStatusPopupAnchor = document.getElementById('repo-status-popup-a-' + pluginId);
+                if (!repoStatusPopup) return;
+
+                var scmAction = response.data.actions.filter(function(action) {
+                  return action._class == "hudson.plugins.git.util.BuildData";
+                });
+                if (!scmAction || scmAction.length == 0) return;
+
+                var sourceUrl = scmAction[0].remoteUrls.filter(function(url) {
+                      return url.indexOf("gerrit.googlesource.com/a/gerrit") === -1;
+                    });
+                if (!sourceUrl || sourceUrl.length == 0) return;
+
+                repoStatusPopup.style.display = 'block';
+                repoStatusPopupAnchor.href = sourceUrl[0].replace("/a", "");
+              }, function errorCallback(response) {}
+            );
+        }, 500);
+      };
+
+      $scope.hideRepoStatus = function(pluginId) {
+        var repoStatusPopup = document.getElementById('repo-status-popup-' + pluginId);
+        if (repoStatusPopup) {
+          setTimeout(function() {
+            repoStatusPopup.style.display = 'none';
+          }, 1000);
+        }
+      };
+
       $scope.refreshAvailable();
     });