http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/metrics-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/metrics-ctrl.js 
b/griffin-ui/js/controllers/metrics-ctrl.js
new file mode 100644
index 0000000..223cca4
--- /dev/null
+++ b/griffin-ui/js/controllers/metrics-ctrl.js
@@ -0,0 +1,180 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function(controllers) {
+    'use strict';
+    controllers.controller('MetricsCtrl', ['$scope', '$http', '$config', 
'$location', '$routeParams', '$timeout', '$compile', '$route', '$barkChart', 
'$rootScope', function($scope, $http, $config, $location, $routeParams, 
$timeout, $compile, $route, $barkChart, $rootScope) {
+        console.log('Route parameter: ' + $routeParams.sysName);
+
+        var echarts = require('echarts');
+
+        pageInit();
+
+        function pageInit() {
+          $scope.$emit('initReq');
+
+          var url_dashboard = $config.uri.dashboard + 
($routeParams.sysName?('/'+$routeParams.sysName):'');
+
+          $http.get(url_dashboard, {cache:true}).success(function(res) {
+            $scope.dashboard = res;
+            // console.log(res);
+            $scope.orgs = [];
+
+            var orgNode = null;
+            angular.forEach(res, function(sys) {
+              orgNode = new Object();
+              $scope.orgs.push(orgNode);
+              orgNode.name = sys.name;
+              orgNode.dq = sys.dq;
+
+              orgNode.assetMap = {};
+
+              angular.forEach(sys.metrics, function(metric) {
+                if(!metric.assetName){
+                  metric.assetName = 'unknown';
+                }
+                
if(Object.getOwnPropertyNames(orgNode.assetMap).indexOf(metric.assetName) == 
-1){//not existed
+                  orgNode.assetMap[metric.assetName] = {};
+
+                }
+                var chartData = metric.details;
+                chartData.sort(function(a, b){
+                  return a.timestamp - b.timestamp;
+                });
+
+                orgNode.assetMap[metric.assetName].details = chartData;
+
+
+              });
+
+                $scope.orgs.push(orgNode);
+            });
+            $scope.originalData = angular.copy(res);
+            // console.log($scope.originalData);
+            if($routeParams.sysName && $scope.originalData && 
$scope.originalData.length > 0){
+              for(var i = 0; i < $scope.originalData.length; i ++){
+                if($scope.originalData[i].name == $routeParams.sysName){
+                  $scope.selectedOrgIndex = i;
+                  $scope.changeOrg();
+                  $scope.orgSelectDisabled = true;
+                  break;
+                }
+
+              }
+            }
+
+            $timeout(function() {
+              redraw($scope.dashboard);
+            });
+
+          });
+        }
+
+
+        $scope.$watch('selectedOrgIndex', function(newValue){
+          console.log(newValue);
+        });
+
+        var redraw = function(data) {
+          // console.log(data);
+
+          $scope.chartHeight = $('.chartItem:eq(0)').width()*0.8+'px';
+
+            angular.forEach(data, function(sys, parentIndex) {
+                var parentIndex = parentIndex
+                angular.forEach(sys.metrics, function(metric, index) {
+
+                    $('#thumbnail'+parentIndex+'-'+index).get(0).style.width = 
$('#thumbnail'+parentIndex+'-'+index).parent().width()+'px';
+                    $('#thumbnail'+parentIndex+'-'+index).get(0).style.height 
= $scope.chartHeight;
+
+                    var thumbnailChart = 
echarts.init($('#thumbnail'+parentIndex+'-'+index).get(0), 'dark');
+                    thumbnailChart.setOption($barkChart.getOptionThum(metric));
+
+                });
+            });
+        }
+
+        $scope.assetOptions = [];
+
+        $scope.changeOrg = function() {
+          $scope.selectedAssetIndex = undefined;
+          $scope.assetOptions = [];
+          $scope.dashboard = [];
+          if($scope.selectedOrgIndex === ""){
+            $scope.dashboard = angular.copy($scope.originalData);
+          } else {
+            var org = 
angular.copy($scope.originalData[$scope.selectedOrgIndex]);
+            $scope.dashboard.push(org);
+            angular.forEach(org.metrics, function(metric, index) {
+              if($scope.assetOptions.indexOf(metric.assetName) == -1) {
+                $scope.assetOptions.push(metric.assetName);
+              }
+            });
+          }
+          // redraw($scope.dashboard);
+          $timeout(function() {
+              redraw($scope.dashboard);
+            }, 0);
+        };
+
+        $scope.changeAsset = function() {
+          $scope.dashboard = [];
+          if($scope.selectedOrgIndex == ""){
+            $scope.dashboard = angular.copy($scope.originalData);
+          } else {
+            var org = 
angular.copy($scope.originalData[$scope.selectedOrgIndex]);
+            $scope.dashboard.push(org);
+          }
+          if($scope.selectedAssetIndex != undefined && 
$scope.selectedAssetIndex != ''){
+            var asset = $scope.assetOptions[$scope.selectedAssetIndex];
+            angular.forEach($scope.dashboard, function(sys) {
+              var oldMetrics = sys.metrics;
+              sys.metrics = [];
+              angular.forEach(oldMetrics, function(metric, index) {
+                if(metric.assetName == asset) {
+                  sys.metrics.push(metric);
+                }
+              });
+            });
+          }
+          $timeout(function() {
+              redraw($scope.dashboard);
+            }, 0);
+        }
+
+        $scope.$on('resizeHandler', function() {
+          if($route.current.$$route.controller == 'MetricsCtrl') {
+            console.log('metrics resize');
+            redraw($scope.dashboard);
+          }
+        });
+
+        /*click the chart to be bigger*/
+        $scope.showBig = function(t){
+          var metricDetailUrl = $config.uri.metricdetail + '/' + t.name;
+          // var metricDetailUrl = '/js/mock_data/anom.json';
+          $http.get(metricDetailUrl).success(function (data){
+            $rootScope.showBigChart($barkChart.getOptionBig(data));
+          });
+
+        }
+
+        $scope.getSample = function(item) {
+          $rootScope.$broadcast('downloadSample', item.name);
+        };
+
+        
+    }
+    ]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/module.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/module.js 
b/griffin-ui/js/controllers/module.js
new file mode 100644
index 0000000..624c962
--- /dev/null
+++ b/griffin-ui/js/controllers/module.js
@@ -0,0 +1,18 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['angular'], function (ng) {
+    'use strict';
+    return ng.module('app.controllers', []);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/mydashboard-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/mydashboard-ctrl.js 
b/griffin-ui/js/controllers/mydashboard-ctrl.js
new file mode 100644
index 0000000..3cc215d
--- /dev/null
+++ b/griffin-ui/js/controllers/mydashboard-ctrl.js
@@ -0,0 +1,84 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function(controllers) {
+    'use strict';
+    controllers.controller('MyDashboardCtrl', ['$scope', '$http', '$config', 
'$location', 'toaster', '$timeout', '$route', '$filter', '$compile', 
'$barkChart', '$rootScope', function($scope, $http, $config, $location, 
toaster, $timeout, $route, $filter, $compile, $barkChart, $rootScope) {
+
+        var echarts = require('echarts');
+
+        pageInit();
+
+        function pageInit() {
+          $scope.$emit('initReq');
+
+          var url_dashboard = $config.uri.getmydashboard + $scope.ntAccount;
+          $http.get(url_dashboard).success(function(res) {
+              $scope.dashboard = res;
+              angular.forEach(res, function(sys) {
+                angular.forEach(sys.metrics, function(metric) {
+                  var chartData = metric.details;
+                  chartData.sort(function(a, b){
+                    return a.timestamp - b.timestamp;
+                  });
+
+                });
+              });
+              $scope.originalData = angular.copy(res);
+              $timeout(function() {
+                redraw($scope.dashboard);
+              }, 0);
+          });
+
+        }
+
+        var redraw = function(data) {
+
+          $scope.chartHeight = $('.chartItem:eq(0)').width()*0.8+'px';
+
+            angular.forEach(data, function(sys, parentIndex) {
+                var parentIndex = parentIndex;
+                angular.forEach(sys.metrics, function(metric, index) {
+                    $('#thumbnail'+parentIndex+'-'+index).get(0).style.width = 
$('#thumbnail'+parentIndex+'-'+index).parent().width()+'px';
+                    $('#thumbnail'+parentIndex+'-'+index).get(0).style.height 
= $scope.chartHeight;
+
+                    var thumbnailChart = 
echarts.init($('#thumbnail'+parentIndex+'-'+index).get(0), 'dark');
+                    thumbnailChart.setOption($barkChart.getOptionThum(metric));
+                });
+            });
+        }
+
+        $scope.$on('resizeHandler', function() {
+            if($route.current.$$route.controller == 'MyDashboardCtrl') {
+                console.log('mydashboard resize');
+                redraw($scope.dashboard);
+            }
+        });
+
+        /*click the chart to be bigger*/
+        $scope.showBig = function(t){
+          var metricDetailUrl = $config.uri.metricdetail + '/' + t.name;
+          // var metricDetailUrl = '/js/mock_data/anom.json';
+          $http.get(metricDetailUrl).success(function (data){
+            $rootScope.showBigChart($barkChart.getOptionBig(data));
+          });
+
+        }
+
+        $scope.getSample = function(item) {
+          $rootScope.$broadcast('downloadSample', item.name);
+        };
+
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/nav-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/nav-ctrl.js 
b/griffin-ui/js/controllers/nav-ctrl.js
new file mode 100644
index 0000000..8808000
--- /dev/null
+++ b/griffin-ui/js/controllers/nav-ctrl.js
@@ -0,0 +1,65 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (controllers) {
+    'use strict';
+    controllers.controller('NavCtrl', ['$scope', '$http', '$config', 
'$location', '$cookies', '$rootScope', '$timeout', function ($scope, $http, 
$config, $location, $cookies, $rootScope, $timeout) {
+      console.log('Navigation controller');
+      var cookieObjs = $cookies.getAll();
+      if(cookieObjs.ntAccount){
+        $rootScope.ntAccount = cookieObjs.ntAccount;
+        $rootScope.fullName = cookieObjs.fullName;
+      }else{
+        window.location.replace('/login/login.html');
+      }
+
+      var adminGroup = ['lzhixing', 'yosha', 'wenzhao', 'aiye', 'lshao'];
+           $rootScope.adminAccess = (adminGroup.indexOf($scope.ntAccount)!=-1);
+
+      // $scope.test = 'test';
+      $scope.isActive = function (route) {
+          return $location.path().indexOf(route) == 0;
+          //return $location.path() == route;
+      }
+
+      var timer = null;
+      $("#searchBox").off("keyup");
+      $("#searchBox").on("keyup", function(event){
+        if(timer){
+          $timeout.cancel(timer);
+        }
+        var searchValue = event.target.value;
+
+        if(searchValue != undefined){
+            timer = $timeout(function(){
+              $rootScope.keyword = searchValue.trim();
+            }, 500);
+        }
+      });
+
+      $scope.$on('$routeChangeStart', function(next, current) {
+        $("#searchBox").val('');
+        $rootScope.keyword = '';
+      });
+
+      $scope.logout = function(){
+        $rootScope.ntAccount = undefined;
+        $rootScope.fullName = undefined;
+        $cookies.remove('ntAccount');
+        $cookies.remove('fullName');
+        window.location.replace('/login/login.html');
+      }
+
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/rule-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/rule-ctrl.js 
b/griffin-ui/js/controllers/rule-ctrl.js
new file mode 100644
index 0000000..a82c3e1
--- /dev/null
+++ b/griffin-ui/js/controllers/rule-ctrl.js
@@ -0,0 +1,174 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (controllers) {
+    'use strict';
+    controllers.controller('RuleCtrl', ['$scope', '$http', '$config', 
'$location', '$timeout', '$route', 'toaster', '$filter', function ($scope, 
$http, $config, $location, $timeout, $route, toaster, $filter) {
+      console.log('rule controller');
+
+      $scope.statusList = $filter('strarr')('modelstatus');
+      $scope.systemList = $filter('strarr')('modelsystem');
+      $scope.typeList = $filter('strarr')('modeltype');
+
+      var allModels = $config.uri.allModels;
+      var ts = null;
+      var start = 0;
+      var number = 10;
+      var originalRowCollection = undefined;
+
+      $scope.paging = function(tableState){
+        console.log(tableState);
+        ts = tableState;
+
+        // tableState.pagination.numberOfPages = 
$scope.rowCollection.length/10 + 1;
+        start = tableState.pagination.start || 0;
+        number = tableState.pagination.number || 10;
+
+        if(start == 0 && !$scope.rowCollection){
+         $http.get(allModels).success(function(data) {
+           data.sort(function(a,b){
+             return -(a.createDate - b.createDate);
+           });
+           originalRowCollection = angular.copy(data);
+           $scope.rowCollection = angular.copy(data);
+
+           $scope.displayed = $scope.rowCollection.slice(start, start+number);
+           tableState.pagination.numberOfPages = 
Math.ceil($scope.rowCollection.length/number);
+         });
+        }else{
+         $scope.displayed = $scope.rowCollection.slice(start, start+number);
+        }
+      };
+
+      var include = function(keyword, str) {
+        if(keyword == undefined || keyword == null){
+          return true;
+        } else if(str == undefined || str == null){
+          return false;
+        } else{
+          var value = keyword.trim().toLowerCase();
+          return str.trim().toLowerCase().includes(value);
+        }
+      };
+
+      var findValue = function(keyword, assetItem) {
+        var date = $filter('date')(assetItem.createDate, 'M/d/yy h:mm a', 
'-0700')
+        return include(keyword, assetItem.name)
+          || include(keyword, assetItem.description)
+          || include(keyword, assetItem.owner)
+          || include(keyword, $filter('strmap')(assetItem.system, 
$scope.systemList))
+          || include(keyword, $filter('strmap')(assetItem.status, 
$scope.statusList))
+          || include(keyword, $filter('strmap')(assetItem.type, 
$scope.typeList))
+          || include(keyword, date);
+      };
+
+      $scope.$watch('keyword', function(newValue){
+        if(originalRowCollection){
+          start = 0;
+          if(newValue == undefined || newValue == ''){
+            $scope.rowCollection = angular.copy(originalRowCollection);
+          }else{
+            var result = [];
+            for (var i = 0; i < originalRowCollection.length; i++) {
+              var item = originalRowCollection[i];
+              if(findValue(newValue, item)){
+                result.push(item);
+              }
+            };
+            $scope.rowCollection = angular.copy(result);
+          }
+          $scope.displayed = $scope.rowCollection.slice(start, start+number);
+          ts.pagination.numberOfPages = 
Math.ceil($scope.rowCollection.length/number);
+        }
+      });
+
+
+      $scope.remove = function remove(row) {
+        var getModelUrl = $config.uri.getModel + '/' +row.name;
+        $http.get(getModelUrl).success(function(data){
+                         $scope.deletedRow = data;
+
+                 });
+        // $scope.deletedRow = row;
+        $scope.deletedBriefRow = row;
+        $('#deleteConfirmation').modal('show');
+
+
+
+      }
+
+      $scope.confirmDelete = function(){
+        var row =   $scope.deletedBriefRow;
+        var deleteModelUrl = $config.uri.deleteModel + '/' + row.name;
+        $http.delete(deleteModelUrl).success(function(){
+
+          var index = $scope.rowCollection.indexOf(row);
+          $scope.rowCollection.splice(index, 1);
+
+          index = $scope.displayed.indexOf(row);
+          $scope.displayed.splice(index, 1);
+
+          $('#deleteConfirmation').modal('hide');
+
+        }).error(function(data, status){
+          toaster.pop('error', 'Error when deleting record', data);
+        });
+      }
+
+
+
+      $scope.edit = function edit() {
+      }
+
+      $scope.$on('$viewContentLoaded', function() {
+        $scope.$emit('initReq');
+      });
+
+
+/*
+       function createRowCollection(){
+         var data = [];
+         for (var j = 0; j < 22; j++) {
+              data.push(createRandomItem());
+          }
+
+          return data;
+       }
+
+       function createRandomItem() {
+         var nameList = ['ViewItem', 'Search', 'BidEvent', 'user_dna', 
'LAST_ITEMS_VIEWED'],
+             systemList = ['Bullseye', 'PDS', 'GPS', 'IDLS', 'Hadoop'],
+             dateList = ['2016-03-10', '2016-03-12', '2016-03-15', 
'2016-03-19', '2016-03-20'],
+             statusList = [0, 1, 2];
+
+           var
+               name = nameList[Math.floor(Math.random() * 5)],
+               system = Math.floor(Math.random() * 7),
+               type = Math.floor(Math.random() * 4),
+               description = 'Only for demo purpose',
+               createDate = dateList[Math.floor(Math.random() * 5)],
+               status = Math.floor(Math.random() * 3);
+
+           return{
+               name: name,
+               system: system,
+               type: type,
+               description: description,
+               createDate: createDate,
+               status:status
+           };
+       }
+*/
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/sidebar-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/sidebar-ctrl.js 
b/griffin-ui/js/controllers/sidebar-ctrl.js
new file mode 100644
index 0000000..b5b6d23
--- /dev/null
+++ b/griffin-ui/js/controllers/sidebar-ctrl.js
@@ -0,0 +1,139 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function(controllers) {
+    'use strict';
+    controllers.controller('SideBarCtrl', ['$scope', '$http', '$config', 
'$filter', '$timeout', '$compile', '$routeParams', '$barkChart', '$rootScope', 
function($scope, $http, $config, $filter, $timeout, $compile, $routeParams, 
$barkChart, $rootScope) {
+
+        var echarts = require('echarts');
+
+        pageInit();
+
+
+        function pageInit() {
+          var url = $config.uri.statistics;
+
+          $http.get(url).success(function(res) {
+              $scope.datasets = res.assets;
+              $scope.metrics = res.metrics;
+              renderDataAssetPie(res.status);
+
+              sideBarList();
+          });
+
+
+        }
+
+        var renderDataAssetPie = function(status) {
+            resizePieChart();
+            $scope.dataAssetPieChart = echarts.init($('#data-asset-pie')[0], 
'dark');
+            
$scope.dataAssetPieChart.setOption($barkChart.getOptionPie(status));
+        }
+
+        $scope.$watch(function(){return $routeParams.sysName;}, 
function(value){
+          console.log('Watched value: ' + value);
+          if(value){
+            sideBarList(value);
+          }else{
+            $scope.briefmetrics = $scope.backup_metrics;
+          }
+        });
+
+        $scope.draw = function(metric, parentIndex, index) {
+
+            var chartId = 'chart' + parentIndex + '-' + index;
+            document.getElementById(chartId).style.width = 
($('.panel-heading').innerWidth()-20)+'px';
+            document.getElementById(chartId).style.height = '200px';
+            var myChart = echarts.init($('#'+chartId).get(0), 'dark');
+            metric.myOption = $barkChart.getOptionSide(metric);
+            myChart.setOption(metric.myOption);
+
+            $('#'+chartId).unbind('click');
+            $('#'+chartId).click(function() {
+              showBig($scope.briefmetrics[parentIndex].metrics[index]);
+            });
+
+        };
+
+        var showBig = function(metric){
+          var metricDetailUrl = $config.uri.metricdetail + '/' + metric.name;
+          $http.get(metricDetailUrl).success(function (data){
+            $rootScope.showBigChart($barkChart.getOptionBig(data));
+          });
+        }
+
+        function sideBarList(sysName){
+          var url_briefmetrics = $config.uri.briefmetrics + (sysName?('/'+ 
sysName):'');
+          $http.get(url_briefmetrics, {cache:true}).success(function(res) {
+              $scope.briefmetrics = res;
+
+              angular.forEach(res, function(sys) {
+                if(sys.metrics && sys.metrics.length > 0){
+                  sys.metrics.sort(function(a, b){
+                    if(a.dqfail == b.dqfail){ //If it's green, sort by 
timestamp
+                      return b.timestamp - a.timestamp;
+                    }else{  //sort by dq
+                      return -(a.dqfail - b.dqfail);
+                    }
+                  });
+                }
+              });
+
+              if(!sysName){
+                $scope.backup_metrics = angular.copy(res);
+              }
+
+              $timeout(function() {
+                resizeSideChart();
+              }, 0);
+          });
+        }
+
+        $(window).resize(function() {
+            console.log('sidebar resize');
+            if(window.innerWidth < 992) {
+              $('#rightbar').css('display', 'none');
+            } else {
+              $('#rightbar').css('display', 'block');
+              resizePieChart();
+              $scope.dataAssetPieChart.resize();
+              resizeSideChart();
+            }
+        });
+
+        function resizeSideChart() {
+            $('#side-bar-metrics').css({
+                height: 
$('#mainContent').height()-$('#side-bar-stats').outerHeight()+70
+            });
+
+            console.log($scope.briefmetrics);
+            angular.forEach($scope.briefmetrics, function(sys, sysIndex) {
+              var sysIndex = sysIndex;
+              angular.forEach(sys.metrics, function(metric, index) {
+                if (!metric.tag) {
+                  $scope.draw(metric, sysIndex, index);
+                }
+              })
+            });
+        }
+
+        function resizePieChart() {
+          $('#data-asset-pie').css({
+              height: $('#data-asset-pie').parent().width(),
+              width: $('#data-asset-pie').parent().width()
+          });
+        }
+    }
+    ]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/subscribemodel-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/subscribemodel-ctrl.js 
b/griffin-ui/js/controllers/subscribemodel-ctrl.js
new file mode 100644
index 0000000..e13bfd1
--- /dev/null
+++ b/griffin-ui/js/controllers/subscribemodel-ctrl.js
@@ -0,0 +1,406 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function(controllers) {
+    'use strict';
+    controllers.controller('SubscribeModelCtrl', ['$scope', '$http', 
'$config', '$location', 'toaster', '$timeout', '$route', '$filter', 
function($scope, $http, $config, $location, toaster, $timeout, $route, $filter) 
{
+        var dbtreeUrl = $config.uri.dbtree;
+        var schemaDefinitionUrl = $config.uri.schemadefinition;
+        var subscribeUrl = $config.uri.getsubscribe;
+        var allModelsUrl = $config.uri.allModels;
+
+        $scope.ruleSystems = $filter('strarr')('modelsystem');
+        $scope.ruleTypes = $filter('strarr')('modeltype');
+
+        $http.get(dbtreeUrl).success(function(data) {
+            var dbList = [];
+            if (data && data.length > 0) {
+                data.forEach(function(db) {
+                    var dbNode = {
+                        name: db.platform,
+                        fullname: db.platform,
+                        l1: true,
+                        children: []
+                    };
+                    dbList.push(dbNode);
+                    if (db.systems && db.systems.length > 0) {
+                        db.systems.forEach(function(system) {
+                            var dsNode = {
+                                name: system.name,
+                                fullname: db.platform + '#' + system.name,
+                                l2: true,
+                                children: []
+                            };
+                            dbNode.children.push(dsNode);
+                            dsNode.parent = dbNode;
+
+
+                            if (system.assets && system.assets.length > 0) {
+                                system.assets.sort(function(a, b){
+                                  return 
(a.name<b.name?-1:(a.name>b.name?1:0));
+                                });
+                                system.assets.forEach(function(schema) {
+                                    var schemaNode = {
+                                        id: schema.id,
+                                        name: schema.name,
+                                        fullname: db.platform + '#' + 
system.name + '#' + schema.name,
+                                        l3: true
+                                    };
+                                    schemaNode.parent = dsNode;
+                                    dsNode.children.push(schemaNode);
+                                });
+                            }
+                        });
+                    }
+
+                });
+            }
+            $scope.dbList = dbList;
+            $scope.dbListTarget = angular.copy(dbList);
+
+            $http.get(subscribeUrl + $scope.ntAccount).success(function(data){
+                $scope.oldSubscription = data;
+                //updateModelsTable();
+                initializeModelsTable();
+                // $scope.changeCB();
+            });
+
+
+
+
+
+        });
+
+        $http.get(allModelsUrl).success(function(data){
+            $scope.allModels = data;
+        });
+
+        var findPlatformIndex = function(pl, subscribes){
+            for (var i = 0; i < subscribes.length; i++) {
+                if(subscribes[i].platform == pl){
+                    return i;
+                }
+            };
+            return -1;
+        };
+
+        var findSystemIndex = function(sys, systems){
+            for (var i = 0; i < systems.length; i++) {
+                if(systems[i].system == sys){
+                    return i;
+                }
+            };
+            return -1;
+        };
+
+        var getSubscribes = function(){
+            var subscribes = [];
+            var checkedList = angular.element('input:checked');
+            angular.forEach(checkedList, function(item){
+                var value = item.value;
+                var res = value.split('#');
+                if(res.length == 2) {
+                    var pl = res[0];
+                    var sys = res[1];
+                    var plIndex = findPlatformIndex(pl, subscribes);
+                    if(plIndex == -1) {
+                        var newPlatform = {
+                            "platform": pl,
+                            "selectAll": false,
+                            "systems": [{
+                                "system": sys,
+                                "selectAll": true,
+                                "dataassets": []
+                            }]
+                        }
+                        subscribes.push(newPlatform);
+                    } else{
+                        var sysIndex = findSystemIndex(sys, 
subscribes[plIndex].systems);
+                        if(sysIndex == -1) {
+                            var newSys = {
+                                "system": sys,
+                                "selectAll": true,
+                                "dataassets": []
+                            };
+                            subscribes[plIndex].systems.push(newSys);
+                        }else{
+                            subscribes[plIndex].systems[sysIndex].selectAll = 
true;
+                        }
+                    }
+                } else if(res.length == 3){
+                    var pl = res[0];
+                    var sys = res[1];
+                    var asset = res[2];
+                    var plIndex = findPlatformIndex(pl, subscribes);
+                    if(plIndex == -1) {
+                        var newPlatform = {
+                            "platform": pl,
+                            "selectAll": false,
+                            "systems":[{
+                                "system": sys,
+                                "selectAll": false,
+                                "dataassets": [asset]
+                            }]
+
+                        };
+                        subscribes.push(newPlatform);
+                    } else{
+                        var sysIndex = findSystemIndex(sys, 
subscribes[plIndex].systems);
+                        if(sysIndex == -1) {
+                            var newSys = {
+                                "system": sys,
+                                "selectAll": false,
+                                "dataassets": [asset]
+                            };
+                            subscribes[plIndex].systems.push(newSys);
+                        }else{
+                            
subscribes[plIndex].systems[sysIndex].dataassets.push(asset);
+                        }
+                    }
+                }
+            })
+            return subscribes;
+        };
+
+        $scope.$on('$viewContentLoaded', function() {
+            $scope.$emit('initReq');
+            resizeWindow();
+        });
+
+        $scope.$on('resizeHandler', function(e) {
+            if ($route.current.$$route.controller == "SubscribeModelCtrl") {
+                resizeWindow();
+            }
+        });
+
+        function resizeWindow() {
+            console.log(window.innerHeight);
+            console.log($('.formStep').offset().top);
+            console.log($('#footerwrap').outerHeight());
+                    $('.formStep').innerHeight(window.innerHeight  -  
$('.formStep').offset().top - $('#footerwrap').outerHeight());
+                    $('fieldset').height(window.innerHeight  -  
$('fieldset').offset().top - $('#footerwrap').outerHeight()- 
$('.btn-container').height() -80);
+                    $('.y-scrollable').css({
+                        'max-height': $('fieldset').height()
+                    });
+
+        }
+
+        $scope.form = {
+            submit: function(form) {
+                var subscribes = angular.copy(getSubscribes());
+                var sid = 
($scope.oldSubscription=="")?null:$scope.oldSubscription._id;
+                var requestData = {
+                    "id": sid,
+                    // "id": $scope.ntAccount,
+                    "ntaccount": $scope.ntAccount,
+                    "subscribes": subscribes
+                };
+                this.data = requestData;
+                // $('#confirm').modal('show');
+                var newsubscribeUrl = $config.uri.newsubscribe;
+                $http.post(newsubscribeUrl, this.data).success(function(data){
+                    $location.path('/mydashboard').replace();
+                }).error(function(data){
+                    console.log("Fail to new subscription.");
+                });
+            },
+            save: function(form) {
+                var newsubscribeUrl = $config.uri.newsubscribe;
+                $http.post(newsubscribeUrl, this.data).success(function(data){
+                    $('#confirm').on('hidden.bs.modal', function(e) {
+                        $('#confirm').off('hidden.bs.modal');
+                        $location.path('/mydashboard').replace();
+                        $scope.$apply();
+                    });
+                    $('#confirm').modal('hide');
+                }).error(function(data){
+                    console.log("Fail to new subscription.");
+                });
+            }
+        };
+
+        var findAssetId = function(assetname, sysname, pfname, dbList){
+            for (var i = 0; i < dbList.length; i++) {
+                var platform = dbList[i];
+                if(platform.name == pfname){
+                    for (var j = 0; j < platform.children.length; j++) {
+                        var sys = platform.children[j];
+                        if(sys.name == sysname){
+                            for (var k = 0; k < sys.children.length; k++) {
+                                var asset = sys.children[k];
+                                if(assetname==asset.name) {
+                                    return asset.id;
+                                }
+                            };
+                        }
+                    };
+                }
+            };
+            return -1;
+        };
+
+          var getModelsInfo = function(assetname, sysname, allModels) {
+            var result = [];
+            angular.forEach(allModels, function(model) {
+                if(model.assetName == assetname
+                    && $scope.ruleSystems[model.system] == sysname) {
+                    var item = {
+                        'systemName': sysname,
+                        'assetName': assetname,
+                        'modelName': model.name,
+                        'modelType': $scope.ruleTypes[model.type],
+                        'desc': model.description
+                    }
+                    result.push(item);
+                }
+            });
+            return result;
+          }
+
+          var initializeModelsTable = function(){
+            if($scope.oldSubscription == undefined || $scope.oldSubscription 
== "" || $scope.oldSubscription.subscribes == undefined){
+                return;
+            }
+            $scope.schemaCollection = [];
+            var subscribes = $scope.oldSubscription.subscribes;
+            angular.forEach(subscribes, function(platform){
+                angular.forEach(platform.systems, function(sys){
+                    angular.forEach(sys.dataassets, function(asset){
+                        var models = getModelsInfo(asset, sys.system, 
$scope.allModels);
+                        $scope.schemaCollection = 
$scope.schemaCollection.concat(models);
+                    })
+                })
+            });
+
+          };
+
+          var updateModelsTable = function(){
+            $scope.schemaCollection = [];
+            var subscribes = angular.copy(getSubscribes());
+            angular.forEach(subscribes, function(platform){
+                angular.forEach(platform.systems, function(sys){
+                    angular.forEach(sys.dataassets, function(asset){
+                        var models = getModelsInfo(asset, sys.system, 
$scope.allModels);
+                        $scope.schemaCollection = 
$scope.schemaCollection.concat(models);
+                    })
+                })
+            });
+
+          };
+
+        $scope.isChecked = function(node) {
+            if($scope.oldSubscription == undefined || $scope.oldSubscription 
== "" || $scope.oldSubscription.subscribes == undefined){
+                return false;
+            } else {
+                var oldSubscribes = $scope.oldSubscription.subscribes;
+                if(node.l2){
+                    for (var i = 0; i < oldSubscribes.length; i++) {
+                        var subscribe = oldSubscribes[i];
+                        if(subscribe.platform == node.parent.name){
+                            for (var j = 0; j < subscribe.systems.length; j++) 
{
+                                var sys = subscribe.systems[j];
+                                if(sys.system == node.name && sys.selectAll){
+                                    return true;
+                                }
+                            };
+                        }
+                    };
+                }else if(node.l3){
+                    for (var i = 0; i < oldSubscribes.length; i++) {
+                        var subscribe = oldSubscribes[i];
+                        if(subscribe.platform == node.parent.parent.name){
+                            for (var j = 0; j < subscribe.systems.length; j++) 
{
+                                var sys = subscribe.systems[j];
+                                if(sys.system == node.parent.name){
+                                    for (var k = 0; k < sys.dataassets.length; 
k++) {
+                                        var asset = sys.dataassets[k];
+                                        if(asset == node.name) {
+                                            return true;
+                                        }
+                                    };
+                                }
+                            };
+                        }
+                    };
+                }
+            }
+            return false;
+        };
+
+        // setTimeout(function() {
+        //     updateModelsTable();
+        // }, 1000);
+
+        $scope.changeCB = function(node, evt) {
+            // $('input[type="checkbox"]').change(function(e) {
+
+                  var checked = $(evt.target).prop("checked"),
+                      container = $(evt.target).parent(),
+                      siblings = container.siblings();
+
+                  container.find('input[type="checkbox"]').prop({
+                    indeterminate: false,
+                    checked: checked
+                  });
+
+
+                   function checkSiblings(el) {
+
+                    var parent = el.parent().parent().parent(),
+                        all = true;
+
+                    el.siblings().each(function() {
+                      return all = 
($(this).children('input[type="checkbox"]').prop("checked") === checked);
+                    });
+
+                    if (all && checked) {
+
+                      parent.children('input[type="checkbox"]').prop({
+                        indeterminate: false,
+                        checked: checked
+                      });
+
+                      checkSiblings(parent);
+
+                    } else if (all && !checked) {
+
+                      
parent.children('input[type="checkbox"]').prop("checked", checked);
+                      
parent.children('input[type="checkbox"]').prop("indeterminate", 
(parent.find('input[type="checkbox"]:checked').length > 0));
+                      checkSiblings(parent);
+
+                    } else {
+
+                      
el.parents("li").children('input[type="checkbox"]').prop({
+                        indeterminate: true,
+                        checked: false
+                      });
+
+                    }
+
+                  };
+
+                  checkSiblings(container);
+
+                  updateModelsTable();
+            //}
+            // setTimeout(function() {
+            //     updateModelsTable();
+            // }, 300);
+            //updateModelsTable();
+        }
+
+
+
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/controllers/viewrule-ctrl.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/controllers/viewrule-ctrl.js 
b/griffin-ui/js/controllers/viewrule-ctrl.js
new file mode 100644
index 0000000..8fa67c5
--- /dev/null
+++ b/griffin-ui/js/controllers/viewrule-ctrl.js
@@ -0,0 +1,87 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (controllers) {
+    'use strict';
+    controllers.controller('ViewRuleCtrl', ['$filter', '$scope', '$http', 
'$config', '$location', 'toaster', '$timeout', '$routeParams', '$barkChart', 
'$route',  function ($filter, $scope, $http, $config, $location, toaster, 
$timeout, $routeParams, $barkChart, $route) {
+
+      var echarts = require('echarts');
+
+      pageInit();
+
+      function pageInit() {
+        $scope.$emit('initReq');
+
+        var getModelUrl = $config.uri.getModel+"/"+$routeParams.modelname;
+        $http.get(getModelUrl).success(function(data){
+          $scope.ruleData = data;
+        }).error(function(data){
+          // errorMessage(0, 'Save model failed, please try again!');
+          toaster.pop('error', data.message);
+        });
+
+        $scope.anTypes = ['', 'History Trend Detection', 'Bollinger Bands 
Detection', 'Deviation Detection'];
+
+        var url= $config.uri.rulemetric+"/"+$routeParams.modelname;
+
+        $http.get(url).success(function(res){
+            $scope.modelresultData = res;
+            if (res.details) {
+              $('#viewrule-chart').height(200);
+              $scope.ruleChart = 
echarts.init(document.getElementById('viewrule-chart'), 'dark');
+              $scope.ruleChart.setOption($barkChart.getOptionSide(res));
+
+            }
+            resizeWindow();
+        }).error(function(data) {
+          resizeWindow();
+          toaster.pop('error', data.message);
+        });
+      }
+
+      $scope.confirmDeploy = function(){
+        var deployModelUrl = $config.uri.enableModel + '/' + 
$scope.ruleData.basic.name;
+        var answer = confirm('Are you sure you want to deploy this model to 
production?')
+
+        if(answer){
+          $http.get(deployModelUrl).success(function(){
+            $scope.ruleData.basic.status = 2;
+            toaster.pop('info', 'Your model has been deployed to prduction!');
+          });
+        }
+
+      }
+
+
+      $scope.$on('resizeHandler', function(e) {
+            if ($route.current.$$route.controller == "ViewRuleCtrl") {
+                resizeWindow();
+            }
+        });
+
+      function resizeWindow(){
+
+            var h1 = $('#viewruleDefinition').height();
+            var h2 = $('#viewTestResult').height();
+            var height = Math.max(h1, h2);
+
+            $('#viewruleDefinition').height(height);
+            $('#viewTestResult').height(height);
+
+            if ($scope.ruleChart) {
+              $scope.ruleChart.resize();
+            }
+      }
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/directives/bigchart.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/directives/bigchart.js 
b/griffin-ui/js/directives/bigchart.js
new file mode 100644
index 0000000..c8e3fc5
--- /dev/null
+++ b/griffin-ui/js/directives/bigchart.js
@@ -0,0 +1,92 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (directives) {
+    'use strict';
+    directives.directive( 'bigChart', ['$compile', '$timeout', function( 
$compile, $timeout ) {
+      return {
+        restrict: 'AE',
+        templateUrl: '/pages/template/bigchart.html',
+        // compile: function(element, attrs){
+        //   return {
+        //     pre: function(scope, element, attrs){
+        //       // $('#bigChartShow').remove();
+        //       console.log('pre');
+        //
+        //     },
+        //     post: function(scope, element, attrs){
+        //       console.log('post');
+        //     }
+        //   };
+        // },
+        // preLink: function( scope, element, attrs ){
+        //   $('#bigChartShow').remove();
+        // },
+        // postLink: function( scope, element, attrs ){
+        //   alert('hello');
+        // // },
+        link: function( scope, element, attrs ) {
+          console.log(scope);
+          var getWidth = function(){
+            return window.innerWidth;
+          }
+          var getHeight = function(){
+            return window.innerHeight;
+          }
+
+        //  $('#bigChartShow').remove();
+          // if($('big-chart')){
+          //   if($('big-chart').length > 1){
+          //     $($('big-chart')[0]).remove();
+          //   }
+          // }
+
+          $timeout(function(){
+            $('#bigChartShow').css({height:getHeight(),
+                                    width: getWidth()
+                                  });
+
+            $(window).resize(function(){
+                $('#bigChartShow').css({height:getHeight(),
+                            width: getWidth()
+                          });
+            });
+          });
+
+          // scope.$watch('chartConfig', function(newValue){
+          //   resizeChart(newValue);
+          // });
+
+          // scope.$on('$routeChangeStart', function(){
+          //   $('#mainWindow').show();
+          //   $('#bigChartContainer').hide();
+          // });
+
+          // function resizeChart(config){
+          //   $timeout(function(){
+          //     config.options.chart.width = getWidth();
+          //     config.options.chart.height = getHeight();
+          //   });
+          // }
+
+          scope.closeBigChart = function(){
+            console.log('close big chart!');
+            $('#bigChartContainer').hide();
+            $('#mainWindow').show();
+
+          }
+        }
+      };
+    }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/directives/index.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/directives/index.js 
b/griffin-ui/js/directives/index.js
new file mode 100644
index 0000000..7bbb0e4
--- /dev/null
+++ b/griffin-ui/js/directives/index.js
@@ -0,0 +1,15 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./treeview', './bigchart'], function () {});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/directives/module.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/directives/module.js 
b/griffin-ui/js/directives/module.js
new file mode 100644
index 0000000..3656955
--- /dev/null
+++ b/griffin-ui/js/directives/module.js
@@ -0,0 +1,18 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+ */
+define(['angular'], function (ng) {
+    'use strict';
+    return ng.module('app.directives', []);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/directives/treeview.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/directives/treeview.js 
b/griffin-ui/js/directives/treeview.js
new file mode 100644
index 0000000..31e89c3
--- /dev/null
+++ b/griffin-ui/js/directives/treeview.js
@@ -0,0 +1,252 @@
+/*
+  The MIT License (MIT)
+
+  Copyright (c) 2013 Steve
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy 
of
+  this software and associated documentation files (the "Software"), to deal in
+  the Software without restriction, including without limitation the rights to
+  use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of
+  the Software, and to permit persons to whom the Software is furnished to do 
so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be included in 
all
+  copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS
+  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS 
OR
+  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
WHETHER
+  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+  Code copy from https://github.com/eu81273/angular.treeview
+*/
+define(['./module'], function (directives) {
+    'use strict';
+    directives.directive( 'treeModel', ['$compile', function( $compile ) {
+      return {
+        restrict: 'A',
+        link: function ( scope, element, attrs ) {
+          //tree id
+          // var treeId = attrs.treeId;
+
+          //tree model
+          var treeModel = attrs.treeModel;
+
+          //node id
+          var nodeId = attrs.nodeId || 'id';
+
+          //node label
+          var nodeLabel = attrs.nodeLabel || 'label';
+
+          //children
+          var nodeChildren = attrs.nodeChildren || 'children';
+
+          //select label function name
+          var labelSelect = attrs.labelSelect || 'selectNodeLabel';
+
+          var l1Icon = attrs.l1Icon || 'fa fa-database',
+              l2Icon = attrs.l2Icon || 'fa fa-table',
+              l3Icon = attrs.l3Icon || 'fa fa-file-text-o';
+
+          //tree template
+          var template =
+            '<ul>' +
+              '<li ng-repeat="node in ' + treeModel + '">' +
+                '<i class="collapsed fa fa-caret-right" ng-show="node.' + 
nodeChildren + '.length && node.collapsed" 
ng-click="selectNodeHead(node)"></i>' +
+                '<i class="expanded fa fa-caret-down" ng-show="node.' + 
nodeChildren + '.length && !node.collapsed" 
ng-click="selectNodeHead(node)"></i>' +
+                '<i class="' + l1Icon + '" ng-show="node.l1"></i>'  +
+                '<i class="' + l2Icon + '" ng-show="node.l2"></i>'  +
+                '<i class="normal '+ l3Icon + '" ng-hide="node.' + 
nodeChildren + '.length"></i> ' +
+                //'<span ng-class="node.selected" 
ng-click="selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
+                '<span ng-class="node.selected" ng-click="' + labelSelect + 
'(node)">{{node.' + nodeLabel + '}}</span>' +
+                // '<div ng-hide="node.collapsed" tree-model="node.' + 
nodeChildren + '" node-id=' + nodeId + ' node-label=' + nodeLabel + ' 
node-children=' + nodeChildren + '></div>' +
+                '<div ng-hide="node.collapsed" tree-model="node.' + 
nodeChildren + '" node-id=' + nodeId + ' node-label=' + nodeLabel + ' 
node-children=' + nodeChildren + ' label-select=' + labelSelect +'></div>' +
+              '</li>' +
+            '</ul>';
+
+
+          //check tree id, tree model
+          // if( treeId && treeModel ) {
+
+            //root node
+            if( attrs.angularTreeview ) {
+
+
+
+              //if node head clicks,
+              scope.selectNodeHead = scope.selectNodeHead || function( 
selectedNode ){
+
+                //Collapse or Expand
+                selectedNode.collapsed = !selectedNode.collapsed;
+              };
+
+              //if node label clicks,
+              scope[labelSelect] = scope[labelSelect] || function( 
selectedNode ){
+
+                //remove highlight from previous node
+                if( scope.currentNode && scope.currentNode.selected ) {
+                  scope.currentNode.selected = undefined;
+                }
+
+                if(selectedNode.children && selectedNode.children.length > 0){
+                  scope.selectNodeHead(selectedNode);
+                }else{
+                  //set highlight to selected node
+                  selectedNode.selected = 'selected';
+                }
+
+                //set currentNode
+                scope.currentNode = selectedNode;
+              };
+            }
+
+
+
+            //Rendering template.
+            element.html('').append( $compile( template )( scope ) );
+          // }
+        }
+      };
+    }]);
+
+    directives.directive( 'treeModelCheck', ['$compile', function( $compile ) {
+      return {
+        restrict: 'A',
+        link: function ( scope, element, attrs ) {
+          //tree id
+          // var treeId = attrs.treeId;
+
+          //tree model
+          var treeModel = attrs.treeModelCheck;
+
+          //node id
+          var nodeId = attrs.nodeId || 'id';
+
+          //node label
+          var nodeLabel = attrs.nodeLabel || 'label';
+
+          //children
+          var nodeChildren = attrs.nodeChildren || 'children';
+
+          //select label function name
+          var labelSelect = attrs.labelSelect || 'selectNodeLabel';
+
+          var l1Icon = attrs.l1Icon || 'fa fa-database',
+              l2Icon = attrs.l2Icon || 'fa fa-table',
+              l3Icon = attrs.l3Icon || 'fa fa-file-text-o';
+
+          //tree template
+          var template =
+            '<ul>' +
+              '<li ng-repeat="node in ' + treeModel + '">' +
+                '<i class="collapsed fa fa-caret-right" ng-show="node.' + 
nodeChildren + '.length && node.collapsed" 
ng-click="selectNodeHead(node)"></i>' +
+                '<i class="expanded fa fa-caret-down" ng-show="node.' + 
nodeChildren + '.length && !node.collapsed" 
ng-click="selectNodeHead(node)"></i>' +
+                '<span class="normal" ng-show="node.l3"></span>' +
+                '<input type="checkbox" ng-checked="isChecked(node)" 
ng-click="changeCB(node, $event)" ng-if="node.l2 || node.l3" 
value="{{node.fullname}}"/>&nbsp;' +
+                '<i class="' + l1Icon + '" ng-show="node.l1"></i>'  +
+                '<i class="' + l2Icon + '" ng-show="node.l2"></i>'  +
+                '<i class="'+ l3Icon + '" ng-hide="node.' + nodeChildren + 
'.length"></i> ' +
+                //'<span ng-class="node.selected" 
ng-click="selectNodeLabel(node)">{{node.' + nodeLabel + '}}</span>' +
+                '<span ng-class="node.selected">{{node.' + nodeLabel + 
'}}</span>' +
+                // '<div ng-hide="node.collapsed" tree-model="node.' + 
nodeChildren + '" node-id=' + nodeId + ' node-label=' + nodeLabel + ' 
node-children=' + nodeChildren + '></div>' +
+                '<div ng-hide="node.collapsed" tree-model-check="node.' + 
nodeChildren + '" node-id=' + nodeId + ' node-label=' + nodeLabel + ' 
node-children=' + nodeChildren + ' label-select=' + labelSelect +'></div>' +
+              '</li>' +
+            '</ul>';
+
+
+          //check tree id, tree model
+          // if( treeId && treeModel ) {
+
+            //root node
+            if( attrs.angularTreeviewcheck ) {
+              // if checkbox clicks,
+              scope.changeCB = scope.changeCB || function( selectedNode){
+                $('input[type="checkbox"]').change(function(e) {
+                  var checked = $(this).prop("checked"),
+                      container = $(this).parent(),
+                      siblings = container.siblings();
+
+                  container.find('input[type="checkbox"]').prop({
+                    indeterminate: false,
+                    checked: checked
+                  });
+
+                  function checkSiblings(el) {
+
+                    var parent = el.parent().parent().parent(),
+                        all = true;
+
+                    el.siblings().each(function() {
+                      return all = 
($(this).children('input[type="checkbox"]').prop("checked") === checked);
+                    });
+
+                    if (all && checked) {
+
+                      parent.children('input[type="checkbox"]').prop({
+                        indeterminate: false,
+                        checked: checked
+                      });
+
+                      checkSiblings(parent);
+
+                    } else if (all && !checked) {
+
+                      
parent.children('input[type="checkbox"]').prop("checked", checked);
+                      
parent.children('input[type="checkbox"]').prop("indeterminate", 
(parent.find('input[type="checkbox"]:checked').length > 0));
+                      checkSiblings(parent);
+
+                    } else {
+
+                      
el.parents("li").children('input[type="checkbox"]').prop({
+                        indeterminate: true,
+                        checked: false
+                      });
+
+                    }
+
+                  }
+
+                  checkSiblings(container);
+                });
+              };
+              //if node head clicks,
+              scope.selectNodeHead = scope.selectNodeHead || function( 
selectedNode ){
+
+                //Collapse or Expand
+                selectedNode.collapsed = !selectedNode.collapsed;
+              };
+
+              //if node label clicks,
+              scope[labelSelect] = scope[labelSelect] || function( 
selectedNode ){
+
+                //remove highlight from previous node
+                if( scope.currentNode && scope.currentNode.selected ) {
+                  scope.currentNode.selected = undefined;
+                }
+
+                if(selectedNode.children && selectedNode.children.length > 0){
+                  scope.selectNodeHead(selectedNode);
+                }else{
+                  //set highlight to selected node
+                  selectedNode.selected = 'selected';
+                }
+
+                //set currentNode
+                scope.currentNode = selectedNode;
+              };
+            }
+
+
+
+            //Rendering template.
+            element.html('').append( $compile( template )( scope ) );
+          // }
+        }
+      };
+    }]);
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/filters/index.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/filters/index.js b/griffin-ui/js/filters/index.js
new file mode 100644
index 0000000..bcd414c
--- /dev/null
+++ b/griffin-ui/js/filters/index.js
@@ -0,0 +1,15 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define([ './strshorten', './strmap'], function () {});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/filters/module.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/filters/module.js b/griffin-ui/js/filters/module.js
new file mode 100644
index 0000000..3b35aeb
--- /dev/null
+++ b/griffin-ui/js/filters/module.js
@@ -0,0 +1,20 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['angular'], function (ng) {
+    'use strict';
+    return ng.module('app.filters', []).config(
+      ['$filterProvider', function($filterProvider){}]
+    );
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/filters/strmap.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/filters/strmap.js b/griffin-ui/js/filters/strmap.js
new file mode 100644
index 0000000..daa8df7
--- /dev/null
+++ b/griffin-ui/js/filters/strmap.js
@@ -0,0 +1,66 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (filters) {
+    'use strict';
+    var constants = {
+      modeltype: ['Accuracy', 'Validity', 'Anomaly Detection', 'Publish 
Metrics'],
+      scheduletype: ['Daily', 'Weekly', 'Monthly', 'Hourly'],
+      modelsystem: ['Bullseye', 'GPS', 'Hadoop', 'PDS', 'IDLS', 'Pulsar', 
'Kafka', 'Sojourner', 'SiteSpeed', 'EDW'],
+      matchfunction: ['LENGTH', 'LOWER', 'UPPER', 'TRIM'],
+      //modelstatus: ['Testing', 'Need Verify', 'Deployed'],
+      modelstatus: ['Initial', 'Validation', 'Production'],
+      vatype: ['Defaut Count', 'Total Count', 'Null Count', 'Unique Count', 
'Duplicate Count', 'Maximum', 'Minimum', 'Mean', 'Median', 'Regular Expression 
Matching', 'Pattern Frequency'],
+      antype: ['Default', 'History Trend Detection', 'Bollinger Bands 
Detection', 'Deviation Detection(Based on MAD)']
+    };
+
+    //get tha value by index from an array
+    filters.filter('strmap', function () {
+        return function (index, array) {
+            var result = index;
+            if(!!array && (array instanceof Array)  && index < array.length){
+              result = array[index];
+            }else if(typeof(array)==='string'){
+              if(constants[array] && index < constants[array].length){
+                result = constants[array][index];
+              }
+            }
+            return result;
+        }
+      });
+
+      //get the index of the value in array
+      filters.filter('stridx', function () {
+          return function (value, array) {
+              var result = -1;
+              if(!!array && (array instanceof Array)  && index < array.length){
+                result = array.indexOf(value);
+              }else if(typeof(array)==='string'){
+                if(constants[array]){
+                  result = constants[array].indexOf(value);
+                }
+              }
+              return result;
+          }
+        });
+
+        //Get the array by name
+        filters.filter('strarr', function () {
+            return function (name) {
+                return constants[name];
+            }
+          });
+
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/filters/strshorten.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/filters/strshorten.js 
b/griffin-ui/js/filters/strshorten.js
new file mode 100644
index 0000000..f4dadf7
--- /dev/null
+++ b/griffin-ui/js/filters/strshorten.js
@@ -0,0 +1,45 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./module'], function (filters) {
+    'use strict';
+
+    // return filters.filter('strings', ['version', function (version) {
+    return filters.filter('strShorten', function () {
+        return function (text) {
+            var str = String(text);
+            var strLength = str.length;
+            var windowWidth = 2000;
+            try{
+              windowWidth = window.innerWidth;
+              console.log('Window Size: ' + windowWidth);
+            }catch(e){
+              console.error(e);
+            }
+
+            if(windowWidth < 1400 && strLength > 10){
+              return str.substring(0, 10) + '...';
+            }else if(windowWidth < 1600 && strLength > 20){
+              return str.substring(0, 20) + '...';
+            }else if(windowWidth < 1800 && strLength > 26){
+              return str.substring(0, 26) + '...';
+            }else if(windowWidth < 2000 && strLength > 30){
+              return str.substring(0, 30) + '...';
+            }else{
+              return str;
+            }
+        }
+      });
+    // }]);
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/main.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/main.js b/griffin-ui/js/main.js
new file mode 100644
index 0000000..8103358
--- /dev/null
+++ b/griffin-ui/js/main.js
@@ -0,0 +1,88 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+
+//Reference: https://www.startersquad.com/blog/angularjs-requirejs/
+
+/*global require*/
+'use strict';
+
+require.config({
+       paths: {
+           'domReady': '../bower_components/domReady/domReady',
+           'angular': '../bower_components/angular/angular',
+                       'angularRoute': 
'../bower_components/angular-route/angular-route',
+
+                       'ngSmartTable': 
'../bower_components/angular-smart-table/dist/smart-table',
+                       'ngAnimate': 
'../bower_components/angular-animate/angular-animate',
+                       'ngToaster': 
'../bower_components/AngularJS-Toaster/toaster',
+                       'ngCookies': 
'../bower_components/angular-cookies/angular-cookies',
+
+           'jquery': '../bower_components/jquery/dist/jquery',
+           'bootstrap': '../bower_components/bootstrap/dist/js/bootstrap',
+           'spin': '../bower_components/spin.js/spin',
+           'angularSpinner': 
'../bower_components/angular-spinner/angular-spinner',
+               'echarts': '../bower_components/echarts/dist/echarts',
+               'echarts-dark': '../bower_components/echarts/theme/dark'
+       },
+       shim: {
+               'angular': {
+                       deps: ['jquery'],
+                       exports: 'angular'
+               },
+               'angularRoute': {
+               deps: ['angular'],
+               exports: 'angularRoute'
+           },
+               'ngSmartTable': {
+                       deps: ['angular'],
+                       exports: 'ngSmartTable'
+               },
+               'ngAnimate': {
+               deps: ['angular'],
+               exports: 'ngAnimate'
+           },
+               'ngToaster': {
+                       deps: ['angular', 'ngAnimate'],
+                       exports: 'ngToaster'
+               },
+               'ngCookies': {
+                       deps: ['angular'],
+                       exports: 'ngCookies'
+               },
+       
+           'jquery': {
+                               exports: 'jquery'
+                       },
+           'bootstrap': {
+             exports: 'bootstrap',
+             deps: ['jquery']
+           },
+           'spin':{
+               exports: 'spin'
+           },
+           'angularSpinner':{
+               exports: 'angularSpinner',
+               deps: ['angular', 'spin']
+           },
+               'echarts': {
+                       exports: 'echarts'
+               },
+               'echarts-dark': {
+                       deps: ['echarts'],
+                       exports: 'echarts-dark'
+               }
+       },
+       deps: ['bs']
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/a8ba6ba9/griffin-ui/js/routes.js
----------------------------------------------------------------------
diff --git a/griffin-ui/js/routes.js b/griffin-ui/js/routes.js
new file mode 100644
index 0000000..099e3ee
--- /dev/null
+++ b/griffin-ui/js/routes.js
@@ -0,0 +1,221 @@
+/*
+       Copyright (c) 2016 eBay Software Foundation.
+       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.
+*/
+define(['./app'], function(app) {
+    'use strict';
+
+    return app.config(['$routeProvider', '$httpProvider', 
function($routeProvider, $httpProvider) {
+
+        $routeProvider.when('/', {
+            redirectTo: '/health'
+        });
+
+        $routeProvider.when('/health', {
+            templateUrl: '/pages/health/health.html',
+            controller: 'HealthCtrl'
+        });
+
+        $routeProvider.when('/rules', {
+            templateUrl: '/pages/rules/rules.html',
+            controller: 'RuleCtrl'
+        });
+
+        $routeProvider.when('/createrule0', {
+            templateUrl: '/pages/rules/createrule0.html',
+            controller: 'CreateRule0Ctrl'
+        });
+
+        $routeProvider.when('/createrule-ac', {
+            templateUrl: '/pages/rules/createrule-ac.html',
+            controller: 'CreateRuleACCtrl'
+        });
+
+        $routeProvider.when('/createrule-va', {
+            templateUrl: '/pages/rules/createrule-va.html',
+            controller: 'CreateRuleVACtrl'
+        });
+
+        $routeProvider.when('/createrule-an', {
+            templateUrl: '/pages/rules/createrule-an.html',
+            controller: 'CreateRuleANCtrl'
+        });
+
+        $routeProvider.when('/createrule-pu', {
+            templateUrl: '/pages/rules/createrule-pu.html',
+            controller: 'CreateRulePUCtrl'
+        });
+
+        $routeProvider.when('/viewrule/:modelname/:modeltype', {
+            templateUrl: '/pages/rules/viewrule.html',
+            controller: 'ViewRuleCtrl'
+        });
+
+        $routeProvider.when('/viewrule/:modelname', {
+            templateUrl: '/pages/rules/viewrule.html',
+            controller: 'ViewRuleCtrl'
+        });
+
+        $routeProvider.when('/metrics', {
+            templateUrl: '/pages/metrics/dashboard.html',
+            controller: 'MetricsCtrl'
+        });
+
+        $routeProvider.when('/metrics/:sysName', {
+            templateUrl: '/pages/metrics/dashboard.html',
+            controller: 'MetricsCtrl'
+        });
+
+        $routeProvider.when('/dataassets', {
+            templateUrl: '/pages/dataassets/dataassets.html',
+            controller: 'DataAssetsCtrl'
+        });
+
+        $routeProvider.when('/dataassets/:assetId', {
+            templateUrl: '/pages/dataassets/editdataasset.html',
+            controller: 'EditDataAssetCtrl'
+        });
+
+        $routeProvider.when('/createdataasset', {
+            templateUrl: '/pages/dataassets/createdataasset.html',
+            controller: 'CreateDataAssetCtrl'
+        });
+
+        $routeProvider.when('/mydashboard', {
+            templateUrl: '/pages/mydashboard/mydashboard.html',
+            controller: 'MyDashboardCtrl'
+        });
+
+        $routeProvider.when('/subscribemodel', {
+            templateUrl: '/pages/mydashboard/subscribemodel.html',
+            controller: 'SubscribeModelCtrl'
+        });
+
+        $routeProvider.when('/undercons', {
+            templateUrl: '/pages/template/undercons.html',
+            controller: null
+        });
+
+        $routeProvider.otherwise({
+            redirectTo: '/'
+        });
+
+        // $routeProvider.otherwise(function(){
+        //     console.log("otherwise");
+        // });
+
+
+        // $locationProvider.html5Mode({
+        //   enabled: true,
+        //   requireBase: false
+        // });
+
+        $httpProvider.interceptors.push(function($q, $location, $rootScope, 
$timeout, $window, $config) {
+            var requestArray = {};
+
+            return {
+                "request": function(config) {
+                    if (isSpinnerRequired($config, config.url)) {
+                        //There's a bug in angular-spinner, the event was sent 
to the component too early while the directive hasn't been compiled completely 
so that the spinner object hasn't be created
+                        //So let's delay 200 ms to browadcast the event
+                        $timeout(function() {
+                            if (!requestArray[config.url])
+                                requestArray[config.url] = 0;
+
+                            if (requestArray[config.url] >= 0) {
+                                $rootScope.$broadcast('us-spinner:spin', 
false);
+                                requestArray[config.url]++;
+                            } else {
+                                requestArray[config.url] = 0;
+                            }
+
+                            console.log(config.url + ": " + 
requestArray[config.url]);
+                        }, 200);
+
+                    }
+                    return config || $q.when(config);
+                },
+                "response": function(response) {
+                    if (isSpinnerRequired($config, response.config.url)) {
+                        $timeout(function() {
+                            if (!requestArray[response.config.url])
+                                requestArray[response.config.url] = 0;
+
+                            $rootScope.$broadcast('us-spinner:stop', false);
+                            requestArray[response.config.url]--;
+
+                            console.log(response.config.url + ": " + 
requestArray[response.config.url]);
+                        }, 0);
+                    }
+                    return response || $q.when(response);
+                },
+
+                "responseError": function(response) {
+
+                    if (isSpinnerRequired($config, response.config.url)) {
+                        $timeout(function() {
+                            if (!requestArray[response.config.url])
+                                requestArray[response.config.url] = 0;
+
+                            $rootScope.$broadcast('us-spinner:stop', false);
+                            requestArray[response.config.url]--;
+
+                            console.log(response.config.url + ": " + 
requestArray[response.config.url]);
+                        }, 0);
+
+                    }
+                    //if(isApiCall(Config, response.config.url)){
+                    if (isSpinnerRequired($config, response.config.url)) {
+                        $rootScope.error = response.status + " " + 
response.statusText;
+                        $rootScope.errorMsg = response.data;
+                        console.error(response.data);
+                        if (response.status == 0 && !response.data) {
+                            $window.alert("The connection to server failed, 
please ensure you've configured proxy to 
https://c2sproxy.vip.ebay.com/wpad.dat. If still fails, please contact 
dl-ebay-lshao-...@ebay.com");
+                            // console.error("status: " + response.status);
+                            // console.error("data: " + response.data);
+                        }
+                        //Disable error handling temporarily
+                        //$location.path("error");
+                    }
+
+                    return $q.reject(response);
+
+                }
+            }
+
+        });
+
+    }]);
+});
+
+function isSpinnerRequired(Config, url){
+    var names = [
+        "dbtree",
+        "getdataasset",
+        "allModels",
+        "getModel",
+        "heatmap",
+        "metricdetail",
+        "dashboard",
+        "getmydashboard",
+        "getsubscribe"
+    ];
+
+    var uriArray = Config.uri;
+    for(var i = 0; i < names.length; i ++){
+        if(url.indexOf(uriArray[names[i]])>=0)
+            return true;
+    }
+
+    return false;
+}

Reply via email to