Start code splitting
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { Route, Redirect } from "react-router-dom";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export class Auth extends React.Component<{
|
||||||
|
loginRoute: string,
|
||||||
|
token: string,
|
||||||
|
location: object
|
||||||
|
}> {
|
||||||
|
static propTypes = {
|
||||||
|
loginRoute: PropTypes.string.isRequired,
|
||||||
|
token: PropTypes.string.isRequired,
|
||||||
|
location: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const myProps = { ...this.props };
|
||||||
|
if (!myProps.token) {
|
||||||
|
delete myProps.component;
|
||||||
|
myProps.render = () => (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: this.props.loginRoute,
|
||||||
|
state: { from: this.props.location }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <Route {...myProps} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
|
import { Auth } from "./authRoute.component";
|
||||||
|
export const AuthRoute = connect(state => ({
|
||||||
|
token: state.token,
|
||||||
|
loginRoute: "/login"
|
||||||
|
}))(Auth);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { ConnectedLogin } from "./login.connected.js";
|
||||||
|
import { ConnectedProtectedRoutes } from "./protectedRoutes.connected.js";
|
||||||
|
import { AuthRoute } from "./authRoute.connected.js";
|
||||||
|
|
||||||
|
export { ConnectedLogin, ConnectedProtectedRoutes, AuthRoute };
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { loginService } from "./serviceApi";
|
||||||
|
|
||||||
|
export const LOGIN_REQUEST = "login:request";
|
||||||
|
export const LOGIN_SUCCESS = "login:success";
|
||||||
|
export const LOGIN_FAILURE = "login:failure";
|
||||||
|
|
||||||
|
export const loginRequest = () => ({
|
||||||
|
type: LOGIN_REQUEST
|
||||||
|
});
|
||||||
|
|
||||||
|
export const loginSuccess = (token: string) => ({
|
||||||
|
type: LOGIN_SUCCESS,
|
||||||
|
token
|
||||||
|
});
|
||||||
|
|
||||||
|
export const loginFailure = () => ({
|
||||||
|
type: LOGIN_FAILURE
|
||||||
|
});
|
||||||
|
|
||||||
|
// Complex actions:
|
||||||
|
|
||||||
|
export const attemptLogin = (
|
||||||
|
user: string,
|
||||||
|
password: string
|
||||||
|
) => async dispatch => {
|
||||||
|
try {
|
||||||
|
dispatch(loginRequest());
|
||||||
|
// the next line delays execution for 5 seconds:
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 5000));
|
||||||
|
const result = await loginService(user, password);
|
||||||
|
dispatch(loginSuccess(result.data));
|
||||||
|
} catch (e) {
|
||||||
|
dispatch(loginFailure());
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import { Redirect } from "react-router-dom";
|
||||||
|
|
||||||
|
export class Login extends React.PureComponent<{
|
||||||
|
onLogin: func,
|
||||||
|
logging: boolean,
|
||||||
|
token: string,
|
||||||
|
location: object
|
||||||
|
}> {
|
||||||
|
static propTypes = {
|
||||||
|
onLogin: PropTypes.func.isRequired,
|
||||||
|
logging: PropTypes.bool.isRequired,
|
||||||
|
token: PropTypes.string.isRequired,
|
||||||
|
location: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
userName: "",
|
||||||
|
password: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
onUserNameBlur = e => this.setState({ userName: e.target.value });
|
||||||
|
|
||||||
|
onPasswordBlur = e => this.setState({ password: e.target.value });
|
||||||
|
|
||||||
|
onLoginClick = () =>
|
||||||
|
this.props.onLogin(this.state.userName, this.state.password);
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (
|
||||||
|
this.state.userName &&
|
||||||
|
this.state.password &&
|
||||||
|
this.props.token
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<Redirect to={this.props.location.state.from.pathname} />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Login Form</h1>
|
||||||
|
<div>
|
||||||
|
User:<input
|
||||||
|
type="text"
|
||||||
|
onBlur={this.onUserNameBlur}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Password:
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
onBlur={this.onPasswordBlur}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={this.onLoginClick}
|
||||||
|
disabled={this.props.logging}
|
||||||
|
>
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
|
import { Login } from "./login.component";
|
||||||
|
import { attemptLogin } from "./login.actions";
|
||||||
|
|
||||||
|
export const ConnectedLogin = connect(
|
||||||
|
state => ({
|
||||||
|
logging: state.logging,
|
||||||
|
token: state.token
|
||||||
|
}),
|
||||||
|
dispatch => ({
|
||||||
|
onLogin: (user: string, password: string) =>
|
||||||
|
dispatch(attemptLogin(user, password))
|
||||||
|
})
|
||||||
|
)(Login);
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import {
|
||||||
|
LOGIN_REQUEST,
|
||||||
|
LOGIN_SUCCESS,
|
||||||
|
LOGIN_FAILURE
|
||||||
|
} from "./login.actions";
|
||||||
|
|
||||||
|
export const reducer = (
|
||||||
|
state: object = {
|
||||||
|
// initial state
|
||||||
|
logging: false,
|
||||||
|
token: ""
|
||||||
|
},
|
||||||
|
action
|
||||||
|
) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case LOGIN_REQUEST:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
logging: true,
|
||||||
|
token: ""
|
||||||
|
};
|
||||||
|
|
||||||
|
case LOGIN_SUCCESS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
logging: false,
|
||||||
|
token: action.token
|
||||||
|
};
|
||||||
|
|
||||||
|
case LOGIN_FAILURE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
logging: false
|
||||||
|
};
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { Redirect, Switch } from "react-router-dom";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
export class ProtectedRoutes extends React.Component<{
|
||||||
|
token: string,
|
||||||
|
children: any,
|
||||||
|
location: object
|
||||||
|
}> {
|
||||||
|
static propTypes = {
|
||||||
|
token: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.any,
|
||||||
|
location: PropTypes.object.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.props.token ? (
|
||||||
|
<Switch>{this.props.children}</Switch>
|
||||||
|
) : (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: "/login",
|
||||||
|
state: { from: this.props.location }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
|
import { ProtectedRoutes } from "./protectedRoutes.component";
|
||||||
|
|
||||||
|
export const ConnectedProtectedRoutes = connect(state => ({
|
||||||
|
token: state.token
|
||||||
|
}))(ProtectedRoutes);
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export const loginService = (user, password) =>
|
||||||
|
axios.post(
|
||||||
|
`http://localhost:8443/gettoken`,
|
||||||
|
`user=${user}&password=${password}`
|
||||||
|
);
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import { createStore, applyMiddleware } from "redux";
|
||||||
|
import thunk from "redux-thunk";
|
||||||
|
|
||||||
|
import { reducer } from "./login.reducer";
|
||||||
|
|
||||||
|
export const store = createStore(reducer, applyMiddleware(thunk));
|
||||||
Reference in New Issue
Block a user