diff --git a/packages/component-fixture-manager/src/fixtures/collectionIDs.js b/packages/component-fixture-manager/src/fixtures/collectionIDs.js index 4f351142bab1ef0de0b4c1d82f767ed391b42b75..5b0da41bf1758f75c2b1394ca7f42ef812761ccc 100644 --- a/packages/component-fixture-manager/src/fixtures/collectionIDs.js +++ b/packages/component-fixture-manager/src/fixtures/collectionIDs.js @@ -5,5 +5,6 @@ const chance = new Chance() module.exports = { standardCollID: chance.guid(), collectionReviewCompletedID: chance.guid(), + collectionNoInvitesID: chance.guid(), twoVersionsCollectionId: chance.guid(), } diff --git a/packages/component-fixture-manager/src/fixtures/collections.js b/packages/component-fixture-manager/src/fixtures/collections.js index f6bb11aaa73ff13cf739b921e31910b2eaba35e5..c0e6b797fa5259fffc927c1be6b11664cd6f5e59 100644 --- a/packages/component-fixture-manager/src/fixtures/collections.js +++ b/packages/component-fixture-manager/src/fixtures/collections.js @@ -1,9 +1,15 @@ const Chance = require('chance') const { user, handlingEditor, answerHE } = require('./userData') -const { fragment, reviewCompletedFragment } = require('./fragments') +const { + fragment, + fragment1, + reviewCompletedFragment, + noInvitesFragment, +} = require('./fragments') const { standardCollID, collectionReviewCompletedID, + collectionNoInvitesID, twoVersionsCollectionId, } = require('./collectionIDs') @@ -93,6 +99,48 @@ const collections = { technicalChecks: { token: chance.guid(), }, + status: 'reviewCompleted', + }, + collection2: { + id: collectionNoInvitesID, + title: chance.sentence(), + type: 'collection', + fragments: [fragment1.id, noInvitesFragment.id], + owners: [user.id], + save: jest.fn(() => collections.collection2), + invitations: [ + { + id: chance.guid(), + role: 'handlingEditor', + hasAnswer: false, + isAccepted: false, + userId: handlingEditor.id, + invitedOn: chance.timestamp(), + respondedOn: null, + }, + { + id: chance.guid(), + role: 'handlingEditor', + hasAnswer: true, + isAccepted: false, + userId: answerHE.id, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + }, + ], + handlingEditor: { + id: handlingEditor.id, + hasAnswer: false, + isAccepted: false, + email: handlingEditor.email, + invitedOn: chance.timestamp(), + respondedOn: null, + name: `${handlingEditor.firstName} ${handlingEditor.lastName}`, + }, + customId: chance.natural({ min: 999999, max: 9999999 }), + technicalChecks: { + token: chance.guid(), + }, status: 'pendingApproval', }, collectionReviewCompleted: { diff --git a/packages/component-fixture-manager/src/fixtures/fragments.js b/packages/component-fixture-manager/src/fixtures/fragments.js index 5696e17019b802e9a131c762b184f058f2bc799e..9fca41e0ffba404be7fd612dd6feb483e6a23763 100644 --- a/packages/component-fixture-manager/src/fixtures/fragments.js +++ b/packages/component-fixture-manager/src/fixtures/fragments.js @@ -7,10 +7,12 @@ const { handlingEditor, admin, inactiveReviewer, + reviewer1, } = require('./userData') const { standardCollID, collectionReviewCompletedID, + collectionNoInvitesID, } = require('./collectionIDs') const { user } = require('./userData') @@ -316,6 +318,111 @@ const fragments = { ], save: jest.fn(() => fragments.fragment), }, + fragment1: { + id: chance.guid(), + collectionId: collectionNoInvitesID, + metadata: { + title: chance.sentence(), + abstract: chance.paragraph(), + }, + recommendations: [ + { + recommendation: 'publish', + recommendationType: 'review', + comments: [ + { + content: chance.paragraph(), + public: chance.bool(), + files: [ + { + id: chance.guid(), + name: 'file.pdf', + size: chance.natural(), + }, + ], + }, + ], + id: chance.guid(), + userId: reviewer1.id, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + submittedOn: chance.timestamp(), + }, + { + recommendation: 'minor', + recommendationType: 'editorRecommendation', + comments: [ + { + content: chance.paragraph(), + public: true, + files: [ + { + id: chance.guid(), + name: 'file.pdf', + size: chance.natural(), + }, + ], + }, + ], + id: chance.guid(), + userId: handlingEditor.id, + createdOn: chance.timestamp(), + updatedOn: chance.timestamp(), + }, + ], + authors: [ + { + email: chance.email(), + id: submittingAuthor.id, + isSubmitting: true, + isCorresponding: false, + }, + { + email: inactiveReviewer.email, + id: inactiveReviewer.id, + isSubmitting: false, + isCorresponding: false, + }, + ], + invitations: [ + { + id: chance.guid(), + role: 'reviewer', + hasAnswer: true, + isAccepted: false, + userId: reviewer1.id, + invitedOn: chance.timestamp(), + respondedOn: chance.timestamp(), + type: 'invitation', + }, + ], + save: jest.fn(() => fragments.fragment), + owners: [user.id], + type: 'fragment', + revision: { + collectionId: collectionNoInvitesID, + metadata: { + title: chance.sentence(), + abstract: chance.paragraph(), + }, + authors: [ + { + email: chance.email(), + id: submittingAuthor.id, + isSubmitting: true, + isCorresponding: false, + }, + ], + owners: [user.id], + type: 'fragment', + }, + }, +} + +fragments.noInvitesFragment = { + ...fragments.fragment1, + invites: [], + id: chance.guid(), } module.exports = fragments diff --git a/packages/component-fixture-manager/src/fixtures/teamIDs.js b/packages/component-fixture-manager/src/fixtures/teamIDs.js index 5528425bf62570b86f0c98472c1001698ab72732..ab1eae10948701757d3d0e745a307204a14b7f4e 100644 --- a/packages/component-fixture-manager/src/fixtures/teamIDs.js +++ b/packages/component-fixture-manager/src/fixtures/teamIDs.js @@ -7,4 +7,5 @@ module.exports = { revTeamID: chance.guid(), authorTeamID: chance.guid(), revRecommendationTeamID: chance.guid(), + rev1TeamID: chance.guid(), } diff --git a/packages/component-fixture-manager/src/fixtures/teams.js b/packages/component-fixture-manager/src/fixtures/teams.js index c100c2a3798fc3bc4e635a98077806f11ad86bcc..370a9c0e988c6c886454314b76173613d898bf25 100644 --- a/packages/component-fixture-manager/src/fixtures/teams.js +++ b/packages/component-fixture-manager/src/fixtures/teams.js @@ -7,17 +7,19 @@ const { revTeamID, authorTeamID, revRecommendationTeamID, + rev1TeamID, } = require('./teamIDs') const { submittingAuthor } = require('./userData') const { collection } = collections -const { fragment, reviewCompletedFragment } = fragments +const { fragment, reviewCompletedFragment, fragment1 } = fragments const { handlingEditor, reviewer, inactiveReviewer, answerReviewer, recReviewer, + reviewer1, } = users const teams = { heTeam: { @@ -71,6 +73,22 @@ const teams = { updateProperties: jest.fn(() => teams.revRecommendationTeam), id: revRecommendationTeamID, }, + rev1Team: { + teamType: { + name: 'reviewer', + permissions: 'reviewer', + }, + group: 'reviewer', + name: 'reviewer', + object: { + type: 'fragment', + id: fragment1.id, + }, + members: [reviewer1.id], + save: jest.fn(() => teams.rev1Team), + updateProperties: jest.fn(() => teams.rev1Team), + id: rev1TeamID, + }, authorTeam: { teamType: { name: 'author', diff --git a/packages/component-fixture-manager/src/fixtures/userData.js b/packages/component-fixture-manager/src/fixtures/userData.js index c6291916908889cf22eaf26ed80c52aebab500bb..2335d630e32ce34e6ffc521956dfcd079deaaf94 100644 --- a/packages/component-fixture-manager/src/fixtures/userData.js +++ b/packages/component-fixture-manager/src/fixtures/userData.js @@ -14,6 +14,7 @@ module.exports = { admin: generateUserData(), author: generateUserData(), reviewer: generateUserData(), + reviewer1: generateUserData(), answerReviewer: generateUserData(), submittingAuthor: generateUserData(), recReviewer: generateUserData(), diff --git a/packages/component-fixture-manager/src/fixtures/users.js b/packages/component-fixture-manager/src/fixtures/users.js index e5ee9ae59e761d936dce39f1a263fa42f70dcf33..f0a6737c38eb46d4990c4131828b75e7af74ee4b 100644 --- a/packages/component-fixture-manager/src/fixtures/users.js +++ b/packages/component-fixture-manager/src/fixtures/users.js @@ -7,6 +7,7 @@ const { revTeamID, authorTeamID, revRecommendationTeamID, + rev1TeamID, } = require('./teamIDs') const keys = Object.keys(usersData) @@ -29,6 +30,9 @@ users = keys.reduce((obj, item) => { if (['reviewer', 'answerReviewer', 'recReviewer'].includes(item)) { teams.push(revRecommendationTeamID) } + if (item === 'reviewer1') { + teams = [rev1TeamID] + } obj[item] = { ...userData, diff --git a/packages/component-manuscript-manager/src/routes/collections/get.js b/packages/component-manuscript-manager/src/routes/collections/get.js index 1314ffda0107a1e4c80a0edab70561f97db82093..ddeeb504d1efee96f4362a6e72455cb7529298f2 100644 --- a/packages/component-manuscript-manager/src/routes/collections/get.js +++ b/packages/component-manuscript-manager/src/routes/collections/get.js @@ -1,8 +1,3 @@ -const { last, get } = require('lodash') - -const filterDuplicates = collection => - get(collection, 'currentVersion.id') === last(collection.fragments) - const { authsome: authsomeHelper, } = require('pubsweet-component-helper-service') @@ -21,5 +16,5 @@ module.exports = models => async (req, res) => { }) } - res.status(200).json(collections.filter(filterDuplicates)) + res.status(200).json(collections) } diff --git a/packages/component-manuscript-manager/src/tests/collections/get.test.js b/packages/component-manuscript-manager/src/tests/collections/get.test.js index 6ee20a4684bf3b12a882a095ffa0bda64225095e..1d140a8c9de3aa2ce316012090ed7dd24a7613a7 100644 --- a/packages/component-manuscript-manager/src/tests/collections/get.test.js +++ b/packages/component-manuscript-manager/src/tests/collections/get.test.js @@ -65,6 +65,26 @@ describe('Get collections route handler', () => { expect(data[0].currentVersion.authors[0]).not.toHaveProperty('email') }) + it('should return the latest fragment with invitation if the request user is reviewer', async () => { + const { reviewer1 } = testFixtures.users + + const res = await requests.sendRequest({ + userId: reviewer1.id, + route, + models, + path, + }) + expect(res.statusCode).toBe(200) + const data = JSON.parse(res._getData()) + expect(data).toHaveLength(1) + + expect(data[0].type).toEqual('collection') + expect(data[0].currentVersion.recommendations).toHaveLength(2) + expect(data[0].currentVersion.authors[0]).not.toHaveProperty('email') + expect(data[0].fragments).toHaveLength(2) + expect(data[0].currentVersion.id).toEqual(data[0].fragments[0]) + }) + it('should return an error if the request user is unauthenticated', async () => { const res = await requests.sendRequest({ route, diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 12bb8a9fb7bbf0732abd72597c7e36e4497097bb..fd01d44a1b4009c558fb8900d8991e9bc47f7b04 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -57,6 +57,9 @@ const ManuscriptLayout = ({ toggleReviewerRecommendations, reviewerRecommendationExpanded, authorResponseToRevisonRequest, + toggleResponeToRevisionRequest, + responseToRevisionRequestExpanded, + shouldReview, submittedOwnRecommendation, reviewerReports, reviewerRecommendations, @@ -69,6 +72,7 @@ const ManuscriptLayout = ({ inviteReviewer, recommendationHandler, inviteHandlingEditor, + versions, isLatestVersion, }) => ( diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index b9ef6729a0e5109d0da6672c4c0128660c4e917b..84d6059a9c3187ed2c5c5c648a1f4fe33af233a4 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -357,7 +357,7 @@ export default compose( this.props.toggleReviewerResponse() } - if (canReview) { + if (canReview && !get(fragment, 'responseToReviewers.content', false)) { this.props.toggleReviewerRecommendations() } if ( diff --git a/packages/xpub-faraday/config/authsome-helpers.js b/packages/xpub-faraday/config/authsome-helpers.js index 500a6a103fc300331121a175465c9b18534487d3..c43c00d912084c864261fd45e5c75fc05bd83a64 100644 --- a/packages/xpub-faraday/config/authsome-helpers.js +++ b/packages/xpub-faraday/config/authsome-helpers.js @@ -141,7 +141,7 @@ const parseUser = ({ user }) => omit(user, sensitiveUserProperties) const getCollections = async ({ user, models }) => { const userPermisssions = await getUserPermissions({ user, Team: models.Team }) - return (await Promise.all( + const collections = (await Promise.all( userPermisssions.map(async up => { let fragment = {} let collection = {} @@ -182,6 +182,11 @@ const getCollections = async ({ user, models }) => { } }), )).filter(Boolean) + return chain(collections) + .sortBy(c => c.currentVersion.version) + .reverse() + .uniqBy('id') + .value() } const reviewerActionStatuses = [