Repository: ambari Updated Branches: refs/heads/side-navigation-feature-branch c7164d8ea -> d8af6aba4
AMBARI-19974. Test and fix new Notifications/Alerts styles on Ambari.(xiwang) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/d8af6aba Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/d8af6aba Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/d8af6aba Branch: refs/heads/side-navigation-feature-branch Commit: d8af6aba46fe3c62b9b5a4d42b2f716b649c20bd Parents: c7164d8 Author: Xi Wang <xiw...@apache.org> Authored: Fri Feb 10 14:13:13 2017 -0800 Committer: Xi Wang <xiw...@apache.org> Committed: Wed Feb 15 10:39:41 2017 -0800 ---------------------------------------------------------------------- .../main/alert_definitions_controller.js | 14 +- .../main/alerts/alert_instances_controller.js | 151 --------------- ambari-web/app/messages.js | 5 + .../app/styles/theme/bootstrap-ambari.css | 152 +++++++++++++++ ambari-web/app/styles/top-nav.less | 20 +- ambari-web/app/templates/application.hbs | 57 +++--- .../main/alerts/alert_notifications_popup.hbs | 69 +++++++ ambari-web/app/views.js | 1 + .../main/alerts/alert_instances_popup_view.js | 190 +++++++++++++++++++ .../alerts/alert_instances_controller_test.js | 33 ---- 10 files changed, 480 insertions(+), 212 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/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 0cfff21..5488fbb 100644 --- a/ambari-web/app/controllers/main/alert_definitions_controller.js +++ b/ambari-web/app/controllers/main/alert_definitions_controller.js @@ -119,7 +119,7 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({ }, /** - * ========================== alerts popup dialog ========================= + * ========================== alerts notifications dropdown dialog ========================= */ /** @@ -128,8 +128,18 @@ App.MainAlertDefinitionsController = Em.ArrayController.extend({ * @type {Number} */ unhealthyAlertInstancesCount: function () { + return this.get('criticalAlertInstancesCount') + this.get('warningAlertInstancesCount'); + }.property('criticalAlertInstancesCount', 'warningAlertInstancesCount'), + + criticalAlertInstancesCount: function () { + return this.get('content').map(function (alertDefinition) { + return alertDefinition.getWithDefault('summary.CRITICAL.count', 0); + }).reduce(Em.sum, 0); + }.property('content.@each.summary'), + + warningAlertInstancesCount: function () { return this.get('content').map(function (alertDefinition) { - return alertDefinition.getWithDefault('summary.CRITICAL.count', 0) + alertDefinition.getWithDefault('summary.WARNING.count', 0); + return alertDefinition.getWithDefault('summary.WARNING.count', 0); }).reduce(Em.sum, 0); }.property('content.@each.summary'), http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/controllers/main/alerts/alert_instances_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/alerts/alert_instances_controller.js b/ambari-web/app/controllers/main/alerts/alert_instances_controller.js index cbeb71a..30eb999 100644 --- a/ambari-web/app/controllers/main/alerts/alert_instances_controller.js +++ b/ambari-web/app/controllers/main/alerts/alert_instances_controller.js @@ -193,157 +193,6 @@ App.MainAlertInstancesController = Em.Controller.extend({ */ getAlertInstancesErrorCallback: function () { this.set('isLoaded', true); - }, - - /** - * Onclick handler for alerts number located right to bg ops number (see application.hbs) - * @method showPopup - * @return {App.ModalPopup} - */ - showPopup: function () { - - var self = this; - - return App.ModalPopup.show({ - - alertsNumberBinding: 'App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount', - - header: Em.computed.i18nFormat('alerts.fastAccess.popup.header', 'alertsNumber'), - - classNames: ['common-modal-wrapper', 'alerts-popup'], - modalDialogClasses: ['modal-lg'], - - secondary: Em.I18n.t('alerts.fastAccess.popup.body.showmore'), - - autoHeight: false, - - isHideBodyScroll: true, - - onSecondary: function () { - this._super(); - App.router.transitionTo('main.alerts.index'); - }, - - bodyClass: App.TableView.extend(App.TableServerViewMixin, { - - updaterBinding: 'App.router.updateController', - - templateName: require('templates/common/modal_popups/alerts_popup'), - - controller: self, - - isPaginate: true, - - willInsertElement: function () { - this._super(); - this.updateAlertInstances(); - }, - - /** - * Number of all critical and warning alert instances - * @type {Boolean} - */ - filteredCount: Em.computed.alias('App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount'), - - content: function () { - return this.get('controller.unhealthyAlertInstances'); - }.property('controller.unhealthyAlertInstances.@each.state'), - - isLoaded: Em.computed.bool('controller.unhealthyAlertInstances'), - - isAlertEmptyList: Em.computed.empty('content'), - - /** - * Update list of shown alert instances - * @method updateAlertInstances - */ - updateAlertInstances: function () { - var self = this, - displayLength = this.get('displayLength'), - startIndex = this.get('startIndex'); - if (!displayLength) return; // wait while table-info is loaded - this.get('updater').set('queryParamsForUnhealthyAlertInstances', { - from: startIndex - 1, - page_size: displayLength - }); - this.set('filteringComplete', false); - this.get('updater').updateUnhealthyAlertInstances(function() { - self.set('filteringComplete', true); - }); - }.observes('displayLength', 'startIndex'), - - /** - * Show spinner when filter/sorting request is in processing - * @method overlayObserver - */ - overlayObserver: function() { - var $tbody = this.$('#alert-info'), - $overlay = this.$('.table-overlay'), - $spinner = $($overlay).find('.spinner'); - if (!this.get('filteringComplete')) { - if (!$tbody) return; - var tbodyPos = $tbody.position(); - if (!tbodyPos) return; - $spinner.css('display', 'block'); - $overlay.css({ - top: tbodyPos.top + 1, - left: tbodyPos.left + 1, - width: $tbody.width() - 1, - height: $tbody.height() - 1 - }); - } - }, - - /** - * No filtering for alert definitions - * @method filter - */ - filter: function() { - this.set('filteredContent', this.get('content')); - }.observes('content.length'), - - /** - * Router transition to alert definition details page - * @param event - */ - gotoAlertDetails: function (event) { - if (event && event.context) { - this.get('parentView').hide(); - var definition = App.AlertDefinition.find().findProperty('id', event.context.get('definitionId')); - App.router.transitionTo('main.alerts.alertDetails', definition); - } - }, - - /** - * Router transition to service summary page - * @param event - */ - goToService: function (event) { - if (event && event.context) { - this.get('parentView').hide(); - App.router.transitionTo('main.services.service.summary', event.context); - } - }, - - /** - * Router transition to host level alerts page - * @param event - */ - goToHostAlerts: function (event) { - if (event && event.context) { - this.get('parentView').hide(); - App.router.transitionTo('main.hosts.hostDetails.alerts', event.context); - } - }, - - didInsertElement: function () { - this.filter(); - this.addObserver('filteringComplete', this, this.overlayObserver); - this.overlayObserver(); - return this._super(); - } - }) - }); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index cb88fda..6e58823 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -1085,6 +1085,11 @@ Em.I18n.translations = { 'form.validator.alertNotificationName':'Invalid Alert Notification Name. Only alphanumerics, hyphens, spaces and underscores are allowed.', 'form.validator.configKey.specific':'"{0}" is invalid Key. Only alphanumerics, hyphens, underscores, asterisks and periods are allowed.', + 'alerts.dropdown.dialog.title': 'Notifications', + 'alerts.dropdown.dialog.filters.critical': 'Critical ({0})', + 'alerts.dropdown.dialog.filters.warning': 'Warning ({0})', + 'alerts.dropdown.dialog.filters.all': 'All ({0})', + 'alerts.add.header': 'Create Alert', 'alerts.add.step1.header': 'Choose Alert Type', 'alerts.add.step1.header.description': 'Select the type of alert you want to create', http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/styles/theme/bootstrap-ambari.css ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/theme/bootstrap-ambari.css b/ambari-web/app/styles/theme/bootstrap-ambari.css index d17e423..36a63a3 100644 --- a/ambari-web/app/styles/theme/bootstrap-ambari.css +++ b/ambari-web/app/styles/theme/bootstrap-ambari.css @@ -1037,6 +1037,7 @@ input.radio:checked + label:after { .navigation-bar-container.collapsed ul.nav.side-nav-footer li.submenu-li.active > a { padding-left: 19px; } + .navigation-bar-fit-height { position: fixed; top: 0; @@ -1059,6 +1060,157 @@ input.radio:checked + label:after { .navigation-bar-fit-height .navigation-bar-container:not(.collapsed) .side-nav-menu { overflow-y: auto; } + +.notifications-group { + position: relative; + top: 1px; +} +#notifications-dropdown.dropdown-menu { + min-width: 300px; + max-width: 300px; + min-height: 150px; + padding: 0px; + z-index: 1000; + right: -50px; + left: auto; + top: 260%; + border: none; + -webkit-box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.29); + -moz-box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.29); + box-shadow: 0px 2px 10px 2px rgba(0, 0, 0, 0.29); +} +#notifications-dropdown.dropdown-menu .popup-arrow-up { + position: absolute; + right: 37px; + top: -40px; + width: 40px; + height: 40px; + overflow: hidden; +} +#notifications-dropdown.dropdown-menu .popup-arrow-up:after { + content: ""; + position: absolute; + width: 20px; + height: 20px; + background: #fff; + transform: rotate(45deg); + top: 30px; + left: 10px; + box-shadow: -1px -1px 10px -2px rgba(0, 0, 0, 0.5); +} +#notifications-dropdown.dropdown-menu .notifications-header { + border-bottom: 1px solid #eee; + padding: 15px 20px; +} +#notifications-dropdown.dropdown-menu .notifications-header .notifications-title { + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 16px; +} +#notifications-dropdown.dropdown-menu .notifications-body { + padding: 0px 15px; + overflow: auto; + max-height: 500px; +} +#notifications-dropdown.dropdown-menu .notifications-body .no-alert-text { + padding: 15px 5px; +} +#notifications-dropdown.dropdown-menu .notifications-body .table-controls { + padding: 10px 0px; + margin: 0px; + border-bottom: 1px solid #eee; +} +#notifications-dropdown.dropdown-menu .notifications-body .table-controls .state-filter { + padding: 0px; + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + font-size: 12px; + color: #666; + position: relative; +} +#notifications-dropdown.dropdown-menu .notifications-body .table-controls .state-filter .form-control.filter-select { + font-size: 12px; + color: #666; + height: 25px; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table { + margin-top: 0px; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody tr { + cursor: pointer; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody tr.no-alert-tr:hover { + cursor: default; + border-color: transparent; + border-bottom-color: #eee; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody tr.no-alert-tr:hover > td { + border-color: transparent; + background-color: white; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.status { + width: 9%; + padding: 15px 3px; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.status .alert-state-CRITICAL { + color: #EF6162; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.status .alert-state-WARNING { + color: #E98A41; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.content { + width: 90%; + padding: 15px 3px 10px 3px; + font-family: 'Roboto', sans-serif; + font-weight: normal; + font-style: normal; + line-height: 1; + color: #333; + line-height: 1.3; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.content .name { + font-weight: bold; + font-size: 12px; + color: #666; + margin-bottom: 5px; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.content .description { + font-size: 12px; + color: #666; + margin-bottom: 4px; + display: block; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + /* Break long urls*/ + overflow-wrap: break-word; + word-wrap: break-word; + -ms-word-break: break-all; + word-break: break-all; + word-break: break-word; + /* Adds a hyphen where the word breaks*/ + -ms-hyphens: auto; + -moz-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} +#notifications-dropdown.dropdown-menu .notifications-body .table.alerts-table tbody td.content .timestamp { + text-align: right; + font-size: 11px; + color: #999; +} +#notifications-dropdown.dropdown-menu .notifications-footer { + border-top: 1px solid #eee; + padding: 15px; +} h1, h2, h3, http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/styles/top-nav.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/top-nav.less b/ambari-web/app/styles/top-nav.less index d1c723a..78c804f 100644 --- a/ambari-web/app/styles/top-nav.less +++ b/ambari-web/app/styles/top-nav.less @@ -38,7 +38,13 @@ } } + .cluster-notifications { + margin-top: 12px; + } .navbar-text.brand-wrapper { + margin-top: 17px; + } + .navbar-text.brand-wrapper, .cluster-notifications { color: @top-nav-brand-color; font-size: 16px; font-weight: normal; @@ -51,6 +57,11 @@ position: relative; } + span.alerts-label { + line-height: 20px; + cursor: pointer; + } + .numberCircle { border-radius: 50%; width: 20px; @@ -94,9 +105,14 @@ a:hover { text-decoration: none; } + .top-nav-user { + margin-top: 2px; + } } - .top-nav-user { - margin-top: 2px; + #notifications-dropdown.dropdown-menu { + .popup-arrow-up { + right: 75px; + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/templates/application.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/application.hbs b/ambari-web/app/templates/application.hbs index 25c3311..94d8337 100644 --- a/ambari-web/app/templates/application.hbs +++ b/ambari-web/app/templates/application.hbs @@ -127,16 +127,8 @@ {{/if}} {{! user dropdown end }} - <div class="navbar-nav navbar-text navbar-right brand-wrapper"> + <div class="navbar-nav navbar-right cluster-notifications"> {{#if enableLinks}} - - {{! cluster name }} - <a href="#" {{bindAttr title="clusterName"}} {{action "showPopup" target="App.router.backgroundOperationsController"}} class="cluster-name"> - {{#unless App.isClusterUser}} - <span>{{clusterDisplayName}}</span> - {{/unless}} - </a> - {{! cluster name end }} {{! bg label }} <a href="#" class="bg-label" {{action "showPopup" target="App.router.backgroundOperationsController"}}> {{#with App.router.backgroundOperationsController}} @@ -147,27 +139,44 @@ {{/with}} </a> {{! bg label end }} - {{! alerts label }} + + {{! new alerts label }} {{#if App.router.clusterController.isAlertsLoaded}} - <a href="#" class="alerts-label" {{action "showPopup" target="App.router.mainAlertInstancesController"}}> - {{#if App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} + <span class="notifications-group"> + <span class="alerts-label dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <span class="glyphicon glyphicon-bell"></span> - {{! alerts exist }} - <span {{bindAttr class=":numberCircle App.router.mainAlertDefinitionsController.isCriticalAlerts:alert-crit-count:alert-warn-count"}}> - {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} - </span> - {{else}} - {{! no alerts }} - <span {{translateAttr title="titlebar.alerts.noAlerts"}} class="numberCircle alerts-none-count"> - {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} - </span> - {{/if}} - </a> + {{#if App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} + {{! alerts exist }} + <span {{bindAttr class=":numberCircle App.router.mainAlertDefinitionsController.isCriticalAlerts:alert-crit-count:alert-warn-count"}}> + {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} + </span> + {{else}} + {{! no alerts }} + <span {{translateAttr title="titlebar.alerts.noAlerts"}} class="numberCircle alerts-none-count"> + {{App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount}} + </span> + {{/if}} + </span> + <div id="notifications-dropdown" class="dropdown-menu row"> + {{view App.AlertInstancesPopupView}} + </div> + </span> {{/if}} - {{! alerts label end }} + {{! alerts label end }} {{/if}} </div> + <div class="navbar-nav navbar-text navbar-right brand-wrapper"> + {{#if enableLinks}} + {{! cluster name }} + <a href="#" {{bindAttr title="clusterName"}} {{action "showPopup" target="App.router.backgroundOperationsController"}} class="cluster-name"> + {{#unless App.isClusterUser}} + <span>{{clusterDisplayName}}</span> + {{/unless}} + </a> + {{! cluster name end }} + {{/if}} + </div> </div> </nav> </div> http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/templates/main/alerts/alert_notifications_popup.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/main/alerts/alert_notifications_popup.hbs b/ambari-web/app/templates/main/alerts/alert_notifications_popup.hbs new file mode 100644 index 0000000..a5f2bf2 --- /dev/null +++ b/ambari-web/app/templates/main/alerts/alert_notifications_popup.hbs @@ -0,0 +1,69 @@ +{{! +* 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. +}} + +<div class="popup-arrow-up"></div> +<div class="notifications-header col-sm-12"> + <div class="notifications-title">{{t alerts.dropdown.dialog.title}} ({{view.alertsNumber}})</div> +</div> + +<div class="notifications-body col-sm-12"> + {{#if view.isLoaded}} + <div class="table-controls row"> + <div class="state-filter pull-right"> + <span>{{t common.show}}: </span> + <div class="btn-group"> + {{view Ember.Select + contentBinding="view.categories" + optionValuePath="content.value" + optionLabelPath="content.label" + selectionBinding="view.selectedCategory" + classNames="filter-select form-control" + }} + </div> + </div> + </div> + <table class="alerts-table table table-hover"> + <tbody> + {{#if view.isAlertEmptyList}} + <tr class="no-alert-tr"> + <td class="no-alert-text">{{t alerts.fastAccess.popup.body.noalerts}}</td> + </tr> + {{else}} + {{#each instance in view.pageContent}} + <tr {{action "gotoAlertDetails" instance target="view"}} {{bindAttr class="instance.isVisible::hidden"}}> + <td class="status"> + <span {{bindAttr class="instance.stateClass :icon-circle"}}></span> + </td> + <td class="content"> + <div class="name">{{instance.label}}</div> + <div class="description">{{instance.text}}</div> + <div class="timestamp">{{instance.lastTriggeredAgoFormatted}}</div> + </td> + </tr> + {{/each}} + {{/if}} + </tbody> + </table> + {{else}} + {{view App.SpinnerView}} + {{/if}} +</div> + +<div class="notifications-footer col-sm-12"> + <button type="button" class="btn btn-primary pull-right" {{action "gotoAllAlerts" target="view"}}>View All</button> +</div> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/views.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js index 77b5d5a..1a2a887 100644 --- a/ambari-web/app/views.js +++ b/ambari-web/app/views.js @@ -129,6 +129,7 @@ require('views/main/alerts/add_alert_definition/step2_view'); require('views/main/alerts/add_alert_definition/step3_view'); require('views/main/alerts'); require('views/main/alerts/manage_alert_groups_view'); +require('views/main/alerts/alert_instances_popup_view'); require('views/main/alerts/manage_alert_notifications_view'); require('views/main/charts'); require('views/main/views/details'); http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/app/views/main/alerts/alert_instances_popup_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/alerts/alert_instances_popup_view.js b/ambari-web/app/views/main/alerts/alert_instances_popup_view.js new file mode 100644 index 0000000..6524f30 --- /dev/null +++ b/ambari-web/app/views/main/alerts/alert_instances_popup_view.js @@ -0,0 +1,190 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var App = require('app'); + +/** + * Option for "filter by state" drop down + * @typedef {object} categoryObject + * @property {string} value "all|warning|critical" + * @property {number} count number of items with <code>state</code> equal to <code>this.value</code> + * @property {string} labelPath key in the messages.js + * @property {string} label localized label + */ +var categoryObject = Em.Object.extend({ + value: '', + count: 0, + labelPath: '', + label: function () { + return Em.I18n.t(this.get('labelPath')).format(this.get('count')); + }.property('count', 'labelPath') +}); + +App.AlertInstancesPopupView = App.TableView.extend(App.TableServerViewMixin, { + + templateName: require('templates/main/alerts/alert_notifications_popup'), + + updaterBinding: 'App.router.updateController', + + controllerBinding: 'App.router.mainAlertInstancesController', + + /** + * Number of all critical and warning alert instances + * @type {Boolean} + */ + alertsNumberBinding: 'App.router.mainAlertDefinitionsController.unhealthyAlertInstancesCount', + criticalNumberBinding: 'App.router.mainAlertDefinitionsController.criticalAlertInstancesCount', + warningNumberBinding: 'App.router.mainAlertDefinitionsController.warningAlertInstancesCount', + + isPaginate: false, + + willInsertElement: function () { + this._super(); + this.updateAlertInstances(); + }, + + didInsertElement: function () { + this.filter(); + this.addObserver('filteringComplete', this, this.overlayObserver); + this.overlayObserver(); + $(".notifications-body .filter-select ").click(function(event){ + event.stopPropagation(); + }); + return this._super(); + }, + + content: function () { + return this.get('controller.unhealthyAlertInstances'); + }.property('controller.unhealthyAlertInstances.@each.state'), + + isLoaded: Em.computed.bool('controller.unhealthyAlertInstances'), + + isAlertEmptyList: Em.computed.or('isAlertContentEmptyList', 'isAlertFilterdEmptyList'), + isAlertContentEmptyList: Em.computed.empty('content'), + isAlertFilterdEmptyList: Em.computed.everyBy('content', 'isVisible', false), + + displayLength: 100, + + /** + * Update list of shown alert instances + * @method updateAlertInstances + */ + updateAlertInstances: function () { + var self = this, + displayLength = this.get('displayLength'), + startIndex = this.get('startIndex'); + if (!displayLength) return; // wait while table-info is loaded + this.get('updater').set('queryParamsForUnhealthyAlertInstances', { + from: startIndex - 1, + page_size: displayLength + }); + this.set('filteringComplete', false); + this.get('updater').updateUnhealthyAlertInstances(function() { + self.set('filteringComplete', true); + }); + }.observes('displayLength', 'startIndex', 'alertsNumber'), + + /** + * Show spinner when filter/sorting request is in processing + * @method overlayObserver + */ + overlayObserver: function() { + var $tbody = this.$('.table.alerts-table'), + $overlay = this.$('.table-overlay'), + $spinner = $($overlay).find('.spinner'); + if (!this.get('filteringComplete')) { + if (!$tbody) return; + var tbodyPos = $tbody.position(); + if (!tbodyPos) return; + $spinner.css('display', 'block'); + $overlay.css({ + top: tbodyPos.top + 1, + left: tbodyPos.left + 1, + width: $tbody.width() - 1, + height: $tbody.height() - 1 + }); + } + }, + + categories: function () { + var allCnt = this.get('alertsNumber'); + var criticalCnt = this.get('criticalNumber'); + var warningCnt = this.get('warningNumber'); + return [ + categoryObject.create({ + value: 'all', + labelPath: 'alerts.dropdown.dialog.filters.all', + count: allCnt + }), + categoryObject.create({ + value: 'alert-state-CRITICAL', + labelPath: 'alerts.dropdown.dialog.filters.critical', + count: criticalCnt + }), + categoryObject.create({ + value: 'alert-state-WARNING', + labelPath: 'alerts.dropdown.dialog.filters.warning', + count: warningCnt + }) + ]; + }.property('criticalNumber', 'warningNumber', 'alertsNumber'), + + selectedCategory: null, + + /** + * Filter notifications by state + * @method filter + */ + filter: function() { + var selectedState = this.get('selectedCategory.value'); + var content = this.get('content'); + if (selectedState == 'all') { + content.setEach("isVisible", true); + this.set('filteredContent', content); + } else { + this.set('filteredContent', content.filter(function (item) { + if (item.get('stateClass') == selectedState) { + item.set('isVisible', true); + return true; + } else { + item.set('isVisible', false); + return false; + } + })); + } + }.observes('content.length', 'selectedCategory'), + + /** + * Router transition to alert definition details page + * @param event + */ + gotoAlertDetails: function (event) { + if (event && event.context) { + var definition = App.AlertDefinition.find().findProperty('id', event.context.get('definitionId')); + App.router.transitionTo('main.alerts.alertDetails', definition); + } + }, + + /** + * Router transition to alert definition page + */ + gotoAllAlerts: function () { + App.router.transitionTo('main.alerts.index'); + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/d8af6aba/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js b/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js index 94653c7..5b53323 100644 --- a/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js +++ b/ambari-web/test/controllers/main/alerts/alert_instances_controller_test.js @@ -64,37 +64,4 @@ describe('App.MainAlertInstancesController', function () { }); - - describe('#showPopup', function () { - - describe('#bodyClass', function () { - - var bodyView; - - beforeEach(function () { - controller.reopen({unhealthyAlertInstances: [ - App.AlertInstance.createRecord({state: 'CRITICAL'}), - App.AlertInstance.createRecord({state: 'WARNING'}), - App.AlertInstance.createRecord({state: 'WARNING'}), - App.AlertInstance.createRecord({state: 'CRITICAL'}) - ]}); - bodyView = controller.showPopup().get('bodyClass').create(); - }); - - it('#content', function () { - expect(bodyView.get('content.length')).to.equal(4); - }); - - it('#isLoaded', function () { - expect(bodyView.get('isLoaded')).to.be.true; - }); - - it('#isAlertEmptyList', function () { - expect(bodyView.get('isAlertEmptyList')).to.be.false; - }); - - }); - - }); - }); \ No newline at end of file