-
Zaman Afzal authoredUnverifiedf20a064a
AccessView.js 14.86 KiB
(function(define) {
'use strict';
define([
'jquery',
'utility',
'underscore',
'underscore.string',
'backbone',
'js/student_account/models/LoginModel',
'js/student_account/models/PasswordResetModel',
'js/student_account/models/RegisterModel',
'js/student_account/models/AccountRecoveryModel',
'js/student_account/views/LoginView',
'js/student_account/views/PasswordResetView',
'js/student_account/views/RegisterView',
'js/student_account/views/InstitutionLoginView',
'js/student_account/views/HintedLoginView',
'edx-ui-toolkit/js/utils/html-utils',
'js/student_account/multiple_enterprise',
'js/vendor/history'
],
function($, utility, _, _s, Backbone, LoginModel, PasswordResetModel, RegisterModel, AccountRecoveryModel,
LoginView, PasswordResetView, RegisterView, InstitutionLoginView, HintedLoginView, HtmlUtils,
multipleEnterpriseInterface) {
return Backbone.View.extend({
tpl: '#access-tpl',
events: {
'click .form-toggle': 'toggleForm'
},
subview: {
login: {},
register: {},
passwordHelp: {},
accountRecoveryHelp: {},
institutionLogin: {},
hintedLogin: {}
},
nextUrl: '/dashboard',
// The form currently loaded
activeForm: '',
initialize: function(options) {
/* Mix non-conflicting functions from underscore.string
* (all but include, contains, and reverse) into the
* Underscore namespace
*/
_.mixin(_s.exports());
this.tpl = $(this.tpl).html();
this.activeForm = options.initial_mode || 'login';
this.thirdPartyAuth = options.third_party_auth || {
currentProvider: null,
providers: []
};
this.thirdPartyAuthHint = options.third_party_auth_hint || null;
// Account activation messages
this.accountActivationMessages = options.account_activation_messages || [];
this.accountRecoveryMessages = options.account_recovery_messages || [];
if (options.login_redirect_url) {
this.nextUrl = options.login_redirect_url;
}
this.formDescriptions = {
login: options.login_form_desc,
register: options.registration_form_desc,
reset: options.password_reset_form_desc,
institution_login: null,
hinted_login: null
};
this.platformName = options.platform_name;
this.supportURL = options.support_link;
this.passwordResetSupportUrl = options.password_reset_support_link;
this.createAccountOption = options.account_creation_allowed;
this.hideAuthWarnings = options.hide_auth_warnings || false;
this.pipelineUserDetails = options.third_party_auth.pipeline_user_details;
this.enterpriseName = options.enterprise_name || '';
this.isAccountRecoveryFeatureEnabled = options.is_account_recovery_feature_enabled || false;
this.isMultipleUserEnterprisesFeatureEnabled =
options.is_multiple_user_enterprises_feature_enabled || false;
// The login view listens for 'sync' events from the reset model
this.resetModel = new PasswordResetModel({}, {
method: 'GET',
url: '#'
});
this.accountRecoveryModel = new AccountRecoveryModel({}, {
method: 'GET',
url: '#'
});
this.render();
// Once the third party error message has been shown once,
// there is no need to show it again, if the user changes mode:
this.thirdPartyAuth.errorMessage = null;
// Once the account activation/account recovery messages have been shown once,
// there is no need to show it again, if the user changes mode:
this.accountActivationMessages = [];
this.accountRecoveryMessages = [];
},
render: function() {
HtmlUtils.setHtml(
$(this.el),
HtmlUtils.HTML(
_.template(this.tpl)({
mode: this.activeForm
})
)
)
this.postRender();
return this;
},
postRender: function() {
// get & check current url hash part & load form accordingly
if (Backbone.history.getHash() === 'forgot-password-modal') {
this.resetPassword();
}
this.loadForm(this.activeForm);
},
loadForm: function(type) {
var loadFunc = _.bind(this.load[type], this);
loadFunc(this.formDescriptions[type]);
},
load: {
login: function(data) {
var model = new LoginModel({}, {
method: data.method,
url: data.submit_url
});
var isTpaSaml = this.thirdPartyAuth && this.thirdPartyAuth.finishAuthUrl ?
this.thirdPartyAuth.finishAuthUrl.indexOf('tpa-saml') >= 0 : false;
this.subview.login = new LoginView({
fields: data.fields,
model: model,
resetModel: this.resetModel,
accountRecoveryModel: this.accountRecoveryModel,
thirdPartyAuth: this.thirdPartyAuth,
accountActivationMessages: this.accountActivationMessages,
accountRecoveryMessages: this.accountRecoveryMessages,
platformName: this.platformName,
supportURL: this.supportURL,
passwordResetSupportUrl: this.passwordResetSupportUrl,
createAccountOption: this.createAccountOption,
hideAuthWarnings: this.hideAuthWarnings,
pipelineUserDetails: this.pipelineUserDetails,
enterpriseName: this.enterpriseName
});
// Listen for 'password-help' event to toggle sub-views
this.listenTo(this.subview.login, 'password-help', this.resetPassword);
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
if (this.isMultipleUserEnterprisesFeatureEnabled === true && !isTpaSaml) {
this.listenTo(this.subview.login, 'auth-complete', this.loginComplete);
} else {
this.listenTo(this.subview.login, 'auth-complete', this.authComplete);
}
},
reset: function(data) {
this.resetModel.ajaxType = data.method;
this.resetModel.urlRoot = data.submit_url;
this.subview.passwordHelp = new PasswordResetView({
fields: data.fields,
model: this.resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
this.listenTo(this.subview.passwordHelp, 'password-email-sent', this.passwordEmailSent);
// Focus on the form
$('.password-reset-form').focus();
},
register: function(data) {
var model = new RegisterModel({}, {
method: data.method,
url: data.submit_url
});
this.subview.register = new RegisterView({
fields: data.fields,
model: model,
thirdPartyAuth: this.thirdPartyAuth,
platformName: this.platformName,
hideAuthWarnings: this.hideAuthWarnings
});
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this.listenTo(this.subview.register, 'auth-complete', this.authComplete);
},
institution_login: function(unused) {
this.subview.institutionLogin = new InstitutionLoginView({
thirdPartyAuth: this.thirdPartyAuth,
platformName: this.platformName,
mode: this.activeForm
});
this.subview.institutionLogin.render();
},
hinted_login: function(unused) {
this.subview.hintedLogin = new HintedLoginView({
thirdPartyAuth: this.thirdPartyAuth,
hintedProvider: this.thirdPartyAuthHint,
platformName: this.platformName
});
this.subview.hintedLogin.render();
}
},
passwordEmailSent: function() {
var $loginAnchorElement = $('#login-anchor');
this.element.hide($(this.el).find('#password-reset-anchor'));
this.element.show($loginAnchorElement);
this.element.scrollTop($loginAnchorElement);
},
resetPassword: function() {
window.analytics.track('edx.bi.password_reset_form.viewed', {
category: 'user-engagement'
});
this.element.hide($(this.el).find('#login-anchor'));
this.loadForm('reset');
this.element.scrollTop($('#password-reset-anchor'));
},
toggleForm: function(e) {
var type = $(e.currentTarget).data('type'),
$form = $('#' + type + '-form'),
scrollX = window.scrollX,
scrollY = window.scrollY,
queryParams = url('?'),
queryStr = queryParams.length > 0 ? '?' + queryParams : '';
e.preventDefault();
window.analytics.track('edx.bi.' + type + '_form.toggled', {
category: 'user-engagement'
});
// Load the form. Institution login is always refreshed since it changes based on the previous form.
if (!this.form.isLoaded($form) || type == 'institution_login') {
this.loadForm(type);
}
this.activeForm = type;
this.element.hide($(this.el).find('.submission-success'));
this.element.hide($(this.el).find('.form-wrapper'));
this.element.show($form);
// Update url without reloading page
if (type != 'institution_login') {
History.pushState(null, document.title, '/' + type + queryStr);
}
analytics.page('login_and_registration', type);
// Focus on the form
$('#' + type).focus();
// Maintain original scroll position
window.scrollTo(scrollX, scrollY);
},
/**
* Once authentication has completed successfully:
*
* If we're in a third party auth pipeline, we must complete the pipeline.
* Otherwise, redirect to the specified next step.
*
*/
authComplete: function() {
if (this.thirdPartyAuth && this.thirdPartyAuth.finishAuthUrl) {
this.redirect(this.thirdPartyAuth.finishAuthUrl);
// Note: the third party auth URL likely contains another redirect URL embedded inside
} else {
this.redirect(this.nextUrl);
}
},
/**
/**
* Take a learner attached to multiple enterprises to the enterprise selection page:
*
*/
loginComplete: function() {
if (this.thirdPartyAuth && this.thirdPartyAuth.finishAuthUrl) {
multipleEnterpriseInterface.check(this.thirdPartyAuth.finishAuthUrl);
// Note: the third party auth URL likely contains another redirect URL embedded inside
} else {
multipleEnterpriseInterface.check(this.nextUrl);
}
},
/**
* Redirect to a URL. Mainly useful for mocking out in tests.
* @param {string} url The URL to redirect to.
*/
redirect: function(url) {
window.location.replace(url);
},
form: {
isLoaded: function($form) {
return $form.html().length > 0;
}
},
/* Helper method to toggle display
* including accessibility considerations
*/
element: {
hide: function($el) {
$el.addClass('hidden');
},
scrollTop: function($el) {
// Scroll to top of selected element
$('html,body').animate({
scrollTop: $el.offset().top
}, 'slow');
},
show: function($el) {
$el.removeClass('hidden');
}
}
});
});
}).call(this, define || RequireJS.define);