Repository: ambari Updated Branches: refs/heads/trunk 53dbf69f9 -> 5a2b89464
AMBARI-9625. Autoclosing of expanding elements on Hosts page (alexantonenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5a2b8946 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5a2b8946 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5a2b8946 Branch: refs/heads/trunk Commit: 5a2b894644334e06e3567f6936858db1873ecc5d Parents: 53dbf69 Author: Alex Antonenko <hiv...@gmail.com> Authored: Fri Feb 13 22:54:59 2015 +0200 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Fri Feb 13 22:54:59 2015 +0200 ---------------------------------------------------------------------- ambari-web/app/assets/test/tests.js | 1 + ambari-web/app/controllers/main/host.js | 4 + ambari-web/app/styles/application.less | 3 +- ambari-web/app/templates/main/host.hbs | 4 +- ambari-web/app/views/main/host.js | 43 ++++- ambari-web/test/views/main/host_test.js | 264 +++++++++++++++++++++++++++ 6 files changed, 306 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/ambari-web/app/assets/test/tests.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js index bd16cde..f9b3f18 100644 --- a/ambari-web/app/assets/test/tests.js +++ b/ambari-web/app/assets/test/tests.js @@ -166,6 +166,7 @@ var files = ['test/init_model_test', 'test/views/common/progress_bar_view_test', 'test/views/main/dashboard_test', 'test/views/main/menu_test', + 'test/views/main/host_test', 'test/views/main/alert_definitions_view_test', 'test/views/main/alerts/manage_alert_groups_view_test', 'test/views/main/alerts/manage_alert_notifications_view_test', http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/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 9511be8..2ea463b 100644 --- a/ambari-web/app/controllers/main/host.js +++ b/ambari-web/app/controllers/main/host.js @@ -43,6 +43,10 @@ App.MainHostController = Em.ArrayController.extend(App.TableServerMixin, { startIndex: 1, + expandedComponentsSections: [], + + expandedVersionsSections: [], + /** * Components which will be shown in component filter * @returns {Array} http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/ambari-web/app/styles/application.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less index ae5c756..11b310b 100644 --- a/ambari-web/app/styles/application.less +++ b/ambari-web/app/styles/application.less @@ -3222,7 +3222,6 @@ table.graphs { } } .collapsed-list { - display: none; padding-left: 10px; } .host-table-versions { @@ -5525,4 +5524,4 @@ input[type="checkbox"].align-checkbox { .bottom-border { border-bottom: 1px solid #dddddd; -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/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 c76ab34..3474686 100644 --- a/ambari-web/app/templates/main/host.hbs +++ b/ambari-web/app/templates/main/host.hbs @@ -139,14 +139,14 @@ {{/unless}} {{view.currentVersion}} </a> - <div class="stack-versions collapsed-list"> + <div {{bindAttr class="view.isVersionsCollapsed:noDisplay:display :stack-versions :collapsed-list"}}> {{{view.versionlabels}}} </div> </td> <td class="host-table-components"> <a href="#" class="expander" {{action toggleComponents target="view"}}> <span {{bindAttr class="view.isComponentsCollapsed:icon-caret-right:icon-caret-down"}}></span> {{view.content.hostComponents.length}} {{pluralize view.content.hostComponents.length singular="t:common.component" plural="t:common.components"}}</a> - <div class="host-components collapsed-list"> + <div {{bindAttr class="view.isComponentsCollapsed:noDisplay:display :host-components :collapsed-list"}}> {{{view.labels}}} </div> </td> http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/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 f116e6c..79e3572 100644 --- a/ambari-web/app/views/main/host.js +++ b/ambari-web/app/views/main/host.js @@ -218,12 +218,26 @@ App.MainHostView = App.TableView.extend(App.TableServerViewMixin, { this.clearFiltersObs(); this.addObserver('selectAllHosts', this, this.toggleAllHosts); this.addObserver('filteringComplete', this, this.overlayObserver); - this.addObserver('startIndex', this, 'updatePagination'); + this.addObserver('startIndex', this, 'updateHostsPagination'); this.addObserver('displayLength', this, 'updatePagination'); this.addObserver('filteredCount', this, this.updatePaging); this.overlayObserver(); }, + updateHostsPagination: function () { + this.clearExpandedSections(); + this.updatePagination(); + }, + + willDestroyElement: function () { + this.clearExpandedSections(); + }, + + clearExpandedSections: function () { + this.get('controller.expandedComponentsSections').clear(); + this.get('controller.expandedVersionsSections').clear(); + }, + onInitialLoad: function () { if (this.get('tableFilteringComplete')) { this.refresh(); @@ -526,19 +540,30 @@ App.MainHostView = App.TableView.extend(App.TableServerViewMixin, { content:null, tagName: 'tr', didInsertElement: function(){ + var hostName = this.get('content.hostName'); App.tooltip(this.$("[rel='HealthTooltip'], [rel='UsageTooltip'], [rel='ComponentsTooltip']")); - this.set('isComponentsCollapsed', true); - this.set('isVersionsCollapsed', true); + this.set('isComponentsCollapsed', !this.get('controller.expandedComponentsSections').contains(hostName)); + this.set('isVersionsCollapsed', !this.get('controller.expandedVersionsSections').contains(hostName)); + }, + + toggleList: function (flagName, arrayName) { + var arrayPropertyName = 'controller.' + arrayName; + var hostNameArray = this.get(arrayPropertyName); + var hostName = this.get('content.hostName'); + this.toggleProperty(flagName); + if (this.get(flagName)) { + this.set(arrayPropertyName, hostNameArray.without(hostName)); + } else { + hostNameArray.push(hostName); + } }, - toggleComponents: function(event) { - this.toggleProperty('isComponentsCollapsed'); - this.$('.host-components').toggle(); + toggleComponents: function () { + this.toggleList('isComponentsCollapsed', 'expandedComponentsSections'); }, - toggleVersions: function(){ - this.toggleProperty('isVersionsCollapsed'); - this.$('.stack-versions').toggle(); + toggleVersions: function () { + this.toggleList('isVersionsCollapsed', 'expandedVersionsSections'); }, /** http://git-wip-us.apache.org/repos/asf/ambari/blob/5a2b8946/ambari-web/test/views/main/host_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/host_test.js b/ambari-web/test/views/main/host_test.js new file mode 100644 index 0000000..84579c2 --- /dev/null +++ b/ambari-web/test/views/main/host_test.js @@ -0,0 +1,264 @@ +/** + * 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'); +require('views/main/host'); + +describe('App.MainHostView', function () { + + var view; + + beforeEach(function () { + view = App.MainHostView.create({ + controller: App.MainHostController.create() + }); + }); + + describe('#didInsertElement', function () { + + var cases = [ + { + methodName: 'clearFiltersObs', + propertyToChange: 'controller.clearFilters', + callCount: 2 + }, + { + methodName: 'toggleAllHosts', + propertyToChange: 'selectAllHosts', + callCount: 1 + }, + { + methodName: 'overlayObserver', + propertyToChange: 'filteringComplete', + callCount: 2 + }, + { + methodName: 'updateHostsPagination', + propertyToChange: 'startIndex', + callCount: 1 + }, + { + methodName: 'updatePagination', + propertyToChange: 'displayLength', + callCount: 1 + }, + { + methodName: 'updatePaging', + propertyToChange: 'filteredCount', + callCount: 2 + } + ], + title = '{0} changed'; + + beforeEach(function () { + cases.forEach(function (item) { + sinon.stub(view, item.methodName, Em.K); + }); + }); + + afterEach(function () { + cases.forEach(function (item) { + view[item.methodName].restore(); + }); + }); + + cases.forEach(function (item) { + it(title.format(item.propertyToChange), function () { + view.didInsertElement(); + view.propertyDidChange(item.propertyToChange); + expect(view[item.methodName].callCount).to.equal(item.callCount); + }); + }); + + }); + + describe('#updateHostsPagination', function () { + + beforeEach(function () { + sinon.stub(view, 'clearExpandedSections', Em.K); + sinon.stub(view, 'updatePagination', Em.K); + }); + + afterEach(function () { + view.clearExpandedSections.restore(); + view.updatePagination.restore(); + }); + + it('should execute clearExpandedSections and updatePagination', function () { + view.updateHostsPagination(); + expect(view.clearExpandedSections.calledOnce).to.be.true; + expect(view.updatePagination.calledOnce).to.be.true; + }); + + }); + + describe('#willDestroyElement', function () { + + beforeEach(function () { + sinon.stub(view, 'clearExpandedSections', Em.K); + }); + + afterEach(function () { + view.clearExpandedSections.restore(); + }); + + it('should execute clearExpandedSections', function () { + view.willDestroyElement(); + expect(view.clearExpandedSections.calledOnce).to.be.true; + }); + + }); + + describe('#clearExpandedSections', function () { + + it('should clear expandedComponentsSections and expandedVersionsSections from controller', function () { + view.get('controller').setProperties({ + expandedComponentsSections: [''], + expandedVersionsSections: [''] + }); + view.clearExpandedSections(); + expect(view.get('controller.expandedComponentsSections')).to.have.length(0); + expect(view.get('controller.expandedVersionsSections')).to.have.length(0); + }); + + }); + + describe('#HostView', function () { + + var hostView; + + beforeEach(function () { + hostView = view.HostView.create({ + content: { + hostName: null + }, + controller: App.MainHostController.create() + }); + }); + + describe('#didInsertElement', function () { + + var cases = [ + { + expandedSections: ['h0'], + isCollapsed: false, + title: '{0} section should be expanded' + }, + { + expandedSections: ['h1'], + isCollapsed: true, + title: '{0} section should be collapsed' + } + ], + testMethod = function (item, elementsName, arrayName, propertyName) { + it(item.title.format(elementsName), function () { + hostView.set('content.hostName', 'h0'); + hostView.set('controller.' + arrayName, item.expandedSections); + hostView.didInsertElement(); + expect(App.tooltip.calledOnce).to.be.true; + expect(hostView.get(propertyName)).to.equal(item.isCollapsed); + }); + }; + + beforeEach(function () { + sinon.stub(App, 'tooltip', Em.K); + }); + + afterEach(function () { + App.tooltip.restore(); + }); + + cases.forEach(function (item) { + testMethod(item, 'components', 'expandedComponentsSections', 'isComponentsCollapsed'); + testMethod(item, 'versions', 'expandedVersionsSections', 'isVersionsCollapsed'); + }); + + }); + + describe('#toggleList', function () { + + var cases = [ + { + isCollapsed: false, + isCollapsedAfter: true, + expandedSections: ['h0'], + expandedSectionsAfter: [], + title: 'section becomes collapsed' + }, + { + isCollapsed: true, + isCollapsedAfter: false, + expandedSections: [], + expandedSectionsAfter: ['h0'], + title: 'section becomes expanded' + } + ]; + + cases.forEach(function (item) { + it(item.title, function () { + hostView.set('content.hostName', 'h0'); + hostView.set('isComponentsCollapsed', item.isCollapsed); + hostView.set('controller.expandedComponentsSections', item.expandedSections); + hostView.toggleList('isComponentsCollapsed', 'expandedComponentsSections'); + expect(hostView.get('isComponentsCollapsed')).to.equal(item.isCollapsedAfter); + expect(hostView.get('controller.expandedComponentsSections')).to.eql(item.expandedSectionsAfter); + }); + }); + + }); + + describe('#toggleComponents', function () { + + beforeEach(function () { + sinon.stub(hostView, 'toggleList', Em.K); + }); + + afterEach(function () { + hostView.toggleList.restore(); + }); + + it('should toggle components list', function () { + hostView.toggleComponents(); + expect(hostView.toggleList.calledOnce).to.be.true; + expect(hostView.toggleList.calledWith('isComponentsCollapsed', 'expandedComponentsSections')).to.be.true; + }); + + }); + + describe('#toggleVersions', function () { + + beforeEach(function () { + sinon.stub(hostView, 'toggleList', Em.K); + }); + + afterEach(function () { + hostView.toggleList.restore(); + }); + + it('should toggle components list', function () { + hostView.toggleVersions(); + expect(hostView.toggleList.calledOnce).to.be.true; + expect(hostView.toggleList.calledWith('isVersionsCollapsed', 'expandedVersionsSections')).to.be.true; + }); + + }); + + }); + +});