Commit 60214959 authored by Tamlyn Rhodes's avatar Tamlyn Rhodes

Create entity selectors

Use reselect to aid with selector composition.
Remove currentUser.isAuthenticated state property as it can be inferred.
parent 6482f315
Pipeline #3110 passed with stage
in 2 minutes and 36 seconds
......@@ -36,7 +36,8 @@
"redux": "^3.6.0",
"redux-form": "^7.0.3",
"redux-logger": "^3.0.1",
"redux-thunk": "^2.2.0"
"redux-thunk": "^2.2.0",
"reselect": "^3.0.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",
......
......@@ -5,6 +5,7 @@ import { push } from 'react-router-redux'
import PropTypes from 'prop-types'
import actions from '../actions'
import { selectCurrentUser } from '../selectors'
export class AuthenticatedComponent extends React.Component {
componentWillMount() {
......@@ -39,7 +40,7 @@ AuthenticatedComponent.propTypes = {
function mapState(state) {
return {
isFetching: state.currentUser.isFetching,
isAuthenticated: state.currentUser.isAuthenticated,
isAuthenticated: !!selectCurrentUser(state),
}
}
......
......@@ -7,6 +7,7 @@ import _ from 'lodash/fp'
import * as T from '../actions/types'
import 'event-source-polyfill'
import token from '../helpers/token'
import { selectCurrentUser } from '../selectors'
const actionMap = {
'collection:create': T.CREATE_COLLECTION_SUCCESS,
......@@ -171,7 +172,7 @@ UpdateSubscriber.propTypes = {
export default connect(
state => ({
currentUser: state.currentUser,
currentUser: selectCurrentUser(state),
}),
dispatch => ({
handleUpdate: (type, body) => dispatch({ type, ...body }),
......
......@@ -6,6 +6,7 @@ import { connect } from 'react-redux'
import { compose } from 'redux'
import withAuthsome from './withAuthsome'
import { selectCurrentUser } from '../selectors'
export class Authorize extends React.Component {
constructor(props) {
......@@ -57,10 +58,7 @@ Authorize.propTypes = {
function mapState(state) {
return {
teams: state.teams,
collections: state.collections,
fragments: state.fragments,
currentUser: state.currentUser.user,
currentUser: selectCurrentUser(state),
}
}
......
import Authsome from 'authsome'
import { connect } from 'react-redux'
import config from 'config'
import {
selectCollection,
selectFragment,
selectTeam,
selectUser,
} from '../selectors'
const mode = require(config.authsome.mode)
// higher order component to inject authsome into a component
export default function withAuthsome() {
const authsome = new Authsome({...config.authsome, mode}, {})
const authsome = new Authsome({ ...config.authsome, mode }, {})
function mapState(state) {
authsome.context = {
// fetch entities from store instead of database
models: {
Collection: {
find: id =>
state.collections.find(collection => collection.id === id),
},
Fragment: {
find: id => state.fragments[id],
},
Team: {
find: id => state.teams.find(team => team.id === id),
},
User: {
find: id => {
return state.users.users.find(user => user.id === id)
},
},
Collection: { find: id => selectCollection(state, { id }) },
Fragment: { find: id => selectFragment(state, { id }) },
Team: { find: id => selectTeam(state, { id }) },
User: { find: id => selectUser(state, { id }) },
},
}
......
......@@ -5,19 +5,19 @@ import {
LOGOUT_SUCCESS,
} from '../actions/types'
export default function(
state = {
isFetching: false,
isAuthenticated: false,
},
action,
) {
const initialState = {
isFetching: false,
// TODO remove isAuthenticated in favour of !!user
isAuthenticated: false,
user: null,
}
export default function(state = initialState, action) {
switch (action.type) {
case GET_CURRENT_USER_REQUEST:
return {
...state,
isFetching: true,
isAuthenticated: false,
}
case GET_CURRENT_USER_SUCCESS:
......@@ -33,6 +33,7 @@ export default function(
...state,
isFetching: false,
isAuthenticated: false,
user: null,
}
case LOGOUT_SUCCESS:
......
import { createSelector } from 'reselect'
export const selectCollections = state => state.collections
export const selectTeams = state => state.teams
export const selectUsers = state => state.users.users
export const selectFragments = state => state.fragments
export const selectCollection = createSelector(
selectCollections,
(_, { id }) => id,
(collections, id) => collections.find(collection => collection.id === id),
)
export const selectFragment = createSelector(
selectFragments,
(_, { id }) => id,
(fragments, id) => fragments[id],
)
export const selectTeam = createSelector(
selectTeams,
(_, { id }) => id,
(teams, id) => teams.find(team => team.id === id),
)
export const selectUser = createSelector(
selectUsers,
(_, { id }) => id,
(users, id) => users.find(user => user.id === id),
)
export const selectCurrentUser = state => state.currentUser.user
......@@ -34,7 +34,11 @@ describe('currentUser reducers', () => {
type: T.GET_CURRENT_USER_FAILURE,
},
)
expect(actual).toEqual({ isFetching: false, isAuthenticated: false })
expect(actual).toEqual({
isFetching: false,
isAuthenticated: false,
user: null,
})
})
it('currentUser request', () => {
......@@ -44,7 +48,7 @@ describe('currentUser reducers', () => {
type: T.GET_CURRENT_USER_REQUEST,
},
)
expect(actual).toEqual({ isFetching: true, isAuthenticated: false })
expect(actual).toEqual({ isFetching: true })
})
it('logout success', () => {
......
import { selectUser } from '../../src/selectors'
describe('Selectors', () => {
it('selectUser', () => {
const user2 = { id: 2, foo: 'bar' }
const state = {
users: {
users: [{ id: 1 }, user2],
},
}
expect(selectUser(state, { id: 2 })).toEqual(user2)
})
})
......@@ -3936,6 +3936,10 @@ require-uncached@^1.0.3:
caller-path "^0.1.0"
resolve-from "^1.0.0"
reselect@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment