Skip to content

Commit ac5a641

Browse files
committed
add ErrorAlert
1 parent a9ec621 commit ac5a641

File tree

9 files changed

+96
-9
lines changed

9 files changed

+96
-9
lines changed

docs/index.html

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>ReactJS Redux GraphQL Apollo Bootstrap Starter</title>
5+
<meta charset="utf-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<meta name="description" content="ReactJS Redux GraphQL Apollo Bootstrap Starter">
9+
<meta name="author" content="Erwan DATIN (MacKentoch)">
10+
</head>
11+
<body>
12+
<section id="root"></section>
13+
<script type="text/javascript" src="./assets/bundle.js"></script>
14+
</body>
15+
</html>
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React, {
2+
PropTypes
3+
} from 'react';
4+
import {
5+
Motion,
6+
spring,
7+
presets
8+
} from 'react-motion';
9+
10+
11+
const ErrorAlert = ({ showAlert, errorTitle, errorMessage, onClose }) => (
12+
<Motion style={{scale: spring(showAlert ? 1 : 0, presets.stiff)}}>
13+
{
14+
({ scale }) => (
15+
<div
16+
className="alert alert-dismissible alert-danger"
17+
style={{
18+
WebkitTransform: `scale(${scale})`,
19+
transform: `scale(${scale})`
20+
}}>
21+
<button
22+
type="button"
23+
className="close"
24+
data-dismiss="alert"
25+
onClick={onClose}>
26+
&times;
27+
</button>
28+
{
29+
errorTitle && errorTitle.length > 0 &&
30+
<strong>
31+
{errorTitle}
32+
</strong>
33+
}
34+
{
35+
<p>
36+
{errorMessage}
37+
</p>
38+
}
39+
</div>
40+
)
41+
}
42+
</Motion>
43+
);
44+
45+
46+
ErrorAlert.propTypes = {
47+
showAlert: PropTypes.bool,
48+
errorTitle: PropTypes.string,
49+
errorMessage: PropTypes.string,
50+
onClose: PropTypes.func.isRequired
51+
};
52+
53+
ErrorAlert.defaultProps = {
54+
showAlert: false
55+
};
56+
57+
export default ErrorAlert;

src/app/components/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import Jumbotron from './jumbotron/Jumbotron';
22
import NavigationBar from './navigation/NavigationBar';
33
import BackToTop from './backToTop/BackToTop';
4+
import ErrorAlert from './alert/ErrorAlert';
45

56
export {
67
Jumbotron,
78
NavigationBar,
8-
BackToTop
9+
BackToTop,
10+
ErrorAlert
911
};

src/app/config/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export const appConfig = {
22
// apollo client:
33
apollo: {
4-
networkInterface: '' // exemple: http://localhost:8080/graphql
4+
networkInterface: 'https://us-west-2.api.scaphold.io/graphql/flawless-basketball' // exemple: http://localhost:8080/graphql
55
}
66
};

src/app/containers/login/Login.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const LoginWithMutation = graphql(
5555
)
5656
.catch(
5757
({data: {error}})=> {
58-
ownProps.onUserRegisterError(error);
58+
ownProps.onUserLogError(error);
5959
ownProps.unsetMutationLoading();
6060
return Promise.reject();
6161
}
@@ -76,7 +76,9 @@ const mapStateToProps = (state) => {
7676
currentView: state.views.currentView,
7777
// user Auth props:
7878
userIsAuthenticated: state.userAuth.isAuthenticated,
79-
mutationLoading: state.userAuth.mutationLoading
79+
mutationLoading: state.userAuth.mutationLoading,
80+
// errors:
81+
errors: state.userAuth.errors
8082
};
8183
};
8284

src/app/redux/modules/userAuth.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const initialState = {
3636
isAuthenticated: false,
3737
lastActionTime: null,
3838
mutationLoading: false,
39+
errors: [],
3940
...emptyUser
4041
};
4142

@@ -53,7 +54,8 @@ export default function (state = initialState, action) {
5354
lastLogin: action.user.lastLogin,
5455
createdAt: action.user.createdAt,
5556
modifiedAt: action.user.modifiedAt,
56-
lastRefreshTime: action.time
57+
lastRefreshTime: action.time,
58+
errors: []
5759
};
5860

5961
case ERROR_USER_LOGGED_IN:
@@ -62,6 +64,8 @@ export default function (state = initialState, action) {
6264
...state,
6365
lastActionTime: action.time,
6466
isAuthenticated: action.isAuthenticated,
67+
// errors:
68+
errors: [...action.errors],
6569
// user infos:
6670
id: initialState.id,
6771
username: initialState.username,

src/app/views/login/Login.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import React, {
55
import cx from 'classnames';
66
import shallowCompare from 'react-addons-shallow-compare';
77
import { Link } from 'react-router';
8+
import { ErrorAlert } from '../../components';
89

910
class Login extends Component {
1011

@@ -48,7 +49,8 @@ class Login extends Component {
4849
password
4950
} = this.state;
5051
const {
51-
mutationLoading
52+
mutationLoading,
53+
errors
5254
} = this.props;
5355

5456
return(
@@ -59,7 +61,12 @@ class Login extends Component {
5961
})}>
6062
<div className="row">
6163
<div className="col-md-4 col-md-offset-4">
62-
64+
<ErrorAlert
65+
showAlert={errors.length > 0}
66+
errorTitle={'Error'}
67+
errorMessage={'login failed'}
68+
onClose={()=>console.log('coming soon...')}
69+
/>
6370
<form
6471
className="form-horizontal"
6572
noValidate>
@@ -179,6 +186,7 @@ Login.propTypes= {
179186
// auth props:
180187
userIsAuthenticated: PropTypes.bool.isRequired,
181188
mutationLoading: PropTypes.bool.isRequired,
189+
errors: PropTypes.array.isRequired,
182190

183191
// apollo actions
184192
loginUser: PropTypes.func.isRequired,

test/redux/actions/views.spec.js

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ chai.use(dirtyChai);
1717

1818

1919
describe('redux - action creator "views"', () => {
20-
2120
it('should return enterHome action object', () => {
2221
const enterHomeACTION = {
2322
type: 'ENTER_HOME_VIEW',

webpack.production.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ const path = require('path');
33
const autoprefixer = require('autoprefixer');
44
const precss = require('precss');
55

6-
const assetsDir = path.resolve(__dirname, 'public/assets');
6+
const assetsDir = path.resolve(__dirname, 'docs/assets');
77
const nodeModulesDir = path.resolve(__dirname, 'node_modules');
88

99
const config = {

0 commit comments

Comments
 (0)