Skip to content
Snippets Groups Projects
Commit 63ebc9da authored by Alexandru Munteanu's avatar Alexandru Munteanu
Browse files

refactor(faraday): update authsome and frontend to accommodate new changes

parent d68bf430
No related branches found
No related tags found
2 merge requests!13Sprint #14,!11Submit revision
Showing
with 125 additions and 59 deletions
......@@ -46,9 +46,9 @@ class Fragment {
const submittingAuthorData = authors.find(
author => author.isSubmitting === true,
)
const submittingAuthor = await UserModel.find(submittingAuthorData.userId)
const submittingAuthor = await UserModel.find(submittingAuthorData.id)
const authorsPromises = authors.map(async author => {
const user = await UserModel.find(author.userId)
const user = await UserModel.find(author.id)
return `${user.firstName} ${user.lastName}`
})
const authorsList = await Promise.all(authorsPromises)
......
......@@ -53,7 +53,10 @@ export default compose(
hasManuscriptFailure: hasManuscriptFailure(state),
version: selectFragment(state, match.params.version),
project: selectCollection(state, match.params.project),
editorialRecommendations: selectEditorialRecommendations(state),
editorialRecommendations: selectEditorialRecommendations(
state,
match.params.version,
),
canSeeEditorialComments: canSeeEditorialComments(
state,
match.params.project,
......
......@@ -100,18 +100,18 @@ const ReviewsAndReports = ({
export default compose(
connect(
(state, { project }) => ({
(state, { project, version }) => ({
reviewers: selectReviewers(state),
recommendations: selectRecommendations(state),
fetchingReviewers: selectFetchingReviewers(state),
isReviewer: currentUserIsReviewer(state, project.id),
isReviewer: currentUserIsReviewer(state, version.id),
recommendations: selectRecommendations(state, version.id),
canSeeReviewersReports: canSeeReviewersReports(state, project.id),
}),
{ getCollectionReviewers },
),
withHandlers({
getReviewers: ({ project, getCollectionReviewers }) => () => {
getCollectionReviewers(project.id)
getReviewers: ({ project, version, getCollectionReviewers }) => () => {
getCollectionReviewers(project.id, version.id)
},
mappedRecommendations: ({ recommendations, reviewers }) => () =>
recommendations.filter(r => r.submittedOn).map(r => ({
......
......@@ -171,6 +171,7 @@ const DashboardCard = ({
invitation={invitation}
modalKey={`reviewer-decision-${project.id}`}
project={project}
version={version}
/>
</RightDetails>
)}
......@@ -185,9 +186,9 @@ export default compose(
setDisplayName('DashboardCard'),
getContext({ journal: PropTypes.object, currentUser: PropTypes.object }),
withTheme,
connect((state, { project }) => ({
connect((state, { project, version }) => ({
isHE: currentUserIs(state, 'handlingEditor'),
invitation: selectInvitation(state, project.id),
invitation: selectInvitation(state, version.id),
canMakeDecision: canMakeDecision(state, project),
canInviteReviewers: canInviteReviewers(state, project),
canMakeRecommendation: canMakeRecommendation(state, project),
......
......@@ -30,20 +30,21 @@ const ModalComponent = connect(state => ({
export default compose(
connect(null, {
reviewerDecision,
getCollections: actions.getCollections,
getFragments: actions.getFragments,
}),
withModal(props => ({
modalComponent: ModalComponent,
})),
withHandlers({
decisionSuccess: ({ getCollections, hideModal }) => () => {
getCollections()
decisionSuccess: ({ getFragments, hideModal }) => () => {
getFragments()
hideModal()
},
}),
withHandlers({
showAcceptModal: ({
project,
version,
showModal,
invitation,
setModalError,
......@@ -54,7 +55,7 @@ export default compose(
title: 'Agree to review Manuscript?',
confirmText: 'Agree',
onConfirm: () => {
reviewerDecision(invitation.id, project.id, true).then(
reviewerDecision(invitation.id, project.id, version.id, true).then(
decisionSuccess,
handleError(setModalError),
)
......@@ -63,6 +64,7 @@ export default compose(
},
showDeclineModal: ({
project,
version,
showModal,
invitation,
setModalError,
......@@ -73,7 +75,7 @@ export default compose(
title: 'Decline to review Manuscript?',
confirmText: 'Decline',
onConfirm: () => {
reviewerDecision(invitation.id, project.id, false).then(
reviewerDecision(invitation.id, project.id, version.id, false).then(
decisionSuccess,
handleError(setModalError),
)
......
......@@ -31,7 +31,7 @@ export default compose(
collection: selectCollection(state, collectionId),
})),
withHandlers({
getCompactReport: ({ collection: { invitations = [] } }) => () => {
getCompactReport: ({ fragment: { invitations = [] } }) => () => {
const reviewerInvitations = invitations.filter(roleFilter('reviewer'))
const accepted = reviewerInvitations.filter(acceptedInvitationFilter)
.length
......
......@@ -124,7 +124,11 @@ export default compose(
recommendationError: selectError(state),
heRecommendation: getHERecommendation(state, collectionId, fragmentId),
}),
{ createRecommendation, getCollections: actions.getCollections },
{
createRecommendation,
getFragments: actions.getFragments,
getCollections: actions.getCollections,
},
),
withProps(({ heRecommendation: { recommendation = '', comments = [] } }) => ({
heRecommendation: {
......@@ -142,21 +146,25 @@ export default compose(
hideModal,
fragmentId,
collectionId,
getFragments,
getCollections,
createRecommendation,
},
) => {
const recommendation = parseFormValues(values)
createRecommendation(collectionId, fragmentId, recommendation).then(r => {
showModal({
onCancel: () => {
getCollections()
hideModal()
},
title: 'Decision submitted',
cancelText: 'OK',
})
})
createRecommendation(collectionId, fragmentId, recommendation).then(
() => {
showModal({
onCancel: () => {
getCollections()
getFragments()
hideModal()
},
title: 'Decision submitted',
cancelText: 'OK',
})
},
)
},
}),
)(DecisionForm)
......
......@@ -60,6 +60,7 @@ export default compose(
{
resetForm,
createRecommendation,
getFragments: actions.getFragments,
getCollections: actions.getCollections,
},
),
......@@ -77,6 +78,7 @@ export default compose(
resetForm,
fragmentId,
collectionId,
getFragments,
getCollections,
createRecommendation,
}) => values => {
......@@ -88,6 +90,7 @@ export default compose(
cancelText: 'OK',
onCancel: () => {
getCollections()
getFragments()
hideModal()
},
})
......
......@@ -36,11 +36,12 @@ const InviteReviewersModal = compose(
),
withHandlers({
getReviewers: ({
versionId,
collectionId,
setReviewers,
getCollectionReviewers,
}) => () => {
getCollectionReviewers(collectionId)
getCollectionReviewers(collectionId, versionId)
},
closeModal: ({ getCollections, hideModal }) => () => {
getCollections()
......@@ -81,6 +82,7 @@ const InviteReviewersModal = compose(
isFetching={fetchingInvite}
reviewerError={reviewerError}
reviewers={reviewers}
versionId={versionId}
/>
<Row>
......
......@@ -60,7 +60,7 @@ export default compose(
onSubmit: (
values,
dispatch,
{ inviteReviewer, collectionId, getReviewers, reset },
{ inviteReviewer, collectionId, versionId, getReviewers, reset },
) => {
const reviewerData = pick(values, [
'email',
......@@ -68,7 +68,7 @@ export default compose(
'firstName',
'affiliation',
])
inviteReviewer(reviewerData, collectionId).then(() => {
inviteReviewer(reviewerData, collectionId, versionId).then(() => {
reset()
getReviewers()
})
......
......@@ -7,7 +7,6 @@ module.exports = {
editors: () => require('./redux/editors').default,
files: () => require('./redux/files').default,
reviewers: () => require('./redux/reviewers').default,
recommendations: () => require('./redux/recommendations').default,
},
},
}
......@@ -41,10 +41,10 @@ export const updateRecommendationSuccess = recommendation => ({
export const selectFetching = state =>
get(state, 'recommendations.fetching') || false
export const selectError = state => get(state, 'recommendations.error')
export const selectRecommendations = state =>
get(state, 'recommendations.recommendations') || []
export const selectEditorialRecommendations = state =>
selectRecommendations(state).filter(
export const selectRecommendations = (state, fragmentId) =>
get(state, `fragments.${fragmentId}.recommendations`) || []
export const selectEditorialRecommendations = (state, fragmentId) =>
selectRecommendations(state, fragmentId).filter(
r => r.recommendationType === 'editorRecommendation' && r.comments,
)
// #endregion
......
......@@ -81,19 +81,17 @@ export const selectFetchingInvite = state =>
export const selectFetchingDecision = state =>
get(state, 'reviewers.fetching.decision') || false
export const selectInvitation = (state, collectionId) => {
export const selectInvitation = (state, fragmentId) => {
const currentUser = selectCurrentUser(state)
const collection = state.collections.find(c => c.id === collectionId)
const invitations = get(collection, 'invitations') || []
const invitations = get(state, `fragments.${fragmentId}.invitations`) || []
return invitations.find(
i => i.userId === currentUser.id && i.role === 'reviewer' && !i.hasAnswer,
)
}
export const currentUserIsReviewer = (state, collectionId) => {
export const currentUserIsReviewer = (state, fragmentId) => {
const currentUser = selectCurrentUser(state)
const collection = state.collections.find(c => c.id === collectionId)
const invitations = get(collection, 'invitations') || []
const invitations = get(state, `fragments.${fragmentId}.invitations`) || []
return !!invitations.find(
i =>
i.userId === currentUser.id &&
......@@ -103,22 +101,37 @@ export const currentUserIsReviewer = (state, collectionId) => {
)
}
export const getCollectionReviewers = collectionId => dispatch => {
export const getCollectionReviewers = (
collectionId,
fragmentId,
) => dispatch => {
dispatch(getReviewersRequest())
return apiGet(`/collections/${collectionId}/invitations?role=reviewer`).then(
return apiGet(
`/collections/${collectionId}/fragments/${fragmentId}/invitations?role=reviewer`,
).then(
r => dispatch(getReviewersSuccess(orderBy(r, orderReviewers))),
err => dispatch(getReviewersError(err)),
err => {
dispatch(getReviewersError(err))
throw err
},
)
}
// #endregion
// #region Actions - invitations
export const inviteReviewer = (reviewerData, collectionId) => dispatch => {
export const inviteReviewer = (
reviewerData,
collectionId,
fragmentId,
) => dispatch => {
dispatch(inviteRequest())
return create(`/collections/${collectionId}/invitations`, {
...reviewerData,
role: 'reviewer',
}).then(
return create(
`/collections/${collectionId}/fragments/${fragmentId}/invitations`,
{
...reviewerData,
role: 'reviewer',
},
).then(
() => dispatch(inviteSuccess()),
err => {
dispatch(inviteError(get(JSON.parse(err.response), 'error')))
......@@ -153,12 +166,16 @@ export const revokeReviewer = (invitationId, collectionId) => dispatch => {
export const reviewerDecision = (
invitationId,
collectionId,
fragmentId,
agree = true,
) => dispatch => {
dispatch(reviewerDecisionRequest())
return update(`/collections/${collectionId}/invitations/${invitationId}`, {
isAccepted: agree,
}).then(
return update(
`/collections/${collectionId}/fragments/${fragmentId}/invitations/${invitationId}`,
{
isAccepted: agree,
},
).then(
res => {
dispatch(reviewerDecisionSuccess())
return res
......
......@@ -59,8 +59,12 @@ const filterObjectData = (
return object
}
const getTeamsByPermissions = async (teamIds = [], permissions, TeamModel) => {
const teams = await Promise.all(
const getTeamsByPermissions = async (
teamIds = [],
permissions = [],
TeamModel,
) =>
(await Promise.all(
teamIds.map(async teamId => {
const team = await TeamModel.find(teamId)
if (!permissions.includes(team.teamType.permissions)) {
......@@ -68,15 +72,20 @@ const getTeamsByPermissions = async (teamIds = [], permissions, TeamModel) => {
}
return team
}),
)
)).filter(Boolean)
return teams.filter(Boolean)
}
const heIsInvitedToFragment = async ({ user, Team, collectionId }) =>
(await getTeamsByPermissions(user.teams, ['handlingEditor'], Team)).some(
// user is a member of the team with access to the fragment's parent collection
t => t.members.includes(user.id) && t.object.id === collectionId,
)
module.exports = {
filterObjectData,
parseAuthorsData,
setPublicStatuses,
filterRefusedInvitations,
filterObjectData,
getTeamsByPermissions,
filterRefusedInvitations,
//
heIsInvitedToFragment,
}
......@@ -119,6 +119,28 @@ async function authenticatedUser(user, operation, object, context) {
}
}
// get fragments for invited reviewers
if (
operation === 'GET' &&
get(object, 'type') === 'fragment' &&
get(object, 'invitations').some(i => i.userId === user.id)
) {
return true
}
// TODO: in the future give him the non draft version of the fragment
if (
operation === 'GET' &&
get(object, 'type') === 'fragment' &&
user.handlingEditor
) {
return helpers.heIsInvitedToFragment({
user,
Team: context.models.Team,
collectionId: object.collectionId,
})
}
if (
operation === 'POST' &&
object.path === '/collections/:collectionId/fragments'
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment