Skip to content
Snippets Groups Projects
Commit 20abacaa authored by Daniel Sandu's avatar Daniel Sandu
Browse files

Merge branch 'develop' of gitlab.coko.foundation:xpub/xpub-faraday into HIN-1033

parents a86963d4 de1c8001
No related branches found
No related tags found
2 merge requests!110Sprint 21 Features,!83Hin 1033
Showing
with 289 additions and 38 deletions
......@@ -2,10 +2,12 @@ import { get, has, last, chain } from 'lodash'
import { selectCurrentUser } from 'xpub-selectors'
export const isHEToManuscript = (state, collectionId) => {
const currentUserId = get(state, 'currentUser.user.id', '')
const collections = get(state, 'collections', [])
const collection = collections.find(c => c.id === collectionId) || {}
return get(collection, 'handlingEditor.id') === currentUserId
const { id = '', isAccepted = false } = chain(state)
.get('collections', [])
.find(c => c.id === collectionId)
.get('handlingEditor', '')
.value()
return isAccepted && id === get(state, 'currentUser.user.id')
}
export const currentUserIs = ({ currentUser: { user } }, role) => {
......@@ -233,6 +235,17 @@ export const getInvitationsWithReviewersForFragment = (state, fragmentId) =>
}))
.value()
export const canMakeHERecommendation = (state, { collection, statuses }) => {
const validHE = isHEToManuscript(state, get(collection, 'id', ''))
const statusImportance = get(
statuses,
`${get(collection, 'status', 'draft')}.importance`,
1,
)
return statusImportance > 1 && statusImportance < 9 && validHE
}
// #region Editorial and reviewer recommendations
export const getFragmentRecommendations = (state, fragmentId) =>
get(state, `fragments.${fragmentId}.recommendations`, [])
......
......@@ -15,7 +15,7 @@ const EditorialReportCard = ({
recommendation,
reviewerName,
reviewerRole,
report: { submittedOn, reviewer },
report: { createdOn, reviewer },
}) => (
<Root>
<Row justify="space-between" mb={2}>
......@@ -31,7 +31,7 @@ const EditorialReportCard = ({
<Tag mr={2}>{reviewerRole}</Tag>
</Fragment>
)}
<DateParser timestamp={submittedOn}>
<DateParser timestamp={createdOn}>
{date => <Text>{date}</Text>}
</DateParser>
</Item>
......
......@@ -2,7 +2,7 @@ Toggle a boolean flag and pass it around in your React components tree.
```js
<RemoteOpener>
{(expanded, toggle) => (
{({ expanded, toggle }) => (
<div>
<button onClick={toggle}>Toggle</button>
<span>{expanded ? 'Collapse me!' : 'Expand me!'}</span>
......
......@@ -14,7 +14,7 @@ const ReviewersTable = ({
onResendReviewerInvite,
onRevokeReviewerInvite,
}) =>
invitations.length > 0 && (
invitations.length > 0 ? (
<Table>
<thead>
<tr>
......@@ -82,6 +82,8 @@ const ReviewersTable = ({
))}
</tbody>
</Table>
) : (
<Text align="center">No reviewers invited yet.</Text>
)
const orderInvitations = i => {
......
import React from 'react'
import { get, tail } from 'lodash'
import { reduxForm } from 'redux-form'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { required } from 'xpub-validators'
import { compose, withProps } from 'recompose'
import { Button, Menu, ValidatedField } from '@pubsweet/ui'
import { withModal } from 'pubsweet-component-modal/src/components'
import {
Row,
Text,
Label,
Textarea,
MultiAction,
ContextualBox,
ItemOverrideAlert,
withFetching,
} from 'pubsweet-component-faraday-ui/src'
const options = [
{ value: 'publish', label: 'Publish' },
{ value: 'reject', label: 'Reject' },
{ value: 'minor', label: 'Request Minor Revision' },
{ value: 'major', label: 'Request Major Revision' },
]
const parseFormValues = ({ recommendation, ...rest }) => {
const comments = Object.entries(rest).map(([key, value]) => ({
content: value,
public: key === 'public',
files: [],
}))
return {
comments,
recommendation,
recommendationType: 'editorRecommendation',
}
}
const HERecommendation = ({
formValues,
handleSubmit,
hasReviewerReports,
highlight,
}) => (
<ContextualBox
highlight={highlight}
label="Your Editorial Recommendation"
mb={2}
>
<Root>
<Row justify="flex-start">
<ItemOverrideAlert flex={0} vertical>
<Label required>Recommendation</Label>
<ValidatedField
component={input => (
<Menu
options={hasReviewerReports ? options : tail(options)}
{...input}
/>
)}
name="recommendation"
validate={[required]}
/>
</ItemOverrideAlert>
</Row>
{get(formValues, 'recommendation') === 'publish' ||
get(formValues, 'recommendation') === 'reject' ? (
<Row mt={2}>
<ItemOverrideAlert vertical>
<Label required>Message for Author</Label>
<ValidatedField
component={Textarea}
name="public"
validate={[required]}
/>
</ItemOverrideAlert>
</Row>
) : (
<ResponsiveRow mt={2}>
<ResponsiveItem mr={1} vertical>
<Label>
Message for Author <Text secondary>Optional</Text>
</Label>
<ValidatedField component={Textarea} name="public" />
</ResponsiveItem>
<ResponsiveItem ml={1} vertical>
<Label>
Message for Editor in Chief <Text secondary>Optional</Text>
</Label>
<ValidatedField component={Textarea} name="private" />
</ResponsiveItem>
</ResponsiveRow>
)}
<Row justify="flex-end" mt={2}>
<Button onClick={handleSubmit} primary size="medium">
Submit recommendation
</Button>
</Row>
</Root>
</ContextualBox>
)
export default compose(
withFetching,
withModal(({ isFetching }) => ({
isFetching,
modalComponent: MultiAction,
})),
withProps(({ formValues }) => ({
modalTitle: options.find(
o => o.value === get(formValues, 'recommendation', 'publish'),
).label,
})),
reduxForm({
form: 'HERecommendation',
onSubmit: (
values,
dispatch,
{ onRecommendationSubmit, showModal, setFetching, modalTitle },
) => {
showModal({
title: `${modalTitle}?`,
onConfirm: props => {
onRecommendationSubmit(parseFormValues(values), {
...props,
setFetching,
})
},
})
},
}),
)(HERecommendation)
// #region styles
const Root = styled.div`
display: flex;
flex-direction: column;
padding: ${th('gridUnit')};
`
const ResponsiveRow = styled(Row)`
@media (max-width: 800px) {
flex-direction: column;
}
`
const ResponsiveItem = styled(ItemOverrideAlert)`
@media (max-width: 800px) {
margin-right: 0;
margin-left: 0;
width: 100%;
}
`
// #endregion
HE recommendation.
```js
const formValues = {
recommendation: 'minor-revision',
}
;<HERecommendation
formValues={formValues}
modalKey="heRecommendation"
onRecommendationSubmit={(values, props) => {
console.log('se face surmit la', values)
props.setFetching(true)
}}
/>
```
......@@ -30,15 +30,22 @@ const ReviewerDetails = ({
onInviteReviewer,
onResendReviewerInvite,
onRevokeReviewerInvite,
toggle,
expanded,
highlight,
canViewReviewersDetails,
...rest
}) =>
canViewReviewersDetails ? (
<ContextualBox
expanded={expanded}
highlight={highlight}
label="Reviewer Details & Reports"
rightChildren={
<ReviewerBreakdown fitContent fragment={fragment} mr={1} />
}
startExpanded
toggle={toggle}
{...rest}
>
<Tabs>
{({ selectedTab, changeTab }) => (
......
export { default as AssignHE } from './AssignHE'
export { default as ReviewerDetails } from './ReviewerDetails'
export { default as HERecommendation } from './HERecommendation'
export { default as ReviewerReportForm } from './ReviewerReportForm'
......@@ -2,12 +2,12 @@ import { withStateHandlers } from 'recompose'
export default withStateHandlers(
{
isFetchingg: false,
isFetching: false,
fetchingError: '',
},
{
setFetching: ({ isFetchingg }) => value => ({
isFetchingg: value,
setFetching: ({ isFetching }) => value => ({
isFetching: value,
}),
toggleFetching: ({ isFetching }) => () => ({
isFetching: !isFetching,
......
const Chance = require('chance')
const chance = new Chance()
const collId = chance.guid()
module.exports = {
standardCollID: collId,
standardCollID: chance.guid(),
collectionReviewCompletedID: chance.guid(),
}
const Chance = require('chance')
const { user, handlingEditor, answerHE } = require('./userData')
const { fragment, reviewCompletedFragment } = require('./fragments')
const { standardCollID } = require('./collectionIDs')
const {
standardCollID,
collectionReviewCompletedID,
} = require('./collectionIDs')
const chance = new Chance()
const collections = {
......@@ -90,6 +93,7 @@ const collections = {
status: 'pendingApproval',
},
collectionReviewCompleted: {
id: collectionReviewCompletedID,
type: 'collection',
owners: [user.id],
status: 'reviewCompleted',
......
......@@ -8,7 +8,10 @@ const {
admin,
inactiveReviewer,
} = require('./userData')
const { standardCollID } = require('./collectionIDs')
const {
standardCollID,
collectionReviewCompletedID,
} = require('./collectionIDs')
const { user } = require('./userData')
const chance = new Chance()
......@@ -38,9 +41,10 @@ const fragments = {
},
],
id: chance.guid(),
userId: recReviewer.id,
userId: answerReviewer.id,
createdOn: chance.timestamp(),
updatedOn: chance.timestamp(),
submittedOn: chance.timestamp(),
},
{
recommendation: 'minor',
......@@ -213,7 +217,7 @@ const fragments = {
hasConflicts: 'no',
hasDataAvailability: 'yes',
},
submitted: 1539000486993,
submitted: chance.timestamp(),
invitations: [
{
id: chance.guid(),
......@@ -246,7 +250,7 @@ const fragments = {
respondedOn: chance.timestamp(),
},
],
collectionId: standardCollID,
collectionId: collectionReviewCompletedID,
declarations: {
agree: true,
},
......
const Chance = require('chance')
const chance = new Chance()
const heID = chance.guid()
const revId = chance.guid()
const authorID = chance.guid()
module.exports = {
heTeamID: heID,
revTeamID: revId,
authorTeamID: authorID,
heTeamID: chance.guid(),
revTeamID: chance.guid(),
authorTeamID: chance.guid(),
revRecommendationTeamID: chance.guid(),
}
......@@ -2,12 +2,23 @@ const users = require('./users')
const collections = require('./collections')
const fragments = require('./fragments')
const { heTeamID, revTeamID, authorTeamID } = require('./teamIDs')
const {
heTeamID,
revTeamID,
authorTeamID,
revRecommendationTeamID,
} = require('./teamIDs')
const { submittingAuthor } = require('./userData')
const { collection } = collections
const { fragment } = fragments
const { handlingEditor, reviewer, inactiveReviewer } = users
const { fragment, reviewCompletedFragment } = fragments
const {
handlingEditor,
reviewer,
inactiveReviewer,
answerReviewer,
recReviewer,
} = users
const teams = {
heTeam: {
teamType: {
......@@ -36,11 +47,27 @@ const teams = {
type: 'fragment',
id: fragment.id,
},
members: [reviewer.id, inactiveReviewer.id],
members: [reviewer.id, inactiveReviewer.id, answerReviewer.id],
save: jest.fn(() => teams.revTeam),
updateProperties: jest.fn(() => teams.revTeam),
id: revTeamID,
},
revRecommendationTeam: {
teamType: {
name: 'reviewer',
permissions: 'reviewer',
},
group: 'reviewer',
name: 'reviewer',
object: {
type: 'fragment',
id: reviewCompletedFragment.id,
},
members: [reviewer.id, answerReviewer.id, recReviewer.id],
save: jest.fn(() => teams.revRecommendationTeam),
updateProperties: jest.fn(() => teams.revRecommendationTeam),
id: revRecommendationTeamID,
},
authorTeam: {
teamType: {
name: 'author',
......
......@@ -2,7 +2,12 @@ const Chance = require('chance')
const usersData = require('./userData')
const chance = new Chance()
const { heTeamID, revTeamID, authorTeamID } = require('./teamIDs')
const {
heTeamID,
revTeamID,
authorTeamID,
revRecommendationTeamID,
} = require('./teamIDs')
const keys = Object.keys(usersData)
let users = {}
......@@ -17,12 +22,12 @@ users = keys.reduce((obj, item) => {
if (item === 'author') {
teams = [authorTeamID]
}
if (
['reviewer', 'answerReviewer', 'recReviewer', 'inactiveReviewer'].includes(
item,
)
) {
teams = [revTeamID]
if (['reviewer', 'inactiveReviewer', 'answerReviewer'].includes(item)) {
teams.push(revTeamID)
}
if (['reviewer', 'answerReviewer', 'recReviewer'].includes(item)) {
teams.push(revRecommendationTeamID)
}
obj[item] = {
......
const authsomeMode = require('xpub-faraday/config/authsome-mode')
module.exports = authsomeMode
const defaultConfig = require('xpub-faraday/config/default')
module.exports = defaultConfig
const defaultConfig = require('xpub-faraday/config/default')
module.exports = defaultConfig
......@@ -22,5 +22,12 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "jest"
},
"jest": {
"verbose": true,
"testRegex": "/src/.*.test.js$"
}
}
const Email = require('./services/email/Email')
const Collection = require('./services/Collection')
const Fragment = require('./services/Fragment')
const services = require('./services/services')
......@@ -8,7 +7,6 @@ const Team = require('./services/Team')
const Invitation = require('./services/Invitation')
module.exports = {
Email,
Collection,
Fragment,
services,
......
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