Skip to content
Snippets Groups Projects
Commit 063d5ffd authored by Andrei Cioromila's avatar Andrei Cioromila
Browse files

Merge branch 'develop' of gitlab.coko.foundation:xpub/xpub-faraday into hin-1036

parents 8bd1dd51 96a86f36
No related branches found
No related tags found
3 merge requests!160Update staging with master features,!150Develop,!89Hin 1036
Showing
with 328 additions and 51 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>
......
......@@ -92,7 +92,12 @@ const ManuscriptCard = ({
title="Are you sure you want to delete this submission?"
>
{onClickEvent => (
<ActionLink icon="trash" onClick={onClickEvent}>
<ActionLink
icon="trash"
onClick={onClickEvent}
size="small"
style={{ height: 16 }}
>
Delete
</ActionLink>
)}
......
......@@ -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 => {
......
......@@ -4,12 +4,9 @@ const Tabs = ({ items, selectedTab, changeTab, children }) =>
children({ selectedTab, changeTab })
export default compose(
withStateHandlers(
{ selectedTab: 0 },
{
changeTab: () => selectedTab => ({
selectedTab,
}),
},
),
withStateHandlers(({ selectedTab = 0 }) => ({ selectedTab }), {
changeTab: () => selectedTab => ({
selectedTab,
}),
}),
)(Tabs)
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',
message: 'Recommend Manuscript for Publishing',
button: 'Submit Recommendation',
},
{
value: 'reject',
label: 'Reject',
message: 'Recommend Manuscript for Rejection',
button: 'Submit Recommendation',
},
{
value: 'minor',
label: 'Request Minor Revision',
message: 'Request Minor Revision',
button: 'Request Revision',
},
{
value: 'major',
label: 'Request Major Revision',
message: 'Request Major Revision',
button: 'Request 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') === 'minor' ||
get(formValues, 'recommendation') === 'major' ? (
<Row mt={2}>
<ResponsiveItem mr={1} vertical>
<Label>
Message for Author <Text secondary>Optional</Text>
</Label>
<ValidatedField component={Textarea} name="public" />
</ResponsiveItem>
</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">
{
options.find(
o => o.value === get(formValues, 'recommendation', 'publish'),
).button
}
</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'),
).message,
confirmMessage: options.find(
o => o.value === get(formValues, 'recommendation', 'publish'),
).button,
})),
reduxForm({
form: 'HERecommendation',
onSubmit: (
values,
dispatch,
{
onRecommendationSubmit,
showModal,
setFetching,
modalTitle,
confirmMessage,
},
) => {
showModal({
title: `${modalTitle}?`,
confirmText:
confirmMessage === 'Submit Recommendation'
? 'Submit'
: confirmMessage,
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)
}}
/>
```
......@@ -21,7 +21,7 @@ import {
const ReviewerDetails = ({
journal,
reports,
reports = [],
fragment,
invitations,
previewFile,
......@@ -30,17 +30,24 @@ 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>
<Tabs selectedTab={reports.length ? 1 : 0}>
{({ selectedTab, changeTab }) => (
<Fragment>
<TabsHeader>
......
export { default as AssignHE } from './AssignHE'
export { default as ReviewerDetails } from './ReviewerDetails'
export { default as HERecommendation } from './HERecommendation'
export { default as ReviewerReportForm } from './ReviewerReportForm'
......@@ -9,8 +9,6 @@ const countryMapper = c => {
return 'SRB'
case 'ME':
return 'MNT'
case 'CG':
return 'CD'
default:
return c
}
......@@ -24,8 +22,6 @@ const codeMapper = c => {
return 'RS'
case 'MNT':
return 'ME'
case 'CD':
return 'CG'
default:
return c
}
......
......@@ -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
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