diff --git a/packages/component-manuscript-manager/src/FragmentsRecommendations.js b/packages/component-manuscript-manager/src/FragmentsRecommendations.js index ea2238a33c903f5b6be5b397d4c951ebe7eedd13..681be174ddfeeefd8e41a8bebf8c2a18b61e90dd 100644 --- a/packages/component-manuscript-manager/src/FragmentsRecommendations.js +++ b/packages/component-manuscript-manager/src/FragmentsRecommendations.js @@ -34,11 +34,12 @@ const FragmentsRecommendations = app => { * "recommendationType": "review" [acceptedValues: review, editorRecommendation] * } * @apiSuccessExample {json} Success - * HTTP/1.1 200 OK + * HTTP/1.1 200 OK * { * "id": "7b2431af-210c-49f9-a69a-e19271066ebd", * "userId": "4c3f8ee1-785b-4adb-87b4-407a27f652c6", - * "submittedOn": 1525428890167, + * "createdOn": 1525428890167, + * "updatedOn": 1525428890167, * "recommendation": "accept", [acceptedValues: accept, revise, etc.], * "comments": * [ @@ -56,7 +57,7 @@ const FragmentsRecommendations = app => { * } * ], * "recommendationType": "review" [acceptedValues: review, editorRecommendation] - * } + * } * @apiErrorExample {json} Invite user errors * HTTP/1.1 403 Forbidden * HTTP/1.1 400 Bad Request @@ -68,6 +69,68 @@ const FragmentsRecommendations = app => { authBearer, require(`${routePath}/post`)(app.locals.models), ) + /** + * @api {patch} /api/collections/:collectionId/fragments/:fragmentId/recommendations/:recommendationId Create 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.], + * "comments": + * [ + * { + * "content": "A very nice manuscript", + * "public": true + * "files": + * [ + * { + * "id": "111-22-333", + * "name": "file.pdf", + * "size": 104232 + * } + * ] + * } + * ], + * "recommendationType": "review" [acceptedValues: review, editorRecommendation] + * } + * @apiSuccessExample {json} Success + * HTTP/1.1 200 OK + * { + * "id": "7b2431af-210c-49f9-a69a-e19271066ebd", + * "userId": "4c3f8ee1-785b-4adb-87b4-407a27f652c6", + * "createdOn": 1525428890167, + * "updatedOn": 1525428890167, + * "recommendation": "accept", [acceptedValues: accept, revise, etc.], + * "comments": + * [ + * { + * "content": "A very nice manuscript", + * "public": true + * "files": + * [ + * { + * "id": "111-22-333", + * "name": "file.pdf", + * "size": 104232 + * } + * ] + * } + * ], + * "recommendationType": "review" [acceptedValues: review, editorRecommendation] + * } + * @apiErrorExample {json} Invite user errors + * HTTP/1.1 403 Forbidden + * HTTP/1.1 400 Bad Request + * HTTP/1.1 404 Not Found + * HTTP/1.1 500 Internal Server Error + */ + app.patch( + `${basePath}/:recommendationId`, + authBearer, + require(`${routePath}/patch`)(app.locals.models), + ) } module.exports = FragmentsRecommendations diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js new file mode 100644 index 0000000000000000000000000000000000000000..ef409bad5ca226b16471fa3d45ad47a938cbe4a9 --- /dev/null +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/patch.js @@ -0,0 +1,31 @@ +const helpers = require('../../helpers/helpers') +// const uuid = require('uuid') + +module.exports = models => async (req, res) => { + // const reqUser = await models.User.find(req.user) + const { collectionId, fragmentId, recommendationId } = req.params + let collection, fragment + try { + collection = await models.Collection.find(collectionId) + if (!collection.fragments.includes(fragmentId)) + return res.status(400).json({ + error: `Collection and fragment do not match.`, + }) + + fragment = await models.Fragment.find(fragmentId) + const recommendation = fragment.recommendations.find( + rec => rec.id === recommendationId, + ) + if (!recommendation) + return res.status(404).json({ error: 'Recommendation not found.' }) + Object.assign(recommendation, req.body) + recommendation.updatedOn = Date.now() + await fragment.save() + return res.status(200).json({ recommendation }) + } catch (e) { + const notFoundError = await helpers.handleNotFoundError(e, 'Item') + return res.status(notFoundError.status).json({ + error: notFoundError.message, + }) + } +} diff --git a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js index 1f0050e3153f5b89e302140577dbb34df77df504..2251f1e91409850aa857922c4e247c12e54781dd 100644 --- a/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js +++ b/packages/component-manuscript-manager/src/routes/fragmentsRecommendations/post.js @@ -4,14 +4,8 @@ const uuid = require('uuid') module.exports = models => async (req, res) => { const { recommendation, comments, recommendationType } = req.body - if ( - !helpers.checkForUndefinedParams( - recommendation, - comments, - recommendationType, - ) - ) - return res.status(400).json({ error: 'Parameters are missing.' }) + if (!helpers.checkForUndefinedParams(recommendationType)) + return res.status(400).json({ error: 'Recommendation type is required.' }) const reqUser = await models.User.find(req.user) const { collectionId, fragmentId } = req.params @@ -34,10 +28,13 @@ module.exports = models => async (req, res) => { const newRecommendation = { id: uuid.v4(), userId: reqUser.id, - submittedOn: new Date(), + createdOn: Date.now(), + updatedOn: Date.now(), recommendationType, - recommendation, - comments, + } + if (recommendation && comments) { + newRecommendation.recommendation = recommendation + newRecommendation.comments = comments } fragment.recommendations.push(newRecommendation) await fragment.save() diff --git a/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js new file mode 100644 index 0000000000000000000000000000000000000000..840d74cc57229a4e604ecf3d10e1f6c9f5c30470 --- /dev/null +++ b/packages/component-manuscript-manager/src/tests/fragmentsRecommendations/patch.test.js @@ -0,0 +1,138 @@ +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' +process.env.SUPPRESS_NO_CONFIG_WARNING = true + +const fixtures = require('./../fixtures/fixtures') +const Chance = require('chance') +const Model = require('./../helpers/Model') +const cloneDeep = require('lodash/cloneDeep') +const requests = require('./../helpers/requests') + +const chance = new Chance() +const reqBody = { + recommendation: 'accept', + comments: [ + { + content: chance.paragraph(), + public: chance.bool(), + files: [ + { + id: chance.guid(), + name: 'file.pdf', + size: chance.natural(), + }, + ], + }, + ], + recommendationType: 'review', +} + +const path = '../../routes/fragmentsRecommendations/patch' +describe('Patch collections invitations route handler', () => { + let testFixtures = {} + let body = {} + let models + beforeEach(() => { + testFixtures = cloneDeep(fixtures) + body = cloneDeep(reqBody) + models = Model.build(testFixtures) + }) + it('should return an error when params are missing', async () => { + const { reviewer } = testFixtures.users + delete body.comments + const res = await requests.sendRequest({ + body, + userId: reviewer.id, + models, + path, + }) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('Parameters are missing.') + }) + it('should return success when the parameters are correct', async () => { + const { reviewer } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + const recommendation = fragment.recommendations[0] + + const res = await requests.sendRequest({ + body, + userId: reviewer.id, + models, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + recommendationId: recommendation.id, + }, + }) + + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + expect(data.userId).toEqual(reviewer.id) + }) + it('should return an error when the fragmentId does not match the collectionId', async () => { + const { reviewer } = testFixtures.users + const { collection } = testFixtures.collections + const { fragment } = testFixtures.fragments + const recommendation = fragment.recommendations[0] + + collection.fragments.length = 0 + const res = await requests.sendRequest({ + body, + userId: reviewer.id, + models, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + recommendationId: recommendation.id, + }, + }) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('Collection and fragment do not match.') + }) + it('should return an error when the collection does not exist', async () => { + const { reviewer } = testFixtures.users + const { fragment } = testFixtures.fragments + const recommendation = fragment.recommendations[0] + const res = await requests.sendRequest({ + body, + userId: reviewer.id, + models, + path, + params: { + collectionId: 'invalid-id', + fragmentId: fragment.id, + recommendationId: recommendation.id, + }, + }) + + expect(res.statusCode).toBe(404) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('Item not found') + }) + it('should return an error when the recommendation does not exist', async () => { + const { reviewer } = testFixtures.users + const { collection } = testFixtures.collection + const { fragment } = testFixtures.fragments + const res = await requests.sendRequest({ + body, + userId: reviewer.id, + models, + path, + params: { + collectionId: collection.id, + fragmentId: fragment.id, + recommendationId: 'invalid-id', + }, + }) + + expect(res.statusCode).toBe(404) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual('Item not found') + }) +}) diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js index 61f83d2767617ddfc03dc2927edfb35d7ab161bd..fec2ea253b827473fa580f507038727af5c95f9b 100644 --- a/packages/xpub-faraday/config/validations.js +++ b/packages/xpub-faraday/config/validations.js @@ -94,10 +94,12 @@ module.exports = { userId: Joi.string().required(), recommendationType: Joi.string().required(), submittedOn: Joi.date(), - recommendation: Joi.string().required(), + createdOn: Joi.date(), + updatedOn: Joi.date(), + recommendation: Joi.string(), comments: Joi.array().items( Joi.object({ - content: Joi.string().required(), + content: Joi.string(), public: Joi.boolean(), files: Joi.array(), }),