mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-27 01:25:52 -05:00
Merge pull request #803 from mewtaylor/issue/gh-683
Fix GH-[683,705,712,797]: Updates to registration UX for teachers
This commit is contained in:
commit
606e3600ba
4 changed files with 67 additions and 35 deletions
|
@ -1,13 +1,15 @@
|
|||
var classNames = require('classnames');
|
||||
var React = require('react');
|
||||
var FormsyMixin = require('formsy-react').Mixin;
|
||||
var ReactPhoneInput = require('react-telephone-input/lib/withStyles');
|
||||
var allCountries = require('react-telephone-input/lib/country_data').allCountries;
|
||||
var defaultValidationHOC = require('./validations.jsx').defaultValidationHOC;
|
||||
var validationHOCFactory = require('./validations.jsx').validationHOCFactory;
|
||||
var Row = require('formsy-react-components').Row;
|
||||
var classNames = require('classnames');
|
||||
var ComponentMixin = require('formsy-react-components').ComponentMixin;
|
||||
var FormsyMixin = require('formsy-react').Mixin;
|
||||
var React = require('react');
|
||||
var ReactPhoneInput = require('react-telephone-input/lib/withStyles');
|
||||
var Row = require('formsy-react-components').Row;
|
||||
|
||||
var defaultValidationHOC = require('./validations.jsx').defaultValidationHOC;
|
||||
var inputHOC = require('./input-hoc.jsx');
|
||||
var intl = require('../../lib/intl.jsx');
|
||||
var validationHOCFactory = require('./validations.jsx').validationHOCFactory;
|
||||
|
||||
var allIso2 = allCountries.map(function (country) {return country.iso2;});
|
||||
|
||||
|
@ -23,7 +25,8 @@ var PhoneInput = React.createClass({
|
|||
getDefaultProps: function () {
|
||||
return {
|
||||
validations: {
|
||||
isPhone: true
|
||||
isPhone: true,
|
||||
phoneLength: true
|
||||
},
|
||||
flagsImagePath: '/images/flags.png',
|
||||
defaultCountry: 'us'
|
||||
|
@ -62,7 +65,8 @@ var PhoneInput = React.createClass({
|
|||
});
|
||||
|
||||
var phoneValidationHOC = validationHOCFactory({
|
||||
isPhone: 'Please enter a valid phone number'
|
||||
isPhone: <intl.FormattedMessage id="teacherRegistration.validationPhoneNumber" />,
|
||||
phoneLength: <intl.FormattedMessage id="teacherRegistration.validationPhoneNumber" />
|
||||
});
|
||||
|
||||
module.exports = inputHOC(defaultValidationHOC(phoneValidationHOC(PhoneInput)));
|
||||
|
|
|
@ -21,6 +21,14 @@ module.exports.validations = {
|
|||
return false;
|
||||
}
|
||||
return phoneNumberUtil.isValidNumber(parsed);
|
||||
},
|
||||
phoneLength: function (values, value) {
|
||||
if (typeof value === 'undefined') return true;
|
||||
if (value && value.national_number === '+') return true;
|
||||
if (value && value.national_number.length === value.country_code.format.length) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -82,38 +82,55 @@ module.exports = {
|
|||
onChangeShowPassword: function (field, value) {
|
||||
this.setState({showPassword: value});
|
||||
},
|
||||
onValidSubmit: function (formData, reset, invalidate) {
|
||||
this.setState({waiting: true});
|
||||
validateUsername: function (username, callback) {
|
||||
callback = callback || function () {};
|
||||
api({
|
||||
host: '',
|
||||
uri: '/accounts/check_username/' + formData.user.username + '/'
|
||||
}, function (err, res) {
|
||||
uri: '/accounts/check_username/' + username + '/'
|
||||
}, function (err, body, res) {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
this.setState({waiting: false});
|
||||
if (err) return invalidate({all: err});
|
||||
res = res[0];
|
||||
switch (res.msg) {
|
||||
if (err || res.statusCode !== 200) {
|
||||
err = err || formatMessage({id: 'general.error'});
|
||||
this.refs.form.refs.formsy.updateInputsWithError({all: err});
|
||||
return callback(false);
|
||||
}
|
||||
body = body[0];
|
||||
|
||||
switch (body.msg) {
|
||||
case 'valid username':
|
||||
this.setState({
|
||||
validUsername: 'pass'
|
||||
});
|
||||
return this.props.onNextStep(formData);
|
||||
return callback(true);
|
||||
case 'username exists':
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameExists'})
|
||||
});
|
||||
return callback(false);
|
||||
case 'bad username':
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameVulgar'})
|
||||
});
|
||||
return callback(false);
|
||||
case 'invalid username':
|
||||
default:
|
||||
return invalidate({
|
||||
this.refs.form.refs.formsy.updateInputsWithError({
|
||||
'user.username': formatMessage({id: 'registration.validationUsernameInvalid'})
|
||||
});
|
||||
return callback(false);
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
onUsernameBlur: function (event) {
|
||||
this.validateUsername(event.currentTarget.value);
|
||||
},
|
||||
onValidSubmit: function (formData) {
|
||||
this.setState({waiting: true});
|
||||
this.validateUsername(formData.user.username, function (isValid) {
|
||||
this.setState({waiting: false});
|
||||
if (isValid) return this.props.onNextStep(formData);
|
||||
}.bind(this));
|
||||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
|
@ -139,7 +156,7 @@ module.exports = {
|
|||
)}
|
||||
</p>
|
||||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Form onValidSubmit={this.onValidSubmit} ref="form">
|
||||
<div>
|
||||
<div className="username-label">
|
||||
<b>{formatMessage({id: 'registration.createUsername'})}</b>
|
||||
|
@ -152,6 +169,7 @@ module.exports = {
|
|||
<Input className={this.state.validUsername}
|
||||
type="text"
|
||||
name="user.username"
|
||||
onBlur={this.onUsernameBlur}
|
||||
validations={{
|
||||
matchRegexp: /^[\w-]*$/,
|
||||
minLength: 3,
|
||||
|
@ -473,14 +491,6 @@ module.exports = {
|
|||
onChooseOrganization: function (name, values) {
|
||||
this.setState({otherDisabled: values.indexOf(this.organizationL10nStems.indexOf('orgChoiceOther')) === -1});
|
||||
},
|
||||
onValidSubmit: function (formData, reset, invalidate) {
|
||||
if (formData.organization.type.length < 1) {
|
||||
return invalidate({
|
||||
'organization.type': this.props.intl.formatMessage({id: 'teacherRegistration.validationRequired'})
|
||||
});
|
||||
}
|
||||
return this.props.onNextStep(formData);
|
||||
},
|
||||
render: function () {
|
||||
var formatMessage = this.props.intl.formatMessage;
|
||||
return (
|
||||
|
@ -494,7 +504,7 @@ module.exports = {
|
|||
tipContent={formatMessage({id: 'registration.nameStepTooltip'})} />
|
||||
</p>
|
||||
<Card>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Form onValidSubmit={this.props.onNextStep}>
|
||||
<Input label={formatMessage({id: 'teacherRegistration.organization'})}
|
||||
type="text"
|
||||
name="organization.name"
|
||||
|
@ -512,13 +522,22 @@ module.exports = {
|
|||
value={[]}
|
||||
options={this.getOrganizationOptions()}
|
||||
onChange={this.onChooseOrganization}
|
||||
validations={{
|
||||
minLength: 1
|
||||
}}
|
||||
validationErrors={{
|
||||
minLength: formatMessage({
|
||||
id: 'teacherRegistration.validationRequired'
|
||||
})
|
||||
}}
|
||||
required />
|
||||
</div>
|
||||
<div className="other-input">
|
||||
<Input type="text"
|
||||
name="organization.other"
|
||||
<Input name="organization.other"
|
||||
type="text"
|
||||
disabled={this.state.otherDisabled}
|
||||
required="isFalse"
|
||||
required={!this.state.otherDisabled}
|
||||
help={null}
|
||||
placeholder={formatMessage({id: 'general.other'})} />
|
||||
</div>
|
||||
<div className="url-input">
|
||||
|
@ -532,7 +551,7 @@ module.exports = {
|
|||
placeholder={'http://'} />
|
||||
</div>
|
||||
<NextStepButton waiting={this.props.waiting}
|
||||
text={<intl.FormattedMessage id="registration.nextStep" />} />
|
||||
text={<intl.FormattedMessage id="registration.nextStep" />} />
|
||||
</Form>
|
||||
</Card>
|
||||
<StepNavigation steps={this.props.totalSteps - 1} active={this.props.activeStep} />
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"general.discuss": "Discuss",
|
||||
"general.dmca": "DMCA",
|
||||
"general.emailAddress": "Email Address",
|
||||
"general.error": "Oops! Something went wrong",
|
||||
"general.explore": "Explore",
|
||||
"general.faq": "FAQ",
|
||||
"general.female": "Female",
|
||||
|
|
Loading…
Reference in a new issue