diff --git a/packages/component-mail-service/src/Mail.js b/packages/component-mail-service/src/Mail.js index aa1feda200bfa5114f7054b2bc2db3c473edaaf3..3b10d7f47afe797b6a568fdf434f78feaceb178a 100644 --- a/packages/component-mail-service/src/Mail.js +++ b/packages/component-mail-service/src/Mail.js @@ -402,9 +402,9 @@ module.exports = { replacements.previewText = 'a manuscript has reached a decision' replacements.intro = `Dear Dr. ${user.firstName} ${user.lastName}` - replacements.paragraph = `An editorial decision has been made regarding manuscript "${ - meta.fragment.title - }" by ${ + replacements.paragraph = `An editorial decision has been made regarding the ${ + meta.manuscriptType + } titled "${meta.fragment.title}" by ${ meta.fragment.authorName }. So, you do not need to proceed with the review of this manuscript. <br/> If you have comments on this manuscript you believe the Editor should see, please email them to Hindawi as soon as possible.` diff --git a/packages/component-mail-service/src/helpers/helpers.js b/packages/component-mail-service/src/helpers/helpers.js index 886226a5619717ca4da72e7dc07f93353a7aa9ff..6f6a01f113ca5124039f23e26d3d49316163f0b2 100644 --- a/packages/component-mail-service/src/helpers/helpers.js +++ b/packages/component-mail-service/src/helpers/helpers.js @@ -8,84 +8,74 @@ const createUrl = (baseUrl, slug, queryParams = null) => : `${baseUrl}${slug}?${querystring.encode(queryParams)}` const getEmailBody = (emailType, replacements) => { - handlePartial('header', { previewText: replacements.previewText }) + handlePartial('header', replacements) handlePartial('footer') - const buttonContext = { - url: replacements.url, - buttonText: replacements.buttonText, - } - handlePartial('mainButton', buttonContext) - - const bodyContext = { - headline: replacements.headline, - paragraph: replacements.paragraph, - } - handlePartial('mainBody', bodyContext) + handlePartial('mainButton', replacements) + handlePartial('mainBody', replacements) return getMainTemplate(emailType, replacements) } const getNotificationBody = (emailType, replacements) => { - handlePartial('notificationHeader', { previewText: replacements.previewText }) + handlePartial('notificationHeader', replacements) handlePartial('footer') - - handlePartial('signature', { - signatureName: replacements.signatureName, - }) - + handlePartial('signature', replacements) if (replacements.detailsUrl !== undefined) - handlePartial('manuscriptDetailsLink', { - beforeAnchor: replacements.beforeAnchor, - detailsUrl: replacements.detailsUrl, - afterAnchor: replacements.afterAnchor, - }) - - handlePartial('notificationBody', { - intro: replacements.intro, - paragraph: replacements.paragraph, - hasLink: replacements.hasLink, - }) + handlePartial('manuscriptDetailsLink', replacements) + handlePartial('notificationBody', replacements) return getMainTemplate(emailType, replacements) } const getInvitationBody = (emailType, replacements) => { - handlePartial('invitationHeader', { previewText: replacements.previewText }) + handlePartial('invitationHeader', replacements) handlePartial('footer') + handlePartial('invitationUpperContent', replacements) + handlePartial('invitationButtons', replacements) + handlePartial('manuscriptData', replacements) + handlePartial('signature', replacements) + handlePartial('invitationLowerContent', replacements) - const upperContext = { - intro: replacements.intro, - upperContent: replacements.upperContent, - } - handlePartial('invitationUpperContent', upperContext) - - const buttonsContext = { - declineUrl: replacements.declineUrl, - agreeUrl: replacements.agreeUrl, - } - handlePartial('invitationButtons', buttonsContext) - - const manuscriptContext = { - manuscriptText: replacements.manuscriptText, - title: replacements.title, - authors: replacements.authors, - abstract: replacements.abstract, - } - handlePartial('manuscriptData', manuscriptContext) - - const signatureContext = { - signatureName: replacements.signatureName, - signatureEmail: replacements.signatureEmail, - } - handlePartial('signature', signatureContext) + return getMainTemplate(emailType, replacements) +} - const lowerContext = { - manuscriptDetailsUrl: replacements.manuscriptDetailsUrl, - lowerContent: replacements.lowerContent, - signature: replacements.signature, +const getBody = (emailType, replacements) => { + const simplePartials = ['header', 'footer', 'mainButton', 'mainBody'] + const notificationPartials = [ + 'notificationHeader', + 'footer', + 'signature', + 'manuscriptDetailsLink', + 'notificationBody', + ] + const invitationPartials = [ + 'invitationHeader', + 'footer', + 'invitationUpperContent', + 'invitationButtons', + 'manuscriptData', + 'signature', + 'invitationLowerContent', + ] + + switch (emailType) { + case 'simpleCTA': + case 'noCTA': + simplePartials.forEach(partial => handlePartial(partial, replacements)) + break + case 'invitation': + invitationPartials.forEach(partial => + handlePartial(partial, replacements), + ) + break + case 'notification': + notificationPartials.forEach(partial => + handlePartial(partial, replacements), + ) + break + default: + break } - handlePartial('invitationLowerContent', lowerContext) - return getMainTemplate(emailType, replacements) } @@ -98,7 +88,7 @@ const readFile = path => } }) -const handlePartial = (partialName, context = {}) => { +const handlePartial = (partialName = 'signature', context = {}) => { let partial = readFile( `${__dirname}/../templates/partials/${partialName}.hbs`, ) @@ -132,4 +122,5 @@ module.exports = { getExpectedDate, getNotificationBody, getInvitationBody, + getBody, } diff --git a/packages/component-manuscript-manager/config/default.js b/packages/component-manuscript-manager/config/default.js index 0a977816afd053a707521a8eea2d19f0af582857..d706fd5a1265f5bf7b6d931cc5bddf7f297f08a7 100644 --- a/packages/component-manuscript-manager/config/default.js +++ b/packages/component-manuscript-manager/config/default.js @@ -59,4 +59,16 @@ module.exports = { private: 'Pending Approval', }, }, + 'manuscript-types': { + research: 'Research', + review: 'Review', + 'clinical-study': 'Clinical Study', + 'case-report': 'Case Report', + 'letter-to-editor': 'Letter to the Editor', + editorial: 'Editorial', + corrigendum: 'Corrigendum', + erratum: 'Erratum', + 'expression-of-concern': 'Expression of Concern', + retraction: 'Retraction', + }, } diff --git a/packages/component-manuscript-manager/config/test.js b/packages/component-manuscript-manager/config/test.js index 1a1a9fa2e0d3cde2c858ca1bf125045bda4206e2..6869d659a3af2b1b643561889f4f81d4c486d1cf 100644 --- a/packages/component-manuscript-manager/config/test.js +++ b/packages/component-manuscript-manager/config/test.js @@ -59,5 +59,25 @@ module.exports = { public: 'Under Review', private: 'Pending Approval', }, + rejected: { + public: 'Rejected', + private: 'Rejected', + }, + published: { + public: 'Published', + private: 'Published', + }, + }, + 'manuscript-types': { + research: 'Research', + review: 'Review', + 'clinical-study': 'Clinical Study', + 'case-report': 'Case Report', + 'letter-to-editor': 'Letter to the Editor', + editorial: 'Editorial', + corrigendum: 'Corrigendum', + erratum: 'Erratum', + 'expression-of-concern': 'Expression of Concern', + retraction: 'Retraction', }, } diff --git a/packages/component-manuscript-manager/src/FragmentsRecommendations.js b/packages/component-manuscript-manager/src/FragmentsRecommendations.js index 681be174ddfeeefd8e41a8bebf8c2a18b61e90dd..2c5d6471192f2832c6ff6757a7048769bb6f026e 100644 --- a/packages/component-manuscript-manager/src/FragmentsRecommendations.js +++ b/packages/component-manuscript-manager/src/FragmentsRecommendations.js @@ -15,7 +15,7 @@ const FragmentsRecommendations = app => { * @apiParam {fragmentId} fragmentId Fragment id * @apiParamExample {json} Body * { - * "recommendation": "accept", [acceptedValues: accept, revise, etc.], + * "recommendation": "publish", [acceptedValues: publish, reject, minor, major], * "comments": * [ * { @@ -40,7 +40,7 @@ const FragmentsRecommendations = app => { * "userId": "4c3f8ee1-785b-4adb-87b4-407a27f652c6", * "createdOn": 1525428890167, * "updatedOn": 1525428890167, - * "recommendation": "accept", [acceptedValues: accept, revise, etc.], + * "recommendation": "publish", * "comments": * [ * { @@ -56,7 +56,7 @@ const FragmentsRecommendations = app => { * ] * } * ], - * "recommendationType": "review" [acceptedValues: review, editorRecommendation] + * "recommendationType": "review" * } * @apiErrorExample {json} Invite user errors * HTTP/1.1 403 Forbidden @@ -70,14 +70,14 @@ const FragmentsRecommendations = app => { require(`${routePath}/post`)(app.locals.models), ) /** - * @api {patch} /api/collections/:collectionId/fragments/:fragmentId/recommendations/:recommendationId Create a recommendation on a fragment + * @api {patch} /api/collections/:collectionId/fragments/:fragmentId/recommendations/:recommendationId Modify a recommendation on a fragment * @apiGroup FragmentsRecommendations * @apiParam {collectionId} collectionId Collection id * @apiParam {fragmentId} fragmentId Fragment id * @apiParam {recommendationId} recommendationId Recommendation id * @apiParamExample {json} Body * { - * "recommendation": "accept", [acceptedValues: accept, revise, etc.], + * "recommendation": "publish", [acceptedValues: publish, reject, minor, major], * "comments": * [ * { @@ -102,7 +102,7 @@ const FragmentsRecommendations = app => { * "userId": "4c3f8ee1-785b-4adb-87b4-407a27f652c6", * "createdOn": 1525428890167, * "updatedOn": 1525428890167, - * "recommendation": "accept", [acceptedValues: accept, revise, etc.], + * "recommendation": "publish", * "comments": * [ * { diff --git a/packages/component-manuscript-manager/src/helpers/Collection.js b/packages/component-manuscript-manager/src/helpers/Collection.js index bde604c66b9d8d1d610f420091d6314958f36c5f..85a056a5c6e0dff186fbdbac54c1c743315a1b2b 100644 --- a/packages/component-manuscript-manager/src/helpers/Collection.js +++ b/packages/component-manuscript-manager/src/helpers/Collection.js @@ -12,6 +12,29 @@ const updateStatusByRecommendation = async (collection, recommendation) => { await collection.save() } +const updateFinalStatusByRecommendation = async ( + collection, + recommendation, +) => { + let newStatus + switch (recommendation) { + case 'reject': + newStatus = 'rejected' + break + case 'publish': + newStatus = 'published' + break + case 'return-to-handling-editor': + newStatus = 'reviewCompleted' + break + default: + break + } + collection.status = newStatus + collection.visibleStatus = statuses[collection.status].private + await collection.save() +} + const updateStatus = async (collection, newStatus) => { collection.status = newStatus collection.visibleStatus = statuses[collection.status].private @@ -25,6 +48,7 @@ const getFragmentAndAuthorData = async ({ }) => { const fragment = await FragmentModel.find(last(fragments)) let { title, abstract } = fragment.metadata + const { type } = fragment.metadata title = title.replace(/<(.|\n)*?>/g, '') abstract = abstract ? abstract.replace(/<(.|\n)*?>/g, '') : '' @@ -38,7 +62,7 @@ const getFragmentAndAuthorData = async ({ }) const authorsList = await Promise.all(authorsPromises) const { id } = fragment - return { title, submittingAuthor, id, abstract, authorsList } + return { title, submittingAuthor, id, abstract, authorsList, type } } const getAgreedReviewerInvitation = (invitations = []) => @@ -54,4 +78,5 @@ module.exports = { getFragmentAndAuthorData, getAgreedReviewerInvitation, updateStatus, + updateFinalStatusByRecommendation, } diff --git a/packages/component-manuscript-manager/src/helpers/User.js b/packages/component-manuscript-manager/src/helpers/User.js index a67ba27d3829787fffbfe39a3f888a8a4b1a110a..41e5d3e25d1a82401913be22c4d22650381822ba 100644 --- a/packages/component-manuscript-manager/src/helpers/User.js +++ b/packages/component-manuscript-manager/src/helpers/User.js @@ -1,7 +1,9 @@ const collectionHelper = require('./Collection') const get = require('lodash/get') const last = require('lodash/last') +const config = require('config') +const manuscriptTypes = config.get('manuscript-types') const getEditorInChief = async UserModel => { const users = await UserModel.all() const eic = users.find(user => user.editorInChief === true) @@ -86,7 +88,7 @@ const setupAgreedReviewersEmailData = async ({ const setupNoResponseReviewersEmailData = async ({ baseUrl, - fragment: { title, authorName }, + fragment: { title, authorName, type }, collection, mailService, UserModel, @@ -100,6 +102,7 @@ const setupNoResponseReviewersEmailData = async ({ let users = await Promise.all(userPromises) users = users.filter(Boolean) const subject = `${collection.customId}: Reviewer Unassigned` + const manuscriptType = manuscriptTypes[type] users.forEach(user => mailService.sendNotificationEmail({ toEmail: user.email, @@ -111,6 +114,7 @@ const setupNoResponseReviewersEmailData = async ({ handlingEditorName: collection.handlingEditor.name, baseUrl, emailSubject: subject, + manuscriptType, }, }), ) diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index d75ec539d9a4f334af75f14dbe568da4e9ceca7c..592c6cea794b2164a6b0f1d7f6a39cb3837b7c84 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -54,6 +54,12 @@ module.exports = models => async (req, res) => { newRecommendation.comments = comments || undefined if (recommendationType === 'editorRecommendation') { + if (reqUser.editorInChief === true) { + await collectionHelper.updateFinalStatusByRecommendation( + collection, + recommendation, + ) + } await collectionHelper.updateStatusByRecommendation( collection, recommendation, @@ -62,6 +68,7 @@ module.exports = models => async (req, res) => { title, submittingAuthor, id, + type, } = await collectionHelper.getFragmentAndAuthorData({ UserModel: models.User, FragmentModel: models.Fragment, @@ -85,7 +92,7 @@ module.exports = models => async (req, res) => { UserModel: models.User, collection, mailService, - fragment: { title, authorName }, + fragment: { title, authorName, type }, }) await userHelper.setupEiCRecommendationEmailData({ baseUrl, diff --git a/packages/xpub-faraday/config/authsome-mode.js b/packages/xpub-faraday/config/authsome-mode.js index fbbea3d6a4401ca8752656b9b80ef5eeca1aa7c3..88f4b83d333383179fffa23d9403a76e319c2502 100644 --- a/packages/xpub-faraday/config/authsome-mode.js +++ b/packages/xpub-faraday/config/authsome-mode.js @@ -14,6 +14,11 @@ async function teamPermissions(user, operation, object, context) { let collectionsPermissions = await Promise.all( teams.map(async team => { const collection = await context.models.Collection.find(team.object.id) + if ( + collection.status === 'rejected' && + team.teamType.permissions === 'reviewer' + ) + return null const collPerm = { id: collection.id, permission: team.teamType.permissions, diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js index d0206232d69f270f4b2d6bd45277a4795f276321..224f6a058928d659a5febbdc45f7ae88ae61bbae 100644 --- a/packages/xpub-faraday/config/default.js +++ b/packages/xpub-faraday/config/default.js @@ -127,4 +127,16 @@ module.exports = { private: 'Revision Requested', }, }, + 'manuscript-types': { + research: 'Research', + review: 'Review', + 'clinical-study': 'Clinical Study', + 'case-report': 'Case Report', + 'letter-to-editor': 'Letter to the Editor', + editorial: 'Editorial', + corrigendum: 'Corrigendum', + erratum: 'Erratum', + 'expression-of-concern': 'Expression of Concern', + retraction: 'Retraction', + }, }