From a4342070765f2bbdef89bbf5e5c996f9b16cd04b Mon Sep 17 00:00:00 2001 From: AlasdairSwan Date: Thu, 18 Dec 2014 14:39:03 -0500 Subject: [PATCH] ECOM-783 updated logistration in light of redesign --- .../static/js/spec/edx.utils.validate_spec.js | 2 +- common/static/js/utils/edx.utils.validate.js | 6 +- .../pages/lms/login_and_register.py | 22 +- common/test/acceptance/tests/lms/test_lms.py | 4 +- .../courseware/features/homepage.feature | 6 +- .../courseware/features/login.feature | 8 +- lms/static/js/spec/main.js | 2 + .../js/spec/student_account/access_spec.js | 8 +- .../js/spec/student_account/login_spec.js | 13 +- .../student_account/password_reset_spec.js | 8 +- .../models/PasswordResetModel.js | 2 +- .../js/student_account/views/AccessView.js | 56 ++- .../js/student_account/views/FormView.js | 16 +- .../js/student_account/views/LoginView.js | 17 +- .../views/PasswordResetView.js | 13 +- lms/static/js/vendor/history.js | 2 + lms/static/sass/base/_base.scss | 9 +- lms/static/sass/base/_variables.scss | 26 +- lms/static/sass/views/_login-register.scss | 364 +++++++++++------- lms/templates/main.html | 25 +- lms/templates/navigation-edx.html | 6 +- lms/templates/navigation.html | 6 +- .../student_account/access.underscore | 39 +- .../student_account/form_field.underscore | 9 +- .../student_account/login.underscore | 73 +++- .../student_account/login_and_register.html | 10 +- .../student_account/password_reset.underscore | 39 +- .../student_account/register.underscore | 65 +++- .../djangoapps/user_api/tests/test_views.py | 32 +- openedx/core/djangoapps/user_api/views.py | 45 ++- 30 files changed, 557 insertions(+), 376 deletions(-) create mode 100644 lms/static/js/vendor/history.js diff --git a/common/static/js/spec/edx.utils.validate_spec.js b/common/static/js/spec/edx.utils.validate_spec.js index 2983f421b2..d6664c4647 100644 --- a/common/static/js/spec/edx.utils.validate_spec.js +++ b/common/static/js/spec/edx.utils.validate_spec.js @@ -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 ) { diff --git a/common/static/js/utils/edx.utils.validate.js b/common/static/js/utils/edx.utils.validate.js index 5a2afa7b02..392c99bc46 100644 --- a/common/static/js/utils/edx.utils.validate.js +++ b/common/static/js/utils/edx.utils.validate.js @@ -19,9 +19,9 @@ var edx = edx || {}; msg: { email: '
  • <%- gettext("The email address you\'ve provided isn\'t formatted correctly.") %>
  • ', - min: '
  • <%- _.sprintf(gettext("%(field)s must have at least %(count)d characters."), context) %>
  • ', - max: '
  • <%- _.sprintf(gettext("%(field)s can only contain up to %(count)d characters."), context) %>
  • ', - required: '
  • <%- _.sprintf(gettext("The %(field)s field cannot be empty."), context) %>
  • ', + min: '
  • <%- _.sprintf( gettext("%(field)s must have at least %(count)d characters."), context ) %>
  • ', + max: '
  • <%- _.sprintf( gettext("%(field)s can only contain up to %(count)d characters."), context ) %>
  • ', + required: '
  • <%- _.sprintf( gettext("Please enter your %(field)s."), context ) %>
  • ', custom: '
  • <%= content %>
  • ' }, diff --git a/common/test/acceptance/pages/lms/login_and_register.py b/common/test/acceptance/pages/lms/login_and_register.py index 1bda4fa2d8..3714179858 100644 --- a/common/test/acceptance/pages/lms/login_and_register.py +++ b/common/test/acceptance/pages/lms/login_and_register.py @@ -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 diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index 09853250bf..94dd57d64a 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -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() diff --git a/lms/djangoapps/courseware/features/homepage.feature b/lms/djangoapps/courseware/features/homepage.feature index c66d06694a..ac9b91e8d1 100644 --- a/lms/djangoapps/courseware/features/homepage.feature +++ b/lms/djangoapps/courseware/features/homepage.feature @@ -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 diff --git a/lms/djangoapps/courseware/features/login.feature b/lms/djangoapps/courseware/features/login.feature index 3576a1adaf..acb5b38e7e 100644 --- a/lms/djangoapps/courseware/features/login.feature +++ b/lms/djangoapps/courseware/features/login.feature @@ -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 diff --git a/lms/static/js/spec/main.js b/lms/static/js/spec/main.js index 4db456cc9c..82594d4af7 100644 --- a/lms/static/js/spec/main.js +++ b/lms/static/js/spec/main.js @@ -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', diff --git a/lms/static/js/spec/student_account/access_spec.js b/lms/static/js/spec/student_account/access_spec.js index 2df49b5d58..110c5bf6cc 100644 --- a/lms/static/js/spec/student_account/access_spec.js +++ b/lms/static/js/spec/student_account/access_spec.js @@ -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() { diff --git a/lms/static/js/spec/student_account/login_spec.js b/lms/static/js/spec/student_account/login_spec.js index 428e09d340..93a0f1b69d 100644 --- a/lms/static/js/spec/student_account/login_spec.js +++ b/lms/static/js/spec/student_account/login_spec.js @@ -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 }); diff --git a/lms/static/js/spec/student_account/password_reset_spec.js b/lms/static/js/spec/student_account/password_reset_spec.js index 37a6ab4b67..0eeff353ca 100644 --- a/lms/static/js/spec/student_account/password_reset_spec.js +++ b/lms/static/js/spec/student_account/password_reset_spec.js @@ -67,7 +67,7 @@ define([ }; beforeEach(function() { - setFixtures('
    '); + setFixtures(''); 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() { diff --git a/lms/static/js/student_account/models/PasswordResetModel.js b/lms/static/js/student_account/models/PasswordResetModel.js index 60858dc630..691b4a86f5 100644 --- a/lms/static/js/student_account/models/PasswordResetModel.js +++ b/lms/static/js/student_account/models/PasswordResetModel.js @@ -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') }; diff --git a/lms/static/js/student_account/views/AccessView.js b/lms/static/js/student_account/views/AccessView.js index 52902d173f..4796834b3a 100644 --- a/lms/static/js/student_account/views/AccessView.js +++ b/lms/static/js/student_account/views/AccessView.js @@ -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'); } } }); diff --git a/lms/static/js/student_account/views/FormView.js b/lms/static/js/student_account/views/FormView.js index 32b3e87472..12f0d51100 100644 --- a/lms/static/js/student_account/views/FormView.js +++ b/lms/static/js/student_account/views/FormView.js @@ -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 ) { diff --git a/lms/static/js/student_account/views/LoginView.js b/lms/static/js/student_account/views/LoginView.js index 85edd59d3f..7b567b9fbd 100644 --- a/lms/static/js/student_account/views/LoginView.js +++ b/lms/static/js/student_account/views/LoginView.js @@ -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 = ['
  • ' + error.responseText + '
  • ']; 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 diff --git a/lms/static/js/student_account/views/PasswordResetView.js b/lms/static/js/student_account/views/PasswordResetView.js index cddedfa66f..d9667218cb 100644 --- a/lms/static/js/student_account/views/PasswordResetView.js +++ b/lms/static/js/student_account/views/PasswordResetView.js @@ -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(); } }); diff --git a/lms/static/js/vendor/history.js b/lms/static/js/vendor/history.js new file mode 100644 index 0000000000..6e5be0f6f0 --- /dev/null +++ b/lms/static/js/vendor/history.js @@ -0,0 +1,2 @@ +/* History.js v1.8b2 https://github.com/browserstate/history.js */ +typeof JSON!="object"&&(JSON={}),function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t=="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];a&&typeof a=="object"&&typeof a.toJSON=="function"&&(a=a.toJSON(e)),typeof rep=="function"&&(a=rep.call(t,e,a));switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a)return"null";gap+=indent,u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n")&&n[0]);return e>4?e:!1}();return e},h.isInternetExplorer=function(){var e=h.isInternetExplorer.cached=typeof h.isInternetExplorer.cached!="undefined"?h.isInternetExplorer.cached:Boolean(h.getInternetExplorerMajorVersion());return e},h.options.html4Mode?h.emulated={pushState:!0,hashChange:!0}:h.emulated={pushState:!Boolean(e.history&&e.history.pushState&&e.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(i.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(i.userAgent)),hashChange:Boolean(!("onhashchange"in e||"onhashchange"in r)||h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8)},h.enabled=!h.emulated.pushState,h.bugs={setHash:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),safariPoll:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),ieDoubleCheck:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<7)},h.isEmptyObject=function(e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},h.cloneObject=function(e){var t,n;return e?(t=l.stringify(e),n=l.parse(t)):n={},n},h.getRootUrl=function(){var e=r.location.protocol+"//"+(r.location.hostname||r.location.host);if(r.location.port||!1)e+=":"+r.location.port;return e+="/",e},h.getBaseHref=function(){var e=r.getElementsByTagName("base"),t=null,n="";return e.length===1&&(t=e[0],n=t.href.replace(/[^\/]+$/,"")),n=n.replace(/\/+$/,""),n&&(n+="/"),n},h.getBaseUrl=function(){var e=h.getBaseHref()||h.getBasePageUrl()||h.getRootUrl();return e},h.getPageUrl=function(){var e=h.getState(!1,!1),t=(e||{}).url||h.getLocationHref(),n;return n=t.replace(/\/+$/,"").replace(/[^\/]+$/,function(e,t,n){return/\./.test(e)?e:e+"/"}),n},h.getBasePageUrl=function(){var e=h.getLocationHref().replace(/[#\?].*/,"").replace(/[^\/]+$/,function(e,t,n){return/[^\/]$/.test(e)?"":e}).replace(/\/+$/,"")+"/";return e},h.getFullUrl=function(e,t){var n=e,r=e.substring(0,1);return t=typeof t=="undefined"?!0:t,/[a-z]+\:\/\//.test(e)||(r==="/"?n=h.getRootUrl()+e.replace(/^\/+/,""):r==="#"?n=h.getPageUrl().replace(/#.*/,"")+e:r==="?"?n=h.getPageUrl().replace(/[\?#].*/,"")+e:t?n=h.getBaseUrl()+e.replace(/^(\.\/)+/,""):n=h.getBasePageUrl()+e.replace(/^(\.\/)+/,"")),n.replace(/\#$/,"")},h.getShortUrl=function(e){var t=e,n=h.getBaseUrl(),r=h.getRootUrl();return h.emulated.pushState&&(t=t.replace(n,"")),t=t.replace(r,"/"),h.isTraditionalAnchor(t)&&(t="./"+t),t=t.replace(/^(\.\/)+/g,"./").replace(/\#$/,""),t},h.getLocationHref=function(e){return e=e||r,e.URL===e.location.href?e.location.href:e.location.href===decodeURIComponent(e.URL)?e.URL:e.location.hash&&decodeURIComponent(e.location.href.replace(/^[^#]+/,""))===e.location.hash?e.location.href:e.URL.indexOf("#")==-1&&e.location.href.indexOf("#")!=-1?e.location.href:e.URL||e.location.href},h.store={},h.idToState=h.idToState||{},h.stateToId=h.stateToId||{},h.urlToId=h.urlToId||{},h.storedStates=h.storedStates||[],h.savedStates=h.savedStates||[],h.normalizeStore=function(){h.store.idToState=h.store.idToState||{},h.store.urlToId=h.store.urlToId||{},h.store.stateToId=h.store.stateToId||{}},h.getState=function(e,t){typeof e=="undefined"&&(e=!0),typeof t=="undefined"&&(t=!0);var n=h.getLastSavedState();return!n&&t&&(n=h.createStateObject()),e&&(n=h.cloneObject(n),n.url=n.cleanUrl||n.url),n},h.getIdByState=function(e){var t=h.extractId(e.url),n;if(!t){n=h.getStateString(e);if(typeof h.stateToId[n]!="undefined")t=h.stateToId[n];else if(typeof h.store.stateToId[n]!="undefined")t=h.store.stateToId[n];else{for(;;){t=(new Date).getTime()+String(Math.random()).replace(/\D/g,"");if(typeof h.idToState[t]=="undefined"&&typeof h.store.idToState[t]=="undefined")break}h.stateToId[n]=t,h.idToState[t]=e}}return t},h.normalizeState=function(e){var t,n;if(!e||typeof e!="object")e={};if(typeof e.normalized!="undefined")return e;if(!e.data||typeof e.data!="object")e.data={};return t={},t.normalized=!0,t.title=e.title||"",t.url=h.getFullUrl(e.url?e.url:h.getLocationHref()),t.hash=h.getShortUrl(t.url),t.data=h.cloneObject(e.data),t.id=h.getIdByState(t),t.cleanUrl=t.url.replace(/\??\&_suid.*/,""),t.url=t.cleanUrl,n=!h.isEmptyObject(t.data),(t.title||n)&&h.options.disableSuid!==!0&&(t.hash=h.getShortUrl(t.url).replace(/\??\&_suid.*/,""),/\?/.test(t.hash)||(t.hash+="?"),t.hash+="&_suid="+t.id),t.hashedUrl=h.getFullUrl(t.hash),(h.emulated.pushState||h.bugs.safariPoll)&&h.hasUrlDuplicate(t)&&(t.url=t.hashedUrl),t},h.createStateObject=function(e,t,n){var r={data:e,title:t,url:n};return r=h.normalizeState(r),r},h.getStateById=function(e){e=String(e);var n=h.idToState[e]||h.store.idToState[e]||t;return n},h.getStateString=function(e){var t,n,r;return t=h.normalizeState(e),n={data:t.data,title:e.title,url:e.url},r=l.stringify(n),r},h.getStateId=function(e){var t,n;return t=h.normalizeState(e),n=t.id,n},h.getHashByState=function(e){var t,n;return t=h.normalizeState(e),n=t.hash,n},h.extractId=function(e){var t,n,r,i;return e.indexOf("#")!=-1?i=e.split("#")[0]:i=e,n=/(.*)\&_suid=([0-9]+)$/.exec(i),r=n?n[1]||e:e,t=n?String(n[2]||""):"",t||!1},h.isTraditionalAnchor=function(e){var t=!/[\/\?\.]/.test(e);return t},h.extractState=function(e,t){var n=null,r,i;return t=t||!1,r=h.extractId(e),r&&(n=h.getStateById(r)),n||(i=h.getFullUrl(e),r=h.getIdByUrl(i)||!1,r&&(n=h.getStateById(r)),!n&&t&&!h.isTraditionalAnchor(e)&&(n=h.createStateObject(null,null,i))),n},h.getIdByUrl=function(e){var n=h.urlToId[e]||h.store.urlToId[e]||t;return n},h.getLastSavedState=function(){return h.savedStates[h.savedStates.length-1]||t},h.getLastStoredState=function(){return h.storedStates[h.storedStates.length-1]||t},h.hasUrlDuplicate=function(e){var t=!1,n;return n=h.extractState(e.url),t=n&&n.id!==e.id,t},h.storeState=function(e){return h.urlToId[e.url]=e.id,h.storedStates.push(h.cloneObject(e)),e},h.isLastSavedState=function(e){var t=!1,n,r,i;return h.savedStates.length&&(n=e.id,r=h.getLastSavedState(),i=r.id,t=n===i),t},h.saveState=function(e){return h.isLastSavedState(e)?!1:(h.savedStates.push(h.cloneObject(e)),!0)},h.getStateByIndex=function(e){var t=null;return typeof e=="undefined"?t=h.savedStates[h.savedStates.length-1]:e<0?t=h.savedStates[h.savedStates.length+e]:t=h.savedStates[e],t},h.getCurrentIndex=function(){var e=null;return h.savedStates.length<1?e=0:e=h.savedStates.length-1,e},h.getHash=function(e){var t=h.getLocationHref(e),n;return n=h.getHashByUrl(t),n},h.unescapeHash=function(e){var t=h.normalizeHash(e);return t=decodeURIComponent(t),t},h.normalizeHash=function(e){var t=e.replace(/[^#]*#/,"").replace(/#.*/,"");return t},h.setHash=function(e,t){var n,i;return t!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.setHash,args:arguments,queue:t}),!1):(h.busy(!0),n=h.extractState(e,!0),n&&!h.emulated.pushState?h.pushState(n.data,n.title,n.url,!1):h.getHash()!==e&&(h.bugs.setHash?(i=h.getPageUrl(),h.pushState(null,null,i+"#"+e,!1)):r.location.hash=e),h)},h.escapeHash=function(t){var n=h.normalizeHash(t);return n=e.encodeURIComponent(n),h.bugs.hashEscape||(n=n.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?")),n},h.getHashByUrl=function(e){var t=String(e).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");return t=h.unescapeHash(t),t},h.setTitle=function(e){var t=e.title,n;t||(n=h.getStateByIndex(0),n&&n.url===e.url&&(t=n.title||h.options.initialTitle));try{r.getElementsByTagName("title")[0].innerHTML=t.replace("<","<").replace(">",">").replace(" & "," & ")}catch(i){}return r.title=t,h},h.queues=[],h.busy=function(e){typeof e!="undefined"?h.busy.flag=e:typeof h.busy.flag=="undefined"&&(h.busy.flag=!1);if(!h.busy.flag){u(h.busy.timeout);var t=function(){var e,n,r;if(h.busy.flag)return;for(e=h.queues.length-1;e>=0;--e){n=h.queues[e];if(n.length===0)continue;r=n.shift(),h.fireQueueItem(r),h.busy.timeout=o(t,h.options.busyDelay)}};h.busy.timeout=o(t,h.options.busyDelay)}return h.busy.flag},h.busy.flag=!1,h.fireQueueItem=function(e){return e.callback.apply(e.scope||h,e.args||[])},h.pushQueue=function(e){return h.queues[e.queue||0]=h.queues[e.queue||0]||[],h.queues[e.queue||0].push(e),h},h.queue=function(e,t){return typeof e=="function"&&(e={callback:e}),typeof t!="undefined"&&(e.queue=t),h.busy()?h.pushQueue(e):h.fireQueueItem(e),h},h.clearQueue=function(){return h.busy.flag=!1,h.queues=[],h},h.stateChanged=!1,h.doubleChecker=!1,h.doubleCheckComplete=function(){return h.stateChanged=!0,h.doubleCheckClear(),h},h.doubleCheckClear=function(){return h.doubleChecker&&(u(h.doubleChecker),h.doubleChecker=!1),h},h.doubleCheck=function(e){return h.stateChanged=!1,h.doubleCheckClear(),h.bugs.ieDoubleCheck&&(h.doubleChecker=o(function(){return h.doubleCheckClear(),h.stateChanged||e(),!0},h.options.doubleCheckInterval)),h},h.safariStatePoll=function(){var t=h.extractState(h.getLocationHref()),n;if(!h.isLastSavedState(t))return n=t,n||(n=h.createStateObject()),h.Adapter.trigger(e,"popstate"),h;return},h.back=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.back,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.back(!1)}),p.go(-1),!0)},h.forward=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.forward,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.forward(!1)}),p.go(1),!0)},h.go=function(e,t){var n;if(e>0)for(n=1;n<=e;++n)h.forward(t);else{if(!(e<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(n=-1;n>=e;--n)h.back(t)}return h};if(h.emulated.pushState){var v=function(){};h.pushState=h.pushState||v,h.replaceState=h.replaceState||v}else h.onPopState=function(t,n){var r=!1,i=!1,s,o;return h.doubleCheckComplete(),s=h.getHash(),s?(o=h.extractState(s||h.getLocationHref(),!0),o?h.replaceState(o.data,o.title,o.url,!1):(h.Adapter.trigger(e,"anchorchange"),h.busy(!1)),h.expectedStateId=!1,!1):(r=h.Adapter.extractEventData("state",t,n)||!1,r?i=h.getStateById(r):h.expectedStateId?i=h.getStateById(h.expectedStateId):i=h.extractState(h.getLocationHref()),i||(i=h.createStateObject(null,null,h.getLocationHref())),h.expectedStateId=!1,h.isLastSavedState(i)?(h.busy(!1),!1):(h.storeState(i),h.saveState(i),h.setTitle(i),h.Adapter.trigger(e,"statechange"),h.busy(!1),!0))},h.Adapter.bind(e,"popstate",h.onPopState),h.pushState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.pushState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.pushState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0},h.replaceState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.replaceState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.replaceState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0};if(s){try{h.store=l.parse(s.getItem("History.store"))||{}}catch(m){h.store={}}h.normalizeStore()}else h.store={},h.normalizeStore();h.Adapter.bind(e,"unload",h.clearAllIntervals),h.saveState(h.storeState(h.extractState(h.getLocationHref(),!0))),s&&(h.onUnload=function(){var e,t,n;try{e=l.parse(s.getItem("History.store"))||{}}catch(r){e={}}e.idToState=e.idToState||{},e.urlToId=e.urlToId||{},e.stateToId=e.stateToId||{};for(t in h.idToState){if(!h.idToState.hasOwnProperty(t))continue;e.idToState[t]=h.idToState[t]}for(t in h.urlToId){if(!h.urlToId.hasOwnProperty(t))continue;e.urlToId[t]=h.urlToId[t]}for(t in h.stateToId){if(!h.stateToId.hasOwnProperty(t))continue;e.stateToId[t]=h.stateToId[t]}h.store=e,h.normalizeStore(),n=l.stringify(e);try{s.setItem("History.store",n)}catch(i){if(i.code!==DOMException.QUOTA_EXCEEDED_ERR)throw i;s.length&&(s.removeItem("History.store"),s.setItem("History.store",n))}},h.intervalList.push(a(h.onUnload,h.options.storeInterval)),h.Adapter.bind(e,"beforeunload",h.onUnload),h.Adapter.bind(e,"unload",h.onUnload));if(!h.emulated.pushState){h.bugs.safariPoll&&h.intervalList.push(a(h.safariStatePoll,h.options.safariPollInterval));if(i.vendor==="Apple Computer, Inc."||(i.appCodeName||"")==="Mozilla")h.Adapter.bind(e,"hashchange",function(){h.Adapter.trigger(e,"popstate")}),h.getHash()&&h.Adapter.onDomLoad(function(){h.Adapter.trigger(e,"hashchange")})}},(!h.options||!h.options.delayInit)&&h.init()}(window) \ No newline at end of file diff --git a/lms/static/sass/base/_base.scss b/lms/static/sass/base/_base.scss index f5437d302e..b4adb76d81 100644 --- a/lms/static/sass/base/_base.scss +++ b/lms/static/sass/base/_base.scss @@ -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; diff --git a/lms/static/sass/base/_variables.scss b/lms/static/sass/base/_variables.scss index 861d59e048..265062d5b8 100644 --- a/lms/static/sass/base/_variables.scss +++ b/lms/static/sass/base/_variables.scss @@ -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); diff --git a/lms/static/sass/views/_login-register.scss b/lms/static/sass/views/_login-register.scss index f2f9ce0579..061defe06f 100644 --- a/lms/static/sass/views/_login-register.scss +++ b/lms/static/sass/views/_login-register.scss @@ -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; } } } diff --git a/lms/templates/main.html b/lms/templates/main.html index 73fd6edfeb..b39a2494b7 100644 --- a/lms/templates/main.html +++ b/lms/templates/main.html @@ -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: % endif @@ -149,18 +141,25 @@ <%include file="mathjax_accessible.html" /> - % if not suppress_toplevel_navigation: <%include file="${header_file}" /> - %endif
    ${self.body()} <%block name="bodyextra"/>
    - % 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}" /> + diff --git a/lms/templates/navigation-edx.html b/lms/templates/navigation-edx.html index 83f92b6a10..22927e8d57 100644 --- a/lms/templates/navigation-edx.html +++ b/lms/templates/navigation-edx.html @@ -80,7 +80,7 @@ site_status_msg = get_site_status_msg(course_id)
  • ${_("Help")}
  • % endif -
  • ${_("Log Out")}
  • +
  • ${_("Sign out")}
  • @@ -126,9 +126,9 @@ site_status_msg = get_site_status_msg(course_id) diff --git a/lms/templates/navigation.html b/lms/templates/navigation.html index 3634835ce2..6d776e807d 100644 --- a/lms/templates/navigation.html +++ b/lms/templates/navigation.html @@ -75,7 +75,7 @@ site_status_msg = get_site_status_msg(course_id)
  • ${_("Help")}
  • % endif -
  • ${_("Log Out")}
  • +
  • ${_("Sign out")}
  • @@ -120,9 +120,9 @@ site_status_msg = get_site_status_msg(course_id) diff --git a/lms/templates/student_account/access.underscore b/lms/templates/student_account/access.underscore index 6117f11d9e..3bff3137c9 100644 --- a/lms/templates/student_account/access.underscore +++ b/lms/templates/student_account/access.underscore @@ -1,40 +1,17 @@ - - -