You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/01/14 13:02:37 UTC
git commit: AMBARI-4284. Alerts, Restart,
Maintenance elements in the Hosts filters. (onechiporenko)
Updated Branches:
refs/heads/trunk b1d187fb2 -> 122dc8397
AMBARI-4284. Alerts, Restart, Maintenance elements in the Hosts filters. (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/122dc839
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/122dc839
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/122dc839
Branch: refs/heads/trunk
Commit: 122dc8397cf8d91aae315e64dbda5067825a1139
Parents: b1d187f
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Tue Jan 14 14:00:19 2014 +0200
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Tue Jan 14 14:00:19 2014 +0200
----------------------------------------------------------------------
ambari-web/app/data/host/categories.js | 98 ++++++++++++
ambari-web/app/styles/application.less | 6 +
ambari-web/app/templates/main/host.hbs | 20 +--
ambari-web/app/views/main/host.js | 221 ++++++++++++++++++----------
4 files changed, 250 insertions(+), 95 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/122dc839/ambari-web/app/data/host/categories.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/data/host/categories.js b/ambari-web/app/data/host/categories.js
new file mode 100644
index 0000000..857304d
--- /dev/null
+++ b/ambari-web/app/data/host/categories.js
@@ -0,0 +1,98 @@
+/**
+ * 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.
+ */
+
+module.exports = [
+ {
+ value: Em.I18n.t('common.all'),
+ isHealthStatus: true,
+ healthStatusValue: '',
+ isActive: true,
+ isVisible: false
+ },
+ {
+ value: Em.I18n.t('hosts.host.healthStatusCategory.green'),
+ isHealthStatus: true,
+ healthStatusValue: 'health-status-LIVE',
+ observes: 'view.content.@each.healthClass'
+ },
+ {
+ value: Em.I18n.t('hosts.host.healthStatusCategory.red'),
+ isHealthStatus: true,
+ healthStatusValue: 'health-status-DEAD-RED',
+ observes: 'view.content.@each.healthClass'
+ },
+ {
+ value: Em.I18n.t('hosts.host.healthStatusCategory.orange'),
+ isHealthStatus: true,
+ healthStatusValue: 'health-status-DEAD-ORANGE',
+ observes: 'view.content.@each.healthClass'
+ },
+ {
+ value: Em.I18n.t('hosts.host.healthStatusCategory.yellow'),
+ isHealthStatus: true,
+ healthStatusValue: 'health-status-DEAD-YELLOW',
+ observes: 'view.content.@each.healthClass'
+ },
+ {
+ value: Em.I18n.t('hosts.host.alerts.label'),
+ hostProperty: 'criticalAlertsCount',
+ class: 'label label-important alerts-status',
+ isHealthStatus: false,
+ healthStatusValue: 'health-status-WITH-ALERTS',
+ column: 7,
+ separator: true,
+ type: 'number',
+ filterValue: '>0',
+ observes: 'view.content.@each.criticalAlertsCount'
+ },
+ {
+ value: Em.I18n.t('common.restart'),
+ hostProperty: 'componentsWithStaleConfigsCount',
+ class: 'icon-refresh',
+ isHealthStatus: false,
+ healthStatusValue: 'health-status-RESTART',
+ column: 8,
+ type: 'number',
+ filterValue: '>0',
+ observes: 'view.content.@each.componentsWithStaleConfigsCount'
+ },
+ {
+ value: Em.I18n.t('common.selected'),
+ hostProperty: 'selected',
+ class: '',
+ isHealthStatus: false,
+ healthStatusValue: 'health-status-SELECTED',
+ selected: true,
+ column: 10,
+ type: 'boolean',
+ filterValue: true,
+ isVisible: false,
+ observes: 'view.content.@each.selected'
+ },
+ {
+ value: Em.I18n.t('common.maintenance'),
+ hostProperty: 'componentsInMaintenanceCount',
+ class: 'maintenance icon-medkit',
+ isHealthStatus: false,
+ healthStatusValue: 'health-status-MAINTENANCE',
+ column: 9,
+ type: 'number',
+ filterValue: '>0',
+ observes: 'view.content.@each.componentsInMaintenanceCount'
+ }
+];
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/122dc839/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index e919a43..006ab4e 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -2694,6 +2694,12 @@ table.graphs {
.maintenance {
color: #000;
}
+ .alerts-status {
+ padding: 1px 6px !important;
+ &:before {
+ content: "!";
+ }
+ }
.host-name-search {
position: relative;
top: 0px;
http://git-wip-us.apache.org/repos/asf/ambari/blob/122dc839/ambari-web/app/templates/main/host.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/main/host.hbs b/ambari-web/app/templates/main/host.hbs
index 07002aa..37ed6d9 100644
--- a/ambari-web/app/templates/main/host.hbs
+++ b/ambari-web/app/templates/main/host.hbs
@@ -27,25 +27,17 @@
{{#view view.statusFilter categoriesBinding="view.categories"}}
{{#each category in view.categories}}
{{#if category.isVisible}}
- {{#if category.alerts}}
- <br /><br />
+ {{#if category.separator}}
+ <br /><br />
{{else}}
- |
+ |
{{/if}}
<span {{bindAttr class="aaa :category-item category.itemClass"}}>
<a {{action selectCategory category target="view"}} href="#">
- {{#if category.alerts}}
- <span class="label label-important">{{t hosts.host.alerts.st}}</span>
+ {{#if category.isHealthStatus}}
+ <span {{bindAttr class=":health-status category.healthStatusValue"}}> </span>
{{else}}
- {{#if category.restart}}
- <span class="icon-refresh"></span>
- {{else}}
- {{#if category.maintenance}}
- <span class="maintenance icon-medkit"></span>
- {{else}}
- <span {{bindAttr class=":health-status category.healthStatusValue"}}> </span>
- {{/if}}
- {{/if}}
+ <span {{bindAttr class="category.class"}}></span>
{{/if}}
{{category.label}}
</a>
http://git-wip-us.apache.org/repos/asf/ambari/blob/122dc839/ambari-web/app/views/main/host.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/main/host.js b/ambari-web/app/views/main/host.js
index 1096f87..d52f9aa 100644
--- a/ambari-web/app/views/main/host.js
+++ b/ambari-web/app/views/main/host.js
@@ -23,6 +23,10 @@ var date = require('utils/date');
App.MainHostView = App.TableView.extend({
templateName:require('templates/main/host'),
+ /**
+ * List of hosts in cluster
+ * @type {Array}
+ */
content:function () {
return this.get('controller.content');
}.property('controller.content.length'),
@@ -53,7 +57,7 @@ App.MainHostView = App.TableView.extend({
/**
* Select/deselect all visible hosts flag
- * @property {bool}
+ * @property {Boolean}
*/
selectAllHosts: false,
@@ -242,69 +246,139 @@ App.MainHostView = App.TableView.extend({
/**
* Category view for all hosts
+ * @type {Object}
*/
+ //@TODO maybe should be separated to two types (basing on <code>isHealthStatus</code>)
categoryObject: Em.Object.extend({
- hostsCount: function () {
+ /**
+ * Text used with <code>hostsCount</code> in category label
+ * @type {String}
+ */
+ value: null,
+ /**
+ * Is category based on host health status
+ * @type {Boolean}
+ */
+ isHealthStatus: true,
+ /**
+ * host health status (used if <code>isHealthStatus</code> is true)
+ * @type {String}
+ */
+ healthStatusValue: '',
+ /**
+ * Should category be displayed on the top of the hosts table
+ * @type {Boolean}
+ */
+ isVisible: true,
+ /**
+ * Is category selected now
+ * @type {Boolean}
+ */
+ isActive: false,
+ /**
+ * String with path that category should observe
+ * @type {String}
+ */
+ observes: null,
+ /**
+ * CSS-class for span in the category-link (used if <code>isHealthStatus</code> is false)
+ * @type {String}
+ */
+ class: null,
+ /**
+ * Associated column number
+ * @type {Number}
+ */
+ column: null,
+ /**
+ * Type of filter value (string, number, boolean)
+ * @type {String}
+ */
+ type: null,
+ /**
+ * @type {String|Number|Boolean}
+ */
+ filterValue: null,
+ /**
+ * Should new line be inserted after this category
+ * @type {Boolean}
+ */
+ separator: false,
+
+ /**
+ * <code>App.Host</code> property that should be used to calculate <code>hostsCount</code> (used if <code>isHealthStatus</code> is false)
+ * @type {String}
+ */
+ hostProperty: null,
+
+ /**
+ * Number of host in current category
+ * @type {Number}
+ */
+ hostsCount: 0,
+
+ /**
+ * Add "active" class for category span-wrapper if current category is selected
+ * @type {String}
+ */
+ itemClass: function() {
+ return this.get('isActive') ? 'active' : '';
+ }.property('isActive'),
+
+ /**
+ * Trigger updating <code>hostsCount</code> only 1 time
+ */
+ updateHostsCount: function() {
+ Em.run.once(this, 'updateOnce');
+ },
+ /**
+ * Update <code>hostsCount</code> in current category
+ */
+ updateOnce: function() {
var statusString = this.get('healthStatusValue');
- var alerts = this.get('alerts');
- var restart = this.get('restart');
- var maintenance = this.get('maintenance');
- var selected = this.get('selected');
- if(alerts) {
- return this.get('view.content').filterProperty('criticalAlertsCount').get('length');
- }
- else {
- if (restart) {
- return this.get('view.content').filterProperty('componentsWithStaleConfigsCount').get('length');
+ if (this.get('isHealthStatus')) {
+ if (statusString == "") {
+ this.set('hostsCount', this.get('view.content').get('length'));
}
else {
- if (maintenance) {
- return this.get('view.content').filterProperty('componentsInMaintenanceCount').get('length');
- }
- else {
- if (selected) {
- return this.get('view.content').filterProperty('selected').get('length');
- }
- else {
- if (statusString == "") {
- return this.get('view.content').get('length');
- }
- else {
- return this.get('view.content').filterProperty('healthClass', statusString ).get('length');
- }
- }
- }
+ this.set('hostsCount', this.get('view.content').filterProperty('healthClass', statusString).get('length'));
}
}
- }.property('view.content.@each.selected', 'view.content.@each.healthClass', 'view.content.@each.criticalAlertsCount', 'view.content.@each.componentsInMaintenanceCount', 'view.content.@each.componentsWithStaleConfigsCount'),
+ else {
+ this.set('hostsCount', this.get('view.content').filterProperty(this.get('hostProperty')).get('length'));
+ }
+ },
+ /**
+ * Text shown on the right of category icon
+ * @type {String}
+ */
label: function () {
return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount'));
}.property('hostsCount')
}),
+ /**
+ * List of categories used to filter hosts
+ * @type {Array}
+ */
categories: function () {
var self = this;
self.categoryObject.reopen({
- view: self,
- isActive: false,
- itemClass: function() {
- return this.get('isActive') ? 'active' : '';
- }.property('isActive')
+ view: self
});
- return [
- self.categoryObject.create({value: Em.I18n.t('common.all'), healthStatusValue: '', isActive: true, isVisible: false}),
- self.categoryObject.create({value: Em.I18n.t('hosts.host.healthStatusCategory.green'), healthStatusValue: 'health-status-LIVE', isVisible: true}),
- self.categoryObject.create({value: Em.I18n.t('hosts.host.healthStatusCategory.red'), healthStatusValue: 'health-status-DEAD-RED', isVisible: true}),
- self.categoryObject.create({value: Em.I18n.t('hosts.host.healthStatusCategory.orange'), healthStatusValue: 'health-status-DEAD-ORANGE', isVisible: true}),
- self.categoryObject.create({value: Em.I18n.t('hosts.host.healthStatusCategory.yellow'), healthStatusValue: 'health-status-DEAD-YELLOW', isVisible: true}),
- self.categoryObject.create({value: Em.I18n.t('hosts.host.alerts.label'), healthStatusValue: 'health-status-WITH-ALERTS', alerts: true, isVisible: true }),
- self.categoryObject.create({value: Em.I18n.t('common.restart'), healthStatusValue: 'health-status-RESTART', restart: true, isVisible: true }),
- self.categoryObject.create({value: Em.I18n.t('common.selected'), healthStatusValue: 'health-status-SELECTED', selected: true, isVisible: false }),
- self.categoryObject.create({value: Em.I18n.t('common.maintenance'), healthStatusValue: 'health-status-MAINTENANCE', maintenance: true, last: true, isVisible: true })
- ];
+ var category_mocks = require('data/host/categories');
+
+ return category_mocks.map(function(category_mock) {
+ var c = self.categoryObject.create(category_mock);
+ if (c.get('observes')) {
+ c.addObserver(c.get('observes'), c, c.updateHostsCount);
+ c.updateHostsCount();
+ }
+ return c;
+ });
}.property(),
/**
@@ -321,59 +395,40 @@ App.MainHostView = App.TableView.extend({
/**
* switch active category label
*/
- onCategoryChange: function(){
+ onCategoryChange: function() {
this.get('categories').setEach('isActive', false);
this.get('categories').findProperty('healthStatusValue', this.get('value')).set('isActive', true);
}.observes('value'),
+
showClearFilter: function(){
var mockEvent = {
context: this.get('categories').findProperty('healthStatusValue', this.get('value'))
};
this.selectCategory(mockEvent);
},
+ /**
+ * Trigger on Category click
+ * @param {Object} event
+ */
selectCategory: function(event){
var category = event.context;
+ var self = this;
this.set('value', category.get('healthStatusValue'));
- if(category.get('alerts')) {
- this.get('parentView').updateFilter(0, '', 'string');
- this.get('parentView').updateFilter(7, '>0', 'number');
- this.get('parentView').updateFilter(8, '', 'number');
- this.get('parentView').updateFilter(9, '', 'number');
- this.get('parentView').updateFilter(10, '', 'boolean');
+ if (category.get('isHealthStatus')) {
+ this.get('parentView').updateFilter(0, category.get('healthStatusValue'), 'string');
+ this.get('categories').filterProperty('isHealthStatus', false).forEach(function(c) {
+ self.get('parentView').updateFilter(c.get('column'), '', c.get('type'));
+ });
}
else {
- if(category.get('restart')) {
- this.get('parentView').updateFilter(0, '', 'string');
- this.get('parentView').updateFilter(7, '', 'number');
- this.get('parentView').updateFilter(8, '>0', 'number');
- this.get('parentView').updateFilter(9, '', 'number');
- this.get('parentView').updateFilter(10, '', 'boolean');
- }
- else {
- if(category.get('maintenance')) {
- this.get('parentView').updateFilter(0, '', 'string');
- this.get('parentView').updateFilter(7, '', 'number');
- this.get('parentView').updateFilter(8, '', 'number');
- this.get('parentView').updateFilter(9, '>0', 'number');
- this.get('parentView').updateFilter(10, '', 'boolean');
+ this.get('categories').filterProperty('isHealthStatus', false).forEach(function(c) {
+ if (c.get('column') === category.get('column')) {
+ self.get('parentView').updateFilter(category.get('column'), category.get('filterValue'), category.get('type'));
}
else {
- if(category.get('selected')) {
- this.get('parentView').updateFilter(0, '', 'string');
- this.get('parentView').updateFilter(7, '', 'number');
- this.get('parentView').updateFilter(8, '', 'number');
- this.get('parentView').updateFilter(9, '', 'number');
- this.get('parentView').updateFilter(10, true, 'boolean');
- }
- else {
- this.get('parentView').updateFilter(0, category.get('healthStatusValue'), 'string');
- this.get('parentView').updateFilter(7, '', 'number');
- this.get('parentView').updateFilter(8, '', 'number');
- this.get('parentView').updateFilter(9, '', 'number');
- this.get('parentView').updateFilter(10, '', 'boolean');
- }
+ self.get('parentView').updateFilter(c.get('column'), '', c.get('type'));
}
- }
+ });
}
},
clearFilter: function() {
@@ -434,6 +489,9 @@ App.MainHostView = App.TableView.extend({
}
}),
+ /**
+ * view of the "selected" filter implemented as a category of host statuses
+ */
selectedFilter: Em.View.extend({
column: 10,
value: null,
@@ -631,6 +689,7 @@ App.MainHostView = App.TableView.extend({
/**
* associations between host property and column index
+ * @type {Array}
*/
colPropAssoc: function(){
var associations = [];