Merge pull request #5647 from edx/alasdair/combine-reg-login-form
Alasdair/combine reg login form
This commit is contained in:
71
common/static/js/spec_helpers/edx.utils.validate.js
Normal file
71
common/static/js/spec_helpers/edx.utils.validate.js
Normal file
@@ -0,0 +1,71 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function( $, _ ) {
|
||||
'use strict';
|
||||
|
||||
edx.utils = edx.utils || {};
|
||||
|
||||
var utils = (function(){
|
||||
var _fn = {
|
||||
validate: {
|
||||
|
||||
field: function( el ) {
|
||||
var $el = $(el);
|
||||
|
||||
return _fn.validate.required( $el ) &&
|
||||
_fn.validate.charLength( $el ) &&
|
||||
_fn.validate.email.valid( $el );
|
||||
},
|
||||
|
||||
charLength: function( $el ) {
|
||||
// Cannot assume there will be both min and max
|
||||
var min = $el.attr('minlength') || 0,
|
||||
max = $el.attr('maxlength') || false,
|
||||
chars = $el.val().length,
|
||||
within = false;
|
||||
|
||||
// if max && min && within the range
|
||||
if ( min <= chars && ( max && chars <= max ) ) {
|
||||
within = true;
|
||||
} else if ( min <= chars && !max ) {
|
||||
within = true;
|
||||
}
|
||||
|
||||
return within;
|
||||
},
|
||||
|
||||
required: function( $el ) {
|
||||
return $el.attr('required') ? $el.val() : true;
|
||||
},
|
||||
|
||||
email: {
|
||||
// This is the same regex used to validate email addresses in Django 1.4
|
||||
regex: new RegExp(
|
||||
[
|
||||
'(^[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+)*',
|
||||
'|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"',
|
||||
')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+[A-Z]{2,6}\\.?$)',
|
||||
'|\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]$'
|
||||
].join(''), 'i'
|
||||
),
|
||||
|
||||
valid: function( $el ) {
|
||||
return $el.data('email') ? _fn.validate.email.format( $el.val() ) : true;
|
||||
},
|
||||
|
||||
format: function( str ) {
|
||||
return _fn.validate.email.regex.test( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
validate: _fn.validate.field
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
edx.utils.validate = utils.validate
|
||||
|
||||
})( jQuery, _ );
|
||||
@@ -286,7 +286,7 @@ FEATURES = {
|
||||
'ENABLE_VIDEO_ABSTRACTION_LAYER_API': False,
|
||||
|
||||
# Enable the new dashboard, account, and profile pages
|
||||
'ENABLE_NEW_DASHBOARD': False,
|
||||
'ENABLE_NEW_DASHBOARD': True,
|
||||
}
|
||||
|
||||
# Ignore static asset files on import which match this pattern
|
||||
@@ -1025,7 +1025,17 @@ 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/common_helpers/edx.utils.validate.js',
|
||||
'js/student_account/models/LoginModel.js',
|
||||
'js/student_account/models/RegisterModel.js',
|
||||
'js/student_account/models/PasswordResetModel.js',
|
||||
'js/student_account/views/LoginView.js',
|
||||
'js/student_account/views/RegisterView.js',
|
||||
'js/student_account/views/PasswordResetView.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 = {
|
||||
|
||||
13
lms/static/js/student_account/accessApp.js
Normal file
13
lms/static/js/student_account/accessApp.js
Normal file
@@ -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);
|
||||
52
lms/static/js/student_account/models/LoginModel.js
Normal file
52
lms/static/js/student_account/models/LoginModel.js
Normal file
@@ -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);
|
||||
38
lms/static/js/student_account/models/PasswordResetModel.js
Normal file
38
lms/static/js/student_account/models/PasswordResetModel.js
Normal file
@@ -0,0 +1,38 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.PasswordResetModel = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
email: ''
|
||||
},
|
||||
|
||||
urlRoot: '/account/password',
|
||||
|
||||
sync: function(method, model) {
|
||||
var headers = {
|
||||
'X-CSRFToken': $.cookie('csrftoken')
|
||||
};
|
||||
|
||||
// Is just expecting email address
|
||||
$.ajax({
|
||||
url: model.urlRoot,
|
||||
type: 'POST',
|
||||
data: model.attributes,
|
||||
headers: headers
|
||||
})
|
||||
.done(function() {
|
||||
model.trigger('success');
|
||||
})
|
||||
.fail( function( error ) {
|
||||
console.log('RegisterModel.save() FAILURE!!!!!');
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
60
lms/static/js/student_account/models/RegisterModel.js
Normal file
60
lms/static/js/student_account/models/RegisterModel.js
Normal file
@@ -0,0 +1,60 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.RegisterModel = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
email: '',
|
||||
name: '',
|
||||
username: '',
|
||||
password: '',
|
||||
level_of_education: '',
|
||||
gender: '',
|
||||
year_of_birth: '',
|
||||
mailing_address: '',
|
||||
goals: '',
|
||||
termsofservice: 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 ) {
|
||||
console.log('RegisterModel.save() FAILURE!!!!!');
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
88
lms/static/js/student_account/views/AccessView.js
Normal file
88
lms/static/js/student_account/views/AccessView.js
Normal file
@@ -0,0 +1,88 @@
|
||||
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'
|
||||
},
|
||||
|
||||
subview: {
|
||||
login: {},
|
||||
register: {},
|
||||
passwordHelp: {}
|
||||
},
|
||||
|
||||
// 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 );
|
||||
this.$header = $(this.el).find('.js-login-register-header');
|
||||
},
|
||||
|
||||
loadForm: function( type ) {
|
||||
if ( type === 'login' ) {
|
||||
this.subview.login = new edx.student.account.LoginView();
|
||||
|
||||
// Listen for 'password-help' event to toggle sub-views
|
||||
this.listenTo( this.subview.login, 'password-help', this.resetPassword );
|
||||
} else if ( type === 'register' ) {
|
||||
this.subview.register = new edx.student.account.RegisterView();
|
||||
} else if ( type === 'reset' ) {
|
||||
this.subview.passwordHelp = new edx.student.account.PasswordResetView();
|
||||
}
|
||||
},
|
||||
|
||||
resetPassword: function() {
|
||||
this.$header.addClass('hidden');
|
||||
$(this.el).find('.form-type').addClass('hidden');
|
||||
this.loadForm('reset');
|
||||
},
|
||||
|
||||
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');
|
||||
},
|
||||
|
||||
form: {
|
||||
isLoaded: function( $form ) {
|
||||
return $form.html().length > 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
163
lms/static/js/student_account/views/LoginView.js
Normal file
163
lms/static/js/student_account/views/LoginView.js
Normal file
@@ -0,0 +1,163 @@
|
||||
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() {
|
||||
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() {
|
||||
var $container = $(this.el);
|
||||
|
||||
this.$form = $container.find('form');
|
||||
this.$errors = $container.find('.error-msg');
|
||||
},
|
||||
|
||||
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 ) {
|
||||
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<len; i++ ) {
|
||||
html.push( _.template( fieldTpl, $.extend( data[i], {
|
||||
form: 'login'
|
||||
}) ) );
|
||||
}
|
||||
|
||||
this.render( html.join('') );
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
|
||||
var obj = {},
|
||||
$form = this.$form,
|
||||
elements = $form[0].elements,
|
||||
i,
|
||||
len = elements.length,
|
||||
$el,
|
||||
key = '',
|
||||
errors = [];
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
|
||||
$el = $( elements[i] );
|
||||
key = $el.attr('name') || false;
|
||||
|
||||
if ( key ) {
|
||||
if ( this.validate( elements[i] ) ) {
|
||||
obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val();
|
||||
$el.css('border', '1px solid #ccc');
|
||||
} else {
|
||||
errors.push( key );
|
||||
$el.css('border', '2px solid red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.errors = errors;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
forgotPassword: function( event ) {
|
||||
event.preventDefault();
|
||||
|
||||
this.trigger('password-help');
|
||||
},
|
||||
|
||||
submitForm: function( event ) {
|
||||
var data = this.getFormData();
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// console.log(this.model);
|
||||
|
||||
if ( !this.errors.length ) {
|
||||
console.log('save me');
|
||||
this.model.set( data );
|
||||
this.model.save();
|
||||
this.toggleErrorMsg( false );
|
||||
} else {
|
||||
console.log('here are the errors ', this.errors);
|
||||
this.toggleErrorMsg( true );
|
||||
}
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
if ( show ) {
|
||||
this.$errors.removeClass('hidden');
|
||||
} else {
|
||||
this.$errors.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
validate: function( $el ) {
|
||||
return edx.utils.validate( $el );
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
155
lms/static/js/student_account/views/PasswordResetView.js
Normal file
155
lms/static/js/student_account/views/PasswordResetView.js
Normal file
@@ -0,0 +1,155 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.PasswordResetView = Backbone.View.extend({
|
||||
tagName: 'form',
|
||||
|
||||
el: '#password-reset-wrapper',
|
||||
|
||||
tpl: $('#password_reset-tpl').html(),
|
||||
|
||||
fieldTpl: $('#form_field-tpl').html(),
|
||||
|
||||
events: {
|
||||
'click .js-reset': 'submitForm'
|
||||
},
|
||||
|
||||
errors: [],
|
||||
|
||||
mode: {},
|
||||
|
||||
$form: {},
|
||||
|
||||
initialize: function() {
|
||||
var fields = this.buildForm([{
|
||||
label: 'E-mail',
|
||||
instructions: 'This is the e-mail address you used to register with edX',
|
||||
name: 'email',
|
||||
required: true,
|
||||
type: 'email',
|
||||
restrictions: []
|
||||
}]);
|
||||
|
||||
this.initModel();
|
||||
this.render( fields );
|
||||
},
|
||||
|
||||
// Renders the form.
|
||||
render: function( html ) {
|
||||
var fields = html || '';
|
||||
|
||||
$(this.el).html( _.template( this.tpl, {
|
||||
fields: fields
|
||||
}));
|
||||
|
||||
this.postRender();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var $container = $(this.el);
|
||||
|
||||
this.$form = $container.find('form');
|
||||
this.$errors = $container.find('.error-msg');
|
||||
|
||||
this.listenTo( this.model, 'success', this.resetComplete) ;
|
||||
},
|
||||
|
||||
initModel: function() {
|
||||
this.model = new edx.student.account.PasswordResetModel();
|
||||
|
||||
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<len; i++ ) {
|
||||
html.push( _.template( fieldTpl, $.extend( data[i], {
|
||||
form: 'reset-password'
|
||||
}) ) );
|
||||
}
|
||||
|
||||
return html.join('');
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
|
||||
var obj = {},
|
||||
$form = this.$form,
|
||||
elements = $form[0].elements,
|
||||
i,
|
||||
len = elements.length,
|
||||
$el,
|
||||
key = '',
|
||||
errors = [];
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
|
||||
$el = $( elements[i] );
|
||||
key = $el.attr('name') || false;
|
||||
|
||||
if ( key ) {
|
||||
if ( this.validate( elements[i] ) ) {
|
||||
obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val();
|
||||
$el.css('border', '1px solid #ccc');
|
||||
} else {
|
||||
errors.push( key );
|
||||
$el.css('border', '2px solid red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.errors = errors;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
resetComplete: function() {
|
||||
var $el = $(this.el);
|
||||
|
||||
$el.find('#password-reset-form').addClass('hidden');
|
||||
$el.find('.js-reset-success').removeClass('hidden');
|
||||
},
|
||||
|
||||
submitForm: function( event ) {
|
||||
var data = this.getFormData();
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if ( !this.errors.length ) {
|
||||
console.log('save me');
|
||||
this.model.set( data );
|
||||
this.model.save();
|
||||
this.toggleErrorMsg( false );
|
||||
} else {
|
||||
console.log('here are the errors ', this.errors);
|
||||
this.toggleErrorMsg( true );
|
||||
}
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
if ( show ) {
|
||||
this.$errors.removeClass('hidden');
|
||||
} else {
|
||||
this.$errors.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
validate: function( $el ) {
|
||||
return edx.utils.validate( $el );
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
157
lms/static/js/student_account/views/RegisterView.js
Normal file
157
lms/static/js/student_account/views/RegisterView.js
Normal file
@@ -0,0 +1,157 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.RegisterView = Backbone.View.extend({
|
||||
tagName: 'form',
|
||||
|
||||
el: '#register-form',
|
||||
|
||||
tpl: $('#register-tpl').html(),
|
||||
|
||||
fieldTpl: $('#form_field-tpl').html(),
|
||||
|
||||
events: {
|
||||
'click .js-register': 'submitForm'
|
||||
},
|
||||
|
||||
errors: [],
|
||||
|
||||
$form: {},
|
||||
|
||||
initialize: function() {
|
||||
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() {
|
||||
var $container = $(this.el);
|
||||
|
||||
this.$form = $container.find('form');
|
||||
this.$errors = $container.find('.error-msg');
|
||||
},
|
||||
|
||||
getInitialData: function() {
|
||||
var that = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
url: '/user_api/v1/account/registration/',
|
||||
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 ) {
|
||||
this.model = new edx.student.account.RegisterModel({
|
||||
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;
|
||||
console.log('buildForm ', data);
|
||||
for ( i=0; i<len; i++ ) {
|
||||
html.push( _.template( fieldTpl, $.extend( data[i], {
|
||||
form: 'register'
|
||||
}) ) );
|
||||
}
|
||||
|
||||
this.render( html.join('') );
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
|
||||
var obj = {},
|
||||
$form = this.$form,
|
||||
elements = $form[0].elements,
|
||||
i,
|
||||
len = elements.length,
|
||||
$el,
|
||||
key = '',
|
||||
errors = [];
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
|
||||
$el = $( elements[i] );
|
||||
key = $el.attr('name') || false;
|
||||
|
||||
if ( key ) {
|
||||
if ( this.validate( elements[i] ) ) {
|
||||
obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val();
|
||||
$el.css('border', '1px solid #ccc');
|
||||
} else {
|
||||
errors.push( key );
|
||||
$el.css('border', '2px solid red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.errors = errors;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
submitForm: function( event ) {
|
||||
var data = this.getFormData();
|
||||
|
||||
event.preventDefault();
|
||||
console.log(data);
|
||||
// console.log(this.model);
|
||||
|
||||
if ( !this.errors.length ) {
|
||||
console.log('save me');
|
||||
this.model.set( data );
|
||||
console.log(this.model);
|
||||
this.model.save();
|
||||
this.toggleErrorMsg( false );
|
||||
} else {
|
||||
console.log('here are the errors ', this.errors);
|
||||
this.toggleErrorMsg( true );
|
||||
}
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
if ( show ) {
|
||||
this.$errors.removeClass('hidden');
|
||||
} else {
|
||||
this.$errors.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
validate: function( $el ) {
|
||||
return edx.utils.validate( $el );
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
// libs and resets *do not edit*
|
||||
@import 'bourbon/bourbon'; // lib - bourbon
|
||||
@import "neat/neat"; // lib - Neat
|
||||
@import 'vendor/bi-app/bi-app-ltr'; // set the layout for left to right languages
|
||||
|
||||
// BASE *default edX offerings*
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
// libs and resets *do not edit*
|
||||
@import 'bourbon/bourbon'; // lib - bourbon
|
||||
@import "neat/neat"; // lib - Neat
|
||||
@import 'vendor/bi-app/bi-app-ltr'; // set the layout for left to right languages
|
||||
|
||||
|
||||
// BASE *default edX offerings*
|
||||
// ====================
|
||||
|
||||
@@ -44,6 +46,7 @@
|
||||
@import 'elements/system-feedback';
|
||||
|
||||
// base - specific views
|
||||
@import 'views/login-register';
|
||||
@import 'views/verification';
|
||||
@import 'views/shoppingcart';
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
// libs and resets *do not edit*
|
||||
@import 'bourbon/bourbon'; // lib - bourbon
|
||||
@import "neat/neat"; // lib - Neat
|
||||
@import 'vendor/bi-app/bi-app-ltr'; // set the layout for left to right languages
|
||||
|
||||
// BASE *default edX offerings*
|
||||
|
||||
31
lms/static/sass/views/_login-register.scss
Normal file
31
lms/static/sass/views/_login-register.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
// lms - views - login/register view
|
||||
// ====================
|
||||
.login-register{
|
||||
|
||||
@include span-columns(6);
|
||||
@include shift(3);
|
||||
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow:0 0 0 50px white inset;
|
||||
-webkit-text-fill-color: #333;
|
||||
}
|
||||
|
||||
input:-webkit-autofill:focus {
|
||||
-webkit-box-shadow: white, 0 0 0 50px white inset;
|
||||
-webkit-text-fill-color: #333;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-block,
|
||||
.desc {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.input-inline {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
}
|
||||
22
lms/templates/student_account/access.underscore
Normal file
22
lms/templates/student_account/access.underscore
Normal file
@@ -0,0 +1,22 @@
|
||||
<header class="js-login-register-header">
|
||||
<h1>Welcome!</h1>
|
||||
<p>Please log in to continue</p>
|
||||
</header>
|
||||
|
||||
<section class="form-type">
|
||||
<h2>
|
||||
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
|
||||
<label for"register-option">I am a new user</label>
|
||||
</h2>
|
||||
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden<% } %>"></div>
|
||||
</section>
|
||||
|
||||
<section class="form-type">
|
||||
<h2>
|
||||
<input type="radio" name="form" id="login-option" value="login" class="form-toggle" <% if ( mode === 'login' ) { %>checked<% } %>>
|
||||
<label for="login-option">I am a returning user with an edX account</label>
|
||||
</h2>
|
||||
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden<% } %>"></div>
|
||||
</section>
|
||||
|
||||
<div id="password-reset-wrapper"></div>
|
||||
41
lms/templates/student_account/form_field.underscore
Normal file
41
lms/templates/student_account/form_field.underscore
Normal file
@@ -0,0 +1,41 @@
|
||||
<p class="form-field">
|
||||
<% if ( type !== 'checkbox' ) { %>
|
||||
<label for="<%= form %>-<%= name %>">
|
||||
<%= label %>
|
||||
<% if ( required ) { %> *</label><% } %>
|
||||
</label>
|
||||
<% } %>
|
||||
|
||||
<% if( form === 'login' && name === 'password' ) { %>
|
||||
<a href="#" class="forgot-password">Forgot password?</a>
|
||||
<% } %>
|
||||
|
||||
<% if ( type === 'select' ) { %>
|
||||
<select id="<%= form %>-<%= name %>" name="<%= name %>" class="input-inline" aria-describedby="<%= form %>-<%= name %>-desc">
|
||||
<% _.each(options, function(el) { %>
|
||||
<option value="<%= el.value%>"><%= el.name %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
<% } else if ( type === 'textarea' ) { %>
|
||||
<textarea id="<%= form %>-<%= name %>" type="<%= type %>" name="<%= name %>" class="input-block" aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%= restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %>
|
||||
<% if ( required ) { %> required<% } %> >
|
||||
</textarea>
|
||||
<% } else { %>
|
||||
<input id="<%= form %>-<%= name %>" type="<%= type %>" name="<%= name %>" class="input-block" aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%= restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %>
|
||||
<% if ( required ) { %> required<% } %>
|
||||
/>
|
||||
<% } %>
|
||||
|
||||
<% if ( type === 'checkbox' ) { %>
|
||||
<label for="<%= form %>-<%= name %>">
|
||||
<%= label %>
|
||||
<% if ( required ) { %> *</label><% } %>
|
||||
</label>
|
||||
<% } %>
|
||||
|
||||
<span id="<%= form %>-<%= name %>-desc" class="desc"><%= instructions %></span>
|
||||
</p>
|
||||
12
lms/templates/student_account/login.underscore
Normal file
12
lms/templates/student_account/login.underscore
Normal file
@@ -0,0 +1,12 @@
|
||||
<form id="login">
|
||||
<div class="error-msg hidden">
|
||||
<h4>We couldn't log you in.</h4>
|
||||
<div class="errors">
|
||||
<p>Email or password is incorrent. <a href="#">Forgot password?</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<%= fields %>
|
||||
<button class="action action-primary action-update js-login">Log in</button>
|
||||
<button type="submit" class="button button-primary button-facebook"><span class="icon icon-facebook"></span>Sign in with Facebook</button>
|
||||
<button type="submit" class="button button-primary button-google"><span class="icon icon-google-plus"></span>Sign in with Google</button>
|
||||
</form>
|
||||
@@ -12,16 +12,13 @@
|
||||
</%block>
|
||||
|
||||
<%block name="header_extras">
|
||||
% for template_name in ["account"]:
|
||||
% for template_name in ["account", "access", "form_field", "login", "register", "password_reset"]:
|
||||
<script type="text/template" id="${template_name}-tpl">
|
||||
<%static:include path="student_account/${template_name}.underscore" />
|
||||
</script>
|
||||
% endfor
|
||||
</%block>
|
||||
|
||||
<h1>Login and Registration!</h1>
|
||||
|
||||
<p>This is a placeholder for the combined login and registration form</p>
|
||||
|
||||
## TODO: Use JavaScript to populate this div with
|
||||
## the actual registration/login forms (loaded asynchronously from the user API)
|
||||
@@ -47,6 +44,7 @@
|
||||
## Note that this list may be empty.
|
||||
##
|
||||
<div id="login-and-registration-container"
|
||||
class="login-register"
|
||||
data-initial-mode="${initial_mode}"
|
||||
data-third-party-auth-providers="${third_party_auth_providers}"
|
||||
/>
|
||||
|
||||
27
lms/templates/student_account/password_reset.underscore
Normal file
27
lms/templates/student_account/password_reset.underscore
Normal file
@@ -0,0 +1,27 @@
|
||||
<header>
|
||||
<h1>Password assistance</h1>
|
||||
</header>
|
||||
|
||||
<section class="form-type">
|
||||
<div id="password-reset-form" class="form-wrapper">
|
||||
<p>Please enter your email address below and we will send you instructions for setting a new password.</p>
|
||||
<form id="password-reset-form">
|
||||
<div class="error-msg hidden">
|
||||
<h4>An error occured.</h4>
|
||||
<div class="errors">
|
||||
<p>Please enter a valid email address</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= fields %>
|
||||
|
||||
<button class="action action-primary action-update js-reset">Reset my password</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="js-reset-success hidden">
|
||||
<h2>Password Reset Successful</h2>
|
||||
<p>We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly.</p>
|
||||
</div>
|
||||
</section>
|
||||
15
lms/templates/student_account/register.underscore
Normal file
15
lms/templates/student_account/register.underscore
Normal file
@@ -0,0 +1,15 @@
|
||||
<form id="register" autocomplete="off">
|
||||
<div class="error-msg hidden">
|
||||
<h4>An error occured in your registration.</h4>
|
||||
<div class="errors">
|
||||
<p>Please enter a valid password</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="button button-primary button-facebook"><span class="icon icon-facebook"></span>Sign up with Facebook</button>
|
||||
<button type="submit" class="button button-primary button-google"><span class="icon icon-google-plus"></span>Sign up with Google</button>
|
||||
<%= fields %>
|
||||
<input id="register-termsofservice" type="checkbox" name="termsofservice">
|
||||
<label for="register-termsofservice">I agree to the <a href="#">Terms of Service and Honor Code</a> *</label>
|
||||
<button class="action action-primary action-update js-register">Create My edX Account</button>
|
||||
</form>
|
||||
Reference in New Issue
Block a user