diff --git a/packages/component-mail-service/src/Mail.js b/packages/component-mail-service/src/Mail.js index f6121253652f20a29125e10a19972415c9647a4b..05f85e808615d23c5c100768dee131c0214d1fa6 100644 --- a/packages/component-mail-service/src/Mail.js +++ b/packages/component-mail-service/src/Mail.js @@ -249,8 +249,17 @@ module.exports = { } return Email.send(mailData) }, - sendNotificationEmail: async ({ toEmail, user, emailType, meta = {} }) => { + sendNotificationEmail: async ({ + toEmail, + user, + emailType, + meta = { privateNote: '' }, + }) => { let subject, textBody + const privateNoteText = + meta.privateNote !== undefined + ? `Private note: "${meta.privateNote}"` + : '' const emailTemplate = 'notification' const replacements = { detailsUrl: helpers.createUrl( @@ -259,6 +268,7 @@ module.exports = { ), beforeAnchor: '', afterAnchor: '', + hasLink: true, } switch (emailType) { case 'unassign-reviewer': @@ -369,6 +379,7 @@ module.exports = { subject = `${ meta.collection.customId }: Manuscript Recommendation Submitted` + replacements.hasLink = false replacements.previewText = 'a manuscript has received a recommendation based on reviews' replacements.intro = `Dear Dr. ${user.firstName} ${user.lastName}` @@ -386,6 +397,27 @@ module.exports = { replacements.signatureName }` break + case 'eic-recommendation': + subject = `${meta.collection.customId}: Manuscript Recommendation` + replacements.previewText = + 'a handling editor has submitted a recommendation' + replacements.intro = `Dear Dr. ${meta.eicName}` + replacements.paragraph = `It is my recommendation, based on the reviews I have received for the manuscript titled "${ + meta.fragment.title + }" by ${meta.fragment.authorName}, that ${ + meta.heRecommendation + }. <br/><br/> + ${privateNoteText}<br/><br/>` + + replacements.beforeAnchor = + 'For more information, and to see the full review, please visit the ' + replacements.signatureName = meta.handlingEditorName + textBody = `${replacements.intro} ${replacements.paragraph} ${ + replacements.beforeAnchor + } ${replacements.detailsUrl} ${replacements.afterAnchor} ${ + replacements.signatureName + }` + break default: subject = 'Hindawi Notification!' break diff --git a/packages/component-mail-service/src/helpers/helpers.js b/packages/component-mail-service/src/helpers/helpers.js index 27aec6312911c7b57bfcb629afbbfcdc490187f0..f0a4bbb75ef25ac5752789dde16246c358826441 100644 --- a/packages/component-mail-service/src/helpers/helpers.js +++ b/packages/component-mail-service/src/helpers/helpers.js @@ -43,6 +43,7 @@ const getNotificationBody = (emailType, replacements) => { handlePartial('notificationBody', { intro: replacements.intro, paragraph: replacements.paragraph, + hasLink: replacements.hasLink, }) return getMainTemplate(emailType, replacements) diff --git a/packages/component-mail-service/src/templates/partials/notificationBody.hbs b/packages/component-mail-service/src/templates/partials/notificationBody.hbs index 5460c5065ee835ca465b278aba5f86e738b39092..c041158eada8ebec8a422962b28f849a647042d2 100644 --- a/packages/component-mail-service/src/templates/partials/notificationBody.hbs +++ b/packages/component-mail-service/src/templates/partials/notificationBody.hbs @@ -6,7 +6,7 @@ <p> </p> <p> {{{paragraph}}} - {{#if detailsUrl }} + {{#if hasLink }} {{> manuscriptDetailsLink}} {{/if}} </p> diff --git a/packages/component-manuscript-manager/src/helpers/User.js b/packages/component-manuscript-manager/src/helpers/User.js index 9b37c6c2b6c85371bcf9b5ce849c09b95da4d23f..28290936faff49ba08c2d00159bd8d5e7c8c93ff 100644 --- a/packages/component-manuscript-manager/src/helpers/User.js +++ b/packages/component-manuscript-manager/src/helpers/User.js @@ -1,4 +1,6 @@ const collectionHelper = require('./Collection') +const get = require('lodash/get') +const last = require('lodash/last') const getEditorInChief = async UserModel => { const users = await UserModel.all() @@ -41,28 +43,30 @@ const setupReviewSubmittedEmailData = async ({ const setupAfterRecommendationEmailData = async ({ baseUrl, - UserModel, - FragmentModel, + fragment: { title, authorName }, collection, mailService, + UserModel, + FragmentModel, }) => { - const { title, authorName } = await collectionHelper.getFragmentAndAuthorData( - { - UserModel, - FragmentModel, - collection, - }, - ) - const toEmail = collection.handlingEditor.email const agreedReviewerInvitations = collectionHelper.getAgreedReviewerInvitation( collection.invitations, ) - const users = await Promise.all( - agreedReviewerInvitations.map(async inv => UserModel.find(inv.userId)), - ) + const hasReview = invUserId => rec => + rec.recommendationType === 'review' && + rec.submittedOn && + invUserId === rec.userId + const userPromises = await agreedReviewerInvitations.map(async inv => { + const fragmentId = last(collection.fragments) + const fragment = await FragmentModel.find(fragmentId) + const submittedReview = fragment.recommendations.find(hasReview(inv.userId)) + if (submittedReview === undefined) return UserModel.find(inv.userId) + }) + let users = await Promise.all(userPromises) + users = users.filter(Boolean) users.forEach(user => mailService.sendNotificationEmail({ - toEmail, + toEmail: user.email, user, emailType: 'after-he-recommendation', meta: { @@ -75,8 +79,41 @@ const setupAfterRecommendationEmailData = async ({ ) } +const setupEiCRecommendationEmailData = async ({ + baseUrl, + UserModel, + fragment: { id, title, authorName }, + collection, + mailService, + publish, + comments, +}) => { + // to do: get private note from recommendation + const privateNote = comments.find(comm => comm.public === false) + const content = get(privateNote, 'content') + const heRecommendation = publish + ? 'we should proceed to publication' + : 'we should reject it for publication' + const eic = await getEditorInChief(UserModel) + const toEmail = eic.email + await mailService.sendNotificationEmail({ + toEmail, + emailType: 'eic-recommendation', + meta: { + collection: { customId: collection.customId, id: collection.id }, + fragment: { id, title, authorName }, + handlingEditorName: collection.handlingEditor.name, + baseUrl, + eicName: `${eic.firstName} ${eic.lastName}`, + heRecommendation, + privateNote: content, + }, + }) +} + module.exports = { getEditorInChief, setupReviewSubmittedEmailData, setupAfterRecommendationEmailData, + setupEiCRecommendationEmailData, } diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index fe6fe6b13f54aed23d9b06e3fab41edb2d5bc67e..454626197b0a386e3aa79a24e538126f87e58295 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -57,14 +57,34 @@ module.exports = models => async (req, res) => { ['reject', 'publish'].includes(recommendation) && recommendationType === 'editorRecommendation' ) { + const { + title, + authorName, + id, + } = await collectionHelper.getFragmentAndAuthorData({ + UserModel: models.User, + FragmentModel: models.Fragment, + collection, + }) + const baseUrl = helpers.getBaseUrl(req) await userHelper.setupAfterRecommendationEmailData({ - baseUrl: helpers.getBaseUrl(req), + baseUrl, UserModel: models.User, FragmentModel: models.Fragment, collection, mailService, + fragment: { title, authorName }, }) await collectionHelper.updateStatus(collection, 'pendingApproval') + await userHelper.setupEiCRecommendationEmailData({ + baseUrl, + UserModel: models.User, + collection, + mailService, + publish: recommendation === 'publish', + fragment: { title, id, authorName }, + comments: newRecommendation.comments, + }) } if ( ['minor', 'major'].includes(recommendation) && diff --git a/packages/component-manuscript-manager/src/tests/fixtures/users.js b/packages/component-manuscript-manager/src/tests/fixtures/users.js index ae54144fab4e8aa3e1a76c765602c3f46769586a..573c25543f255e06ffe659e1dcc5bd3feb2d38cb 100644 --- a/packages/component-manuscript-manager/src/tests/fixtures/users.js +++ b/packages/component-manuscript-manager/src/tests/fixtures/users.js @@ -64,6 +64,21 @@ const users = { handlingEditor: true, title: 'Mr', }, + editorInChief: { + type: 'user', + username: chance.word(), + email: chance.email(), + password: 'password', + admin: false, + id: chance.guid(), + firstName: chance.first(), + lastName: chance.last(), + affiliation: chance.company(), + title: 'Mr', + save: jest.fn(() => users.editorInChief), + isConfirmed: false, + editorInChief: true, + }, } module.exports = users diff --git a/packages/component-manuscript-manager/src/tests/helpers/Model.js b/packages/component-manuscript-manager/src/tests/helpers/Model.js index 3d6ae0871452e134c63f65913af6b9de4b210f8a..3e5a7364b9a7e907530d21ae9575644a69294dbc 100644 --- a/packages/component-manuscript-manager/src/tests/helpers/Model.js +++ b/packages/component-manuscript-manager/src/tests/helpers/Model.js @@ -20,6 +20,7 @@ const build = fixtures => { }, } UserMock.find = jest.fn(id => findMock(id, 'users', fixtures)) + UserMock.all = jest.fn(() => Object.values(fixtures.users)) models.User = UserMock return models }