better client error handling on API calls.
This commit is contained in:
parent
203387074a
commit
5279698fee
|
@ -149,7 +149,6 @@ def delete(hashid):
|
|||
# check that this request came from user dashboard to prevent XSS and CSRF
|
||||
referrer = referrer_to_baseurl(request.referrer)
|
||||
service = referrer_to_baseurl(settings.SERVICE_URL)
|
||||
|
||||
if referrer != service:
|
||||
return jsonerror(400, {'error': 'Improper request.'})
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ const isValidUrl = require('valid-url').isWebUri
|
|||
const isValidEmail = require('is-valid-email')
|
||||
const React = require('react')
|
||||
const toastr = window.toastr
|
||||
const fetch = window.fetch
|
||||
|
||||
const modals = require('../modals')
|
||||
|
||||
|
@ -208,7 +209,7 @@ module.exports = class CreateForm extends React.Component {
|
|||
e.preventDefault()
|
||||
|
||||
try {
|
||||
let r = await (await fetch(`/api-int/forms/sitewide-check`, {
|
||||
let resp = await fetch(`/api-int/forms/sitewide-check`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({email: this.state.email, url: this.state.url}),
|
||||
credentials: 'same-origin',
|
||||
|
@ -216,9 +217,10 @@ module.exports = class CreateForm extends React.Component {
|
|||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (!r.ok) {
|
||||
if (!resp.ok || !r.ok) {
|
||||
toastr.warning("The verification file wasn't found.")
|
||||
this.setState({verified: false, disableVerification: true})
|
||||
|
||||
|
@ -232,7 +234,9 @@ module.exports = class CreateForm extends React.Component {
|
|||
this.setState({verified: true})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toastr.error(e.message)
|
||||
toastr.error(
|
||||
'Failed to call the sitewide verification API, see the console for more details.'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +244,7 @@ module.exports = class CreateForm extends React.Component {
|
|||
e.preventDefault()
|
||||
|
||||
try {
|
||||
let r = await (await fetch('/api-int/forms', {
|
||||
let resp = await fetch('/api-int/forms', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
email: this.state.email,
|
||||
|
@ -252,13 +256,23 @@ module.exports = class CreateForm extends React.Component {
|
|||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (!r.ok || r.error) {
|
||||
toastr.warning(
|
||||
r.error
|
||||
? `Error creating form: ${r.error}`
|
||||
: 'Unexpected error creating form.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
toastr.success('Form created!')
|
||||
this.props.history.push(`/forms/${r.hashid}`)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toastr.error(e.message)
|
||||
toastr.error('Failed to create form, see the console for more details.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/** @format */
|
||||
|
||||
const toastr = window.toastr
|
||||
const fetch = window.fetch
|
||||
const React = require('react')
|
||||
const cs = require('class-set')
|
||||
const {Link} = require('react-router-dom')
|
||||
|
@ -22,10 +24,15 @@ module.exports = class FormList extends React.Component {
|
|||
|
||||
async componentDidMount() {
|
||||
try {
|
||||
let r = await (await fetch('/api-int/forms', {
|
||||
let resp = await fetch('/api-int/forms', {
|
||||
credentials: 'same-origin',
|
||||
headers: {Accept: 'application/json'}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (!resp.ok || r.error) {
|
||||
throw new Error(r.error || '')
|
||||
}
|
||||
|
||||
this.setState({
|
||||
user: r.user,
|
||||
|
@ -36,6 +43,9 @@ module.exports = class FormList extends React.Component {
|
|||
} catch (e) {
|
||||
console.error(e)
|
||||
this.setState({error: e.message})
|
||||
toastr.error(
|
||||
'Failed to fetch your forms. See the console for more details.'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +184,7 @@ class FormItem extends React.Component {
|
|||
{form.email}
|
||||
</td>
|
||||
<td className="n-submissions" data-label="Submissions counter">
|
||||
{form.counter == 0 ? (
|
||||
{form.counter === 0 ? (
|
||||
<Link
|
||||
to={`/forms/${form.hashid}/integrations`}
|
||||
className="no-underline"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/** @format */
|
||||
|
||||
const toastr = window.toastr
|
||||
const fetch = window.fetch
|
||||
const React = require('react')
|
||||
const {Route, Link, NavLink, Redirect} = require('react-router-dom')
|
||||
const CodeMirror = require('react-codemirror2')
|
||||
|
@ -99,10 +100,18 @@ module.exports = class FormPage extends React.Component {
|
|||
let hashid = this.props.match.params.hashid
|
||||
|
||||
try {
|
||||
let r = await (await fetch(`/api-int/forms/${hashid}`, {
|
||||
let resp = await fetch(`/api-int/forms/${hashid}`, {
|
||||
credentials: 'same-origin',
|
||||
headers: {Accept: 'application/json'}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (!resp.ok || r.error) {
|
||||
toastr.warning(
|
||||
r.error ? `Error fetching form: ${r.error}` : 'Error fetching form.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({form: r})
|
||||
} catch (e) {
|
||||
|
@ -273,17 +282,22 @@ class FormSubmissions extends React.Component {
|
|||
let subid = e.currentTarget.dataset.sub
|
||||
|
||||
try {
|
||||
let r = await (await fetch(
|
||||
let resp = await fetch(
|
||||
`/api-int/forms/${this.props.form.hashid}/submissions/${subid}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
credentials: 'same-origin',
|
||||
headers: {Accept: 'application/json'}
|
||||
}
|
||||
)).json()
|
||||
)
|
||||
let r = await resp.json()
|
||||
|
||||
if (r.error) {
|
||||
toastr.warning(`Failed to delete submission: ${r.error}`)
|
||||
if (!resp.ok || r.error) {
|
||||
toastr.warning(
|
||||
r.error
|
||||
? `Failed to delete submission: ${r.error}`
|
||||
: `Failed to delete submission.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -461,7 +475,7 @@ class FormSettings extends React.Component {
|
|||
|
||||
async update(e) {
|
||||
try {
|
||||
let res = await (await fetch(`/api-int/forms/${this.props.form.hashid}`, {
|
||||
let resp = await fetch(`/api-int/forms/${this.props.form.hashid}`, {
|
||||
method: 'PATCH',
|
||||
body: JSON.stringify({
|
||||
[e.currentTarget.name]: !e.currentTarget.checked
|
||||
|
@ -471,10 +485,15 @@ class FormSettings extends React.Component {
|
|||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (res.error) {
|
||||
toastr.warning(`Failed to save settings: ${res.error}`)
|
||||
if (!resp.ok || r.error) {
|
||||
toastr.warning(
|
||||
r.error
|
||||
? `Failed to save settings: ${r.error}`
|
||||
: 'Failed to save settings.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -503,16 +522,21 @@ class FormSettings extends React.Component {
|
|||
|
||||
this.setState({deleting: false})
|
||||
try {
|
||||
let res = await (await fetch(`/api-int/forms/${this.props.form.hashid}`, {
|
||||
let resp = await fetch(`/api-int/forms/${this.props.form.hashid}`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'same-origin',
|
||||
headers: {
|
||||
Accept: 'application/json'
|
||||
}
|
||||
})).json()
|
||||
})
|
||||
let r = await resp.json()
|
||||
|
||||
if (res.error) {
|
||||
toastr.warning(`Failed to delete form: ${res.error}`)
|
||||
if (resp.error || r.error) {
|
||||
toastr.warning(
|
||||
r.error
|
||||
? `failed to delete form: ${r.error}`
|
||||
: 'failed to delete form.'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@
|
|||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0-rc.1",
|
||||
"@babel/preset-env": "^7.0.0-rc.1",
|
||||
"@babel/preset-react": "^7.0.0-rc.1",
|
||||
"@babel/core": "7.0.0-rc.1",
|
||||
"@babel/preset-env": "7.0.0-rc.1",
|
||||
"@babel/preset-react": "7.0.0-rc.1",
|
||||
"babelify": "^9.0.0",
|
||||
"browserify": "^16.2.2",
|
||||
"envify": "^4.1.0",
|
||||
|
|
Loading…
Reference in New Issue