Commit a81b3b36 by Waheed Ahmed Committed by GitHub

Merge pull request #13287 from edx/waheed/ecom-4186-fix-account-settings-tabpanel

Fixed account settings tab-panels.
parents 008b7086 00578159
...@@ -33,7 +33,7 @@ class AccountSettingsPage(FieldsMixin, PageObject): ...@@ -33,7 +33,7 @@ class AccountSettingsPage(FieldsMixin, PageObject):
""" """
structure = [] structure = []
sections = self.q(css='.section') sections = self.q(css='#aboutTabSections-tabpanel .section')
for section in sections: for section in sections:
section_title_element = section.find_element_by_class_name('section-header') section_title_element = section.find_element_by_class_name('section-header')
field_title_elements = section.find_elements_by_class_name('u-field-title') field_title_elements = section.find_elements_by_class_name('u-field-title')
......
...@@ -73,18 +73,14 @@ define(['backbone', ...@@ -73,18 +73,14 @@ define(['backbone',
var accountSettingsView = createAccountSettingsPage(); var accountSettingsView = createAccountSettingsPage();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
var request = requests[0]; var request = requests[0];
expect(request.method).toBe('GET'); expect(request.method).toBe('GET');
expect(request.url).toBe(Helpers.USER_ACCOUNTS_API_URL); expect(request.url).toBe(Helpers.USER_ACCOUNTS_API_URL);
AjaxHelpers.respondWithError(requests, 500); AjaxHelpers.respondWithError(requests, 500);
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, false);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, true); Helpers.expectLoadingErrorIsVisible(accountSettingsView, true);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
}); });
...@@ -93,18 +89,14 @@ define(['backbone', ...@@ -93,18 +89,14 @@ define(['backbone',
var accountSettingsView = createAccountSettingsPage(); var accountSettingsView = createAccountSettingsPage();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
var request = requests[0]; var request = requests[0];
expect(request.method).toBe('GET'); expect(request.method).toBe('GET');
expect(request.url).toBe(Helpers.USER_ACCOUNTS_API_URL); expect(request.url).toBe(Helpers.USER_ACCOUNTS_API_URL);
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData()); AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
request = requests[1]; request = requests[1];
expect(request.method).toBe('GET'); expect(request.method).toBe('GET');
...@@ -116,9 +108,7 @@ define(['backbone', ...@@ -116,9 +108,7 @@ define(['backbone',
expect(request.url).toBe(Helpers.USER_PREFERENCES_API_URL); expect(request.url).toBe(Helpers.USER_PREFERENCES_API_URL);
AjaxHelpers.respondWithError(requests, 500); AjaxHelpers.respondWithError(requests, 500);
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, false);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, true); Helpers.expectLoadingErrorIsVisible(accountSettingsView, true);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
}); });
it('renders fields after the models are successfully fetched', function() { it('renders fields after the models are successfully fetched', function() {
...@@ -126,15 +116,14 @@ define(['backbone', ...@@ -126,15 +116,14 @@ define(['backbone',
var accountSettingsView = createAccountSettingsPage(); var accountSettingsView = createAccountSettingsPage();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData()); AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
AjaxHelpers.respondWithJson(requests, Helpers.TIME_ZONE_RESPONSE); AjaxHelpers.respondWithJson(requests, Helpers.TIME_ZONE_RESPONSE);
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData()); AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, false); accountSettingsView.render();
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView); Helpers.expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView);
}); });
......
...@@ -71,26 +71,16 @@ define(['backbone', ...@@ -71,26 +71,16 @@ define(['backbone',
var accountSettingsView = createAccountSettingsView(); var accountSettingsView = createAccountSettingsView();
accountSettingsView.render(); accountSettingsView.render();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
accountSettingsView.showLoadingError(); accountSettingsView.showLoadingError();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, false);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, true); Helpers.expectLoadingErrorIsVisible(accountSettingsView, true);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
}); });
it('renders all fields as expected', function() { it('renders all fields as expected', function() {
var accountSettingsView = createAccountSettingsView(); var accountSettingsView = createAccountSettingsView();
accountSettingsView.render(); accountSettingsView.render();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, true);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsButNotFieldsToBeRendered(accountSettingsView);
accountSettingsView.renderFields();
Helpers.expectLoadingIndicatorIsVisible(accountSettingsView, false);
Helpers.expectLoadingErrorIsVisible(accountSettingsView, false); Helpers.expectLoadingErrorIsVisible(accountSettingsView, false);
Helpers.expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView); Helpers.expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView);
}); });
......
...@@ -95,7 +95,7 @@ define(['underscore'], function(_) { ...@@ -95,7 +95,7 @@ define(['underscore'], function(_) {
var expectSettingsSectionsAndFieldsToBeRendered = function(accountSettingsView, fieldsAreRendered) { var expectSettingsSectionsAndFieldsToBeRendered = function(accountSettingsView, fieldsAreRendered) {
var sectionsData = accountSettingsView.options.tabSections.aboutTabSections; var sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
var sectionElements = accountSettingsView.$('.section'); var sectionElements = accountSettingsView.$('#aboutTabSections-tabpanel .section');
expect(sectionElements.length).toBe(sectionsData.length); expect(sectionElements.length).toBe(sectionsData.length);
_.each(sectionElements, function(sectionElement, sectionIndex) { _.each(sectionElements, function(sectionElement, sectionIndex) {
......
...@@ -11,13 +11,28 @@ ...@@ -11,13 +11,28 @@
initialize: function(options) { initialize: function(options) {
this.options = options; this.options = options;
_.bindAll(this, 'render', 'renderFields');
}, },
render: function() { render: function() {
this.$el.html(_.template(sectionTemplate)({ this.$el.html(_.template(sectionTemplate)({
sections: this.options.sections, sections: this.options.sections,
activeTabName: this.options.activeTabName tabName: this.options.tabName,
tabLabel: this.options.tabLabel
})); }));
this.renderFields();
},
renderFields: function() {
var view = this;
_.each(view.$('.' + view.options.tabName + '-section-body'), function(sectionEl, index) {
_.each(view.options.sections[index].fields, function(field) {
$(sectionEl).append(field.view.render().el);
});
});
return this;
} }
}); });
......
...@@ -265,9 +265,6 @@ ...@@ -265,9 +265,6 @@
visibility: null, visibility: null,
user_id: accountUserId user_id: accountUserId
}); });
// Render the fields
accountSettingsView.renderFields();
}; };
showLoadingError = function() { showLoadingError = function() {
......
...@@ -164,12 +164,20 @@ ...@@ -164,12 +164,20 @@
data: data, data: data,
success: function() { success: function() {
view.showSuccessMessage(); view.showSuccessMessage();
view.setMessageTimeout();
}, },
error: function(xhr) { error: function(xhr) {
view.showErrorMessage(xhr); view.showErrorMessage(xhr);
view.setMessageTimeout();
} }
}); });
}, },
setMessageTimeout: function() {
var view = this;
setTimeout(function() {
view.showHelpMessage();
}, 6000);
},
successMessage: function() { successMessage: function() {
return HtmlUtils.joinHtml( return HtmlUtils.joinHtml(
this.indicators.success, this.indicators.success,
......
...@@ -4,77 +4,109 @@ ...@@ -4,77 +4,109 @@
'gettext', 'gettext',
'jquery', 'jquery',
'underscore', 'underscore',
'backbone', 'common/js/components/views/tabbed_view',
'edx-ui-toolkit/js/utils/html-utils', 'edx-ui-toolkit/js/utils/html-utils',
'js/student_account/views/account_section_view', 'js/student_account/views/account_section_view',
'text!templates/student_account/account_settings.underscore' 'text!templates/student_account/account_settings.underscore'
], function(gettext, $, _, Backbone, HtmlUtils, AccountSectionView, accountSettingsTemplate) { ], function(gettext, $, _, TabbedView, HtmlUtils, AccountSectionView, accountSettingsTemplate) {
var AccountSettingsView = Backbone.View.extend({ var AccountSettingsView = TabbedView.extend({
navLink: '.account-nav-link', navLink: '.account-nav-link',
activeTab: 'aboutTabSections', activeTab: 'aboutTabSections',
accountSettingsTabs: [ accountSettingsTabs: [
{name: 'aboutTabSections', id: 'about-tab', label: gettext('Account Information'), class: 'active'}, {
{name: 'accountsTabSections', id: 'accounts-tab', label: gettext('Linked Accounts')}, name: 'aboutTabSections',
{name: 'ordersTabSections', id: 'orders-tab', label: gettext('Order History')} id: 'about-tab',
label: gettext('Account Information'),
class: 'active',
tabindex: 0,
selected: true,
expanded: true
},
{
name: 'accountsTabSections',
id: 'accounts-tab',
label: gettext('Linked Accounts'),
tabindex: -1,
selected: false,
expanded: false
},
{
name: 'ordersTabSections',
id: 'orders-tab',
label: gettext('Order History'),
tabindex: -1,
selected: false,
expanded: false
}
], ],
events: { events: {
'click .account-nav-link': 'changeTab' 'click .account-nav-link': 'switchTab',
'keydown .account-nav-link': 'keydownHandler'
}, },
initialize: function(options) { initialize: function(options) {
this.options = options; this.options = options;
_.bindAll(this, 'render', 'changeTab', 'renderFields', 'showLoadingError'); _.bindAll(this, 'render', 'switchTab', 'setActiveTab', 'showLoadingError');
}, },
render: function() { render: function() {
var tabName,
view = this;
HtmlUtils.setHtml(this.$el, HtmlUtils.template(accountSettingsTemplate)({ HtmlUtils.setHtml(this.$el, HtmlUtils.template(accountSettingsTemplate)({
accountSettingsTabs: this.accountSettingsTabs accountSettingsTabs: this.accountSettingsTabs
})); }));
this.renderSection(this.options.tabSections[this.activeTab]); _.each(view.accountSettingsTabs, function(tab) {
tabName = tab.name;
view.renderSection(view.options.tabSections[tabName], tabName, tab.label);
});
return this; return this;
}, },
changeTab: function(e) { switchTab: function(e) {
var $currentTab; var $currentTab,
$accountNavLink = $('.account-nav-link');
if (e) {
e.preventDefault();
$currentTab = $(e.target);
this.activeTab = $currentTab.data('name');
_.each(this.$('.account-settings-tabpanels'), function(tabPanel) {
$(tabPanel).addClass('hidden');
});
e.preventDefault(); $('#' + this.activeTab + '-tabpanel').removeClass('hidden');
$currentTab = $(e.target);
this.activeTab = $currentTab.data('name');
this.renderSection(this.options.tabSections[this.activeTab]);
this.renderFields();
$(this.navLink).removeClass('active'); $accountNavLink.attr('tabindex', -1);
$currentTab.addClass('active'); $accountNavLink.attr('aria-selected', false);
$accountNavLink.attr('aria-expanded', false);
$currentTab.attr('tabindex', 0);
$currentTab.attr('aria-selected', true);
$currentTab.attr('aria-expanded', true);
$(this.navLink).removeClass('active');
$currentTab.addClass('active');
}
},
$(this.navLink).removeAttr('aria-describedby'); setActiveTab: function() {
$currentTab.attr('aria-describedby', 'header-subtitle-' + this.activeTab); this.switchTab();
}, },
renderSection: function(tabSections) { renderSection: function(tabSections, tabName, tabLabel) {
var accountSectionView = new AccountSectionView({ var accountSectionView = new AccountSectionView({
activeTabName: this.activeTab, tabName: tabName,
tabLabel: tabLabel,
sections: tabSections, sections: tabSections,
el: '.account-settings-sections' el: '#' + tabName + '-tabpanel'
}); });
accountSectionView.render(); accountSectionView.render();
}, },
renderFields: function() {
var view = this;
view.$('.ui-loading-indicator').addClass('is-hidden');
_.each(view.$('.account-settings-section-body'), function(sectionEl, index) {
_.each(view.options.tabSections[view.activeTab][index].fields, function(field) {
$(sectionEl).append(field.view.render().el);
});
});
return this;
},
showLoadingError: function() { showLoadingError: function() {
this.$('.ui-loading-indicator').addClass('is-hidden');
this.$('.ui-loading-error').removeClass('is-hidden'); this.$('.ui-loading-error').removeClass('is-hidden');
} }
}); });
......
...@@ -58,36 +58,32 @@ ...@@ -58,36 +58,32 @@
padding: 0; padding: 0;
list-style: none; list-style: none;
.account-nav-item { .account-nav-link {
@include float(left); @include float(left);
display: flex; font-size: em(14);
margin: 0; color: $gray;
text-transform: none; padding: 5px 25px 23px;
justify-content: center; display: inline-block;
box-shadow: none;
border: none;
border-radius: 0;
background: transparent none;
}
.account-nav-link { button {
font-size: em(14); @extend %ui-clear-button;
color: $gray; @extend %btn-no-style;
padding: 5px 25px 23px; @include appearance(none);
display: inline-block; display:block;
border-radius: 0; padding: ($baseline/4);
&:hover,
&:focus {
text-decoration: none;
border-bottom: 4px solid $courseware-border-bottom-color !important;
} }
&.active{
button { border-bottom: 4px solid $black-t3 !important;
@extend %ui-clear-button;
@extend %btn-no-style;
@include appearance(none);
display:block;
padding: ($baseline/4);
&:hover,
&:focus {
text-decoration: none;
border-bottom: 4px solid $courseware-border-bottom-color !important;
}
&.active{
border-bottom: 4px solid $black-t3 !important;
}
} }
} }
} }
......
...@@ -2,16 +2,18 @@ ...@@ -2,16 +2,18 @@
<div class="account-settings-container"> <div class="account-settings-container">
<div class="wrapper-header"> <div class="wrapper-header">
<h2 class="header-title"><%- gettext("Account Settings") %></h2> <h2 class="header-title"><%- gettext("Account Settings") %></h2>
<ul class="left list-inline account-nav"> <div class="left list-inline account-nav" role="tablist">
<% _.each(accountSettingsTabs, function(tab) { %> <% _.each(accountSettingsTabs, function(tab) { %>
<li class="account-nav-item"> <button id="<%- tab.id %>" aria-controls="<%- tab.name %>-tabpanel" tabindex="<%- tab.tabindex %>" aria-selected="<%- tab.selected %>" aria-expanded="<%- tab.expanded %>" data-name="<%- tab.name %>" aria-describedby="header-subtitle-<%- tab.name %>" class="tab account-nav-link <%- tab.class %>" role="tab">
<button id="<%- tab.id %>" data-name="<%- tab.name %>" <% if (tab.class) { %> aria-describedby="header-subtitle-<%- tab.name %>" <% } %> class="account-nav-link <%- tab.class %>" ><%- tab.label %></button> <%- tab.label %>
</li> </button>
<% }); %> <% }); %>
</ul> </div>
</div> </div>
<div class="account-settings-sections"> <div class="account-settings-sections">
<% _.each(accountSettingsTabs, function(tab) { %>
<div id="<%- tab.name %>-tabpanel" class="account-settings-tabpanels <% if (!tab.class) { %> hidden <% } %>" aria-label="<%- tab.label %>" role="tabpanel"></div>
<% }); %>
</div> </div>
</div> </div>
</main> </main>
<h2 class="sr" id="header-subtitle-<%- tabName %>">
<%- tabLabel %>
</h2>
<% _.each(sections, function(section) { %> <% _.each(sections, function(section) { %>
<div class="section"> <div class="section">
<% if (section.subtitle) { %> <% if (section.subtitle) { %>
<p id="header-subtitle-<%- activeTabName %>" class="account-settings-header-subtitle"><%- section.subtitle %></p> <p class="account-settings-header-subtitle"><%- section.subtitle %></p>
<% } %> <% } %>
<h3 class="section-header"><%- gettext(section.title) %></h3> <h3 class="section-header"><%- gettext(section.title) %></h3>
<div class="account-settings-section-body"> <div class="account-settings-section-body <%- tabName %>-section-body">
<div class="ui-loading-indicator">
<span class="spin"><span class="icon fa fa-refresh" aria-hidden="true"></span></span>
<span class="copy"><%- gettext("Loading") %></span>
</div>
<div class="ui-loading-error is-hidden"> <div class="ui-loading-error is-hidden">
<span class="fa fa-exclamation-triangle message-error" aria-hidden="true"></span> <span class="fa fa-exclamation-triangle message-error" aria-hidden="true"></span>
<span class="copy"><%- gettext("An error occurred. Please reload the page.") %></span> <span class="copy"><%- gettext("An error occurred. Please reload the page.") %></span>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment