Newer
Older

Alexandru Munteanu
committed
import { get, orderBy } from 'lodash'
import { selectCurrentUser } from 'xpub-selectors'
import {
get as apiGet,
create,
remove,
update,
} from 'pubsweet-client/src/helpers/api'

Alexandru Munteanu
committed
import { orderReviewers } from './utils'
const GET_REVIEWERS_REQUEST = 'GET_REVIEWERS_REQUEST'
const GET_REVIEWERS_ERROR = 'GET_REVIEWERS_ERROR'
const GET_REVIEWERS_SUCCESS = 'GET_REVIEWERS_SUCCESS'
export const getReviewersRequest = () => ({
type: GET_REVIEWERS_REQUEST,
})
export const getReviewersError = error => ({
type: GET_REVIEWERS_ERROR,
error,
})
export const getReviewersSuccess = reviewers => ({
type: GET_REVIEWERS_SUCCESS,
payload: { reviewers },
})
// reviewer invite constants and action creators
const INVITE_REVIEWER_REQUEST = 'INVITE_REVIEWER_REQUEST'
const INVITE_REVIEWER_SUCCESS = 'INVITE_REVIEWER_SUCCESS'
const INVITE_REVIEWER_ERROR = 'INVITE_REVIEWER_ERROR'
const inviteRequest = () => ({
type: INVITE_REVIEWER_REQUEST,
})
const inviteSuccess = () => ({
type: INVITE_REVIEWER_SUCCESS,
})
const inviteError = error => ({
type: INVITE_REVIEWER_ERROR,
error,
})
// reviewer decision constants and action creators
const REVIEWER_DECISION_REQUEST = 'REVIEWER_DECISION_REQUEST'
const REVIEWER_DECISION_ERROR = 'REVIEWER_DECISION_ERROR'
const REVIEWER_DECISION_SUCCESS = 'REVIEWER_DECISION_SUCCESS'
const reviewerDecisionRequest = () => ({ type: REVIEWER_DECISION_REQUEST })
const reviewerDecisionError = error => ({
type: REVIEWER_DECISION_ERROR,
error,
})
const reviewerDecisionSuccess = () => ({ type: REVIEWER_DECISION_SUCCESS })
decision: false,
invite: false,
reviewers: false,
},
error: null,
reviewers: [],
const CLEAR_ERROR = 'reviewers/CLEAR_ERROR'
export const clearReviewersError = () => ({
type: CLEAR_ERROR,
})
export const selectReviewers = state => get(state, 'reviewers.reviewers') || []
export const selectReviewersError = state => get(state, 'reviewers.error')
export const selectFetchingReviewers = state =>
get(state, 'reviewers.fetching.reviewers') || false
get(state, 'reviewers.fetching.invite') || false
export const selectFetchingDecision = state =>
get(state, 'reviewers.fetching.decision') || false

Alexandru Munteanu
committed
export const selectInvitation = (state, fragmentId) => {
const currentUser = selectCurrentUser(state)

Alexandru Munteanu
committed
const invitations = get(state, `fragments.${fragmentId}.invitations`) || []
return invitations.find(
i => i.userId === currentUser.id && i.role === 'reviewer' && !i.hasAnswer,
)
}

Alexandru Munteanu
committed
export const currentUserIsReviewer = (state, fragmentId) => {
const currentUser = selectCurrentUser(state)

Alexandru Munteanu
committed
const invitations = get(state, `fragments.${fragmentId}.invitations`) || []
return !!invitations.find(
i =>
i.userId === currentUser.id &&
i.role === 'reviewer' &&
i.hasAnswer &&
i.isAccepted,
)
}

Alexandru Munteanu
committed
export const getCollectionReviewers = (
collectionId,
fragmentId,
) => dispatch => {
dispatch(getReviewersRequest())

Alexandru Munteanu
committed
return apiGet(
`/collections/${collectionId}/fragments/${fragmentId}/invitations?role=reviewer`,
).then(

Alexandru Munteanu
committed
r => dispatch(getReviewersSuccess(orderBy(r, orderReviewers))),

Alexandru Munteanu
committed
err => {
dispatch(getReviewersError(err))
throw err
},
)
}
// #region Actions - invitations

Alexandru Munteanu
committed
export const inviteReviewer = (
reviewerData,
collectionId,
fragmentId,
) => dispatch => {
dispatch(inviteRequest())

Alexandru Munteanu
committed
return create(
`/collections/${collectionId}/fragments/${fragmentId}/invitations`,
{
...reviewerData,
role: 'reviewer',
},
).then(
() => dispatch(inviteSuccess()),
err => {
dispatch(inviteError(get(JSON.parse(err.response), 'error')))
throw err
},
export const setReviewerPassword = reviewerBody => dispatch => {
dispatch(reviewerDecisionRequest())
return create(`/users/reset-password`, reviewerBody).then(r => {
dispatch(reviewerDecisionSuccess())
return r
})
}
export const revokeReviewer = (
invitationId,
collectionId,
fragmentId,
) => dispatch => {
dispatch(inviteRequest())
return remove(
`/collections/${collectionId}/fragments/${fragmentId}/invitations/${invitationId}`,
).then(
() => dispatch(inviteSuccess()),
err => {
dispatch(inviteError(get(JSON.parse(err.response), 'error')))
throw err
},
// #region Actions - decision
export const reviewerDecision = (
invitationId,
collectionId,

Alexandru Munteanu
committed
fragmentId,
agree = true,
) => dispatch => {
dispatch(reviewerDecisionRequest())

Alexandru Munteanu
committed
return update(
`/collections/${collectionId}/fragments/${fragmentId}/invitations/${invitationId}`,
{
isAccepted: agree,
},
).then(
dispatch(reviewerDecisionSuccess())
return res
},
err => {
dispatch(reviewerDecisionError(err.message))
throw err
},
)
}
export const reviewerDecline = (
invitationId,
collectionId,
fragmentId,
invitationToken,
) => dispatch => {
dispatch(reviewerDecisionRequest())
return update(
`/collections/${collectionId}/fragments/${fragmentId}/invitations/${invitationId}/decline`,
{
invitationToken,
},
).then(
res => {
dispatch(reviewerDecisionSuccess())
return res
},
err => {
dispatch(reviewerDecisionError(err.message))
throw err
export default (state = initialState, action = {}) => {
switch (action.type) {
case GET_REVIEWERS_REQUEST:
return {
...state,
fetching: {
...state.fetching,
reviewers: true,
},
}
case GET_REVIEWERS_ERROR:
return {
...state,
fetching: {
...state.fetching,
reviewers: false,
},
error: action.error,
}
case GET_REVIEWERS_SUCCESS:
return {
...state,
fetching: {
...state.fetching,
reviewers: false,
},
reviewers: action.payload.reviewers,
}
case INVITE_REVIEWER_REQUEST:
return {
...state,
fetching: {
...state.fetching,
invite: true,
},
}
case INVITE_REVIEWER_SUCCESS:
return {
...state,
fetching: {
...state.fetching,
invite: false,
},
error: null,
}
case INVITE_REVIEWER_ERROR:
return {
...state,
fetching: {
...state.fetching,
invite: false,
},
error: action.error,
}
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
case REVIEWER_DECISION_REQUEST:
return {
...state,
fetching: {
...state.fetching,
decision: true,
},
}
case REVIEWER_DECISION_ERROR:
return {
...state,
fetching: {
...state.fetching,
decision: false,
},
error: action.error,
}
case REVIEWER_DECISION_SUCCESS:
return {
...state,
fetching: {
...state.fetching,
decision: false,
},
error: null,
}
case CLEAR_ERROR: {
return {
...state,
error: null,
}
}
default:
return state
}
}