From bd0c5f227c7a9c1d2c2c98d70a7e0c87a702bb31 Mon Sep 17 00:00:00 2001 From: AlasdairSwan Date: Fri, 17 Oct 2014 14:09:14 -0400 Subject: [PATCH] ECOM-369 Added initial Backbone code which allows a user to login to lms --- lms/envs/common.py | 7 +- lms/static/js/student_account/accessApp.js | 13 ++ .../js/student_account/models/LoginModel.js | 52 ++++++ .../js/student_account/views/AccessView.js | 84 +++++++++ .../js/student_account/views/LoginView.js | 160 ++++++++++++++++++ .../student_account/access.underscore | 15 ++ .../student_account/form_field.underscore | 27 +++ .../student_account/login.underscore | 6 + .../student_account/login_and_register.html | 4 +- 9 files changed, 365 insertions(+), 3 deletions(-) create mode 100644 lms/static/js/student_account/accessApp.js create mode 100644 lms/static/js/student_account/models/LoginModel.js create mode 100644 lms/static/js/student_account/views/AccessView.js create mode 100644 lms/static/js/student_account/views/LoginView.js create mode 100644 lms/templates/student_account/access.underscore create mode 100644 lms/templates/student_account/form_field.underscore create mode 100644 lms/templates/student_account/login.underscore diff --git a/lms/envs/common.py b/lms/envs/common.py index c57ff34565..595edf30e4 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -1025,7 +1025,12 @@ instructor_dash_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/ins # JavaScript used by the student account and profile pages # These are not courseware, so they do not need many of the courseware-specific # JavaScript modules. -student_account_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/student_account/**/*.js')) +student_account_js = [ + 'js/student_account/models/LoginModel.js', + 'js/student_account/views/LoginView.js', + 'js/student_account/views/AccessView.js', + 'js/student_account/accessApp.js', +] student_profile_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'js/student_profile/**/*.js')) PIPELINE_CSS = { diff --git a/lms/static/js/student_account/accessApp.js b/lms/static/js/student_account/accessApp.js new file mode 100644 index 0000000000..b3e3a893b9 --- /dev/null +++ b/lms/static/js/student_account/accessApp.js @@ -0,0 +1,13 @@ +var edx = edx || {}; + +(function($) { + 'use strict'; + + edx.student = edx.student || {}; + edx.student.account = edx.student.account || {}; + + return new edx.student.account.AccessView({ + mode: $('#login-and-registration-container').data('initial-mode') || 'login', + thirdPartyAuth: $('#login-and-registration-container').data('third-party-auth-providers') || false + }); +})(jQuery); \ No newline at end of file diff --git a/lms/static/js/student_account/models/LoginModel.js b/lms/static/js/student_account/models/LoginModel.js new file mode 100644 index 0000000000..7930d281ca --- /dev/null +++ b/lms/static/js/student_account/models/LoginModel.js @@ -0,0 +1,52 @@ +var edx = edx || {}; + +(function($, _, Backbone, gettext) { + 'use strict'; + + edx.student = edx.student || {}; + edx.student.account = edx.student.account || {}; + + edx.student.account.LoginModel = Backbone.Model.extend({ + + defaults: { + email: '', + password: '', + remember: false + }, + + urlRoot: '', + + initialize: function( obj ) { + this.urlRoot = obj.url; + }, + + sync: function(method, model) { + var headers = { + 'X-CSRFToken': $.cookie('csrftoken') + }; + + $.ajax({ + url: model.urlRoot, + type: 'POST', + data: model.attributes, + headers: headers + }) + .done(function() { + var query = window.location.search, + url = '/dashboard'; + + model.trigger('sync'); + + // If query string in url go back to that page + if ( query.length > 1 ) { + url = query.substring( query.indexOf('=') + 1 ); + } + + window.location.href = url; + }) + .fail( function( error ) { + model.trigger('error', error); + }); + } + }); +})(jQuery, _, Backbone, gettext); \ No newline at end of file diff --git a/lms/static/js/student_account/views/AccessView.js b/lms/static/js/student_account/views/AccessView.js new file mode 100644 index 0000000000..432552fbba --- /dev/null +++ b/lms/static/js/student_account/views/AccessView.js @@ -0,0 +1,84 @@ +var edx = edx || {}; + +(function($, _, Backbone, gettext) { + 'use strict'; + + edx.student = edx.student || {}; + edx.student.account = edx.student.account || {}; + + edx.student.account.AccessView = Backbone.View.extend({ + el: '#login-and-registration-container', + + tpl: $('#access-tpl').html(), + + events: { + 'change .form-toggle': 'toggleForm' + }, + + // The form currently loaded + activeForm: '', + + initialize: function( obj ) { + this.activeForm = obj.mode; + console.log(obj); + + this.render(); + }, + + render: function() { + $(this.el).html( _.template( this.tpl, { + mode: this.activeForm + })); + + this.postRender(); + + return this; + }, + + postRender: function() { + // Load the default form + this.loadForm( this.activeForm ); + }, + + loadForm: function( type ) { + if ( type === 'login' ) { + console.log('load login'); + return new edx.student.account.LoginView(); + } + + // return new app.LoginView({ + // el: $('#' + type + '-form'), + // model: this.getModel( type ), + // tpl: $('#' + type + '-form-tpl').html() + // }); + }, + + toggleForm: function( e ) { + var type = $(e.currentTarget).val(), + $form = $('#' + type + '-form'); + + if ( !this.form.isLoaded( $form ) ) { + this.loadForm( type ); + } + + $(this.el).find('.form-wrapper').addClass('hidden'); + $form.removeClass('hidden'); + }, + + getModel: function( type ) { + var models = { + join: app.JoinModel, + login: app.JoinModel + }; + + return models[type] ? new models[type]() : false; + }, + + form: { + isLoaded: function( $form ) { + return $form.html().length > 0; + } + } + }); + +})(jQuery, _, Backbone, gettext); \ No newline at end of file diff --git a/lms/static/js/student_account/views/LoginView.js b/lms/static/js/student_account/views/LoginView.js new file mode 100644 index 0000000000..10fd470566 --- /dev/null +++ b/lms/static/js/student_account/views/LoginView.js @@ -0,0 +1,160 @@ +var edx = edx || {}; + +(function($, _, Backbone, gettext) { + 'use strict'; + + edx.student = edx.student || {}; + edx.student.account = edx.student.account || {}; + + edx.student.account.LoginView = Backbone.View.extend({ + tagName: 'form', + + el: '#login-form', + + tpl: $('#login-tpl').html(), + + fieldTpl: $('#form_field-tpl').html(), + + events: { + 'click .js-login': 'submitForm', + 'click .forgot-password': 'forgotPassword' + }, + + errors: [], + + $form: {}, + + initialize: function( obj ) { + this.getInitialData(); + }, + + // Renders the form. + render: function( html ) { + var fields = html || ''; + + $(this.el).html( _.template( this.tpl, { + fields: fields + })); + + this.postRender(); + + return this; + }, + + postRender: function() { + + this.$form = $(this.el).find('form'); + }, + + getInitialData: function() { + var that = this; + + $.ajax({ + type: 'GET', + dataType: 'json', + url: '/user_api/v1/account/login_session/', + success: function( data ) { + console.log(data); + that.buildForm( data.fields ); + that.initModel( data.submit_url, data.method ); + }, + error: function( jqXHR, textStatus, errorThrown ) { + console.log('fail ', errorThrown); + } + }); + }, + + initModel: function( url, method ) { + this.model = new edx.student.account.LoginModel({ + url: url + }); + + this.listenTo( this.model, 'error', function( error ) { + console.log(error.status, ' error: ', error.responseText); + }); + }, + + buildForm: function( data ) { + var html = [], + i, + len = data.length, + fieldTpl = this.fieldTpl; + + for ( i=0; i +

+ checked<% } %> > + +

+
+ + +
+

+ checked<% } %>> + +

+
+
diff --git a/lms/templates/student_account/form_field.underscore b/lms/templates/student_account/form_field.underscore new file mode 100644 index 0000000000..b5787baf5a --- /dev/null +++ b/lms/templates/student_account/form_field.underscore @@ -0,0 +1,27 @@ +

+ <% if ( type !== 'checkbox' ) { %> + <% } %> + + <% } %> + + <% if( form === 'login' && name === 'password' ) { %> + Forgot password? + <% } %> + + minlength="<%= restrictions.min_length %>"<% } %> + <% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %> + <% if ( required ) { %> required<% } %> + /> + + <% if ( type === 'checkbox' ) { %> + <% } %> + + <% } %> + + <%= instructions %> +

\ No newline at end of file diff --git a/lms/templates/student_account/login.underscore b/lms/templates/student_account/login.underscore new file mode 100644 index 0000000000..c1f85c3088 --- /dev/null +++ b/lms/templates/student_account/login.underscore @@ -0,0 +1,6 @@ +
+ <%= fields %> + + + +
\ No newline at end of file diff --git a/lms/templates/student_account/login_and_register.html b/lms/templates/student_account/login_and_register.html index 19ed498fd8..ee2b49c503 100644 --- a/lms/templates/student_account/login_and_register.html +++ b/lms/templates/student_account/login_and_register.html @@ -12,7 +12,7 @@ <%block name="header_extras"> -% for template_name in ["account"]: +% for template_name in ["account", "access", "form_field", "login"]: @@ -21,7 +21,7 @@

Login and Registration!

-

This is a placeholder for the combined login and registration form

+

This is a placeholder for the combined login and registration form.

## TODO: Use JavaScript to populate this div with ## the actual registration/login forms (loaded asynchronously from the user API)