ECOM-783 updated logistration in light of redesign
This commit is contained in:
@@ -12,7 +12,7 @@ describe('edx.utils.validate', function () {
|
||||
EMAIL_ERROR_FRAGMENT = 'formatted',
|
||||
MIN_ERROR_FRAGMENT = 'least',
|
||||
MAX_ERROR_FRAGMENT = 'up to',
|
||||
REQUIRED_ERROR_FRAGMENT = 'empty',
|
||||
REQUIRED_ERROR_FRAGMENT = 'Please enter your',
|
||||
CUSTOM_MESSAGE = 'custom message';
|
||||
|
||||
var createFixture = function( type, name, required, minlength, maxlength, value ) {
|
||||
|
||||
@@ -19,9 +19,9 @@ var edx = edx || {};
|
||||
|
||||
msg: {
|
||||
email: '<li><%- gettext("The email address you\'ve provided isn\'t formatted correctly.") %></li>',
|
||||
min: '<li><%- _.sprintf(gettext("%(field)s must have at least %(count)d characters."), context) %></li>',
|
||||
max: '<li><%- _.sprintf(gettext("%(field)s can only contain up to %(count)d characters."), context) %></li>',
|
||||
required: '<li><%- _.sprintf(gettext("The %(field)s field cannot be empty."), context) %></li>',
|
||||
min: '<li><%- _.sprintf( gettext("%(field)s must have at least %(count)d characters."), context ) %></li>',
|
||||
max: '<li><%- _.sprintf( gettext("%(field)s can only contain up to %(count)d characters."), context ) %></li>',
|
||||
required: '<li><%- _.sprintf( gettext("Please enter your %(field)s."), context ) %></li>',
|
||||
custom: '<li><%= content %></li>'
|
||||
},
|
||||
|
||||
|
||||
@@ -120,8 +120,8 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
def is_browser_on_page(self):
|
||||
"""Check whether the combined login/registration page has loaded. """
|
||||
return (
|
||||
self.q(css="#register-option").is_present() and
|
||||
self.q(css="#login-option").is_present() and
|
||||
self.q(css="#login-anchor").is_present() and
|
||||
self.q(css="#register-anchor").is_present() and
|
||||
self.current_form is not None
|
||||
)
|
||||
|
||||
@@ -130,7 +130,10 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
old_form = self.current_form
|
||||
|
||||
# Toggle the form
|
||||
self.q(css=".form-toggle:not(:checked)").click()
|
||||
if old_form == "login":
|
||||
self.q(css=".form-toggle[data-type='register']").click()
|
||||
else:
|
||||
self.q(css=".form-toggle[data-type='login']").click()
|
||||
|
||||
# Wait for the form to change before returning
|
||||
EmptyPromise(
|
||||
@@ -157,9 +160,9 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
"""
|
||||
# Fill in the form
|
||||
self.q(css="#register-email").fill(email)
|
||||
self.q(css="#register-password").fill(password)
|
||||
self.q(css="#register-username").fill(username)
|
||||
self.q(css="#register-name").fill(full_name)
|
||||
self.q(css="#register-username").fill(username)
|
||||
self.q(css="#register-password").fill(password)
|
||||
if country:
|
||||
self.q(css="#register-country option[value='{country}']".format(country=country)).click()
|
||||
if (terms_of_service):
|
||||
@@ -168,7 +171,7 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
# Submit it
|
||||
self.q(css=".register-button").click()
|
||||
|
||||
def login(self, email="", password="", remember_me=True):
|
||||
def login(self, email="", password=""):
|
||||
"""Fills in and submits the login form.
|
||||
|
||||
Requires that the "login" form is visible.
|
||||
@@ -179,14 +182,11 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
Keyword Arguments:
|
||||
email (unicode): The user's email address.
|
||||
password (unicode): The user's password.
|
||||
remember_me (boolean): If True, check the "remember me" box.
|
||||
|
||||
"""
|
||||
# Fill in the form
|
||||
self.q(css="#login-email").fill(email)
|
||||
self.q(css="#login-password").fill(password)
|
||||
if remember_me:
|
||||
self.q(css="#login-remember").click()
|
||||
|
||||
# Submit it
|
||||
self.q(css=".login-button").click()
|
||||
@@ -217,6 +217,8 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
# Submit it
|
||||
self.q(css="button.js-reset").click()
|
||||
|
||||
return CombinedLoginAndRegisterPage(self.browser).wait_for_page()
|
||||
|
||||
@property
|
||||
@unguarded
|
||||
def current_form(self):
|
||||
@@ -233,7 +235,7 @@ class CombinedLoginAndRegisterPage(PageObject):
|
||||
return "register"
|
||||
elif self.q(css=".login-button").visible:
|
||||
return "login"
|
||||
elif self.q(css=".js-reset").visible or self.q(css=".js-reset-success").visible:
|
||||
elif self.q(css=".js-reset").visible:
|
||||
return "password-reset"
|
||||
|
||||
@property
|
||||
|
||||
@@ -218,9 +218,9 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
|
||||
|
||||
# Verify that the expected errors are displayed.
|
||||
errors = self.register_page.wait_for_errors()
|
||||
self.assertIn(u'The Username field cannot be empty.', errors)
|
||||
self.assertIn(u'Please enter your Public username.', errors)
|
||||
self.assertIn(u'You must agree to the edX Terms of Service and Honor Code.', errors)
|
||||
self.assertIn(u'The Country field cannot be empty.', errors)
|
||||
self.assertIn(u'Please select your Country.', errors)
|
||||
|
||||
def test_toggle_to_login_form(self):
|
||||
self.register_page.visit().toggle_form()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
@shard_1
|
||||
Feature: LMS.Homepage for web users
|
||||
In order to get an idea what edX is about
|
||||
As a an anonymous web user
|
||||
As an anonymous web user
|
||||
I want to check the information on the home page
|
||||
|
||||
Scenario: User can see the "Login" button
|
||||
Scenario: User can see the "Sign in" button
|
||||
Given I visit the homepage
|
||||
Then I should see a link called "Log in"
|
||||
Then I should see a link called "Sign in"
|
||||
|
||||
Scenario: User can see the "Register Now" button
|
||||
Given I visit the homepage
|
||||
|
||||
@@ -8,7 +8,7 @@ Feature: LMS.Login in as a registered user
|
||||
Given I am an edX user
|
||||
And I am an unactivated user
|
||||
And I visit the homepage
|
||||
When I click the link with the text "Log in"
|
||||
When I click the link with the text "Sign in"
|
||||
And I submit my credentials on the login form
|
||||
Then I should see the login error message "This account has not been activated"
|
||||
|
||||
@@ -18,15 +18,15 @@ Feature: LMS.Login in as a registered user
|
||||
Given I am an edX user
|
||||
And I am an activated user
|
||||
And I visit the homepage
|
||||
When I click the link with the text "Log in"
|
||||
When I click the link with the text "Sign in"
|
||||
And I submit my credentials on the login form
|
||||
Then I should be on the dashboard page
|
||||
|
||||
Scenario: Logout of a signed in account
|
||||
Given I am logged in
|
||||
When I click the dropdown arrow
|
||||
And I click the link with the text "Log Out"
|
||||
Then I should see a link with the text "Log in"
|
||||
And I click the link with the text "Sign out"
|
||||
Then I should see a link with the text "Sign in"
|
||||
And I should see that the path is "/"
|
||||
|
||||
Scenario: Login with valid redirect
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
'string_utils': 'xmodule_js/common_static/js/src/string_utils',
|
||||
|
||||
// Manually specify LMS files that are not converted to RequireJS
|
||||
'history': 'js/vendor/history',
|
||||
'js/verify_student/photocapture': 'js/verify_student/photocapture',
|
||||
'js/staff_debug_actions': 'js/staff_debug_actions',
|
||||
|
||||
@@ -372,6 +373,7 @@
|
||||
'underscore',
|
||||
'backbone',
|
||||
'gettext',
|
||||
'history',
|
||||
'utility',
|
||||
'js/student_account/views/LoginView',
|
||||
'js/student_account/views/PasswordResetView',
|
||||
|
||||
@@ -96,13 +96,13 @@ define([
|
||||
var assertForms = function(visibleType, hiddenType) {
|
||||
expect($(visibleType)).not.toHaveClass('hidden');
|
||||
expect($(hiddenType)).toHaveClass('hidden');
|
||||
expect($('#password-reset-wrapper')).toBeEmpty();
|
||||
expect($('#password-reset-form')).toHaveClass('hidden');
|
||||
};
|
||||
|
||||
var selectForm = function(type) {
|
||||
// Create a fake change event to control form toggling
|
||||
var changeEvent = $.Event('change');
|
||||
changeEvent.currentTarget = $('#' + type + '-option');
|
||||
changeEvent.currentTarget = $('.form-toggle[data-type="' + type + '"]');
|
||||
|
||||
// Load form corresponding to the change event
|
||||
view.toggleForm(changeEvent);
|
||||
@@ -133,9 +133,7 @@ define([
|
||||
TemplateHelpers.installTemplate('templates/student_account/form_field');
|
||||
|
||||
// Stub analytics tracking
|
||||
// TODO: use RequireJS to ensure that this is loaded correctly
|
||||
window.analytics = window.analytics || {};
|
||||
window.analytics.track = window.analytics.track || function() {};
|
||||
window.analytics = jasmine.createSpyObj('analytics', ['track', 'page', 'pageview', 'trackLink']);
|
||||
});
|
||||
|
||||
it('can initially display the login form', function() {
|
||||
|
||||
@@ -4,12 +4,14 @@ define([
|
||||
'js/common_helpers/template_helpers',
|
||||
'js/common_helpers/ajax_helpers',
|
||||
'js/student_account/models/LoginModel',
|
||||
'js/student_account/views/LoginView'
|
||||
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView) {
|
||||
'js/student_account/views/LoginView',
|
||||
'js/student_account/models/PasswordResetModel'
|
||||
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView, PasswordResetModel) {
|
||||
'use strict';
|
||||
describe('edx.student.account.LoginView', function() {
|
||||
|
||||
var model = null,
|
||||
resetModel = null,
|
||||
view = null,
|
||||
requests = null,
|
||||
authComplete = false,
|
||||
@@ -79,10 +81,17 @@ define([
|
||||
method: FORM_DESCRIPTION.method
|
||||
});
|
||||
|
||||
// Initialize the passwordReset model
|
||||
resetModel = new PasswordResetModel({}, {
|
||||
method: 'GET',
|
||||
url: '#'
|
||||
});
|
||||
|
||||
// Initialize the login view
|
||||
view = new LoginView({
|
||||
fields: FORM_DESCRIPTION.fields,
|
||||
model: model,
|
||||
resetModel: resetModel,
|
||||
thirdPartyAuth: THIRD_PARTY_AUTH,
|
||||
platformName: PLATFORM_NAME
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ define([
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
setFixtures('<div id="password-reset-wrapper"></div>');
|
||||
setFixtures('<div id="password-reset-form" class="form-wrapper hidden"></div>');
|
||||
TemplateHelpers.installTemplate('templates/student_account/password_reset');
|
||||
TemplateHelpers.installTemplate('templates/student_account/form_field');
|
||||
});
|
||||
@@ -90,6 +90,12 @@ define([
|
||||
|
||||
// Verify that the success message is visible
|
||||
expect($('.js-reset-success')).not.toHaveClass('hidden');
|
||||
|
||||
// Verify that login form has loaded
|
||||
expect($('#login-form')).not.toHaveClass('hidden');
|
||||
|
||||
// Verify that password reset view has been removed
|
||||
expect($( view.el ).html().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('validates the email field', function() {
|
||||
|
||||
@@ -21,7 +21,7 @@ var edx = edx || {};
|
||||
this.urlRoot = options.url;
|
||||
},
|
||||
|
||||
sync: function(method, model) {
|
||||
sync: function( method, model ) {
|
||||
var headers = {
|
||||
'X-CSRFToken': $.cookie('csrftoken')
|
||||
};
|
||||
|
||||
@@ -6,13 +6,21 @@ var edx = edx || {};
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
// Bind to StateChange Event
|
||||
History.Adapter.bind( window, 'statechange', function() {
|
||||
/* Note: We are using History.getState() for legacy browser (IE) support
|
||||
* using History.js plugin instead of the native event.state
|
||||
*/
|
||||
var State = History.getState();
|
||||
});
|
||||
|
||||
edx.student.account.AccessView = Backbone.View.extend({
|
||||
el: '#login-and-registration-container',
|
||||
|
||||
tpl: '#access-tpl',
|
||||
|
||||
events: {
|
||||
'change .form-toggle': 'toggleForm'
|
||||
'click .form-toggle': 'toggleForm'
|
||||
},
|
||||
|
||||
subview: {
|
||||
@@ -37,8 +45,15 @@ var edx = edx || {};
|
||||
currentProvider: null,
|
||||
providers: []
|
||||
};
|
||||
|
||||
this.platformName = obj.platformName;
|
||||
|
||||
// The login view listens for 'sync' events from the reset model
|
||||
this.resetModel = new edx.student.account.PasswordResetModel({}, {
|
||||
method: 'GET',
|
||||
url: '#'
|
||||
});
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
@@ -55,7 +70,6 @@ var edx = edx || {};
|
||||
postRender: function() {
|
||||
// Load the default form
|
||||
this.loadForm( this.activeForm );
|
||||
this.$header = $(this.el).find('.js-login-register-header');
|
||||
},
|
||||
|
||||
loadForm: function( type ) {
|
||||
@@ -72,6 +86,7 @@ var edx = edx || {};
|
||||
context.subview.login = new edx.student.account.LoginView({
|
||||
fields: data.fields,
|
||||
model: model,
|
||||
resetModel: context.resetModel,
|
||||
thirdPartyAuth: context.thirdPartyAuth,
|
||||
platformName: context.platformName
|
||||
});
|
||||
@@ -85,15 +100,16 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
reset: function( data, context ) {
|
||||
var model = new edx.student.account.PasswordResetModel({}, {
|
||||
method: data.method,
|
||||
url: data.submit_url
|
||||
});
|
||||
context.resetModel.ajaxType = data.method;
|
||||
context.resetModel.urlRoot = data.submit_url;
|
||||
|
||||
context.subview.passwordHelp = new edx.student.account.PasswordResetView({
|
||||
fields: data.fields,
|
||||
model: model
|
||||
model: context.resetModel
|
||||
});
|
||||
|
||||
// Listen for 'password-email-sent' event to toggle sub-views
|
||||
context.listenTo( context.subview.passwordHelp, 'password-email-sent', context.passwordEmailSent );
|
||||
},
|
||||
|
||||
register: function( data, context ) {
|
||||
@@ -133,15 +149,20 @@ var edx = edx || {};
|
||||
});
|
||||
},
|
||||
|
||||
passwordEmailSent: function() {
|
||||
this.element.hide( $(this.el).find('#password-reset-anchor') );
|
||||
this.element.show( $('#login-anchor') );
|
||||
this.element.scrollTop( $('#login-anchor') );
|
||||
},
|
||||
|
||||
resetPassword: function() {
|
||||
window.analytics.track('edx.bi.password_reset_form.viewed', {
|
||||
category: 'user-engagement'
|
||||
});
|
||||
|
||||
this.element.hide( this.$header );
|
||||
this.element.hide( $(this.el).find('.form-type') );
|
||||
this.element.hide( $(this.el).find('#login-anchor') );
|
||||
this.loadForm('reset');
|
||||
this.element.scrollTop( $('#password-reset-wrapper') );
|
||||
this.element.scrollTop( $('#password-reset-anchor') );
|
||||
},
|
||||
|
||||
showFormError: function() {
|
||||
@@ -149,10 +170,12 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
toggleForm: function( e ) {
|
||||
var type = $(e.currentTarget).val(),
|
||||
var type = $(e.currentTarget).data('type'),
|
||||
$form = $('#' + type + '-form'),
|
||||
$anchor = $('#' + type + '-anchor');
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
window.analytics.track('edx.bi.' + type + '_form.toggled', {
|
||||
category: 'user-engagement'
|
||||
});
|
||||
@@ -161,9 +184,14 @@ var edx = edx || {};
|
||||
this.loadForm( type );
|
||||
}
|
||||
|
||||
this.element.hide( $(this.el).find('.submission-success') );
|
||||
this.element.hide( $(this.el).find('.form-wrapper') );
|
||||
this.element.show( $form );
|
||||
this.element.scrollTop( $anchor );
|
||||
|
||||
// Update url without reloading page
|
||||
History.pushState( null, document.title, '/account/' + type + '/' );
|
||||
analytics.page( 'login_and_registration', type );
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -291,8 +319,7 @@ var edx = edx || {};
|
||||
*/
|
||||
element: {
|
||||
hide: function( $el ) {
|
||||
$el.addClass('hidden')
|
||||
.attr('aria-hidden', true);
|
||||
$el.addClass('hidden');
|
||||
},
|
||||
|
||||
scrollTop: function( $el ) {
|
||||
@@ -303,8 +330,7 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
show: function( $el ) {
|
||||
$el.removeClass('hidden')
|
||||
.attr('aria-hidden', false);
|
||||
$el.removeClass('hidden');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -98,8 +98,7 @@ var edx = edx || {};
|
||||
element: {
|
||||
hide: function( $el ) {
|
||||
if ( $el ) {
|
||||
$el.addClass('hidden')
|
||||
.attr('aria-hidden', true);
|
||||
$el.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -112,8 +111,7 @@ var edx = edx || {};
|
||||
|
||||
show: function( $el ) {
|
||||
if ( $el ) {
|
||||
$el.removeClass('hidden')
|
||||
.attr('aria-hidden', false);
|
||||
$el.removeClass('hidden');
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -148,7 +146,6 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
|
||||
var obj = {},
|
||||
$form = this.$form,
|
||||
elements = $form[0].elements,
|
||||
@@ -229,6 +226,15 @@ var edx = edx || {};
|
||||
} else {
|
||||
this.toggleErrorMsg( true );
|
||||
}
|
||||
|
||||
this.postFormSubmission();
|
||||
},
|
||||
|
||||
/* Allows extended views to add custom
|
||||
* code after form submission
|
||||
*/
|
||||
postFormSubmission: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
|
||||
@@ -27,8 +27,10 @@ var edx = edx || {};
|
||||
this.providers = data.thirdPartyAuth.providers || [];
|
||||
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
|
||||
this.platformName = data.platformName;
|
||||
this.resetModel = data.resetModel;
|
||||
|
||||
this.listenTo( this.model, 'sync', this.saveSuccess );
|
||||
this.listenTo( this.resetModel, 'sync', this.resetEmail );
|
||||
},
|
||||
|
||||
render: function( html ) {
|
||||
@@ -55,6 +57,7 @@ var edx = edx || {};
|
||||
|
||||
this.$form = this.$container.find('form');
|
||||
this.$errors = this.$container.find('.submission-error');
|
||||
this.$resetSuccess = this.$container.find('.js-reset-success');
|
||||
this.$authError = this.$container.find('.already-authenticated-msg');
|
||||
this.$submitButton = this.$container.find(this.submitButton);
|
||||
|
||||
@@ -71,6 +74,16 @@ var edx = edx || {};
|
||||
event.preventDefault();
|
||||
|
||||
this.trigger('password-help');
|
||||
this.element.hide( this.$resetSuccess );
|
||||
},
|
||||
|
||||
postFormSubmission: function() {
|
||||
this.element.hide( this.$resetSuccess );
|
||||
},
|
||||
|
||||
resetEmail: function() {
|
||||
this.element.hide( this.$errors );
|
||||
this.element.show( this.$resetSuccess );
|
||||
},
|
||||
|
||||
thirdPartyAuth: function( event ) {
|
||||
@@ -81,13 +94,15 @@ var edx = edx || {};
|
||||
}
|
||||
},
|
||||
|
||||
saveSuccess: function () {
|
||||
saveSuccess: function() {
|
||||
this.trigger('auth-complete');
|
||||
this.element.hide( this.$resetSuccess );
|
||||
},
|
||||
|
||||
saveError: function( error ) {
|
||||
this.errors = ['<li>' + error.responseText + '</li>'];
|
||||
this.setErrors();
|
||||
this.element.hide( this.$resetSuccess );
|
||||
|
||||
/* If we've gotten a 403 error, it means that we've successfully
|
||||
* authenticated with a third-party provider, but we haven't
|
||||
|
||||
@@ -7,7 +7,7 @@ var edx = edx || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.PasswordResetView = edx.student.account.FormView.extend({
|
||||
el: '#password-reset-wrapper',
|
||||
el: '#password-reset-form',
|
||||
|
||||
tpl: '#password_reset-tpl',
|
||||
|
||||
@@ -22,6 +22,8 @@ var edx = edx || {};
|
||||
submitButton: '.js-reset',
|
||||
|
||||
preRender: function() {
|
||||
this.element.show( $( this.el ) );
|
||||
this.element.show( $( this.el ).parent() );
|
||||
this.listenTo( this.model, 'sync', this.saveSuccess );
|
||||
},
|
||||
|
||||
@@ -35,12 +37,11 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
saveSuccess: function() {
|
||||
var $el = $(this.el),
|
||||
$msg = $el.find('.js-reset-success');
|
||||
this.trigger('password-email-sent');
|
||||
|
||||
this.element.hide( $el.find('#password-reset-form') );
|
||||
this.element.show( $msg );
|
||||
this.element.scrollTop( $msg );
|
||||
// Destroy the view (but not el) and unbind events
|
||||
this.$el.empty().off();
|
||||
this.stopListening();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
2
lms/static/js/vendor/history.js
vendored
Normal file
2
lms/static/js/vendor/history.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -3,7 +3,6 @@
|
||||
// }
|
||||
|
||||
html, body {
|
||||
background: $body-bg;
|
||||
font-family: $sans-serif;
|
||||
font-size: 1em;
|
||||
font-style: normal;
|
||||
@@ -11,6 +10,14 @@ html, body {
|
||||
//-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
html{
|
||||
background: white;
|
||||
}
|
||||
|
||||
body {
|
||||
background: $body-bg;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
color: $base-font-color;
|
||||
font: normal 1.2em/1.2em $serif;
|
||||
|
||||
@@ -68,18 +68,18 @@ $white-t1: rgba($white, 0.25);
|
||||
$white-t2: rgba($white, 0.5);
|
||||
$white-t3: rgba($white, 0.75);
|
||||
|
||||
$gray: rgb(127,127,127);
|
||||
$gray-l1: tint($gray,20%);
|
||||
$gray-l2: tint($gray,40%);
|
||||
$gray-l3: tint($gray,60%); // #cbcbcb;
|
||||
$gray-l4: tint($gray,80%); // #e5e5e5;
|
||||
$gray-l5: tint($gray,90%); // #f2f2f2;
|
||||
$gray-l6: tint($gray,95%); // #f8f8f8;
|
||||
$gray-l7: tint($gray,99%);
|
||||
$gray-d1: shade($gray,20%);
|
||||
$gray-d2: shade($gray,40%);
|
||||
$gray-d3: shade($gray,60%);
|
||||
$gray-d4: shade($gray,80%);
|
||||
$gray: rgb(127,127,127); // #7f7f7f
|
||||
$gray-l1: tint($gray,20%); // #989898
|
||||
$gray-l2: tint($gray,40%); // #b2b2b2
|
||||
$gray-l3: tint($gray,60%); // #cbcbcb
|
||||
$gray-l4: tint($gray,80%); // #e5e5e5
|
||||
$gray-l5: tint($gray,90%); // #f2f2f2
|
||||
$gray-l6: tint($gray,95%); // #f8f8f8
|
||||
$gray-l7: tint($gray,99%); // #fdfdfd
|
||||
$gray-d1: shade($gray,20%); // #656565
|
||||
$gray-d2: shade($gray,40%); // #4c4c4c
|
||||
$gray-d3: shade($gray,60%); // #323232
|
||||
$gray-d4: shade($gray,80%); // #191919
|
||||
|
||||
$pink: rgb(182,37,103);
|
||||
$pink-l1: tint($pink,20%);
|
||||
@@ -175,11 +175,13 @@ $m-blue-l2: #42B5E9;
|
||||
$m-blue-l3: #59BEEC;
|
||||
$m-blue-l4: tint($m-blue,90%);
|
||||
$m-blue-l5: tint($m-blue,95%);
|
||||
$m-blue-l6: #4bb4fb;
|
||||
$m-blue-d1: #1790C7;
|
||||
$m-blue-d2: #1580B0;
|
||||
$m-blue-d3: #126F9A;
|
||||
$m-blue-d4: #0A4A67;
|
||||
$m-blue-d5: #009EE7;
|
||||
$m-blue-d6: #256A97;
|
||||
$m-blue-t0: rgba($m-blue,0.125);
|
||||
$m-blue-t1: rgba($m-blue,0.25);
|
||||
$m-blue-t2: rgba($m-blue,0.50);
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
line-height: lh(1);
|
||||
}
|
||||
|
||||
$sm-btn-google: #dd4b39;
|
||||
$sm-btn-facebook: #3b5998;
|
||||
$sm-btn-linkedin: #0077b5;
|
||||
|
||||
.section-bkg-wrapper {
|
||||
background: $m-gray-l4;
|
||||
}
|
||||
@@ -27,7 +31,7 @@
|
||||
@include outer-container;
|
||||
$grid-columns: 12;
|
||||
background: white;
|
||||
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
|
||||
h2 {
|
||||
@@ -81,18 +85,74 @@
|
||||
}
|
||||
}
|
||||
|
||||
.form-toggle {
|
||||
margin: 0;
|
||||
form {
|
||||
border: 1px solid $gray-l4;
|
||||
border-radius: 5px;
|
||||
padding: 0 25px;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
position: relative;
|
||||
height: 16px;
|
||||
margin: 20px 0 10px;
|
||||
|
||||
&.lines {
|
||||
margin-bottom: 20px;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: $gray-l4;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 12px;
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
background: white;
|
||||
padding: 0 10px;
|
||||
z-index: 10;
|
||||
text-transform: none;
|
||||
font-size: 0.7em;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
margin: 0 28px;
|
||||
padding: 7px 0;
|
||||
width: calc( 100% - 56px );
|
||||
border: 3px solid $m-blue-d5;
|
||||
border-radius: 5px;
|
||||
color: $m-blue-d5;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
text-transform: none;
|
||||
background: white;
|
||||
|
||||
&:hover {
|
||||
background: white;
|
||||
border-color: $m-blue-d6;
|
||||
color: $m-blue-d6;
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-type {
|
||||
@include box-sizing(border-box);
|
||||
@include span-columns(12);
|
||||
padding: 25px 10px;
|
||||
|
||||
&:nth-of-type(2) {
|
||||
border-bottom: 1px solid $gray-l4;
|
||||
}
|
||||
width: 330px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.note {
|
||||
@@ -100,7 +160,9 @@
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
color: $gray;
|
||||
margin-top: 15px;
|
||||
margin: 10px;
|
||||
color: $m-gray-l1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +180,10 @@
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.password-reset-form {
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
|
||||
%bold-label {
|
||||
@include font-size(16);
|
||||
font-family: $sans-serif;
|
||||
@@ -133,8 +199,11 @@
|
||||
}
|
||||
|
||||
.action-label {
|
||||
@extend %bold-label;
|
||||
margin-bottom: 20px;
|
||||
@include font-size(13);
|
||||
font-family: $sans-serif;
|
||||
font-weight: regular;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
@@ -142,7 +211,18 @@
|
||||
clear: both;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0 0 $baseline 0;
|
||||
margin: 0 0 5px 0;
|
||||
|
||||
&.select-gender {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
&.select-gender,
|
||||
&.select-year_of_birth {
|
||||
width: calc( 50% - 10px );
|
||||
float: left;
|
||||
clear: none;
|
||||
}
|
||||
|
||||
/** FROM _accounts.scss - start **/
|
||||
label,
|
||||
@@ -153,12 +233,14 @@
|
||||
font-family: $sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.5em;
|
||||
color: $base-font-color;
|
||||
}
|
||||
|
||||
label {
|
||||
@include transition(color 0.15s ease-in-out 0s);
|
||||
margin: 0 0 ($baseline/4) 0;
|
||||
margin: 0 0 6px 0;
|
||||
color: tint($black, 20%);
|
||||
font-weight: $font-semibold;
|
||||
|
||||
@@ -170,14 +252,23 @@
|
||||
color: $red;
|
||||
}
|
||||
|
||||
&[for="register-honor_code"] {
|
||||
display: block;
|
||||
margin: -30px 5% 15px;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
font-family: $sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
.field-link {
|
||||
position: relative;
|
||||
color: $link-color-d1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
color: $m-blue-d5;
|
||||
font-weight: $font-regular;
|
||||
text-decoration: none !important; // needed but nasty
|
||||
font-family: $sans-serif;
|
||||
@@ -189,8 +280,8 @@
|
||||
textarea {
|
||||
display: block;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: ($baseline/2) ($baseline*.75);
|
||||
margin: 0 0 5px;
|
||||
padding: 0 ($baseline/2);
|
||||
|
||||
&.long {
|
||||
width: 100%;
|
||||
@@ -211,8 +302,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
textarea.long {
|
||||
height: ($baseline*5);
|
||||
input {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: none;
|
||||
|
||||
&.long {
|
||||
height: ($baseline*5);
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
@@ -242,56 +341,122 @@
|
||||
}
|
||||
|
||||
.action-primary {
|
||||
@extend %m-btn-primary;
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
text-transform: none;
|
||||
color: white;
|
||||
background: $m-blue-d5;
|
||||
border: 3px solid $m-blue-d6;
|
||||
border-radius: 5px;
|
||||
box-shadow: none;
|
||||
font-weight: 600;
|
||||
text-shadow: none;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background: $m-blue-l6;
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.login-provider {
|
||||
@extend %btn-secondary-blue-outline;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
@extend %btn-secondary-grey-outline;
|
||||
width: 130px;
|
||||
padding: 0 0 0 40px;
|
||||
height: 34px;
|
||||
text-align: left;
|
||||
text-shadow: none;
|
||||
text-transform: none;
|
||||
position: relative;
|
||||
font-size: 0.8em;
|
||||
border-color: $lightGrey1;
|
||||
|
||||
&:nth-of-type(odd) {
|
||||
margin-right: 13px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: inherit;
|
||||
margin-right: $baseline/2;
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: 0;
|
||||
width: 30px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.icon {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
&.button-Google:hover,
|
||||
&.button-Google:focus {
|
||||
background-color: #dd4b39;
|
||||
border: 1px solid #A5382B;
|
||||
&.button-Google {
|
||||
color: $sm-btn-google;
|
||||
|
||||
.icon {
|
||||
background: $sm-btn-google;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $sm-btn-google;
|
||||
border: 1px solid #A5382B;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 1px 0 #8D3024;
|
||||
}
|
||||
}
|
||||
|
||||
&.button-Google:hover {
|
||||
box-shadow: 0 2px 1px 0 #8D3024;
|
||||
&.button-Facebook {
|
||||
color: $sm-btn-facebook;
|
||||
|
||||
.icon {
|
||||
background: $sm-btn-facebook;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $sm-btn-facebook;
|
||||
border: 1px solid #263A62;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 1px 0 #30487C;
|
||||
}
|
||||
}
|
||||
|
||||
&.button-Facebook:hover,
|
||||
&.button-Facebook:focus {
|
||||
background-color: #3b5998;
|
||||
border: 1px solid #263A62;
|
||||
}
|
||||
&.button-LinkedIn {
|
||||
color: $sm-btn-linkedin;
|
||||
|
||||
&.button-Facebook:hover {
|
||||
box-shadow: 0 2px 1px 0 #30487C;
|
||||
}
|
||||
.icon {
|
||||
background: $sm-btn-linkedin;
|
||||
}
|
||||
|
||||
&.button-LinkedIn:hover,
|
||||
&.button-LinkedIn:focus {
|
||||
background-color: #0077b5;
|
||||
border: 1px solid #06527D;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: $sm-btn-linkedin;
|
||||
border: 1px solid #06527D;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&.button-LinkedIn:hover {
|
||||
box-shadow: 0 2px 1px 0 #005D8E;
|
||||
&:hover {
|
||||
box-shadow: 0 2px 1px 0 #005D8E;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -299,9 +464,9 @@
|
||||
/** Error Container - from _account.scss **/
|
||||
.status {
|
||||
@include box-sizing(border-box);
|
||||
margin: 0 0 $baseline 0;
|
||||
margin: 0 0 25px 0;
|
||||
border-bottom: 3px solid shade($yellow, 10%);
|
||||
padding: $baseline $baseline;
|
||||
padding: 25px;
|
||||
background: tint($yellow,20%);
|
||||
|
||||
.message-title {
|
||||
@@ -312,15 +477,15 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.message-copy {
|
||||
.message-copy,
|
||||
.message-copy p {
|
||||
@extend %body-text;
|
||||
font-family: $sans-serif;
|
||||
margin: 0 !important;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin: 0 0 ($baseline/4) 0;
|
||||
margin: 0 0 ($baseline/4) $baseline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -353,100 +518,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
/** RWD **/
|
||||
@include media( $tablet ) {
|
||||
$grid-columns: 8;
|
||||
|
||||
%inline-form-field-tablet {
|
||||
clear: none;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header .headline,
|
||||
.header .tagline,
|
||||
@include media( max-width 330px) {
|
||||
.form-type {
|
||||
@include span-columns(6);
|
||||
@include shift(1);
|
||||
}
|
||||
|
||||
.form-toggle {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
&.select-gender {
|
||||
@extend %inline-form-field-tablet;
|
||||
width: calc( 50% - 10px );
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
&.select-year_of_birth {
|
||||
@extend %inline-form-field-tablet;
|
||||
width: calc( 50% - 10px );
|
||||
}
|
||||
|
||||
.field-link {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media( $desktop ) {
|
||||
$grid-columns: 12;
|
||||
|
||||
%inline-form-field-desktop {
|
||||
clear: none;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.header .headline,
|
||||
.header .tagline,
|
||||
.form-type {
|
||||
width: 600px;
|
||||
margin-left: calc( 50% - 300px );
|
||||
margin-right: calc( 50% - 300px );
|
||||
}
|
||||
|
||||
.form-toggle {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
&.select-level_of_education {
|
||||
@extend %inline-form-field-desktop;
|
||||
width: 300px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
&.select-gender {
|
||||
@extend %inline-form-field-desktop;
|
||||
width: 60px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
&.select-year_of_birth {
|
||||
@extend %inline-form-field-desktop;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.field-link {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
width: 98%;
|
||||
margin: 0 1%;
|
||||
}
|
||||
|
||||
.login-provider {
|
||||
@include span-columns(6);
|
||||
|
||||
/* Node uses last-child which is not specific enough */
|
||||
&:nth-of-type(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
header_extra_file = 'theme-head-extra.html'
|
||||
header_file = 'theme-header.html'
|
||||
google_analytics_file = 'theme-google-analytics.html'
|
||||
footer_file = 'theme-footer.html'
|
||||
|
||||
style_overrides_file = None
|
||||
|
||||
@@ -111,12 +110,6 @@
|
||||
|
||||
google_analytics_file = microsite.get_template_path('google_analytics.html')
|
||||
|
||||
if settings.FEATURES['IS_EDX_DOMAIN'] and not is_microsite():
|
||||
footer_file = microsite.get_template_path('footer-edx-new.html')
|
||||
|
||||
else:
|
||||
footer_file = microsite.get_template_path('footer.html')
|
||||
|
||||
style_overrides_file = microsite.get_value('css_overrides_file')
|
||||
%>
|
||||
|
||||
@@ -136,7 +129,6 @@
|
||||
|
||||
<%include file="${google_analytics_file}" />
|
||||
|
||||
|
||||
% if style_overrides_file:
|
||||
<link rel="stylesheet" type="text/css" href="${static.url(style_overrides_file)}" />
|
||||
% endif
|
||||
@@ -149,18 +141,25 @@
|
||||
|
||||
<%include file="mathjax_accessible.html" />
|
||||
|
||||
% if not suppress_toplevel_navigation:
|
||||
<%include file="${header_file}" />
|
||||
%endif
|
||||
|
||||
<div class="content-wrapper" id="content">
|
||||
${self.body()}
|
||||
<%block name="bodyextra"/>
|
||||
</div>
|
||||
|
||||
% if not suppress_toplevel_navigation:
|
||||
<%include file="${footer_file}" />
|
||||
% endif
|
||||
<%block name="footer">
|
||||
## Can be overridden by child templates wanting to hide the footer.
|
||||
<%
|
||||
if theme_enabled() and not is_microsite():
|
||||
footer_file = 'theme-footer.html'
|
||||
elif settings.FEATURES['IS_EDX_DOMAIN'] and not is_microsite():
|
||||
footer_file = microsite.get_template_path('footer-edx-new.html')
|
||||
else:
|
||||
footer_file = microsite.get_template_path('footer.html')
|
||||
%>
|
||||
<%include file="${footer_file}" />
|
||||
</%block>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ site_status_msg = get_site_status_msg(course_id)
|
||||
<li><a href="${marketing_link('FAQ')}">${_("Help")}</a></li>
|
||||
% endif
|
||||
</%block>
|
||||
<li><a href="${reverse('logout')}" role="menuitem">${_("Log Out")}</a></li>
|
||||
<li><a href="${reverse('logout')}" role="menuitem">${_("Sign out")}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -126,9 +126,9 @@ site_status_msg = get_site_status_msg(course_id)
|
||||
<div class="nav-courseware-02">
|
||||
% if not settings.FEATURES['DISABLE_LOGIN_BUTTON']:
|
||||
% if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain:
|
||||
<a class="cta cta-login nav-courseware-button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Log in")}</a>
|
||||
<a class="cta cta-login nav-courseware-button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
|
||||
% else:
|
||||
<a class="cta cta-login nav-courseware-button" href="/login${login_query()}">${_("Log in")}</a>
|
||||
<a class="cta cta-login nav-courseware-button" href="/login${login_query()}">${_("Sign in")}</a>
|
||||
% endif
|
||||
% endif
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ site_status_msg = get_site_status_msg(course_id)
|
||||
<li><a href="${marketing_link('FAQ')}">${_("Help")}</a></li>
|
||||
% endif
|
||||
</%block>
|
||||
<li><a href="${reverse('logout')}" role="menuitem">${_("Log Out")}</a></li>
|
||||
<li><a href="${reverse('logout')}" role="menuitem">${_("Sign out")}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
@@ -120,9 +120,9 @@ site_status_msg = get_site_status_msg(course_id)
|
||||
<li class="nav-courseware-01">
|
||||
% if not settings.FEATURES['DISABLE_LOGIN_BUTTON']:
|
||||
% if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain:
|
||||
<a class="cta cta-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Log in")}</a>
|
||||
<a class="cta cta-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
|
||||
% else:
|
||||
<a class="cta cta-login" href="/login${login_query()}">${_("Log in")}</a>
|
||||
<a class="cta cta-login" href="/login${login_query()}">${_("Sign in")}</a>
|
||||
% endif
|
||||
% endif
|
||||
</li>
|
||||
|
||||
@@ -1,40 +1,17 @@
|
||||
<header class="js-login-register-header header">
|
||||
<h1 class="headline"><%- gettext("Welcome!") %></h1>
|
||||
<p class="tagline"><%- gettext("Log in or register to take courses from the world's best universities.") %></p>
|
||||
</header>
|
||||
|
||||
<section id="form-load-fail" class="form-type hidden" aria-hidden="true">
|
||||
<section id="form-load-fail" class="form-type hidden">
|
||||
<div class="status submission-error">
|
||||
<p class="message-copy"><%- gettext("Sorry, we're having some technical problems. Wait a few minutes and try again.") %></p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<% if ( mode === 'login' ) { %>
|
||||
<section id="register-anchor" class="form-type">
|
||||
<span>
|
||||
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
|
||||
<label for="register-option" class="form-label"><%- gettext("I am a new user") %></label>
|
||||
</span>
|
||||
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden" aria-hidden="true<% } %>"></div>
|
||||
</section>
|
||||
<% } %>
|
||||
|
||||
<section id="login-anchor" class="form-type">
|
||||
<span>
|
||||
<input type="radio" name="form" id="login-option" value="login" class="form-toggle" <% if ( mode === 'login' ) { %>checked<% } %>>
|
||||
<label for="login-option" class="form-label"><%- gettext("I am a returning user") %></label>
|
||||
</span>
|
||||
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden" aria-hidden="true<% } %>"></div>
|
||||
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden<% } %>"></div>
|
||||
</section>
|
||||
|
||||
<% if ( mode === 'register' ) { %>
|
||||
<section id="register-anchor" class="form-type">
|
||||
<span>
|
||||
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
|
||||
<label for="register-option" class="form-label"><%- gettext("I am a new user") %></label>
|
||||
</span>
|
||||
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden" aria-hidden="true<% } %>"></div>
|
||||
</section>
|
||||
<% } %>
|
||||
<section id="register-anchor" class="form-type">
|
||||
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden<% } %>"></div>
|
||||
</section>
|
||||
|
||||
<div id="password-reset-wrapper"></div>
|
||||
<section id="password-reset-anchor" class="form-type">
|
||||
<div id="password-reset-form" class="form-wrapper hidden" aria-hidden="true"></div>
|
||||
</section>
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
name="<%= name %>"
|
||||
class="input-inline"
|
||||
aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( typeof errorMessages !== 'undefined' ) {
|
||||
_.each(errorMessages, function( msg, type ) {%>
|
||||
data-errormsg-<%= type %>="<%= msg %>"
|
||||
<% });
|
||||
} %>
|
||||
<% if ( required ) { %> aria-required="true" required<% } %>>
|
||||
<% _.each(options, function(el) { %>
|
||||
<option value="<%= el.value%>"<% if ( el.default ) { %> data-isdefault="true"<% } %>><%= el.name %></option>
|
||||
@@ -49,7 +54,7 @@
|
||||
<% } %>
|
||||
|
||||
<% if ( type === 'checkbox' ) { %>
|
||||
<label for="<%= form %>-<%= name %>" class="inline">
|
||||
<label for="<%= form %>-<%= name %>">
|
||||
<%= label %>
|
||||
<% if ( required && requiredStr ) { %> <%= requiredStr %><% } %>
|
||||
</label>
|
||||
@@ -58,6 +63,4 @@
|
||||
<% if( form === 'login' && name === 'password' ) { %>
|
||||
<a href="#" class="forgot-password field-link"><%- gettext("Forgot password?") %></a>
|
||||
<% } %>
|
||||
|
||||
<span id="<%= form %>-<%= name %>-desc" class="desc"><%= instructions %></span>
|
||||
</p>
|
||||
|
||||
@@ -1,27 +1,60 @@
|
||||
<form id="login" class="login-form">
|
||||
<div class="status already-authenticated-msg hidden" aria-hidden="true">
|
||||
<% if (context.currentProvider) { %>
|
||||
<p class="message-copy">
|
||||
<%- _.sprintf(gettext("You've successfully logged into %(currentProvider)s, but your %(currentProvider)s account isn't linked with an %(platformName)s account. To link your accounts, go to your %(platformName)s dashboard."), context) %>
|
||||
</p>
|
||||
<% } %>
|
||||
</div>
|
||||
<div class="status already-authenticated-msg hidden">
|
||||
<% if (context.currentProvider) { %>
|
||||
<p class="message-copy">
|
||||
<%- _.sprintf( gettext("You've successfully signed into %(currentProvider)s, but your %(currentProvider)s account isn't linked with an %(platformName)s account. To link your accounts, go to your %(platformName)s dashboard."), context ) %>
|
||||
</p>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("We couldn't log you in.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
<div class="js-reset-success status submission-success hidden">
|
||||
<h4 class="message-title"><%- gettext("Password Reset Email Sent") %></h4>
|
||||
<div class="message-copy">
|
||||
<p>
|
||||
<%- gettext("We've sent instructions for resetting your password to the email address you provided.") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="status submission-error hidden" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("We couldn't sign you in.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
</div>
|
||||
|
||||
<form id="login" class="login-form">
|
||||
|
||||
<div class="section-title lines">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("Sign in") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<%= context.fields %>
|
||||
|
||||
<button class="action action-primary action-update js-login login-button"><%- gettext("Log in") %></button>
|
||||
<button class="action action-primary action-update js-login login-button"><%- gettext("Sign in") %></button>
|
||||
|
||||
<div class="login-providers">
|
||||
<div class="section-title lines">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("or sign in with") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<% _.each( context.providers, function( provider ) {
|
||||
if ( provider.loginUrl ) { %>
|
||||
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider login-<%- provider.name %>" data-provider-url="<%- provider.loginUrl %>">
|
||||
<div class="icon <%- provider.iconClass %>" aria-hidden="true"></div>
|
||||
<%- provider.name %>
|
||||
</button>
|
||||
<% }
|
||||
}); %>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<% _.each( context.providers, function( provider ) {
|
||||
if ( provider.loginUrl ) { %>
|
||||
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider login-<%- provider.name %>" data-provider-url="<%- provider.loginUrl %>">
|
||||
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
|
||||
<%- _.sprintf(gettext("Log in using %(name)s"), provider) %>
|
||||
</button>
|
||||
<% }
|
||||
}); %>
|
||||
<div class="toggle-form">
|
||||
<div class="section-title">
|
||||
<h2>
|
||||
<span class="text"><%- _.sprintf( gettext("New to %(platformName)s?"), context ) %></span>
|
||||
</h2>
|
||||
</div>
|
||||
<button class="nav-btn form-toggle" data-type="register"><%- gettext("Create an account") %></button>
|
||||
</div>
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
|
||||
<%inherit file="../main.html" />
|
||||
|
||||
<%block name="pagetitle">${_("Log in or Register")}</%block>
|
||||
<%block name="pagetitle">${_("Sign in or Register")}</%block>
|
||||
|
||||
<%block name="js_extra">
|
||||
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
|
||||
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
|
||||
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
|
||||
<script src="${static.url('js/vendor/url.min.js')}"></script>
|
||||
<script src="${static.url('js/vendor/history.js')}"></script>
|
||||
<%static:js group='student_account'/>
|
||||
</%block>
|
||||
|
||||
@@ -29,3 +30,10 @@
|
||||
data-platform-name='${platform_name}'
|
||||
/>
|
||||
</div>
|
||||
|
||||
% if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
|
||||
## This overwrites the "footer" block declared in main.html
|
||||
## with an empty block, effectively hiding the footer
|
||||
## from logistration pages.
|
||||
<%block name="footer"/>
|
||||
% endif
|
||||
|
||||
@@ -1,28 +1,19 @@
|
||||
<header class="header">
|
||||
<h1 class="headline"><%- gettext("Reset Password") %></h1>
|
||||
</header>
|
||||
<div class="status submission-error hidden" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("An error occurred.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
</div>
|
||||
|
||||
<section class="form-type">
|
||||
<div id="password-reset-form" class="form-wrapper">
|
||||
<p class="action-label"><%- gettext("Enter the email address you used to create your account. We'll send you a link you can use to reset your password.") %></p>
|
||||
<form id="password-reset-form">
|
||||
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("An error occurred.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
</div>
|
||||
<form id="password-reset" class="password-reset-form">
|
||||
|
||||
<%= fields %>
|
||||
|
||||
<button class="action action-primary action-update js-reset"><%- gettext("Reset password") %></button>
|
||||
</form>
|
||||
<div class="section-title lines">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("Password assistance") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="js-reset-success status submission-success hidden" aria-hidden="true">
|
||||
<h4 class="message-title"><%- gettext("Password Reset Email Sent") %></h4>
|
||||
<div class="message-copy">
|
||||
<p>
|
||||
<%- gettext("We've sent instructions for resetting your password to the email address you provided.") %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<p class="action-label"><%- gettext("Please enter your email address below and we will send you instructions for setting a new password.") %></p>
|
||||
|
||||
<%= fields %>
|
||||
|
||||
<button class="action action-primary action-update js-reset"><%- gettext("Reset my password") %></button>
|
||||
</form>
|
||||
|
||||
@@ -1,29 +1,52 @@
|
||||
<% if (context.currentProvider) { %>
|
||||
<div class="status" aria-hidden="false">
|
||||
<p class="message-copy">
|
||||
<%- _.sprintf(gettext("You've successfully logged into %(currentProvider)s."), context) %>
|
||||
<%- _.sprintf(gettext("We just need a little more information before you start learning with %(platformName)s."), context) %>
|
||||
</p>
|
||||
</div>
|
||||
<% } else {
|
||||
_.each( context.providers, function( provider) {
|
||||
if ( provider.registerUrl ) { %>
|
||||
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider register-<%- provider.name %>" data-provider-url="<%- provider.registerUrl %>">
|
||||
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
|
||||
<%- _.sprintf(gettext("Register using %(name)s"), provider) %>
|
||||
</button>
|
||||
<% }
|
||||
});
|
||||
} %>
|
||||
<div class="status submission-error hidden" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("We couldn't create your account.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
</div>
|
||||
|
||||
<form id="register" autocomplete="off">
|
||||
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
|
||||
<h4 class="message-title"><%- gettext("We couldn't complete your registration.") %></h4>
|
||||
<ul class="message-copy"></ul>
|
||||
<% if (context.currentProvider) { %>
|
||||
<div class="status" aria-hidden="false">
|
||||
<p class="message-copy">
|
||||
<%- _.sprintf( gettext("You've successfully signed into %(currentProvider)s."), context ) %>
|
||||
<%- _.sprintf( gettext("We just need a little more information before you start learning with %(platformName)s."), context ) %>
|
||||
</p>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<div class="login-providers">
|
||||
<div class="section-title lines">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("Create an account using") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
<%
|
||||
_.each( context.providers, function( provider) {
|
||||
if ( provider.registerUrl ) { %>
|
||||
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider register-<%- provider.name %>" data-provider-url="<%- provider.registerUrl %>">
|
||||
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
|
||||
<%- provider.name %>
|
||||
</button>
|
||||
<% }
|
||||
}); %>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<div class="section-title lines">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("or create a new one here") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<%= context.fields %>
|
||||
|
||||
<button class="action action-primary action-update js-register register-button"><%- gettext("Register") %></button>
|
||||
<button class="action action-primary action-update js-register register-button"><%- gettext("Create your account") %></button>
|
||||
<p class="note">* <%- gettext("Required field") %></p>
|
||||
</form>
|
||||
|
||||
<div class="toggle-form">
|
||||
<div class="section-title">
|
||||
<h2>
|
||||
<span class="text"><%- gettext("Already have an account?") %></span>
|
||||
</h2>
|
||||
</div>
|
||||
<button class="nav-btn form-toggle" data-type="login"><%- gettext("Sign in") %></button>
|
||||
</div>
|
||||
|
||||
@@ -633,17 +633,6 @@ class LoginSessionViewTest(ApiTestCase):
|
||||
"max_length": account_api.PASSWORD_MAX_LENGTH
|
||||
},
|
||||
"errorMessages": {},
|
||||
},
|
||||
{
|
||||
"name": "remember",
|
||||
"defaultValue": False,
|
||||
"type": "checkbox",
|
||||
"required": False,
|
||||
"label": "Remember me",
|
||||
"placeholder": "",
|
||||
"instructions": "",
|
||||
"restrictions": {},
|
||||
"errorMessages": {},
|
||||
}
|
||||
])
|
||||
|
||||
@@ -847,7 +836,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
u"name": u"name",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Full Name",
|
||||
u"label": u"Full name",
|
||||
u"instructions": u"The name that will appear on your certificates",
|
||||
u"restrictions": {
|
||||
"max_length": profile_api.FULL_NAME_MAX_LENGTH,
|
||||
@@ -861,7 +850,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
u"name": u"username",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Username",
|
||||
u"label": u"Public username",
|
||||
u"instructions": u"The name that will identify you in your courses",
|
||||
u"restrictions": {
|
||||
"min_length": account_api.USERNAME_MIN_LENGTH,
|
||||
@@ -927,7 +916,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
u"defaultValue": u"Bob",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Full Name",
|
||||
u"label": u"Full name",
|
||||
u"instructions": u"The name that will appear on your certificates",
|
||||
u"restrictions": {
|
||||
"max_length": profile_api.FULL_NAME_MAX_LENGTH
|
||||
@@ -943,7 +932,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
u"defaultValue": u"Bob123",
|
||||
u"type": u"text",
|
||||
u"required": True,
|
||||
u"label": u"Username",
|
||||
u"label": u"Public username",
|
||||
u"placeholder": u"",
|
||||
u"instructions": u"The name that will identify you in your courses",
|
||||
u"restrictions": {
|
||||
@@ -960,7 +949,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"name": "level_of_education",
|
||||
"type": "select",
|
||||
"required": False,
|
||||
"label": "Highest Level of Education Completed",
|
||||
"label": "Highest level of education completed",
|
||||
"options": [
|
||||
{"value": "", "name": "--", "default": True},
|
||||
{"value": "p", "name": "Doctorate"},
|
||||
@@ -1007,7 +996,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"name": "year_of_birth",
|
||||
"type": "select",
|
||||
"required": False,
|
||||
"label": "Year of Birth",
|
||||
"label": "Year of birth",
|
||||
"options": year_options,
|
||||
}
|
||||
)
|
||||
@@ -1019,7 +1008,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"name": "mailing_address",
|
||||
"type": "textarea",
|
||||
"required": False,
|
||||
"label": "Mailing Address",
|
||||
"label": "Mailing address",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1030,7 +1019,7 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"name": "goals",
|
||||
"type": "textarea",
|
||||
"required": False,
|
||||
"label": "If you'd like, tell us why you're interested in {platform_name}".format(
|
||||
"label": "Tell us why you're interested in {platform_name}".format(
|
||||
platform_name=settings.PLATFORM_NAME
|
||||
)
|
||||
}
|
||||
@@ -1063,6 +1052,9 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"type": "select",
|
||||
"required": True,
|
||||
"options": country_options,
|
||||
"errorMessages": {
|
||||
"required": "Please select your Country."
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1222,9 +1214,9 @@ class RegistrationViewTest(ApiTestCase):
|
||||
"password",
|
||||
"city",
|
||||
"country",
|
||||
"level_of_education",
|
||||
"gender",
|
||||
"year_of_birth",
|
||||
"level_of_education",
|
||||
"mailing_address",
|
||||
"goals",
|
||||
"honor_code",
|
||||
|
||||
@@ -112,19 +112,6 @@ class LoginSessionView(APIView):
|
||||
}
|
||||
)
|
||||
|
||||
# Translators: This phrase appears next to a checkbox on the login form
|
||||
# which the user can check in order to remain logged in after their
|
||||
# session ends.
|
||||
remember_label = _(u"Remember me")
|
||||
|
||||
form_desc.add_field(
|
||||
"remember",
|
||||
field_type="checkbox",
|
||||
label=remember_label,
|
||||
default=False,
|
||||
required=False,
|
||||
)
|
||||
|
||||
return HttpResponse(form_desc.to_json(), content_type="application/json")
|
||||
|
||||
@method_decorator(require_post_params(["email", "password"]))
|
||||
@@ -171,9 +158,15 @@ class RegistrationView(APIView):
|
||||
DEFAULT_FIELDS = ["email", "name", "username", "password"]
|
||||
|
||||
EXTRA_FIELDS = [
|
||||
"city", "country", "level_of_education", "gender",
|
||||
"year_of_birth", "mailing_address", "goals",
|
||||
"honor_code", "terms_of_service",
|
||||
"city",
|
||||
"country",
|
||||
"gender",
|
||||
"year_of_birth",
|
||||
"level_of_education",
|
||||
"mailing_address",
|
||||
"goals",
|
||||
"honor_code",
|
||||
"terms_of_service",
|
||||
]
|
||||
|
||||
# This end-point is available to anonymous users,
|
||||
@@ -348,7 +341,7 @@ class RegistrationView(APIView):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's full name.
|
||||
name_label = _(u"Full Name")
|
||||
name_label = _(u"Full name")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's full name.
|
||||
@@ -376,7 +369,7 @@ class RegistrationView(APIView):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's public username.
|
||||
username_label = _(u"Username")
|
||||
username_label = _(u"Public username")
|
||||
|
||||
# Translators: These instructions appear on the registration form, immediately
|
||||
# below a field meant to hold the user's public username.
|
||||
@@ -432,7 +425,7 @@ class RegistrationView(APIView):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the user's highest completed level of education.
|
||||
education_level_label = _(u"Highest Level of Education Completed")
|
||||
education_level_label = _(u"Highest level of education completed")
|
||||
|
||||
form_desc.add_field(
|
||||
"level_of_education",
|
||||
@@ -478,7 +471,7 @@ class RegistrationView(APIView):
|
||||
"""
|
||||
# Translators: This label appears above a dropdown menu on the registration
|
||||
# form used to select the user's year of birth.
|
||||
yob_label = _(u"Year of Birth")
|
||||
yob_label = _(u"Year of birth")
|
||||
|
||||
options = [(unicode(year), unicode(year)) for year in UserProfile.VALID_YEARS]
|
||||
form_desc.add_field(
|
||||
@@ -502,7 +495,7 @@ class RegistrationView(APIView):
|
||||
"""
|
||||
# Translators: This label appears above a field on the registration form
|
||||
# meant to hold the user's mailing address.
|
||||
mailing_address_label = _(u"Mailing Address")
|
||||
mailing_address_label = _(u"Mailing address")
|
||||
|
||||
form_desc.add_field(
|
||||
"mailing_address",
|
||||
@@ -524,7 +517,7 @@ class RegistrationView(APIView):
|
||||
# Translators: This phrase appears above a field on the registration form
|
||||
# meant to hold the user's reasons for registering with edX.
|
||||
goals_label = _(
|
||||
u"If you'd like, tell us why you're interested in {platform_name}"
|
||||
u"Tell us why you're interested in {platform_name}"
|
||||
).format(platform_name=settings.PLATFORM_NAME)
|
||||
|
||||
form_desc.add_field(
|
||||
@@ -575,13 +568,19 @@ class RegistrationView(APIView):
|
||||
(country_code, unicode(country_name))
|
||||
for country_code, country_name in sorted_countries
|
||||
]
|
||||
|
||||
error_msg = _(u"Please select your Country.")
|
||||
|
||||
form_desc.add_field(
|
||||
"country",
|
||||
label=country_label,
|
||||
field_type="select",
|
||||
options=options,
|
||||
include_default_option=True,
|
||||
required=required
|
||||
required=required,
|
||||
error_messages={
|
||||
"required": error_msg
|
||||
}
|
||||
)
|
||||
|
||||
def _add_honor_code_field(self, form_desc, required=True):
|
||||
|
||||
Reference in New Issue
Block a user