Allow configurable password reset support link.
Defaults to SUPPORT_SITE_LINK intentionally. Also fixed surrounding quality tests, and overall quality improvements.
This commit is contained in:
@@ -94,6 +94,7 @@ from lms.envs.common import (
|
||||
HELP_TOKENS_BOOKS,
|
||||
|
||||
SUPPORT_SITE_LINK,
|
||||
PASSWORD_RESET_SUPPORT_LINK,
|
||||
ACTIVATION_EMAIL_SUPPORT_LINK,
|
||||
|
||||
CONTACT_EMAIL,
|
||||
|
||||
@@ -133,6 +133,9 @@ def login_and_registration_form(request, initial_mode="login"):
|
||||
'third_party_auth_hint': third_party_auth_hint or '',
|
||||
'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
'support_link': configuration_helpers.get_value('SUPPORT_SITE_LINK', settings.SUPPORT_SITE_LINK),
|
||||
'password_reset_support_link': configuration_helpers.get_value(
|
||||
'PASSWORD_RESET_SUPPORT_LINK', settings.PASSWORD_RESET_SUPPORT_LINK
|
||||
) or settings.SUPPORT_SITE_LINK,
|
||||
'account_activation_messages': account_activation_messages,
|
||||
|
||||
# Include form descriptions retrieved from the user API.
|
||||
@@ -560,6 +563,9 @@ def account_settings_context(request):
|
||||
}
|
||||
},
|
||||
'platform_name': configuration_helpers.get_value('PLATFORM_NAME', settings.PLATFORM_NAME),
|
||||
'password_reset_support_link': configuration_helpers.get_value(
|
||||
'PASSWORD_RESET_SUPPORT_LINK', settings.PASSWORD_RESET_SUPPORT_LINK
|
||||
) or settings.SUPPORT_SITE_LINK,
|
||||
'user_accounts_api_url': reverse("accounts_api", kwargs={'username': user.username}),
|
||||
'user_preferences_api_url': reverse('preferences_api', kwargs={'username': user.username}),
|
||||
'disable_courseware_js': True,
|
||||
|
||||
@@ -309,9 +309,11 @@ ENABLE_COMPREHENSIVE_THEMING = ENV_TOKENS.get('ENABLE_COMPREHENSIVE_THEMING', EN
|
||||
# Marketing link overrides
|
||||
MKTG_URL_LINK_MAP.update(ENV_TOKENS.get('MKTG_URL_LINK_MAP', {}))
|
||||
|
||||
# Intentional defaults.
|
||||
SUPPORT_SITE_LINK = ENV_TOKENS.get('SUPPORT_SITE_LINK', SUPPORT_SITE_LINK)
|
||||
PASSWORD_RESET_SUPPORT_LINK = ENV_TOKENS.get('PASSWORD_RESET_SUPPORT_LINK', SUPPORT_SITE_LINK)
|
||||
ACTIVATION_EMAIL_SUPPORT_LINK = ENV_TOKENS.get(
|
||||
'ACTIVATION_EMAIL_SUPPORT_LINK', SUPPORT_SITE_LINK # Intentional default.
|
||||
'ACTIVATION_EMAIL_SUPPORT_LINK', SUPPORT_SITE_LINK
|
||||
)
|
||||
|
||||
# Mobile store URL overrides
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
"SITE_NAME": "localhost:8003",
|
||||
"STATIC_URL_BASE": "/static/",
|
||||
"SUPPORT_SITE_LINK": "https://support.example.com",
|
||||
"PASSWORD_RESET_SUPPORT_LINK": "https://support.example.com/password-reset-help.html",
|
||||
"ACTIVATION_EMAIL_SUPPORT_LINK": "https://support.example.com/activation-email-help.html",
|
||||
"SYSLOG_SERVER": "",
|
||||
"TECH_SUPPORT_EMAIL": "technical@example.com",
|
||||
|
||||
@@ -2271,6 +2271,7 @@ MKTG_URL_LINK_MAP = {
|
||||
STATIC_TEMPLATE_VIEW_DEFAULT_FILE_EXTENSION = 'html'
|
||||
|
||||
SUPPORT_SITE_LINK = ''
|
||||
PASSWORD_RESET_SUPPORT_LINK = ''
|
||||
ACTIVATION_EMAIL_SUPPORT_LINK = ''
|
||||
|
||||
############################# SOCIAL MEDIA SHARING #############################
|
||||
|
||||
@@ -361,6 +361,7 @@ MKTG_URL_LINK_MAP = {
|
||||
}
|
||||
|
||||
SUPPORT_SITE_LINK = 'https://support.example.com'
|
||||
PASSWORD_RESET_SUPPORT_LINK = 'https://support.example.com/password-reset-help.html'
|
||||
ACTIVATION_EMAIL_SUPPORT_LINK = 'https://support.example.com/activation-email-help.html'
|
||||
|
||||
############################ STATIC FILES #############################
|
||||
|
||||
@@ -14,50 +14,15 @@ define(['backbone',
|
||||
'use strict';
|
||||
|
||||
describe('edx.user.AccountSettingsFactory', function() {
|
||||
var FIELDS_DATA = {
|
||||
'country': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'gender': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'language': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'level_of_education': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'password': {
|
||||
'url': '/password_reset'
|
||||
}, 'year_of_birth': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'preferred_language': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}, 'time_zone': {
|
||||
'options': Helpers.FIELD_OPTIONS
|
||||
}
|
||||
};
|
||||
|
||||
var AUTH_DATA = {
|
||||
'providers': [
|
||||
{
|
||||
'id': 'oa2-network1',
|
||||
'name': 'Network1',
|
||||
'connected': true,
|
||||
'accepts_logins': 'true',
|
||||
'connect_url': 'yetanother1.com/auth/connect',
|
||||
'disconnect_url': 'yetanother1.com/auth/disconnect'
|
||||
},
|
||||
{
|
||||
'id': 'oa2-network2',
|
||||
'name': 'Network2',
|
||||
'connected': true,
|
||||
'accepts_logins': 'true',
|
||||
'connect_url': 'yetanother2.com/auth/connect',
|
||||
'disconnect_url': 'yetanother2.com/auth/disconnect'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var createAccountSettingsPage = function() {
|
||||
var context = AccountSettingsPage(
|
||||
FIELDS_DATA, [], AUTH_DATA, Helpers.USER_ACCOUNTS_API_URL, Helpers.USER_PREFERENCES_API_URL, 'edX'
|
||||
Helpers.FIELDS_DATA,
|
||||
[],
|
||||
Helpers.AUTH_DATA,
|
||||
Helpers.PASSWORD_RESET_SUPPORT_LINK,
|
||||
Helpers.USER_ACCOUNTS_API_URL,
|
||||
Helpers.USER_PREFERENCES_API_URL,
|
||||
Helpers.PLATFORM_NAME
|
||||
);
|
||||
return context.accountSettingsView;
|
||||
};
|
||||
|
||||
@@ -7,12 +7,63 @@ define(['underscore'], function(_) {
|
||||
var IMAGE_UPLOAD_API_URL = '/api/profile_images/v0/staff/upload';
|
||||
var IMAGE_REMOVE_API_URL = '/api/profile_images/v0/staff/remove';
|
||||
var FIND_COURSES_URL = '/courses';
|
||||
|
||||
var PASSWORD_RESET_SUPPORT_LINK = 'https://support.edx.org/hc/en-us/articles/206212088-What-if-I-did-not-receive-a-password-reset-message-'; // eslint-disable-line max-len
|
||||
var PLATFORM_NAME = 'edX';
|
||||
var PROFILE_IMAGE = {
|
||||
image_url_large: '/media/profile-images/image.jpg',
|
||||
has_image: true
|
||||
};
|
||||
|
||||
var FIELD_OPTIONS = [
|
||||
['0', 'Option 0'],
|
||||
['1', 'Option 1'],
|
||||
['2', 'Option 2'],
|
||||
['3', 'Option 3']
|
||||
];
|
||||
var TIME_ZONE_RESPONSE = [{
|
||||
time_zone: 'America/Guyana',
|
||||
description: 'America/Guyana (ECT, UTC-0500)'
|
||||
}];
|
||||
var FIELDS_DATA = {
|
||||
country: {
|
||||
options: FIELD_OPTIONS
|
||||
}, gender: {
|
||||
options: FIELD_OPTIONS
|
||||
}, language: {
|
||||
options: FIELD_OPTIONS
|
||||
}, level_of_education: {
|
||||
options: FIELD_OPTIONS
|
||||
}, password: {
|
||||
url: '/password_reset'
|
||||
}, year_of_birth: {
|
||||
options: FIELD_OPTIONS
|
||||
}, preferred_language: {
|
||||
options: FIELD_OPTIONS
|
||||
}, time_zone: {
|
||||
options: FIELD_OPTIONS
|
||||
}
|
||||
};
|
||||
var AUTH_DATA = {
|
||||
providers: [
|
||||
{
|
||||
id: 'oa2-network1',
|
||||
name: 'Network1',
|
||||
connected: true,
|
||||
accepts_logins: 'true',
|
||||
connect_url: 'yetanother1.com/auth/connect',
|
||||
disconnect_url: 'yetanother1.com/auth/disconnect'
|
||||
},
|
||||
{
|
||||
id: 'oa2-network2',
|
||||
name: 'Network2',
|
||||
connected: true,
|
||||
accepts_logins: 'true',
|
||||
connect_url: 'yetanother2.com/auth/connect',
|
||||
disconnect_url: 'yetanother2.com/auth/disconnect'
|
||||
}
|
||||
]
|
||||
};
|
||||
var IMAGE_MAX_BYTES = 1024 * 1024;
|
||||
var IMAGE_MIN_BYTES = 100;
|
||||
var DEFAULT_ACCOUNT_SETTINGS_DATA = {
|
||||
username: 'student',
|
||||
name: 'Student',
|
||||
@@ -28,35 +79,19 @@ define(['underscore'], function(_) {
|
||||
profile_image: PROFILE_IMAGE,
|
||||
accomplishments_shared: false
|
||||
};
|
||||
|
||||
var createAccountSettingsData = function(options) {
|
||||
return _.extend(_.extend({}, DEFAULT_ACCOUNT_SETTINGS_DATA), options);
|
||||
};
|
||||
|
||||
var DEFAULT_USER_PREFERENCES_DATA = {
|
||||
'pref-lang': '2',
|
||||
'time_zone': null
|
||||
};
|
||||
|
||||
var createAccountSettingsData = function(options) {
|
||||
return _.extend(_.extend({}, DEFAULT_ACCOUNT_SETTINGS_DATA), options);
|
||||
};
|
||||
|
||||
var createUserPreferencesData = function(options) {
|
||||
return _.extend(_.extend({}, DEFAULT_USER_PREFERENCES_DATA), options);
|
||||
};
|
||||
|
||||
var FIELD_OPTIONS = [
|
||||
['0', 'Option 0'],
|
||||
['1', 'Option 1'],
|
||||
['2', 'Option 2'],
|
||||
['3', 'Option 3']
|
||||
];
|
||||
|
||||
var TIME_ZONE_RESPONSE = [{
|
||||
time_zone: 'America/Guyana',
|
||||
description: 'America/Guyana (ECT, UTC-0500)'
|
||||
}];
|
||||
|
||||
var IMAGE_MAX_BYTES = 1024 * 1024;
|
||||
var IMAGE_MIN_BYTES = 100;
|
||||
|
||||
var expectLoadingIndicatorIsVisible = function(view, visible) {
|
||||
if (visible) {
|
||||
expect($('.ui-loading-indicator')).not.toHaveClass('is-hidden');
|
||||
@@ -88,10 +123,6 @@ define(['underscore'], function(_) {
|
||||
}
|
||||
};
|
||||
|
||||
var expectSettingsSectionsButNotFieldsToBeRendered = function(accountSettingsView) {
|
||||
expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView, false);
|
||||
};
|
||||
|
||||
var expectSettingsSectionsAndFieldsToBeRendered = function(accountSettingsView, fieldsAreRendered) {
|
||||
var sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
|
||||
|
||||
@@ -99,7 +130,8 @@ define(['underscore'], function(_) {
|
||||
expect(sectionElements.length).toBe(sectionsData.length);
|
||||
|
||||
_.each(sectionElements, function(sectionElement, sectionIndex) {
|
||||
expect($(sectionElement).find('.section-header').text().trim()).toBe(sectionsData[sectionIndex].title);
|
||||
expect($(sectionElement).find('.section-header').text()
|
||||
.trim()).toBe(sectionsData[sectionIndex].title);
|
||||
|
||||
var sectionFieldElements = $(sectionElement).find('.u-field');
|
||||
|
||||
@@ -115,6 +147,10 @@ define(['underscore'], function(_) {
|
||||
});
|
||||
};
|
||||
|
||||
var expectSettingsSectionsButNotFieldsToBeRendered = function(accountSettingsView) {
|
||||
expectSettingsSectionsAndFieldsToBeRendered(accountSettingsView, false);
|
||||
};
|
||||
|
||||
return {
|
||||
USER_ACCOUNTS_API_URL: USER_ACCOUNTS_API_URL,
|
||||
USER_PREFERENCES_API_URL: USER_PREFERENCES_API_URL,
|
||||
@@ -122,13 +158,17 @@ define(['underscore'], function(_) {
|
||||
FIND_COURSES_URL: FIND_COURSES_URL,
|
||||
IMAGE_UPLOAD_API_URL: IMAGE_UPLOAD_API_URL,
|
||||
IMAGE_REMOVE_API_URL: IMAGE_REMOVE_API_URL,
|
||||
IMAGE_MAX_BYTES: IMAGE_MAX_BYTES,
|
||||
IMAGE_MIN_BYTES: IMAGE_MIN_BYTES,
|
||||
PASSWORD_RESET_SUPPORT_LINK: PASSWORD_RESET_SUPPORT_LINK,
|
||||
PLATFORM_NAME: PLATFORM_NAME,
|
||||
PROFILE_IMAGE: PROFILE_IMAGE,
|
||||
createAccountSettingsData: createAccountSettingsData,
|
||||
createUserPreferencesData: createUserPreferencesData,
|
||||
FIELD_OPTIONS: FIELD_OPTIONS,
|
||||
TIME_ZONE_RESPONSE: TIME_ZONE_RESPONSE,
|
||||
FIELDS_DATA: FIELDS_DATA,
|
||||
AUTH_DATA: AUTH_DATA,
|
||||
IMAGE_MAX_BYTES: IMAGE_MAX_BYTES,
|
||||
IMAGE_MIN_BYTES: IMAGE_MIN_BYTES,
|
||||
createAccountSettingsData: createAccountSettingsData,
|
||||
createUserPreferencesData: createUserPreferencesData,
|
||||
expectLoadingIndicatorIsVisible: expectLoadingIndicatorIsVisible,
|
||||
expectLoadingErrorIsVisible: expectLoadingErrorIsVisible,
|
||||
expectElementContainsField: expectElementContainsField,
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
|
||||
this.platformName = options.platform_name;
|
||||
this.supportURL = options.support_link;
|
||||
this.passwordResetSupportUrl = options.password_reset_support_link;
|
||||
this.createAccountOption = options.account_creation_allowed;
|
||||
|
||||
// The login view listens for 'sync' events from the reset model
|
||||
@@ -129,6 +130,7 @@
|
||||
accountActivationMessages: this.accountActivationMessages,
|
||||
platformName: this.platformName,
|
||||
supportURL: this.supportURL,
|
||||
passwordResetSupportUrl: this.passwordResetSupportUrl,
|
||||
createAccountOption: this.createAccountOption
|
||||
});
|
||||
|
||||
|
||||
@@ -5,206 +5,226 @@
|
||||
'underscore',
|
||||
'gettext',
|
||||
'edx-ui-toolkit/js/utils/html-utils',
|
||||
'edx-ui-toolkit/js/utils/string-utils',
|
||||
'js/student_account/views/FormView',
|
||||
'text!templates/student_account/form_success.underscore',
|
||||
'text!templates/student_account/form_status.underscore'
|
||||
],
|
||||
function($, _, gettext, HtmlUtils, FormView, formSuccessTpl, formStatusTpl) {
|
||||
return FormView.extend({
|
||||
el: '#login-form',
|
||||
tpl: '#login-tpl',
|
||||
events: {
|
||||
'click .js-login': 'submitForm',
|
||||
'click .forgot-password': 'forgotPassword',
|
||||
'click .login-provider': 'thirdPartyAuth'
|
||||
},
|
||||
formType: 'login',
|
||||
requiredStr: '',
|
||||
optionalStr: '',
|
||||
submitButton: '.js-login',
|
||||
formSuccessTpl: formSuccessTpl,
|
||||
formStatusTpl: formStatusTpl,
|
||||
authWarningJsHook: 'js-auth-warning',
|
||||
passwordResetSuccessJsHook: 'js-password-reset-success',
|
||||
defaultFormErrorsTitle: gettext('We couldn\'t sign you in.'),
|
||||
], function(
|
||||
$, _, gettext,
|
||||
HtmlUtils,
|
||||
StringUtils,
|
||||
FormView,
|
||||
formSuccessTpl,
|
||||
formStatusTpl
|
||||
) {
|
||||
return FormView.extend({
|
||||
el: '#login-form',
|
||||
tpl: '#login-tpl',
|
||||
events: {
|
||||
'click .js-login': 'submitForm',
|
||||
'click .forgot-password': 'forgotPassword',
|
||||
'click .login-provider': 'thirdPartyAuth'
|
||||
},
|
||||
formType: 'login',
|
||||
requiredStr: '',
|
||||
optionalStr: '',
|
||||
submitButton: '.js-login',
|
||||
formSuccessTpl: formSuccessTpl,
|
||||
formStatusTpl: formStatusTpl,
|
||||
authWarningJsHook: 'js-auth-warning',
|
||||
passwordResetSuccessJsHook: 'js-password-reset-success',
|
||||
defaultFormErrorsTitle: gettext('We couldn\'t sign you in.'),
|
||||
|
||||
preRender: function(data) {
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.hasSecondaryProviders = (
|
||||
data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
|
||||
preRender: function(data) {
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.hasSecondaryProviders = (
|
||||
data.thirdPartyAuth.secondaryProviders && data.thirdPartyAuth.secondaryProviders.length
|
||||
);
|
||||
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
|
||||
this.errorMessage = data.thirdPartyAuth.errorMessage || '';
|
||||
this.platformName = data.platformName;
|
||||
this.resetModel = data.resetModel;
|
||||
this.supportURL = data.supportURL;
|
||||
this.passwordResetSupportUrl = data.passwordResetSupportUrl;
|
||||
this.createAccountOption = data.createAccountOption;
|
||||
this.accountActivationMessages = data.accountActivationMessages;
|
||||
|
||||
this.listenTo(this.model, 'sync', this.saveSuccess);
|
||||
this.listenTo(this.resetModel, 'sync', this.resetEmail);
|
||||
},
|
||||
|
||||
render: function(html) {
|
||||
var fields = html || '';
|
||||
|
||||
$(this.el).html(_.template(this.tpl)({
|
||||
// We pass the context object to the template so that
|
||||
// we can perform variable interpolation using sprintf
|
||||
context: {
|
||||
fields: fields,
|
||||
currentProvider: this.currentProvider,
|
||||
providers: this.providers,
|
||||
hasSecondaryProviders: this.hasSecondaryProviders,
|
||||
platformName: this.platformName,
|
||||
createAccountOption: this.createAccountOption
|
||||
}
|
||||
}));
|
||||
|
||||
this.postRender();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var formErrorsTitle;
|
||||
this.$container = $(this.el);
|
||||
this.$form = this.$container.find('form');
|
||||
this.$formFeedback = this.$container.find('.js-form-feedback');
|
||||
this.$submitButton = this.$container.find(this.submitButton);
|
||||
|
||||
if (this.errorMessage) {
|
||||
formErrorsTitle = _.sprintf(
|
||||
gettext('An error occurred when signing you in to %s.'),
|
||||
this.platformName
|
||||
);
|
||||
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
|
||||
this.errorMessage = data.thirdPartyAuth.errorMessage || '';
|
||||
this.platformName = data.platformName;
|
||||
this.resetModel = data.resetModel;
|
||||
this.supportURL = data.supportURL;
|
||||
this.createAccountOption = data.createAccountOption;
|
||||
this.accountActivationMessages = data.accountActivationMessages;
|
||||
|
||||
this.listenTo(this.model, 'sync', this.saveSuccess);
|
||||
this.listenTo(this.resetModel, 'sync', this.resetEmail);
|
||||
},
|
||||
|
||||
render: function(html) {
|
||||
var fields = html || '';
|
||||
|
||||
$(this.el).html(_.template(this.tpl)({
|
||||
// We pass the context object to the template so that
|
||||
// we can perform variable interpolation using sprintf
|
||||
context: {
|
||||
fields: fields,
|
||||
currentProvider: this.currentProvider,
|
||||
providers: this.providers,
|
||||
hasSecondaryProviders: this.hasSecondaryProviders,
|
||||
platformName: this.platformName,
|
||||
createAccountOption: this.createAccountOption
|
||||
}
|
||||
}));
|
||||
|
||||
this.postRender();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var formErrorsTitle;
|
||||
this.$container = $(this.el);
|
||||
this.$form = this.$container.find('form');
|
||||
this.$formFeedback = this.$container.find('.js-form-feedback');
|
||||
this.$submitButton = this.$container.find(this.submitButton);
|
||||
|
||||
if (this.errorMessage) {
|
||||
formErrorsTitle = _.sprintf(
|
||||
gettext('An error occurred when signing you in to %s.'),
|
||||
this.platformName
|
||||
);
|
||||
this.renderErrors(formErrorsTitle, [this.errorMessage]);
|
||||
} else if (this.currentProvider) {
|
||||
/* If we're already authenticated with a third-party
|
||||
* provider, try logging in. The easiest way to do this
|
||||
* is to simply submit the form.
|
||||
*/
|
||||
this.model.save();
|
||||
}
|
||||
|
||||
// Display account activation success or error messages.
|
||||
this.renderAccountActivationMessages();
|
||||
},
|
||||
|
||||
renderAccountActivationMessages: function() {
|
||||
_.each(this.accountActivationMessages, this.renderAccountActivationMessage, this);
|
||||
},
|
||||
|
||||
renderAccountActivationMessage: function(message) {
|
||||
this.renderFormFeedback(this.formStatusTpl, {
|
||||
jsHook: message.tags,
|
||||
message: HtmlUtils.HTML(message.message)
|
||||
});
|
||||
},
|
||||
|
||||
forgotPassword: function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.trigger('password-help');
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
postFormSubmission: function() {
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
resetEmail: function() {
|
||||
var email = $('#password-reset-email').val(),
|
||||
successTitle = gettext('Check Your Email'),
|
||||
successMessageHtml = HtmlUtils.interpolateHtml(
|
||||
gettext('{paragraphStart}You entered {boldStart}{email}{boldEnd}. If this email address is associated with your {platform_name} account, we will send a message with password reset instructions to this email address.{paragraphEnd}' + // eslint-disable-line max-len
|
||||
'{paragraphStart}If you do not receive a password reset message, verify that you entered the correct email address, or check your spam folder.{paragraphEnd}' + // eslint-disable-line max-len
|
||||
'{paragraphStart}If you need further assistance, {anchorStart}contact technical support{anchorEnd}.{paragraphEnd}'), { // eslint-disable-line max-len
|
||||
boldStart: HtmlUtils.HTML('<b>'),
|
||||
boldEnd: HtmlUtils.HTML('</b>'),
|
||||
paragraphStart: HtmlUtils.HTML('<p>'),
|
||||
paragraphEnd: HtmlUtils.HTML('</p>'),
|
||||
email: email,
|
||||
platform_name: this.platformName,
|
||||
anchorStart: HtmlUtils.HTML('<a href="' + this.supportURL + '">'),
|
||||
anchorEnd: HtmlUtils.HTML('</a>')
|
||||
}
|
||||
);
|
||||
|
||||
this.clearFormErrors();
|
||||
this.clearPasswordResetSuccess();
|
||||
|
||||
this.renderFormFeedback(this.formSuccessTpl, {
|
||||
jsHook: this.passwordResetSuccessJsHook,
|
||||
title: successTitle,
|
||||
messageHtml: successMessageHtml
|
||||
});
|
||||
},
|
||||
|
||||
thirdPartyAuth: function(event) {
|
||||
var providerUrl = $(event.currentTarget).data('provider-url') || '';
|
||||
|
||||
if (providerUrl) {
|
||||
window.location.href = providerUrl;
|
||||
}
|
||||
},
|
||||
|
||||
saveSuccess: function() {
|
||||
this.trigger('auth-complete');
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
saveError: function(error) {
|
||||
var msg = error.responseText;
|
||||
if (error.status === 0) {
|
||||
msg = gettext('An error has occurred. Check your Internet connection and try again.');
|
||||
} else if (error.status === 500) {
|
||||
msg = gettext('An error has occurred. Try refreshing the page, or check your Internet connection.');
|
||||
}
|
||||
this.errors = ['<li>' + msg + '</li>'];
|
||||
this.clearPasswordResetSuccess();
|
||||
|
||||
/* If we've gotten a 403 error, it means that we've successfully
|
||||
* authenticated with a third-party provider, but we haven't
|
||||
* linked the account to an EdX account. In this case,
|
||||
* we need to prompt the user to enter a little more information
|
||||
* to complete the registration process.
|
||||
*/
|
||||
if (error.status === 403 &&
|
||||
error.responseText === 'third-party-auth' &&
|
||||
this.currentProvider) {
|
||||
this.clearFormErrors();
|
||||
this.renderAuthWarning();
|
||||
} else {
|
||||
this.renderErrors(this.defaultFormErrorsTitle, this.errors);
|
||||
}
|
||||
this.toggleDisableButton(false);
|
||||
},
|
||||
|
||||
renderAuthWarning: function() {
|
||||
var message = _.sprintf(
|
||||
gettext('You have successfully signed into %(currentProvider)s, but your %(currentProvider)s' +
|
||||
' account does not have a linked %(platformName)s account. To link your accounts,' +
|
||||
' sign in now using your %(platformName)s password.'),
|
||||
{currentProvider: this.currentProvider, platformName: this.platformName}
|
||||
);
|
||||
|
||||
this.clearAuthWarning();
|
||||
this.renderFormFeedback(this.formStatusTpl, {
|
||||
jsHook: this.authWarningJsHook,
|
||||
message: message
|
||||
});
|
||||
},
|
||||
|
||||
clearPasswordResetSuccess: function() {
|
||||
var query = '.' + this.passwordResetSuccessJsHook;
|
||||
this.clearFormFeedbackItems(query);
|
||||
},
|
||||
|
||||
clearAuthWarning: function() {
|
||||
var query = '.' + this.authWarningJsHook;
|
||||
this.clearFormFeedbackItems(query);
|
||||
this.renderErrors(formErrorsTitle, [this.errorMessage]);
|
||||
} else if (this.currentProvider) {
|
||||
/* If we're already authenticated with a third-party
|
||||
* provider, try logging in. The easiest way to do this
|
||||
* is to simply submit the form.
|
||||
*/
|
||||
this.model.save();
|
||||
}
|
||||
});
|
||||
|
||||
// Display account activation success or error messages.
|
||||
this.renderAccountActivationMessages();
|
||||
},
|
||||
|
||||
renderAccountActivationMessages: function() {
|
||||
_.each(this.accountActivationMessages, this.renderAccountActivationMessage, this);
|
||||
},
|
||||
|
||||
renderAccountActivationMessage: function(message) {
|
||||
this.renderFormFeedback(this.formStatusTpl, {
|
||||
jsHook: message.tags,
|
||||
message: HtmlUtils.HTML(message.message)
|
||||
});
|
||||
},
|
||||
|
||||
forgotPassword: function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
this.trigger('password-help');
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
postFormSubmission: function() {
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
resetEmail: function() {
|
||||
var email = $('#password-reset-email').val(),
|
||||
successTitle = gettext('Check Your Email'),
|
||||
successMessageHtml = HtmlUtils.interpolateHtml(
|
||||
gettext('{paragraphStart}You entered {boldStart}{email}{boldEnd}. If this email address is associated with your {platform_name} account, we will send a message with password reset instructions to this email address.{paragraphEnd}' + // eslint-disable-line max-len
|
||||
'{paragraphStart}If you do not receive a password reset message, verify that you entered the correct email address, or check your spam folder.{paragraphEnd}' + // eslint-disable-line max-len
|
||||
'{paragraphStart}If you need further assistance, {anchorStart}contact technical support{anchorEnd}.{paragraphEnd}'), { // eslint-disable-line max-len
|
||||
boldStart: HtmlUtils.HTML('<b>'),
|
||||
boldEnd: HtmlUtils.HTML('</b>'),
|
||||
paragraphStart: HtmlUtils.HTML('<p>'),
|
||||
paragraphEnd: HtmlUtils.HTML('</p>'),
|
||||
email: email,
|
||||
platform_name: this.platformName,
|
||||
anchorStart: HtmlUtils.HTML(
|
||||
StringUtils.interpolate(
|
||||
'<a href="{passwordResetSupportUrl}">', {
|
||||
passwordResetSupportUrl: this.passwordResetSupportUrl
|
||||
}
|
||||
)
|
||||
),
|
||||
anchorEnd: HtmlUtils.HTML('</a>')
|
||||
}
|
||||
);
|
||||
|
||||
this.clearFormErrors();
|
||||
this.clearPasswordResetSuccess();
|
||||
|
||||
this.renderFormFeedback(this.formSuccessTpl, {
|
||||
jsHook: this.passwordResetSuccessJsHook,
|
||||
title: successTitle,
|
||||
messageHtml: successMessageHtml
|
||||
});
|
||||
},
|
||||
|
||||
thirdPartyAuth: function(event) {
|
||||
var providerUrl = $(event.currentTarget).data('provider-url') || '';
|
||||
|
||||
if (providerUrl) {
|
||||
window.location.href = providerUrl;
|
||||
}
|
||||
},
|
||||
|
||||
saveSuccess: function() {
|
||||
this.trigger('auth-complete');
|
||||
this.clearPasswordResetSuccess();
|
||||
},
|
||||
|
||||
saveError: function(error) {
|
||||
var msg = error.responseText;
|
||||
if (error.status === 0) {
|
||||
msg = gettext('An error has occurred. Check your Internet connection and try again.');
|
||||
} else if (error.status === 500) {
|
||||
msg = gettext('An error has occurred. Try refreshing the page, or check your Internet connection.'); // eslint-disable-line max-len
|
||||
}
|
||||
this.errors = [
|
||||
StringUtils.interpolate(
|
||||
'<li>{msg}</li>', {
|
||||
msg: msg
|
||||
}
|
||||
)
|
||||
];
|
||||
this.clearPasswordResetSuccess();
|
||||
|
||||
/* If we've gotten a 403 error, it means that we've successfully
|
||||
* authenticated with a third-party provider, but we haven't
|
||||
* linked the account to an EdX account. In this case,
|
||||
* we need to prompt the user to enter a little more information
|
||||
* to complete the registration process.
|
||||
*/
|
||||
if (error.status === 403 &&
|
||||
error.responseText === 'third-party-auth' &&
|
||||
this.currentProvider) {
|
||||
this.clearFormErrors();
|
||||
this.renderAuthWarning();
|
||||
} else {
|
||||
this.renderErrors(this.defaultFormErrorsTitle, this.errors);
|
||||
}
|
||||
this.toggleDisableButton(false);
|
||||
},
|
||||
|
||||
renderAuthWarning: function() {
|
||||
var message = _.sprintf(
|
||||
gettext('You have successfully signed into %(currentProvider)s, but your %(currentProvider)s' +
|
||||
' account does not have a linked %(platformName)s account. To link your accounts,' +
|
||||
' sign in now using your %(platformName)s password.'),
|
||||
{currentProvider: this.currentProvider, platformName: this.platformName}
|
||||
);
|
||||
|
||||
this.clearAuthWarning();
|
||||
this.renderFormFeedback(this.formStatusTpl, {
|
||||
jsHook: this.authWarningJsHook,
|
||||
message: message
|
||||
});
|
||||
},
|
||||
|
||||
clearPasswordResetSuccess: function() {
|
||||
var query = '.' + this.passwordResetSuccessJsHook;
|
||||
this.clearFormFeedbackItems(query);
|
||||
},
|
||||
|
||||
clearAuthWarning: function() {
|
||||
var query = '.' + this.authWarningJsHook;
|
||||
this.clearFormFeedbackItems(query);
|
||||
}
|
||||
});
|
||||
});
|
||||
}).call(this, define || RequireJS.define);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
fieldsData,
|
||||
ordersHistoryData,
|
||||
authData,
|
||||
passwordResetSupportUrl,
|
||||
userAccountsApiUrl,
|
||||
userPreferencesApiUrl,
|
||||
accountUserId,
|
||||
@@ -76,6 +77,7 @@
|
||||
screenReaderTitle: gettext('Reset Your Password'),
|
||||
valueAttribute: 'password',
|
||||
emailAttribute: 'email',
|
||||
passwordResetSupportUrl: passwordResetSupportUrl,
|
||||
linkTitle: gettext('Reset Your Password'),
|
||||
linkHref: fieldsData.password.url,
|
||||
helpMessage: StringUtils.interpolate(
|
||||
@@ -191,7 +193,7 @@
|
||||
),
|
||||
fields: _.map(authData.providers, function(provider) {
|
||||
return {
|
||||
'view': new AccountSettingsFieldViews.AuthFieldView({
|
||||
view: new AccountSettingsFieldViews.AuthFieldView({
|
||||
title: provider.name,
|
||||
valueAttribute: 'auth-' + provider.id,
|
||||
helpMessage: '',
|
||||
@@ -208,10 +210,10 @@
|
||||
|
||||
ordersHistoryData.unshift(
|
||||
{
|
||||
'title': gettext('ORDER NAME'),
|
||||
'order_date': gettext('ORDER PLACED'),
|
||||
'price': gettext('TOTAL'),
|
||||
'number': gettext('ORDER NUMBER')
|
||||
title: gettext('ORDER NAME'),
|
||||
order_date: gettext('ORDER PLACED'),
|
||||
price: gettext('TOTAL'),
|
||||
number: gettext('ORDER NUMBER')
|
||||
}
|
||||
);
|
||||
|
||||
@@ -228,7 +230,7 @@
|
||||
orderNumber = 'orderId';
|
||||
}
|
||||
return {
|
||||
'view': new AccountSettingsFieldViews.OrderHistoryFieldView({
|
||||
view: new AccountSettingsFieldViews.OrderHistoryFieldView({
|
||||
totalPrice: order.price,
|
||||
orderId: order.number,
|
||||
orderDate: order.order_date,
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
field_order_history_template,
|
||||
StringUtils,
|
||||
HtmlUtils
|
||||
)
|
||||
{
|
||||
) {
|
||||
var AccountSettingsFieldViews = {
|
||||
ReadonlyFieldView: FieldViews.ReadonlyFieldView.extend({
|
||||
fieldTemplate: field_readonly_account_template
|
||||
@@ -44,7 +43,7 @@
|
||||
this.indicators.success,
|
||||
StringUtils.interpolate(
|
||||
gettext('We\'ve sent a confirmation message to {new_email_address}. Click the link in the message to update your email address.'), // eslint-disable-line max-len
|
||||
{'new_email_address': this.fieldValue()}
|
||||
{new_email_address: this.fieldValue()}
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -53,7 +52,7 @@
|
||||
fieldTemplate: field_dropdown_account_template,
|
||||
saveSucceeded: function() {
|
||||
var data = {
|
||||
'language': this.modelValue()
|
||||
language: this.modelValue()
|
||||
};
|
||||
|
||||
var view = this;
|
||||
@@ -189,9 +188,19 @@
|
||||
successMessage: function() {
|
||||
return HtmlUtils.joinHtml(
|
||||
this.indicators.success,
|
||||
StringUtils.interpolate(
|
||||
gettext('We\'ve sent a message to {email_address}. Click the link in the message to reset your password.'), // eslint-disable-line max-len
|
||||
{'email_address': this.model.get(this.options.emailAttribute)}
|
||||
HtmlUtils.interpolateHtml(
|
||||
gettext('We\'ve sent a message to {email}. Click the link in the message to reset your password. Didn\'t receive the message? Contact {anchorStart}technical support{anchorEnd}.'), // eslint-disable-line max-len
|
||||
{
|
||||
email: this.model.get(this.options.emailAttribute),
|
||||
anchorStart: HtmlUtils.HTML(
|
||||
StringUtils.interpolate(
|
||||
'<a href="{passwordResetSupportUrl}">', {
|
||||
passwordResetSupportUrl: this.options.passwordResetSupportUrl
|
||||
}
|
||||
)
|
||||
),
|
||||
anchorEnd: HtmlUtils.HTML('</a>')
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -209,7 +218,7 @@
|
||||
saveValue: function() {
|
||||
if (this.persistChanges === true) {
|
||||
var attributes = {},
|
||||
value = this.fieldValue() ? [{'code': this.fieldValue()}] : [];
|
||||
value = this.fieldValue() ? [{code: this.fieldValue()}] : [];
|
||||
attributes[this.options.valueAttribute] = value;
|
||||
this.saveAttributes(attributes);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str
|
||||
fieldsData,
|
||||
ordersHistoryData,
|
||||
authData,
|
||||
'${ password_reset_support_link | n, js_escaped_string }',
|
||||
'${ user_accounts_api_url | n, js_escaped_string }',
|
||||
'${ user_preferences_api_url | n, js_escaped_string }',
|
||||
${ user.id | n, dump_js_escaped_json },
|
||||
|
||||
Reference in New Issue
Block a user