You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by at...@apache.org on 2014/03/27 13:11:21 UTC
git commit: AMBARI-5237 Implement pagination on "Confirm Hosts" step.
(atkach)
Repository: ambari
Updated Branches:
refs/heads/trunk a3d1d6732 -> 74ef96200
AMBARI-5237 Implement pagination on "Confirm Hosts" step. (atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/74ef9620
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/74ef9620
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/74ef9620
Branch: refs/heads/trunk
Commit: 74ef96200a8b8ba1bc761d5ad7d561d35721cc4a
Parents: a3d1d67
Author: atkach <at...@hortonworks.com>
Authored: Thu Mar 27 14:08:14 2014 +0200
Committer: atkach <at...@hortonworks.com>
Committed: Thu Mar 27 14:08:14 2014 +0200
----------------------------------------------------------------------
.../app/controllers/wizard/step2_controller.js | 4 +-
.../app/controllers/wizard/step3_controller.js | 149 ++++-------------
ambari-web/app/messages.js | 2 +
ambari-web/app/styles/application.less | 19 +++
.../app/templates/common/items_list_popup.hbs | 21 +++
.../wizard/step2_host_name_pattern_popup.hbs | 21 ---
ambari-web/app/templates/wizard/step3.hbs | 158 +++++++++++--------
ambari-web/app/views/common/table_view.js | 93 +++++++++--
ambari-web/app/views/wizard/step3_view.js | 133 +++++++++++++++-
9 files changed, 381 insertions(+), 219 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/controllers/wizard/step2_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step2_controller.js b/ambari-web/app/controllers/wizard/step2_controller.js
index 4d7df4c..e2eec44 100644
--- a/ambari-web/app/controllers/wizard/step2_controller.js
+++ b/ambari-web/app/controllers/wizard/step2_controller.js
@@ -309,8 +309,8 @@ App.WizardStep2Controller = Em.Controller.extend({
this.hide();
},
bodyClass: Ember.View.extend({
- templateName: require('templates/wizard/step2_host_name_pattern_popup'),
- hostNames: hostNames
+ templateName: require('templates/common/items_list_popup'),
+ items: hostNames
})
});
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/controllers/wizard/step3_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step3_controller.js b/ambari-web/app/controllers/wizard/step3_controller.js
index f5b2fa6..b3720a3 100644
--- a/ambari-web/app/controllers/wizard/step3_controller.js
+++ b/ambari-web/app/controllers/wizard/step3_controller.js
@@ -38,68 +38,6 @@ App.WizardStep3Controller = Em.Controller.extend({
stopBootstrap: false,
isSubmitDisabled: true,
- categoryObject: Em.Object.extend({
- hostsCount: function () {
- var category = this;
- var hosts = this.get('controller.hosts').filter(function(_host) {
- if (_host.get('bootStatus') == category.get('hostsBootStatus')) {
- return true;
- } else {
- return (_host.get('bootStatus') == 'DONE' && category.get('hostsBootStatus') == 'REGISTERING');
- }
- }, this);
- return hosts.get('length');
- }.property('controller.hosts.@each.bootStatus'), // 'hosts.@each.bootStatus'
- label: function () {
- return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount'));
- }.property('value', 'hostsCount')
- }),
- getCategory: function(field, value){
- return this.get('categories').find(function(item){
- return item.get(field) == value;
- });
- },
-
- categories: function () {
- var self = this;
- self.categoryObject.reopen({
- controller: self,
- isActive: function(){
- return this.get('controller.category') == this;
- }.property('controller.category'),
- itemClass: function(){
- return this.get('isActive') ? 'active' : '';
- }.property('isActive')
- });
-
- var categories = [
- self.categoryObject.create({value: Em.I18n.t('common.all'), hostsCount: function () {
- return this.get('controller.hosts.length');
- }.property('controller.hosts.length') }),
- self.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.installing'), hostsBootStatus: 'RUNNING'}),
- self.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.registering'), hostsBootStatus: 'REGISTERING'}),
- self.categoryObject.create({value: Em.I18n.t('common.success'), hostsBootStatus: 'REGISTERED' }),
- self.categoryObject.create({value: Em.I18n.t('common.fail'), hostsBootStatus: 'FAILED', last: true })
- ];
-
- this.set('category', categories.get('firstObject'));
-
- return categories;
- }.property(),
-
- category: false,
-
- allChecked: false,
-
- onAllChecked: function () {
- var hosts = this.get('visibleHosts');
- hosts.setEach('isChecked', this.get('allChecked'));
- }.observes('allChecked'),
-
- noHostsSelected: function () {
- return !(this.hosts.someProperty('isChecked', true));
- }.property('hosts.@each.isChecked'),
-
isRetryDisabled: true,
isLoaded: false,
@@ -160,20 +98,8 @@ App.WizardStep3Controller = Em.Controller.extend({
hosts.pushObject(hostInfo);
}
-
- if(hosts.length > 200) {
- lazyloading.run({
- destination: this.get('hosts'),
- source: hosts,
- context: this,
- initSize: 100,
- chunkSize: 150,
- delay: 50
- });
- } else {
- this.set('hosts', hosts);
- this.set('isLoaded', true);
- }
+ this.set('hosts', hosts);
+ this.set('isLoaded', true);
},
/**
@@ -195,22 +121,6 @@ App.WizardStep3Controller = Em.Controller.extend({
return this.get('bootHosts').length != 0 && this.get('bootHosts').someProperty('bootStatus', 'RUNNING');
},
- filterByCategory: function () {
- var category = this.get('category.hostsBootStatus');
- if (category) {
- this.get('hosts').forEach(function (host) {
- host.set('isVisible', (category === host.get('bootStatus')));
- });
- } else { // if (this.get('category') === 'All Hosts')
- this.get('hosts').setEach('isVisible', true);
- }
- }.observes('category', 'hosts.@each.bootStatus'),
-
- /* Returns the current set of visible hosts on view (All, Succeeded, Failed) */
- visibleHosts: function () {
- return this.get('hosts').filterProperty('isVisible');
- }.property('hosts.@each.isVisible'),
-
removeHosts: function (hosts) {
var self = this;
App.showConfirmationPopup(function() {
@@ -229,7 +139,7 @@ App.WizardStep3Controller = Em.Controller.extend({
removeSelectedHosts: function () {
if (!this.get('noHostsSelected')) {
- var selectedHosts = this.get('visibleHosts').filterProperty('isChecked', true);
+ var selectedHosts = this.get('hosts').filterProperty('isChecked', true);
selectedHosts.forEach(function (_hostInfo) {
console.log('Removing: ' + _hostInfo.name);
});
@@ -237,6 +147,24 @@ App.WizardStep3Controller = Em.Controller.extend({
}
},
+ /**
+ * show popup with the list of hosts which are selected
+ */
+ selectedHostsPopup: function () {
+ var selectedHosts = this.get('hosts').filterProperty('isChecked').mapProperty('name');
+ App.ModalPopup.show({
+ header: Em.I18n.t('installer.step3.selectedHosts.popup.header'),
+ onPrimary: function () {
+ this.hide();
+ },
+ secondary: null,
+ bodyClass: Ember.View.extend({
+ items: selectedHosts,
+ templateName: require('templates/common/items_list_popup')
+ })
+ });
+ },
+
retryHost: function (hostInfo) {
this.retryHosts([hostInfo]);
},
@@ -287,7 +215,7 @@ App.WizardStep3Controller = Em.Controller.extend({
setRegistrationInProgress: function () {
var bootHosts = this.get('bootHosts');
//if hosts aren't loaded yet then registration should be in progress
- var result = (bootHosts.length === 0);
+ var result = (bootHosts.length === 0 && !this.get('isLoaded'));
for (var i = 0, l = bootHosts.length; i < l; i++) {
if (bootHosts[i].get('bootStatus') !== 'REGISTERED' && bootHosts[i].get('bootStatus') !== 'FAILED') {
result = true;
@@ -679,20 +607,18 @@ App.WizardStep3Controller = Em.Controller.extend({
},
submit: function () {
- if (!this.get('isSubmitDisabled')) {
- if(this.get('isHostHaveWarnings')) {
- var self = this;
- App.showConfirmationPopup(
- function(){
- self.set('content.hosts', self.get('bootHosts'));
- App.router.send('next');
- },
- Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
- }
- else {
- this.set('content.hosts', this.get('bootHosts'));
- App.router.send('next');
- }
+ if (this.get('isHostHaveWarnings')) {
+ var self = this;
+ App.showConfirmationPopup(
+ function () {
+ self.set('content.hosts', self.get('bootHosts'));
+ App.router.send('next');
+ },
+ Em.I18n.t('installer.step3.hostWarningsPopup.hostHasWarnings'));
+ }
+ else {
+ this.set('content.hosts', this.get('bootHosts'));
+ App.router.send('next');
}
},
@@ -1369,13 +1295,6 @@ App.WizardStep3Controller = Em.Controller.extend({
registeredHosts: self.get('registeredHosts')
})
})
- },
-
- back: function () {
- if (this.get('isRegistrationInProgress')) {
- return;
- }
- App.router.send('back');
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index c4c1440..fbe3880 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -531,6 +531,8 @@ Em.I18n.translations = {
'installer.step3.hosts.bootLog.registering':'\nRegistering with the server...',
'installer.step3.hostLogPopup.highlight':'click to highlight',
'installer.step3.hostLogPopup.copy':'press CTRL+C',
+ 'installer.step3.hostsTable.selectAll':'Select All Hosts',
+ 'installer.step3.selectedHosts.popup.header':'Selected Hosts',
'installer.step4.header':'Choose Services',
'installer.step4.body':'Choose which services you want to install on your cluster.',
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/styles/application.less
----------------------------------------------------------------------
diff --git a/ambari-web/app/styles/application.less b/ambari-web/app/styles/application.less
index 6087d93..ac93e5d 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -414,6 +414,19 @@ h1 {
}
}
#confirm-hosts {
+ table {
+ margin-bottom: 0;
+ td {
+ input[type="checkbox"] {
+ margin-left: 15px;
+ }
+ }
+ th {
+ input[type="checkbox"] {
+ margin: 0;
+ }
+ }
+ }
#host-filter {
margin-top: 3px;
ul {
@@ -437,6 +450,12 @@ h1 {
}
}
}
+ .page-bar {
+ padding: 5px;
+ .selected-hosts-info {
+ margin: 0;
+ }
+ }
.progress {
margin-bottom: 0;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/templates/common/items_list_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/items_list_popup.hbs b/ambari-web/app/templates/common/items_list_popup.hbs
new file mode 100644
index 0000000..6544a1b
--- /dev/null
+++ b/ambari-web/app/templates/common/items_list_popup.hbs
@@ -0,0 +1,21 @@
+{{!
+* 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.
+}}
+
+{{#each item in view.items}}
+ <p>{{item}}</p>
+{{/each}}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/templates/wizard/step2_host_name_pattern_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step2_host_name_pattern_popup.hbs b/ambari-web/app/templates/wizard/step2_host_name_pattern_popup.hbs
deleted file mode 100644
index 66e7f48..0000000
--- a/ambari-web/app/templates/wizard/step2_host_name_pattern_popup.hbs
+++ /dev/null
@@ -1,21 +0,0 @@
-{{!
-* 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.
-}}
-
-{{#each host in view.hostNames}}
- <p>{{host}}</p>
-{{/each}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/templates/wizard/step3.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step3.hbs b/ambari-web/app/templates/wizard/step3.hbs
index 2b6fb18..5b8bdad 100644
--- a/ambari-web/app/templates/wizard/step3.hbs
+++ b/ambari-web/app/templates/wizard/step3.hbs
@@ -23,11 +23,11 @@
<div class="box">
<div class="box-header">
<div class="button-section">
- <a class="btn btn-primary" {{bindAttr disabled="noHostsSelected"}}
- href="#" {{action removeSelectedHosts target="controller" }}><i
+ <button class="btn btn-primary" {{bindAttr disabled="view.noHostsSelected"}}
+ {{action removeSelectedHosts target="controller" }}><i
class="icon-trash icon-white"></i>
{{t installer.step3.removeSelected}}
- </a>
+ </button>
{{#unless isRetryDisabled}}
<a class="btn btn-primary decommission"
href="#" {{action retrySelectedHosts target="controller"}}><i
@@ -39,9 +39,9 @@
<div id="host-filter" class="pull-right">
<ul class="clearfix">
<li class="first">{{t common.show}}:</li>
- {{#each category in controller.categories}}
+ {{#each category in view.categories}}
<li {{bindAttr class="category.itemClass"}}>
- <a {{action selectCategory category target="controller"}} href="#">
+ <a {{action selectCategory category target="view"}} href="#">
{{category.label}}
</a>
</li>
@@ -54,64 +54,96 @@
</div>
</div>
- <div class="pre-scrollable" style="max-height: 440px;">
- <table class="table table-bordered table-striped">
- <thead>
- <tr>
- <th class="span1">{{view Ember.Checkbox checkedBinding="allChecked"}}</th>
- <th class="span3">{{t common.host}}</th>
- <!-- retrieved from local storage initially -->
- <th class="span3">{{t common.progress}}</th>
- <th class="span2">{{t common.status}}</th>
- <!-- given by the parsing function that parses data from bootstrap call, dynamically assign the color -->
- <th class="span3">{{t common.action}}</th>
- <!-- trash icon -->
- <!-- retry icon -->
- </tr>
- </thead>
-
- <tbody>
- {{#each host in hosts}}
- {{#view App.WizardHostView categoryBinding="controller.category" hostInfoBinding="host"}}
- <td>
- {{view Ember.Checkbox checkedBinding="host.isChecked"}}
- </td>
- <td>
- {{host.name}}
- </td>
- <td>
- <div {{bindAttr class="host.bootBarColor host.isBootDone::progress-striped host.isBootDone::active :progress"}}>
- <div class="bar" style="width:100%">
- </div>
+ <div class="pre-scrollable" style="max-height: 440px;">
+ <table class="table table-bordered table-striped">
+ <thead>
+ <tr>
+ <th class="span1">
+ <div class="btn-group">
+ <a class="btn">
+ {{view Ember.Checkbox checkedBinding="view.pageChecked"}}
+ </a>
+ <button class="btn dropdown-toggle" data-toggle="dropdown">
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+ <li>
+ <a {{action selectAll target="view"}}>{{t installer.step3.hostsTable.selectAll}}</a>
+ </li>
+ </ul>
+ </div>
+ </th>
+ <th class="span3">{{t common.host}}</th>
+ <!-- retrieved from local storage initially -->
+ <th class="span3">{{t common.progress}}</th>
+ <th class="span2">{{t common.status}}</th>
+ <!-- given by the parsing function that parses data from bootstrap call, dynamically assign the color -->
+ <th class="span3">{{t common.action}}</th>
+ <!-- trash icon -->
+ <!-- retry icon -->
+ </tr>
+ </thead>
+ <tbody>
+ {{#if view.pageContent}}
+ {{#each host in view.pageContent}}
+ {{#view App.WizardHostView categoryBinding="controller.category" hostInfoBinding="host"}}
+ <td>
+ {{view Ember.Checkbox checkedBinding="host.isChecked"}}
+ </td>
+ <td>
+ {{host.name}}
+ </td>
+ <td>
+ <div {{bindAttr class="host.bootBarColor host.isBootDone::progress-striped host.isBootDone::active :progress"}}>
+ <div class="bar" style="width:100%">
+ </div>
+ </div>
+ </td>
+ <td>
+ <a href="javascript:void(null)"
+ data-toggle="modal" {{action hostLogPopup host target="controller"}}><span {{bindAttr class="host.bootStatusColor"}}>{{host.bootStatusForDisplay}}</span></a>
+ </td>
+ <td>
+ {{#if view.isRemovable}}<a class="btn btn-mini" {{action remove target="view"}}><i
+ class="icon-trash"></i>
+ {{t common.remove}}</a>{{/if}}
+ {{#if view.isRetryable}}<a class="btn btn-mini" {{action retry target="view"}}><i
+ class="icon-repeat"></i>
+ {{t common.retry}}</a>{{/if}}
+ </td>
+ {{/view}}
+ {{/each}}
+ {{else}}
+ <tr>
+ <td colspan="5">
+ {{t hosts.table.noHosts}}
+ </td>
+ </tr>
+ {{/if}}
+ </tbody>
+ </table>
+ </div>
+ <div id="hosts">
+ <div class="page-bar">
+ <div class="selected-hosts-info span6">
+ {{#if view.selectedHostsCount}}
+ <a {{action selectedHostsPopup target="controller"}} href="#">
+ {{view.selectedHostsCount}}
+ {{pluralize view.selectedHostsCount singular="t:hosts.filters.selectedHostInfo" plural="t:hosts.filters.selectedHostsInfo"}}
+ </a>
+ -
+ <a {{action unSelectAll target="view"}} href="#">{{t hosts.filters.clearSelection}}</a>
+ {{/if}}
+ </div>
+ <div class="info">{{view.paginationInfo}}</div>
+ <div class="paging_two_button">
+ {{view view.paginationFirst}}
+ {{view view.paginationLeft}}
+ {{view view.paginationRight}}
+ {{view view.paginationLast}}
+ </div>
</div>
- </td>
- <td>
- <a href="javascript:void(null)"
- data-toggle="modal" {{action hostLogPopup host target="controller"}}><span {{bindAttr class="host.bootStatusColor"}}>{{host.bootStatusForDisplay}}</span></a>
- </td>
- <td>
- {{#if view.isRemovable}}<a class="btn btn-mini" {{action remove target="view"}}><i class="icon-trash"></i>
- {{t common.remove}}</a>{{/if}}
- {{#if view.isRetryable}}<a class="btn btn-mini" {{action retry target="view"}}><i class="icon-repeat"></i>
- {{t common.retry}}</a>{{/if}}
- </td>
- {{/view}}
- {{/each}}
- {{#unless visibleHosts.length}}
- <tr>
- <td colspan="5"><p>{{t installer.step3.hosts.noHosts}}</p></td>
- </tr>
- {{/unless}}
-
- </tbody>
-
- </table>
- </div>
- <div class="box-footer">
- <hr/>
- <div class="footer-pagination">
</div>
- </div>
</div>
{{#if hasMoreRegisteredHosts}}
<div {{bindAttr class=":alert alert-warn"}}>
@@ -126,7 +158,7 @@
{{/unless}}
</div>
<div class="btn-area">
- <a class="btn pull-left" {{bindAttr disabled="isRegistrationInProgress"}} {{action back target="controller"}}>← {{t common.back}}</a>
- <a class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} →</a>
+ <button class="btn pull-left" {{bindAttr disabled="isRegistrationInProgress"}} {{action back}}>← {{t common.back}}</button>
+ <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} →</button>
</div>
</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/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 ffb73f7..ef65cca 100644
--- a/ambari-web/app/views/common/table_view.js
+++ b/ambari-web/app/views/common/table_view.js
@@ -47,6 +47,21 @@ App.TableView = Em.View.extend(App.UserPref, {
displayLengthOnLoad: null,
/**
+ * The number of rows to show on every page
+ * The value should be a number converted into string type in order to support select element API
+ * Example: "10", "25"
+ * @type {String}
+ */
+ displayLength: null,
+
+ /**
+ * default value of display length
+ * The value should be a number converted into string type in order to support select element API
+ * Example: "10", "25"
+ */
+ defaultDisplayLength: "10",
+
+ /**
* Do filtering, using saved in the local storage filter conditions
*/
willInsertElement:function () {
@@ -54,12 +69,14 @@ App.TableView = Em.View.extend(App.UserPref, {
var name = this.get('controller.name');
this.set('startIndexOnLoad', App.db.getStartIndex(name));
- if (App.db.getDisplayLength(name)) {
- this.set('displayLength', App.db.getDisplayLength(name));
- } else {
- self.dataLoading().done(function (initValue) {
- self.set('displayLength', initValue);
- });
+ if (!this.get('displayLength')) {
+ if (App.db.getDisplayLength(name)) {
+ this.set('displayLength', App.db.getDisplayLength(name));
+ } else {
+ self.dataLoading().done(function (initValue) {
+ self.set('displayLength', initValue);
+ });
+ }
}
var filterConditions = App.db.getFilterConditions(name);
@@ -130,7 +147,7 @@ App.TableView = Em.View.extend(App.UserPref, {
getUserPrefErrorCallback: function () {
// this user is first time login
console.log('Persist did NOT find the key');
- var displayLengthDefault = "10";
+ var displayLengthDefault = this.get('defaultDisplayLength');
this.set('displayLengthOnLoad', displayLengthDefault);
if (App.get('isAdmin')) {
this.postUserPref(this.displayLengthKey(), displayLengthDefault);
@@ -173,7 +190,9 @@ App.TableView = Em.View.extend(App.UserPref, {
}.property("parentView.startIndex", 'filteredContent.length'),
click: function () {
- this.get('parentView').previousPage();
+ if (this.get('class') === "paginate_previous") {
+ this.get('parentView').previousPage();
+ }
}
}),
@@ -189,7 +208,45 @@ App.TableView = Em.View.extend(App.UserPref, {
}.property("parentView.endIndex", 'filteredContent.length'),
click: function () {
- this.get('parentView').nextPage();
+ if (this.get('class') === "paginate_next") {
+ this.get('parentView').nextPage();
+ }
+ }
+ }),
+
+ paginationFirst: Ember.View.extend({
+ tagName: 'a',
+ template: Ember.Handlebars.compile('<i class="icon-step-backward"></i>'),
+ classNameBindings: ['class'],
+ class: function () {
+ if ((this.get("parentView.endIndex")) > parseInt(this.get("parentView.displayLength"))) {
+ return "paginate_previous";
+ }
+ return "paginate_disabled_previous";
+ }.property("parentView.endIndex", 'filteredContent.length'),
+
+ click: function () {
+ if (this.get('class') === "paginate_previous") {
+ this.get('parentView').firstPage();
+ }
+ }
+ }),
+
+ paginationLast: Ember.View.extend({
+ tagName: 'a',
+ template: Ember.Handlebars.compile('<i class="icon-step-forward"></i>'),
+ classNameBindings: ['class'],
+ class: function () {
+ if (this.get("parentView.endIndex") !== this.get("parentView.filteredContent.length")) {
+ return "paginate_next";
+ }
+ return "paginate_disabled_next";
+ }.property("parentView.endIndex", 'filteredContent.length'),
+
+ click: function () {
+ if (this.get('class') === "paginate_next") {
+ this.get('parentView').lastPage();
+ }
}
}),
@@ -233,12 +290,22 @@ App.TableView = Em.View.extend(App.UserPref, {
this.set('startIndex', result);
}
},
-
/**
- * The number of rows to show on every page
- * @type {Number}
+ * Onclick handler for first page button on the page
*/
- displayLength: null,
+ firstPage: function () {
+ this.set('startIndex', 1);
+ },
+ /**
+ * Onclick handler for last page button on the page
+ */
+ lastPage: function () {
+ var pagesCount = this.get('filteredContent.length') / parseInt(this.get('displayLength'));
+ var startIndex = (this.get('filteredContent.length') % parseInt(this.get('displayLength')) === 0) ?
+ (pagesCount - 1) * parseInt(this.get('displayLength')) :
+ Math.floor(pagesCount) * parseInt(this.get('displayLength'));
+ this.set('startIndex', ++startIndex);
+ },
/**
* Calculates default value for startIndex property after applying filter or changing displayLength
http://git-wip-us.apache.org/repos/asf/ambari/blob/74ef9620/ambari-web/app/views/wizard/step3_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step3_view.js b/ambari-web/app/views/wizard/step3_view.js
index 3211e6d..f953e68 100644
--- a/ambari-web/app/views/wizard/step3_view.js
+++ b/ambari-web/app/views/wizard/step3_view.js
@@ -19,25 +19,148 @@
var App = require('app');
-App.WizardStep3View = Em.View.extend({
+App.WizardStep3View = App.TableView.extend({
templateName: require('templates/wizard/step3'),
- category: '',
- didInsertElement: function () {
- this.get('controller').loadStep();
- },
+ content:function () {
+ return this.get('controller.hosts');
+ }.property('controller.hosts.length'),
message:'',
linkText: '',
status: '',
+ selectedCategory: function() {
+ return this.get('categories').findProperty('isActive');
+ }.property('categories.@each.isActive'),
+
registeredHostsMessage: '',
+ displayLength: "20",
+
+ didInsertElement: function () {
+ this.get('controller').loadStep();
+ },
+
+ pageChecked: false,
+
+ /**
+ * select checkboxes of hosts on page
+ */
+ onPageChecked: function () {
+ if (this.get('selectionInProgress')) return;
+ this.get('pageContent').setEach('isChecked', this.get('pageChecked'));
+ }.observes('pageChecked'),
+
+ /**
+ * select checkboxes of all hosts
+ */
+ selectAll: function () {
+ this.get('content').setEach('isChecked', true);
+ },
+
+ /**
+ * reset checkbox of all hosts
+ */
+ unSelectAll: function() {
+ this.get('content').setEach('isChecked', false);
+ },
+
+ watchSelectionOnce: function(){
+ Em.run.once(this, 'watchSelection');
+ }.observes('content.@each.isChecked'),
+
+ /**
+ * watch selection and calculate flags as:
+ * - noHostsSelected
+ * - selectedHostsCount
+ * - pageChecked
+ */
+ watchSelection: function() {
+ this.set('selectionInProgress', true);
+ this.set('pageChecked', !!this.get('pageContent.length') && this.get('pageContent').everyProperty('isChecked', true));
+ this.set('selectionInProgress', false);
+ var noHostsSelected = true;
+ var selectedHostsCount = 0;
+ this.get('content').forEach(function(host){
+ selectedHostsCount += ~~host.get('isChecked');
+ noHostsSelected = (noHostsSelected) ? !host.get('isChecked') : noHostsSelected;
+ });
+ this.set('noHostsSelected', noHostsSelected);
+ this.set('selectedHostsCount', selectedHostsCount);
+ },
+
setRegisteredHosts: function(){
this.set('registeredHostsMessage',Em.I18n.t('installer.step3.warning.registeredHosts').format(this.get('controller.registeredHosts').length));
}.observes('controller.registeredHosts'),
+ categoryObject: Em.Object.extend({
+ hostsCount: 0,
+ label: function () {
+ return "%@ (%@)".fmt(this.get('value'), this.get('hostsCount'));
+ }.property('value', 'hostsCount'),
+ isActive: false,
+ itemClass: function () {
+ return this.get('isActive') ? 'active' : '';
+ }.property('isActive')
+ }),
+
+ categories: function () {
+ return [
+ this.categoryObject.create({value: Em.I18n.t('common.all'), hostsBootStatus: 'ALL', isActive: true}),
+ this.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.installing'), hostsBootStatus: 'RUNNING'}),
+ this.categoryObject.create({value: Em.I18n.t('installer.step3.hosts.status.registering'), hostsBootStatus: 'REGISTERING'}),
+ this.categoryObject.create({value: Em.I18n.t('common.success'), hostsBootStatus: 'REGISTERED' }),
+ this.categoryObject.create({value: Em.I18n.t('common.fail'), hostsBootStatus: 'FAILED', last: true })
+ ];
+ }.property(),
+
+ countCategoryHosts: function () {
+ var counters = {
+ "RUNNING": 0,
+ "REGISTERING": 0,
+ "REGISTERED": 0,
+ "FAILED": 0
+ };
+ this.get('content').forEach(function (host) {
+ if (counters[host.get('bootStatus')] !== undefined) {
+ counters[host.get('bootStatus')]++;
+ }
+ }, this);
+ counters["ALL"] = this.get('content.length');
+ this.get('categories').forEach(function(category) {
+ category.set('hostsCount', counters[category.get('hostsBootStatus')]);
+ }, this);
+ }.observes('content.@each.bootStatus'),
+
+
+ /**
+ * filter hosts by category
+ */
+ filter: function () {
+ var result = [];
+ var selectedCategory = this.get('selectedCategory');
+ if (!selectedCategory || selectedCategory.get('hostsBootStatus') === 'ALL') {
+ result = this.get('content');
+ } else {
+ result = this.get('content').filterProperty('bootStatus', this.get('selectedCategory.hostsBootStatus'));
+ }
+ this.set('filteredContent', result);
+ }.observes('content.@each.bootStatus', 'selectedCategory'),
+ /**
+ * Trigger on Category click
+ * @param {Object} event
+ */
+ selectCategory: function (event) {
+ var categoryStatus = event.context.get('hostsBootStatus');
+ var self = this;
+ this.get('categories').forEach(function (category) {
+ category.set('isActive', (category.get('hostsBootStatus') === categoryStatus));
+ });
+ this.watchSelection();
+ },
+
monitorStatuses: function() {
var hosts = this.get('controller.bootHosts');
var failedHosts = hosts.filterProperty('bootStatus', 'FAILED').length;