-
Tania Fecheta authorede4fc98dc
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
import { connect } from 'react-redux'
import { actions } from 'pubsweet-client'
import { ConnectPage } from 'xpub-connect'
import { withJournal } from 'xpub-journal'
import { withRouter } from 'react-router-dom'
import { head, get, isUndefined } from 'lodash'
import { getFormValues, change as changeForm } from 'redux-form'
import {
selectFragment,
selectCollection,
selectCurrentUser,
} from 'xpub-selectors'
import { get as apiGet } from 'pubsweet-client/src/helpers/api'
import {
compose,
withState,
lifecycle,
withProps,
withHandlers,
setDisplayName,
fromRenderProps,
} from 'recompose'
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 {
selectReviewRecommendations,
selectEditorialRecommendations,
} from 'pubsweet-components-faraday/src/redux/recommendations'
import {
canReview,
getUserToken,
currentUserIs,
canViewReports,
canMakeRevision,
canMakeDecision,
isHEToManuscript,
canSubmitRevision,
canEditManuscript,
getVersionOptions,
canInviteReviewers,
pendingHEInvitation,
currentUserIsReviewer,
parseCollectionDetails,
canMakeHERecommendation,
canViewReviewersDetails,
canViewEditorialComments,
pendingReviewerInvitation,
canViewResponseFromAuthor,
getFragmentAuthorResponse,
canOverrideTechnicalChecks,
authorCanViewReportsDetails,
getOwnPendingRecommendation,
getOwnSubmittedRecommendation,
canAuthorViewEditorialComments,
getFragmentReviewerRecommendations,
getInvitationsWithReviewersForFragment,
} from 'pubsweet-component-faraday-selectors'
import {
handleError,
withFetching,
RemoteOpener,
} from 'pubsweet-component-faraday-ui'
import ManuscriptLayout from './ManuscriptLayout'
import withInviteReviewer from '../inviteReviewer/withInviteReviewer'
import withSubmitRevision from '../submitRevision/withSubmitRevision'
import withHandleRecommendation from '../handleRecommendation/withHandleRecommendation'
import withInviteHandlingEditor from '../inviteHandlingEditor/withInviteHandlingEditor'
import {
redirectToError,
parseSearchParams,
getPublonsReviewers,
isLatestVersion,
} from './utils'
import {
canAssignHE,
selectFetching,
getHandlingEditors,
selectHandlingEditors,
} from '../redux/editors'
export default compose(
setDisplayName('ManuscriptPage'),
withJournal,
withRouter,
withFetching,
withState('publonReviewers', 'setPublonsReviewers', []),
withState('editorInChief', 'setEiC', 'N/A'),
ConnectPage(({ match }) => [
actions.getCollection({ id: match.params.project }),
actions.getFragments({ id: match.params.project }),
actions.getUsers(),
actions.getTeams(),
]),
connect(
(state, { match }) => ({
currentUser: selectCurrentUser(state),
handlingEditors: selectHandlingEditors(state),
hasManuscriptFailure: hasManuscriptFailure(state),
fragment: selectFragment(state, match.params.version),
collection: parseCollectionDetails(
state,
selectCollection(state, match.params.project),
),
reviewerReports: selectReviewRecommendations(state, match.params.version),
pendingHEInvitation: pendingHEInvitation(state, match.params.project),
pendingOwnRecommendation: getOwnPendingRecommendation(
state,
match.params.version,
),
submittedOwnRecommendation: getOwnSubmittedRecommendation(
state,
match.params.version,
),
pendingReviewerInvitation: pendingReviewerInvitation(
state,
match.params.version,
),
editorialRecommendations: selectEditorialRecommendations(
state,
match.params.version,
),
reviewerRecommendations: getFragmentReviewerRecommendations(
state,
match.params.version,
),
authorResponseToRevisonRequest: getFragmentAuthorResponse(
state,
match.params.version,
),
}),
{
changeForm,
clearCustomError,
getUsers: actions.getUsers,
getFragment: actions.getFragment,
getCollection: actions.getCollection,
updateVersion: actions.updateFragment,
},
),
connect(
(
state,
{
match,
journal,
fragment,
collection,
isFetching,
currentUser,
pendingHEInvitation,
pendingOwnRecommendation,
pendingReviewerInvitation,
},
) => ({
currentUser: {
...currentUser,
token: getUserToken(state),
isHE: currentUserIs(state, 'isHE'),
isEIC: currentUserIs(state, 'adminEiC'),
isInvitedHE: !isUndefined(pendingHEInvitation),
isInvitedToReview: !isUndefined(pendingReviewerInvitation),
isReviewer: currentUserIsReviewer(state, get(fragment, 'id', '')),
isHEToManuscript: isHEToManuscript(state, get(collection, 'id', '')),
permissions: {
canReview: canReview(state, collection, fragment),
canSubmitRevision: canSubmitRevision(state, fragment),
canMakeHERecommendation: canMakeHERecommendation(state, {
collection,
statuses: get(journal, 'statuses', {}),
}),
canAssignHE: canAssignHE(state, collection),
canViewReports: canViewReports(state, match.params.project),
canViewEditorialComments: canViewEditorialComments(
state,
collection,
fragment,
),
canInviteReviewers: canInviteReviewers(state, collection),
canMakeRecommendation: !isUndefined(pendingOwnRecommendation),
canMakeRevision: canMakeRevision(state, collection, fragment),
canMakeDecision: canMakeDecision(state, collection),
canEditManuscript: canEditManuscript(state, collection, fragment),
canViewReviewersDetails: canViewReviewersDetails(state, collection),
authorCanViewReportsDetails: authorCanViewReportsDetails(
state,
collection,
get(fragment, 'id', ''),
),
canOverrideTechChecks: canOverrideTechnicalChecks(state, collection),
canAuthorViewEditorialComments: canAuthorViewEditorialComments(
state,
collection,
match.params.version,
),
canViewResponseFromAuthor: canViewResponseFromAuthor(
state,
collection,
match.params.version,
),
},
},
isFetchingData: {
editorsFetching: selectFetching(state),
publonsFetching: isFetching,
},
formValues: {
revision: getFormValues('revision')(state),
eicDecision: getFormValues('eic-decision')(state),
reviewerReport: getFormValues('reviewerReport')(state),
responseToInvitation: getFormValues('answer-invitation')(state),
editorialRecommendation: getFormValues('HERecommendation')(state),
},
invitationsWithReviewers: getInvitationsWithReviewersForFragment(
state,
get(fragment, 'id', ''),
),
versions: getVersionOptions(state, collection),
}),
),
ConnectPage(({ currentUser }) => {
if (currentUser.isEIC) {
return [getHandlingEditors()]
}
return []
}),
withHandlers({
fetchUpdatedCollection: ({
fragment,
getUsers,
collection,
getFragment,
getCollection,
}) => () => {
getCollection({ id: collection.id })
getFragment(collection, fragment)
getUsers()
},
getPublonsReviewers: ({ clearError, setFetching, setPublonsReviewers }) => (
fragmentId,
errorFn,
) => {
clearError()
setFetching(true)
getPublonsReviewers(fragmentId)
.then(res => {
setFetching(false)
setPublonsReviewers(res)
})
.catch(e => {
setFetching(false)
handleError(errorFn)(e)
})
},
}),
withHandlers({
updateManuscript: ({ updateVersion, collection, fragment }) => data =>
updateVersion(collection, {
id: fragment.id,
...data,
}),
setEditorInChief: ({ setEiC }) => eic => {
if (eic) {
const { firstName = '', lastName = '' } = eic
setEiC(`${firstName} ${lastName}`)
}
},
}),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleAssignHE: toggle,
heExpanded: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleHEResponse: toggle,
heResponseExpanded: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleReviewerResponse: toggle,
reviewerResponseExpanded: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleReviewerRecommendations: toggle,
reviewerRecommendationExpanded: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleResponseToRevisionRequest: toggle,
responseToRevisionRequest: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleReviewerDetails: toggle,
reviewerDetailsExpanded: expanded,
})),
fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({
toggleEditorialComments: toggle,
editorialCommentsExpanded: expanded,
})),
withProps(({ collection, fragment }) => ({
getSignedUrl,
isLatestVersion: isLatestVersion(collection, fragment),
})),
withInviteHandlingEditor,
withInviteReviewer,
withSubmitRevision,
withHandleRecommendation,
lifecycle({
componentDidMount() {
const {
match,
history,
setError,
location,
reviewerReports,
setEditorInChief,
clearCustomError,
getPublonsReviewers,
hasManuscriptFailure,
fetchUpdatedCollection,
editorialRecommendations,
fragment,
currentUser: {
isEIC,
isInvitedHE,
isInvitedToReview,
isHEToManuscript,
permissions: { canInviteReviewers, canSubmitRevision, canReview },
},
} = this.props
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') {
history.replace(location.pathname)
reviewerDecision({ invitationId, collectionId, fragmentId })
.then(fetchUpdatedCollection)
.catch(redirectToError(history.replace))
}
apiGet(`/users?editorInChief=true`).then(res =>
setEditorInChief(head(res.users)),
)
if (canInviteReviewers) {
getPublonsReviewers(fragmentId, setError)
}
if (isInvitedHE) {
this.props.toggleHEResponse()
}
if (isInvitedToReview) {
this.props.toggleReviewerResponse()
}
if (canReview && !get(fragment, 'responseToReviewers.content', false)) {
this.props.toggleReviewerRecommendations()
}
if (
isHEToManuscript &&
!!reviewerReports.length &&
editorialRecommendations.length === 0 &&
get(fragment, 'responseToReviewers.content', false)
) {
this.props.toggleReviewerDetails()
}
if ((isEIC || isHEToManuscript) && !!editorialRecommendations.length) {
this.props.toggleEditorialComments()
}
if (canSubmitRevision) {
this.props.toggleEditorialComments()
}
if (
get(fragment, 'responseToReviewers.content', false) &&
!editorialRecommendations.length
) {
this.props.toggleResponseToRevisionRequest()
}
},
componentDidUpdate(prevProps) {
const {
editorialRecommendations: prevEditorialRecommendations,
editorInChief: prevEditorInChief,
} = prevProps
const {
currentUser: { isEIC, isHEToManuscript },
collection: { status },
editorialRecommendations: currentEditorialRecommendations,
editorInChief: currentEditorInChief,
} = this.props
if (
prevEditorInChief === currentEditorInChief &&
prevEditorialRecommendations !== currentEditorialRecommendations &&
(isEIC || isHEToManuscript) &&
status === 'rejected'
) {
prevProps.toggleEditorialComments()
}
},
}),
)(ManuscriptLayout)