ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akovale...@apache.org
Subject ambari git commit: AMBARI-8666. Alerts UI: cleanup #4. (akovalenko)
Date Thu, 11 Dec 2014 18:33:19 GMT
Repository: ambari
Updated Branches:
  refs/heads/trunk 8e4ce69df -> da7643e51


AMBARI-8666. Alerts UI: cleanup #4. (akovalenko)


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

Branch: refs/heads/trunk
Commit: da7643e51b4cb22181af4bc739f44339ba637e16
Parents: 8e4ce69
Author: Aleksandr Kovalenko <akovalenko@hortonworks.com>
Authored: Thu Dec 11 19:56:05 2014 +0200
Committer: Aleksandr Kovalenko <akovalenko@hortonworks.com>
Committed: Thu Dec 11 20:32:25 2014 +0200

----------------------------------------------------------------------
 .../main/alert_definitions_controller.js        | 41 ++++++------
 .../alerts/definition_configs_controller.js     | 11 +++-
 ambari-web/app/controllers/main/host/details.js | 10 ---
 .../main/host/host_alerts_controller.js         | 17 ++++-
 .../controllers/main/service/info/summary.js    | 31 ++++++---
 ambari-web/app/messages.js                      |  9 +--
 ambari-web/app/models/alert_config.js           | 36 +++++++++--
 ambari-web/app/models/alert_definition.js       | 34 ++++++----
 ambari-web/app/models/alert_instance.js         | 42 ++++++++++--
 ambari-web/app/routes/main.js                   | 20 ++++--
 ambari-web/app/styles/alerts.less               | 40 ++++++------
 ambari-web/app/styles/application.less          |  1 -
 .../app/templates/common/alerts_popup.hbs       |  5 +-
 .../app/templates/main/alerts/configs.hbs       |  2 +-
 .../alerts/configs/alert_config_threshold.hbs   |  6 +-
 .../main/alerts/definition_details.hbs          |  8 +--
 .../main/host/details/host_component.hbs        |  2 +-
 .../app/templates/main/host/host_alerts.hbs     | 19 ++++--
 .../app/views/main/host/host_alerts_view.js     | 66 ++-----------------
 ambari-web/app/views/main/host/menu.js          | 68 +++++++++-----------
 .../test/controllers/main/host/details_test.js  |  9 ---
 ambari-web/test/models/alert_definition_test.js | 16 ++---
 22 files changed, 259 insertions(+), 234 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/controllers/main/alert_definitions_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alert_definitions_controller.js b/ambari-web/app/controllers/main/alert_definitions_controller.js
index 2a27f5a..a792840 100644
--- a/ambari-web/app/controllers/main/alert_definitions_controller.js
+++ b/ambari-web/app/controllers/main/alert_definitions_controller.js
@@ -41,7 +41,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * </ul>
    * @type {App.AlertDefinition[]}
    */
-  content: function() {
+  content: function () {
     return App.AlertDefinition.getAllDefinitions();
   }.property('mapperTimestamp'),
 
@@ -51,7 +51,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * @method toggleState
    * @return {App.ModalPopup}
    */
-  toggleState: function(event) {
+  toggleState: function (event) {
     var alertDefinition = event.context;
     var self = this;
     var bodyMessage = Em.Object.create({
@@ -60,7 +60,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
     });
 
     return App.showConfirmationFeedBackPopup(function (query) {
-      self.toggleDefinitionState (alertDefinition);
+      self.toggleDefinitionState(alertDefinition);
     }, bodyMessage);
   },
 
@@ -70,7 +70,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * @returns {$.ajax}
    * @method toggleDefinitionState
    */
-  toggleDefinitionState: function(alertDefinition) {
+  toggleDefinitionState: function (alertDefinition) {
     var newState = !alertDefinition.get('enabled');
     alertDefinition.set('enabled', newState);
     return App.ajax.send({
@@ -90,7 +90,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * @method getCriticalAlertsCountForService
    * @return {number}
    */
-  getCriticalAlertsCountForService: function(service) {
+  getCriticalAlertsCountForService: function (service) {
     var alertsForService = this.get('content').filterProperty('service', service);
     return alertsForService.filterProperty('isCriticalOrWarning').get('length');
   },
@@ -105,12 +105,12 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * @type {number}
    */
   allAlertsCount: function () {
-    return this.get('unhealthyAlertInstances').get('length');
+    return this.get('unhealthyAlertInstances.length');
   }.property('unhealthyAlertInstances.length'),
 
-  unhealthyAlertInstances: function() {
+  unhealthyAlertInstances: function () {
     return App.AlertInstance.find().toArray().filterProperty('state', 'CRITICAL').concat(
-      App.AlertInstance.find().toArray().filterProperty('state', 'WARNING')
+        App.AlertInstance.find().toArray().filterProperty('state', 'WARNING')
     );
   }.property('mapperTimestamp'),
 
@@ -126,20 +126,29 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
    * @method showPopup
    * @return {App.ModalPopup}
    */
-  showPopup: function() {
+  showPopup: function () {
 
     var self = this;
 
     return App.ModalPopup.show({
 
-      header: Em.I18n.t('alerts.fastAccess.popup.header').format(self.get('allAlertsCount')),
+      header: function () {
+        return Em.I18n.t('alerts.fastAccess.popup.header').format(this.get('definitionsController.allAlertsCount'));
+      }.property('definitionsController.allAlertsCount'),
+
+      definitionsController: this,
 
       classNames: ['sixty-percent-width-modal', 'alerts-popup'],
 
-      secondary: null,
+      secondary: Em.I18n.t('alerts.fastAccess.popup.body.showmore'),
 
       isHideBodyScroll: true,
 
+      onSecondary: function () {
+        this.hide();
+        App.router.transitionTo('main.alerts.index');
+      },
+
       bodyClass: Em.View.extend({
 
         templateName: require('templates/common/alerts_popup'),
@@ -196,16 +205,8 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
           Em.run.next(this, function () {
             App.tooltip($(".timeago"));
           });
-        },
-
-        /**
-         * Router transition to alert summary page
-         */
-        showMore: function () {
-          this.get('parentView').hide();
-          App.router.transitionTo('main.alerts.index');
         }
       })
-    })
+    });
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/alerts/definition_configs_controller.js b/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
index 8b6f551..1b5c2d1 100644
--- a/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
+++ b/ambari-web/app/controllers/main/alerts/definition_configs_controller.js
@@ -138,6 +138,7 @@ App.MainAlertDefinitionConfigsController = Em.Controller.extend({
     }
 
     configs.setEach('isDisabled', !this.get('canEdit'));
+    configs.setEach('allConfigs', configs);
 
     this.set('configs', configs);
   },
@@ -488,6 +489,14 @@ App.MainAlertDefinitionConfigsController = Em.Controller.extend({
         value: property.get('value')
       }
     });
-  }
+  },
+
+  /**
+   * Define whether all configs are valid
+   * @type {Boolean}
+   */
+  hasErrors: function () {
+    return this.get('configs').someProperty('isValid', false);
+  }.property('configs.@each.isValid')
 
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/controllers/main/host/details.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/details.js b/ambari-web/app/controllers/main/host/details.js
index b639975..2b15729 100644
--- a/ambari-web/app/controllers/main/host/details.js
+++ b/ambari-web/app/controllers/main/host/details.js
@@ -52,16 +52,6 @@ App.MainHostDetailsController = Em.Controller.extend({
   },
 
   /**
-   * Open summary page of the selected service
-   * @param {object} event
-   * @method routeToService
-   */
-  routeToService: function (event) {
-    var service = event.context;
-    App.router.transitionTo('main.services.service.summary', service);
-  },
-
-  /**
    * List of active (not in passive state) host components
    * @type {Ember.Enumerable}
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/controllers/main/host/host_alerts_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/host/host_alerts_controller.js b/ambari-web/app/controllers/main/host/host_alerts_controller.js
index 9eaddd6..e753c05 100644
--- a/ambari-web/app/controllers/main/host/host_alerts_controller.js
+++ b/ambari-web/app/controllers/main/host/host_alerts_controller.js
@@ -21,7 +21,7 @@ var App = require('app');
 App.MainHostAlertsController = Em.ArrayController.extend({
   name: 'mainHostAlertsController',
 
-  selectedHost: function() {
+  selectedHost: function () {
     return App.get('router.mainHostDetailsController.content');
   }.property('App.router.mainHostDetailsController.content'),
 
@@ -29,8 +29,19 @@ App.MainHostAlertsController = Em.ArrayController.extend({
    * List of all <code>App.AlertInstance</code> by Host
    * @type {App.AlertInstance[]}
    */
-  content: function() {
+  content: function () {
     return App.AlertInstance.find().toArray().filterProperty('host', this.get('selectedHost'));
-  }.property('App.router.mainAlertInstancesController.isLoaded', 'selectedHost')
+  }.property('App.router.mainAlertInstancesController.isLoaded', 'selectedHost'),
+
+  /**
+   * Open details page of the selected alertDefinition
+   * @param {object} event
+   * @method routeToAlertDefinition
+   */
+  routeToAlertDefinition: function (event) {
+    var alertDefinition = App.AlertDefinition.getAllDefinitions().findProperty('id', event.context);
+    App.router.transitionTo('main.alerts.alertDetails', alertDefinition);
+  }
+
 
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/controllers/main/service/info/summary.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/info/summary.js b/ambari-web/app/controllers/main/service/info/summary.js
index fff7628..58f9b23 100644
--- a/ambari-web/app/controllers/main/service/info/summary.js
+++ b/ambari-web/app/controllers/main/service/info/summary.js
@@ -5,9 +5,9 @@
  * 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
@@ -88,17 +88,17 @@ App.MainServiceInfoSummaryController = Em.Controller.extend({
     });
   },
 
-  gotoConfigs: function (){
+  gotoConfigs: function () {
     App.router.get('mainServiceItemController').set('routeToConfigs', true);
     App.router.transitionTo('main.services.service.configs', this.get('content'));
     App.router.get('mainServiceItemController').set('routeToConfigs', false);
   },
 
-  nagiosUrl: function(){
+  nagiosUrl: function () {
     return App.router.get('clusterController.nagiosUrl');
   }.property('App.router.clusterController.nagiosUrl'),
-  
-  isNagiosInstalled: function(){
+
+  isNagiosInstalled: function () {
     return App.router.get('clusterController.isNagiosInstalled');
   }.property('App.router.clusterController.isNagiosInstalled'),
 
@@ -106,8 +106,10 @@ App.MainServiceInfoSummaryController = Em.Controller.extend({
     var service = event.context;
     return App.ModalPopup.show({
       header: Em.I18n.t('services.service.summary.alerts.popup.header').format(service.get('displayName')),
+      autoHeight: false,
       bodyClass: Em.View.extend({
         templateName: require('templates/main/service/info/service_alert_popup'),
+        classNames: ['service-alerts'],
         controllerBinding: 'App.router.mainAlertDefinitionsController',
         didInsertElement: function () {
           Em.run.next(this, function () {
@@ -116,7 +118,20 @@ App.MainServiceInfoSummaryController = Em.Controller.extend({
         },
         alerts: function () {
           var serviceDefinitions = this.get('controller.content').filterProperty('service', service);
-          return serviceDefinitions.filterProperty('isCriticalOrWarning');
+          // definitions should be sorted in order: critical, warning, all other
+          var criticalDefinitions = [];
+          var warningDefinitions = [];
+          serviceDefinitions.forEach(function (definition) {
+            if (definition.get('isCritical')) {
+              criticalDefinitions.push(definition);
+              serviceDefinitions = serviceDefinitions.without(definition);
+            } else if (definition.get('isWarning')) {
+              warningDefinitions.push(definition);
+              serviceDefinitions = serviceDefinitions.without(definition);
+            }
+          });
+          serviceDefinitions = criticalDefinitions.concat(warningDefinitions, serviceDefinitions);
+          return serviceDefinitions;
         }.property('controller.content'),
         gotoAlertDetails: function (event) {
           if (event && event.context) {
@@ -128,7 +143,7 @@ App.MainServiceInfoSummaryController = Em.Controller.extend({
           this.get('parentView').hide();
         }
       }),
-      isHideBodyScroll: true,
+      isHideBodyScroll: false,
       primary: Em.I18n.t('common.close'),
       secondary: null
     });

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index e165ef6..201a312 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -246,6 +246,7 @@ Em.I18n.translations = {
 
   'models.alert_instance.tiggered.verbose': "Occured on {0} <br> Checked on {1}",
   'models.alert_definition.triggered.verbose': "Occured on {0}",
+  'models.alert_definition.triggered.checked': "Status Changed: {0}\nLast Checked: {1}",
 
   'passiveState.turnOn':'Turn On Maintenance Mode',
   'passiveState.turnOff':'Turn Off Maintenance Mode',
@@ -871,8 +872,7 @@ Em.I18n.translations = {
   'alerts.table.header.lastTriggered': 'Last Status Changed',
   'alerts.table.header.lastChecked': 'Last Checked',
   'alerts.table.header.lastTrigger': 'Last Changed',
-  'alerts.table.header.text': 'Text',
-  'alerts.table.header.triggeredOn': 'Triggered On',
+  'alerts.table.header.check.response': 'Check Response',
   'alerts.table.header.definitionName': 'Alert Definition Name',
   'alerts.table.header.notification': 'Notification',
   'alerts.table.state': 'State',
@@ -885,6 +885,7 @@ Em.I18n.translations = {
   'alerts.table.state.enabled.confirm.btn': 'Confirm Disable',
   'alerts.table.state.disabled.confirm.btn': 'Confirm Enable',
   'alerts.filters.filteredAlertsInfo': '{0} of {1} definitions showing',
+  'alerts.definition.name': 'Alert Definition name',
 
   'alerts.definition.details.enable': 'Enable',
   'alerts.definition.details.disable': 'Disable',
@@ -1420,7 +1421,7 @@ Em.I18n.translations = {
 
   'services.service.summary.alerts.noAlerts': 'No alerts',
   'services.service.summary.alerts.alertsExist': '{0} alerts',
-  'services.service.summary.alerts.popup.header': 'Critical or Warning Alerts for {0}',
+  'services.service.summary.alerts.popup.header': 'Alerts for {0}',
 
   'services.service.info.metrics.flume.channelFillPercent':'Channel Fill Percentage',
   'services.service.info.metrics.flume.channelSize':'Channel Size',
@@ -1876,7 +1877,7 @@ Em.I18n.translations = {
   'alerts.actions.manage_alert_groups_popup.duplicateButton':'Duplicate Alert Group',
   'alerts.actions.manage_alert_groups_popup.addDefinition':'Add alert definitions to selected Alert Group',
   'alerts.actions.manage_alert_groups_popup.addDefinitionDisabled':'There are no available alert definitions to add',
-  'alerts.actions.manage_alert_groups_popup.addDefinitionToDefault': 'You cannot add alert definition to a default group',
+  'alerts.actions.manage_alert_groups_popup.addDefinitionToDefault': 'Cannot modify default alert group',
   'alerts.actions.manage_alert_groups_popup.removeDefinition':'Remove alert definitions from selected Alert Group',
   'alerts.actions.manage_alert_groups_popup.removeDefinitionDisabled':'Cannot modify default alert group',
   'alerts.actions.manage_alert_groups_popup.selectDefsDialog.title': 'Select Alert Group Definitions',

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/models/alert_config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alert_config.js b/ambari-web/app/models/alert_config.js
index 0eaf7b7..a3b8a46 100644
--- a/ambari-web/app/models/alert_config.js
+++ b/ambari-web/app/models/alert_config.js
@@ -139,7 +139,25 @@ App.AlertConfigProperty = Ember.Object.extend({
       default:
         console.error('Unable to find viewClass for displayType ', displayType);
     }
-  }.property('displayType')
+  }.property('displayType'),
+
+  /**
+   * Define whether property is valid
+   * Computed property
+   * Should be defined in child class
+   * @type {Boolean}
+   */
+  isValid: function () {
+    return true;
+  }.property(),
+
+  /**
+   * Array of a group of configs, that current config property relates to
+   * Should be set in controller in rendering configs function
+   * Used to get access to other configs properties of one group
+   * @type {App.AlertConfigProperty[]}
+   */
+  allConfigs: []
 
 });
 
@@ -211,7 +229,13 @@ App.AlertConfigProperties = {
     displayType: 'textField',
     unit: 'Minute',
     classNames: 'alert-interval-input',
-    apiProperty: 'interval'
+    apiProperty: 'interval',
+    isValid: function () {
+      var value = this.get('value');
+      if (!value) return false;
+      value = ('' + value).trim();
+      return !isNaN(value) && value >= 1;
+    }.property('value')
   }),
 
   /**
@@ -254,7 +278,7 @@ App.AlertConfigProperties = {
 
     /**
      * Value actually displayed to the user. This value is transformed
-     * based on the limited types of 'valueMetric's. Mappings from 
+     * based on the limited types of 'valueMetric's. Mappings from
      * 'value' to 'displayValue' is handled by observers.
      */
     displayValue: '',
@@ -271,7 +295,7 @@ App.AlertConfigProperties = {
 
     apiProperty: [],
 
-    init:function () {
+    init: function () {
       this.valueWasChanged();
       this._super();
     },
@@ -316,10 +340,10 @@ App.AlertConfigProperties = {
      */
     wasChanged: function () {
       return (this.get('previousValue') !== null && this.get('value') !== this.get('previousValue')) ||
-        (this.get('previousText') !== null && this.get('text') !== this.get('previousText'));
+      (this.get('previousText') !== null && this.get('text') !== this.get('previousText'));
     }.property('value', 'text', 'previousValue', 'previousText'),
 
-    valueWasChanged : function() {
+    valueWasChanged: function () {
       var value = this.get('value');
       var valueMetric = this.get('valueMetric');
       var displayValue = this.get('displayValue');

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/models/alert_definition.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alert_definition.js b/ambari-web/app/models/alert_definition.js
index 75f55c4..173897e 100644
--- a/ambari-web/app/models/alert_definition.js
+++ b/ambari-web/app/models/alert_definition.js
@@ -71,10 +71,10 @@ App.AlertDefinition = DS.Model.extend({
    */
   lastTriggeredAgoFormatted: function () {
     var lastTriggered = this.get('lastTriggered');
-    return lastTriggered ? $.timeago(new Date(lastTriggered)): '';
+    return lastTriggered ? $.timeago(new Date(lastTriggered)) : '';
   }.property('lastTriggered'),
 
-  lastTriggeredVerboseDisplay : function() {
+  lastTriggeredVerboseDisplay: function () {
     var lastTriggered = this.get('lastTriggered');
     return Em.I18n.t('models.alert_definition.triggered.verbose').format(dateUtils.dateFormat(lastTriggered));
   }.property('lastTriggered'),
@@ -89,7 +89,7 @@ App.AlertDefinition = DS.Model.extend({
     var previousPrefixAgo = $.timeago.settings.strings.prefixAgo;
     $.timeago.settings.strings.suffixAgo = null;
     $.timeago.settings.strings.prefixAgo = 'for';
-    var triggeredFor = lastTriggered ? $.timeago(new Date(lastTriggered)): '';
+    var triggeredFor = lastTriggered ? $.timeago(new Date(lastTriggered)) : '';
     $.timeago.settings.strings.suffixAgo = previousSuffixAgo;
     $.timeago.settings.strings.prefixAgo = previousPrefixAgo;
     return triggeredFor;
@@ -115,26 +115,27 @@ App.AlertDefinition = DS.Model.extend({
   status: function () {
     var order = this.get('order'),
         summary = this.get('summary'),
-        hostCnt = 0;
-    order.forEach(function(state) {
+        hostCnt = 0,
+        self = this;
+    order.forEach(function (state) {
       var cnt = summary[state] ? summary[state] : 0;
       hostCnt += cnt;
     });
     if (hostCnt > 1) {
       // multiple hosts
       return order.map(function (state) {
-        var shortState = state.substring(0, 4);
-        return summary[state] ? '<span class="label alert-state-' + state + '">' + shortState + ' ( ' + summary[state] + ' )</span>' : null;
+        var shortState = self.get('shortState')[state];
+        return summary[state] ? '<span class="alert-state-single-host label alert-state-' + state + '">' + shortState + ' (' + summary[state] + ')</span>' : null;
       }).compact().join(' ');
     } else if (hostCnt == 1) {
       // single host, single status
       return order.map(function (state) {
-        return summary[state] ? '<span class="alert-state-single-host label alert-state-'+ state + '">' + state + '</span>' : null;
+        var shortState = self.get('shortState')[state];
+        return summary[state] ? '<span class="alert-state-single-host label alert-state-' + state + '">' + shortState + '</span>' : null;
       }).compact().join(' ');
     } else if (hostCnt == 0) {
-      // penging
-      var state = 'PENDING';
-      return '<span class="alert-state-single-host label alert-state-'+ state + '">' + state + '</span>';
+      // none
+      return '<span class="alert-state-single-host label alert-state-PENDING">NONE</span>';
     }
     return null;
   }.property('summary'),
@@ -185,7 +186,7 @@ App.AlertDefinition = DS.Model.extend({
    * cluster services and other services into a common display-name.
    * @see App.AlertInstance#serviceDisplayName()
    */
-  serviceDisplayName : function() {
+  serviceDisplayName: function () {
     var serviceName = this.get('service.displayName');
     if (!serviceName) {
       serviceName = this.get('serviceName');
@@ -214,8 +215,13 @@ App.AlertDefinition = DS.Model.extend({
   severityOrder: ['CRITICAL', 'WARNING', 'OK', 'UNKNOWN', 'PENDING'],
   order: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
 
-  // todo: in future be mapped from server response
-  thresholds: '5-10'
+  shortState: {
+    'CRITICAL': 'CRIT',
+    'WARNING': 'WARN',
+    'OK': 'OK',
+    'UNKNOWN': 'UNKWN',
+    'PENDING': 'NONE'
+  }
 });
 
 App.AlertDefinition.reopenClass({

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/models/alert_instance.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/models/alert_instance.js b/ambari-web/app/models/alert_instance.js
index 5345262..30aff05 100644
--- a/ambari-web/app/models/alert_instance.js
+++ b/ambari-web/app/models/alert_instance.js
@@ -43,7 +43,8 @@ App.AlertInstance = DS.Model.extend({
    */
   status: function () {
     var state = this.get('state');
-    return '<span class="label alert-state-single-host alert-state-' + state + '">' + state + '</span>';
+    var shortState = this.get('shortState')[state];
+    return '<span class="label alert-state-single-host alert-state-' + state + '">' + shortState + '</span>';
   }.property('state'),
 
   /**
@@ -52,7 +53,7 @@ App.AlertInstance = DS.Model.extend({
    * cluster services and other services into a common display-name.
    * @see App.AlertDefinition#serviceDisplayName()
    */
-  serviceDisplayName : function() {
+  serviceDisplayName: function () {
     var serviceName = this.get('service.displayName');
     if (!serviceName) {
       serviceName = this.get('serviceName');
@@ -67,7 +68,7 @@ App.AlertInstance = DS.Model.extend({
    * Formatted timestamp for latest instance triggering
    * @type {string}
    */
-  lastCheckedFormatted: function() {
+  lastCheckedFormatted: function () {
     return dateUtils.dateFormat(this.get('latestTimestamp'));
   }.property('latestTimestamp'),
 
@@ -75,7 +76,7 @@ App.AlertInstance = DS.Model.extend({
    * Formatted timestamp for latest instance triggering
    * @type {string}
    */
-  lastTriggeredFormatted: function() {
+  lastTriggeredFormatted: function () {
     return dateUtils.dateFormat(this.get('originalTimestamp'));
   }.property('originalTimestamp'),
 
@@ -85,10 +86,10 @@ App.AlertInstance = DS.Model.extend({
    */
   lastTriggeredAgoFormatted: function () {
     var lastTriggered = this.get('originalTimestamp');
-    return lastTriggered ? $.timeago(new Date(lastTriggered)): '';
+    return lastTriggered ? $.timeago(new Date(lastTriggered)) : '';
   }.property('originalTimestamp'),
 
-  lastTriggeredVerboseDisplay : function() {
+  lastTriggeredVerboseDisplay: function () {
     var originalTimestamp = this.get('originalTimestamp');
     var latestTimestamp = this.get('latestTimestamp');
     return Em.I18n.t('models.alert_instance.tiggered.verbose').format(
@@ -106,18 +107,45 @@ App.AlertInstance = DS.Model.extend({
     var previousPrefixAgo = $.timeago.settings.strings.prefixAgo;
     $.timeago.settings.strings.suffixAgo = null;
     $.timeago.settings.strings.prefixAgo = 'for';
-    var triggeredFor = lastTriggered ? $.timeago(new Date(lastTriggered)): '';
+    var triggeredFor = lastTriggered ? $.timeago(new Date(lastTriggered)) : '';
     $.timeago.settings.strings.suffixAgo = previousSuffixAgo;
     $.timeago.settings.strings.prefixAgo = previousPrefixAgo;
     return triggeredFor;
   }.property('originalTimestamp'),
 
   /**
+   * Formatted lastChecked and lastTriggered timestamp
+   * @returns {string}
+   */
+  statusChangedAndLastCheckedFormatted: function () {
+    var lastCheckedFormatted = this.get('lastCheckedFormatted');
+    var lastTriggeredFormatted = this.get('lastTriggeredFormatted');
+    return Em.I18n.t('models.alert_definition.triggered.checked').format(lastCheckedFormatted, lastTriggeredFormatted);
+  }.property('lastCheckedFormatted', 'lastTriggeredFormatted'),
+
+  /**
    * List of css-classes for alert instance status
    * @type {object}
    */
   typeIcons: {
     'DISABLED': 'icon-off'
+  },
+
+  /**
+   * Define if definition serviceName is Ambari
+   * Used in some logic in templates to distinguish definitions with Ambari serviceName
+   * @returns {boolean}
+   */
+  isAmbariServiceName: function () {
+    return this.get('serviceName') === 'AMBARI';
+  }.property('serviceName'),
+
+  shortState: {
+    'CRITICAL': 'CRIT',
+    'WARNING': 'WARN',
+    'OK': 'OK',
+    'UNKNOWN': 'UNKWN',
+    'PENDING': 'NONE'
   }
 });
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/routes/main.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/routes/main.js b/ambari-web/app/routes/main.js
index 34edf7e..6f9613d 100644
--- a/ambari-web/app/routes/main.js
+++ b/ambari-web/app/routes/main.js
@@ -273,7 +273,7 @@ module.exports = Em.Route.extend({
         connectOutlets: function (router, context) {
           router.get('mainHostDetailsController').connectOutlet('mainHostAlerts');
         },
-        exit: function(router) {
+        exit: function (router) {
           router.set('mainAlertInstancesController.isUpdating', false);
         }
       }),
@@ -335,7 +335,7 @@ module.exports = Em.Route.extend({
         router.get('mainController').connectOutlet('mainAlertDefinitionDetails', alertDefinition);
       },
 
-      exit: function(router) {
+      exit: function (router) {
         router.set('mainAlertInstancesController.isUpdating', false);
       }
     }),
@@ -507,7 +507,7 @@ module.exports = Em.Route.extend({
           router.get('mainAdminController').connectOutlet('mainAdminKerberos');
         }
       }),
-      adminAddKerberos:  require('routes/add_kerberos_routes')
+      adminAddKerberos: require('routes/add_kerberos_routes')
     }),
 
     stackAndUpgrade: Em.Route.extend({
@@ -524,7 +524,7 @@ module.exports = Em.Route.extend({
       index: Em.Route.extend({
         route: '/',
         connectOutlets: function (router) {
-          if(App.get('supports.stackUpgrade')) {
+          if (App.get('supports.stackUpgrade')) {
             router.set('mainAdminController.category', "stackVersions");
             router.get('mainAdminController').connectOutlet('mainStackVersions');
           }
@@ -539,7 +539,7 @@ module.exports = Em.Route.extend({
       update: Em.Route.extend({
         route: '/updates',
         connectOutlets: function (router) {
-          if(App.get('supports.stackUpgrade')) {
+          if (App.get('supports.stackUpgrade')) {
             router.set('mainAdminController.category', "stackVersions");
             router.get('mainAdminController').connectOutlet('repoVersions');
           }
@@ -726,5 +726,15 @@ module.exports = Em.Route.extend({
   },
   gotoAlertDetails: function (router, event) {
     router.transitionTo('alerts.alertDetails', event.context);
+  },
+
+  /**
+   * Open summary page of the selected service
+   * @param {object} event
+   * @method routeToService
+   */
+  routeToService: function (router, event) {
+    var service = event.context;
+    router.transitionTo('main.services.service.summary', service);
   }
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/styles/alerts.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/alerts.less b/ambari-web/app/styles/alerts.less
index 6c026e7..efc18f4 100644
--- a/ambari-web/app/styles/alerts.less
+++ b/ambari-web/app/styles/alerts.less
@@ -145,6 +145,8 @@
 
   .type-icon {
     margin-right: 5px;
+    width: 10px;
+    display: inline-block;
   }
 }
 
@@ -158,13 +160,13 @@
   .col1,
   td:first-child + td,
   th:first-child + th {
-    width: 20%;
+    width: 23%;
   }
 
   .col2,
   td:first-child + td + td,
   th:first-child + th + th {
-    width: 10%
+    width: 7%
   }
 
   .col3,
@@ -317,6 +319,14 @@
       width: 30%;
     }
   }
+
+  .badge-container {
+    height: 26px;
+    .alert-threshold-badge {
+      line-height: 26px;
+      height: 26px;
+    }
+  }
 }
 
 #host-alerts-table {
@@ -329,7 +339,7 @@
   .col0,
   td:first-child,
   th:first-child {
-    width: 10%;
+    width: 15%;
     .filter-input-width {
       width: 80%;
     }
@@ -338,7 +348,7 @@
   .col1,
   td:first-child + td,
   th:first-child + th {
-    width: 25%;
+    width: 30%;
     .filter-input-width {
       width: 90%;
     }
@@ -347,23 +357,14 @@
   .col2,
   td:first-child + td + td,
   th:first-child + th + th {
-    width: 15%;
+    width: 20%;
     .filter-input-width {
-      width: 80%;
+      width: inherit;
     }
   }
   .col3,
   td:first-child + td + td + td,
   th:first-child + th + th + th {
-    width: 15%;
-    .filter-input-width {
-      width: inherit;
-    }
-  }
-
-  .col4,
-  td:first-child + td + td + td + td,
-  th:first-child + th + th + th + th {
     width: 35%;
   }
 
@@ -506,6 +507,11 @@
     }
   }
 }
+
+.service-alerts {
+  max-height: 246px;
+}
+
 .alerts-popup-wrap {
   .top-wrap {
     width: 100%;
@@ -522,9 +528,6 @@
       width: 31%;
       padding-left: 10px;
     }
-    .last-triggered-top {
-      padding-left: 10px;
-    }
     .status-top,.name-top,.service-top,.last-triggered-top {
       float: left;
       text-align: left;
@@ -547,7 +550,6 @@
         min-width: 20px;
       }
       .name-text {
-        padding-left: 5px;
         float: left;
         width: 33%;
       }

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index b6809bb..c9556d1 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -2517,7 +2517,6 @@ width:100%;
 }
 .alerts {
   margin: 0px;
-  max-height: 500px;
   overflow-y: auto;
   li {
     border-bottom: 1px solid #eee;

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/common/alerts_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/alerts_popup.hbs b/ambari-web/app/templates/common/alerts_popup.hbs
index 44753dd..18fa3eb 100644
--- a/ambari-web/app/templates/common/alerts_popup.hbs
+++ b/ambari-web/app/templates/common/alerts_popup.hbs
@@ -22,7 +22,7 @@
       <div class="top-wrap">
         <div class="service-top">{{t alerts.definition.details.serviceHost}}</div>
         <div class="name-top">{{t alerts.fastAccess.popup.body.name}}</div>
-        <div class="last-triggered-top">{{t alerts.table.header.triggeredOn}}</div>
+        <div class="last-triggered-top">{{t common.status}}</div>
       </div>
         <div id="alert-info">
           {{#if view.isAlertEmptyList}}
@@ -50,9 +50,6 @@
             </div>
           {{/each}}
         {{/if}}
-        <div class="show-more" {{action "showMore" target="view"}}>
-          <a href="#">{{t alerts.fastAccess.popup.body.showmore}}</a>
-        </div>
       </div>
     </div>
   {{else}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/main/alerts/configs.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts/configs.hbs b/ambari-web/app/templates/main/alerts/configs.hbs
index 88911b6..b7e2b7f 100644
--- a/ambari-web/app/templates/main/alerts/configs.hbs
+++ b/ambari-web/app/templates/main/alerts/configs.hbs
@@ -17,7 +17,7 @@
 }}
 <form class="form-horizontal alert-configs">
   {{#each property in controller.configs}}
-    <div {{bindAttr class=":control-group property.name"}}>
+    <div {{bindAttr class=":control-group property.name property.isValid::error"}}>
       {{#if property.isPreLabeled}}
         <label {{bindAttr class=":control-label property.isShifted:shifted"}}>{{property.label}}</label>
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/main/alerts/configs/alert_config_threshold.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts/configs/alert_config_threshold.hbs b/ambari-web/app/templates/main/alerts/configs/alert_config_threshold.hbs
index 14d1c35..f4d68ce 100644
--- a/ambari-web/app/templates/main/alerts/configs/alert_config_threshold.hbs
+++ b/ambari-web/app/templates/main/alerts/configs/alert_config_threshold.hbs
@@ -16,8 +16,8 @@
 * limitations under the License.
 }}
 
-<div class="control-group">
-  <div class="span3"><span {{bindAttr class="view.property.badgeCssClass :alert-state-single-host :label"}}>{{view.property.badge}}</span>&nbsp;</div>
+<div>
+  <div class="span2 badge-container"><span {{bindAttr class="view.property.badgeCssClass :alert-threshold-badge :alert-state-single-host :label"}}>{{view.property.badge}}</span>&nbsp;</div>
   {{#if view.property.showInputForValue}}
     <div {{bindAttr class=":span2 view.property.valueMetric:input-append"}}>
         {{view Em.TextField valueBinding="view.property.displayValue" disabledBinding="view.property.isDisabled" class="span11"}}
@@ -26,7 +26,7 @@
         {{/if}}
     </div>
   {{/if}}
-  <div {{bindAttr class=":alert-text-input view.property.showInputForValue:span7:span9"}}>
+  <div {{bindAttr class=":alert-text-input view.property.showInputForValue:span8:span10"}}>
     {{#if view.property.showInputForText}}
       {{view Em.TextField valueBinding="view.property.text" disabledBinding="view.property.isDisabled"}}
     {{/if}}

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/main/alerts/definition_details.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts/definition_details.hbs b/ambari-web/app/templates/main/alerts/definition_details.hbs
index c959caf..64218ad 100644
--- a/ambari-web/app/templates/main/alerts/definition_details.hbs
+++ b/ambari-web/app/templates/main/alerts/definition_details.hbs
@@ -60,7 +60,7 @@
           {{#isAccessible ADMIN}}
             {{#unless App.router.mainAlertDefinitionConfigsController.canEdit}}
               <a {{action editConfigs target="App.router.mainAlertDefinitionConfigsController"}} class="pull-right edit-link">
-                <strong>{{t common.edit}}</strong>
+                {{t common.edit}}
               </a>
             {{/unless}}
           {{/isAccessible}}
@@ -70,7 +70,7 @@
         {{#if App.router.mainAlertDefinitionConfigsController.canEdit}}
           <div class="edit-buttons">
             <button {{action cancelEditConfigs target="App.router.mainAlertDefinitionConfigsController"}} class="btn">{{t common.cancel}}</button>
-            <button {{bindAttr disabled="controller.editing.thresholds.isError"}} {{action saveConfigs target="App.router.mainAlertDefinitionConfigsController"}}
+            <button {{bindAttr disabled="App.router.mainAlertDefinitionConfigsController.hasErrors"}} {{action saveConfigs target="App.router.mainAlertDefinitionConfigsController"}}
                 class="btn btn-primary">{{t common.save}}
             </button>
           </div>
@@ -167,13 +167,13 @@
 
       {{#if App.router.mainAlertInstancesController.isLoaded}}
 
-      <table class="table table-bordered table-striped alerts-table" id="alert-instances-table">
+      <table class="table advanced-header-table table-bordered table-striped alerts-table" id="alert-instances-table">
         <thead>
         <tr>
           <th class="first">{{t alerts.definition.details.serviceHost}}</th>
           <th>{{t common.status}}</th>
           <th>{{t alerts.definition.details.24-hour}}</th>
-          <th>{{t alerts.table.header.text}}</th>
+          <th>{{t alerts.table.header.check.response}}</th>
         </tr>
         </thead>
         <tbody>

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/main/host/details/host_component.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/details/host_component.hbs b/ambari-web/app/templates/main/host/details/host_component.hbs
index 1151493..5a2a040 100644
--- a/ambari-web/app/templates/main/host/details/host_component.hbs
+++ b/ambari-web/app/templates/main/host/details/host_component.hbs
@@ -32,7 +32,7 @@
     {{component.displayName}}
   {{/if}}
   &nbsp;/&nbsp;
-  <a href="#" {{action routeToService component.service target="controller"}}>{{component.service.displayName}}</a>
+  <a href="#" {{action routeToService component.service}}>{{component.service.displayName}}</a>
   &nbsp;
   {{#if component.staleConfigs}}
     <span class="text-warning icon-refresh"></span>

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/templates/main/host/host_alerts.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host/host_alerts.hbs b/ambari-web/app/templates/main/host/host_alerts.hbs
index d1834af..407cca8 100644
--- a/ambari-web/app/templates/main/host/host_alerts.hbs
+++ b/ambari-web/app/templates/main/host/host_alerts.hbs
@@ -27,14 +27,12 @@
       {{#view view.sortView classNames="label-row" contentBinding="view.filteredContent"}}
         {{view view.parentView.serviceSort class="first service-sorting"}}
         {{view view.parentView.nameSort class="name-sorting"}}
-        {{view view.parentView.lastCheckedSort class="last-checked-sorting"}}
         {{view view.parentView.statusSort class="status-sorting"}}
         {{view view.parentView.textSort class="text-sorting"}}
       {{/view}}
     <tr class="filter-row">
       <th class="first">{{view view.serviceFilterView class="service-filter"}}</th>
       <th>{{view view.nameFilterView class="name-filter"}}</th>
-      <th>{{view view.checkedFilterView class="checked-filter"}}</th>
       <th>{{view view.stateFilterView class="status-filter"}}</th>
       <th>{{view view.textView class="text-filter"}}</th>
     </tr>
@@ -43,17 +41,24 @@
     {{#if view.pageContent}}
       {{#each alertInstance in view.pageContent}}
         <tr>
-          <td class="first">{{alertInstance.serviceDisplayName}}</td>
-          <td>{{alertInstance.label}}</td>
-          <td>{{alertInstance.lastCheckedFormatted}}</td>
-          <td>{{{alertInstance.status}}} <time class="timeago" {{bindAttr data-original-title="alertInstance.lastTriggeredFormatted"}}>{{alertInstance.lastTriggeredForFormatted}}</time></td>
+          <td class="first">
+            {{#if alertInstance.isAmbariServiceName}}
+              {{alertInstance.serviceDisplayName}}
+            {{else}}
+              <a href="#" {{action routeToService alertInstance.service}}>{{alertInstance.serviceDisplayName}}</a>
+            {{/if}}
+          </td>
+          <td>
+            <a href="#" {{action routeToAlertDefinition alertInstance.definitionId target="controller"}}>{{alertInstance.label}}</a>
+          </td>
+          <td>{{{alertInstance.status}}} <time class="timeago" {{bindAttr data-original-title="alertInstance.statusChangedAndLastCheckedFormatted"}}>{{alertInstance.lastTriggeredForFormatted}}</time></td>
           <td><span class="alert-text" {{bindAttr data-original-title="alertInstance.text"}} class="alert-text">{{alertInstance.text}}</span></td>
         </tr>
       {{/each}}
     {{else}}
       <tr>
         <td class="first"></td>
-        <td colspan="4">
+        <td colspan="3">
           {{t alerts.table.noAlerts}}
         </td>
       </tr>

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/views/main/host/host_alerts_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/host_alerts_view.js b/ambari-web/app/views/main/host/host_alerts_view.js
index 03f3463..d06cb97 100644
--- a/ambari-web/app/views/main/host/host_alerts_view.js
+++ b/ambari-web/app/views/main/host/host_alerts_view.js
@@ -18,12 +18,12 @@
 
 var App = require('app');
 var filters = require('views/common/filter_view'),
-  sort = require('views/common/sort_view');
+    sort = require('views/common/sort_view');
 
 App.MainHostAlertsView = App.TableView.extend({
   templateName: require('templates/main/host/host_alerts'),
 
-  content: function() {
+  content: function () {
     return this.get('controller.content');
   }.property('controller.content.@each'),
 
@@ -55,7 +55,7 @@ App.MainHostAlertsView = App.TableView.extend({
   nameSort: sort.fieldView.extend({
     column: 2,
     name: 'label',
-    displayName: Em.I18n.t('common.name')
+    displayName: Em.I18n.t('alerts.definition.name')
   }),
 
   /**
@@ -81,24 +81,13 @@ App.MainHostAlertsView = App.TableView.extend({
   }),
 
   /**
-   * Sorting header for <label>alertDefinition.lastTriggeredSort</label>
-   * @type {Em.View}
-   */
-  lastCheckedSort: sort.fieldView.extend({
-    column: 3,
-    name: 'latestTimestamp',
-    displayName: Em.I18n.t('alerts.table.header.lastChecked'),
-    type: 'number'
-  }),
-
-  /**
    * Sorting header for <label>alertDefinition.label</label>
    * @type {Em.View}
    */
   textSort: sort.fieldView.extend({
     column: 5,
     name: 'text',
-    displayName: Em.I18n.t('alerts.table.header.text')
+    displayName: Em.I18n.t('alerts.table.header.check.response')
   }),
 
 
@@ -109,7 +98,7 @@ App.MainHostAlertsView = App.TableView.extend({
   nameFilterView: filters.createTextView({
     column: 2,
     fieldType: 'filter-input-width',
-    onChangeValue: function(){
+    onChangeValue: function () {
       this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'string');
     }
   }),
@@ -177,51 +166,6 @@ App.MainHostAlertsView = App.TableView.extend({
   }),
 
   /**
-   * Filtering header for <label>alertDefinition.lastTriggered</label>
-   * @type {Em.View}
-   */
-  checkedFilterView: filters.createSelectView({
-    column: 3,
-    appliedEmptyValue: ["", ""],
-    fieldType: 'filter-input-width,modified-filter',
-    content: [
-      {
-        value: 'Any',
-        label: Em.I18n.t('any')
-      },
-      {
-        value: 'Past 1 hour',
-        label: 'Past 1 hour'
-      },
-      {
-        value: 'Past 1 Day',
-        label: 'Past 1 Day'
-      },
-      {
-        value: 'Past 2 Days',
-        label: 'Past 2 Days'
-      },
-      {
-        value: 'Past 7 Days',
-        label: 'Past 7 Days'
-      },
-      {
-        value: 'Past 14 Days',
-        label: 'Past 14 Days'
-      },
-      {
-        value: 'Past 30 Days',
-        label: 'Past 30 Days'
-      }
-    ],
-    emptyValue: 'Any',
-    onChangeValue: function () {
-      this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'date');
-    }
-  }),
-
-
-  /**
    * Filtering header for <label>alertDefinition.service.serviceName</label>
    * @type {Em.View}
    */

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/app/views/main/host/menu.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host/menu.js b/ambari-web/app/views/main/host/menu.js
index 9a7fbae..15700fb 100644
--- a/ambari-web/app/views/main/host/menu.js
+++ b/ambari-web/app/views/main/host/menu.js
@@ -23,6 +23,19 @@ App.MainHostMenuView = Em.CollectionView.extend({
   classNames: ["nav", "nav-tabs"],
   host: null,
   content: function () {
+    //count Alerts badge text and class
+
+    var criticalWarningCount = this.get('host.criticalWarningAlertsCount');
+    var criticalCount = this.get('host.alertsSummary.CRITICAL');
+    var warningCount = this.get('host.alertsSummary.WARNING');
+    var badgeText = "" + criticalWarningCount;
+    var badgeClasses = "label ";
+    if (criticalCount > 0) {
+      badgeClasses += "label-important";
+    } else if (warningCount > 0) {
+      badgeClasses += "label-warning ";
+    }
+
     var array = [
       {
         label: Em.I18n.t('common.summary'),
@@ -31,6 +44,12 @@ App.MainHostMenuView = Em.CollectionView.extend({
       {
         label: Em.I18n.t('common.configs'),
         routing: 'configs'
+      },
+      {
+        label: Em.I18n.t('hosts.host.alerts.label'),
+        routing: 'alerts',
+        badgeText: badgeText,
+        badgeClasses: badgeClasses
       }
       /* { label:'Audit', routing:'audit'} */
     ];
@@ -40,61 +59,34 @@ App.MainHostMenuView = Em.CollectionView.extend({
         routing: 'stackVersions'
       });
     }
-    array.push({
-      label: 'Alerts',
-      routing: 'alerts',
-      badgeText: '0',
-      badgeClasses: 'label '
-    });
     return array;
-  }.property(''),
+  }.property('host.alertsSummary.CRITICAL', 'host.alertsSummary.WARNING', 'host.criticalWarningAlertsCount'),
 
-  init: function(){ this._super(); this.activateView(); },
+  init: function () {
+    this._super();
+    this.activateView();
+  },
 
   activateView: function () {
     var defaultRoute = App.router.get('currentState.name') || "summary";
     $.each(this._childViews, function () {
       this.set('active', (this.get('content.routing') == defaultRoute ? "active" : ""));
     });
-    this.hostAlertsObserver();
   },
 
-  deactivateChildViews: function() {
-    $.each(this._childViews, function(){
+  deactivateChildViews: function () {
+    $.each(this._childViews, function () {
       this.set('active', "");
     });
   },
 
-  hostAlertsObserver : function() {
-    var criticalWarningCount = this.get('host.criticalWarningAlertsCount');
-    var criticalCount = this.get('host.alertsSummary.CRITICAL');
-    var warningCount = this.get('host.alertsSummary.WARNING');
-    var badgeText = "" + criticalWarningCount;
-    var badgeClasses = "label ";
-    if (criticalCount > 0) {
-      badgeClasses += "label-important";
-    } else if (warningCount > 0){
-      badgeClasses += "label-warning ";
-    }
-    // Update content
-    var content = this.get('content');
-    if (content) {
-      content.forEach(function(item) {
-        if (item.label == 'Alerts' && (item.badgeText !== badgeText || item.badgeClasses != badgeClasses)) {
-          Ember.set(item, 'badgeText', badgeText);
-          Ember.set(item, 'badgeClasses', badgeClasses);
-        }
-      });
-    }
-  }.observes('host.alertsSummary.CRITICAL', 'host.alertsSummary.WARNING', 'host.criticalWarningAlertsCount'),
-
   itemViewClass: Em.View.extend({
     classNameBindings: ["active"],
     active: "",
     template: Ember.Handlebars.compile('<a {{action hostNavigate view.content.routing }} href="#"> {{unbound view.content.label}} ' +
-        '{{#if view.content.badgeText}} '+
-          '<span {{bindAttr class="view.content.badgeClasses"}}> '+
-            '{{view.content.badgeText}}'+
-          '</span>  {{/if}}</a>')
+    '{{#if view.content.badgeText}} ' +
+    '<span {{bindAttr class="view.content.badgeClasses"}}> ' +
+    '{{view.content.badgeText}}' +
+    '</span>  {{/if}}</a>')
   })
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/test/controllers/main/host/details_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/host/details_test.js b/ambari-web/test/controllers/main/host/details_test.js
index 489fbef..a36267b 100644
--- a/ambari-web/test/controllers/main/host/details_test.js
+++ b/ambari-web/test/controllers/main/host/details_test.js
@@ -50,15 +50,6 @@ describe('App.MainHostDetailsController', function () {
     });
   });
 
-  describe('#routeToService()', function () {
-    it('transiotion to dashboard', function () {
-      sinon.stub(App.router, 'transitionTo', Em.K);
-      controller.routeToService({context: {'service': 'service'}});
-      expect(App.router.transitionTo.calledWith('main.services.service.summary', {'service': 'service'})).to.be.true;
-      App.router.transitionTo.restore();
-    });
-  });
-
   describe('#startComponent()', function () {
     it('call sendComponentCommand', function () {
       var event = {

http://git-wip-us.apache.org/repos/asf/ambari/blob/da7643e5/ambari-web/test/models/alert_definition_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/models/alert_definition_test.js b/ambari-web/test/models/alert_definition_test.js
index 65da5f9..a5278a0 100644
--- a/ambari-web/test/models/alert_definition_test.js
+++ b/ambari-web/test/models/alert_definition_test.js
@@ -36,17 +36,17 @@ describe('App.AlertDefinition', function () {
       {
         summary: {OK: 1, UNKNOWN: 1, WARNING: 2},
         m: 'No CRITICAL',
-        e: '<span class="label alert-state-OK">OK ( 1 )</span> ' +
-        '<span class="label alert-state-WARNING">WARN ( 2 )</span> ' +
-        '<span class="label alert-state-UNKNOWN">UNKN ( 1 )</span>'
+        e: '<span class="alert-state-single-host label alert-state-OK">OK (1)</span> ' +
+        '<span class="alert-state-single-host label alert-state-WARNING">WARN (2)</span> ' +
+        '<span class="alert-state-single-host label alert-state-UNKNOWN">UNKWN (1)</span>'
       },
       {
         summary: {WARNING: 2, CRITICAL: 3, UNKNOWN: 1, OK: 1},
         m: 'All states exists',
-        e: '<span class="label alert-state-OK">OK ( 1 )</span> ' +
-        '<span class="label alert-state-WARNING">WARN ( 2 )</span> ' +
-        '<span class="label alert-state-CRITICAL">CRIT ( 3 )</span> ' +
-        '<span class="label alert-state-UNKNOWN">UNKN ( 1 )</span>'
+        e: '<span class="alert-state-single-host label alert-state-OK">OK (1)</span> ' +
+        '<span class="alert-state-single-host label alert-state-WARNING">WARN (2)</span> ' +
+        '<span class="alert-state-single-host label alert-state-CRITICAL">CRIT (3)</span> ' +
+        '<span class="alert-state-single-host label alert-state-UNKNOWN">UNKWN (1)</span>'
       },
       {
         summary: {OK: 1},
@@ -56,7 +56,7 @@ describe('App.AlertDefinition', function () {
       {
         summary: {},
         m: 'Pending',
-        e: '<span class="alert-state-single-host label alert-state-PENDING">PENDING</span>'
+        e: '<span class="alert-state-single-host label alert-state-PENDING">NONE</span>'
       }
     ]).forEach(function (test) {
       it(test.m, function () {


Mime
View raw message