http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/assets/font/fontawesome-webfont.woff ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/font/fontawesome-webfont.woff b/ambari-web/app/assets/font/fontawesome-webfont.woff index 09f2469..b9bd17e 100644 Binary files a/ambari-web/app/assets/font/fontawesome-webfont.woff and b/ambari-web/app/assets/font/fontawesome-webfont.woff differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/assets/licenses/NOTICE.txt ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/licenses/NOTICE.txt b/ambari-web/app/assets/licenses/NOTICE.txt index 7a464dc..d2aa8f8 100644 --- a/ambari-web/app/assets/licenses/NOTICE.txt +++ b/ambari-web/app/assets/licenses/NOTICE.txt @@ -30,9 +30,10 @@ Copyright (c) 2012, Michael Bostock. This product includes bootstrap-datepicker.js (http://www.eyecon.ro/bootstrap-datepicker - Apache License, Version 2.0) Copyright (c) 2012 Stefan Petre -This product includes Font Awesome 2.0 (http://fortawesome.github.com/Font-Awesome - Creative Commons 3.0) +This product includes Font Awesome 3.2.1 (http://fortawesome.github.com/Font-Awesome - Creative Commons 3.0) +Copyright (c) 2013 Dave Gandy -This product incudes Rickshaw 1.1.2 (http://code.shutterstock.com/rickshaw/ - MIT License) +This product includes Rickshaw 1.1.2 (http://code.shutterstock.com/rickshaw/ - MIT License) Copyright (C) 2011 by Shutterstock Images, LLC This product includes Timeago (http://timeago.yarp.com/ - MIT License) http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/controllers/main/host.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/host.js b/ambari-web/app/controllers/main/host.js index c037e3b..65f9981 100644 --- a/ambari-web/app/controllers/main/host.js +++ b/ambari-web/app/controllers/main/host.js @@ -32,6 +32,7 @@ App.MainHostController = Em.ArrayController.extend({ /** * Components which will be shown in component filter + * @returns {Array} */ componentsForFilter:function() { var installedComponents = componentHelper.getInstalledComponents(); @@ -39,21 +40,33 @@ App.MainHostController = Em.ArrayController.extend({ return installedComponents; }.property('App.router.clusterController.isLoaded'), + /** + * Master components + * @returns {Array} + */ masterComponents:function () { return this.get('componentsForFilter').filterProperty('isMaster', true); }.property('componentsForFilter'), + /** + * Slave components + * @returns {Array} + */ slaveComponents:function () { return this.get('componentsForFilter').filterProperty('isSlave', true); }.property('componentsForFilter'), + /** + * Client components + * @returns {Array} + */ clientComponents: function() { return this.get('componentsForFilter').filterProperty('isClient', true); }.property('componentsForFilter'), /** * Filter hosts by componentName of <code>component</code> - * @param component App.HostComponent + * @param {App.HostComponent} component */ filterByComponent:function (component) { if(!component) @@ -99,9 +112,6 @@ App.MainHostController = Em.ArrayController.extend({ templateName: require('templates/main/host/alerts_popup') }), primary: Em.I18n.t('common.close'), - onPrimary: function() { - this.hide(); - }, secondary : null, didInsertElement: function () { this.$().find('.modal-footer').addClass('align-center'); @@ -125,7 +135,7 @@ App.MainHostController = Em.ArrayController.extend({ /** * remove hosts with id equal host_id - * @param host_id + * @param {String} host_id */ checkRemoved:function (host_id) { var hosts = this.get('content'); http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index 532a1eb..8ded97d 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -164,6 +164,7 @@ Em.I18n.translations = { 'common.restart': 'Restart', 'common.discard': 'Discard', 'common.actions': 'Actions', + 'common.maintenance': 'Maintenance', 'requestInfo.installComponents':'Install Components', 'requestInfo.installServices':'Install Services', @@ -1303,6 +1304,9 @@ Em.I18n.translations = { 'hosts.table.restartComponents.withNames':'Restart {0}', 'hosts.table.restartComponents.withoutNames':'{0} components should be restarted', + 'hosts.table.componentsInMaintenance.withNames':'{0} in maintenance mode', + 'hosts.table.componentsInMaintenance.withoutNames':'{0} components in maintenance mode', + 'hosts.selectHostsDialog.title': 'Select Configuration Group Hosts', 'hosts.selectHostsDialog.message': 'Select hosts that should belong to this {0} Configuration Group. All hosts belonging to this group will have the same set of {0} configurations.', 'hosts.selectHostsDialog.filter.placeHolder': 'Filter...', http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/models/host.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/host.js b/ambari-web/app/models/host.js index 91fe812..c215b73 100644 --- a/ambari-web/app/models/host.js +++ b/ambari-web/app/models/host.js @@ -44,61 +44,104 @@ App.Host = DS.Model.extend({ cpuSystem:DS.attr('number'), cpuUser:DS.attr('number'), + /** + * Overall CPU usage (system and user) + * @returns {Number} + */ cpuUsage: function () { - if (this.get('cpuSystem') && this.get('cpu_user')) { - return this.get('cpuSystem') + this.get('cpu_user'); + if (this.get('cpuSystem') && this.get('cpuUser')) { + return this.get('cpuSystem') + this.get('cpuUser'); } + return 0; }.property('cpuSystem', 'cpuUser'), + /** + * Percent value of used memory + * @returns {Number} + */ memoryUsage: function () { if (this.get('memFree') && this.get('memTotal')) { var memUsed = this.get('memTotal') - this.get('memFree'); return (100 * memUsed) / this.get('memTotal'); } + return 0; }.property('memTotal', 'memFree'), + /** + * Get count of critical alerts for current host + * @returns {Number} + */ criticalAlertsCount: function () { return App.router.get('clusterController.alertsHostMap')[this.get('hostName')]; }.property('App.router.clusterController.alerts.length'), + /** + * Get count of host components with stale configs + * @returns {Number} + */ componentsWithStaleConfigsCount: function() { return this.get('hostComponents').filterProperty('staleConfigs', true).length; }.property('[email protected]'), + /** + * Get count of host components in maintenance mode + * @returns {Number} + */ + componentsInMaintenanceCount: function() { + return this.get('hostComponents').filterProperty('workStatus', App.HostComponentStatus.maintenance).length; + }.property('[email protected]').volatile(), + + /** + * Truncate hostName if it longer than 43 symbols + * @returns {String} + */ publicHostNameFormatted: function() { return this.get('publicHostName').length < 43 ? this.get('publicHostName') : this.get('publicHostName').substr(0, 40) + '...'; }.property('publicHostName'), + /** + * Count of mounted on host disks + * @returns {Number} + */ disksMounted: function() { return this.get('diskInfo.length'); }.property('diskInfo.length'), /** * API return diskTotal and diskFree. Need to save their different + * @returns {Number} */ diskUsed: function(){ return this.get('diskTotal') - this.get('diskFree'); }.property('diskFree', 'diskTotal'), + /** * Format diskUsed value to float with 2 digits (also convert to GB) + * @returns {String} Format: '*** GB' */ diskUsedFormatted: function() { return Math.round(this.get('diskUsed') * Math.pow(10, 2)) / Math.pow(10, 2) + 'GB'; }.property('diskUsed'), + /** * Format diskTotal value to float with 2 digits (also convert to GB) + * @returns {String} Format: '*** GB' */ diskTotalFormatted: function() { return Math.round(this.get('diskTotal') * Math.pow(10, 2)) / Math.pow(10, 2) + 'GB'; }.property('diskTotal'), + /** * Percent value of used disk space + * @returns {Number} */ diskUsage: function() { return (this.get('diskUsed')) / this.get('diskTotal') * 100; }.property('diskUsed', 'diskTotal'), + /** * Format diskUsage to float with 2 digits + * @returns {String} Format: '**.** %' */ diskUsageFormatted: function() { if (isNaN(this.get('diskUsage')) || this.get('diskUsage') < 0) { @@ -111,6 +154,10 @@ App.Host = DS.Model.extend({ return s + '%'; }.property('diskUsage'), + /** + * Formatted string with data about disk usage + * @returns {String} + */ diskInfoBar: function() { if (isNaN(this.get('diskUsage')) || this.get('diskUsage') < 0) { return this.get('diskUsageFormatted'); @@ -118,25 +165,39 @@ App.Host = DS.Model.extend({ return this.get('diskUsedFormatted') + '/' + this.get('diskTotalFormatted') + ' (' + this.get('diskUsageFormatted') + ' ' + Em.I18n.t('services.service.summary.diskInfoBar.used') + ')'; }.property('diskUsedFormatted', 'diskTotalFormatted'), + /** - * formatted bytes to appropriate value + * Formatted bytes to appropriate value + * @returns {String} */ memoryFormatted: function () { return misc.formatBandwidth(this.get('memory') * 1024); }.property('memory'), + /** * Return true if the host has not sent heartbeat within the last 180 seconds + * @returns {bool} */ isNotHeartBeating : function() { return (App.testMode) ? false : ((new Date()).getTime() - this.get('lastHeartBeatTime')) > 180 * 1000; }.property('lastHeartBeatTime'), + /** + * Average load + * @returns {Number} + */ loadAvg: function() { if (this.get('loadOne') != null) return this.get('loadOne').toFixed(2); if (this.get('loadFive') != null) return this.get('loadFive').toFixed(2); if (this.get('loadFifteen') != null) return this.get('loadFifteen').toFixed(2); + return null; }.property('loadOne', 'loadFive', 'loadFifteen'), + /** + * Host health indicator + * Based on <code>healthStatus</code> + * @returns {String} + */ healthClass: function(){ var statusMap = { 'UNKNOWN': 'health-status-DEAD-YELLOW', @@ -147,6 +208,11 @@ App.Host = DS.Model.extend({ return statusMap[this.get('healthStatus')] || 'health-status-DEAD-YELLOW'; }.property('healthStatus'), + /** + * Tooltip for host indicator + * Contains affected host components names (based on <code>healthClass</code>) + * @returns {String} + */ healthToolTip: function(){ var hostComponents = this.get('hostComponents').filter(function(item){ if(item.get('workStatus') !== App.HostComponentStatus.started){ http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/models/host_component.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/host_component.js b/ambari-web/app/models/host_component.js index f94446b..081442c 100644 --- a/ambari-web/app/models/host_component.js +++ b/ambari-web/app/models/host_component.js @@ -26,6 +26,10 @@ App.HostComponent = DS.Model.extend({ staleConfigs: DS.attr('boolean'), host: DS.belongsTo('App.Host'), service: DS.belongsTo('App.Service'), + /** + * Determine if component is client + * @returns {bool} + */ isClient:function () { if(['PIG', 'SQOOP', 'HCAT', 'MAPREDUCE2_CLIENT'].contains(this.get('componentName'))){ return true; @@ -33,12 +37,27 @@ App.HostComponent = DS.Model.extend({ return Boolean(this.get('componentName').match(/_client/gi)); }.property('componentName'), + /** + * Determine if component is running now + * Based on <code>workStatus</code> + * @returns {bool} + */ isRunning: function(){ return (this.get('workStatus') == 'STARTED' || this.get('workStatus') == 'STARTING'); }.property('workStatus'), + + /** + * Formatted <code>componentName</code> + * @returns {String} + */ displayName: function () { return App.format.role(this.get('componentName')); }.property('componentName'), + + /** + * Determine if component is master + * @returns {bool} + */ isMaster: function () { switch (this.get('componentName')) { case 'NAMENODE': @@ -64,6 +83,11 @@ App.HostComponent = DS.Model.extend({ return false; } }.property('componentName'), + + /** + * Determine if component is slave + * @returns {bool} + */ isSlave: function(){ switch (this.get('componentName')) { case 'DATANODE': @@ -82,6 +106,7 @@ App.HostComponent = DS.Model.extend({ * They include some from master components, * some from slave components, and rest from * client components. + * @returns {bool} */ isDeletable: function() { var canDelete = false; @@ -104,6 +129,7 @@ App.HostComponent = DS.Model.extend({ /** * A host-component is decommissioning when it is in HDFS service's list of * decomNodes. + * @returns {bool} */ isDecommissioning: function () { var decommissioning = false; @@ -119,6 +145,7 @@ App.HostComponent = DS.Model.extend({ }.property('componentName', 'host.hostName', 'App.router.clusterController.isLoaded', 'App.router.updateController.isUpdated'), /** * User friendly host component status + * @returns {String} */ componentTextStatus: function () { return App.HostComponentStatus.getTextStatus(this.get("workStatus")); @@ -138,6 +165,11 @@ App.HostComponentStatus = { maintenance: "MAINTENANCE", unknown: "UNKNOWN", + /** + * Get host component status in "machine" format + * @param {String} value + * @returns {String} + */ getKeyName:function(value){ switch(value){ case this.started: @@ -162,6 +194,11 @@ App.HostComponentStatus = { return 'Unknown'; }, + /** + * Get user-friendly host component status + * @param {String} value + * @returns {String} + */ getTextStatus: function (value) { switch (value) { case this.installing: http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index 1c25d2d..05531cf 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -2691,6 +2691,9 @@ table.graphs { background-image: @status-dead-yellow-marker; .status-dot-position; } + .maintenance { + color: #000; + } .host-name-search { position: relative; top: 0px; @@ -2715,6 +2718,7 @@ table.graphs { .health-status-bar { font-size: 0.9em; margin-left: 0; + margin-bottom: 15px; min-width: 790px; color: #b4b4b4; .health-status { @@ -2778,7 +2782,7 @@ table.graphs { .col0, td:first-child, th:first-child { - width: 3%; + width: 2%; min-width:13px!important; } .col1, @@ -2786,15 +2790,15 @@ table.graphs { th:first-child + th{ width: 19%; } - .col2, + .col2, .col3, td:first-child + td + td, - th:first-child + th + th{ - width:3%; + th:first-child + th + th, + td:first-child + td + td + td, + th:first-child + th + th + th,{ + width:2%; min-width:13px!important; } - .col3,.col4,.col5,.col6,.col7, - td:first-child + td + td + td, - th:first-child + th + th + th, + .col4,.col5,.col6,.col7,.col8, td:first-child + td + td + td + td, th:first-child + th + th + th + th, td:first-child + td + td + td + td + td, @@ -2802,12 +2806,14 @@ table.graphs { td:first-child + td + td + td + td + td + td, th:first-child + th + th + th + th + th + th, td:first-child + td + td + td + td + td + td + td, - th:first-child + th + th + th + th + th + th + th{ - width: 12%; - } - .col8, + th:first-child + th + th + th + th + th + th + th, td:first-child + td + td + td + td + td + td + td + td, th:first-child + th + th + th + th + th + th + th + th{ + width: 12%; + } + .col9, + td:first-child + td + td + td + td + td + td + td + td + td, + th:first-child + th + th + th + th + th + th + th + th + th{ width: 15%; } http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/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 fcadc6f..8962ec7 100644 --- a/ambari-web/app/templates/main/host.hbs +++ b/ambari-web/app/templates/main/host.hbs @@ -27,16 +27,24 @@ {{#view view.statusFilter categoriesBinding="view.categories"}} {{#each category in view.categories}} {{#if category.isVisible}} - | + {{#if category.alerts}} + <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> {{else}} {{#if category.restart}} - <span class="muted icon-refresh"></span> + <span class="icon-refresh"></span> {{else}} - <span {{bindAttr class=":health-status category.healthStatusValue"}}> </span> + {{#if category.maintenance}} + <span class="maintenance icon-medkit"></span> + {{else}} + <span {{bindAttr class=":health-status category.healthStatusValue"}}> </span> + {{/if}} {{/if}} {{/if}} {{category.label}} @@ -63,6 +71,7 @@ <th class="first"> </th> {{view view.parentView.nameSort}} <th> </th> + <th> </th> {{view view.parentView.ipSort}} {{view view.parentView.cpuSort}} {{view view.parentView.memorySort}} @@ -74,6 +83,7 @@ <th class="first"> </th> <th>{{view view.nameFilterView}}</th> <th> </th> + <th> </th> <th>{{view view.ipFilterView}}</th> <th>{{view view.cpuFilterView}}</th> <th>{{view view.ramFilterView}}</th> @@ -102,6 +112,11 @@ <span class="muted icon-refresh" rel="ComponentsTooltip" {{bindAttr title="view.restartRequiredComponentsMessage"}}></span> {{/if}} </td> + <td class="maintenance"> + {{#if host.componentsInMaintenanceCount}} + <span class="icon-medkit" rel="ComponentsTooltip" {{bindAttr title="view.componentsInMaintenanceMessage"}}></span> + {{/if}} + </td> <td>{{host.ip}}</td> <td>{{host.cpu}}</td> <td>{{host.memoryFormatted}}</td> @@ -114,7 +129,7 @@ <td>{{host.loadAvg}}</td> <td> - <a href="#" class="host-components-expander" {{action toggleComponents target="view"}}> <span class="caret right"></span>{{view.componentsMessage}}</a> + <a href="#" class="host-components-expander" {{action toggleComponents target="view"}}> <span class="caret right"></span>{{view.content.hostComponents.length}} {{pluralize view.content.hostComponents.length singular="t:common.component" plural="t:common.components"}}</a> <div id="host-{{unbound host.hostName}}" class="host-components"> {{{view.labels}}} </div> @@ -124,7 +139,7 @@ {{else}} <tr> <td class="first"></td> - <td colspan="8"> + <td colspan="9"> {{t hosts.table.noHosts}} </td> </tr> http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/ambari-web/app/views/common/table_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/table_view.js b/ambari-web/app/views/common/table_view.js index e80c4d8..ecbf7d9 100644 --- a/ambari-web/app/views/common/table_view.js +++ b/ambari-web/app/views/common/table_view.js @@ -348,6 +348,7 @@ App.TableView = Em.View.extend({ var filterConditions = this.get('filterConditions'); if (!filterConditions.length) { this.set('filtersUsed', false); + return; } var filtersUsed = false; filterConditions.forEach(function(filterCondition) { http://git-wip-us.apache.org/repos/asf/ambari/blob/a440c0a8/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 4e455f7..110d9c2 100644 --- a/ambari-web/app/views/main/host.js +++ b/ambari-web/app/views/main/host.js @@ -44,6 +44,7 @@ App.MainHostView = App.TableView.extend({ didInsertElement: function() { this.addObserver('controller.clearFilters', this, this.clearFiltersObs); this.clearFiltersObs(); + this.addObserver('[email protected].@each', this, this.filter); }, sortView: sort.wrapperView, @@ -93,16 +94,10 @@ App.MainHostView = App.TableView.extend({ this.$('.host-components').toggle(); }, - componentsMessage: function() { - var count = this.get('content.hostComponents.length'); - if (count == 1) { - return count + ' ' + Em.I18n.t('common.component'); - } - else { - return count + ' ' + Em.I18n.t('common.components'); - } - }.property('content.hostComponents.@each'), - + /** + * Tooltip message for "Restart Required" icon + * @returns {String} + */ restartRequiredComponentsMessage: function() { var restartRequiredComponents = this.get('content.hostComponents').filterProperty('staleConfigs', true); var count = restartRequiredComponents.length; @@ -113,10 +108,31 @@ App.MainHostView = App.TableView.extend({ return Em.I18n.t('hosts.table.restartComponents.withoutNames').format(count); }.property('[email protected]'), + /** + * Tooltip message for "Maintenance" icon + * @returns {String} + */ + componentsInMaintenanceMessage: function() { + var componentsInMaintenance = this.get('content.hostComponents').filterProperty('workStatus', App.HostComponentStatus.maintenance); + var count = componentsInMaintenance.length; + if (count <= 5) { + return Em.I18n.t('hosts.table.componentsInMaintenance.withNames').format(componentsInMaintenance.getEach('displayName').join(', ')); + } + return Em.I18n.t('hosts.table.componentsInMaintenance.withoutNames').format(count); + }.property('[email protected]'), + + /** + * String with list of host components <code>displayName</code> + * @returns {String} + */ labels: function() { return this.get('content.hostComponents').getEach('displayName').join("<br />"); }.property('content.hostComponents.@each'), + /** + * CSS value for disk usage bar + * @returns {String} + */ usageStyle:function () { return "width:" + this.get('content.diskUsage') + "%"; }.property('content.diskUsage') @@ -132,6 +148,7 @@ App.MainHostView = App.TableView.extend({ var statusString = this.get('healthStatusValue'); var alerts = this.get('alerts'); var restart = this.get('restart'); + var maintenance = this.get('maintenance'); if(alerts) { return this.get('view.content').filterProperty('criticalAlertsCount').get('length'); } @@ -140,15 +157,20 @@ App.MainHostView = App.TableView.extend({ return this.get('view.content').filterProperty('componentsWithStaleConfigsCount').get('length'); } else { - if (statusString == "") { - return this.get('view.content').get('length'); + if (maintenance) { + return this.get('view.content').filterProperty('componentsInMaintenanceCount').get('length'); } else { - return this.get('view.content').filterProperty('healthClass', statusString ).get('length'); + if (statusString == "") { + return this.get('view.content').get('length'); + } + else { + return this.get('view.content').filterProperty('healthClass', statusString ).get('length'); + } } } } - }.property('[email protected]', '[email protected]', '[email protected][email protected]'), + }.property('[email protected]', '[email protected]', '[email protected]', '[email protected][email protected]'), label: function () { return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount')); @@ -172,7 +194,8 @@ App.MainHostView = App.TableView.extend({ 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, last: 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.maintenance'), healthStatusValue: 'health-status-MAINTENANCE', maintenance: true, last: true, isVisible: true }) ]; return categories; @@ -203,17 +226,29 @@ App.MainHostView = App.TableView.extend({ 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'); } 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'); + } else { - this.get('parentView').updateFilter(7, '', 'number'); - this.get('parentView').updateFilter(8, '', 'number'); - this.get('parentView').updateFilter(0, category.get('healthStatusValue'), 'string'); + 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'); + } + 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'); + } } } }, @@ -259,6 +294,23 @@ App.MainHostView = App.TableView.extend({ }), /** + * view of the maintenance filter implemented as a category of host statuses + */ + maintenanceFilter: Em.View.extend({ + column: 9, + value: null, + classNames: ['noDisplay'], + showClearFilter: function(){ + var mockEvent = { + context: this.get('parentView.categories').findProperty('healthStatusValue', 'health-status-MAINTENANCE') + }; + if(this.get('value')) { + this.get('parentView.childViews').findProperty('column', 0).selectCategory(mockEvent); + } + } + }), + + /** * Filter view for name column * Based on <code>filters</code> library */ @@ -453,6 +505,7 @@ App.MainHostView = App.TableView.extend({ associations[6] = 'hostComponents'; associations[7] = 'criticalAlertsCount'; associations[8] = 'componentsWithStaleConfigsCount'; + associations[9] = 'componentsInMaintenanceCount'; return associations; }.property() }); \ No newline at end of file
