Commit 6945d354 authored by Audrey Hamelers's avatar Audrey Hamelers

#476 set new reviewer & send emails

parent 904ce58b
Pipeline #12981 passed with stages
in 1 minute and 19 seconds
import React from 'react'
import { Button } from '@pubsweet/ui'
import { graphql, compose } from 'react-apollo'
import { states } from 'config'
import { Buttons } from '../ui'
import SelectReviewer from '../SelectReviewer'
import { INVITE_REVIEWER, QUERY_ACTIVITY_INFO } from './operations'
class ReviewerEdit extends React.Component {
state = { newReviewer: null }
......@@ -14,9 +17,11 @@ class ReviewerEdit extends React.Component {
changeNote,
deleteNote,
newNote,
inviteReviewer,
} = this.props
const { teams, meta } = manuscript
const { teams, meta, status } = manuscript
const { fundingGroup, notes } = meta
const tagged = states.indexOf(status) >= states.indexOf('tagging')
const reviewerNote = notes
? notes.find(n => n.notesType === 'selectedReviewer')
: null
......@@ -64,12 +69,21 @@ class ReviewerEdit extends React.Component {
})
}
if (result) {
close()
if (tagged && newReviewer !== 'delete') {
const success = await inviteReviewer({
variables: { id: manuscript.id },
})
if (success) {
close()
}
} else {
close()
}
}
}}
primary
>
Save
Save{tagged && newReviewer !== 'delete' && ' & send invitation'}
</Button>
<Button onClick={close}>Exit</Button>
</Buttons>
......@@ -78,4 +92,13 @@ class ReviewerEdit extends React.Component {
}
}
export default ReviewerEdit
export default compose(
graphql(INVITE_REVIEWER, {
name: 'inviteReviewer',
options: props => ({
refetchQueries: [
{ query: QUERY_ACTIVITY_INFO, variables: { id: props.manuscript.id } },
],
}),
}),
)(ReviewerEdit)
......@@ -47,6 +47,12 @@ export const LINK_AND_DELETE = gql`
}
`
export const INVITE_REVIEWER = gql`
mutation SetNewReviewer($id: ID!) {
setManuscriptReviewer(id: $id)
}
`
export const QUERY_ACTIVITY_INFO = gql`
query QueryActivitiesByManuscriptId($id: ID!) {
activities: epmc_queryActivitiesByManuscriptId(id: $id) {
......
......@@ -6,6 +6,8 @@ const {
htmlEmailBase,
setReviewerTemplate,
newReviewerTemplate,
newReviewFinalTemplate,
setReviewFinalTemplate,
checkReviewerTemplate,
rejectSubmissionTemplate,
removeDupeTemplate,
......@@ -100,13 +102,13 @@ const resetPassword = (email, user, token) => {
const completedEmail = (email, manInfo) => {
const link = `https://europepmc.org/articles/${manInfo.pmcid}`
const html = completedTemplate(manInfo.title, link, manInfo.pmcid)
const html = completedTemplate(parsed(manInfo.title), link, manInfo.pmcid)
const subject = `${manInfo.id}: Manuscript available in Europe PMC`
sendMail(email, subject, html, null, null, system)
}
const deletedEmail = (email, manInfo) => {
const html = deletedTemplate(manInfo.title)
const html = deletedTemplate(parsed(manInfo.title))
const subject = `${manInfo.id}: Submission cancelled`
sendMail(email, subject, html, null, null, system)
}
......@@ -118,7 +120,7 @@ const incompleteEmail = (manInfo, submitter) => {
const link = `${url}submission/${manInfo.id}/${
manInfo.status === 'INITIAL' ? 'create' : 'submit'
}`
const html = incompleteTemplate(salutation, manInfo.title, link)
const html = incompleteTemplate(salutation, parsed(manInfo.title), link)
const subject = `${manInfo.id}: Your submission is incomplete`
sendMail(email, subject, html, null, null, system)
}
......@@ -131,7 +133,7 @@ const stalledEmail = (manInfo, reviewer) => {
: `${url}submission/${manInfo.id}/${
manInfo.status === 'xml-review' ? 'review' : 'submit'
}`
const html = stalledTemplate(salutation, manInfo.title, link)
const html = stalledTemplate(salutation, parsed(manInfo.title), link)
const subject = `${manInfo.id}: Please review your submission`
sendMail(email, subject, html, null, null, system)
}
......@@ -141,7 +143,7 @@ const stalledErrorEmail = (manInfo, user) => {
const { email } = user.identities[0]
const salutation = `${title ? `${title} ` : ''}${givenNames} ${surname}`
const link = `${url}submission/${manInfo.id}/submit`
const html = stalledErrorTemplate(salutation, manInfo.title, link)
const html = stalledErrorTemplate(salutation, parsed(manInfo.title), link)
const subject = `${manInfo.id}: Your submission still needs corrections`
sendMail(email, subject, html, null, null, system)
}
......@@ -172,6 +174,36 @@ const reviewerEmail = ({ reviewer, manInfo, submitter, token }) => {
sendMail(reviewer.email, subject, html, null, null, system)
}
const finalReviewerEmail = ({ reviewer, manInfo, submitter = null, token }) => {
const { title, givenNames, surname } = submitter || ''
const submitterName =
submitter && `${title ? `${title} ` : ''}${givenNames} ${surname}`
const { title: t, givenNames: g, surname: s } = reviewer.name
const salutation = `${t ? `${t} ` : ''}${g} ${s}`
const finalReview = manInfo.status === 'xml-review'
const link = `${url}submission/${manInfo.id}/review`
const args = [
salutation,
parsed(manInfo.title),
submitterName,
link,
finalReview,
]
let html = ''
if (reviewer.id) {
html = setReviewFinalTemplate(...args)
} else if (token) {
args[3] = `${url}dashboard?accept=${token}`
html = newReviewFinalTemplate(...args)
}
if (html) {
const subject = finalReview
? `Please review manuscript ${manInfo.id}`
: `You've been assigned to review ${manInfo.id}`
sendMail(reviewer.email, subject, html, null, null, system)
}
}
const submitterRejectEmail = ({ reviewer, manInfo, submitter, message }) => {
const { title, givenNames, surname } = submitter
const { email } = submitter.identities[0]
......@@ -264,6 +296,7 @@ module.exports = {
taggerErrorEmail,
bulkUploaderEmail,
reviewerEmail,
finalReviewerEmail,
submitterRejectEmail,
grantEmail,
removeDuplicateEmail,
......
......@@ -3,6 +3,8 @@ const {
newReviewerTemplate,
setReviewerTemplate,
checkReviewerTemplate,
newReviewFinalTemplate,
setReviewFinalTemplate,
} = require('./reviewerAdded')
const { rejectSubmissionTemplate } = require('./rejectSubmission')
const {
......@@ -89,6 +91,8 @@ module.exports = {
resetPasswordTemplate,
newReviewerTemplate,
setReviewerTemplate,
newReviewFinalTemplate,
setReviewFinalTemplate,
checkReviewerTemplate,
rejectSubmissionTemplate,
grantsAddedTemplate,
......
......@@ -29,8 +29,57 @@ const checkReviewerTemplate = (salutation, title, submitter, link) => `
<p>The Europe PMC Helpdesk</p>
`
const newReviewFinalTemplate = (
salutation,
title,
submitter,
link,
finalReview,
) => `
${finalReview ? `<h1 style="font-weight:600;">Review web version</h1>` : ''}
<p>Dear ${salutation},</p>
<p>A manuscript, <b>${title}</b>, was submitted to Europe PMC plus on your behalf by ${submitter}.</p>
<p>You have been made the reviewer of this submission, which means you are responsible for approving the final web version.</p>
<p>${
finalReview
? 'The web version of the submission is awaiting your final approval. P'
: 'To ensure you are notified when the submission is ready for final approval, p'
}lease <a style="color:#20699C" href="${link}">log in to or create a Europe PMC plus account</a> to accept this submission for review.</p>
<p>If you do not think you are the correct person to review this submission, and you would like to reject the assignment, we would greatly appreciate it if you would reply to this email and let us know.</p>
<p>Kind regards,</p>
<p>The Europe PMC Helpdesk</p>
`
const setReviewFinalTemplate = (
salutation,
title,
submitter,
link,
finalReview,
) => `
${finalReview ? `<h1 style="font-weight:600;">Review web version</h1>` : ''}
<p>Dear ${salutation},</p>
<p>${
submitter
? `A manuscript, <b>${title}</b>, was submitted to Europe PMC plus on your behalf by ${submitter}.`
: `You previously submitted the manuscript <b>${title}</b> to Europe PMC plus.`
}</p>
<p>You have been made the reviewer of this submission, which means you are responsible for approving the final web version.</p>
${
finalReview
? `<p>Please proceed to <a style="color:#20699C" href="${link}">${link}</a> to approve or request corrections to the web version of your manuscript.</p>
<p>Please note that only errors or omissions that impact the scientific accuracy of your article are eligible for correction.</p>`
: '<p>You will be informed via email when this submission is ready for final review.</p>'
}
<p>If you do not think you are the correct person to review this submission, and you would like to reject the assignment, we would greatly appreciate it if you would reply to this email and let us know.</p>
<p>Kind regards,</p>
<p>The Europe PMC Helpdesk</p>
`
module.exports = {
newReviewerTemplate,
setReviewerTemplate,
checkReviewerTemplate,
newReviewFinalTemplate,
setReviewFinalTemplate,
}
......@@ -41,6 +41,7 @@ const gJournal = model => {
const gTeams = model =>
model.map(t => ({
id: t.id,
role: t.roleName,
teamMembers: t.users.map(u => ({
user: {
......
......@@ -23,6 +23,7 @@ const {
finalReviewEmail,
taggerErrorEmail,
deletedEmail,
finalReviewerEmail,
} = rfr('server/email')
const grantCheck = (origMan, changeMan) => {
......@@ -443,18 +444,21 @@ const Manuscript = {
if (reviewer.id) {
let trx
try {
trx = await transaction.start(Team.knex())
const team = new Team({
const teamInput = {
manuscriptId: input.id,
userId: reviewer.id,
roleName: 'reviewer',
updatedBy: userId,
})
await team.saveWithTrx(trx)
await NoteAccess.delete(reviewerNote.id, userId)
}
trx = await transaction.start(Team.knex())
if (revTeam) {
await Team.delete(revTeam.id, userId)
lodash.assign(revTeam, teamInput)
await revTeam.saveWithTrx(trx)
} else {
const team = new Team(teamInput)
await team.saveWithTrx(trx)
}
await NoteAccess.delete(reviewerNote.id, userId)
await trx.commit()
} catch (error) {
if (trx) {
......@@ -590,6 +594,66 @@ const Manuscript = {
}
},
setReviewer: async (id, userId) => {
const getMan = await ManuscriptAccess.selectById(id, true)
const manuscript = gManuscript(getMan)
const { meta, teams, status } = manuscript
const { title, notes } = meta
const revNote = notes.find(n => n.notesType === 'selectedReviewer')
const reviewer = revNote && JSON.parse(revNote.content)
const manInfo = {
id,
title,
status,
}
const revTeam = teams.find(team => team.role === 'reviewer')
const sTeam = teams.find(team => team.role === 'submitter')
if (reviewer) {
const submitter =
sTeam &&
sTeam.teamMembers[0] &&
(sTeam.teamMembers[0].user.id !== reviewer.id || !reviewer.id) &&
sTeam.teamMembers[0].alias.name
if (reviewer.id) {
let trx
let team
try {
const teamInput = {
manuscriptId: id,
userId: reviewer.id,
roleName: 'reviewer',
updatedBy: userId,
}
trx = await transaction.start(Team.knex())
if (revTeam) {
team = await Team.find(revTeam.id)
lodash.assign(team, teamInput)
} else {
team = new Team(teamInput)
}
await team.saveWithTrx(trx)
await NoteAccess.delete(revNote.id, userId)
await trx.commit()
} catch (error) {
if (trx) {
await trx.rollback()
}
logger.error('Nothing was created: ', error)
return false
}
}
await finalReviewerEmail({
reviewer,
manInfo,
submitter,
token: revNote.id,
})
return true
}
logger.error('No reviewer note; cannot send new reviewer email')
return false
},
review: async (input, userId) => {
const originalMan = await ManuscriptAccess.selectById(input.id)
const errors = []
......
......@@ -148,6 +148,14 @@ const resolvers = {
return rejectedMan
},
async setManuscriptReviewer(_, { id }, { user }) {
if (!user) {
throw new Error('You are not authenticated!')
}
const manuscript = await ManuscriptManager.setReviewer(id, user)
return manuscript
},
async reviewManuscript(_, { data }, { user }) {
if (!user) {
throw new Error('You are not authenticated!')
......
......@@ -38,6 +38,7 @@ extend type Mutation {
createManuscript(data: CreateManuscriptInput!): Manuscript!
deleteManuscript(id: ID!): Boolean!
recoverManuscript(id: ID!): Boolean!
setManuscriptReviewer(id: ID!): Boolean!
linkDeleteManuscript(id: ID!): MutationResult!
replaceManuscript(keepId: ID!, throwId: ID!): Boolean!
updateManuscript(data: ManuscriptInput!): Manuscript!
......
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