parse json in all responses & handle login error

This commit is contained in:
Danny van Kooten 2017-01-13 12:47:21 +01:00
parent 9200df8569
commit b5b31d89f8
5 changed files with 89 additions and 11 deletions

View File

@ -2,6 +2,7 @@
import { h, render, Component } from 'preact';
import Client from '../lib/client.js';
import Notification from '../components/Notification.js';
class LoginForm extends Component {
@ -11,6 +12,7 @@ class LoginForm extends Component {
this.state = {
email: '',
password: '',
message: ''
}
}
@ -23,7 +25,15 @@ class LoginForm extends Component {
email: this.state.email,
password: this.state.password,
}
}).then((r) => { this.props.onSuccess() })
}).then((r) => {
this.props.onSuccess()
}).catch((e) => {
this.setState({
message: e.message,
password: ''
})
})
}
render() {
@ -34,17 +44,19 @@ class LoginForm extends Component {
<form method="POST" onSubmit={this.handleSubmit}>
<div class="small-margin">
<label>Email address</label>
<input type="email" name="email" placeholder="Email address" onChange={this.linkState('email')} required="required" />
<input type="email" name="email" placeholder="Email address" value={this.state.email} onChange={this.linkState('email')} required="required" />
</div>
<div class="small-margin">
<label>Password</label>
<input type="password" name="password" placeholder="**********" onChange={this.linkState('password')} required="required" />
<input type="password" name="password" placeholder="**********" value={this.state.password} onChange={this.linkState('password')} required="required" />
</div>
<div class="small-margin">
<input type="submit" value="Sign in" />
</div>
</form>
<Notification message={this.state.message} kind="" />
</div>
)
}
}

View File

@ -0,0 +1,40 @@
'use strict'
import { h, render, Component } from 'preact';
class Notification extends Component {
constructor(props) {
super(props)
this.state = {
message: props.message,
kind: props.kind || 'error'
}
}
clearMessage() {
this.setState({ message: '' })
}
componentWillReceiveProps(newProps) {
if(newProps.message != this.state.message) {
this.setState({ message: newProps.message, kind: newProps.kind || 'error' })
window.setTimeout(this.clearMessage.bind(this), 5000)
}
}
render() {
if(this.state.message === '') {
return ''
}
return (
<div class={`notification`}>
<div class={`notification-${this.state.kind}`}>
{this.state.message}
</div>
</div>
)}
}
export default Notification

View File

@ -19,13 +19,21 @@ Client.request = function(resource, args) {
}
}
return fetch(`/api/${resource}`, args).then((r) => {
if( r.ok ) {
return r.json();
return fetch(`/api/${resource}`, args)
.then(parseJSON)
.then(checkData)
}
function parseJSON(r) {
return r.json()
}
function checkData(d) {
if(d.Error) {
throw new Error(d.Error)
}
throw new Error(r);
})
return d.Data
}
export default Client

View File

@ -10,7 +10,7 @@ class Login extends Component {
<div>
<HeaderBar showLogout={false} />
<div class="container">
<LoginForm onSuccess={this.props.onLogin} />
<LoginForm onSuccess={this.props.onLogin}/>
</div>
</div>
)

View File

@ -110,7 +110,6 @@ a {
}
@keyframes rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
@ -121,6 +120,25 @@ a {
font-size: 120%;
}
.notification {
top: 20px;
left: 0;
right: 0;
text-align: center;
position: fixed;
color: white;
div {
color: white;
display: inline-block;
padding: 6px 12px;
background: green;
}
.notification-error {
background: red;
}
}
h1 {
font-size: 28px;