Commit b94b1e21 authored by nickstiffler's avatar nickstiffler Committed by Yannis Barlas
Browse files

feat(*): allow multiple curators per manuscript

parent 97837451
......@@ -153,8 +153,11 @@ const mapProps = args => {
formattedData.author = submittingAuthor
const curatorTeam = manuscript.teams.find(t => t.role === 'curator')
const curator = curatorTeam.members[0] && curatorTeam.members[0].user
formattedData.curator = curator
const curators =
curatorTeam.members.length > 0 &&
curatorTeam.members.map(member => member.user)
formattedData.curator = curators
const editorTeam = manuscript.teams.find(t => t.role === 'editor')
const editor = editorTeam.members[0] && editorTeam.members[0].user
......
......@@ -85,7 +85,10 @@ const StatusRow = props => {
const editorValue = editor ? editor.displayName : ''
const sectionEditorValue = sectionEditor ? sectionEditor.displayName : ''
const scienceOfficerValue = scienceOfficer ? scienceOfficer.displayName : ''
const curatorValue = curator ? curator.displayName : ''
const curatorValue =
curator && curator.length > 0
? curator.map(user => user.displayName).join(', ')
: ''
return (
<>
......
......@@ -26,7 +26,7 @@ const getManuscriptTeam = manuscriptTeams => {
const manuscriptSO = manuscriptSOs && manuscriptSOs[0]
const manuscriptCurators = membersOfTeam(manuscriptTeams, 'curator')
const manuscriptCurator = manuscriptCurators && manuscriptCurators[0]
const manuscriptCurator = manuscriptCurators
return {
curator: manuscriptCurator,
......@@ -94,8 +94,13 @@ const transformCuratorReviews = reviews =>
reviews.map(review => ({
content: review.content,
curatorId: get(review, 'curator.id'),
curatorName: get(review, 'curator.displayName'),
openAcknowledgement: review.openAcknowledgement,
pending: !review.submitted,
recommendation: review.recommendation,
reviewerId: get(review, 'curator.id'),
reviewerName: get(review, 'curator.displayName'),
showRequestToSeeRevision: false,
submitted: review.submitted,
}))
......
......@@ -143,11 +143,7 @@ export default (data, mutations) => {
const invitedReviewers = getInvitedReviewersTeam(teams)
const reviewerCounts = getReviewerCounts(teams)
const versionReviews = transformReviews(reviews)
const curatorReview =
assignedCurator &&
transformCuratorReviews(curatorReviews).find(
item => item.curatorId === assignedCurator.id,
)
const curatorReview = transformCuratorReviews(curatorReviews)
const previousReviewers = []
if (latest && filteredVersions.length > 1) {
......@@ -244,8 +240,13 @@ export default (data, mutations) => {
const updateManuscriptTeams = values => {
const curatorMembers = []
if (values.curator && values.curator.id)
curatorMembers.push(values.curator.id)
if (values.curator) {
values.curator.forEach(curator => {
if (curator.id) {
curatorMembers.push(curator.id)
}
})
}
const editorMembers = []
if (values.editor && values.editor.id) {
......
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { useQuery, useMutation } from '@apollo/react-hooks'
import { clone } from 'lodash'
import {
CURATOR_PREVIEW,
......@@ -172,19 +173,28 @@ const CuratorView = props => {
let save, handleClickSubmit
if (latest) {
save = input =>
save = input => {
const curatorInput = clone(input)
delete curatorInput.confidentialComments
delete curatorInput.reviseQualifier
saveMutation({
variables: {
id: thisReview.id,
input,
input: curatorInput,
},
})
}
submitReview = input => {
const curatorInput = clone(input)
delete curatorInput.confidentialComments
delete curatorInput.reviseQualifier
submitMutation({
variables: {
id: thisReview.id,
input,
input: curatorInput,
},
}).then(() => {
setSubmissionData(null)
......
......@@ -74,13 +74,10 @@ const EditorView = props => {
setShowChatModal(true)
}
const onClickCuratorChat = () => {
const selectedChat =
assignedCurator &&
chatData.find(
item =>
item.chatType === 'curator' && item.reviewerId === assignedCurator.id,
)
const onClickCuratorChat = curatorId => {
const selectedChat = chatData.find(
item => item.chatType === 'curator' && item.reviewerId === curatorId,
)
setChatModalThreadId(selectedChat.id)
setChatModalHeader('Chat with Curator')
setShowChatModal(true)
......@@ -308,7 +305,8 @@ const EditorView = props => {
const editorName = assignedEditor && assignedEditor.displayName
const curatorId = assignedCurator && assignedCurator.id
const curatorName = assignedCurator && assignedCurator.displayName
const curatorNames =
assignedCurator && assignedCurator.map(c => c.displayName)
const sectionEditorName =
assignedSectionEditor && assignedSectionEditor.displayName
const scienceOfficerName =
......@@ -344,7 +342,7 @@ const EditorView = props => {
categories={categories}
createDoi={createDoi}
curatorId={curatorId}
curatorName={curatorName}
curatorName={curatorNames}
curatorReview={curatorReview}
dataType={dataType}
dbReferenceId={dbReferenceId}
......
......@@ -141,6 +141,7 @@ const ScienceOfficerView = props => {
)
const {
curator: assignedCurator,
editor: assignedEditor,
scienceOfficer: assignedScienceOfficer,
sectionEditor: assignedSectionEditor,
......@@ -163,6 +164,8 @@ const ScienceOfficerView = props => {
const reviewerCounts = getReviewerCounts(teams)
const versionReviews = transformReviews(reviews)
const curatorNames =
assignedCurator && assignedCurator.map(c => c.displayName)
const editorName = assignedEditor && assignedEditor.displayName
const sectionEditorName =
assignedSectionEditor && assignedSectionEditor.displayName
......@@ -177,6 +180,7 @@ const ScienceOfficerView = props => {
acceptedReviewersCount={reviewerCounts.accepted}
authorEmail={authorEmail}
authorName={authorName}
curatorName={curatorNames}
dataType={dataType}
decision={decision}
decisionLetter={decisionLetter}
......
import React from 'react'
import PropTypes from 'prop-types'
import Review from './Review'
import ReviewList from './ReviewList'
const CuratorSection = props => {
const {
content,
curatorId,
curatorName,
onClickChat,
openAcknowledgement,
pending,
recommendation,
showChat,
} = props
const { curatorName, onClickChat, reviews, showChat } = props
if (!curatorName) return 'No curator is currently assigned to this manuscript'
return (
<Review
content={content}
<ReviewList
label="Curator feedback"
onClickChat={onClickChat}
openAcknowledgement={openAcknowledgement}
pending={pending}
recommendation={recommendation}
reviewerId={curatorId}
reviewerName={curatorName}
reviews={reviews}
showChat={showChat}
showRequestToSeeRevision={false}
/>
......@@ -33,30 +20,29 @@ const CuratorSection = props => {
}
CuratorSection.propTypes = {
/** Curator review text content */
content: PropTypes.string,
/** Curator's user id */
curatorId: PropTypes.string.isRequired,
/** Curator's display name */
curatorName: PropTypes.string.isRequired,
/** Function to run on clicking the chat button */
onClickChat: PropTypes.func,
/** Whether the curator wanted open acknowledgement of their feedback */
openAcknowledgement: PropTypes.bool,
/** Whether the review has been submitted or not */
pending: PropTypes.bool,
/** Curator review recommendation */
recommendation: PropTypes.oneOf(['accept', 'reject', 'revise']),
/** The curator assessments */
reviews: PropTypes.arrayOf(
PropTypes.shape({
askedToSeeRevision: PropTypes.bool,
content: PropTypes.string,
openAcknowledgement: PropTypes.bool,
pending: PropTypes.bool,
recommendation: PropTypes.oneOf(['accept', 'reject', 'revise']),
reviewerId: PropTypes.string,
reviewerName: PropTypes.string,
}),
),
/** Whether to show the chat button */
showChat: PropTypes.bool,
}
CuratorSection.defaultProps = {
content: null,
onClickChat: null,
openAcknowledgement: false,
pending: true,
recommendation: null,
reviews: [],
showChat: false,
}
......
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { get } from 'lodash'
import { grid } from '../_helpers'
import { Accordion as AccordionBase, Chat } from '../common'
......@@ -149,13 +148,10 @@ const EditorPanel = props => {
{showCurators && (
<Accordion label="Curator" startExpanded={startCuratorsExpanded}>
<CuratorSection
content={get(curatorReview, 'content')}
curatorId={curatorId}
curatorName={curatorName}
onClickChat={onClickCuratorChat}
openAcknowledgement={get(curatorReview, 'openAcknowledgement')}
pending={!get(curatorReview, 'submitted')}
recommendation={get(curatorReview, 'recommendation')}
reviews={curatorReview}
showChat={showCuratorChat}
/>
</Accordion>
......@@ -289,7 +285,7 @@ EditorPanel.propTypes = {
/** Submitting author's display name */
authorName: PropTypes.string,
/** Assigned curator's display name */
curatorName: PropTypes.string,
curatorName: PropTypes.arrayOf(PropTypes.string),
/** Assigned editor's display name */
editorName: PropTypes.string,
......
......@@ -48,7 +48,7 @@ const InfoSection = props => {
{
label: 'Curator',
status: 'primary',
value: curatorName,
value: curatorName.join(', '),
},
{
label: 'Submitting Author',
......@@ -75,7 +75,7 @@ const InfoSection = props => {
InfoSection.propTypes = {
authorEmail: PropTypes.string.isRequired,
authorName: PropTypes.string.isRequired,
curatorName: PropTypes.string,
curatorName: PropTypes.arrayOf(PropTypes.string),
editorName: PropTypes.string,
sectionEditorName: PropTypes.string,
scienceOfficerName: PropTypes.string,
......
......@@ -130,15 +130,17 @@ const Review = props => {
value={content}
/>
<Editor
bold
italic
label="Confidential Comments"
readOnly
subscript
superscript
value={confidentialComments}
/>
{confidentialComments && (
<Editor
bold
italic
label="Confidential Comments"
readOnly
subscript
superscript
value={confidentialComments}
/>
)}
</>
)}
......
......@@ -18,7 +18,7 @@ const StyledReview = styled(Review)`
`
const ReviewList = props => {
const { onClickChat, reviews, showChat } = props
const { label, onClickChat, reviews, showChat } = props
const [notify] = useState(null)
......@@ -32,7 +32,7 @@ const ReviewList = props => {
return (
<div>
<Header>Reviewer feedback</Header>
<Header>{label}</Header>
{(!reviews || reviews.length === 0) &&
`No reviewers have accepted their invitation for this article yet`}
......@@ -52,6 +52,7 @@ const ReviewList = props => {
}
ReviewList.propTypes = {
label: PropTypes.string,
onClickChat: PropTypes.func,
reviews: PropTypes.arrayOf(
PropTypes.shape({
......@@ -70,6 +71,7 @@ ReviewList.propTypes = {
}
ReviewList.defaultProps = {
label: 'Reviewer feedback',
onClickChat: null,
reviews: [],
showChat: false,
......
......@@ -59,20 +59,34 @@ const Footer = props => {
)
}
const userToValue = user => ({
label: user.displayName,
isDisabled: user.isDisabled,
value: user.id,
})
const userToValue = user => {
if (Array.isArray(user)) {
return user.map(u => ({
label: u.displayName,
isDisabled: u.isDisabled,
value: u.id,
}))
}
return {
label: user.displayName,
isDisabled: user.isDisabled,
value: user.id,
}
}
const Role = props => {
const { label, name, options, setFieldValue, value } = props
const { isMulti, label, name, options, setFieldValue, value } = props
const selectOptions = options ? options.map(userToValue) : []
const handleChange = selected => {
if (!selected) {
if (!selected || selected.length === 0) {
setFieldValue(name, null)
} else if (Array.isArray(selected)) {
const selectedOptions = selected.map(user =>
options.find(item => item.id === user.value),
)
setFieldValue(name, selectedOptions)
} else {
const option = options.find(item => item.id === selected.value)
setFieldValue(name, option)
......@@ -85,6 +99,7 @@ const Role = props => {
<Select
// menuIsOpen
isClearable
isMulti={isMulti}
onChange={handleChange}
options={selectOptions}
value={value && userToValue(value)}
......@@ -169,6 +184,7 @@ const ManuscriptTeamManager = props => {
/>
<Role
isMulti
label="curator"
name="curator"
options={curators}
......
......@@ -85,7 +85,7 @@ const ReviewerPanel = props => {
} = props
const decisionExists = !!decision
if (!canStillReview)
if (!canStillReview && !review.content)
return (
<Wrapper>
<Status status="error">
......
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