Skip to content
Snippets Groups Projects
ManuscriptPage.js 8.4 KiB
Newer Older
import { connect } from 'react-redux'
import { actions } from 'pubsweet-client'
import { ConnectPage } from 'xpub-connect'
import { withJournal } from 'xpub-journal'
import { getFormValues } from 'redux-form'
import { replace } from 'react-router-redux'
import { withRouter } from 'react-router-dom'
import { head, get, isEmpty, isUndefined } from 'lodash'
  selectCollection,
  selectCurrentUser,
import { get as apiGet } from 'pubsweet-client/src/helpers/api'
import { getSignedUrl } from 'pubsweet-components-faraday/src/redux/files'
import { reviewerDecision } from 'pubsweet-components-faraday/src/redux/reviewers'
import {
  hasManuscriptFailure,
  clearCustomError,
} from 'pubsweet-components-faraday/src/redux/errors'
import { selectEditorialRecommendations } from 'pubsweet-components-faraday/src/redux/recommendations'
  canMakeRevision,
  canMakeDecision,
  canEditManuscript,
  canMakeRecommendation,
  canOverrideTechnicalChecks,
} from 'pubsweet-component-faraday-selectors'
import { RemoteOpener } from 'pubsweet-component-faraday-ui'

import ManuscriptLayout from './ManuscriptLayout'
import { parseEicDecision, parseSearchParams, redirectToError } from './utils'
  getHandlingEditors,
  assignHandlingEditor,
  revokeHandlingEditor,
  selectHandlingEditors,
} from '../redux/editors'
import {
  createRecommendation,
  recommendationsFetching,
} from '../redux/recommendations'
  setDisplayName('ManuscriptPage'),
  withState('editorInChief', 'setEiC', 'N/A'),
  ConnectPage(({ match }) => [
    actions.getCollection({ id: match.params.project }),
    actions.getFragments({ id: match.params.project }),
  ]),
  connect(
    (state, { match }) => ({
      currentUser: selectCurrentUser(state),
      handlingEditors: selectHandlingEditors(state),
      hasManuscriptFailure: hasManuscriptFailure(state),
      fragment: selectFragment(state, match.params.version),
      collection: selectCollection(state, match.params.project),
      pendingHEInvitation: pendingHEInvitation(state, match.params.project),
      editorialRecommendations: selectEditorialRecommendations(
        state,
        match.params.version,
      ),
      getFragment: actions.getFragment,
      getCollection: actions.getCollection,
      updateVersion: actions.updateFragment,
  connect(
    (
      state,
      { pendingHEInvitation, currentUser, match, collection, fragment },
    ) => ({
      currentUser: {
        ...currentUser,
        token: getUserToken(state),
        isEIC: currentUserIs(state, 'adminEiC'),
        isHE: currentUserIs(state, 'isHE'),
        isReviewer: currentUserIsReviewer(state),
        canAssignHE: canAssignHE(state, match.params.project),
      },
      isFetching: {
        editorsFetching: selectFetching(state),
        recommendationsFetching: recommendationsFetching(state),
      },
      permissions: {
        isInvitedHE: !isUndefined(pendingHEInvitation),
        canMakeRevision: canMakeRevision(state, collection, fragment),
        canMakeDecision: canMakeDecision(state, collection, fragment),
        canEditManuscript: canEditManuscript(state, collection, fragment),
        canOverrideTechChecks: canOverrideTechnicalChecks(state, collection),
        canMakeRecommendation: canMakeRecommendation(
          state,
          collection,
          fragment,
        ),
      },
      formValues: {
        eicDecision: getFormValues('eic-decision')(state),
        heInvitation: getFormValues('he-answer-invitation')(state),
      },
    }),
  ),
  ConnectPage(({ currentUser, handlingEditors, collection }) => {
    if (currentUser.isEIC) {
      return [getHandlingEditors()]
    }
    return []
  withHandlers({
    fetchUpdatedCollection: ({
      fragment,
      collection,
      getFragment,
      getCollection,
    }) => () => {
      getCollection({ id: collection.id })
      getFragment(collection, fragment)
    },
  }),
    updateManuscript: ({ updateVersion, collection, fragment }) => data =>
      updateVersion(collection, {
        id: fragment.id,
    setEditorInChief: ({ setEiC }) => eic => {
      if (eic) {
        const { firstName = '', lastName = '' } = eic
        setEiC(`${firstName} ${lastName}`)
      }
    },
    assignHE: ({
      assignHandlingEditor,
      collection: { id: collectionId },
    }) => (email, modalProps) =>
      assignHandlingEditor({
        email,
        collectionId,
      })
          modalProps.hideModal()
        })
        .catch(() => modalProps.setModalError('Oops! Something went wrong.')),
    revokeHE: ({
      getCollection,
      revokeHandlingEditor,
      collection: { id: collectionId },
    }) => (invitationId, modalProps) =>
      revokeHandlingEditor({
        invitationId,
        collectionId,
      })
        .then(() => {
          getCollection({ id: collectionId })
          modalProps.hideModal()
        })
        .catch(() => modalProps.setModalError('Oops! Something went wrong.')),
      createRecommendation,
    }) => (values, modalProps) => {
      const recommendation = parseEicDecision(values)
      createRecommendation({
        recommendation,
        fragmentId: fragment.id,
        collectionId: collection.id,
      })
        .then(() => {
          modalProps.hideModal()
        })
        .catch(() => {
          modalProps.setModalError('Oops! Something went wrong.')
        })
    },
    onHEResponse: ({
      history,
      collection,
      pendingHEInvitation,
      fetchUpdatedCollection,
    }) => (values, { hideModal, setModalError, setFetching }) => {
      const isAccepted = get(values, 'decision', 'decline') === 'accept'
      setFetching(true)
      return handlingEditorDecision({
        isAccepted,
        collectionId: collection.id,
        reason: get(values, 'reason', ''),
        invitationId: pendingHEInvitation.id,
      })
        .then(() => {
          setFetching(false)
          hideModal()
          if (isAccepted) {
            fetchUpdatedCollection()
          } else {
            history.replace('/')
          }
        })
        .catch(() => {
          setFetching(false)
          setModalError('Something went wrong...')
        })
    },
  fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
    toggleAssignHE: toggle,
    heExpanded: expanded,
  })),
  fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
    toggleHEResponse: toggle,
    heResponseExpanded: expanded,
  })),
  lifecycle({
    componentDidMount() {
      const {
        getCollection,
        reviewerDecision,
        setEditorInChief,
        clearCustomError,
        hasManuscriptFailure,
      if (hasManuscriptFailure) {
        history.push('/not-found')
        clearCustomError()
      }

      const collectionId = match.params.project
      const fragmentId = match.params.version
      const { agree, invitationId } = parseSearchParams(location.search)
      if (agree === 'true') {
        replace(location.pathname)
        reviewerDecision(invitationId, collectionId, fragmentId, true)
          .then(() => {
            getCollection({ id: collectionId })
            getFragment({ id: collectionId }, { id: fragmentId })
          })
          .catch(redirectToError(replace))
      }

      apiGet(`/users?editorInChief=true`).then(res =>
        setEditorInChief(head(res.users)),
      )

      if (isInvitedHE) {
        this.props.toggleHEResponse()
      }
  withProps(({ fragment }) => ({
    hasResponseToReviewers:
      !isEmpty(get(fragment, 'files.responseToReviewers')) ||
      get(fragment, 'commentsToReviewers'),