Merge pull request #12369 from edx/waheed/ecom-2981-account-settings-nav
Account Settings Navigation
This commit is contained in:
@@ -57,3 +57,9 @@ class AccountSettingsPage(FieldsMixin, PageObject):
|
||||
Wait for loading indicator to become visible.
|
||||
"""
|
||||
EmptyPromise(self._is_loading_in_progress, "Loading is in progress.").fulfill()
|
||||
|
||||
def switch_account_settings_tabs(self, tab_id):
|
||||
"""
|
||||
Switch between the different account settings tabs.
|
||||
"""
|
||||
self.q(css='#{}'.format(tab_id)).click()
|
||||
|
||||
@@ -228,13 +228,13 @@ class FieldsMixin(object):
|
||||
"Link field with link title \"{0}\" is visible.".format(expected_title)
|
||||
).fulfill()
|
||||
|
||||
def click_on_link_in_link_field(self, field_id):
|
||||
def click_on_link_in_link_field(self, field_id, field_type='a'):
|
||||
"""
|
||||
Click the link in a link field.
|
||||
"""
|
||||
self.wait_for_field(field_id)
|
||||
|
||||
query = self.q(css='.u-field-{} a'.format(field_id))
|
||||
query = self.q(css='.u-field-{} {}'.format(field_id, field_type))
|
||||
if query.present:
|
||||
query.first.click()
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
"""
|
||||
expected_sections_structure = [
|
||||
{
|
||||
'title': 'Basic Account Information (required)',
|
||||
'title': 'Basic Account Information',
|
||||
'fields': [
|
||||
'Username',
|
||||
'Full Name',
|
||||
@@ -169,21 +169,13 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
]
|
||||
},
|
||||
{
|
||||
'title': 'Additional Information (optional)',
|
||||
'title': 'Additional Information',
|
||||
'fields': [
|
||||
'Education Completed',
|
||||
'Gender',
|
||||
'Year of Birth',
|
||||
'Preferred Language',
|
||||
]
|
||||
},
|
||||
{
|
||||
'title': 'Connected Accounts',
|
||||
'fields': [
|
||||
'Dummy',
|
||||
'Facebook',
|
||||
'Google',
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -240,13 +232,13 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
self.account_settings_page.wait_for_page()
|
||||
self.assertEqual(self.account_settings_page.value_for_dropdown_field(field_id), new_value)
|
||||
|
||||
def _test_link_field(self, field_id, title, link_title, success_message):
|
||||
def _test_link_field(self, field_id, title, link_title, field_type, success_message):
|
||||
"""
|
||||
Test behaviour a link field.
|
||||
"""
|
||||
self.assertEqual(self.account_settings_page.title_for_field(field_id), title)
|
||||
self.assertEqual(self.account_settings_page.link_title_for_link_field(field_id), link_title)
|
||||
self.account_settings_page.click_on_link_in_link_field(field_id)
|
||||
self.account_settings_page.click_on_link_in_link_field(field_id, field_type=field_type)
|
||||
self.account_settings_page.wait_for_message(field_id, success_message)
|
||||
|
||||
def test_username_field(self):
|
||||
@@ -316,7 +308,8 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
self._test_link_field(
|
||||
u'password',
|
||||
u'Password',
|
||||
u'Reset Password',
|
||||
u'Reset Your Password',
|
||||
u'button',
|
||||
success_message='Click the link in the message to reset your password.',
|
||||
)
|
||||
|
||||
@@ -434,7 +427,7 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
actual_events
|
||||
)
|
||||
|
||||
def test_connected_accounts(self):
|
||||
def test_linked_accounts(self):
|
||||
"""
|
||||
Test that fields for third party auth providers exist.
|
||||
|
||||
@@ -442,9 +435,11 @@ class AccountSettingsPageTest(AccountSettingsTestMixin, WebAppTest):
|
||||
because that would require accounts with the providers.
|
||||
"""
|
||||
providers = (
|
||||
['auth-oa2-facebook', 'Facebook', 'Link'],
|
||||
['auth-oa2-google-oauth2', 'Google', 'Link'],
|
||||
['auth-oa2-facebook', 'Facebook', 'Link Your Account'],
|
||||
['auth-oa2-google-oauth2', 'Google', 'Link Your Account'],
|
||||
)
|
||||
# switch to "Linked Accounts" tab
|
||||
self.account_settings_page.switch_account_settings_tabs('accounts-tab')
|
||||
for field_id, title, link_title in providers:
|
||||
self.assertEqual(self.account_settings_page.title_for_field(field_id), title)
|
||||
self.assertEqual(self.account_settings_page.link_title_for_link_field(field_id), link_title)
|
||||
|
||||
@@ -222,19 +222,29 @@ class LoginFromCombinedPageTest(UniqueCourseTest):
|
||||
def _link_dummy_account(self):
|
||||
""" Go to Account Settings page and link the user's account to the Dummy provider """
|
||||
account_settings = AccountSettingsPage(self.browser).visit()
|
||||
# switch to "Linked Accounts" tab
|
||||
account_settings.switch_account_settings_tabs('accounts-tab')
|
||||
|
||||
field_id = "auth-oa2-dummy"
|
||||
account_settings.wait_for_field(field_id)
|
||||
self.assertEqual("Link", account_settings.link_title_for_link_field(field_id))
|
||||
self.assertEqual("Link Your Account", account_settings.link_title_for_link_field(field_id))
|
||||
account_settings.click_on_link_in_link_field(field_id)
|
||||
account_settings.wait_for_link_title_for_link_field(field_id, "Unlink")
|
||||
|
||||
# make sure we are on "Linked Accounts" tab after the account settings
|
||||
# page is reloaded
|
||||
account_settings.switch_account_settings_tabs('accounts-tab')
|
||||
account_settings.wait_for_link_title_for_link_field(field_id, "Unlink This Account")
|
||||
|
||||
def _unlink_dummy_account(self):
|
||||
""" Verify that the 'Dummy' third party auth provider is linked, then unlink it """
|
||||
# This must be done after linking the account, or we'll get cross-test side effects
|
||||
account_settings = AccountSettingsPage(self.browser).visit()
|
||||
# switch to "Linked Accounts" tab
|
||||
account_settings.switch_account_settings_tabs('accounts-tab')
|
||||
|
||||
field_id = "auth-oa2-dummy"
|
||||
account_settings.wait_for_field(field_id)
|
||||
self.assertEqual("Unlink", account_settings.link_title_for_link_field(field_id))
|
||||
self.assertEqual("Unlink This Account", account_settings.link_title_for_link_field(field_id))
|
||||
account_settings.click_on_link_in_link_field(field_id)
|
||||
account_settings.wait_for_message(field_id, "Successfully unlinked")
|
||||
|
||||
@@ -372,9 +382,12 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
|
||||
|
||||
# Now unlink the account (To test the account settings view and also to prevent cross-test side effects)
|
||||
account_settings = AccountSettingsPage(self.browser).visit()
|
||||
# switch to "Linked Accounts" tab
|
||||
account_settings.switch_account_settings_tabs('accounts-tab')
|
||||
|
||||
field_id = "auth-oa2-dummy"
|
||||
account_settings.wait_for_field(field_id)
|
||||
self.assertEqual("Unlink", account_settings.link_title_for_link_field(field_id))
|
||||
self.assertEqual("Unlink This Account", account_settings.link_title_for_link_field(field_id))
|
||||
account_settings.click_on_link_in_link_field(field_id)
|
||||
account_settings.wait_for_message(field_id, "Successfully unlinked")
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
|
||||
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
|
||||
|
||||
var sectionsData = accountSettingsView.options.sectionsData;
|
||||
var sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
|
||||
|
||||
expect(sectionsData[0].fields.length).toBe(6);
|
||||
|
||||
@@ -180,14 +180,6 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
defaultValue: null
|
||||
}, requests);
|
||||
});
|
||||
|
||||
var section2Fields = sectionsData[2].fields;
|
||||
expect(section2Fields.length).toBe(2);
|
||||
for (var i = 0; i < section2Fields.length; i++) {
|
||||
|
||||
var view = section2Fields[i].view;
|
||||
AccountSettingsFieldViewSpecHelpers.verifyAuthField(view, view.options, requests);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,13 +10,13 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
spyOn(view, 'redirect_to');
|
||||
|
||||
FieldViewsSpecHelpers.expectTitleAndMessageToContain(view, data.title, data.helpMessage);
|
||||
expect(view.$(selector).text().trim()).toBe('Unlink');
|
||||
expect(view.$(selector).text().trim()).toBe('Unlink This Account');
|
||||
view.$(selector).click();
|
||||
FieldViewsSpecHelpers.expectMessageContains(view, 'Unlinking');
|
||||
AjaxHelpers.expectRequest(requests, 'POST', data.disconnectUrl);
|
||||
AjaxHelpers.respondWithNoContent(requests);
|
||||
|
||||
expect(view.$(selector).text().trim()).toBe('Link');
|
||||
expect(view.$(selector).text().trim()).toBe('Link Your Account');
|
||||
FieldViewsSpecHelpers.expectMessageContains(view, 'Successfully unlinked.');
|
||||
|
||||
view.$(selector).click();
|
||||
|
||||
@@ -32,7 +32,7 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
});
|
||||
|
||||
var view = new AccountSettingsFieldViews.PasswordFieldView(fieldData).render();
|
||||
view.$('.u-field-value > a').click();
|
||||
view.$('.u-field-value > button').click();
|
||||
AjaxHelpers.expectRequest(requests, 'POST', '/password_reset', "email=legolas%40woodland.middlearth");
|
||||
AjaxHelpers.respondWithJson(requests, {"success": "true"});
|
||||
FieldViewsSpecHelpers.expectMessageContains(
|
||||
|
||||
@@ -15,7 +15,7 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
var model = new UserAccountModel();
|
||||
model.set(Helpers.createAccountSettingsData());
|
||||
|
||||
var sectionsData = [
|
||||
var aboutSectionsData = [
|
||||
{
|
||||
title: "Basic Account Information",
|
||||
fields: [
|
||||
@@ -53,7 +53,9 @@ define(['backbone', 'jquery', 'underscore', 'common/js/spec_helpers/ajax_helpers
|
||||
var accountSettingsView = new AccountSettingsView({
|
||||
el: $('.wrapper-account-settings'),
|
||||
model: model,
|
||||
sectionsData : sectionsData
|
||||
tabSections: {
|
||||
aboutTabSections: aboutSectionsData
|
||||
}
|
||||
});
|
||||
|
||||
return accountSettingsView;
|
||||
|
||||
@@ -75,8 +75,8 @@ define(['underscore'], function(_) {
|
||||
|
||||
if ('fieldValue' in view) {
|
||||
expect(view.fieldValue()).toBe(view.modelValue());
|
||||
} else if (view.fieldType === 'link') {
|
||||
expect($(element).find('a').length).toBe(1);
|
||||
} else if (view.fieldType === 'button') {
|
||||
expect($(element).find('button').length).toBe(1);
|
||||
} else {
|
||||
throw new Error('Unexpected field type: ' + view.fieldType);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ define(['underscore'], function(_) {
|
||||
};
|
||||
|
||||
var expectSettingsSectionsAndFieldsToBeRendered = function (accountSettingsView, fieldsAreRendered) {
|
||||
var sectionsData = accountSettingsView.options.sectionsData;
|
||||
var sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
|
||||
|
||||
var sectionElements = accountSettingsView.$('.section');
|
||||
expect(sectionElements.length).toBe(sectionsData.length);
|
||||
|
||||
27
lms/static/js/student_account/views/account_section_view.js
Normal file
27
lms/static/js/student_account/views/account_section_view.js
Normal file
@@ -0,0 +1,27 @@
|
||||
;(function (define, undefined) {
|
||||
'use strict';
|
||||
define([
|
||||
'gettext',
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'text!templates/student_account/account_settings_section.underscore'
|
||||
], function (gettext, $, _, Backbone, sectionTemplate) {
|
||||
|
||||
var AccountSectionView = Backbone.View.extend({
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = options;
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(_.template(sectionTemplate)({
|
||||
sections: this.options.sections,
|
||||
activeTabName: this.options.activeTabName
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return AccountSectionView;
|
||||
});
|
||||
}).call(this, define || RequireJS.define);
|
||||
@@ -2,30 +2,35 @@
|
||||
'use strict';
|
||||
define([
|
||||
'gettext', 'jquery', 'underscore', 'backbone', 'logger',
|
||||
'js/views/fields',
|
||||
'js/student_account/models/user_account_model',
|
||||
'js/student_account/models/user_preferences_model',
|
||||
'js/student_account/views/account_settings_fields',
|
||||
'js/student_account/views/account_settings_view'
|
||||
], function (gettext, $, _, Backbone, Logger, FieldViews, UserAccountModel, UserPreferencesModel,
|
||||
], function (gettext, $, _, Backbone, Logger, UserAccountModel, UserPreferencesModel,
|
||||
AccountSettingsFieldViews, AccountSettingsView) {
|
||||
|
||||
return function (fieldsData, authData, userAccountsApiUrl, userPreferencesApiUrl, accountUserId, platformName) {
|
||||
var accountSettingsElement, userAccountModel, userPreferencesModel, aboutSectionsData,
|
||||
accountsSectionData, accountSettingsView, showAccountSettingsPage, showLoadingError;
|
||||
|
||||
var accountSettingsElement = $('.wrapper-account-settings');
|
||||
accountSettingsElement = $('.wrapper-account-settings');
|
||||
|
||||
var userAccountModel = new UserAccountModel();
|
||||
userAccountModel = new UserAccountModel();
|
||||
userAccountModel.url = userAccountsApiUrl;
|
||||
|
||||
var userPreferencesModel = new UserPreferencesModel();
|
||||
userPreferencesModel = new UserPreferencesModel();
|
||||
userPreferencesModel.url = userPreferencesApiUrl;
|
||||
|
||||
var sectionsData = [
|
||||
aboutSectionsData = [
|
||||
{
|
||||
title: gettext('Basic Account Information (required)'),
|
||||
title: gettext('Basic Account Information'),
|
||||
subtitle: gettext(
|
||||
'These settings include basic information about your account. You can also ' +
|
||||
'specify additional information and see your linked social accounts on this page.'
|
||||
),
|
||||
fields: [
|
||||
{
|
||||
view: new FieldViews.ReadonlyFieldView({
|
||||
view: new AccountSettingsFieldViews.ReadonlyFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Username'),
|
||||
valueAttribute: 'username',
|
||||
@@ -35,7 +40,7 @@
|
||||
})
|
||||
},
|
||||
{
|
||||
view: new FieldViews.TextFieldView({
|
||||
view: new AccountSettingsFieldViews.TextFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Full Name'),
|
||||
valueAttribute: 'name',
|
||||
@@ -60,12 +65,14 @@
|
||||
view: new AccountSettingsFieldViews.PasswordFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Password'),
|
||||
screenReaderTitle: gettext('Reset your Password'),
|
||||
screenReaderTitle: gettext('Reset Your Password'),
|
||||
valueAttribute: 'password',
|
||||
emailAttribute: 'email',
|
||||
linkTitle: gettext('Reset Password'),
|
||||
linkTitle: gettext('Reset Your Password'),
|
||||
linkHref: fieldsData.password.url,
|
||||
helpMessage: gettext('When you click "Reset Password", a message will be sent to your email address. Click the link in the message to reset your password.')
|
||||
helpMessage: gettext('When you click "Reset Your Password", edX will send a message ' +
|
||||
'to the email address for your edX account. Click the link in the message to ' +
|
||||
'reset your password.')
|
||||
})
|
||||
},
|
||||
{
|
||||
@@ -83,7 +90,7 @@
|
||||
})
|
||||
},
|
||||
{
|
||||
view: new FieldViews.DropdownFieldView({
|
||||
view: new AccountSettingsFieldViews.DropdownFieldView({
|
||||
model: userAccountModel,
|
||||
required: true,
|
||||
title: gettext('Country or Region'),
|
||||
@@ -95,10 +102,10 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
title: gettext('Additional Information (optional)'),
|
||||
title: gettext('Additional Information'),
|
||||
fields: [
|
||||
{
|
||||
view: new FieldViews.DropdownFieldView({
|
||||
view: new AccountSettingsFieldViews.DropdownFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Education Completed'),
|
||||
valueAttribute: 'level_of_education',
|
||||
@@ -107,7 +114,7 @@
|
||||
})
|
||||
},
|
||||
{
|
||||
view: new FieldViews.DropdownFieldView({
|
||||
view: new AccountSettingsFieldViews.DropdownFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Gender'),
|
||||
valueAttribute: 'gender',
|
||||
@@ -116,7 +123,7 @@
|
||||
})
|
||||
},
|
||||
{
|
||||
view: new FieldViews.DropdownFieldView({
|
||||
view: new AccountSettingsFieldViews.DropdownFieldView({
|
||||
model: userAccountModel,
|
||||
title: gettext('Year of Birth'),
|
||||
valueAttribute: 'year_of_birth',
|
||||
@@ -137,16 +144,17 @@
|
||||
}
|
||||
];
|
||||
|
||||
if (_.isArray(authData.providers)) {
|
||||
var accountsSectionData = {
|
||||
title: gettext('Connected Accounts'),
|
||||
accountsSectionData = [
|
||||
{
|
||||
title: gettext('Linked Accounts'),
|
||||
subtitle: gettext(
|
||||
'You can link your social media accounts to your edX account to make signing in to edx.org ' +
|
||||
'and the edX mobile apps easier.'
|
||||
),
|
||||
fields: _.map(authData.providers, function(provider) {
|
||||
return {
|
||||
'view': new AccountSettingsFieldViews.AuthFieldView({
|
||||
title: provider.name,
|
||||
screenReaderTitle: interpolate_text(
|
||||
gettext("Connect your {accountName} account"), {accountName: provider['name']}
|
||||
),
|
||||
valueAttribute: 'auth-' + provider.id,
|
||||
helpMessage: '',
|
||||
connected: provider.connected,
|
||||
@@ -156,24 +164,23 @@
|
||||
})
|
||||
};
|
||||
})
|
||||
};
|
||||
sectionsData.push(accountsSectionData);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var accountSettingsView = new AccountSettingsView({
|
||||
accountSettingsView = new AccountSettingsView({
|
||||
model: userAccountModel,
|
||||
accountUserId: accountUserId,
|
||||
el: accountSettingsElement,
|
||||
sectionsData: sectionsData
|
||||
tabSections: {
|
||||
aboutTabSections: aboutSectionsData,
|
||||
accountsTabSections: accountsSectionData
|
||||
},
|
||||
userPreferencesModel: userPreferencesModel
|
||||
});
|
||||
|
||||
accountSettingsView.render();
|
||||
|
||||
var showLoadingError = function () {
|
||||
accountSettingsView.showLoadingError();
|
||||
};
|
||||
|
||||
var showAccountFields = function () {
|
||||
showAccountSettingsPage = function () {
|
||||
// Record that the account settings page was viewed.
|
||||
Logger.log('edx.user.settings.viewed', {
|
||||
page: "account",
|
||||
@@ -185,11 +192,15 @@
|
||||
accountSettingsView.renderFields();
|
||||
};
|
||||
|
||||
showLoadingError = function () {
|
||||
accountSettingsView.showLoadingError();
|
||||
};
|
||||
|
||||
userAccountModel.fetch({
|
||||
success: function () {
|
||||
// Fetch the user preferences model
|
||||
userPreferencesModel.fetch({
|
||||
success: showAccountFields,
|
||||
success: showAccountSettingsPage,
|
||||
error: showLoadingError
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,191 +1,233 @@
|
||||
;(function (define, undefined) {
|
||||
'use strict';
|
||||
define([
|
||||
'gettext', 'jquery', 'underscore', 'backbone', 'js/views/fields'
|
||||
], function (gettext, $, _, Backbone, FieldViews) {
|
||||
'gettext',
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'js/views/fields',
|
||||
'text!templates/fields/field_text_account.underscore',
|
||||
'text!templates/fields/field_readonly_account.underscore',
|
||||
'text!templates/fields/field_link_account.underscore',
|
||||
'text!templates/fields/field_dropdown_account.underscore',
|
||||
'text!templates/fields/field_social_link_account.underscore'
|
||||
], function (
|
||||
gettext, $, _, Backbone,
|
||||
FieldViews,
|
||||
field_text_account_template,
|
||||
field_readonly_account_template,
|
||||
field_link_account_template,
|
||||
field_dropdown_account_template,
|
||||
field_social_link_template)
|
||||
{
|
||||
|
||||
var AccountSettingsFieldViews = {};
|
||||
var AccountSettingsFieldViews = {
|
||||
ReadonlyFieldView: FieldViews.ReadonlyFieldView.extend({
|
||||
fieldTemplate: field_readonly_account_template
|
||||
}),
|
||||
TextFieldView: FieldViews.TextFieldView.extend({
|
||||
fieldTemplate: field_text_account_template
|
||||
}),
|
||||
DropdownFieldView: FieldViews.DropdownFieldView.extend({
|
||||
fieldTemplate: field_dropdown_account_template
|
||||
}),
|
||||
EmailFieldView: FieldViews.TextFieldView.extend({
|
||||
fieldTemplate: field_text_account_template,
|
||||
successMessage: function () {
|
||||
return this.indicators.success + window.interpolate_text(
|
||||
gettext(
|
||||
'We\'ve sent a confirmation message to {new_email_address}. Click the link in the ' +
|
||||
'message to update your email address.'
|
||||
),
|
||||
{'new_email_address': this.fieldValue()}
|
||||
);
|
||||
}
|
||||
}),
|
||||
LanguagePreferenceFieldView: FieldViews.DropdownFieldView.extend({
|
||||
fieldTemplate: field_dropdown_account_template,
|
||||
saveSucceeded: function () {
|
||||
var data = {
|
||||
'language': this.modelValue()
|
||||
};
|
||||
|
||||
AccountSettingsFieldViews.EmailFieldView = FieldViews.TextFieldView.extend({
|
||||
|
||||
successMessage: function() {
|
||||
return this.indicators.success + interpolate_text(
|
||||
gettext(
|
||||
/* jshint maxlen: false */
|
||||
'We\'ve sent a confirmation message to {new_email_address}. Click the link in the message to update your email address.'
|
||||
),
|
||||
{'new_email_address': this.fieldValue()}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
AccountSettingsFieldViews.LanguagePreferenceFieldView = FieldViews.DropdownFieldView.extend({
|
||||
|
||||
saveSucceeded: function () {
|
||||
var data = {
|
||||
'language': this.modelValue()
|
||||
};
|
||||
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/i18n/setlang/',
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function () {
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function () {
|
||||
view.showNotificationMessage(
|
||||
view.indicators.error +
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/i18n/setlang/',
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function () {
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function () {
|
||||
view.showNotificationMessage(
|
||||
view.indicators.error +
|
||||
gettext('You must sign out and sign back in before your language changes take effect.')
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}),
|
||||
PasswordFieldView: FieldViews.LinkFieldView.extend({
|
||||
fieldType: 'button',
|
||||
fieldTemplate: field_link_account_template,
|
||||
events: {
|
||||
'click button': 'linkClicked'
|
||||
},
|
||||
initialize: function (options) {
|
||||
this.options = _.extend({}, options);
|
||||
this._super(options);
|
||||
_.bindAll(this, 'resetPassword');
|
||||
},
|
||||
linkClicked: function (event) {
|
||||
event.preventDefault();
|
||||
this.resetPassword(event);
|
||||
},
|
||||
resetPassword: function () {
|
||||
var data = {};
|
||||
data[this.options.emailAttribute] = this.model.get(this.options.emailAttribute);
|
||||
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: view.options.linkHref,
|
||||
data: data,
|
||||
success: function () {
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function (xhr) {
|
||||
view.showErrorMessage(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
successMessage: function () {
|
||||
return this.indicators.success + window.interpolate_text(
|
||||
gettext(
|
||||
'We\'ve sent a message to {email_address}. Click the link in the message to reset ' +
|
||||
'your password.'
|
||||
),
|
||||
{'email_address': this.model.get(this.options.emailAttribute)}
|
||||
);
|
||||
}
|
||||
}),
|
||||
LanguageProficienciesFieldView: FieldViews.DropdownFieldView.extend({
|
||||
fieldTemplate: field_dropdown_account_template,
|
||||
modelValue: function () {
|
||||
var modelValue = this.model.get(this.options.valueAttribute);
|
||||
if (_.isArray(modelValue) && modelValue.length > 0) {
|
||||
return modelValue[0].code;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
saveValue: function () {
|
||||
if (this.persistChanges === true) {
|
||||
var attributes = {},
|
||||
value = this.fieldValue() ? [{'code': this.fieldValue()}] : [];
|
||||
attributes[this.options.valueAttribute] = value;
|
||||
this.saveAttributes(attributes);
|
||||
}
|
||||
}
|
||||
}),
|
||||
AuthFieldView: FieldViews.LinkFieldView.extend({
|
||||
fieldTemplate: field_social_link_template,
|
||||
className: function () {
|
||||
return 'u-field u-field-social u-field-' + this.options.valueAttribute;
|
||||
},
|
||||
initialize: function (options) {
|
||||
this.options = _.extend({}, options);
|
||||
this._super(options);
|
||||
_.bindAll(this, 'redirect_to', 'disconnect', 'successMessage', 'inProgressMessage');
|
||||
},
|
||||
render: function () {
|
||||
var linkTitle = '',
|
||||
linkClass = '',
|
||||
subTitle = '',
|
||||
screenReaderTitle = window.interpolate_text(
|
||||
gettext("Link your {accountName} account"), {accountName: this.options.title}
|
||||
);
|
||||
if (this.options.connected) {
|
||||
linkTitle = gettext('Unlink This Account');
|
||||
linkClass = 'social-field-linked';
|
||||
subTitle = window.interpolate_text(
|
||||
gettext('You can use your {accountName} account to sign in to your edX account.'),
|
||||
{accountName: this.options.title}
|
||||
);
|
||||
screenReaderTitle = window.interpolate_text(
|
||||
gettext("Unlink your {accountName} account"), {accountName: this.options.title}
|
||||
);
|
||||
} else if (this.options.acceptsLogins) {
|
||||
linkTitle = gettext('Link Your Account');
|
||||
linkClass = 'social-field-unlinked';
|
||||
subTitle = window.interpolate_text(
|
||||
gettext(
|
||||
'Link your {accountName} account to your edX account and ' +
|
||||
'use {accountName} to sign in to edX.'
|
||||
), {accountName: this.options.title}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
this.$el.html(this.template({
|
||||
id: this.options.valueAttribute,
|
||||
title: this.options.title,
|
||||
screenReaderTitle: screenReaderTitle,
|
||||
linkTitle: linkTitle,
|
||||
subTitle: subTitle,
|
||||
linkClass: linkClass,
|
||||
linkHref: '#',
|
||||
message: this.helpMessage
|
||||
}));
|
||||
this.delegateEvents();
|
||||
return this;
|
||||
},
|
||||
linkClicked: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
AccountSettingsFieldViews.PasswordFieldView = FieldViews.LinkFieldView.extend({
|
||||
this.showInProgressMessage();
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = _.extend({}, options);
|
||||
this._super(options);
|
||||
_.bindAll(this, 'resetPassword');
|
||||
},
|
||||
|
||||
linkClicked: function (event) {
|
||||
event.preventDefault();
|
||||
this.resetPassword(event);
|
||||
},
|
||||
|
||||
resetPassword: function () {
|
||||
var data = {};
|
||||
data[this.options.emailAttribute] = this.model.get(this.options.emailAttribute);
|
||||
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: view.options.linkHref,
|
||||
data: data,
|
||||
success: function () {
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function (xhr) {
|
||||
view.showErrorMessage(xhr);
|
||||
if (this.options.connected) {
|
||||
this.disconnect();
|
||||
} else {
|
||||
// Direct the user to the providers site to start the authentication process.
|
||||
// See python-social-auth docs for more information.
|
||||
this.redirect_to(this.options.connectUrl);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
redirect_to: function (url) {
|
||||
window.location.href = url;
|
||||
},
|
||||
disconnect: function () {
|
||||
var data = {};
|
||||
|
||||
successMessage: function () {
|
||||
return this.indicators.success + interpolate_text(
|
||||
gettext(
|
||||
/* jshint maxlen: false */
|
||||
'We\'ve sent a message to {email_address}. Click the link in the message to reset your password.'
|
||||
),
|
||||
{'email_address': this.model.get(this.options.emailAttribute)}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
AccountSettingsFieldViews.LanguageProficienciesFieldView = FieldViews.DropdownFieldView.extend({
|
||||
|
||||
modelValue: function () {
|
||||
var modelValue = this.model.get(this.options.valueAttribute);
|
||||
if (_.isArray(modelValue) && modelValue.length > 0) {
|
||||
return modelValue[0].code;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
saveValue: function () {
|
||||
if (this.persistChanges === true) {
|
||||
var attributes = {},
|
||||
value = this.fieldValue() ? [{'code': this.fieldValue()}] : [];
|
||||
attributes[this.options.valueAttribute] = value;
|
||||
this.saveAttributes(attributes);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AccountSettingsFieldViews.AuthFieldView = FieldViews.LinkFieldView.extend({
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = _.extend({}, options);
|
||||
this._super(options);
|
||||
_.bindAll(this, 'redirect_to', 'disconnect', 'successMessage', 'inProgressMessage');
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var linkTitle;
|
||||
if (this.options.connected) {
|
||||
linkTitle = gettext('Unlink');
|
||||
} else if (this.options.acceptsLogins) {
|
||||
linkTitle = gettext('Link')
|
||||
} else {
|
||||
linkTitle = ''
|
||||
}
|
||||
|
||||
this.$el.html(this.template({
|
||||
id: this.options.valueAttribute,
|
||||
title: this.options.title,
|
||||
screenReaderTitle: this.options.screenReaderTitle,
|
||||
linkTitle: linkTitle,
|
||||
linkHref: '',
|
||||
message: this.helpMessage
|
||||
}));
|
||||
return this;
|
||||
},
|
||||
|
||||
linkClicked: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.showInProgressMessage();
|
||||
|
||||
if (this.options.connected) {
|
||||
this.disconnect();
|
||||
} else {
|
||||
// Direct the user to the providers site to start the authentication process.
|
||||
// Disconnects the provider from the user's edX account.
|
||||
// See python-social-auth docs for more information.
|
||||
this.redirect_to(this.options.connectUrl);
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: this.options.disconnectUrl,
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function () {
|
||||
view.options.connected = false;
|
||||
view.render();
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function (xhr) {
|
||||
view.showErrorMessage(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
inProgressMessage: function () {
|
||||
return this.indicators.inProgress + (
|
||||
this.options.connected ? gettext('Unlinking') : gettext('Linking')
|
||||
);
|
||||
},
|
||||
successMessage: function () {
|
||||
return this.indicators.success + gettext('Successfully unlinked.');
|
||||
}
|
||||
},
|
||||
|
||||
redirect_to: function (url) {
|
||||
window.location.href = url;
|
||||
},
|
||||
|
||||
disconnect: function () {
|
||||
var data = {};
|
||||
|
||||
// Disconnects the provider from the user's edX account.
|
||||
// See python-social-auth docs for more information.
|
||||
var view = this;
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: this.options.disconnectUrl,
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function () {
|
||||
view.options.connected = false;
|
||||
view.render();
|
||||
view.showSuccessMessage();
|
||||
},
|
||||
error: function (xhr) {
|
||||
view.showErrorMessage(xhr);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
inProgressMessage: function() {
|
||||
return this.indicators.inProgress + (this.options.connected ? gettext('Unlinking') : gettext('Linking'));
|
||||
},
|
||||
|
||||
successMessage: function() {
|
||||
return this.indicators.success + gettext('Successfully unlinked.');
|
||||
}
|
||||
});
|
||||
}),
|
||||
};
|
||||
|
||||
return AccountSettingsFieldViews;
|
||||
});
|
||||
|
||||
@@ -1,29 +1,71 @@
|
||||
;(function (define, undefined) {
|
||||
'use strict';
|
||||
define([
|
||||
'gettext', 'jquery', 'underscore', 'backbone', 'text!templates/student_account/account_settings.underscore'
|
||||
], function (gettext, $, _, Backbone, accountSettingsTemplate) {
|
||||
'gettext',
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'js/student_account/views/account_section_view',
|
||||
'text!templates/student_account/account_settings.underscore'
|
||||
], function (gettext, $, _, Backbone, AccountSectionView, accountSettingsTemplate) {
|
||||
|
||||
var AccountSettingsView = Backbone.View.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')}
|
||||
],
|
||||
events: {
|
||||
'click .account-nav-link': 'changeTab'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.options = _.extend({}, options);
|
||||
_.bindAll(this, 'render', 'renderFields', 'showLoadingError');
|
||||
this.options = options;
|
||||
_.bindAll(this, 'render', 'changeTab', 'renderFields', 'showLoadingError');
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.$el.html(_.template(accountSettingsTemplate)({
|
||||
sections: this.options.sectionsData
|
||||
accountSettingsTabs: this.accountSettingsTabs
|
||||
}));
|
||||
this.renderSection(this.options.tabSections[this.activeTab]);
|
||||
return this;
|
||||
},
|
||||
|
||||
renderFields: function () {
|
||||
this.$('.ui-loading-indicator').addClass('is-hidden');
|
||||
changeTab: function(e) {
|
||||
var $currentTab;
|
||||
|
||||
e.preventDefault();
|
||||
$currentTab = $(e.target);
|
||||
this.activeTab = $currentTab.data('name');
|
||||
this.renderSection(this.options.tabSections[this.activeTab]);
|
||||
this.renderFields();
|
||||
|
||||
$(this.navLink).removeClass('active');
|
||||
$currentTab.addClass('active');
|
||||
|
||||
$(this.navLink).removeAttr('aria-describedby');
|
||||
$currentTab.attr('aria-describedby', 'header-subtitle-'+this.activeTab);
|
||||
},
|
||||
|
||||
renderSection: function (tabSections) {
|
||||
var accountSectionView = new AccountSectionView({
|
||||
activeTabName: this.activeTab,
|
||||
sections: tabSections,
|
||||
el: '.account-settings-sections'
|
||||
});
|
||||
|
||||
accountSectionView.render();
|
||||
},
|
||||
|
||||
renderFields: function () {
|
||||
var view = this;
|
||||
_.each(this.$('.account-settings-section-body'), function (sectionEl, index) {
|
||||
_.each(view.options.sectionsData[index].fields, function (field) {
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -230,8 +230,15 @@
|
||||
},
|
||||
|
||||
finishEditing: function() {
|
||||
var modelValue;
|
||||
if (this.persistChanges === false || this.mode !== 'edit') {return;}
|
||||
if (this.fieldValue() !== this.modelValue()) {
|
||||
|
||||
modelValue = this.modelValue();
|
||||
if (!(_.isUndefined(modelValue) || _.isNull(modelValue))) {
|
||||
modelValue = modelValue.toString();
|
||||
}
|
||||
|
||||
if (this.fieldValue() !== modelValue) {
|
||||
this.saveValue();
|
||||
} else {
|
||||
if (this.editable === 'always') {
|
||||
|
||||
@@ -518,7 +518,6 @@ $dark-gray: rgb(51, 51, 51) !default;
|
||||
$border-color: rgb(200, 200, 200) !default;
|
||||
$sidebar-color: rgb(246, 246, 246) !default;
|
||||
$outer-border-color: $gray-l3;
|
||||
$light-gray: rgb(221,221,221) !default;
|
||||
|
||||
// used by descriptor css
|
||||
$lightGrey: rgb(237,241,245) !default;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
.wrapper-footer {
|
||||
@extend %ui-print-excluded;
|
||||
margin-top: ($baseline*2) + px;
|
||||
box-shadow: 0 -1px 5px 0 $shadow-l1;
|
||||
border-top: 1px solid tint(palette(grayscale, light), 50%);
|
||||
padding: 25px ($baseline/2 + px) ($baseline*1.5 + px) ($baseline/2 + px);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
.wrapper-footer {
|
||||
@extend %ui-print-excluded;
|
||||
margin-top: ($baseline*2);
|
||||
box-shadow: 0 -1px 5px 0 $shadow-l1;
|
||||
border-top: 1px solid tint($m-gray, 50%);
|
||||
padding: 25px ($baseline/2) ($baseline*1.5) ($baseline/2);
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
|
||||
// +Container - Account Settings
|
||||
.wrapper-account-settings {
|
||||
@extend .container;
|
||||
padding-top: ($baseline*2);
|
||||
background: $white;
|
||||
width: 100%;
|
||||
|
||||
.account-settings-container {
|
||||
padding: 0;
|
||||
max-width: grid-width(12);
|
||||
padding: 10px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.ui-loading-indicator,
|
||||
@@ -36,15 +38,59 @@
|
||||
.wrapper-account-settings {
|
||||
|
||||
.wrapper-header {
|
||||
max-width: grid-width(12);
|
||||
height: 139px;
|
||||
border-bottom: 4px solid $m-gray-l4;
|
||||
|
||||
.header-title {
|
||||
@extend %t-title4;
|
||||
margin-bottom: ($baseline/2);
|
||||
padding-top: ($baseline*2);
|
||||
}
|
||||
|
||||
.header-subtitle {
|
||||
color: $gray-l2;
|
||||
}
|
||||
|
||||
.account-nav {
|
||||
@include float(left);
|
||||
margin: ($baseline/2) 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
.account-nav-item {
|
||||
@include float(left);
|
||||
display: flex;
|
||||
margin: 0;
|
||||
text-transform: none;
|
||||
justify-content: center;
|
||||
|
||||
.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;
|
||||
}
|
||||
&.active{
|
||||
border-bottom: 4px solid $black-t3 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,27 +100,189 @@
|
||||
.section-header {
|
||||
@extend %t-title6;
|
||||
@extend %t-strong;
|
||||
padding-bottom: ($baseline/2);
|
||||
border-bottom: 1px solid $gray-l4;
|
||||
padding-top: ($baseline/2)*3;
|
||||
color: $dark-gray1;
|
||||
}
|
||||
|
||||
.section {
|
||||
background-color: $white;
|
||||
padding: $baseline;
|
||||
margin-top: $baseline;
|
||||
border: 1px solid $gray-l4;
|
||||
box-shadow: 0 0 1px 1px $shadow-l2;
|
||||
border-radius: 5px;
|
||||
}
|
||||
border-bottom: 4px solid $m-gray-l4;
|
||||
|
||||
a span {
|
||||
color: $link-color;
|
||||
}
|
||||
.account-settings-header-subtitle {
|
||||
font-size: em(18);
|
||||
line-height: normal;
|
||||
color: $dark-gray;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
a span {
|
||||
&:hover, &:focus {
|
||||
color: $pink;
|
||||
text-decoration: none !important;
|
||||
.account-settings-section-body {
|
||||
|
||||
.u-field {
|
||||
border-bottom: 2px solid $m-gray-l4;
|
||||
|
||||
.field {
|
||||
width: 30%;
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
select {
|
||||
@include appearance(none);
|
||||
padding: 14px 30px 14px 15px;
|
||||
border: 1px solid $light-gray;
|
||||
background-color: transparent;
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
&::-ms-expand{
|
||||
display: none;
|
||||
}
|
||||
~ .icon-caret-down{
|
||||
&:after{
|
||||
content: "";
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
border-top: 7px solid $blue;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 20px;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.field-label {
|
||||
display: block;
|
||||
width: auto;
|
||||
margin-bottom: 0.625rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1;
|
||||
color: $dark-gray;
|
||||
}
|
||||
|
||||
.field-input {
|
||||
@include transition(all 0.125s ease-in-out 0s);
|
||||
display: inline-block;
|
||||
padding: 0.625rem;
|
||||
border: 1px solid $light-gray;
|
||||
border-radius: 2px;
|
||||
background: $white;
|
||||
font-size: $body-font-size;
|
||||
color: $dark-gray;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.u-field-link {
|
||||
@extend %ui-clear-button;
|
||||
|
||||
// set styles
|
||||
@extend %btn-pl-default-base;
|
||||
@include font-size(18);
|
||||
width: 100%;
|
||||
border: 1px solid $blue;
|
||||
color: $blue;
|
||||
padding: 11px 14px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
#u-field-value-username {
|
||||
padding-top: ($baseline/2);
|
||||
}
|
||||
}
|
||||
|
||||
.social-field-linked {
|
||||
background: $m-gray-l4;
|
||||
box-shadow: 0 1px 2px 1px $shadow-l2;
|
||||
padding: 1.25rem;
|
||||
box-sizing: border-box;
|
||||
margin: 10px;
|
||||
width: 100%;
|
||||
|
||||
.field-label {
|
||||
@include font-size(24);
|
||||
}
|
||||
|
||||
.u-field-social-help {
|
||||
display: inline-block;
|
||||
padding: 20px 0 6px;
|
||||
}
|
||||
|
||||
.u-field-link {
|
||||
@include font-size(14);
|
||||
@include text-align(left);
|
||||
border: none;
|
||||
margin-top: $baseline;
|
||||
font-weight: $font-semibold;
|
||||
padding: 0;
|
||||
|
||||
&:focus, &:hover, &:active {
|
||||
background-color: transparent;
|
||||
color: $m-blue-d3;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.social-field-unlinked {
|
||||
background: $m-gray-l4;
|
||||
box-shadow: 0 1px 2px 1px $shadow-l2;
|
||||
padding: 1.25rem;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
width: 100%;
|
||||
|
||||
.field-label {
|
||||
@include font-size(24);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.u-field-link {
|
||||
@include font-size(14);
|
||||
margin-top: $baseline;
|
||||
font-weight: $font-semibold;
|
||||
}
|
||||
}
|
||||
|
||||
.u-field-message {
|
||||
position: relative;
|
||||
padding: 24px 0 0 ($baseline*5);
|
||||
|
||||
.u-field-message-notification {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
padding: 38px 0 0 ($baseline*5);
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
margin-bottom: ($baseline*2);
|
||||
}
|
||||
}
|
||||
|
||||
.u-field-social {
|
||||
border-bottom: none;
|
||||
margin-right: 20px;
|
||||
width: 30%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
|
||||
.u-field-social-help {
|
||||
@include font-size(12);
|
||||
color: $m-gray-d1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
42
lms/templates/fields/field_dropdown_account.underscore
Normal file
42
lms/templates/fields/field_dropdown_account.underscore
Normal file
@@ -0,0 +1,42 @@
|
||||
<div class="u-field-value field">
|
||||
<% if (editable !== 'never') { %>
|
||||
<% if (title && titleVisible) { %>
|
||||
<label class="u-field-title field-label" for="u-field-select-<%- id %>">
|
||||
<%- title %>
|
||||
</label>
|
||||
<% } else { %>
|
||||
<label class="sr" for="u-field-select-<%- id %>">
|
||||
<%- screenReaderTitle %>
|
||||
</label>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<% if (iconName) { %>
|
||||
<span class="u-field-icon icon fa <%- iconName %> fa-fw" aria-hidden="true"></span>
|
||||
<% } %>
|
||||
|
||||
<% if (editable === 'never') { %>
|
||||
<span class="sr"><%- screenReaderTitle %></span>
|
||||
<span class="u-field-value-readonly"></span>
|
||||
<% } else { %>
|
||||
<select name="select" id="u-field-select-<%- id %>" aria-describedby="u-field-help-message-<%- id %>">
|
||||
<% if (showBlankOption) { %>
|
||||
<option value=""></option>
|
||||
<% } %>
|
||||
<% _.each(selectOptions, function(selectOption) { %>
|
||||
<option value="<%- selectOption[0] %>"><%- selectOption[1] %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
<span class="icon-caret-down" aria-hidden="true"></span>
|
||||
<button class="u-field-value-display">
|
||||
<span class="sr"><%- screenReaderTitle %> </span>
|
||||
<span class="u-field-value-readonly"></span>
|
||||
<span class="sr"><%- gettext('Click to edit') %></span>
|
||||
</button>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<span class="u-field-message" id="u-field-message-<%- id %>">
|
||||
<span class="u-field-message-notification" aria-live="polite"></span>
|
||||
<span class="u-field-message-help" id="u-field-help-message-<%- id %>"><%- message %></span>
|
||||
</span>
|
||||
8
lms/templates/fields/field_link_account.underscore
Normal file
8
lms/templates/fields/field_link_account.underscore
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="u-field-value field">
|
||||
<span class="u-field-title field-label"><%- title %></span>
|
||||
<button class="u-field-link u-field-link-title-<%- id %> " id="u-field-link-<%- id %>" aria-describedby="u-field-message-help-<%- id %>"><%- linkTitle %></button>
|
||||
</div>
|
||||
<span class="u-field-message" id="u-field-message-<%- id %>">
|
||||
<span class="u-field-message-notification" aria-live="polite"></span>
|
||||
<span class="u-field-message-help" id="u-field-message-help-<%- id %>"> <%- message %></span>
|
||||
</span>
|
||||
8
lms/templates/fields/field_readonly_account.underscore
Normal file
8
lms/templates/fields/field_readonly_account.underscore
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="field">
|
||||
<span class="u-field-title field-label"><%- title %></span>
|
||||
<span class="u-field-value" id="u-field-value-<%- id %>" aria-describedby="u-field-message-help-<%- id %>"><b><%- value %></b></span>
|
||||
</div>
|
||||
<span class="u-field-message" id="u-field-message-<%- id %>">
|
||||
<span class="u-field-message-notification" aria-live="polite"></span>
|
||||
<span class="u-field-message-help" id="u-field-message-help-<%- id %>"> <%- message %></span>
|
||||
</span>
|
||||
13
lms/templates/fields/field_social_link_account.underscore
Normal file
13
lms/templates/fields/field_social_link_account.underscore
Normal file
@@ -0,0 +1,13 @@
|
||||
<div class="u-field-value field <%- linkClass %>">
|
||||
<h4 class="u-field-title field-label"><%- title %></h4>
|
||||
<span class="u-field-social-help"><%- subTitle %></span>
|
||||
<a class="u-field-link" id="u-field-link-<%- id %>" href="<%- linkHref %>" aria-describedby="u-field-message-help-<%- id %>">
|
||||
<span class="sr"><%- screenReaderTitle %></span>
|
||||
<span class="u-field-link-title-<%- id %>" aria-hidden="true"><%- linkTitle %></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<span class="u-field-message" id="u-field-message-<%- id %>">
|
||||
<span class="u-field-message-notification" aria-live="polite"></span>
|
||||
<span class="u-field-message-help" id="u-field-message-help-<%- id %>"><%- message %></span>
|
||||
</span>
|
||||
8
lms/templates/fields/field_text_account.underscore
Normal file
8
lms/templates/fields/field_text_account.underscore
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="u-field-value field">
|
||||
<label class="u-field-title field-label" for="field-input-<%- id %>"><%- title %></label>
|
||||
<input class="field-input input-text" type="text" id="field-input-<%- id %>" title="Input field for <%- id %>" aria-describedby="u-field-message-help-<%- id %>" name="input" value="<%- value %>" />
|
||||
</div>
|
||||
<span class="u-field-message" id="u-field-message-<%- id %>">
|
||||
<span class="u-field-message-notification" aria-live="polite"></span>
|
||||
<span class="u-field-message-help" id="u-field-message-help-<%- id %>"> <%- message %></span>
|
||||
</span>
|
||||
@@ -2,25 +2,16 @@
|
||||
<div class="account-settings-container">
|
||||
<div class="wrapper-header">
|
||||
<h2 class="header-title"><%- gettext("Account Settings") %></h2>
|
||||
<small class="account-settings-header-subtitle"><%- gettext("These settings include basic information about your account. You can also specify additional information and see your linked social accounts on this page.") %></small>
|
||||
<ul class="left list-inline account-nav">
|
||||
<% _.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>
|
||||
<% }); %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="account-settings-sections">
|
||||
<% _.each(sections, function(section) { %>
|
||||
<div class="section">
|
||||
<h3 class="section-header"><%- gettext(section.title) %></h3>
|
||||
<div class="account-settings-section-body">
|
||||
<div class="ui-loading-indicator">
|
||||
<span class="spin"><i class="icon fa fa-refresh" aria-hidden=true></i></span>
|
||||
<span class="copy"><%- gettext("Loading") %></span>
|
||||
</div>
|
||||
<div class="ui-loading-error is-hidden">
|
||||
<i class="fa fa-exclamation-triangle message-error" aria-hidden=true></i>
|
||||
<span class="copy"><%- gettext("An error occurred. Please reload the page.") %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<% _.each(sections, function(section) { %>
|
||||
<div class="section">
|
||||
<% if (section.subtitle) { %>
|
||||
<p id="header-subtitle-<%- activeTabName %>" class="account-settings-header-subtitle"><%- gettext(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="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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% }); %>
|
||||
Reference in New Issue
Block a user