Redo team-based registration (#657)
For compatibility with referral campaign flows, re-implement team registration such that the team is selected through providing an email with a known team domain. The support email is now only shown when an email that _looks_ like a UK/US university email address, but is not known.
This commit is contained in:
parent
f462bd8f99
commit
d9a8acd431
2 changed files with 60 additions and 83 deletions
|
@ -90,6 +90,7 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
|
this._unmounted = false;
|
||||||
this.dispatcherRef = dis.register(this.onAction);
|
this.dispatcherRef = dis.register(this.onAction);
|
||||||
// attach this to the instance rather than this.state since it isn't UI
|
// attach this to the instance rather than this.state since it isn't UI
|
||||||
this.registerLogic = new Signup.Register(
|
this.registerLogic = new Signup.Register(
|
||||||
|
@ -107,6 +108,7 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
dis.unregister(this.dispatcherRef);
|
dis.unregister(this.dispatcherRef);
|
||||||
|
this._unmounted = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
|
@ -273,6 +275,14 @@ module.exports = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onTeamSelected: function(team) {
|
||||||
|
if (!this._unmounted) {
|
||||||
|
this.setState({
|
||||||
|
teamIcon: team ? team.icon : null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_getRegisterContentJsx: function() {
|
_getRegisterContentJsx: function() {
|
||||||
var currStep = this.registerLogic.getStep();
|
var currStep = this.registerLogic.getStep();
|
||||||
var registerStep;
|
var registerStep;
|
||||||
|
@ -293,7 +303,9 @@ module.exports = React.createClass({
|
||||||
guestUsername={this.props.username}
|
guestUsername={this.props.username}
|
||||||
minPasswordLength={MIN_PASSWORD_LENGTH}
|
minPasswordLength={MIN_PASSWORD_LENGTH}
|
||||||
onError={this.onFormValidationFailed}
|
onError={this.onFormValidationFailed}
|
||||||
onRegisterClick={this.onFormSubmit} />
|
onRegisterClick={this.onFormSubmit}
|
||||||
|
onTeamSelected={this.onTeamSelected}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "Register.STEP_m.login.email.identity":
|
case "Register.STEP_m.login.email.identity":
|
||||||
|
@ -367,7 +379,7 @@ module.exports = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div className="mx_Login">
|
<div className="mx_Login">
|
||||||
<div className="mx_Login_box">
|
<div className="mx_Login_box">
|
||||||
<LoginHeader />
|
<LoginHeader icon={this.state.teamIcon}/>
|
||||||
{this._getRegisterContentJsx()}
|
{this._getRegisterContentJsx()}
|
||||||
<LoginFooter />
|
<LoginFooter />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,8 +44,8 @@ module.exports = React.createClass({
|
||||||
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
teams: React.PropTypes.arrayOf(React.PropTypes.shape({
|
||||||
// The displayed name of the team
|
// The displayed name of the team
|
||||||
"name": React.PropTypes.string,
|
"name": React.PropTypes.string,
|
||||||
// The suffix with which every team email address ends
|
// The domain of team email addresses
|
||||||
"emailSuffix": React.PropTypes.string,
|
"domain": React.PropTypes.string,
|
||||||
})).required,
|
})).required,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -117,9 +117,6 @@ module.exports = React.createClass({
|
||||||
|
|
||||||
_doSubmit: function() {
|
_doSubmit: function() {
|
||||||
let email = this.refs.email.value.trim();
|
let email = this.refs.email.value.trim();
|
||||||
if (this.state.selectedTeam) {
|
|
||||||
email += "@" + this.state.selectedTeam.emailSuffix;
|
|
||||||
}
|
|
||||||
var promise = this.props.onRegisterClick({
|
var promise = this.props.onRegisterClick({
|
||||||
username: this.refs.username.value.trim() || this.props.guestUsername,
|
username: this.refs.username.value.trim() || this.props.guestUsername,
|
||||||
password: this.refs.password.value.trim(),
|
password: this.refs.password.value.trim(),
|
||||||
|
@ -134,25 +131,6 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onSelectTeam: function(teamIndex) {
|
|
||||||
let team = this._getSelectedTeam(teamIndex);
|
|
||||||
if (team) {
|
|
||||||
this.refs.email.value = this.refs.email.value.split("@")[0];
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
selectedTeam: team,
|
|
||||||
showSupportEmail: teamIndex === "other",
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_getSelectedTeam: function(teamIndex) {
|
|
||||||
if (this.props.teamsConfig &&
|
|
||||||
this.props.teamsConfig.teams[teamIndex]) {
|
|
||||||
return this.props.teamsConfig.teams[teamIndex];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if all fields were valid last time
|
* Returns true if all fields were valid last time
|
||||||
* they were validated.
|
* they were validated.
|
||||||
|
@ -167,20 +145,36 @@ module.exports = React.createClass({
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_isUniEmail: function(email) {
|
||||||
|
return email.endsWith('.ac.uk') || email.endsWith('.edu');
|
||||||
|
},
|
||||||
|
|
||||||
validateField: function(field_id) {
|
validateField: function(field_id) {
|
||||||
var pwd1 = this.refs.password.value.trim();
|
var pwd1 = this.refs.password.value.trim();
|
||||||
var pwd2 = this.refs.passwordConfirm.value.trim();
|
var pwd2 = this.refs.passwordConfirm.value.trim();
|
||||||
|
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case FIELD_EMAIL:
|
case FIELD_EMAIL:
|
||||||
let email = this.refs.email.value;
|
const email = this.refs.email.value;
|
||||||
if (this.props.teamsConfig) {
|
if (this.props.teamsConfig && this._isUniEmail(email)) {
|
||||||
let team = this.state.selectedTeam;
|
const matchingTeam = this.props.teamsConfig.teams.find(
|
||||||
if (team) {
|
(team) => {
|
||||||
email = email + "@" + team.emailSuffix;
|
return email.split('@').pop() === team.domain;
|
||||||
}
|
}
|
||||||
|
) || null;
|
||||||
|
this.setState({
|
||||||
|
selectedTeam: matchingTeam,
|
||||||
|
showSupportEmail: !matchingTeam,
|
||||||
|
});
|
||||||
|
this.props.onTeamSelected(matchingTeam);
|
||||||
|
} else {
|
||||||
|
this.props.onTeamSelected(null);
|
||||||
|
this.setState({
|
||||||
|
selectedTeam: null,
|
||||||
|
showSupportEmail: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
let valid = email === '' || Email.looksValid(email);
|
const valid = email === '' || Email.looksValid(email);
|
||||||
this.markFieldValid(field_id, valid, "RegistrationForm.ERR_EMAIL_INVALID");
|
this.markFieldValid(field_id, valid, "RegistrationForm.ERR_EMAIL_INVALID");
|
||||||
break;
|
break;
|
||||||
case FIELD_USERNAME:
|
case FIELD_USERNAME:
|
||||||
|
@ -260,61 +254,35 @@ module.exports = React.createClass({
|
||||||
return cls;
|
return cls;
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderEmailInputSuffix: function() {
|
|
||||||
let suffix = null;
|
|
||||||
if (!this.state.selectedTeam) {
|
|
||||||
return suffix;
|
|
||||||
}
|
|
||||||
let team = this.state.selectedTeam;
|
|
||||||
if (team) {
|
|
||||||
suffix = "@" + team.emailSuffix;
|
|
||||||
}
|
|
||||||
return suffix;
|
|
||||||
},
|
|
||||||
|
|
||||||
render: function() {
|
render: function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
var emailSection, teamSection, teamAdditionSupport, registerButton;
|
var emailSection, belowEmailSection, registerButton;
|
||||||
if (this.props.showEmail) {
|
if (this.props.showEmail) {
|
||||||
let emailSuffix = this._renderEmailInputSuffix();
|
|
||||||
emailSection = (
|
emailSection = (
|
||||||
<div>
|
|
||||||
<input type="text" ref="email"
|
<input type="text" ref="email"
|
||||||
autoFocus={true} placeholder="Email address (optional)"
|
autoFocus={true} placeholder="Email address (optional)"
|
||||||
defaultValue={this.props.defaultEmail}
|
defaultValue={this.props.defaultEmail}
|
||||||
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
className={this._classForField(FIELD_EMAIL, 'mx_Login_field')}
|
||||||
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
||||||
value={self.state.email}/>
|
value={self.state.email}/>
|
||||||
{emailSuffix ? <input className="mx_Login_field" value={emailSuffix} disabled/> : null }
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
if (this.props.teamsConfig) {
|
if (this.props.teamsConfig) {
|
||||||
teamSection = (
|
|
||||||
<select
|
|
||||||
defaultValue="-1"
|
|
||||||
className="mx_Login_field"
|
|
||||||
onBlur={function() {self.validateField(FIELD_EMAIL);}}
|
|
||||||
onChange={function(ev) {self.onSelectTeam(ev.target.value);}}
|
|
||||||
>
|
|
||||||
<option key="-1" value="-1">No team</option>
|
|
||||||
{this.props.teamsConfig.teams.map((t, index) => {
|
|
||||||
return (
|
|
||||||
<option key={index} value={index}>
|
|
||||||
{t.name}
|
|
||||||
</option>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<option key="-2" value="other">Other</option>
|
|
||||||
</select>
|
|
||||||
);
|
|
||||||
if (this.props.teamsConfig.supportEmail && this.state.showSupportEmail) {
|
if (this.props.teamsConfig.supportEmail && this.state.showSupportEmail) {
|
||||||
teamAdditionSupport = (
|
belowEmailSection = (
|
||||||
<span>
|
<p className="mx_Login_support">
|
||||||
If your team is not listed, email
|
Sorry, but your university is not registered with us just yet.
|
||||||
|
Email us on
|
||||||
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
<a href={"mailto:" + this.props.teamsConfig.supportEmail}>
|
||||||
{this.props.teamsConfig.supportEmail}
|
{this.props.teamsConfig.supportEmail}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
to get your university signed up. Or continue to register with Riot to enjoy our open source platform.
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
} else if (this.state.selectedTeam) {
|
||||||
|
belowEmailSection = (
|
||||||
|
<p className="mx_Login_support">
|
||||||
|
You are registering with {this.state.selectedTeam.name}
|
||||||
|
</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,11 +301,8 @@ module.exports = React.createClass({
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<form onSubmit={this.onSubmit}>
|
<form onSubmit={this.onSubmit}>
|
||||||
{teamSection}
|
|
||||||
{teamAdditionSupport}
|
|
||||||
<br />
|
|
||||||
{emailSection}
|
{emailSection}
|
||||||
<br />
|
{belowEmailSection}
|
||||||
<input type="text" ref="username"
|
<input type="text" ref="username"
|
||||||
placeholder={ placeholderUserName } defaultValue={this.props.defaultUsername}
|
placeholder={ placeholderUserName } defaultValue={this.props.defaultUsername}
|
||||||
className={this._classForField(FIELD_USERNAME, 'mx_Login_field')}
|
className={this._classForField(FIELD_USERNAME, 'mx_Login_field')}
|
||||||
|
|
Loading…
Reference in a new issue