diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/actions/auth.js | 20 | ||||
| -rw-r--r-- | src/actions/object-stores.js | 24 | ||||
| -rw-r--r-- | src/actions/projects.js | 24 | ||||
| -rw-r--r-- | src/actions/users.js | 19 | ||||
| -rw-r--r-- | src/api/index.js | 13 | ||||
| -rw-r--r-- | src/api/routes/auth.js | 9 | ||||
| -rw-r--r-- | src/api/routes/simulations.js | 73 | ||||
| -rw-r--r-- | src/api/routes/users.js | 90 | ||||
| -rw-r--r-- | src/api/sagas/index.js | 9 | ||||
| -rw-r--r-- | src/api/sagas/users.js | 47 | ||||
| -rw-r--r-- | src/api/socket.js | 40 | ||||
| -rw-r--r-- | src/auth/index.js | 4 | ||||
| -rw-r--r-- | src/components/modals/Modal.js | 1 | ||||
| -rw-r--r-- | src/components/navigation/Navbar.js | 5 | ||||
| -rw-r--r-- | src/components/projects/ProjectAuthList.sass | 5 | ||||
| -rw-r--r-- | src/containers/auth/Login.js | 9 | ||||
| -rw-r--r-- | src/containers/auth/ProfileName.js | 16 | ||||
| -rw-r--r-- | src/containers/projects/VisibleProjectAuthList.js | 9 | ||||
| -rw-r--r-- | src/index.js | 19 | ||||
| -rw-r--r-- | src/pages/Projects.js | 21 | ||||
| -rw-r--r-- | src/reducers/auth.js | 8 | ||||
| -rw-r--r-- | src/reducers/index.js | 6 | ||||
| -rw-r--r-- | src/reducers/objects.js | 44 | ||||
| -rw-r--r-- | src/reducers/projects.js | 15 | ||||
| -rw-r--r-- | src/shapes/index.js | 4 | ||||
| -rw-r--r-- | src/store/configureStore.js | 29 |
26 files changed, 500 insertions, 63 deletions
diff --git a/src/actions/auth.js b/src/actions/auth.js index f54563ae..2ca6a986 100644 --- a/src/actions/auth.js +++ b/src/actions/auth.js @@ -1,15 +1,23 @@ -export const COMPLETE_LOGIN = "COMPLETE_LOGIN"; +export const LOG_IN = "LOG_IN"; +export const LOG_IN_SUCCEEDED = "LOG_IN_SUCCEEDED"; export const LOG_OUT = "LOG_OUT"; -export const completeLogin = (payload) => { +export function logIn(payload) { return { - type: COMPLETE_LOGIN, + type: LOG_IN, payload }; -}; +} -export const logOut = () => { +export function logInSucceeded(payload) { + return { + type: LOG_IN_SUCCEEDED, + payload + }; +} + +export function logOut() { return { type: LOG_OUT }; -}; +} diff --git a/src/actions/object-stores.js b/src/actions/object-stores.js new file mode 100644 index 00000000..08f3f0bd --- /dev/null +++ b/src/actions/object-stores.js @@ -0,0 +1,24 @@ +export const ADD_TO_SIMULATION_STORE = "ADD_TO_SIMULATION_STORE"; +export const ADD_TO_AUTHORIZATION_STORE = "ADD_TO_AUTHORIZATION_STORE"; +export const ADD_TO_USER_STORE = "ADD_TO_USER_STORE"; + +export function addToSimulationStore(simulation) { + return { + type: ADD_TO_SIMULATION_STORE, + simulation + }; +} + +export function addToAuthorizationStore(authorization) { + return { + type: ADD_TO_AUTHORIZATION_STORE, + authorization + }; +} + +export function addToUserStore(user) { + return { + type: ADD_TO_USER_STORE, + user + } +} diff --git a/src/actions/projects.js b/src/actions/projects.js index 0ab1f820..efbd15e9 100644 --- a/src/actions/projects.js +++ b/src/actions/projects.js @@ -5,42 +5,42 @@ export const ADD_PROJECT = "ADD_PROJECT"; export const DELETE_PROJECT = "DELETE_PROJECT"; export const OPEN_PROJECT = "OPEN_PROJECT"; -export const setAuthVisibilityFilter = (filter) => { +export function setAuthVisibilityFilter(filter) { return { type: SET_AUTH_VISIBILITY_FILTER, filter: filter }; -}; +} -export const openNewProjectModal = () => { +export function openNewProjectModal() { return { type: OPEN_NEW_PROJECT_MODAL }; -}; +} -export const closeNewProjectModal = () => { +export function closeNewProjectModal() { return { type: CLOSE_NEW_PROJECT_MODAL }; -}; +} -export const addProject = (name) => { +export function addProject(name) { return { type: ADD_PROJECT, name }; -}; +} -export const deleteProject = (id) => { +export function deleteProject(id) { return { type: DELETE_PROJECT, id }; -}; +} -export const openProject = (id) => { +export function openProject(id) { return { type: OPEN_PROJECT, id }; -}; +} diff --git a/src/actions/users.js b/src/actions/users.js new file mode 100644 index 00000000..093adddd --- /dev/null +++ b/src/actions/users.js @@ -0,0 +1,19 @@ +export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER = "FETCH_AUTHORIZATIONS_OF_CURRENT_USER"; +export const FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED = "FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED"; + +export function fetchAuthorizationsOfCurrentUser() { + return (dispatch, getState) => { + const {auth} = getState(); + dispatch({ + type: FETCH_AUTHORIZATIONS_OF_CURRENT_USER, + userId: auth.userId + }); + }; +} + +export function fetchAuthorizationsOfCurrentUserSucceeded(authorizationsOfCurrentUser) { + return { + type: FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED, + authorizationsOfCurrentUser + }; +} diff --git a/src/api/index.js b/src/api/index.js index e69de29b..a26422c0 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -0,0 +1,13 @@ +import {sendSocketRequest} from "./socket"; + +export function sendRequest(request) { + return new Promise((resolve, reject) => { + sendSocketRequest(request, response => { + if (response.status.code === 200) { + resolve(response.content); + } else { + reject(response); + } + }) + }); +} diff --git a/src/api/routes/auth.js b/src/api/routes/auth.js new file mode 100644 index 00000000..76a39572 --- /dev/null +++ b/src/api/routes/auth.js @@ -0,0 +1,9 @@ +export function performTokenSignIn(token) { + return new Promise((resolve, reject) => { + window["jQuery"].post( + "/tokensignin", + {idtoken: token}, + data => resolve(data) + ) + }); +} diff --git a/src/api/routes/simulations.js b/src/api/routes/simulations.js new file mode 100644 index 00000000..3c7c748e --- /dev/null +++ b/src/api/routes/simulations.js @@ -0,0 +1,73 @@ +import {sendRequest} from "../index"; + +export function addSimulation(simulation) { + return sendRequest({ + path: "/simulations", + method: "POST", + parameters: { + body: { + simulation + }, + path: {}, + query: {} + } + }); +} + +export function getSimulation(simulationId) { + return sendRequest({ + path: "/simulations/{simulationId}", + method: "GET", + parameters: { + body: {}, + path: { + simulationId + }, + query: {} + } + }); +} + +export function updateSimulation(simulation) { + return sendRequest({ + path: "/simulations/{simulationId}", + method: "PUT", + parameters: { + body: { + simulation + }, + path: { + simulationId: simulation.id + }, + query: {} + } + }); +} + +export function deleteSimulation(simulationId) { + return sendRequest({ + path: "/simulations/{simulationId}", + method: "DELETE", + parameters: { + body: {}, + path: { + simulationId + }, + query: {} + } + }); +} + +export function getAuthorizationsBySimulation(simulationId) { + return sendRequest({ + path: "/simulations/{simulationId}/authorizations", + method: "GET", + parameters: { + body: {}, + path: { + simulationId + }, + query: {} + } + }) +} diff --git a/src/api/routes/users.js b/src/api/routes/users.js new file mode 100644 index 00000000..c91e07b2 --- /dev/null +++ b/src/api/routes/users.js @@ -0,0 +1,90 @@ +import {sendRequest} from "../index"; + +export function getUserByEmail(email) { + return sendRequest({ + path: "/users", + method: "GET", + parameters: { + body: {}, + path: {}, + query: { + email + } + } + }); +} + +export function addUser(user) { + return sendRequest({ + path: "/users", + method: "POST", + parameters: { + body: { + user: user + }, + path: {}, + query: {} + } + }); +} + +export function getUser(userId) { + return sendRequest({ + path: "/users/{userId}", + method: "GET", + parameters: { + body: {}, + path: { + userId + }, + query: {} + } + }); +} + +export function updateUser(userId, user) { + return sendRequest({ + path: "/users/{userId}", + method: "PUT", + parameters: { + body: { + user: { + givenName: user.givenName, + familyName: user.familyName + } + }, + path: { + userId + }, + query: {} + } + }); +} + +export function deleteUser(userId) { + return sendRequest({ + path: "/users/{userId}", + method: "DELETE", + parameters: { + body: {}, + path: { + userId + }, + query: {} + } + }); +} + +export function getAuthorizationsByUser(userId) { + return sendRequest({ + path: "/users/{userId}/authorizations", + method: "GET", + parameters: { + body: {}, + path: { + userId + }, + query: {} + } + }); +} diff --git a/src/api/sagas/index.js b/src/api/sagas/index.js new file mode 100644 index 00000000..ea92533a --- /dev/null +++ b/src/api/sagas/index.js @@ -0,0 +1,9 @@ +import {takeEvery} from "redux-saga/effects"; +import {LOG_IN} from "../../actions/auth"; +import {FETCH_AUTHORIZATIONS_OF_CURRENT_USER} from "../../actions/users"; +import {fetchAuthorizationsOfCurrentUser, fetchLoggedInUser} from "./users"; + +export default function* rootSaga() { + yield takeEvery(LOG_IN, fetchLoggedInUser); + yield takeEvery(FETCH_AUTHORIZATIONS_OF_CURRENT_USER, fetchAuthorizationsOfCurrentUser); +} diff --git a/src/api/sagas/users.js b/src/api/sagas/users.js new file mode 100644 index 00000000..b999b693 --- /dev/null +++ b/src/api/sagas/users.js @@ -0,0 +1,47 @@ +import {call, put} from "redux-saga/effects"; +import {logInSucceeded} from "../../actions/auth"; +import {addToAuthorizationStore, addToSimulationStore, addToUserStore} from "../../actions/object-stores"; +import {fetchAuthorizationsOfCurrentUserSucceeded} from "../../actions/users"; +import {performTokenSignIn} from "../routes/auth"; +import {getSimulation} from "../routes/simulations"; +import {addUser, getAuthorizationsByUser, getUser} from "../routes/users"; + +export function* fetchLoggedInUser(action) { + try { + const tokenResponse = yield call(performTokenSignIn, action.payload.authToken); + let userId = tokenResponse.userId; + + if (tokenResponse.isNewUser) { + const newUser = yield call(addUser, action.payload); + userId = newUser.id; + } + + yield put(logInSucceeded(Object.assign({userId}, action.payload))); + } catch (error) { + console.log(error); + } +} + +export function* fetchAuthorizationsOfCurrentUser(action) { + try { + const authorizations = yield call(getAuthorizationsByUser, action.userId); + + for (const authorization of authorizations) { + yield put(addToAuthorizationStore(authorization)); + + const simulation = yield call(getSimulation, authorization.simulationId); + yield put(addToSimulationStore(simulation)); + + const user = yield call(getUser, authorization.userId); + yield put(addToUserStore(user)); + } + + const authorizationIds = authorizations.map(authorization => ( + [authorization.userId, authorization.simulationId] + )); + + yield put(fetchAuthorizationsOfCurrentUserSucceeded(authorizationIds)); + } catch (error) { + console.log(error); + } +} diff --git a/src/api/socket.js b/src/api/socket.js new file mode 100644 index 00000000..86422808 --- /dev/null +++ b/src/api/socket.js @@ -0,0 +1,40 @@ +import io from "socket.io-client"; +import {getAuthToken} from "../auth/index"; + +let socket; +let requestIdCounter = 0; +const callbacks = {}; + +export function setupSocketConnection(onConnect) { + socket = io.connect("http://localhost:8081"); + socket.on("connect", onConnect); + socket.on("response", onSocketResponse); +} + +export function sendSocketRequest(request, callback) { + if (!socket.connected) { + console.error("Attempted to send request over unconnected socket"); + return; + } + + const newId = requestIdCounter++; + callbacks[newId] = callback; + + request.id = newId; + request.token = getAuthToken(); + + if (!request.isRootRoute) { + request.path = "/v1" + request.path; + } + + socket.emit("request", request); + + console.log("Sent socket request:", request); +} + +function onSocketResponse(json) { + const response = JSON.parse(json); + console.log("Received socket response:", response); + callbacks[response.id](response); + delete callbacks[response.id]; +} diff --git a/src/auth/index.js b/src/auth/index.js index 5ea24ff9..1bfc10c1 100644 --- a/src/auth/index.js +++ b/src/auth/index.js @@ -1,4 +1,4 @@ -import {COMPLETE_LOGIN, LOG_OUT} from "../actions/auth"; +import {LOG_IN_SUCCEEDED, LOG_OUT} from "../actions/auth"; const getAuthObject = () => { const authItem = localStorage.getItem("auth"); @@ -38,7 +38,7 @@ export const clearAuthLocalStorage = () => { export const authRedirectMiddleware = store => next => action => { switch (action.type) { - case COMPLETE_LOGIN: + case LOG_IN_SUCCEEDED: saveAuthLocalStorage(action.payload); window.location.href = "/projects"; break; diff --git a/src/components/modals/Modal.js b/src/components/modals/Modal.js index e7054fec..c4f10b29 100644 --- a/src/components/modals/Modal.js +++ b/src/components/modals/Modal.js @@ -26,7 +26,6 @@ class Modal extends React.Component { window["$"]("#" + this.id).on("hide.bs.modal", () => { if (this.visible) { this.props.onCancel(); - console.log("TEST"); } }); } diff --git a/src/components/navigation/Navbar.js b/src/components/navigation/Navbar.js index bbd08591..96dd93b4 100644 --- a/src/components/navigation/Navbar.js +++ b/src/components/navigation/Navbar.js @@ -3,6 +3,7 @@ import FontAwesome from "react-fontawesome"; import Mailto from "react-mailto"; import {Link} from "react-router-dom"; import Logout from "../../containers/auth/Logout"; +import ProfileName from "../../containers/auth/ProfileName"; import "./Navbar.css"; class Navbar extends Component { @@ -23,7 +24,9 @@ class Navbar extends Component { headers={{subject: "OpenDC Support"}}> <FontAwesome name="question-circle" size="lg"/> </Mailto> - <Link className="username" title="My Profile" to="/profile">Profile</Link> + <Link className="username" title="My Profile" to="/profile"> + <ProfileName/> + </Link> <Logout/> </div> </div> diff --git a/src/components/projects/ProjectAuthList.sass b/src/components/projects/ProjectAuthList.sass index 1c65305e..5cdfacaa 100644 --- a/src/components/projects/ProjectAuthList.sass +++ b/src/components/projects/ProjectAuthList.sass @@ -48,10 +48,13 @@ span margin-right: 10px +.project-row .project-icons + text-align: right + .project-row .project-icons div display: inline position: relative - top: 5px + top: 4px width: 30px height: 30px margin-right: 5px diff --git a/src/containers/auth/Login.js b/src/containers/auth/Login.js index 358ea7e9..f1deb33c 100644 --- a/src/containers/auth/Login.js +++ b/src/containers/auth/Login.js @@ -2,7 +2,7 @@ import PropTypes from "prop-types"; import React from "react"; import GoogleLogin from "react-google-login"; import {connect} from "react-redux"; -import {completeLogin} from "../../actions/auth"; +import {logIn} from "../../actions/auth"; class LoginContainer extends React.Component { static propTypes = { @@ -12,8 +12,11 @@ class LoginContainer extends React.Component { onAuthResponse(response) { this.props.onLogin({ + email: response.getBasicProfile().getEmail(), + givenName: response.getBasicProfile().getGivenName(), + familyName: response.getBasicProfile().getFamilyName(), googleId: response.googleId, - authToken: response.accessToken, + authToken: response.getAuthResponse().id_token, expiresAt: response.getAuthResponse().expires_at }); } @@ -44,7 +47,7 @@ const mapStateToProps = (state, ownProps) => { const mapDispatchToProps = dispatch => { return { - onLogin: (payload) => dispatch(completeLogin(payload)), + onLogin: (payload) => dispatch(logIn(payload)), }; }; diff --git a/src/containers/auth/ProfileName.js b/src/containers/auth/ProfileName.js new file mode 100644 index 00000000..27df133c --- /dev/null +++ b/src/containers/auth/ProfileName.js @@ -0,0 +1,16 @@ +import React from "react"; +import {connect} from "react-redux"; + +const mapStateToProps = state => { + return { + text: state.auth.givenName + " " + state.auth.familyName + }; +}; + +const SpanElement = ({text}) => <span>{text}</span>; + +const ProfileName = connect( + mapStateToProps +)(SpanElement); + +export default ProfileName; diff --git a/src/containers/projects/VisibleProjectAuthList.js b/src/containers/projects/VisibleProjectAuthList.js index 746380f6..f668711e 100644 --- a/src/containers/projects/VisibleProjectAuthList.js +++ b/src/containers/projects/VisibleProjectAuthList.js @@ -15,8 +15,15 @@ const getVisibleProjectAuths = (projectAuths, filter) => { }; const mapStateToProps = state => { + const denormalizedAuthorizations = state.authorizationsOfCurrentUser.map(authorizationIds => { + const authorization = Object.assign({}, state.objects.authorizations[authorizationIds]); + authorization.simulation = state.objects.simulations[authorization.simulationId]; + authorization.user = state.objects.users[authorization.userId]; + return authorization; + }); + return { - authorizations: getVisibleProjectAuths(state.authorizations, state.authVisibilityFilter) + authorizations: getVisibleProjectAuths(denormalizedAuthorizations, state.authVisibilityFilter) }; }; diff --git a/src/index.js b/src/index.js index 1176224e..8fa45ebf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,18 +1,21 @@ import React from "react"; import ReactDOM from "react-dom"; import {Provider} from "react-redux"; +import {setupSocketConnection} from "./api/socket"; import "./index.css"; import registerServiceWorker from "./registerServiceWorker"; import Routes from "./routes"; import configureStore from "./store/configureStore"; -const store = configureStore(); +setupSocketConnection(() => { + const store = configureStore(); -ReactDOM.render( - <Provider store={store}> - <Routes/> - </Provider>, - document.getElementById('root') -); + ReactDOM.render( + <Provider store={store}> + <Routes/> + </Provider>, + document.getElementById('root') + ); -registerServiceWorker(); + registerServiceWorker(); +}); diff --git a/src/pages/Projects.js b/src/pages/Projects.js index 69a28f9d..06655768 100644 --- a/src/pages/Projects.js +++ b/src/pages/Projects.js @@ -1,6 +1,7 @@ import React from 'react'; import {connect} from "react-redux"; import {addProject, openNewProjectModal} from "../actions/projects"; +import {fetchAuthorizationsOfCurrentUser} from "../actions/users"; import Navbar from "../components/navigation/Navbar"; import ProjectFilterPanel from "../components/projects/FilterPanel"; import NewProjectButton from "../components/projects/NewProjectButton"; @@ -9,9 +10,9 @@ import NewProjectModal from "../containers/projects/NewProjectModal"; import VisibleProjectList from "../containers/projects/VisibleProjectAuthList"; import "./Projects.css"; -class Projects extends React.Component { +class ProjectsContainer extends React.Component { componentDidMount() { - // TODO perform initial fetch + this.props.fetchAuthorizationsOfCurrentUser(); } onInputSubmission(text) { @@ -25,7 +26,7 @@ class Projects extends React.Component { <div className="container project-page-container full-height"> <ProjectFilterPanel/> <VisibleProjectList/> - <NewProjectButton onClick={() => {this.props.dispatch(openNewProjectModal())}}/> + <NewProjectButton onClick={() => {this.props.openNewProjectModal()}}/> </div> <NewProjectModal/> <Login visible={false}/> @@ -34,4 +35,16 @@ class Projects extends React.Component { } } -export default connect()(Projects); +const mapDispatchToProps = dispatch => { + return { + fetchAuthorizationsOfCurrentUser: () => dispatch(fetchAuthorizationsOfCurrentUser()), + openNewProjectModal: () => dispatch(openNewProjectModal()), + }; +}; + +const Projects = connect( + undefined, + mapDispatchToProps +)(ProjectsContainer); + +export default Projects; diff --git a/src/reducers/auth.js b/src/reducers/auth.js index 0d01b300..a65b3b3e 100644 --- a/src/reducers/auth.js +++ b/src/reducers/auth.js @@ -1,12 +1,12 @@ -import {COMPLETE_LOGIN, LOG_OUT} from "../actions/auth"; +import {LOG_IN_SUCCEEDED, LOG_OUT} from "../actions/auth"; -export const auth = (state = {}, action) => { +export function auth(state = {}, action) { switch (action.type) { - case COMPLETE_LOGIN: + case LOG_IN_SUCCEEDED: return action.payload; case LOG_OUT: return {}; default: return state; } -}; +} diff --git a/src/reducers/index.js b/src/reducers/index.js index 4e35f6e8..71379a6f 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -1,10 +1,12 @@ import {combineReducers} from "redux"; import {auth} from "./auth"; -import {authorizations, authVisibilityFilter, newProjectModalVisible} from "./projects"; +import {objects} from "./objects"; +import {authorizationsOfCurrentUser, authVisibilityFilter, newProjectModalVisible} from "./projects"; const rootReducer = combineReducers({ auth, - authorizations, + objects, + authorizationsOfCurrentUser, newProjectModalVisible, authVisibilityFilter, }); diff --git a/src/reducers/objects.js b/src/reducers/objects.js new file mode 100644 index 00000000..69e68ca7 --- /dev/null +++ b/src/reducers/objects.js @@ -0,0 +1,44 @@ +import {combineReducers} from "redux"; +import {ADD_TO_AUTHORIZATION_STORE, ADD_TO_SIMULATION_STORE, ADD_TO_USER_STORE} from "../actions/object-stores"; + +export const objects = combineReducers({ + simulations, + authorizations, + users, +}); + +function simulations(state = {}, action) { + switch (action.type) { + case ADD_TO_SIMULATION_STORE: + return Object.assign( + state, + {[action.simulation.id]: action.simulation} + ); + default: + return state; + } +} + +function authorizations(state = {}, action) { + switch (action.type) { + case ADD_TO_AUTHORIZATION_STORE: + return Object.assign( + state, + {[[action.authorization.userId, action.authorization.simulationId]]: action.authorization} + ); + default: + return state; + } +} + +function users(state = {}, action) { + switch (action.type) { + case ADD_TO_USER_STORE: + return Object.assign( + state, + {[action.user.id]: action.user} + ); + default: + return state; + } +} diff --git a/src/reducers/projects.js b/src/reducers/projects.js index b6450fd7..ba3c792d 100644 --- a/src/reducers/projects.js +++ b/src/reducers/projects.js @@ -5,9 +5,12 @@ import { OPEN_NEW_PROJECT_MODAL, SET_AUTH_VISIBILITY_FILTER } from "../actions/projects"; +import {FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED} from "../actions/users"; -export const authorizations = (state = [], action) => { +export function authorizationsOfCurrentUser(state = [], action) { switch (action.type) { + case FETCH_AUTHORIZATIONS_OF_CURRENT_USER_SUCCEEDED: + return action.authorizationsOfCurrentUser; case ADD_PROJECT: return [ ...state, @@ -22,9 +25,9 @@ export const authorizations = (state = [], action) => { default: return state; } -}; +} -export const newProjectModalVisible = (state = false, action) => { +export function newProjectModalVisible(state = false, action) { switch (action.type) { case OPEN_NEW_PROJECT_MODAL: return true; @@ -33,13 +36,13 @@ export const newProjectModalVisible = (state = false, action) => { default: return state; } -}; +} -export const authVisibilityFilter = (state = "SHOW_ALL", action) => { +export function authVisibilityFilter(state = "SHOW_ALL", action) { switch (action.type) { case SET_AUTH_VISIBILITY_FILTER: return action.filter; default: return state; } -}; +} diff --git a/src/shapes/index.js b/src/shapes/index.js index 72153f54..770e8d76 100644 --- a/src/shapes/index.js +++ b/src/shapes/index.js @@ -4,7 +4,7 @@ const Shapes = {}; Shapes.User = PropTypes.shape({ id: PropTypes.number.isRequired, - googleId: PropTypes.number.isRequired, + googleId: PropTypes.string.isRequired, email: PropTypes.string.isRequired, givenName: PropTypes.string.isRequired, familyName: PropTypes.string.isRequired, @@ -25,4 +25,4 @@ Shapes.Authorization = PropTypes.shape({ authorizationLevel: PropTypes.string.isRequired, }); -export default Shapes;
\ No newline at end of file +export default Shapes; diff --git a/src/store/configureStore.js b/src/store/configureStore.js index ec932cf7..ecd804a2 100644 --- a/src/store/configureStore.js +++ b/src/store/configureStore.js @@ -1,20 +1,29 @@ import {applyMiddleware, compose, createStore} from "redux"; import persistState from "redux-localstorage"; import {createLogger} from "redux-logger"; +import createSagaMiddleware from 'redux-saga'; +import thunk from "redux-thunk"; +import rootSaga from "../api/sagas/index"; import {authRedirectMiddleware} from "../auth/index"; import rootReducer from "../reducers/index"; +const sagaMiddleware = createSagaMiddleware(); const logger = createLogger(); -const configureStore = () => createStore( - rootReducer, - compose( - persistState("auth"), - applyMiddleware( - logger, - authRedirectMiddleware, +export default function configureStore() { + const store = createStore( + rootReducer, + compose( + persistState("auth"), + applyMiddleware( + logger, + thunk, + sagaMiddleware, + authRedirectMiddleware, + ) ) - ) -); + ); + sagaMiddleware.run(rootSaga); -export default configureStore; + return store; +} |
