Newer
Older

Sebastian Mihalache
committed
const config = require('config')
const { findLast, isEmpty, maxBy, get, flatMap, last } = require('lodash')
const { features = {}, recommendations: configRecommendations } = config
Andrei Cioromila
committed
const Fragment = require('./Fragment')

Mihail Hagiu
committed
class Collection {
constructor({ collection = {} }) {
this.collection = collection
}
async updateStatusByRecommendation({
recommendation,
isHandlingEditor = false,
Andrei Cioromila
committed
fragments,
}) {
let newStatus
if (isHandlingEditor) {
newStatus = 'pendingApproval'
if (['minor', 'major'].includes(recommendation)) {
newStatus = 'revisionRequested'
}
} else {
if (recommendation === 'minor') {
Andrei Cioromila
committed
newStatus = this.hasAtLeastOneReviewReport(fragments)
? 'reviewCompleted'
: 'heAssigned'
if (recommendation === 'major') {
}
}
return this.updateStatus({ newStatus })
}
async updateFinalStatusByRecommendation({ recommendation }) {
let newStatus
switch (recommendation) {
case 'reject':
newStatus = 'rejected'
break
case 'publish':
newStatus = 'accepted'
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
break
case 'return-to-handling-editor':
newStatus = 'reviewCompleted'
break
default:
break
}
await this.updateStatus({ newStatus })
}
async updateStatus({ newStatus }) {
this.collection.status = newStatus
await this.collection.save()
}
async addHandlingEditor({ user, invitation }) {
this.collection.handlingEditor = {
id: user.id,
name: `${user.firstName} ${user.lastName}`,
invitedOn: invitation.invitedOn,
respondedOn: invitation.respondedOn,
email: user.email,
hasAnswer: invitation.hasAnswer,
isAccepted: invitation.isAccepted,
}
await this.updateStatus({ newStatus: 'heInvited' })
}
async updateHandlingEditor({ isAccepted }) {
const { collection: { handlingEditor } } = this
handlingEditor.hasAnswer = true
handlingEditor.isAccepted = isAccepted
handlingEditor.respondedOn = Date.now()
const newStatus = isAccepted ? 'heAssigned' : 'submitted'
await this.updateStatus({ newStatus })
async updateStatusByNumberOfReviewers({ invitations }) {
const reviewerInvitations = invitations.filter(
inv => inv.role === 'reviewer',
)
if (reviewerInvitations.length === 0)
await this.updateStatus({ newStatus: 'heAssigned' })
}
async updateStatusOnRecommendation({ isEditorInChief, recommendation }) {
if (isEditorInChief) {
if (recommendation === 'return-to-handling-editor') {
Andrei Cioromila
committed
return this.updateStatus({ newStatus: 'reviewCompleted' })
Andrei Cioromila
committed
return this.updateFinalStatusByRecommendation({
Andrei Cioromila
committed
return this.updateStatusByRecommendation({
recommendation,
isHandlingEditor: true,
})
Sebastian Mihalache
committed
getHELastName() {
Sebastian Mihalache
committed
const [firstName, lastName] = this.collection.handlingEditor.name.split(' ')
return lastName || firstName
Sebastian Mihalache
committed
}

Mihail Hagiu
committed
Andrei Cioromila
committed
async getReviewerNumber({ userId }) {
const allCollectionFragments = await this.collection.getFragments()
const allCollectionInvitations = flatMap(
allCollectionFragments,
fragment => fragment.invitations,

Mihail Hagiu
committed
)
const allNumberedInvitationsForUser = allCollectionInvitations

Mihail Hagiu
committed
.filter(invite => invite.userId === userId)

Mihail Hagiu
committed
.filter(invite => invite.reviewerNumber)
if (isEmpty(allNumberedInvitationsForUser)) {
const maxReviewerNumber = get(
maxBy(allCollectionInvitations, 'reviewerNumber'),
'reviewerNumber',
0,
)
return maxReviewerNumber + 1
}

Mihail Hagiu
committed
return allNumberedInvitationsForUser[0].reviewerNumber
}
Andrei Cioromila
committed
// eslint-disable-next-line class-methods-use-this
hasAtLeastOneReviewReport(fragments) {
return fragments.some(fragment =>
new Fragment({ fragment }).hasReviewReport(),
)
}
canHEMakeRecommendation(fragments, fragmentHelper) {
if (this.collection.fragments.length === 1) {
return fragmentHelper.hasReviewReport()
}
const previousVersionRecommendations = get(
fragments[fragments.length - 2],
'recommendations',
[],
)

Sebastian Mihalache
committed
const lastEditorRecommendation = findLast(
Andrei Cioromila
committed
previousVersionRecommendations,
recommendation =>
recommendation.recommendationType === 'editorRecommendation',
)

Sebastian Mihalache
committed
if (lastEditorRecommendation.recommendation === 'minor') {
Andrei Cioromila
committed
return this.hasAtLeastOneReviewReport(fragments)

Sebastian Mihalache
committed
} else if (lastEditorRecommendation.recommendation === 'major') {
Andrei Cioromila
committed
return fragmentHelper.hasReviewReport()
}

Sebastian Mihalache
committed
return false
Andrei Cioromila
committed
}
Andrei Cioromila
committed
async getAllFragments({ FragmentModel }) {
return Promise.all(
this.collection.fragments.map(async fragment =>
FragmentModel.find(fragment),
),
)
}

Sebastian Mihalache
committed
isLatestVersion(fragmentId) {
return last(this.collection.fragments) === fragmentId
}
}
module.exports = Collection