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