Unverified Commit dce9b99a authored by Paul Kaplan's avatar Paul Kaplan Committed by GitHub

Merge pull request #5058 from paulkaplan/split-phone-bundle

Don't require a big phone number validation library on every page
parents ca5e62d5 b0390f36
...@@ -17,6 +17,21 @@ const validationHOCFactory = require('./validations.jsx').validationHOCFactory; ...@@ -17,6 +17,21 @@ const validationHOCFactory = require('./validations.jsx').validationHOCFactory;
require('./row.scss'); require('./row.scss');
require('./phone-input.scss'); require('./phone-input.scss');
const Formsy = require('formsy-react');
const libphonenumber = require('google-libphonenumber');
const phoneNumberUtil = libphonenumber.PhoneNumberUtil.getInstance();
Formsy.addValidationRule('isPhone', (values, value) => {
if (typeof value === 'undefined') return true;
if (value && value.national_number === '+') return true;
try {
const parsed = phoneNumberUtil.parse(value.national_number, value.country_code.iso2);
return phoneNumberUtil.isValidNumber(parsed);
} catch (err) {
return false;
}
});
class PhoneInput extends React.Component { class PhoneInput extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
......
const defaults = require('lodash.defaultsdeep'); const defaults = require('lodash.defaultsdeep');
const intl = require('../../lib/intl.jsx'); const intl = require('../../lib/intl.jsx');
const libphonenumber = require('google-libphonenumber');
const omit = require('lodash.omit'); const omit = require('lodash.omit');
const phoneNumberUtil = libphonenumber.PhoneNumberUtil.getInstance();
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const React = require('react'); const React = require('react');
module.exports.validations = { module.exports.validations = {
notEquals: (values, value, neq) => (value !== neq), notEquals: (values, value, neq) => (value !== neq),
notEqualsField: (values, value, field) => (value !== values[field]), notEqualsField: (values, value, field) => (value !== values[field])
isPhone: (values, value) => {
if (typeof value === 'undefined') return true;
if (value && value.national_number === '+') return true;
try {
const parsed = phoneNumberUtil.parse(value.national_number, value.country_code.iso2);
return phoneNumberUtil.isValidNumber(parsed);
} catch (err) {
return false;
}
}
}; };
module.exports.validations.notEqualsUsername = module.exports.validations.notEquals; module.exports.validations.notEqualsUsername = module.exports.validations.notEquals;
......
/* eslint-disable react/no-multi-comp */
const bindAll = require('lodash.bindall');
const injectIntl = require('react-intl').injectIntl;
const intlShape = require('react-intl').intlShape;
const PropTypes = require('prop-types');
const React = require('react');
const intl = require('../../lib/intl.jsx');
const Card = require('../../components/card/card.jsx');
const Checkbox = require('../../components/forms/checkbox.jsx');
const Form = require('../../components/forms/form.jsx');
const PhoneInput = require('../../components/forms/phone-input.jsx');
const Slide = require('../../components/slide/slide.jsx');
const StepNavigation = require('../../components/stepnavigation/stepnavigation.jsx');
const Tooltip = require('../../components/tooltip/tooltip.jsx');
const {DEFAULT_COUNTRY, NextStepButton} = require('./steps.jsx');
require('./steps.scss');
/*
* This step is separate from the other steps because it includes a large library
* for phone number validation.
*/
class PhoneNumberStep extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleValidSubmit'
]);
}
handleValidSubmit (formData, reset, invalidate) {
if (!formData.phone || formData.phone.national_number === '+') {
return invalidate({
phone: this.props.intl.formatMessage({id: 'form.validationRequired'})
});
}
return this.props.onNextStep(formData);
}
render () {
return (
<Slide className="registration-step phone-step">
<h2>
<intl.FormattedMessage id="teacherRegistration.phoneNumber" />
</h2>
<p className="description">
<intl.FormattedMessage id="teacherRegistration.phoneStepDescription" />
<Tooltip
tipContent={
this.props.intl.formatMessage({id: 'registration.nameStepTooltip'})
}
title={'?'}
/>
</p>
<Card>
<Form onValidSubmit={this.handleValidSubmit}>
<PhoneInput
required
defaultCountry={this.props.defaultCountry}
label={
this.props.intl.formatMessage({id: 'teacherRegistration.phoneNumber'})
}
name="phone"
/>
<Checkbox
name="phoneConsent"
required="isFalse"
validationErrors={{
isFalse: this.props.intl.formatMessage({
id: 'teacherRegistration.validationPhoneConsent'
})
}}
valueLabel={
this.props.intl.formatMessage({id: 'teacherRegistration.phoneConsent'})
}
/>
<NextStepButton
text={<intl.FormattedMessage id="registration.nextStep" />}
waiting={this.props.waiting}
/>
</Form>
</Card>
<StepNavigation
active={this.props.activeStep}
steps={this.props.totalSteps - 1}
/>
</Slide>
);
}
}
PhoneNumberStep.propTypes = {
activeStep: PropTypes.number,
defaultCountry: PropTypes.string,
intl: intlShape,
onNextStep: PropTypes.func,
totalSteps: PropTypes.number,
waiting: PropTypes.bool
};
PhoneNumberStep.defaultProps = {
defaultCountry: DEFAULT_COUNTRY,
waiting: false
};
const IntlPhoneNumberStep = injectIntl(PhoneNumberStep);
module.exports = IntlPhoneNumberStep;
...@@ -20,7 +20,6 @@ const CheckboxGroup = require('../../components/forms/checkbox-group.jsx'); ...@@ -20,7 +20,6 @@ const CheckboxGroup = require('../../components/forms/checkbox-group.jsx');
const Form = require('../../components/forms/form.jsx'); const Form = require('../../components/forms/form.jsx');
const GeneralError = require('../../components/forms/general-error.jsx'); const GeneralError = require('../../components/forms/general-error.jsx');
const Input = require('../../components/forms/input.jsx'); const Input = require('../../components/forms/input.jsx');
const PhoneInput = require('../../components/forms/phone-input.jsx');
const RadioGroup = require('../../components/forms/radio-group.jsx'); const RadioGroup = require('../../components/forms/radio-group.jsx');
const Select = require('../../components/forms/select.jsx'); const Select = require('../../components/forms/select.jsx');
const Slide = require('../../components/slide/slide.jsx'); const Slide = require('../../components/slide/slide.jsx');
...@@ -703,93 +702,6 @@ NameStep.defaultProps = { ...@@ -703,93 +702,6 @@ NameStep.defaultProps = {
const IntlNameStep = injectIntl(NameStep); const IntlNameStep = injectIntl(NameStep);
/*
* PHONE NUMBER STEP
*/
class PhoneNumberStep extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleValidSubmit'
]);
}
handleValidSubmit (formData, reset, invalidate) {
if (!formData.phone || formData.phone.national_number === '+') {
return invalidate({
phone: this.props.intl.formatMessage({id: 'form.validationRequired'})
});
}
return this.props.onNextStep(formData);
}
render () {
return (
<Slide className="registration-step phone-step">
<h2>
<intl.FormattedMessage id="teacherRegistration.phoneNumber" />
</h2>
<p className="description">
<intl.FormattedMessage id="teacherRegistration.phoneStepDescription" />
<Tooltip
tipContent={
this.props.intl.formatMessage({id: 'registration.nameStepTooltip'})
}
title={'?'}
/>
</p>
<Card>
<Form onValidSubmit={this.handleValidSubmit}>
<PhoneInput
required
defaultCountry={this.props.defaultCountry}
label={
this.props.intl.formatMessage({id: 'teacherRegistration.phoneNumber'})
}
name="phone"
/>
<Checkbox
name="phoneConsent"
required="isFalse"
validationErrors={{
isFalse: this.props.intl.formatMessage({
id: 'teacherRegistration.validationPhoneConsent'
})
}}
valueLabel={
this.props.intl.formatMessage({id: 'teacherRegistration.phoneConsent'})
}
/>
<NextStepButton
text={<intl.FormattedMessage id="registration.nextStep" />}
waiting={this.props.waiting}
/>
</Form>
</Card>
<StepNavigation
active={this.props.activeStep}
steps={this.props.totalSteps - 1}
/>
</Slide>
);
}
}
PhoneNumberStep.propTypes = {
activeStep: PropTypes.number,
defaultCountry: PropTypes.string,
intl: intlShape,
onNextStep: PropTypes.func,
totalSteps: PropTypes.number,
waiting: PropTypes.bool
};
PhoneNumberStep.defaultProps = {
defaultCountry: DEFAULT_COUNTRY,
waiting: false
};
const IntlPhoneNumberStep = injectIntl(PhoneNumberStep);
/* /*
* ORGANIZATION STEP * ORGANIZATION STEP
*/ */
...@@ -1666,11 +1578,12 @@ RegistrationError.propTypes = { ...@@ -1666,11 +1578,12 @@ RegistrationError.propTypes = {
const IntlRegistrationError = injectIntl(RegistrationError); const IntlRegistrationError = injectIntl(RegistrationError);
module.exports.DEFAULT_COUNTRY = DEFAULT_COUNTRY;
module.exports.NextStepButton = NextStepButton;
module.exports.UsernameStep = IntlUsernameStep; module.exports.UsernameStep = IntlUsernameStep;
module.exports.ChoosePasswordStep = IntlChoosePasswordStep; module.exports.ChoosePasswordStep = IntlChoosePasswordStep;
module.exports.DemographicsStep = IntlDemographicsStep; module.exports.DemographicsStep = IntlDemographicsStep;
module.exports.NameStep = IntlNameStep; module.exports.NameStep = IntlNameStep;
module.exports.PhoneNumberStep = IntlPhoneNumberStep;
module.exports.OrganizationStep = IntlOrganizationStep; module.exports.OrganizationStep = IntlOrganizationStep;
module.exports.AddressStep = IntlAddressStep; module.exports.AddressStep = IntlAddressStep;
module.exports.UseScratchStep = IntlUseScratchStep; module.exports.UseScratchStep = IntlUseScratchStep;
......
...@@ -12,6 +12,7 @@ const sessionActions = require('../../redux/session.js'); ...@@ -12,6 +12,7 @@ const sessionActions = require('../../redux/session.js');
const Deck = require('../../components/deck/deck.jsx'); const Deck = require('../../components/deck/deck.jsx');
const Progression = require('../../components/progression/progression.jsx'); const Progression = require('../../components/progression/progression.jsx');
const Steps = require('../../components/registration/steps.jsx'); const Steps = require('../../components/registration/steps.jsx');
const PhoneNumberStep = require('../../components/registration/phone-number-step.jsx');
const render = require('../../lib/render.jsx'); const render = require('../../lib/render.jsx');
...@@ -119,7 +120,7 @@ class TeacherRegistration extends React.Component { ...@@ -119,7 +120,7 @@ class TeacherRegistration extends React.Component {
waiting={this.state.waiting} waiting={this.state.waiting}
onNextStep={this.handleAdvanceStep} onNextStep={this.handleAdvanceStep}
/> />
<Steps.PhoneNumberStep <PhoneNumberStep
defaultCountry={this.state.formData.countryCode} defaultCountry={this.state.formData.countryCode}
waiting={this.state.waiting} waiting={this.state.waiting}
onNextStep={this.handleAdvanceStep} onNextStep={this.handleAdvanceStep}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment