Elbrus — Change Email Address Patch
To update an Elbrus implementation to give users the ability to change their email address, you’ll need to modify and add the files as detailed below.
Important:
This addition requires changes to templates, views, JavaScript, and SSP application files. Test changes thoroughly against your existing customizations before deploying to your published domain.
Modify CheckoutApplication/SuiteScript/checkout.ssp
Replace
var SiteSettings
, parameters
, siteType
, Environment
, Language
, Currency
, Error
, login
, order
, session
, Application
, environmentParameters
;
With
var SiteSettings
, parameters
, siteType
, Environment
, Language
, Currency
, Error
, login
, order
, session
, Application
, environmentParameters
, password_reset_expired
;
Replace
if (session.isChangePasswordRequest())
{
parameters.fragment = 'reset-password';
login = true;
}
With
if (parameters.passwdret)
{
try
{
if (session.isChangePasswordRequest())
{
parameters.fragment = 'reset-password';
login = true;
}
}
catch (e)
{
password_reset_expired = true;
}
}
Replace
<% if (Error) { %>
<script>SC.ENVIRONMENT.contextError = <%= JSON.stringify(Error) %>;</script>
<% } %>
With
<% if (Error) { %>
<script>SC.ENVIRONMENT.contextError = <%= JSON.stringify(Error) %>;</script>
<% } %>
<% if (parameters.key) { %>
<script>SC.ENVIRONMENT.email_verification_error = true;</script>
<% } else if (password_reset_expired) { %>
<script>SC.ENVIRONMENT.password_reset_expired_error = true;</script>
<% } else if (parameters.passwdret && parameters.fragment !== 'reset-password') { %>
<script>SC.ENVIRONMENT.password_reset_invalid_error = true;</script>
<% } %>
Modify LoginRegister/Javascript/LoginRegister.View.js
Replace
define('LoginRegister.View'
, [ 'login_register.tpl'
, 'Profile.Model'
, 'LoginRegister.Login.View'
, 'LoginRegister.Register.View'
, 'LoginRegister.CheckoutAsGuest.View'
, 'Backbone.CompositeView'
, 'SC.Configuration'
, 'Header.Simplified.View'
, 'Footer.Simplified.View'
, 'Backbone'
, 'underscore'
, 'Utils'
]
, function (
login_register_tpl
, ProfileModel
, LoginView
, RegisterView
, CheckoutAsGuestView
, BackboneCompositeView
, Configuration
, HeaderSimplifiedView
, FooterSimplifiedView
, Backbone
, _
, Utils
)
With
define('LoginRegister.View'
, [ 'login_register.tpl'
, 'GlobalViews.Message.View'
, 'Profile.Model'
, 'LoginRegister.Login.View'
, 'LoginRegister.Register.View'
, 'LoginRegister.CheckoutAsGuest.View'
, 'Backbone.CompositeView'
, 'SC.Configuration'
, 'Header.Simplified.View'
, 'Footer.Simplified.View'
, 'Backbone'
, 'underscore'
, 'Utils'
]
, function (
login_register_tpl
, GlobalViewsMessageView
, ProfileModel
, LoginView
, RegisterView
, CheckoutAsGuestView
, BackboneCompositeView
, Configuration
, HeaderSimplifiedView
, FooterSimplifiedView
, Backbone
, _
, Utils
)
Replace
this.enableCheckoutAsGuest = is_checking_out && profile_model.get('isLoggedIn') === 'F' &&
(Configuration.getRegistrationType() === 'optional' || Configuration.getRegistrationType() === 'disabled');
BackboneCompositeView.add(this);
With
this.enableCheckoutAsGuest = is_checking_out && profile_model.get('isLoggedIn') === 'F' &&
(Configuration.getRegistrationType() === 'optional' || Configuration.getRegistrationType() === 'disabled');
if (SC.ENVIRONMENT.email_verification_error)
{
this.message = _('The validation process has failed. Please login into your account and click on the validation link again.').translate();
delete SC.ENVIRONMENT.email_verification_error;
}
else if (SC.ENVIRONMENT.password_reset_invalid_error)
{
this.message = _('Your reset password link is invalid. Request a new one using the Forgot Password link.').translate();
delete SC.ENVIRONMENT.password_reset_invalid_error;
}
else if (SC.ENVIRONMENT.password_reset_expired_error)
{
this.message = _('Your reset password link has expired. Request a new one using the Forgot Password link.').translate();
delete SC.ENVIRONMENT.password_reset_expired_error;
}
BackboneCompositeView.add(this);
Replace
, 'Register': function ()
{
return new RegisterView(this.child_view_options);
}
}
With
{
return new RegisterView(this.child_view_options);
}
, 'Messages': function ()
{
if (this.message)
{
return new GlobalViewsMessageView({
message: this.message
, type: 'error'
, closable: true
});
}
}
}
Modify LoginRegister/Templates/login_register.tpl
Replace
<header class="login-register-header">
{{#if showRegister}}
<h1 class="login-register-title"> {{translate 'Log in | Register'}}</h1>
{{else}}
<h1 class="login-register-title"> {{translate 'Log in'}}</h1>
{{/if}}
</header>
With
<header class="login-register-header">
{{#if showRegister}}
<h1 class="login-register-title"> {{translate 'Log in | Register'}}</h1>
{{else}}
<h1 class="login-register-title"> {{translate 'Log in'}}</h1>
{{/if}}
</header>
<div data-view="Messages"></div>
Modify MyAccountApplication/SuiteScript/my_account.ssp
Replace
<%
var SiteSettings
, siteType
, Environment
, Language
, Currency
, Error
, Application
, environmentParameters
, session
, parameters
, external_payment
;
try
{
SiteSettings = require('SiteSettings.Model').get();
parameters = request.getAllParameters();
session = require('SC.Models.Init').session;
// Access control, if you are not loged this will send you to the log in page
if (!session.isLoggedIn2() || session.getCustomer().isGuest())
{
delete parameters.sitepath;
parameters.origin = 'customercenter';
if (parameters.fragment)
{
parameters.origin_hash = parameters.fragment;
delete parameters.fragment;
}
return nlapiSetRedirectURL('EXTERNAL', SiteSettings.touchpoints.login, null, false, parameters);
}
Application = require('Application');
Environment = Application.getEnvironment(request);
environmentParameters = [];
siteType = SiteSettings.sitetype;
Language = Environment.currentLanguage && Environment.currentLanguage.locale || '';
Currency = Environment.currencyCodeSpecifiedOnUrl;
environmentParameters.push('lang=' + Language);
environmentParameters.push('cur=' + Currency);
environmentParameters.push('X-SC-Touchpoint=myaccount');
_.each(require('ExternalPayment.Model').getParametersFromRequest(request), function(value, key) {
environmentParameters.push(key.concat('=', value));
});
}
catch (e)
{
Error = Application.processError(e);
}
%>
With
<%
var SiteSettings
, siteType
, Environment
, Language
, Currency
, Error
, Application
, environmentParameters
, session
, parameters
, external_payment
, email_change_verification
;
try
{
Application = require('Application');
Environment = Application.getEnvironment(request);
environmentParameters = [];
SiteSettings = require('SiteSettings.Model').get();
parameters = request.getAllParameters();
session = require('SC.Models.Init').session;
// Access control, if you are not loged this will send you to the log in page
if (!session.isLoggedIn2() || session.getCustomer().isGuest())
{
delete parameters.sitepath;
parameters.origin = 'customercenter';
if (parameters.fragment)
{
parameters.origin_hash = parameters.fragment;
delete parameters.fragment;
}
return nlapiSetRedirectURL('EXTERNAL', SiteSettings.touchpoints.login, null, false, parameters);
}
else if (session.isLoggedIn2() && parameters.key)
{
try
{
session.verifyEmailChange(parameters.key)
email_change_verification = true;
}
catch (e)
{
email_change_verification = e.details;
}
}
siteType = SiteSettings.sitetype;
Language = Environment.currentLanguage && Environment.currentLanguage.locale || '';
Currency = Environment.currencyCodeSpecifiedOnUrl;
environmentParameters.push('lang=' + Language);
environmentParameters.push('cur=' + Currency);
environmentParameters.push('X-SC-Touchpoint=myaccount');
_.each(require('ExternalPayment.Model').getParametersFromRequest(request), function(value, key) {
environmentParameters.push(key.concat('=', value));
});
}
catch (e)
{
Error = Application.processError(e);
}
%>
Replace
<% if (Error) { %>
<script>SC.ENVIRONMENT.contextError = <%= JSON.stringify(Error) %>;</script>
<% } %>
With
<% if (Error) { %>
<script>SC.ENVIRONMENT.contextError = <%= JSON.stringify(Error) %>;</script>
<% } %>
<% if (email_change_verification) { %>
<script>SC.SESSION.email_change_verification = '<%= email_change_verification %>';</script>
<% } %>
Modify Overview/Javascript/Overview.Home.View.js
Replace
define('Overview.Home.View'
, [
'SC.Configuration'
, 'Overview.Banner.View'
, 'Overview.Profile.View'
, 'Overview.Payment.View'
, 'Overview.Shipping.View'
, 'Backbone.CollectionView'
, 'OrderHistory.List.Tracking.Number.View'
, 'RecordViews.View'
, 'Handlebars'
, 'overview_home.tpl'
, 'Backbone'
, 'Backbone.CompositeView'
, 'underscore'
, 'Utils'
]
, function(
Configuration
, OverviewBannerView
, OverviewProfileView
, OverviewPaymentView
, OverviewShippingView
, BackboneCollectionView
, OrderHistoryListTrackingNumberView
, RecordViewsView
, Handlebars
, overview_home_tpl
, Backbone
, BackboneCompositeView
, _
)
With
define('Overview.Home.View'
, [
'SC.Configuration'
, 'GlobalViews.Message.View'
, 'Overview.Banner.View'
, 'Overview.Profile.View'
, 'Overview.Payment.View'
, 'Overview.Shipping.View'
, 'Backbone.CollectionView'
, 'OrderHistory.List.Tracking.Number.View'
, 'RecordViews.View'
, 'Handlebars'
, 'overview_home.tpl'
, 'Backbone'
, 'Backbone.CompositeView'
, 'underscore'
, 'Utils'
]
, function(
Configuration
, GlobalViewsMessageView
, OverviewBannerView
, OverviewProfileView
, OverviewPaymentView
, OverviewShippingView
, BackboneCollectionView
, OrderHistoryListTrackingNumberView
, RecordViewsView
, Handlebars
, overview_home_tpl
, Backbone
, BackboneCompositeView
, _
)
Replace
this.creditcards.on('reset destroy change add', this.showContent, this);
}
With
this.creditcards.on('reset destroy change add', this.showContent, this);
if (SC.SESSION.email_change_verification)
{
this.email_change_verification = SC.SESSION.email_change_verification;
delete SC.SESSION.email_change_verification;
}
}
Replace
, 'Overview.Shipping': function()
{
return new OverviewShippingView({ model: this.defaultShippingAddress });
}
With
, 'Overview.Shipping': function()
{
return new OverviewShippingView({ model: this.defaultShippingAddress });
}
, 'Overview.Messages': function ()
{
if (this.email_change_verification)
{
return new GlobalViewsMessageView({
message: this.email_change_verification === 'true' ? _('Your email has been changed successfully to <strong>').translate() + this.model.get('email') + '</strong>' : this.email_change_verification
, type: this.email_change_verification === 'true' ? 'success' : 'error'
, closable: true
});
}
}
Modify Overview/Templates/overview_home.tpl
Replace
<section class="overview-home">
<div class="overview-home-orders" data-permissions="{{purchasesPermissions}}">
With
<section class="overview-home">
<div data-view="Overview.Messages"></div>
<div class="overview-home-orders" data-permissions="{{purchasesPermissions}}">
Add Profile/Javascript/Profile.ChangeEmailAddress.Model.js
// Profile.ChangeEmailAddress.Model.js
// ===================================--
// View Model for changing user's email
// @module Profile
define(
'Profile.ChangeEmailAddress.Model'
, [
'Backbone'
, 'underscore'
, 'Utils'
]
, function (
Backbone
, _
)
{
'use strict';
// @class Profile.ChangeEmailAddress.Model @extends Backbone.Model
return Backbone.Model.extend(
{
urlRoot: 'services/Profile.Service.ss'
, validation: {
current_password: { required: true, msg: _('Current password is required').translate() }
, confirm_email: [
{ required: true, msg: _('Confirm Email is required').translate() }
, { equalTo: 'new_email', msg: _('New Email and Confirm New Email do not match').translate() }
]
, new_email: { required: true, msg: _('New Email is required').translate() }
}
});
});
Add Profile/Javascript/Profile.ChangeEmailAddress.View.js
// @module Profile
define(
'Profile.ChangeEmailAddress.View'
, [
'GlobalViews.Message.View'
, 'Backbone.FormView'
, 'SC.Configuration'
, 'profile_change_email.tpl'
, 'Backbone'
, 'underscore'
, 'Utils'
]
, function (
GlobalViewsMessageView
, BackboneFormView
, Configuration
, profile_change_email_tpl
, Backbone
, _
)
{
'use strict';
// @class Profile.ChangeEmailAddress.View @extends Backbone.View
return Backbone.View.extend({
template: profile_change_email_tpl
, page_header: _('Change Email').translate()
, title: _('Change Email').translate()
, events: {
'submit form': 'saveFormCustom'
}
, bindings: {
'[name="current_password"]': 'current_password'
, '[name="new_email"]': 'new_email'
, '[name="confirm_email"]': 'confirm_email'
}
, initialize: function()
{
Backbone.View.prototype.initialize.apply(this, arguments);
BackboneFormView.add(this);
}
, saveFormCustom: function ()
{
this.new_email = this.$('[name="new_email"]').val();
BackboneFormView.saveForm.apply(this, arguments);
}
, showSuccess: function (placeholder)
{
var global_view_message = new GlobalViewsMessageView({
message: _('A confirmation email has been sent to <strong>').translate() + this.new_email + '</strong>'
, type: 'success'
, closable: true
});
placeholder.html(global_view_message.render().$el.html());
}
});
});
Modify Profile/Javascript/Profile.Information.View.js
Replace
define(
'Profile.Information.View'
, [
'SC.Configuration'
, 'GlobalViews.Message.View'
, 'Backbone.FormView'
, 'profile_information.tpl'
, 'Backbone'
, 'underscore'
, 'jQuery'
, 'Utils'
]
, function (
Configuration
, GlobalViewsMessageView
, BackboneFormView
, profile_information_tpl
, Backbone
, _
, jQuery
)
{
'use strict';
// @class Profile.Information.View @extends Backbone.View
return Backbone.View.extend({
template: profile_information_tpl
, page_header: _('Profile Information').translate()
, title: _('Profile Information').translate()
, attributes: {'class': 'ProfileInformationView'}
, events: {
'submit form': 'saveForm'
, 'change input[data-type="phone"]': 'formatPhone'
}
, bindings: {
'[name="firstname"]': 'firstname'
, '[name="lastname"]': 'lastname'
, '[name="companyname"]': 'companyname'
, '[name="phone"]': 'phone'
}
, initialize: function()
{
BackboneFormView.add(this);
}
, formatPhone: function (e)
{
var $target = jQuery(e.target);
$target.val(_($target.val()).formatPhone());
}
, showSuccess: function ()
With
define(
'Profile.Information.View'
, [
'SC.Configuration'
, 'GlobalViews.Message.View'
, 'Backbone.FormView'
, 'Profile.ChangeEmailAddress.Model'
, 'Profile.ChangeEmailAddress.View'
, 'profile_information.tpl'
, 'Backbone'
, 'underscore'
, 'jQuery'
, 'Utils'
]
, function (
Configuration
, GlobalViewsMessageView
, BackboneFormView
, ProfileChangeEmailModel
, ProfileChangeEmailView
, profile_information_tpl
, Backbone
, _
, jQuery
)
{
'use strict';
// @class Profile.Information.View @extends Backbone.View
return Backbone.View.extend({
template: profile_information_tpl
, page_header: _('Profile Information').translate()
, title: _('Profile Information').translate()
, attributes: {'class': 'ProfileInformationView'}
, events: {
'submit form': 'saveForm'
, 'change input[data-type="phone"]': 'formatPhone'
, 'click [data-action="change-email"]': 'changeEmail'
}
, bindings: {
'[name="firstname"]': 'firstname'
, '[name="lastname"]': 'lastname'
, '[name="companyname"]': 'companyname'
, '[name="phone"]': 'phone'
}
, initialize: function(options)
{
BackboneFormView.add(this);
this.application = options.application;
}
, formatPhone: function (e)
{
var $target = jQuery(e.target);
$target.val(_($target.val()).formatPhone());
}
, changeEmail: function ()
{
var model = new ProfileChangeEmailModel(this.model.attributes);
var view = new ProfileChangeEmailView({
application: this.application
, model: model
});
var self = this;
model.on('save', function () {
view.showSuccess(self.$('[data-type="alert-placeholder"]'));
});
view.useLayoutError = true;
this.application.getLayout().showInModal(view);
}
, showSuccess: function ()
Add Profile/Sass/_profile-change-email.scss
.profile-change-email-button-back {
@extend .button-back;
}
.profile-change-email-button-back-icon {
@extend .button-back-icon;
}
.profile-change-email-form-label {
display: inline-block;
}
.profile-change-email-form-group-label-required {
@extend .input-required;
}
.profile-change-email {
@extend .address-edit;
}
.profile-change-email-form-title {}
.profile-change-email-form-area {}
.profile-change-email-form {
margin-top: $sc-base-margin * 3;
}
.profile-change-email-form-group,
.profile-change-email-form-actions {
@extend .control-group;
}
.profile-change-email-form-group-label {
@extend .input-label
}
.profile-change-email-form-group-label-required {
}
.profile-change-email-form-group-input {
@extend .input-large
}
.profile-change-email-form-actions-change {
@extend .button-primary;
@extend .button-medium;
}
.profile-change-email-group-form-controls{}
.profile-change-email-form-info-block{}
Modify Profile/SuiteScript/Profile.Model.js
Replace
if (data.email && data.email !== this.currentSettings.email && data.email === data.confirm_email)
{
if(data.isGuest === 'T')
{
customerUpdate.email = data.email;
}
else
{
login.changeEmail(data.current_password, data.email, true);
}
}
With
if (data.email && data.email !== this.currentSettings.email && data.email === data.confirm_email && data.isGuest === 'T')
{
customerUpdate.email = data.email;
}
else if (data.new_email && data.new_email === data.confirm_email && data.new_email !== this.currentSettings.email)
{
ModelsInit.session.login({
email: data.email
, password: data.current_password
});
login.changeEmail(data.current_password, data.new_email, true);
}
Add Profile/Templates/profile_change_email.tpl
<section class="profile-change-email">
<div data-type="alert-placeholder"></div>
<div class="profile-change-email-form-area">
<form class="profile-change-email-form">
<fieldset>
<small class="profile-change-email-form-label">{{translate 'Required'}} <span class="profile-change-email-form-group-label-required">*</span></small>
<div class="profile-change-email-form-group" data-input="new_email" data-validation="control-group">
<label class="profile-change-email-form-group-label" for="new_email">{{translate 'New Email'}} <span class="profile-change-email-form-group-label-required">*</span></label>
<div class="profile-change-email-group-form-controls" data-validation="control">
<input type="email" class="profile-change-email-form-group-input" id="new_email" name="new_email" value="" placeholder="{{translate 'your@example.com'}}">
</div>
</div>
<div class="profile-change-email-form-group" data-input="confirm_email" data-validation="control-group">
<label class="profile-change-email-form-group-label" for="confirm_email">{{translate 'Confirm New Email'}} <span class="profile-change-email-form-group-label-required">*</span></label>
<div class="profile-change-email-group-form-controls" data-validation="control">
<input type="email" class="profile-change-email-form-group-input" id="confirm_email" name="confirm_email" value="" placeholder="{{translate 'your@example.com'}}">
</div>
</div>
<div class="profile-change-email-form-group" data-input="current_email" data-validation="control-group">
<label class="profile-change-email-form-group-label" for="current_password">{{translate 'Password'}} <span class="profile-change-email-form-group-label-required">*</span></label>
<div class="profile-change-email-group-form-controls" data-validation="control">
<input type="password" class="profile-change-email-form-group-input" id="current_password" name="current_password" value="">
</div>
</div>
</fieldset>
<p class="profile-change-email-form-info-block"><small> {{translate 'You will still be able to login with your current email address and password until your new email address is verified.'}} </small></p>
<div class="profile-change-email-form-actions">
<button type="submit" class="profile-change-email-form-actions-change">{{translate 'Send Verification Email'}}</button>
</div>
</form>
</div>
</section>
Modify Profile/Templates/profile_information.tpl
Replace
<p class="profile-information-input-email" id="email">{{email}}</p>
With
<p class="profile-information-input-email" id="email">{{email}} | <a class="profile-information-change-email-address" data-action="change-email">{{translate 'Change Address'}}</a></p>