From f0c2280fde5188c1ef797d5dc74eb16f695db4cc Mon Sep 17 00:00:00 2001 From: Matthew Taylor Date: Tue, 2 Aug 2016 15:23:09 -0400 Subject: [PATCH] Updates to registration UX for teachers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Phone too long validation occurs before submit now. 2. Organization “other” type is now being required 3. Organization type required now shows up at the same time as other organization validation errors 4. Username check now occurs earlier, on blur rather than on submit --- src/components/forms/phone-input.jsx | 22 ++++++---- src/components/forms/validations.jsx | 8 ++++ src/components/registration/steps.jsx | 62 ++++++++++++++++++++------- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/src/components/forms/phone-input.jsx b/src/components/forms/phone-input.jsx index a4e26eb50..03a01470d 100644 --- a/src/components/forms/phone-input.jsx +++ b/src/components/forms/phone-input.jsx @@ -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: , + phoneLength: }); module.exports = inputHOC(defaultValidationHOC(phoneValidationHOC(PhoneInput))); diff --git a/src/components/forms/validations.jsx b/src/components/forms/validations.jsx index 6410322b9..3d6dbbcc4 100644 --- a/src/components/forms/validations.jsx +++ b/src/components/forms/validations.jsx @@ -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; } }; diff --git a/src/components/registration/steps.jsx b/src/components/registration/steps.jsx index 5cb9ee1c1..f4f15fef3 100644 --- a/src/components/registration/steps.jsx +++ b/src/components/registration/steps.jsx @@ -82,38 +82,53 @@ module.exports = { onChangeShowPassword: function (field, value) { this.setState({showPassword: value}); }, - onValidSubmit: function (formData, reset, invalidate) { - this.setState({waiting: true}); + validateUsername: function (username) { api({ host: '', - uri: '/accounts/check_username/' + formData.user.username + '/' + uri: '/accounts/check_username/' + username + '/' }, function (err, res) { var formatMessage = this.props.intl.formatMessage; - this.setState({waiting: false}); - if (err) return invalidate({all: err}); + if (err) { + this.refs.form.refs.formsy.updateInputsWithError({all: err}); + return false; + } res = res[0]; switch (res.msg) { case 'valid username': this.setState({ validUsername: 'pass' }); - return this.props.onNextStep(formData); + return true; case 'username exists': - return invalidate({ + this.refs.form.refs.formsy.updateInputsWithError({ 'user.username': formatMessage({id: 'registration.validationUsernameExists'}) }); + return false; case 'bad username': - return invalidate({ + this.refs.form.refs.formsy.updateInputsWithError({ 'user.username': formatMessage({id: 'registration.validationUsernameVulgar'}) }); + return false; case 'invalid username': default: - return invalidate({ + this.refs.form.refs.formsy.updateInputsWithError({ 'user.username': formatMessage({id: 'registration.validationUsernameInvalid'}) }); + return false; } }.bind(this)); }, + onUsernameBlur: function (event) { + this.validateUsername(event.currentTarget.value); + }, + onValidSubmit: function (formData) { + this.setState({waiting: true}); + this.validateUsername(formData.user.username); + this.setState({waiting: false}); + if (this.state.validUsername === 'pass') { + this.props.onNextStep(formData); + } + }, render: function () { var formatMessage = this.props.intl.formatMessage; return ( @@ -139,7 +154,7 @@ module.exports = { )}

-
+
{formatMessage({id: 'registration.createUsername'})} @@ -152,6 +167,7 @@ module.exports = {

- +
-
@@ -532,7 +562,7 @@ module.exports = { placeholder={'http://'} />
} /> + text={} />