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 PropTypes from "prop-types"; |
||||||
import React from "react"; |
import React, { Component } from "react"; |
||||||
import { connect } from "react-redux"; |
import { connect } from "react-redux"; |
||||||
import { Redirect, Route } from "react-router-dom"; |
import { Redirect, Route } from "react-router-dom"; |
||||||
|
import { Loader } from "semantic-ui-react"; |
||||||
|
|
||||||
|
import { sendGetSelfUserRequest } from "../../actions/user/saga.actions"; |
||||||
|
|
||||||
const propTypes = { |
const propTypes = { |
||||||
path: PropTypes.string.isRequired, |
|
||||||
userToken: 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 }) => { |
class PrivateRoute extends Component { |
||||||
return ( |
componentWillMount() { |
||||||
<Route |
const { dispatch, userToken, selfUser } = this.props; |
||||||
{...rest} |
// If the user token exists and the self user object isn't loaded, dispatch |
||||||
render={props => { |
if (userToken && Object.keys(selfUser).length === 0) { |
||||||
if (!!userToken) return React.createElement(component, props); |
dispatch(sendGetSelfUserRequest()); |
||||||
return <Redirect to="/auth/login" />; |
} |
||||||
}} |
} |
||||||
/> |
|
||||||
); |
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; |
PrivateRoute.propTypes = propTypes; |
||||||
|
|
||||||
const mapStateToProps = state => ({ |
const mapStateToProps = state => ({ |
||||||
userToken: state.auth.userToken |
userToken: state.auth.userToken, |
||||||
|
selfUser: state.user.selfUser, |
||||||
|
isSendingUserRequest: state.user.isSendingUserRequest |
||||||
}); |
}); |
||||||
|
|
||||||
export default connect(mapStateToProps)(PrivateRoute); |
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 { combineReducers } from "redux"; |
||||||
import authReducer from "./authReducer"; |
import authReducer from "./authReducer"; |
||||||
|
import userReducer from "./userReducer"; |
||||||
|
|
||||||
const reducer = combineReducers({ |
const reducer = combineReducers({ |
||||||
auth: authReducer |
auth: authReducer, |
||||||
|
user: userReducer |
||||||
}); |
}); |
||||||
|
|
||||||
export default reducer; |
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