mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-22 15:17:53 -05:00
Add address validation
This commit is contained in:
parent
f8037f6767
commit
cfa85427b1
9 changed files with 90 additions and 16 deletions
|
@ -47,6 +47,8 @@ env:
|
|||
- SENTRY_DSN_VAR=SENTRY_DSN_$TRAVIS_BRANCH
|
||||
- SENTRY_DSN=${!SENTRY_DSN_VAR}
|
||||
- SENTRY_DSN=${SENTRY_DSN:-$SENTRY_DSN_STAGING}
|
||||
# SMARTY_STREETS_API_KEY
|
||||
- secure: "uQKNgJaJEju8ErGUxIbLE0Y6ee4j6OFFbBpqyuKrNMk6apvvvXLp3lTdGZJq6j/ZwQeQ384m5bbfmhFwr7piPFj7W/zBXVKcifbF6ShfP7skMl834Kkefs3uEWU0VZw3nURgzNInSOPqqGLsISFywpwBXUWKfL0Q87KHNU0/I0EkwvImm3SAlNpR38m3yKcMF3h0zK8Fh2mO7iyHEIhtssdWabaRjf3t6Mr5vikACeXYJg+k4oEQZtsnSNnlLYWumdEDsxwonMozGKUBqlXwhHCdYNOJ1DUGuntbXOnylLt1/LA9I9B4hWQOrRDwqjyIOI+2dpADoCN040+Zr1VSrJhk7Wb7ogeaQLzZ4W/3dX54rbsnFHa+MuKqOsAxQ0Tjfk5xWq/pbLRsAyW6Pl7Q1v4yWOQ2COnM/tfJ6UaH9bxppOyKsX8n33rFjlvZU6CtY1GGa7fpB2zOKI5B5OovLjHeokIe/Tx+4coEDZqt44qkTGWr/eWDxrvkQqpQ29F9My3wBgB3gdou+3lWExS0a9M2wwp4EIduXEKNZXLGDuVefH5f3eFy09wH+nhctmMF8uhMbPefFubEi7fqXTkxntmDTy+/pD2A2w1jJhBwLhwlik335k+Wrbl3dclt7cjJ6fRVX9b+AuBCbGr633vM4xbk90whwXizSECIt5InGSw="
|
||||
- SKIP_CLEANUP=true
|
||||
- NODE_ENV=production
|
||||
- WWW_VERSION=${TRAVIS_COMMIT:0:5}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
var classNames = require('classnames');
|
||||
var Formsy = require('formsy-react');
|
||||
var React = require('react');
|
||||
var GeneralError = require('./general-error.jsx');
|
||||
var validations = require('./validations.jsx').validations;
|
||||
|
||||
for (var validation in validations) {
|
||||
|
@ -20,6 +21,7 @@ var Form = React.createClass({
|
|||
);
|
||||
return (
|
||||
<Formsy.Form {... this.props} className={classes}>
|
||||
<GeneralError name="all" />
|
||||
{this.props.children}
|
||||
</Formsy.Form>
|
||||
);
|
||||
|
|
13
src/components/forms/general-error.jsx
Normal file
13
src/components/forms/general-error.jsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
var Formsy = require('formsy-react');
|
||||
var React = require('react');
|
||||
|
||||
module.exports = Formsy.HOC(React.createClass({
|
||||
render: function () {
|
||||
if (!this.props.showError()) return null;
|
||||
return (
|
||||
<p className="error">
|
||||
{this.props.getErrorMessage()}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
}));
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
.spinner {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
|
@ -17,10 +18,14 @@
|
|||
animation: circleFadeDelay 1.2s infinite ease-in-out both;
|
||||
margin: 0 auto;
|
||||
border-radius: 100%;
|
||||
background-color: darken($ui-blue, 8%);
|
||||
background-color: darken($ui-white, 8%);
|
||||
width: 15%;
|
||||
height: 15%;
|
||||
content: "";
|
||||
|
||||
.white & {
|
||||
background-color: darken($ui-blue, 8%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
src/lib/smarty-streets.js
Normal file
21
src/lib/smarty-streets.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
var defaults = require('lodash.defaults');
|
||||
var api = require('./api');
|
||||
|
||||
module.exports = function smartyStreetApi (params, callback) {
|
||||
defaults(params, {
|
||||
'auth-id': process.env.SMARTY_STREETS_API_KEY
|
||||
});
|
||||
api({
|
||||
host: 'https://api.smartystreets.com',
|
||||
uri: '/street-address',
|
||||
params: params
|
||||
}, function (err, body, res) {
|
||||
if (err) return callback(err);
|
||||
if (res.statusCode !== 200) {
|
||||
return callback(
|
||||
'There was an error contacting the address validation server.'
|
||||
);
|
||||
}
|
||||
return callback(err, body);
|
||||
});
|
||||
};
|
|
@ -1,7 +1,4 @@
|
|||
module.exports = {
|
||||
// Bind environment
|
||||
api_host: process.env.API_HOST || 'https://api.scratch.mit.edu',
|
||||
|
||||
// Search and metadata
|
||||
title: 'Imagine, Program, Share',
|
||||
description:
|
||||
|
|
|
@ -31,13 +31,6 @@
|
|||
<link rel="shortcut icon" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/css/lib/normalize.min.css" />
|
||||
|
||||
<!-- Environment -->
|
||||
<script>
|
||||
window.env = {
|
||||
API_HOST: "{{&api_host}}"
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Polyfills -->
|
||||
<script src="/js/polyfill.min.js"></script>
|
||||
</head>
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
var React = require('react');
|
||||
|
||||
var countryData = require('../../lib/country-data');
|
||||
var log = require('../../lib/log');
|
||||
var smartyStreets = require('../../lib/smarty-streets');
|
||||
|
||||
var Button = require('../../components/forms/button.jsx');
|
||||
var Checkbox = require('../../components/forms/checkbox.jsx');
|
||||
|
@ -11,6 +13,7 @@ var Input = require('../../components/forms/input.jsx');
|
|||
var PhoneInput = require('../../components/forms/phone-input.jsx');
|
||||
var RadioGroup = require('../../components/forms/radio-group.jsx');
|
||||
var Select = require('../../components/forms/select.jsx');
|
||||
var Spinner = require('../../components/spinner/spinner.jsx');
|
||||
var TextArea = require('../../components/forms/textarea.jsx');
|
||||
|
||||
var DEFAULT_COUNTRY = 'us';
|
||||
|
@ -222,12 +225,43 @@ module.exports = {
|
|||
countryChoice: (
|
||||
(this.props.formData.user && this.props.formData.user.country) ||
|
||||
this.props.defaultCountry
|
||||
)
|
||||
),
|
||||
waiting: false
|
||||
};
|
||||
},
|
||||
onChangeCountry: function (field, choice) {
|
||||
this.setState({countryChoice: choice});
|
||||
},
|
||||
onValidSubmit: function (formData, reset, invalidate) {
|
||||
if (formData.address.country !== 'us') {
|
||||
return this.props.onNextStep(formData);
|
||||
}
|
||||
this.setState({waiting: true});
|
||||
var address = {
|
||||
street: formData.address.line1,
|
||||
secondary: formData.address.line2 || '',
|
||||
city: formData.address.city,
|
||||
state: formData.address.state,
|
||||
zipcode: formData.address.zip
|
||||
};
|
||||
smartyStreets(address, function (err, res) {
|
||||
this.setState({waiting: false});
|
||||
if (err) {
|
||||
// We don't want to prevent registration because
|
||||
// address validation isn't working. Log it and
|
||||
// move on.
|
||||
log.error(err);
|
||||
return this.props.onNextStep(formData);
|
||||
}
|
||||
if (res && res.length > 0) {
|
||||
return this.props.onNextStep(formData);
|
||||
} else {
|
||||
return invalidate({
|
||||
'all': 'This doesn\'t look like a real address'
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
render: function () {
|
||||
var stateOptions = countryData.subdivisionOptions[this.state.countryChoice];
|
||||
var stateDefault = 'Please select...';
|
||||
|
@ -239,7 +273,7 @@ module.exports = {
|
|||
Your responses to these questions will be kept private.
|
||||
Why do we ask for this information <a onClick={this.handle}>?</a>
|
||||
</p>}>
|
||||
<Form onValidSubmit={this.props.onNextStep}>
|
||||
<Form onValidSubmit={this.onValidSubmit}>
|
||||
<Select label="Country"
|
||||
name="address.country"
|
||||
options={countryData.countryOptions}
|
||||
|
@ -249,12 +283,17 @@ module.exports = {
|
|||
<Input label="Address Line 1" type="text" name="address.line1" required />
|
||||
<Input label="Address Line 2" type="text" name="address.line2" />
|
||||
<Input label="City" type="text" name="address.city" required />
|
||||
<Input label="ZIP Code" type="text" name="address.zip" required />
|
||||
{stateOptions.length > 2 ?
|
||||
<Select label="State / Province" name="address.state" options={stateOptions} required /> :
|
||||
[]
|
||||
}
|
||||
<Button type="submit">Next Step</Button>
|
||||
<Input label="ZIP Code" type="text" name="address.zip" required />
|
||||
<Button type="submit" disabled={this.state.waiting}>
|
||||
{this.state.waiting ?
|
||||
<Spinner /> :
|
||||
<span>Next Step</span>
|
||||
}
|
||||
</Button>
|
||||
</Form>
|
||||
</FormStep>
|
||||
);
|
||||
|
|
|
@ -114,7 +114,9 @@ module.exports = {
|
|||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"' + (process.env.NODE_ENV || 'development') + '"',
|
||||
'process.env.SENTRY_DSN': '"' + (process.env.SENTRY_DSN || '') + '"'
|
||||
'process.env.SENTRY_DSN': '"' + (process.env.SENTRY_DSN || '') + '"',
|
||||
'process.env.API_HOST': '"' + (process.env.API_HOST || 'https://api.scratch.mit.edu') + '"',
|
||||
'process.env.SMARTY_STREETS_API_KEY': '"' + (process.env.SMARTY_STREETS_API_KEY || '') + '"'
|
||||
}),
|
||||
new webpack.optimize.CommonsChunkPlugin('common', 'js/common.bundle.js'),
|
||||
new webpack.optimize.OccurenceOrderPlugin()
|
||||
|
|
Loading…
Reference in a new issue