import { get, orderBy } from 'lodash' import { selectCurrentUser } from 'xpub-selectors' import { get as apiGet, create, remove, update, } from 'pubsweet-client/src/helpers/api' 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 }) const initialState = { fetching: { decision: false, invite: false, reviewers: false, }, error: null, reviewers: [], } // selectors 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 export const selectFetchingInvite = state => get(state, 'reviewers.fetching.invite') || false export const selectFetchingDecision = state => get(state, 'reviewers.fetching.decision') || false export const selectInvitation = (state, collectionId) => { const currentUser = selectCurrentUser(state) const collection = state.collections.find(c => c.id === collectionId) const invitations = get(collection, 'invitations') || [] return invitations.find( i => i.userId === currentUser.id && i.role === 'reviewer' && !i.hasAnswer, ) } export const getCollectionReviewers = collectionId => dispatch => { dispatch(getReviewersRequest()) return apiGet(`/collections/${collectionId}/invitations?role=reviewer`).then( r => dispatch(getReviewersSuccess(orderBy(r, orderReviewers))), err => dispatch(getReviewersError(err)), ) } // invitation actions export const inviteReviewer = (reviewerData, collectionId) => dispatch => { dispatch(inviteRequest()) return create(`/collections/${collectionId}/invitations`, { ...reviewerData, role: 'reviewer', }).then( () => dispatch(inviteSuccess()), err => dispatch(inviteError(get(JSON.parse(err.response), 'error'))), ) } export const setReviewerPassword = reviewerBody => dispatch => { dispatch(reviewerDecisionRequest()) return create(`/users/reset-password`, reviewerBody).then(r => { dispatch(reviewerDecisionSuccess()) return r }) } export const revokeReviewer = (invitationId, collectionId) => dispatch => { dispatch(inviteRequest()) return remove( `/collections/${collectionId}/invitations/${invitationId}`, ).then(() => dispatch(inviteSuccess()), err => dispatch(inviteError(err))) } // reviewer decision actions export const reviewerDecision = ( invitationId, collectionId, agree = true, ) => dispatch => { dispatch(reviewerDecisionRequest()) // 'accept api call' return update(`/collections/${collectionId}/invitations/${invitationId}`, { isAccepted: agree, }).then( res => { dispatch(reviewerDecisionSuccess()) return res }, err => { dispatch(reviewerDecisionError(err.message)) throw err }, ) } export const reviewerDecline = ( invitationId, collectionId, invitationToken, ) => dispatch => { dispatch(reviewerDecisionRequest()) return update( `/collections/${collectionId}/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, }, reviewers: [], } 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, } 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, } default: return state } }