You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by xi...@apache.org on 2014/11/26 01:34:46 UTC
[2/2] ambari git commit: AMBARI-8448. Alerts UI: Cluster level
alert-definitions table has multiple issues.(xiwang)
AMBARI-8448. Alerts UI: Cluster level alert-definitions table has multiple issues.(xiwang)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3af54a1f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3af54a1f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3af54a1f
Branch: refs/heads/trunk
Commit: 3af54a1ff275df89e6ec24cd5a7f8dd9a4350fe1
Parents: 80ffaa9
Author: Xi Wang <xi...@apache.org>
Authored: Mon Nov 24 17:52:07 2014 -0800
Committer: Xi Wang <xi...@apache.org>
Committed: Tue Nov 25 16:20:05 2014 -0800
----------------------------------------------------------------------
.../main/alert_definitions_controller.js | 25 +++-
ambari-web/app/messages.js | 11 +-
ambari-web/app/models/alert_definition.js | 4 +
ambari-web/app/styles/alerts.less | 110 +++++++++++++++++-
ambari-web/app/styles/application.less | 101 +----------------
ambari-web/app/templates/main/alerts.hbs | 31 +++--
ambari-web/app/views/common/filter_view.js | 5 +
ambari-web/app/views/common/sort_view.js | 2 +-
.../app/views/main/alert_definitions_view.js | 113 +++++++++++++++----
.../main/alert_definitions_controller_test.js | 4 +-
10 files changed, 268 insertions(+), 138 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/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 88c9ff7..86f673d 100644
--- a/ambari-web/app/controllers/main/alert_definitions_controller.js
+++ b/ambari-web/app/controllers/main/alert_definitions_controller.js
@@ -46,13 +46,30 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({
}.property('mapperTimestamp'),
/**
+ * Enable/disable alertDefinition confirmation popup
+ * @param {object} event
+ * @method toggleState
+ */
+ toggleState: function(event) {
+ var alertDefinition = event.context;
+ var self = this;
+ var bodyMessage = Em.Object.create({
+ confirmMsg: alertDefinition.get('enabled') ? Em.I18n.t('alerts.table.state.enabled.confirm.msg') : Em.I18n.t('alerts.table.state.disabled.confirm.msg'),
+ confirmButton: alertDefinition.get('enabled') ? Em.I18n.t('alerts.table.state.enabled.confirm.btn') : Em.I18n.t('alerts.table.state.disabled.confirm.btn')
+ });
+
+ return App.showConfirmationFeedBackPopup(function (query) {
+ self.toggleDefinitionState (alertDefinition);
+ }, bodyMessage);
+ },
+
+ /**
* Enable/disable alertDefinition
- * @param {object} e
+ * @param {object} alertDefinition
* @returns {$.ajax}
- * @method toggleState
+ * @method toggleDefinitionState
*/
- toggleState: function(e) {
- var alertDefinition = e.context;
+ toggleDefinitionState: function(alertDefinition) {
return App.ajax.send({
name: 'alerts.update_alert_definition',
sender: this,
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 5a7ff55..b9e7a92 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -855,8 +855,17 @@ Em.I18n.translations = {
'alerts.table.noAlerts': 'No Alerts to display',
'alerts.table.header.lastTriggered': 'Last Triggered',
+ 'alerts.table.header.definitionName': 'Definition Name',
'alerts.table.header.notification': 'Notification',
- 'alerts.filters.filteredAlertsInfo': '{0} of {1} alerts showing',
+ 'alerts.table.state.enabled': 'Enabled',
+ 'alerts.table.state.disabled': 'Disabled',
+ 'alerts.table.state.enabled.tooltip': 'Disable this alert definition',
+ 'alerts.table.state.disabled.tooltip': 'Enable this alert definition',
+ 'alerts.table.state.enabled.confirm.msg': 'You are about to Disable this alert definition.',
+ 'alerts.table.state.disabled.confirm.msg': 'You are about to Enable this alert definition.',
+ '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.thresholds': 'Thresholds',
'alerts.definition.details.enable': 'Enable',
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/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 9d5f52c..3d53156 100644
--- a/ambari-web/app/models/alert_definition.js
+++ b/ambari-web/app/models/alert_definition.js
@@ -110,6 +110,10 @@ App.AlertDefinition = DS.Model.extend({
'UNKNOWN': 'icon-question-sign'
},
+ /**
+ * Sort on load definitions by this severity order
+ */
+ severityOrder: ['CRITICAL', 'WARNING', 'OK', 'UNKNOWN', 'PENDING'],
order: ['OK', 'WARNING', 'CRITICAL', 'UNKNOWN'],
// todo: in future be mapped from server response
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/styles/alerts.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/alerts.less b/ambari-web/app/styles/alerts.less
index af69fe8..e9783cb 100644
--- a/ambari-web/app/styles/alerts.less
+++ b/ambari-web/app/styles/alerts.less
@@ -81,7 +81,7 @@
th:first-child + th {
width: 18%;
.filter-input-width {
- width: 90%;
+ width: 80%;
}
}
@@ -90,19 +90,25 @@
th:first-child + th + th {
width: 17%;
.filter-input-width {
- width: 90%;
+ width: 80%;
}
}
.col3,
td:first-child + td + td + td,
th:first-child + th + th + th {
- width: 25%
+ width: 20%;
+ .filter-input-width {
+ width: 80%;
+ }
}
.col4,
td:first-child + td + td + td + td,
th:first-child + th + th + th + th {
- width: 10%;
+ width: 13%;
+ .filter-input-width {
+ width: 80%;
+ }
}
}
@@ -267,4 +273,98 @@
th:first-child + th + th + th + th {
width: 20%;
}
-}
\ No newline at end of file
+}
+
+/*****start styles for alerts popup*****/
+.alerts-popup {
+ .modal-body, .modal-footer, .modal-header {
+ min-width: 600px;
+ }
+ #alert-info {
+ .log-list-wrap:hover {
+ background-color: #e6e6e6;
+ }
+ }
+}
+.alerts-popup-wrap {
+ .top-wrap {
+ width: 100%;
+ border-bottom: 1px solid #CCC;
+ text-align: center;
+ font-size: 15px;
+ padding: 0 0 20px 0;
+ height: 20px;
+ .status-top {
+ width: 10%;
+ padding-left: 20px;
+ }
+ .name-top {
+ width: 40%;
+ padding-left: 110px;
+ }
+ .service-top {
+ width: 15%;
+ padding-left: 5px;
+ }
+ .last-triggered-top {
+ width: 20%;
+ padding-left: 5px;
+ }
+ .status-top,.name-top,.service-top,.last-triggered-top {
+ float: left;
+ text-align: left;
+ }
+ .select-wrap {
+ float: right;
+ margin-top: -8px;
+ select {
+ width: 140px;
+ }
+ }
+ }
+ #alert-info{
+ overflow: auto;
+ max-height: 340px;
+ width: 100%;
+ .alert-list-wrap {
+ padding: 10px 10px 10px 20px;
+ border-top: 1px solid #CCC;
+ border-bottom: 1px solid #CCC;
+ }
+ .alert-list-line-cursor{
+ width: 100%;
+ min-height: 20px;
+ .status-icon {
+ padding-left: 5px;
+ float: left;
+ width: 10%;
+ min-width: 30px;
+ }
+ .name-text {
+ padding-left: 10px;
+ width: 40%;
+ float: left;
+ }
+ .service-text {
+ padding-left: 5px;
+ width: 15%;
+ float: left;
+ }
+ .last-triggered-text {
+ padding-left: 5px;
+ color: #808080;
+ font-size: 12px;
+ }
+ }
+ .show-more {
+ width: 98.8%;
+ min-height: 20px;
+ cursor: pointer;
+ border-top: 1px solid #CCC;
+ text-align: center;
+ padding: 10px 10px 10px 0px;
+ font-size: 16px;
+ }
+ }
+}
+/*****end styles for alert popup*****/
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index ab0558b..a69645b 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -1450,6 +1450,9 @@ a:focus {
-webkit-border-top-left-radius: 0px;
border-top-left-radius: 0px;
-moz-border-radius-topleft: 0px;
+ -webkit-border-top-right-radius: 0px;
+ border-top-right-radius: 0px;
+ -moz-border-radius-topright: 0px;
}
}
/*****end styles for table*****/
@@ -2098,101 +2101,6 @@ width:100%;
}
}
-/*****start styles for alerts popup*****/
-.alerts-popup {
- .modal-body, .modal-footer, .modal-header {
- min-width: 600px;
- }
- #alert-info {
- .log-list-wrap:hover {
- background-color: #e6e6e6;
- }
- }
-}
-.alerts-popup-wrap {
- .top-wrap {
- width: 100%;
- border-bottom: 1px solid #CCC;
- text-align: center;
- font-size: 15px;
- padding: 0 0 20px 0;
- height: 20px;
- .status-top {
- width: 10%;
- padding-left: 20px;
- }
- .name-top {
- width: 40%;
- padding-left: 110px;
- }
- .service-top {
- width: 15%;
- padding-left: 5px;
- }
- .last-triggered-top {
- width: 20%;
- padding-left: 5px;
- }
- .status-top,.name-top,.service-top,.last-triggered-top {
- float: left;
- text-align: left;
- }
- .select-wrap {
- float: right;
- margin-top: -8px;
- select {
- width: 140px;
- }
- }
- }
- #alert-info{
- overflow: auto;
- max-height: 340px;
- width: 100%;
- .alert-list-wrap {
- padding: 10px 10px 10px 20px;
- border-top: 1px solid #CCC;
- border-bottom: 1px solid #CCC;
- }
- .alert-list-line-cursor{
- width: 100%;
- min-height: 20px;
- .status-icon {
- padding-left: 5px;
- float: left;
- width: 10%;
- min-width: 30px;
- }
- .name-text {
- padding-left: 10px;
- width: 40%;
- float: left;
- }
- .service-text {
- padding-left: 5px;
- width: 15%;
- float: left;
- }
- .last-triggered-text {
- padding-left: 5px;
- color: #808080;
- font-size: 12px;
- }
- }
- .show-more {
- width: 98.8%;
- min-height: 20px;
- cursor: pointer;
- border-top: 1px solid #CCC;
- text-align: center;
- padding: 10px 10px 10px 0px;
- font-size: 16px;
- }
- }
-}
-/*****end styles for alert popup*****/
-
-
/*****start styles for install tasks logs*****/
.task-list-main-warp, .task-detail-info {
i {
@@ -2644,6 +2552,9 @@ width:100%;
/*end services summary*/
/*start alerts summary*/
+#alert-actions-button {
+ margin-right: 10px;
+}
.alerts {
margin: 0px;
max-height: 500px;
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/templates/main/alerts.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/alerts.hbs b/ambari-web/app/templates/main/alerts.hbs
index fb53f17..b449666 100644
--- a/ambari-web/app/templates/main/alerts.hbs
+++ b/ambari-web/app/templates/main/alerts.hbs
@@ -16,14 +16,15 @@
* limitations under the License.
}}
-<div class="pull-left advanced-header-table groups-filter">
- {{view view.alertGroupFilterView}}
-</div>
-<div class="pull-right">
+<div id="alert-actions-button" class="pull-left">
{{view App.MainAlertDefinitionActionsView controllerBinding="App.router.mainAlertDefinitionActionsController"}}
</div>
+<div id="alert-groups-filter" class="pull-left advanced-header-table groups-filter">
+ {{view view.alertGroupFilterView}}
+</div>
+
<div id="alerts">
<div class="box-header row">
</div>
@@ -34,14 +35,14 @@
{{view view.parentView.statusSort}}
{{view view.parentView.serviceSort}}
{{view view.parentView.lastTriggeredSort}}
- <th><span class="icon-off"></span></th>
+ {{view view.parentView.enabledSort}}
{{/view}}
<tr class="filter-row">
<th class="first">{{view view.nameFilterView}}</th>
<th>{{view view.stateFilterView}}</th>
<th>{{view view.serviceFilterView}}</th>
<th>{{view view.triggeredFilterView}}</th>
- <th></th>
+ <th>{{view view.enabledFilterView}}</th>
</tr>
</thead>
<tbody>
@@ -54,10 +55,20 @@
<td>{{{alertDefinition.status}}}</td>
<td>{{alertDefinition.service.serviceName}}</td>
<td>{{alertDefinition.lastTriggeredFormatted}}</td>
- <td class="last">
- <a href="#" {{action "toggleState" alertDefinition target="controller"}} {{bindAttr class="alertDefinition.enabled:enabled:disabled"}}>
- <span class="icon-off"></span>
- </a>
+ <td class="last toggle-state-button">
+ {{#if alertDefinition.enabled}}
+ {{t alerts.table.state.enabled}}
+ <a href="#" {{action "toggleState" alertDefinition target="controller"}} {{bindAttr class=":enable-disable-button alertDefinition.enabled:enabled:disabled"}}
+ {{bindAttr data-original-title="alerts.table.state.enabled.tooltip"}}>
+ <span class="icon-off"></span>
+ </a>
+ {{else}}
+ {{t alerts.table.state.disabled}}
+ <a href="#" {{action "toggleState" alertDefinition target="controller"}} {{bindAttr class=":enable-disable-button alertDefinition.enabled:enabled:disabled"}}
+ {{bindAttr data-original-title="alerts.table.state.disabled.tooltip"}}>
+ <span class="icon-off"></span>
+ </a>
+ {{/if}}
</td>
</tr>
{{/each}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/views/common/filter_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/filter_view.js b/ambari-web/app/views/common/filter_view.js
index 1efcb72..bdfea3d 100644
--- a/ambari-web/app/views/common/filter_view.js
+++ b/ambari-web/app/views/common/filter_view.js
@@ -617,6 +617,11 @@ module.exports = {
return origin.mapProperty('id').contains(compareValue);
};
break;
+ case 'enable_disable':
+ return function (origin, compareValue) {
+ return origin == (compareValue == 'enabled');
+ };
+ break;
case 'string':
default:
return function (origin, compareValue) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/views/common/sort_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/common/sort_view.js b/ambari-web/app/views/common/sort_view.js
index e66630c..4f28b74 100644
--- a/ambari-web/app/views/common/sort_view.js
+++ b/ambari-web/app/views/common/sort_view.js
@@ -172,7 +172,7 @@ var wrapperView = Em.View.extend({
func = function(a, b) {
var a_summary = a.get('summary'),
b_summary = b.get('summary'),
- st_order = a.get('order'),
+ st_order = a.get('severityOrder'),
ret = 0;
for(var i = 0; i < st_order.length; i++) {
var a_v = Em.isNone(a_summary[st_order[i]]) ? 0 : a_summary[st_order[i]],
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/app/views/main/alert_definitions_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/alert_definitions_view.js b/ambari-web/app/views/main/alert_definitions_view.js
index c8535cc..1300c83 100644
--- a/ambari-web/app/views/main/alert_definitions_view.js
+++ b/ambari-web/app/views/main/alert_definitions_view.js
@@ -29,6 +29,12 @@ App.MainAlertDefinitionsView = App.TableView.extend({
return this.get('controller.content');
}.property('controller.content.@each'),
+ didInsertElement: function () {
+ Em.run.later(this, function () {
+ App.tooltip($(".enable-disable-button"));
+ }, 50) ;
+ },
+
/**
* @type {number}
*/
@@ -36,7 +42,7 @@ App.MainAlertDefinitionsView = App.TableView.extend({
return this.get('content.length');
}.property('content.length'),
- colPropAssoc: ['', 'label', 'summary', 'service.serviceName', 'lastTriggered', 'groups'],
+ colPropAssoc: ['', 'label', 'summary', 'service.serviceName', 'lastTriggered', 'groups', 'enabled'],
sortView: sort.wrapperView,
@@ -47,7 +53,7 @@ App.MainAlertDefinitionsView = App.TableView.extend({
nameSort: sort.fieldView.extend({
column: 1,
name: 'label',
- displayName: Em.I18n.t('common.name')
+ displayName: Em.I18n.t('alerts.table.header.definitionName')
}),
/**
@@ -58,7 +64,8 @@ App.MainAlertDefinitionsView = App.TableView.extend({
column: 2,
name: 'summary',
displayName: Em.I18n.t('common.status'),
- type: 'alert_status'
+ type: 'alert_status',
+ status: 'sorting_desc'
}),
/**
@@ -84,6 +91,16 @@ App.MainAlertDefinitionsView = App.TableView.extend({
}),
/**
+ * Sorting header for <label>alertDefinition.enabled</label>
+ * @type {Em.View}
+ */
+ enabledSort: sort.fieldView.extend({
+ template:Em.Handlebars.compile('<span {{bindAttr class="view.status :column-name"}}><span class="icon-off"></span></span>'),
+ column: 6,
+ name: 'enabled'
+ }),
+
+ /**
* Filtering header for <label>alertDefinition.label</label>
* @type {Em.View}
*/
@@ -203,20 +220,60 @@ App.MainAlertDefinitionsView = App.TableView.extend({
}),
/**
+ * Filtering header for <label>alertDefinition.enabled</label>
+ * @type {Em.View}
+ */
+ enabledFilterView: filters.createSelectView({
+ column: 6,
+ fieldType: 'filter-input-width',
+ content: [
+ {
+ value: '',
+ label: Em.I18n.t('common.all')
+ },
+ {
+ value: 'enabled',
+ label: Em.I18n.t('alerts.table.state.enabled')
+ },
+ {
+ value: 'disabled',
+ label: Em.I18n.t('alerts.table.state.disabled')
+ }
+ ],
+ onChangeValue: function () {
+ this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'enable_disable');
+ }
+ }),
+
+ /**
* Filtering header for <label>alertDefinition</label> groups
* @type {Em.View}
*/
alertGroupFilterView: filters.createSelectView({
-
column: 5,
-
fieldType: 'filter-input-width',
-
+ template: Ember.Handlebars.compile(
+ '<div class="btn-group display-inline-block">' +
+ '<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">' +
+ '<span class="filters-label">Groups: </span>' +
+ '<span>{{view.selected.label}} <span class="caret"></span></span>' +
+ '</a>' +
+ '<ul class="dropdown-menu">' +
+ '{{#each category in view.content}}' +
+ '<li {{bindAttr class=":category-item category.selected:active"}}>' +
+ '<a {{action selectCategory category target="view"}} href="#">' +
+ '<span {{bindAttr class="category.class"}}></span>{{category.label}}</a>' +
+ '</li>'+
+ '{{/each}}' +
+ '</ul>'+
+ '</div>'
+ ),
content: [],
didInsertElement: function() {
this._super();
this.updateContent();
+ this.set('value', '');
},
/**
@@ -224,26 +281,42 @@ App.MainAlertDefinitionsView = App.TableView.extend({
* @method updateContent
*/
updateContent: function() {
- var value = this.get('value');
+ var alertGroups = App.AlertGroup.find().map(function (group) {
+ return Em.Object.create({
+ value: group.get('id'),
+ label: group.get('displayNameDefinitions'),
+ default: group.get('default')
+ });
+ });
+ var defaultGroups = alertGroups.filterProperty('default');
+ defaultGroups.forEach(function(defaultGroup) {
+ alertGroups.removeObject(defaultGroup);
+ });
+ var sortedGroups = defaultGroups.sortProperty('label').concat(alertGroups.sortProperty('label'));
this.set('content', [
- {
+ Em.Object.create({
value: '',
label: Em.I18n.t('common.all') + ' (' + this.get('parentView.controller.content.length') + ')'
- }
- ].concat(App.AlertGroup.find().map(function (group) {
- return {
- value: group.get('id'),
- label: group.get('displayNameDefinitions')
- };
- })));
-
- this.set('selected', this.get('content').findProperty('value', value));
+ })
+ ].concat(sortedGroups));
+ this.onValueChange();
}.observes('App.router.clusterController.isLoaded', 'controller.mapperTimestamp'),
- onChangeValue: function () {
- this.get('parentView').updateFilter(this.get('column'), this.get('value'), 'alert_group');
- }
+ selectCategory: function (event) {
+ var category = event.context;
+ this.set('value', category.value);
+ this.get('parentView').updateFilter(this.get('column'), category.value, 'alert_group');
+ },
+
+ onValueChange: function () {
+ var value = this.get('value');
+ if (value != undefined ) {
+ this.get('content').setEach('selected', false);
+ this.set('selected', this.get('content').findProperty('value', value));
+ this.get('content').findProperty('value', value).set('selected', true);
+ }
+ }.observes('value')
}),
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/3af54a1f/ambari-web/test/controllers/main/alert_definitions_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/alert_definitions_controller_test.js b/ambari-web/test/controllers/main/alert_definitions_controller_test.js
index a605899..03a4d80 100644
--- a/ambari-web/test/controllers/main/alert_definitions_controller_test.js
+++ b/ambari-web/test/controllers/main/alert_definitions_controller_test.js
@@ -30,7 +30,7 @@ describe('App.MainAlertDefinitionsController', function() {
});
- describe('#toggleState', function() {
+ describe('#toggleDefinitionState', function() {
beforeEach(function() {
sinon.stub(App.ajax, 'send', Em.K);
@@ -47,7 +47,7 @@ describe('App.MainAlertDefinitionsController', function() {
it('should do ajax-request', function() {
var alertDefinition = controller.get('content')[0];
- controller.toggleState({context: alertDefinition});
+ controller.toggleDefinitionState(alertDefinition);
expect(App.ajax.send.calledOnce).to.be.true;
});