You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2013/08/08 20:27:14 UTC

[3/3] git commit: AMBARI-2829. Dashboard refactor and unit tests. (onechiporenko via yusaku)

AMBARI-2829. Dashboard refactor and unit tests. (onechiporenko via yusaku)


Project: http://git-wip-us.apache.org/repos/asf/incubator-ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ambari/commit/e81d705b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ambari/tree/e81d705b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ambari/diff/e81d705b

Branch: refs/heads/trunk
Commit: e81d705b778e7d172de89e6cd1d0d2a37b10bda8
Parents: d75875c
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Thu Aug 8 11:25:34 2013 -0700
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Thu Aug 8 11:25:34 2013 -0700

----------------------------------------------------------------------
 ambari-web/app/assets/test/tests.js             |  18 ++
 ambari-web/app/messages.js                      |  15 ++
 ambari-web/app/templates/main/dashboard.hbs     |  16 +-
 .../main/dashboard/edit_widget_popup.hbs        |   2 +-
 .../main/dashboard/widgets/hbase_links.hbs      |   2 +-
 .../main/dashboard/widgets/hdfs_links.hbs       |   2 +-
 .../main/dashboard/widgets/mapreduce_links.hbs  |   4 +-
 ambari-web/app/views.js                         |   5 +
 ambari-web/app/views/main/dashboard.js          |   9 +-
 ambari-web/app/views/main/dashboard/widget.js   |  29 ++--
 .../dashboard/widgets/cluster_metrics_widget.js |  25 +++
 .../main/dashboard/widgets/datanode_live.js     |  64 ++-----
 .../dashboard/widgets/hbase_average_load.js     |  59 ++-----
 .../views/main/dashboard/widgets/hbase_links.js |  27 ++-
 .../main/dashboard/widgets/hbase_master_heap.js |  93 ++--------
 .../dashboard/widgets/hbase_master_uptime.js    | 101 +----------
 .../widgets/hbase_regions_in_transition.js      |  55 ++----
 .../main/dashboard/widgets/hdfs_capacity.js     | 106 +++---------
 .../views/main/dashboard/widgets/hdfs_links.js  |  25 ++-
 .../main/dashboard/widgets/jobtracker_cpu.js    | 104 +++---------
 .../main/dashboard/widgets/jobtracker_heap.js   |  87 ++--------
 .../main/dashboard/widgets/jobtracker_rpc.js    |  61 +------
 .../main/dashboard/widgets/jobtracker_uptime.js | 100 +----------
 .../main/dashboard/widgets/links_widget.js      |  49 ++++++
 .../main/dashboard/widgets/mapreduce_links.js   |  25 ++-
 .../main/dashboard/widgets/mapreduce_slots.js   |  15 +-
 .../views/main/dashboard/widgets/metrics_cpu.js |  10 +-
 .../main/dashboard/widgets/metrics_load.js      |  10 +-
 .../main/dashboard/widgets/metrics_memory.js    |  10 +-
 .../main/dashboard/widgets/metrics_network.js   |  10 +-
 .../main/dashboard/widgets/namenode_cpu.js      | 104 +++---------
 .../main/dashboard/widgets/namenode_heap.js     | 118 ++++---------
 .../main/dashboard/widgets/namenode_rpc.js      |  64 +------
 .../main/dashboard/widgets/namenode_uptime.js   | 101 +----------
 .../dashboard/widgets/node_managers_live.js     |  57 +------
 .../main/dashboard/widgets/pie_chart_widget.js  | 140 +++++++++++++++
 .../dashboard/widgets/resource_manager_heap.js  |  86 ++--------
 .../widgets/resource_manager_uptime.js          |  99 +----------
 .../main/dashboard/widgets/tasktracker_live.js  |  60 +------
 .../views/main/dashboard/widgets/text_widget.js |  66 ++++++++
 .../dashboard/widgets/uptime_text_widget.js     | 149 ++++++++++++++++
 .../views/main/dashboard/widgets/yarn_memory.js |  93 ++--------
 .../test/views/main/dashboard/widget_test.js    |  73 ++++++++
 .../dashboard/widgets/datanode_live_test.js     |  69 ++++++++
 .../widgets/hbase_average_load_test.js          | 103 +++++++++++
 .../widgets/hbase_master_uptime_test.js         |  95 +++++++++++
 .../widgets/hbase_regions_in_transition_test.js | 102 +++++++++++
 .../dashboard/widgets/jobtracker_rpc_test.js    | 107 ++++++++++++
 .../dashboard/widgets/jobtracker_uptime_test.js |  95 +++++++++++
 .../main/dashboard/widgets/links_widget_test.js |  45 +++++
 .../main/dashboard/widgets/namenode_cpu_test.js | 107 ++++++++++++
 .../main/dashboard/widgets/namenode_rpc_test.js | 107 ++++++++++++
 .../dashboard/widgets/namenode_uptime_test.js   |  95 +++++++++++
 .../widgets/node_managers_live_test.js          |  97 +++++++++++
 .../dashboard/widgets/pie_chart_widget_test.js  | 169 +++++++++++++++++++
 .../widgets/resource_manager_uptime_test.js     |  95 +++++++++++
 .../dashboard/widgets/tasktracker_live_test.js  |  69 ++++++++
 .../main/dashboard/widgets/text_widget_test.js  |  84 +++++++++
 .../widgets/uptime_text_widget_test.js          |  90 ++++++++++
 ambari-web/test/views/main/dashboard_test.js    | 122 +++++++++++++
 60 files changed, 2504 insertions(+), 1495 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index aa1e6f2..a3d7947 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -63,6 +63,24 @@ require('test/utils/config_test');
 require('test/utils/string_utils_test');
 require('test/views/common/chart/linear_time_test');
 require('test/views/common/filter_view_test');
+require('test/views/main/dashboard_test');
+require('test/views/main/dashboard/widget_test');
+require('test/views/main/dashboard/widgets/text_widget_test');
+require('test/views/main/dashboard/widgets/uptime_text_widget_test');
+require('test/views/main/dashboard/widgets/node_managers_live_test');
+require('test/views/main/dashboard/widgets/datanode_live_test');
+require('test/views/main/dashboard/widgets/tasktracker_live_test');
+require('test/views/main/dashboard/widgets/hbase_average_load_test');
+require('test/views/main/dashboard/widgets/hbase_regions_in_transition_test');
+require('test/views/main/dashboard/widgets/jobtracker_rpc_test');
+require('test/views/main/dashboard/widgets/namenode_rpc_test');
+require('test/views/main/dashboard/widgets/hbase_master_uptime_test');
+require('test/views/main/dashboard/widgets/jobtracker_uptime_test');
+require('test/views/main/dashboard/widgets/namenode_uptime_test');
+require('test/views/main/dashboard/widgets/resource_manager_uptime_test');
+require('test/views/main/dashboard/widgets/links_widget_test');
+require('test/views/main/dashboard/widgets/pie_chart_widget_test');
+require('test/views/main/dashboard/widgets/namenode_cpu_test');
 require('test/views/common/configs/services_config_test');
 require('test/models/host_test');
 require('test/models/rack_test');
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 266adf6..2836337 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -1142,6 +1142,9 @@ Em.I18n.translations = {
   'charts.heatmap.metrics.MRMemHeapUsed' :'MapReduce JVM Heap Memory Used',
   'charts.heatmap.metrics.YarnMemHeapUsed' :'YARN JVM Heap Memory Used',
   'charts.heatmap.metrics.reducesRunning' :'MapReduce Reduces Running',
+
+  'charts.heatmap.metrics.YarnResourceUsed' :'YARN Resource used %',
+
   'charts.heatmap.metrics.memoryUsed' :'Host Memory Used %',
   'charts.heatmap.metrics.processRun' :'Total Running Processes',
   'charts.heatmap.metrics.YarnResourceUsed' :'YARN Resource used %',
@@ -1207,6 +1210,18 @@ Em.I18n.translations = {
   'dashboard.widgets.NodeManagersLive': 'NodeManagers Live',
   'dashboard.widgets.YARNMemory': 'YARN Memory',
 
+  'dashboard': {
+    'widgets': {
+      'popupHeader': 'Customize Widget',
+      'hintInfo': {
+        'common': 'Edit the percentage thresholds to change the color of current pie chart. <br />Enter two numbers between 0 to {0}',
+        'hint1': 'Edit the percentage of thresholds to change the color of current widget. <br />Assume all components UP is 100, and all DOWN is 0. <br /> So enter two numbers between 0 to {0}',
+        'hint2': 'Edit the thresholds to change the color of current widget.<br /><br />So enter two numbers larger than 0.',
+        'hint3': 'Edit the thresholds to change the color of current widget.<br />The unit is milli-second. <br />So enter two numbers larger than 0. '
+      }
+    }
+  },
+
   'dashboard.services':'Services',
   'dashboard.services.hosts':'Hosts',
   'dashboard.services.uptime':'{0}',

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/templates/main/dashboard.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard.hbs b/ambari-web/app/templates/main/dashboard.hbs
index 6cd35a2..9c27428 100644
--- a/ambari-web/app/templates/main/dashboard.hbs
+++ b/ambari-web/app/templates/main/dashboard.hbs
@@ -88,13 +88,13 @@
                   </button>
                   <ul class="dropdown-menu right-align-dropdown">
                     <li>
-                      <a {{action "resetAllWidgets" target="view"}}>
+                      <a href="#" {{action "resetAllWidgets" target="view"}}>
                         <i class="icon-refresh"></i>
                         {{t dashboard.button.reset}}
                       </a>
                     </li>
                     <li>
-                      <a {{action "switchToClassic" target="view"}}>
+                      <a href="#" {{action "switchToClassic" target="view"}}>
                         <i class="icon-backward"></i>
                         {{t dashboard.button.switch}}
                       </a>
@@ -114,15 +114,9 @@
             <div class="thumbnails row-fluid" id="sortable">
               {{#if view.visibleWidgets.length}}
                 {{#each widgetClass in view.visibleWidgets}}
-                  {{#if widgetClass.isProgressBar}}
-                    <div class="span4p8">
-                      {{view widgetClass }}
-                    </div>
-                  {{else}}
-                    <div class="span2p4">
-                      {{view widgetClass }}
-                    </div>
-                  {{/if}}
+                  <div {{bindAttr class="widgetClass.class"}}>
+                    {{view widgetClass }}
+                  </div>
                 {{/each}}
               {{/if}}
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs b/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
index 201910f..30cc5be 100644
--- a/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
+++ b/ambari-web/app/templates/main/dashboard/edit_widget_popup.hbs
@@ -18,7 +18,7 @@
 <form class="form-horizontal" autocomplete="off">
     <div class="each-row">
         <div class="alert alert-info">
-          {{view.configPropertyObj.hintInfo}}
+          {{{view.configPropertyObj.hintInfo}}}
         </div>
     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/templates/main/dashboard/widgets/hbase_links.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/widgets/hbase_links.hbs b/ambari-web/app/templates/main/dashboard/widgets/hbase_links.hbs
index 309f1aa..ac13928 100644
--- a/ambari-web/app/templates/main/dashboard/widgets/hbase_links.hbs
+++ b/ambari-web/app/templates/main/dashboard/widgets/hbase_links.hbs
@@ -38,7 +38,7 @@
         </tr>
         <!--region servers-->
         <tr>
-            <td><a href="#" {{action filterHosts view.regionServerComponent}}>{{view.model.regionServers.length}} {{t dashboard.services.hbase.regionServers}}</a></td>
+            <td><a href="#" {{action filterHosts view.component}}>{{view.model.regionServers.length}} {{t dashboard.services.hbase.regionServers}}</a></td>
         </tr>
         <!--hbase master Web UI-->
         <tr>

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/templates/main/dashboard/widgets/hdfs_links.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/widgets/hdfs_links.hbs b/ambari-web/app/templates/main/dashboard/widgets/hdfs_links.hbs
index 7f1d88a..edaa684 100644
--- a/ambari-web/app/templates/main/dashboard/widgets/hdfs_links.hbs
+++ b/ambari-web/app/templates/main/dashboard/widgets/hdfs_links.hbs
@@ -36,7 +36,7 @@
         <!--Data Nodes-->
         <tr>
           <td>
-              <a href="#" {{action filterHosts view.dataNodeComponent}}>{{view.model.dataNodes.length}} {{t dashboard.services.hdfs.datanodes}}</a>
+              <a href="#" {{action filterHosts view.component}}>{{view.model.dataNodes.length}} {{t dashboard.services.hdfs.datanodes}}</a>
           </td>
         </tr>
       </table>

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/templates/main/dashboard/widgets/mapreduce_links.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/dashboard/widgets/mapreduce_links.hbs b/ambari-web/app/templates/main/dashboard/widgets/mapreduce_links.hbs
index 33d6547..63ac451 100644
--- a/ambari-web/app/templates/main/dashboard/widgets/mapreduce_links.hbs
+++ b/ambari-web/app/templates/main/dashboard/widgets/mapreduce_links.hbs
@@ -31,11 +31,11 @@
         </tr>
         <!--taskTrackers-->
         <tr>
-          <td><a href="#" {{action filterHosts view.taskTrackerComponent}}>{{view.model.taskTrackers.length}} {{t dashboard.services.mapreduce.taskTrackers}}</a></td>
+          <td><a href="#" {{action filterHosts view.component}}>{{view.model.taskTrackers.length}} {{t dashboard.services.mapreduce.taskTrackers}}</a></td>
         </tr>
         <!--jobTracker Web UI-->
         <tr>
-          <td><a {{bindAttr href="view.jobTrackerWebUrl"}} target="_blank">{{t services.service.summary.jobTrackerWebUI}}</a></td>
+          <td><a {{bindAttr href="view.webUrl"}} target="_blank">{{t services.service.summary.jobTrackerWebUI}}</a></td>
         </tr>
       </table>
     </div>

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index cb804c3..4f7bd1a 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -99,6 +99,11 @@ require('views/main/dashboard/cluster_metrics/memory');
 require('views/main/dashboard/cluster_metrics/network');
 
 require('views/main/dashboard/widget');
+require('views/main/dashboard/widgets/text_widget');
+require('views/main/dashboard/widgets/uptime_text_widget');
+require('views/main/dashboard/widgets/links_widget');
+require('views/main/dashboard/widgets/pie_chart_widget');
+require('views/main/dashboard/widgets/cluster_metrics_widget');
 require('views/main/dashboard/widgets/namenode_heap');
 require('views/main/dashboard/widgets/namenode_cpu');
 require('views/main/dashboard/widgets/hdfs_capacity');

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard.js b/ambari-web/app/views/main/dashboard.js
index 8e9da3a..a3953e6 100644
--- a/ambari-web/app/views/main/dashboard.js
+++ b/ambari-web/app/views/main/dashboard.js
@@ -125,8 +125,8 @@ App.MainDashboardView = Em.View.extend({
       }, this);
     }
     var obj = this.get('initPrefObject');
-    obj.visible = visibleFull;
-    obj.hidden = hiddenFull;
+    obj.set('visible', visibleFull);
+    obj.set('hidden', hiddenFull);
   },
   
   hdfs_model: null,
@@ -491,10 +491,7 @@ App.MainDashboardView = Em.View.extend({
         },
         templateName: require('templates/main/dashboard/alert_notification_popup')
       }),
-      primary: 'Close',
-      onPrimary: function() {
-        this.hide();
-      },
+      primary: Em.I18n.t('common.close'),
       secondary : null,
       didInsertElement: function () {
         this.$().find('.modal-footer').addClass('align-center');

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widget.js b/ambari-web/app/views/main/dashboard/widget.js
index 06d8920..2b3828c 100644
--- a/ambari-web/app/views/main/dashboard/widget.js
+++ b/ambari-web/app/views/main/dashboard/widget.js
@@ -33,11 +33,11 @@ App.DashboardWidgetView = Em.View.extend({
     } else if (this.get('model_type') == 'yarn') {
       return this.get('parentView').get('yarn_model');
     }
-  }.property(''), //data bind from parent view
+  }.property(), //data bind from parent view
 
   id: null, // id 1-10 used to identify
   viewID: function(){ // used by re-sort
-    return 'widget-' + this.id;
+    return 'widget-' + this.get('id');
   }.property('id'),  //html id bind to view-class: widget-(1)
   attributeBindings: ['viewID'],
 
@@ -64,12 +64,12 @@ App.DashboardWidgetView = Em.View.extend({
       //update view on dashboard
       var objClass = parent.widgetsMapper(this.id);
       parent.get('visibleWidgets').removeObject(objClass);
-      parent.get('hiddenWidgets').pushObject(Em.Object.create({displayName: this.title, id: this.id, checked: false}));
+      parent.get('hiddenWidgets').pushObject(Em.Object.create({displayName: this.get('title'), id: this.get('id'), checked: false}));
     } else {
       //reconstruct new persist value then post in persist
       parent.getUserPref(parent.get('persistKey'));
       var oldValue = parent.get('currentPrefObject');
-      var deletedId = this.id;
+      var deletedId = this.get('id');
       var newValue = Em.Object.create({
         dashboardVersion: oldValue.dashboardVersion,
         visible: [],
@@ -81,7 +81,7 @@ App.DashboardWidgetView = Em.View.extend({
           newValue.visible.push(oldValue.visible[i]);
         }
       }
-      newValue.hidden.push([deletedId, this.title]);
+      newValue.hidden.push([deletedId, this.get('title')]);
       parent.postUserPref(parent.get('persistKey'), newValue);
       parent.translateToReal(newValue);
     }
@@ -93,8 +93,7 @@ App.DashboardWidgetView = Em.View.extend({
     var configObj = Ember.Object.create({
       thresh1: self.get('thresh1') + '',
       thresh2: self.get('thresh2') + '',
-      hintInfo: 'Edit the percentage thresholds to change the color of current pie chart. ' + ' '+
-        ' Enter two numbers between 0 to ' + max_tmp,
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.common').format(max_tmp),
       isThresh1Error: false,
       isThresh2Error: false,
       errorMessage1: "",
@@ -143,7 +142,7 @@ App.DashboardWidgetView = Em.View.extend({
 
     var browserVerion = this.getInternetExplorerVersion();
     App.ModalPopup.show({
-      header: 'Customize Widget',
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget' ],
       bodyClass: Ember.View.extend({
         templateName: require('templates/main/dashboard/edit_widget_popup'),
@@ -161,17 +160,13 @@ App.DashboardWidgetView = Em.View.extend({
             var parent = self.get('parentView');
             parent.getUserPref(parent.get('persistKey'));
             var oldValue = parent.get('currentPrefObject');
-            oldValue.threshold[parseInt(self.id)] = [configObj.get('thresh1'), configObj.get('thresh2')];
+            oldValue.threshold[parseInt(self.get('id'))] = [configObj.get('thresh1'), configObj.get('thresh2')];
             parent.postUserPref(parent.get('persistKey'), oldValue);
           }
 
           this.hide();
         }
       },
-      secondary : Em.I18n.t('common.cancel'),
-      onSecondary: function () {
-        this.hide();
-      },
 
       didInsertElement: function () {
         var handlers = [configObj.get('thresh1'), configObj.get('thresh2')];
@@ -198,7 +193,7 @@ App.DashboardWidgetView = Em.View.extend({
             }
           });
 
-          function updateColors (handlers) {
+          function updateColors(handlers) {
             var colorstops = colors[0] + ", "; // start with the first color
             for (var i = 0; i < handlers.length; i++) {
               colorstops += colors[i] + " " + handlers[i]*100/max_tmp + "%,";
@@ -255,8 +250,12 @@ App.DashboardWidgetView = Em.View.extend({
     } else if (lineNum == 5) {
       return "simple-text-hidden-five-line";
     }
-  }.property('this.hiddenInfo.length')
+    return '';
+  }.property('hiddenInfo.length')
 
 });
 
 
+App.DashboardWidgetView.reopenClass({
+  class: 'span2p4'
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js b/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
new file mode 100644
index 0000000..d6b2db7
--- /dev/null
+++ b/ambari-web/app/views/main/dashboard/widgets/cluster_metrics_widget.js
@@ -0,0 +1,25 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+var App = require('app');
+
+App.ClusterMetricsDashboardWidgetView = App.DashboardWidgetView.extend({
+
+  templateName: require('templates/main/dashboard/widgets/cluster_metrics')
+
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/datanode_live.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/datanode_live.js b/ambari-web/app/views/main/dashboard/widgets/datanode_live.js
index 1453712..962b47f 100644
--- a/ambari-web/app/views/main/dashboard/widgets/datanode_live.js
+++ b/ambari-web/app/views/main/dashboard/widgets/datanode_live.js
@@ -18,9 +18,8 @@
 
 var App = require('app');
 
-App.DataNodeUpView = App.DashboardWidgetView.extend({
+App.DataNodeUpView = App.TextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/simple_text'),
   title: Em.I18n.t('dashboard.widgets.DataNodeUp'),
   id: '4',
 
@@ -32,31 +31,14 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
   hiddenInfo: function () {
     var result = [];
     result.pushObject( App.HostComponent.find().filterProperty('componentName', 'DATANODE').filterProperty("workStatus","STARTED").length
-      + ' ' + this.t('dashboard.services.hdfs.nodes.live'));
+      + ' ' + Em.I18n.t('dashboard.services.hdfs.nodes.live'));
     result.pushObject( App.HostComponent.find().filterProperty('componentName', 'DATANODE').filterProperty("workStatus","INSTALLED").length
-      + ' ' + this.t('dashboard.services.hdfs.nodes.dead'));
-    result.pushObject(this.get('model.decommissionDataNodes.length')+ ' ' + this.t('dashboard.services.hdfs.nodes.decom'));
+      + ' ' + Em.I18n.t('dashboard.services.hdfs.nodes.dead'));
+    result.pushObject(this.get('model.decommissionDataNodes.length')+ ' ' + Em.I18n.t('dashboard.services.hdfs.nodes.decom'));
     return result;
   }.property('model', 'model.decommissionDataNodes.length'),
   hiddenInfoClass: "hidden-info-three-line",
 
-  classNameBindings: ['isRed', 'isOrange', 'isGreen'],
-  isRed: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') <= thresh1? true: false;
-  }.property('data','thresh1','thresh2'),
-  isOrange: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return (this.get('data') <= thresh2 && this.get('data') > thresh1 )? true: false;
-  }.property('data','thresh1','thresh2'),
-  isGreen: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') > thresh2? true: false;
-  }.property('data','thresh1','thresh2'),
-
   thresh1: 40,
   thresh2: 70,
   maxValue: 100,
@@ -75,9 +57,7 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
     var configObj = Ember.Object.create({
       thresh1: parent.get('thresh1') + '',
       thresh2: parent.get('thresh2') + '',
-      hintInfo: 'Edit the percentage of thresholds to change the color of current widget. ' +
-        ' Assume all data nodes UP is 100, and all DOWN is 0. '+
-        ' So enter two numbers between 0 to ' + max_tmp,
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.hint1').format(max_tmp),
       isThresh1Error: false,
       isThresh2Error: false,
       errorMessage1: "",
@@ -126,7 +106,7 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
 
     var browserVerion = this.getInternetExplorerVersion();
     App.ModalPopup.show({
-      header: 'Customize Widget',
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget'],
       bodyClass: Ember.View.extend({
         templateName: require('templates/main/dashboard/edit_widget_popup'),
@@ -148,10 +128,6 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
           this.hide();
         }
       },
-      secondary : Em.I18n.t('common.cancel'),
-      onSecondary: function () {
-        this.hide();
-      },
 
       didInsertElement: function () {
         var handlers = [configObj.get('thresh1'), configObj.get('thresh2')];
@@ -166,36 +142,17 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
             max: max_tmp,
             values: handlers,
             create: function (event, ui) {
-              updateColors(handlers);
+              parent.updateColors(handlers, colors);
             },
             slide: function (event, ui) {
-              updateColors(ui.values);
+              parent.updateColors(ui.values, colors);
               configObj.set('thresh1', ui.values[0] + '');
               configObj.set('thresh2', ui.values[1] + '');
             },
             change: function (event, ui) {
-              updateColors(ui.values);
+              parent.updateColors(ui.values, colors);
             }
           });
-
-          function updateColors(handlers) {
-            var colorstops = colors[0] + ", "; // start with the first color
-            for (var i = 0; i < handlers.length; i++) {
-              colorstops += colors[i] + " " + handlers[i] + "%,";
-              colorstops += colors[i+1] + " " + handlers[i] + "%,";
-            }
-            // end with the last color
-            colorstops += colors[colors.length - 1];
-            var css1 = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
-            $('#slider-range').css('background-image', css1);
-            var css2 = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
-            $('#slider-range').css('background-image', css2);
-            //$('#slider-range').css('filter', 'progid:DXImageTransform.Microsoft.gradient( startColorStr= ' + colors[0] + ', endColorStr= ' + colors[2] +',  GradientType=1 )' ); // IE 10-
-            var css3 = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
-            $('#slider-range').css('background-image', css3);
-
-            $('#slider-range .ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the  original ranger color
-          }
         } else {
           configObj.set('isIE9', true);
           configObj.set('isGreenOrangeRed', false);
@@ -203,5 +160,4 @@ App.DataNodeUpView = App.DashboardWidgetView.extend({
       }
     });
   }
-
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hbase_average_load.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_average_load.js b/ambari-web/app/views/main/dashboard/widgets/hbase_average_load.js
index 795e417..b02c420 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_average_load.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_average_load.js
@@ -18,41 +18,27 @@
 
 var App = require('app');
 
-App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
+App.HBaseAverageLoadView = App.TextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/simple_text'),
   title: Em.I18n.t('dashboard.widgets.HBaseAverageLoad'),
   id: '21',
 
-  isPieChart: false,
-  isText: true,
-  isProgressBar: false,
   model_type: 'hbase',
   hiddenInfo: function () {
     var avgLoad = this.get('model.averageLoad');
     if (avgLoad == null) {
-      avgLoad = this.t('services.service.summary.notAvailable');
+      avgLoad = Em.I18n.t('services.service.summary.notAvailable');
     }
     var result = [];
-    result.pushObject(this.t('dashboard.services.hbase.averageLoadPerServer').format(avgLoad));
+    result.pushObject(Em.I18n.t('dashboard.services.hbase.averageLoadPerServer').format(avgLoad));
     return result;
   }.property("model.averageLoad"),
 
-  classNameBindings: ['isRed', 'isOrange', 'isGreen', 'isNA'],
   isGreen: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') <= thresh1? true: false;
-  }.property('data','thresh1','thresh2'),
-  isOrange: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return (this.get('data') <= thresh2 && this.get('data') > thresh1 )? true: false;
+    return this.get('data') <= this.get('thresh1');
   }.property('data','thresh1','thresh2'),
   isRed: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') > thresh2? true: false;
+    return this.get('data') > this.get('thresh2');
   }.property('data','thresh1','thresh2'),
   isNA: function (){
     return this.get('data') === null || isNaN(this.get('data'));
@@ -70,7 +56,7 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
     if(this.get('data') || this.get('data') == 0){
       return this.get('data') + "";
     }else{
-      return this.t('services.service.summary.notAvailable');
+      return Em.I18n.t('services.service.summary.notAvailable');
     }
   }.property('model.averageLoad'),
 
@@ -79,9 +65,7 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
     var configObj = Ember.Object.create({
       thresh1: parent.get('thresh1') + '',
       thresh2: parent.get('thresh2') + '',
-      hintInfo: 'Edit the thresholds to change the color of current widget. ' +
-
-        ' So enter two numbers larger than 0. ',
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.hint2'),
       isThresh1Error: false,
       isThresh2Error: false,
       errorMessage1: "",
@@ -125,7 +109,7 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
 
     var browserVerion = this.getInternetExplorerVersion();
     App.ModalPopup.show( {
-      header: 'Customize Widget',
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget'],
       bodyClass: Ember.View.extend({
         templateName: require('templates/main/dashboard/edit_widget_popup'),
@@ -149,10 +133,6 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
           this.hide();
         }
       },
-      secondary : Em.I18n.t('common.cancel'),
-      onSecondary: function() {
-        this.hide();
-      },
 
       didInsertElement: function () {
         var colors = ['#95A800', '#FF8E00', '#B80000']; //color green, orange ,red
@@ -168,28 +148,9 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
             max: 100,
             values: handlers,
             create: function (event, ui) {
-              updateColors(handlers);
+              parent.updateColors(handlers, colors);
             }
           });
-
-          function updateColors(handlers) {
-            var colorstops = colors[0] + ", "; // start with the first color
-            for (var i = 0; i < handlers.length; i++) {
-              colorstops += colors[i] + " " + handlers[i] + "%,";
-              colorstops += colors[i+1] + " " + handlers[i] + "%,";
-            }
-            // end with the last color
-            colorstops += colors[colors.length - 1];
-            var css1 = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
-            $('#slider-range').css('background-image', css1);
-            var css2 = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
-            $('#slider-range').css('background-image', css2);
-            //$('#slider-range').css('filter', 'progid:DXImageTransform.Microsoft.gradient( startColorStr= ' + colors[0] + ', endColorStr= ' + colors[2] +',  GradientType=1 )' ); // IE 10-
-            var css3 = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
-            $('#slider-range').css('background-image', css3);
-
-            $('#slider-range .ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the  original ranger color
-          }
         } else {
           configObj.set('isIE9', true);
           configObj.set('isGreenOrangeRed', true);
@@ -198,4 +159,4 @@ App.HBaseAverageLoadView = App.DashboardWidgetView.extend({
     });
   }
 
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_links.js b/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
index 1bbe533..bbac1ac 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_links.js
@@ -18,18 +18,18 @@
 
 var App = require('app');
 
-App.HBaseLinksView = App.DashboardWidgetView.extend({
+App.HBaseLinksView = App.LinkDashboardWidgetView.extend({
 
   templateName: require('templates/main/dashboard/widgets/hbase_links'),
   title: Em.I18n.t('dashboard.widgets.HBaseLinks'),
   id: '19',
 
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-  isLinks: true,
   model_type: 'hbase',
 
+  port: '60010',
+
+  componentName: 'HBASE_REGIONSERVER',
+
   /**
    * All master components
    */
@@ -70,18 +70,15 @@ App.HBaseLinksView = App.DashboardWidgetView.extend({
     }
   }.property('activeMaster'),
 
-  regionServerComponent: function () {
-    return App.HostComponent.find().findProperty('componentName', 'HBASE_REGIONSERVER');
-  }.property(),
-
   hbaseMasterWebUrl: function () {
     if (this.get('activeMaster.host') && this.get('activeMaster.host').get('publicHostName')) {
-      return "http://" + this.get('activeMaster.host').get('publicHostName') + ":60010";
+      return "http://" + this.get('activeMaster.host').get('publicHostName') + ':' + this.get('port');
     }
-  }.property('activeMaster')
+    return '';
+  }.property('activeMaster'),
 
-})
+  calcWebUrl: function() {
+    return '';
+  }
 
-App.HBaseLinksView.reopenClass({
-  isLinks: true
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hbase_master_heap.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_master_heap.js b/ambari-web/app/views/main/dashboard/widgets/hbase_master_heap.js
index da48f7f..b9645ee 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_master_heap.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_master_heap.js
@@ -19,17 +19,15 @@
 var App = require('app');
 var numberUtils = require('utils/number_utils');
 
-App.HBaseMasterHeapPieChartView = App.DashboardWidgetView.extend({
+App.HBaseMasterHeapPieChartView = App.PieChartDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/pie_chart'),
   title: Em.I18n.t('dashboard.widgets.HBaseMasterHeap'),
   id: '20',
 
-  isPieChart: true,
-  isText: false,
-  isProgressBar: false,
   model_type: 'hbase',
 
+  modelFieldMax: 'heapMemoryMax',
+  modelFieldUsed: 'heapMemoryUsed',
   hiddenInfo: function () {
     var heapUsed = this.get('model').get('heapMemoryUsed');
     var heapMax = this.get('model').get('heapMemoryMax');
@@ -40,78 +38,17 @@ App.HBaseMasterHeapPieChartView = App.DashboardWidgetView.extend({
     return result;
   }.property('model.heapMemoryUsed', 'model.heapMemoryMax'),
 
-  thresh1: null,
-  thresh2: null,
-  maxValue: 100,
-
-  isPieExist: function () {
-    var total = this.get('model.heapMemoryMax') * 1000000;
-    return total > 0 ;
-  }.property('model.heapMemoryMax'),
-
-  content: App.ChartPieView.extend({
-
-    model: null,  //data bind here
-    id: 'widget-hbase-heap', // html id
-    stroke: '#D6DDDF', //light grey
-    thresh1: null, //bind from parent
-    thresh2: null,
-    innerR: 25,
-
-    existCenterText: true,
-    centerTextColor: function () {
-      return this.get('contentColor');
-    }.property('contentColor'),
-
-    palette: new Rickshaw.Color.Palette({
-      scheme: [ '#FFFFFF', '#D6DDDF'].reverse()
-    }),
-
-    data: function () {
-      var heapUsed = this.get('model').get('heapMemoryUsed');
-      var heapMax = this.get('model').get('heapMemoryMax');
-      var percent = heapMax > 0 ? (100 * heapUsed / heapMax).toFixed() : 0;
-      return [percent, 100-percent];
-    }.property('model.heapMemoryUsed', 'model.heapMemoryMax'),
-
-    contentColor: function () {
-      var used = parseFloat(this.get('data')[0]);
-      var thresh1 = parseFloat(this.get('thresh1'));
-      var thresh2 = parseFloat(this.get('thresh2'));
-      var color_green = '#95A800';
-      var color_red = '#B80000';
-      var color_orange = '#FF8E00';
-      if (used <= thresh1) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_green  ].reverse()
-        }))
-        return color_green;
-      } else if (used <= thresh2) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_orange  ].reverse()
-        }))
-        return color_orange;
-      } else {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_red  ].reverse()
-        }))
-        return color_red;
-      }
-    }.property('data', 'this.thresh1', 'this.thresh2'),
-
-    // refresh text and color when data in model changed
-    refreshSvg: function () {
-      // remove old svg
-      var old_svg =  $("#" + this.id);
-      if(old_svg){
-        old_svg.remove();
-      }
-      // draw new svg
-      this.appendSvg();
-    }.observes('this.data', 'this.thresh1', 'this.thresh2')
-
-  })
-
-})
+  widgetHtmlId: 'widget-hbase-heap',
 
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  },
 
+  calcDataForPieChart: function() {
+    var used = this.get('model').get(this.get('modelFieldUsed'));
+    var total = this.get('model').get(this.get('modelFieldMax'));
+    var percent = total > 0 ? ((used)*100 / total).toFixed() : 0;
+    return [ percent, 100 - percent];
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hbase_master_uptime.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_master_uptime.js b/ambari-web/app/views/main/dashboard/widgets/hbase_master_uptime.js
index 3ced6ec..c6e9b67 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_master_uptime.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_master_uptime.js
@@ -17,107 +17,20 @@
  */
 
 var App = require('app');
-var date = require('utils/date');
 
-App.HBaseMasterUptimeView = App.DashboardWidgetView.extend({
+App.HBaseMasterUptimeView = App.UptimeTextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/uptime'),
   title: Em.I18n.t('dashboard.widgets.HBaseMasterUptime'),
   id: '23',
 
-  isPieChart: false,
-  isText: true,
-  isProgressBar: false,
   model_type: 'hbase',
-  hiddenInfo: [],
-  hiddenInfoClass: "hidden-info-three-line",
 
-  classNameBindings: ['isRed', 'isOrange', 'isGreen', 'isNA'],
-  isGreen: function () {
-    return this.get('data') != null;
-  }.property('data'),
-  isOrange: function () {
-    return false;
-  }.property('data'),
-  isRed: function () {
-    return false;
-  }.property('data'),
-  isNA: function () {
-    return this.get('data') == null;
-  }.property('data'),
+  component: 'Hbase Master',
+  modelField: 'masterStartTime',
 
-  thresh1: 5,
-  thresh2: 10,
-  maxValue: 'infinity',
-
-  data: function () {
-    var uptime = this.get('model.masterStartTime');
-    if (uptime && uptime > 0) {
-      var uptimeString = this.timeConverter(uptime);
-      var diff = (new Date()).getTime() - uptime;
-      if (diff < 0) {
-        diff = 0;
-      }
-      var formatted = date.timingFormat(diff); //17.67 days
-      var timeUnit = null;
-      switch (formatted.split(" ")[1]) {
-        case 'secs':
-          timeUnit = 's';
-          break;
-        case 'hours':
-          timeUnit = 'hr';
-          break;
-        case 'days':
-          timeUnit = 'd';
-          break;
-        case 'mins':
-          timeUnit = 'min';
-          break;
-        default:
-          timeUnit = formatted.split(" ")[1];
-      }
-      this.set('timeUnit', timeUnit);
-      this.set('hiddenInfo', []);
-      this.get('hiddenInfo').pushObject(formatted);
-      this.get('hiddenInfo').pushObject(uptimeString[0]);
-      this.get('hiddenInfo').pushObject(uptimeString[1]);
-      return parseFloat(formatted.split(" ")[0]);
-    }
-    this.set('hiddenInfo', []);
-    this.set('hiddenInfo', ['Hbase Master','Not Running']);
-    return null;
-  }.property('model.masterStartTime'),
-
-  timeUnit: null,
-
-  content: function () {
-    var data = this.get('data');
-    if (data) {
-      return data.toFixed(1) + ' '+ this.get('timeUnit');
-    } else {
-      return this.t('services.service.summary.notAvailable');
-    }
-  }.property('model.masterStartTime'),
-
-  timeConverter: function (timestamp){
-    var origin = new Date(timestamp);
-    origin = origin.toString();
-    var result = [];
-    var start = origin.indexOf('GMT');
-    if (start == -1) { // ie
-      var arr = origin.split(" ");
-      result.pushObject(arr[0] + " " + arr[1] + " " + arr[2] + " " + arr[3]);
-      var second = '';
-      for (var i = 4; i < arr.length; i++) {
-        second = second + " " + arr[i];
-      }
-      result.pushObject(second);
-    } else { // other browsers
-      var end = origin.indexOf(" ", start);
-      result.pushObject(origin.slice(0, start-10));
-      result.pushObject(origin.slice(start-9));
-    }
-    return result;
+  didInsertElement: function() {
+    this._super();
+    this.calc();
   }
 
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hbase_regions_in_transition.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hbase_regions_in_transition.js b/ambari-web/app/views/main/dashboard/widgets/hbase_regions_in_transition.js
index d583fc7..d93f9e7 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hbase_regions_in_transition.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hbase_regions_in_transition.js
@@ -18,15 +18,11 @@
 
 var App = require('app');
 
-App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
+App.HBaseRegionsInTransitionView = App.TextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/simple_text'),
   title: Em.I18n.t('dashboard.widgets.HBaseRegionsInTransition'),
   id: '22',
 
-  isPieChart: false,
-  isText: true,
-  isProgressBar: false,
   model_type: 'hbase',
   hiddenInfo: function () {
     var result = [];
@@ -37,20 +33,14 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
 
   classNameBindings: ['isRed', 'isOrange', 'isGreen', 'isNA'],
   isGreen: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') <= thresh1? true: false;
-  }.property('data','thresh1','thresh2'),
+    return this.get('data') <= this.get('thresh1');
+  }.property('data','thresh1'),
   isOrange: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return (this.get('data') <= thresh2 && this.get('data') > thresh1 )? true: false;
+    return (this.get('data') <= this.get('thresh2') && this.get('data') > this.get('thresh1') );
   }.property('data','thresh1','thresh2'),
   isRed: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') > thresh2? true: false;
-  }.property('data','thresh1','thresh2'),
+    return this.get('data') > this.get('thresh2');
+  }.property('data','thresh2'),
   isNA: function () {
     return this.get('data') === null;
   }.property('data'),
@@ -72,9 +62,7 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
     var configObj = Ember.Object.create({
       thresh1: parent.get('thresh1') + '',
       thresh2: parent.get('thresh2') + '',
-      hintInfo: 'Edit the thresholds to change the color of current widget. ' +
-
-        ' So enter two numbers larger than 0. ',
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.hint2'),
       isThresh1Error: false,
       isThresh2Error: false,
       errorMessage1: "",
@@ -117,7 +105,7 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
 
     var browserVerion = this.getInternetExplorerVersion();
     App.ModalPopup.show({
-      header: 'Customize Widget',
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget'],
       bodyClass: Ember.View.extend({
         templateName: require('templates/main/dashboard/edit_widget_popup'),
@@ -141,10 +129,6 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
           this.hide();
         }
       },
-      secondary : Em.I18n.t('common.cancel'),
-      onSecondary: function () {
-        this.hide();
-      },
 
       didInsertElement: function () {
         var colors = ['#95A800', '#FF8E00', '#B80000']; //color green, orange ,red
@@ -160,28 +144,9 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
             max: 100,
             values: handlers,
             create: function (event, ui) {
-              updateColors(handlers);
+              parent.updateColors(handlers, colors);
             }
           });
-
-          function updateColors (handlers) {
-            var colorstops = colors[0] + ", "; // start with the first color
-            for (var i = 0; i < handlers.length; i++) {
-              colorstops += colors[i] + " " + handlers[i] + "%,";
-              colorstops += colors[i+1] + " " + handlers[i] + "%,";
-            }
-            // end with the last color
-            colorstops += colors[colors.length - 1];
-            var css1 = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
-            $('#slider-range').css('background-image', css1);
-            var css2 = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
-            $('#slider-range').css('background-image', css2);
-            //$('#slider-range').css('filter', 'progid:DXImageTransform.Microsoft.gradient( startColorStr= ' + colors[0] + ', endColorStr= ' + colors[2] +',  GradientType=1 )' ); // IE 10-
-            var css3 = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
-            $('#slider-range').css('background-image', css3);
-
-            $('#slider-range .ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the  original ranger color
-          }
         } else {
           configObj.set('isIE9', true);
           configObj.set('isGreenOrangeRed', true);
@@ -190,4 +155,4 @@ App.HBaseRegionsInTransitionView = App.DashboardWidgetView.extend({
     });
   }
 
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hdfs_capacity.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hdfs_capacity.js b/ambari-web/app/views/main/dashboard/widgets/hdfs_capacity.js
index 9a27d01..9b31557 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hdfs_capacity.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hdfs_capacity.js
@@ -19,19 +19,30 @@
 var App = require('app');
 var numberUtils = require('utils/number_utils');
 
-App.NameNodeCapacityPieChartView = App.DashboardWidgetView.extend({
+App.NameNodeCapacityPieChartView = App.PieChartDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/pie_chart'),
   title: Em.I18n.t('dashboard.widgets.NameNodeCapacity'),
   id: '2',
 
-  isPieChart: true,
-  isText: false,
-  isProgressBar: false,
   model_type: 'hdfs',
 
-  hiddenInfo: function () {
+  modelFieldMax: 'capacityTotal',
+  /**
+   * HDFS model has 'remaining' value, but not 'used'
+   */
+  modelFieldUsed: 'capacityRemaining',
+
+  widgetHtmlId: 'widget-nn-capacity',
+
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  },
+
+  calcHiddenInfo: function () {
     var text = this.t("dashboard.services.hdfs.capacityUsed");
+    var total = this.get('model').get(this.get('modelFieldMax')) + 0;
+    var used = total - this.get('model').get(this.get('modelFieldUsed')) + 0;
     var total = this.get('model.capacityTotal');
     var remaining = this.get('model.capacityRemaining');
     var used = total !== null && remaining !== null ? total - remaining : null;
@@ -43,80 +54,13 @@ App.NameNodeCapacityPieChartView = App.DashboardWidgetView.extend({
     result.pushObject(percent + '% used');
     result.pushObject(numberUtils.bytesToSize(used, 1, 'parseFloat') + ' of ' + numberUtils.bytesToSize(total, 1, 'parseFloat'));
     return result;
-  }.property('model.capacityUsed', 'model.capacityTotal'),
-
-  thresh1: 40,// can be customized
-  thresh2: 70,
-  maxValue: 100,
-
-  isPieExist: function () {
-    var total = this.get('model.capacityTotal') + 0;
-    return total > 0 ;
-  }.property('model.capacityTotal'),
-
-  content: App.ChartPieView.extend({
-
-    model: null,  //data bind here
-    id: 'widget-nn-capacity', // html id
-    stroke: '#D6DDDF', //light grey
-    thresh1: null,  // can be customized later
-    thresh2: null,
-    innerR: 25,
-
-    existCenterText: true,
-    centerTextColor: function () {
-      return this.get('contentColor');
-    }.property('contentColor'),
-
-    palette: new Rickshaw.Color.Palette({
-      scheme: [ '#FFFFFF', '#D6DDDF'].reverse()
-    }),
-
-    data: function () {
-      var total = this.get('model.capacityTotal') + 0;
-      var remaining = this.get('model.capacityRemaining') + 0;
-      var used = total - remaining;
-      var percent = total > 0 ? ((used * 100) / total).toFixed() : 0;
-      if (percent == "NaN" || percent < 0) {
-        percent = Em.I18n.t('services.service.summary.notAvailable') + " ";
-      }
-      return [ percent, 100 - percent];
-    }.property('model.capacityUsed', 'model.capacityTotal'),
-
-    contentColor: function () {
-      var used = parseFloat(this.get('data')[0]);
-      var thresh1 = parseFloat(this.get('thresh1'));
-      var thresh2 = parseFloat(this.get('thresh2'));
-      var color_green = '#95A800';
-      var color_red = '#B80000';
-      var color_orange = '#FF8E00';
-      if (used <= thresh1) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_green  ].reverse()
-        }))
-        return color_green;
-      } else if (used <= thresh2) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_orange  ].reverse()
-        }))
-        return color_orange;
-      } else {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_red  ].reverse()
-        }))
-        return color_red;
-      }
-    }.property('data', 'this.thresh1', 'this.thresh2'),
-
-    // refresh text and color when data in model changed
-    refreshSvg: function () {
-      // remove old svg
-      var old_svg =  $("#" + this.id);
-      old_svg.remove();
+  },
 
-      // draw new svg
-      this.appendSvg();
-    }.observes('this.data', 'this.thresh1', 'this.thresh2')
-  })
+  calcDataForPieChart: function() {
+    var total = this.get('model').get(this.get('modelFieldMax')) * 1024 * 1024;
+    var used = total - this.get('model').get(this.get('modelFieldUsed')) * 1024 * 1024;
+    var percent = total > 0 ? ((used)*100 / total).toFixed() : 0;
+    return [ percent, 100 - percent];
+  }
 
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/hdfs_links.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/hdfs_links.js b/ambari-web/app/views/main/dashboard/widgets/hdfs_links.js
index 6c16686..ede0003 100644
--- a/ambari-web/app/views/main/dashboard/widgets/hdfs_links.js
+++ b/ambari-web/app/views/main/dashboard/widgets/hdfs_links.js
@@ -18,28 +18,23 @@
 
 var App = require('app');
 
-App.HDFSLinksView = App.DashboardWidgetView.extend({
+App.HDFSLinksView = App.LinkDashboardWidgetView.extend({
 
   templateName: require('templates/main/dashboard/widgets/hdfs_links'),
   title: Em.I18n.t('dashboard.widgets.HDFSLinks'),
   id: '17',
 
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-  isLinks: true,
   model_type: 'hdfs',
 
-  dataNodeComponent: function () {
-    return App.HostComponent.find().findProperty('componentName', 'DATANODE');
-  }.property(),
+  port: '50070',
 
-  nodeWebUrl: function () {
-    return "http://" + this.get('model').get('nameNode').get('publicHostName') + ":50070";
-  }.property('model.nameNode')
+  componentName: 'DATANODE',
 
-})
+  modelField: 'nameNode',
 
-App.HDFSLinksView. reopenClass({
-  isLinks: true
-})
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/jobtracker_cpu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/jobtracker_cpu.js b/ambari-web/app/views/main/dashboard/widgets/jobtracker_cpu.js
index fe62bc7..4bfc6c6 100644
--- a/ambari-web/app/views/main/dashboard/widgets/jobtracker_cpu.js
+++ b/ambari-web/app/views/main/dashboard/widgets/jobtracker_cpu.js
@@ -18,22 +18,29 @@
 
 var App = require('app');
 
-App.JobTrackerCpuPieChartView = App.DashboardWidgetView.extend({
+App.JobTrackerCpuPieChartView = App.PieChartDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/pie_chart'),
   title: Em.I18n.t('dashboard.widgets.JobTrackerCpu'),
   id: '7',
 
-  isPieChart: true,
-  isText: false,
-  isProgressBar: false,
   model_type: 'mapreduce',
-  hiddenInfo: function () {
-    var value = this.get('model.jobTrackerCpu');
+
+  widgetHtmlId: 'widget-jt-cpu',
+
+  modelFieldUsed: 'jobTrackerCpu',
+
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  },
+
+  calcHiddenInfo: function() {
+    var value = this.get('model').get(this.get('modelFieldUsed'));
     var obj1;
     if( value == null) {
       obj1 = Em.I18n.t('services.service.summary.notAvailable');
-    }else{
+    }
+    else {
       value = value >= 100 ? 100: value;
       obj1 = (value + 0).toFixed(2) + '%';
     }
@@ -41,76 +48,17 @@ App.JobTrackerCpuPieChartView = App.DashboardWidgetView.extend({
     result.pushObject(obj1);
     result.pushObject('CPU wait I/O');
     return result;
-  }.property('model.jobTrackerCpu'),
-
-  thresh1: 40,// can be customized
-  thresh2: 70,
-  maxValue: 100,
-
-  isPieExist: function () {
-    var total = this.get('model.jobTrackerCpu');
-    return total !== null ;
-  }.property('model.jobTrackerCpu'),
-
-  content: App.ChartPieView.extend({
-
-    model: null,  //data bind here
-    id: 'widget-jt-cpu', // html id
-    stroke: '#D6DDDF', //light grey
-    thresh1: 50,  // can be customized later
-    thresh2: 80,
-    innerR: 25,
-
-    existCenterText: true,
-    centerTextColor: function () {
-      return this.get('contentColor');
-    }.property('contentColor'),
-
-    palette: new Rickshaw.Color.Palette({
-      scheme: [ '#FFFFFF', '#D6DDDF'].reverse()
-    }),
-
-    data: function () {
-      var value = this.get('model.jobTrackerCpu');
-      value = value >= 100 ? 100: value;
-      var percent = (value + 0).toFixed(1);
-      return [ percent, 100 - percent];
-    }.property('model.jobTrackerCpu'),
-
-    contentColor: function () {
-      var used = parseFloat(this.get('data')[0]);
-      var thresh1 = parseFloat(this.get('thresh1'));
-      var thresh2 = parseFloat(this.get('thresh2'));
-      var color_green = '#95A800';
-      var color_red = '#B80000';
-      var color_orange = '#FF8E00';
-      if (used <= thresh1) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_green  ].reverse()
-        }))
-        return color_green;
-      } else if (used <= thresh2) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_orange  ].reverse()
-        }))
-        return color_orange;
-      } else {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_red  ].reverse()
-        }))
-        return color_red;
-      }
-    }.property('data', 'thresh1', 'thresh2'),
+  },
 
-    // refresh text and color when data in model changed
-    refreshSvg: function () {
-      // remove old svg
-      var old_svg =  $("#" + this.id);
-      old_svg.remove();
+  calcIsPieExists: function() {
+    return (this.get('model').get(this.get('modelFieldUsed')) != null);
+  },
 
-      // draw new svg
-      this.appendSvg();
-    }.observes('model.jobTrackerCpu', 'thresh1', 'thresh2')
-  })
+  calcDataForPieChart: function() {
+    var value = this.get('model').get(this.get('modelFieldUsed'));
+    value = value >= 100 ? 100: value;
+    var percent = (value + 0).toFixed(1);
+    return [ percent, 100 - percent];
+  }
 
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/jobtracker_heap.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/jobtracker_heap.js b/ambari-web/app/views/main/dashboard/widgets/jobtracker_heap.js
index 46d5c07..6df6c40 100644
--- a/ambari-web/app/views/main/dashboard/widgets/jobtracker_heap.js
+++ b/ambari-web/app/views/main/dashboard/widgets/jobtracker_heap.js
@@ -19,18 +19,14 @@
 var App = require('app');
 var numberUtils = require('utils/number_utils');
 
-App.JobTrackerHeapPieChartView = App.DashboardWidgetView.extend({
+App.JobTrackerHeapPieChartView = App.PieChartDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/pie_chart'),
   title: Em.I18n.t('dashboard.widgets.JobTrackerHeap'),
   id: '6',
 
-  isPieChart: true,
-  isText: false,
-  isProgressBar: false,
   model_type: 'mapreduce',
 
-  hiddenInfo: function () {
+ /* hiddenInfo: function () {
     var heapUsed = this.get('model').get('jobTrackerHeapUsed');
     var heapMax = this.get('model').get('jobTrackerHeapMax');
     var percent = heapMax > 0 ? 100 * heapUsed / heapMax : 0;
@@ -38,75 +34,14 @@ App.JobTrackerHeapPieChartView = App.DashboardWidgetView.extend({
     result.pushObject(percent.toFixed(1) + '% used');
     result.pushObject(numberUtils.bytesToSize(heapUsed, 1, "parseFloat") + ' of ' + numberUtils.bytesToSize(heapMax, 1, "parseFloat"));
     return result;
-  }.property('model.jobTrackerHeapUsed', 'model.jobTrackerHeapMax'),
+  }.property('model.jobTrackerHeapUsed', 'model.jobTrackerHeapMax'),*/
+  modelFieldMax: 'jobTrackerHeapMax',
+  modelFieldUsed: 'jobTrackerHeapUsed',
 
-  thresh1: 40,// can be customized
-  thresh2: 70,
-  maxValue: 100,
+  widgetHtmlId: 'widget-jt-heap',
 
-  isPieExist: function () {
-    var total = this.get('model.jobTrackerHeapMax') * 1000000;
-    return total > 0 ;
-  }.property('model.jobTrackerHeapMax'),
-
-  content: App.ChartPieView.extend({
-
-    model: null,  //data bind here
-    id: 'widget-jt-heap', // id in html
-    stroke: '#D6DDDF', //light grey
-    thresh1: null,
-    thresh2: null,
-    innerR: 25,
-
-    existCenterText: true,
-    centerTextColor: function () {
-      return this.get('contentColor');
-    }.property('contentColor'),
-
-    palette: new Rickshaw.Color.Palette({
-      scheme: [ '#FFFFFF', '#D6DDDF'].reverse()
-    }),
-
-    data: function () {
-      var used = this.get('model.jobTrackerHeapUsed') * 1000000;
-      var total = this.get('model.jobTrackerHeapMax') * 1000000;
-      var percent = total > 0 ? ((used)*100 / total).toFixed() : 0;
-      return [ percent, 100 - percent];
-    }.property('model.jobTrackerHeapUsed', 'model.jobTrackerHeapMax'),
-
-    contentColor: function (){
-      var used = parseFloat(this.get('data')[0]);
-      var thresh1 = parseFloat(this.get('thresh1'));
-      var thresh2 = parseFloat(this.get('thresh2'));
-      var color_green = '#95A800';
-      var color_red = '#B80000';
-      var color_orange = '#FF8E00';
-      if (used <= thresh1) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_green  ].reverse()
-        }))
-        return color_green;
-      } else if (used <= thresh2) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_orange  ].reverse()
-        }))
-        return color_orange;
-      } else {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_red  ].reverse()
-        }))
-        return color_red;
-      }
-    }.property('data', 'this.thresh1', 'this.thresh2'),
-
-    refreshSvg: function () {
-      // remove old svg
-      var old_svg =  $("#" + this.id);
-      old_svg.remove();
-
-      // draw new svg
-      this.appendSvg();
-    }.observes('this.data', 'this.thresh1', 'this.thresh2')
-  })
-
-})
\ No newline at end of file
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/jobtracker_rpc.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/jobtracker_rpc.js b/ambari-web/app/views/main/dashboard/widgets/jobtracker_rpc.js
index 9c046d1..46780b3 100644
--- a/ambari-web/app/views/main/dashboard/widgets/jobtracker_rpc.js
+++ b/ambari-web/app/views/main/dashboard/widgets/jobtracker_rpc.js
@@ -18,15 +18,11 @@
 
 var App = require('app');
 
-App.JobTrackerRpcView = App.DashboardWidgetView.extend({
+App.JobTrackerRpcView = App.TextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/simple_text'),
   title: Em.I18n.t('dashboard.widgets.JobTrackerRpc'),
   id:'9',
 
-  isPieChart: false,
-  isText: true,
-  isProgressBar: false,
   model_type: 'mapreduce',
   hiddenInfo: function (){
     var result = [];
@@ -35,26 +31,6 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
     return result;
   }.property('model.jobTrackerRpc'),
 
-  classNameBindings: ['isRed', 'isOrange', 'isGreen', 'isNA'],
-  isGreen: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') <= thresh1? true: false;
-  }.property('data','thresh1','thresh2'),
-  isOrange: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return (this.get('data') <= thresh2 && this.get('data') > thresh1 )? true: false;
-  }.property('data','thresh1','thresh2'),
-  isRed: function () {
-    var thresh1 = this.get('thresh1');
-    var thresh2 = this.get('thresh2');
-    return this.get('data') > thresh2? true: false;
-  }.property('data','thresh1','thresh2'),
-  isNA: function () {
-     return this.get('data') === null;
-  }.property('data'),
-
   thresh1: 0.5,
   thresh2: 2,
   maxValue: 'infinity',
@@ -75,7 +51,7 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
     if (this.get('data') || this.get('data') == 0) {
       return this.get('data') + " ms";
     } else {
-      return this.t('services.service.summary.notAvailable');
+      return Em.I18n.t('services.service.summary.notAvailable');
     }
   }.property('model.jobTrackerRpc'),
 
@@ -84,9 +60,7 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
     var configObj = Ember.Object.create({
       thresh1: parent.get('thresh1') + '',
       thresh2: parent.get('thresh2') + '',
-      hintInfo: 'Edit the thresholds to change the color of current widget. ' +
-        ' The unit is milli-second. '+
-        ' So enter two numbers larger than 0. ',
+      hintInfo: Em.I18n.t('dashboard.widgets.hintInfo.hint3'),
       isThresh1Error: false,
       isThresh2Error: false,
       errorMessage1: "",
@@ -128,7 +102,7 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
 
     var browserVerion = this.getInternetExplorerVersion();
     App.ModalPopup.show({
-      header: 'Customize Widget',
+      header: Em.I18n.t('dashboard.widgets.popupHeader'),
       classNames: [ 'sixty-percent-width-modal-edit-widget'],
       bodyClass: Ember.View.extend({
         templateName: require('templates/main/dashboard/edit_widget_popup'),
@@ -152,10 +126,6 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
           this.hide();
         }
       },
-      secondary : Em.I18n.t('common.cancel'),
-      onSecondary: function () {
-        this.hide();
-      },
 
       didInsertElement: function () {
         var colors = ['#95A800', '#FF8E00', '#B80000']; //color green, orange ,red
@@ -171,28 +141,9 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
             max: 100,
             values: handlers,
             create: function (event, ui) {
-              updateColors(handlers);
+              parent.updateColors(handlers, colors);
             }
           });
-
-          function updateColors (handlers) {
-            var colorstops = colors[0] + ", "; // start with the first color
-            for (var i = 0; i < handlers.length; i++) {
-              colorstops += colors[i] + " " + handlers[i] + "%,";
-              colorstops += colors[i+1] + " " + handlers[i] + "%,";
-            }
-            // end with the last color
-            colorstops += colors[colors.length - 1];
-            var css1 = '-webkit-linear-gradient(left,' + colorstops + ')'; // chrome & safari
-            $('#slider-range').css('background-image', css1);
-            var css2 = '-ms-linear-gradient(left,' + colorstops + ')'; // IE 10+
-            $('#slider-range').css('background-image', css2);
-            //$('#slider-range').css('filter', 'progid:DXImageTransform.Microsoft.gradient( startColorStr= ' + colors[0] + ', endColorStr= ' + colors[2] +',  GradientType=1 )' ); // IE 10-
-            var css3 = '-moz-linear-gradient(left,' + colorstops + ')'; // Firefox
-            $('#slider-range').css('background-image', css3);
-
-            $('#slider-range .ui-widget-header').css({'background-color': '#FF8E00', 'background-image': 'none'}); // change the  original ranger color
-          }
         } else {
           configObj.set('isIE9', true);
           configObj.set('isGreenOrangeRed', true);
@@ -201,4 +152,4 @@ App.JobTrackerRpcView = App.DashboardWidgetView.extend({
     });
   }
 
-})
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/jobtracker_uptime.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/jobtracker_uptime.js b/ambari-web/app/views/main/dashboard/widgets/jobtracker_uptime.js
index c7921fd..282e138 100644
--- a/ambari-web/app/views/main/dashboard/widgets/jobtracker_uptime.js
+++ b/ambari-web/app/views/main/dashboard/widgets/jobtracker_uptime.js
@@ -17,106 +17,20 @@
  */
 
 var App = require('app');
-var date = require('utils/date');
 
-App.JobTrackerUptimeView = App.DashboardWidgetView.extend({
+App.JobTrackerUptimeView = App.UptimeTextDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/uptime'),
   title: Em.I18n.t('dashboard.widgets.JobTrackerUptime'),
   id: '16',
 
-  isPieChart: false,
-  isText: true,
-  isProgressBar: false,
   model_type: 'mapreduce',
-  hiddenInfo: [],
-  hiddenInfoClass: "hidden-info-three-line",
 
-  classNameBindings: ['isRed', 'isOrange', 'isGreen', 'isNA'],
-  isGreen: function () {
-    return this.get('data') != null;
-  }.property('data'),
-  isOrange: function () {
-   return false;
-  }.property('data'),
-  isRed: function () {
-    return false;
-  }.property('data'),
-  isNA: function () {
-    return this.get('data') == null;
-  }.property('data'),
+  component: 'JobTracker',
+  modelField: 'jobTrackerStartTime',
 
-  thresh1: 5,
-  thresh2: 10,
-  maxValue: 'infinity',
-
-  data: function(){
-    var uptime = this.get('model.jobTrackerStartTime');
-    if (uptime && uptime > 0) {
-      var uptimeString = this.timeConverter(uptime);
-      var diff = (new Date()).getTime() - uptime;
-      if (diff < 0) {
-        diff = 0;
-      }
-      var formatted = date.timingFormat(diff); //17.67 days
-      var timeUnit = null;
-      switch (formatted.split(" ")[1]){
-        case 'secs':
-          timeUnit = 's';
-          break;
-        case 'hours':
-          timeUnit = 'hr';
-          break;
-        case 'days':
-          timeUnit = 'd';
-          break;
-        case 'mins':
-          timeUnit = 'min';
-          break;
-        default:
-          timeUnit = formatted.split(" ")[1];
-      }
-      this.set('timeUnit', timeUnit);
-      this.set('hiddenInfo', []);
-      this.get('hiddenInfo').pushObject(formatted);
-      this.get('hiddenInfo').pushObject(uptimeString[0]);
-      this.get('hiddenInfo').pushObject(uptimeString[1]);
-      return parseFloat(formatted.split(" ")[0]);
-    }
-    this.set('hiddenInfo', ['JobTracker','Not Running']);
-    return null;
-  }.property('model.jobTrackerStartTime'),
-
-  timeUnit: null,
-
-  content: function () {
-    var data = this.get('data');
-    if (data) {
-      return data.toFixed(1) + ' '+ this.get('timeUnit');
-    } else {
-      return this.t('services.service.summary.notAvailable');
-    }
-  }.property('model.jobTrackerStartTime'),
-
-  timeConverter: function (timestamp) {
-    var origin = new Date(timestamp);
-    origin = origin.toString();
-    var result = [];
-    var start = origin.indexOf('GMT');
-    if(start == -1){ // ie
-      var arr = origin.split(" ");
-      result.pushObject(arr[0] + " " + arr[1] + " " + arr[2] + " " + arr[3]);
-      var second = '';
-      for(var i = 4; i < arr.length; i++){
-        second = second + " " + arr[i];
-      }
-      result.pushObject(second);
-    }else{ // other browsers
-      var end = origin.indexOf(" ", start);
-      result.pushObject(origin.slice(0, start-10));
-      result.pushObject(origin.slice(start-9));
-    }
-    return result;
+  didInsertElement: function() {
+    this._super();
+    this.calc();
   }
 
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/links_widget.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/links_widget.js b/ambari-web/app/views/main/dashboard/widgets/links_widget.js
new file mode 100644
index 0000000..1aabdcb
--- /dev/null
+++ b/ambari-web/app/views/main/dashboard/widgets/links_widget.js
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+var App = require('app');
+var date = require('utils/date');
+
+App.LinkDashboardWidgetView = App.DashboardWidgetView.extend({
+
+  componentName: null,
+
+  component: function() {
+    return App.HostComponent.find().findProperty('componentName', this.get('componentName'));
+  }.property(),
+
+  port: null,
+
+  modelField: null,
+
+  webUrl: null,
+
+  didInsertElement: function() {
+    this._super();
+    this.addObserver('model.' + this.get('modelField'), this, this.calc);
+  },
+  calc: function() {
+    this.set('webUrl', this.calcWebUrl());
+  },
+  calcWebUrl: function() {
+    if (this.get('model')) {
+      return "http://" + this.get('model').get(this.get('modelField')).get('publicHostName') + ':' + this.get('port');
+    }
+    return '';
+  }
+});

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/mapreduce_links.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/mapreduce_links.js b/ambari-web/app/views/main/dashboard/widgets/mapreduce_links.js
index 443a9f6..afdfbe6 100644
--- a/ambari-web/app/views/main/dashboard/widgets/mapreduce_links.js
+++ b/ambari-web/app/views/main/dashboard/widgets/mapreduce_links.js
@@ -18,28 +18,23 @@
 
 var App = require('app');
 
-App.MapReduceLinksView = App.DashboardWidgetView.extend({
+App.MapReduceLinksView = App.LinkDashboardWidgetView.extend({
 
   templateName: require('templates/main/dashboard/widgets/mapreduce_links'),
   title: Em.I18n.t('dashboard.widgets.MapReduceLinks'),
   id: '18',
 
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-  isLinks: true,
   model_type: 'mapreduce',
 
-  taskTrackerComponent: function () {
-    return App.HostComponent.find().findProperty('componentName', 'TASKTRACKER');
-  }.property(),
+  port: '50030',
 
-  jobTrackerWebUrl: function () {
-    return "http://" + this.get('model').get('jobTracker').get('publicHostName') + ":50030";
-  }.property('model.jobTracker')
+  componentName: 'TASKTRACKER',
 
-})
+  modelField: 'jobTracker',
 
-App.MapReduceLinksView. reopenClass({
-  isLinks: true
-})
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  }
+
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/mapreduce_slots.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/mapreduce_slots.js b/ambari-web/app/views/main/dashboard/widgets/mapreduce_slots.js
index 8a0c1d6..40c613f 100644
--- a/ambari-web/app/views/main/dashboard/widgets/mapreduce_slots.js
+++ b/ambari-web/app/views/main/dashboard/widgets/mapreduce_slots.js
@@ -24,18 +24,17 @@ App.MapReduceSlotsView = App.DashboardWidgetView.extend({
   title: Em.I18n.t('dashboard.widgets.MapReduceSlots'),
   id:'10',
 
-  isPieChart: false,
-  isText: false,
   isProgressBar: true,
   model_type: 'mapreduce',
-  hiddenInfo: function (){
+  hiddenInfo: function () {
     var result = [];
-    if(this.get('isViewExist')){
+    if(this.get('isViewExist')) {
       var line1 = "Map: " + this.get('model.mapSlotsOccupied') + " Occupied / " + this.get('model.mapSlotsReserved') + " Reserved / " + this.get('model.mapSlots') + " Total";
       result.pushObject(line1);
       var line2 = "Reduce: " + this.get('model.reduceSlotsOccupied') + " Occupied / " + this.get('model.reduceSlotsReserved') + " Reserved / " + this.get('model.reduceSlots') + " Total";
       result.pushObject(line2);
-    }else{
+    }
+    else {
       result.pushObject('MapReduce Not Started');
     }
     return result;
@@ -81,8 +80,8 @@ App.MapReduceSlotsView = App.DashboardWidgetView.extend({
     return this.get('model.reduceSlotsOccupied') + "/" + this.get('model.reduceSlotsReserved') + "/" + this.get('model.reduceSlots');
   }.property('model.reduceSlotsReserved','model.reduceSlotsOccupied','model.reduceSlots')
 
-})
+});
 
 App.MapReduceSlotsView.reopenClass({
-  isProgressBar: true
-})
\ No newline at end of file
+  class: 'span4p8'
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/metrics_cpu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/metrics_cpu.js b/ambari-web/app/views/main/dashboard/widgets/metrics_cpu.js
index 3f7f139..7bc7620 100644
--- a/ambari-web/app/views/main/dashboard/widgets/metrics_cpu.js
+++ b/ambari-web/app/views/main/dashboard/widgets/metrics_cpu.js
@@ -18,19 +18,13 @@
 
 var App = require('app');
 
-App.ChartClusterMetricsCPUWidgetView = App.DashboardWidgetView.extend({
+App.ChartClusterMetricsCPUWidgetView = App.ClusterMetricsDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/cluster_metrics'),
   title: Em.I18n.t('dashboard.clusterMetrics.cpu'),
   id: '13',
 
-  isClusterMetrics: true,
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-
   content: App.ChartClusterMetricsCPU.extend({
     noTitleUnderGraph: true,
     inWidget: true
   })
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/metrics_load.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/metrics_load.js b/ambari-web/app/views/main/dashboard/widgets/metrics_load.js
index 23298fb..80360a7 100644
--- a/ambari-web/app/views/main/dashboard/widgets/metrics_load.js
+++ b/ambari-web/app/views/main/dashboard/widgets/metrics_load.js
@@ -18,19 +18,13 @@
 
 var App = require('app');
 
-App.ChartClusterMetricsLoadWidgetView = App.DashboardWidgetView.extend({
+App.ChartClusterMetricsLoadWidgetView = App.ClusterMetricsDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/cluster_metrics'),
   title: Em.I18n.t('dashboard.clusterMetrics.load'),
   id: '14',
 
-  isClusterMetrics: true,
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-
   content: App.ChartClusterMetricsLoad.extend({
     noTitleUnderGraph: true,
     inWidget: true
   })
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/metrics_memory.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/metrics_memory.js b/ambari-web/app/views/main/dashboard/widgets/metrics_memory.js
index ff22cd5..4a30dcc 100644
--- a/ambari-web/app/views/main/dashboard/widgets/metrics_memory.js
+++ b/ambari-web/app/views/main/dashboard/widgets/metrics_memory.js
@@ -18,19 +18,13 @@
 
 var App = require('app');
 
-App.ChartClusterMetricsMemoryWidgetView = App.DashboardWidgetView.extend({
+App.ChartClusterMetricsMemoryWidgetView = App.ClusterMetricsDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/cluster_metrics'),
   title: Em.I18n.t('dashboard.clusterMetrics.memory'),
   id: '11',
 
-  isClusterMetrics: true,
-  isPieChart: false,
-  isText: false,
-  isProgressBar: false,
-
   content: App.ChartClusterMetricsMemory.extend({
     noTitleUnderGraph: true,
     inWidget: true
   })
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/metrics_network.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/metrics_network.js b/ambari-web/app/views/main/dashboard/widgets/metrics_network.js
index 17ea447..d82784e 100644
--- a/ambari-web/app/views/main/dashboard/widgets/metrics_network.js
+++ b/ambari-web/app/views/main/dashboard/widgets/metrics_network.js
@@ -18,19 +18,13 @@
 
 var App = require('app');
 
-App.ChartClusterMetricsNetworkWidgetView = App.DashboardWidgetView.extend({
+App.ChartClusterMetricsNetworkWidgetView = App.ClusterMetricsDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/cluster_metrics'),
   title: Em.I18n.t('dashboard.clusterMetrics.network'),
   id: '12',
 
-  isClusterMetrics: true,
-  isPieChart: false,
-  isText:false,
-  isProgressBar:false,
-
   content: App.ChartClusterMetricsNetwork.extend({
     noTitleUnderGraph: true,
     inWidget: true
   })
-})
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ambari/blob/e81d705b/ambari-web/app/views/main/dashboard/widgets/namenode_cpu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/dashboard/widgets/namenode_cpu.js b/ambari-web/app/views/main/dashboard/widgets/namenode_cpu.js
index 3873776..35708c5 100644
--- a/ambari-web/app/views/main/dashboard/widgets/namenode_cpu.js
+++ b/ambari-web/app/views/main/dashboard/widgets/namenode_cpu.js
@@ -18,22 +18,29 @@
 
 var App = require('app');
 
-App.NameNodeCpuPieChartView = App.DashboardWidgetView.extend({
+App.NameNodeCpuPieChartView = App.PieChartDashboardWidgetView.extend({
 
-  templateName: require('templates/main/dashboard/widgets/pie_chart'),
   title: Em.I18n.t('dashboard.widgets.NameNodeCpu'),
   id: '3',
 
-  isPieChart: true,
-  isText: false,
-  isProgressBar: false,
   model_type: 'hdfs',
-  hiddenInfo: function () {
-    var value = this.get('model.nameNodeCpu');
+
+  widgetHtmlId: 'widget-nn-cpu',
+
+  modelFieldUsed: 'nameNodeCpu',
+
+  didInsertElement: function() {
+    this._super();
+    this.calc();
+  },
+
+  calcHiddenInfo: function() {
+    var value = this.get('model').get(this.get('modelFieldUsed'));
     var obj1;
     if( value == null) {
       obj1 = Em.I18n.t('services.service.summary.notAvailable');
-    }else{
+    }
+    else {
       value = value >= 100 ? 100: value;
       obj1 = (value + 0).toFixed(2) + '%';
     }
@@ -41,76 +48,17 @@ App.NameNodeCpuPieChartView = App.DashboardWidgetView.extend({
     result.pushObject(obj1);
     result.pushObject('CPU wait I/O');
     return result;
-  }.property('model.nameNodeCpu'),
-
-  thresh1: 40,// can be customized
-  thresh2: 70,
-  maxValue: 100,
-
-  isPieExist: function () {
-    var total = this.get('model.nameNodeCpu');
-    return total !== null ;
-  }.property('model.nameNodeCpu'),
-
-  content: App.ChartPieView.extend({
-
-    model: null,  //data bind here
-    id: 'widget-nn-cpu', // html id
-    stroke: '#D6DDDF', //light grey
-    thresh1: null,  // can be customized later
-    thresh2: null,
-    innerR: 25,
-
-    existCenterText: true,
-    centerTextColor: function () {
-      return this.get('contentColor');
-    }.property('contentColor'),
-
-    palette: new Rickshaw.Color.Palette ({
-      scheme: [ '#FFFFFF', '#D6DDDF'].reverse()
-    }),
-
-    data: function () {
-      var value = this.get('model.nameNodeCpu');
-      value = value >= 100 ? 100: value;
-      var percent = (value + 0).toFixed(1);
-      return [ percent, 100 - percent];
-    }.property('model.nameNodeCpu'),
-
-    contentColor: function () {
-      var used = parseFloat(this.get('data')[0]);
-      var thresh1 = parseFloat(this.get('thresh1'));
-      var thresh2 = parseFloat(this.get('thresh2'));
-      var color_green = '#95A800';
-      var color_red = '#B80000';
-      var color_orange = '#FF8E00';
-      if (used <= thresh1) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_green  ].reverse()
-        }))
-        return color_green;
-      } else if (used <= thresh2) {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_orange  ].reverse()
-        }))
-        return color_orange;
-      } else {
-        this.set('palette', new Rickshaw.Color.Palette({
-          scheme: [ '#FFFFFF', color_red  ].reverse()
-        }))
-        return color_red;
-      }
-    }.property('data', 'thresh1', 'thresh2'),
+  },
 
-    // refresh text and color when data in model changed
-    refreshSvg: function () {
-      // remove old svg
-      var old_svg =  $("#" + this.id);
-      old_svg.remove();
+  calcIsPieExists: function() {
+    return (this.get('model').get(this.get('modelFieldUsed')) != null);
+  },
 
-      // draw new svg
-      this.appendSvg();
-    }.observes('model.nameNodeCpu', 'thresh1', 'thresh2')
-  })
+  calcDataForPieChart: function() {
+    var value = this.get('model').get(this.get('modelFieldUsed'));
+    value = value >= 100 ? 100: value;
+    var percent = (value + 0).toFixed(1);
+    return [ percent, 100 - percent];
+  }
 
-})
+});
\ No newline at end of file