parent
4cadf5df3a
commit
e69773ac8e
15 changed files with 295 additions and 28 deletions
@ -0,0 +1,50 @@ |
||||
import { |
||||
IS_SENDING_USER_REQUEST, |
||||
SET_USER_REQUEST_ERROR, |
||||
CLEAR_USER_REQUEST_ERROR, |
||||
SET_USER_REQUEST_SUCCESS, |
||||
CLEAR_USER_REQUEST_SUCCESS, |
||||
SET_SELF_USER |
||||
} from "../../constants/user.constants"; |
||||
import { parseError } from "../common.actions"; |
||||
|
||||
export function isSendingUserRequest(sendingRequest) { |
||||
return { |
||||
type: IS_SENDING_USER_REQUEST, |
||||
data: sendingRequest |
||||
}; |
||||
} |
||||
|
||||
export function setUserRequestError(exception) { |
||||
let error = parseError(exception); |
||||
return { |
||||
type: SET_USER_REQUEST_ERROR, |
||||
data: error |
||||
}; |
||||
} |
||||
|
||||
export function clearUserRequestError() { |
||||
return { |
||||
type: CLEAR_USER_REQUEST_ERROR |
||||
}; |
||||
} |
||||
|
||||
export function setUserRequestSuccess(response) { |
||||
return { |
||||
type: SET_USER_REQUEST_SUCCESS, |
||||
data: response.detail || response |
||||
}; |
||||
} |
||||
|
||||
export function clearUserRequestSuccess() { |
||||
return { |
||||
type: CLEAR_USER_REQUEST_SUCCESS |
||||
}; |
||||
} |
||||
|
||||
export function setSelfUser(selfUser) { |
||||
return { |
||||
type: SET_SELF_USER, |
||||
data: selfUser |
||||
}; |
||||
} |
@ -0,0 +1,7 @@ |
||||
import { SEND_GET_SELF_USER_REQUEST } from "../../constants/user.constants"; |
||||
|
||||
export function sendGetSelfUserRequest() { |
||||
return { |
||||
type: SEND_GET_SELF_USER_REQUEST |
||||
}; |
||||
} |
@ -0,0 +1,5 @@ |
||||
import { get } from "./baseApi"; |
||||
|
||||
export function getSelfUser() { |
||||
return get("/user/").then(resp => Promise.resolve(resp)); |
||||
} |
@ -1,30 +1,66 @@ |
||||
import PropTypes from "prop-types"; |
||||
import React from "react"; |
||||
import React, { Component } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { Redirect, Route } from "react-router-dom"; |
||||
import { Loader } from "semantic-ui-react"; |
||||
|
||||
import { sendGetSelfUserRequest } from "../../actions/user/saga.actions"; |
||||
|
||||
const propTypes = { |
||||
path: PropTypes.string.isRequired, |
||||
userToken: PropTypes.string.isRequired, |
||||
component: PropTypes.oneOfType([PropTypes.element, PropTypes.func]).isRequired |
||||
selfUser: PropTypes.object.isRequired, |
||||
isSendingUserRequest: PropTypes.bool.isRequired, |
||||
path: PropTypes.string.isRequired, |
||||
component: PropTypes.oneOfType([PropTypes.element, PropTypes.func]) |
||||
.isRequired, |
||||
dispatch: PropTypes.func.isRequired |
||||
}; |
||||
|
||||
const PrivateRoute = ({ userToken, component, ...rest }) => { |
||||
return ( |
||||
<Route |
||||
{...rest} |
||||
render={props => { |
||||
if (!!userToken) return React.createElement(component, props); |
||||
return <Redirect to="/auth/login" />; |
||||
}} |
||||
/> |
||||
); |
||||
}; |
||||
class PrivateRoute extends Component { |
||||
componentWillMount() { |
||||
const { dispatch, userToken, selfUser } = this.props; |
||||
// If the user token exists and the self user object isn't loaded, dispatch |
||||
if (userToken && Object.keys(selfUser).length === 0) { |
||||
dispatch(sendGetSelfUserRequest()); |
||||
} |
||||
} |
||||
|
||||
render() { |
||||
const { |
||||
userToken, |
||||
selfUser, |
||||
isSendingUserRequest, |
||||
component, |
||||
...rest |
||||
} = this.props; |
||||
// If the user token exists and |
||||
// * self user object isn't loaded yet or |
||||
// * we are still sending user request |
||||
// show loading spinner |
||||
if ( |
||||
!!userToken && |
||||
(Object.keys(selfUser).length === 0 || isSendingUserRequest) |
||||
) { |
||||
return <Loader active />; |
||||
} |
||||
return ( |
||||
<Route |
||||
{...rest} |
||||
render={props => { |
||||
if (!!userToken) return React.createElement(component, props); |
||||
return <Redirect to="/auth/login" />; |
||||
}} |
||||
/> |
||||
); |
||||
} |
||||
} |
||||
|
||||
PrivateRoute.propTypes = propTypes; |
||||
|
||||
const mapStateToProps = state => ({ |
||||
userToken: state.auth.userToken |
||||
userToken: state.auth.userToken, |
||||
selfUser: state.user.selfUser, |
||||
isSendingUserRequest: state.user.isSendingUserRequest |
||||
}); |
||||
|
||||
export default connect(mapStateToProps)(PrivateRoute); |
||||
|
@ -0,0 +1,47 @@ |
||||
import React, { Component } from "react"; |
||||
import { connect } from "react-redux"; |
||||
import { Card, Container, Header, Label, List } from "semantic-ui-react"; |
||||
|
||||
class Profile extends Component { |
||||
render() { |
||||
const { selfUser } = this.props; |
||||
return <ProfileView user={selfUser} />; |
||||
} |
||||
} |
||||
|
||||
function mapStateToProps(state) { |
||||
return { ...state.user }; |
||||
} |
||||
|
||||
const ProfileView = ({ user }) => ( |
||||
<Container> |
||||
<Header>Profile</Header> |
||||
<Card> |
||||
<Card.Content> |
||||
<Card.Header>{user.username || "No username!"}</Card.Header> |
||||
<Card.Meta>{user.email || "No email!"}</Card.Meta> |
||||
<Card.Description> |
||||
<span> |
||||
{user.client && "Client"}{user.provider && "Provider"} |
||||
{!user.client && !user.provider && "User Registration Not Completed"} |
||||
</span> |
||||
{user.first_name} {user.last_name} |
||||
{user.userinfo && <List> |
||||
{Object.keys(user.userinfo).map(function(key) { |
||||
return (<List.Item key={key}> |
||||
{user.userinfo[key]} |
||||
</List.Item>) |
||||
})} |
||||
</List>} |
||||
</Card.Description> |
||||
</Card.Content> |
||||
<Card.Content extra> |
||||
<Label color={user.is_active ? "teal" : "red"} size="tiny" tag> |
||||
{user.is_active ? "Active" : "Deactivated"} |
||||
</Label> |
||||
</Card.Content> |
||||
</Card> |
||||
</Container> |
||||
); |
||||
|
||||
export default connect(mapStateToProps)(Profile); |
@ -0,0 +1,10 @@ |
||||
// Reducer User Action Constants
|
||||
export const IS_SENDING_USER_REQUEST = "IS_SENDING_USER_REQUEST"; |
||||
export const SET_USER_REQUEST_ERROR = "SET_USER_REQUEST_ERROR"; |
||||
export const CLEAR_USER_REQUEST_ERROR = "CLEAR_USER_REQUEST_ERROR"; |
||||
export const SET_USER_REQUEST_SUCCESS = "SET_USER_REQUEST_SUCCESS"; |
||||
export const CLEAR_USER_REQUEST_SUCCESS = "CLEAR_USER_REQUEST_SUCCESS"; |
||||
export const SET_SELF_USER = "SET_SELF_USER"; |
||||
|
||||
// Saga User Action Constants
|
||||
export const SEND_GET_SELF_USER_REQUEST = "SEND_GET_SELF_USER_REQUEST"; |
@ -1,8 +1,10 @@ |
||||
import { combineReducers } from "redux"; |
||||
import authReducer from "./authReducer"; |
||||
import userReducer from "./userReducer"; |
||||
|
||||
const reducer = combineReducers({ |
||||
auth: authReducer |
||||
auth: authReducer, |
||||
user: userReducer |
||||
}); |
||||
|
||||
export default reducer; |
||||
|
@ -0,0 +1,54 @@ |
||||
import { |
||||
IS_SENDING_USER_REQUEST, |
||||
SET_USER_REQUEST_ERROR, |
||||
CLEAR_USER_REQUEST_ERROR, |
||||
SET_USER_REQUEST_SUCCESS, |
||||
CLEAR_USER_REQUEST_SUCCESS, |
||||
SET_SELF_USER |
||||
} from "../constants/user.constants"; |
||||
|
||||
const initialState = { |
||||
isSendingUserRequest: false, |
||||
userRequestError: "", |
||||
userRequestSuccess: "", |
||||
selfUser: {} |
||||
}; |
||||
|
||||
function userReducer(state = initialState, action) { |
||||
switch (action.type) { |
||||
case IS_SENDING_USER_REQUEST: |
||||
return { |
||||
...state, |
||||
isSendingUserRequest: action.data |
||||
}; |
||||
case SET_USER_REQUEST_ERROR: |
||||
return { |
||||
...state, |
||||
userRequestError: action.data |
||||
}; |
||||
case CLEAR_USER_REQUEST_ERROR: |
||||
return { |
||||
...state, |
||||
userRequestError: "" |
||||
}; |
||||
case SET_USER_REQUEST_SUCCESS: |
||||
return { |
||||
...state, |
||||
userRequestSuccess: action.data |
||||
}; |
||||
case CLEAR_USER_REQUEST_SUCCESS: |
||||
return { |
||||
...state, |
||||
userRequestSuccess: "" |
||||
}; |
||||
case SET_SELF_USER: |
||||
return { |
||||
...state, |
||||
selfUser: action.data |
||||
}; |
||||
default: |
||||
return state; |
||||
} |
||||
} |
||||
|
||||
export default userReducer; |
@ -0,0 +1,43 @@ |
||||
import { effects } from "redux-saga"; |
||||
import { setSelfUserToken } from "../actions/auth/reducer.actions"; |
||||
import { |
||||
isSendingUserRequest, |
||||
setUserRequestError, |
||||
setUserRequestSuccess, |
||||
clearUserRequestError, |
||||
clearUserRequestSuccess, |
||||
setSelfUser |
||||
} from "../actions/user/reducer.actions"; |
||||
import { getSelfUser } from "../api/user.api"; |
||||
|
||||
function* getSelfUserCall() { |
||||
yield effects.put(isSendingUserRequest(true)); |
||||
try { |
||||
const wasSuccessful = yield effects.call(getSelfUser); |
||||
yield effects.put(setUserRequestSuccess(wasSuccessful)); |
||||
yield effects.put(clearUserRequestError()); |
||||
// Check if the user exists, if yes set the user, otherwise force logout
|
||||
if (wasSuccessful.results && wasSuccessful.results.length) { |
||||
yield effects.put(setSelfUser(wasSuccessful.results[0])); |
||||
} else { |
||||
yield effects.put(setSelfUserToken("")); |
||||
yield effects.put(setSelfUser({})); |
||||
} |
||||
return wasSuccessful; |
||||
} catch (exception) { |
||||
yield effects.put(setUserRequestError(exception)); |
||||
return false; |
||||
} finally { |
||||
yield effects.put(isSendingUserRequest(false)); |
||||
} |
||||
} |
||||
|
||||
export function* getSelfUserFlow(request) { |
||||
yield effects.put(clearUserRequestSuccess()); |
||||
yield effects.put(clearUserRequestError()); |
||||
const wasSuccessful = yield effects.call(getSelfUserCall); |
||||
if (!wasSuccessful) { |
||||
yield effects.put(setSelfUserToken("")); |
||||
yield effects.put(setSelfUser({})); |
||||
} |
||||
} |
Loading…
Reference in new issue