diff --git a/packages/component-faraday-ui/src/ContextualBox.js b/packages/component-faraday-ui/src/ContextualBox.js index 016b6618f4e3bf09e7c92d4c7f246a6ecbfe7a70..32ff2966e40f3884d0069955ea65d619a1e8c689 100644 --- a/packages/component-faraday-ui/src/ContextualBox.js +++ b/packages/component-faraday-ui/src/ContextualBox.js @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react' +import React from 'react' import { has } from 'lodash' import styled from 'styled-components' import { Icon, H3 } from '@pubsweet/ui' @@ -21,12 +21,12 @@ const CustomHeader = ({ onClick={toggle} transparent={transparent} > - <Fragment> + <div> <Icon secondary size={2}> {expanded ? 'minus' : 'plus'} </Icon> <H3>{label}</H3> - </Fragment> + </div> {typeof rightChildren === 'function' ? rightChildren({ ...props, expanded, transparent }) : rightChildren} diff --git a/packages/component-faraday-ui/src/InviteReviewers.js b/packages/component-faraday-ui/src/InviteReviewers.js new file mode 100644 index 0000000000000000000000000000000000000000..4be1711af62034edc507eb0c33adbbcfa01a3b6c --- /dev/null +++ b/packages/component-faraday-ui/src/InviteReviewers.js @@ -0,0 +1,105 @@ +import React from 'react' +import { compose } from 'recompose' +import styled from 'styled-components' +import { reduxForm } from 'redux-form' +import { th } from '@pubsweet/ui-toolkit' +import { required } from 'xpub-validators' +import { withModal } from 'pubsweet-component-modal/src/components' +import { Button, H4, Menu, TextField, ValidatedField } from '@pubsweet/ui' + +import { + Row, + Item, + Label, + MultiAction, + ItemOverrideAlert, + withFetching, + withCountries, +} from '../' + +const InviteReviewers = ({ countries, handleSubmit, reset }) => ( + <Root> + <Row justify="space-between" mb={2}> + <H4>Invite reviewer</H4> + <Item justify="flex-end"> + <Button onClick={reset} size="small"> + Clear Fields + </Button> + <Button ml={2} onClick={handleSubmit} primary size="small"> + Invite + </Button> + </Item> + </Row> + <Row> + <Item mr={2} vertical> + <Label required>Email</Label> + <ValidatedField + component={TextField} + name="email" + validate={[required]} + /> + </Item> + <Item mr={2} vertical> + <Label required>First Name</Label> + <ValidatedField + component={TextField} + name="firstName" + validate={[required]} + /> + </Item> + <Item mr={2} vertical> + <Label required>Last Name</Label> + <ValidatedField + component={TextField} + name="lastName" + validate={[required]} + /> + </Item> + <Item mr={2} vertical> + <Label required>Affiliation</Label> + <ValidatedField + component={TextField} + name="affiliation" + validate={[required]} + /> + </Item> + + <ItemOverrideAlert vertical> + <Label required>Country</Label> + <ValidatedField + component={input => <Menu options={countries} {...input} />} + name="country" + validate={[required]} + /> + </ItemOverrideAlert> + </Row> + </Root> +) + +export default compose( + withFetching, + withCountries, + withModal(({ isFetching, modalKey }) => ({ + modalKey, + isFetching, + modalComponent: MultiAction, + })), + reduxForm({ + form: 'invite-reviewers-form', + onSubmit: (values, dispatch, { showModal, onInvite, setFetching }) => { + showModal({ + title: 'Send invitation to Review?', + subtitle: values.email, + onConfirm: modalProps => { + onInvite(values, { ...modalProps, setFetching }) + }, + }) + }, + }), +)(InviteReviewers) + +// #region styles +const Root = styled.div` + padding: calc(${th('gridUnit')} * 2); +` +// #endregion diff --git a/packages/component-faraday-ui/src/InviteReviewers.md b/packages/component-faraday-ui/src/InviteReviewers.md new file mode 100644 index 0000000000000000000000000000000000000000..851bb7ceb0f93de220d32ce6b954cabf6bec40e1 --- /dev/null +++ b/packages/component-faraday-ui/src/InviteReviewers.md @@ -0,0 +1,9 @@ +The invite reviewers form. + +```js +<InviteReviewers + onInvite={(reviewer, props) => { + props.setFetching(true) + }} +/> +``` diff --git a/packages/component-faraday-ui/src/ReviewersTable.js b/packages/component-faraday-ui/src/ReviewersTable.js index e0bdabb2722aa52c0e0fcf9bd5382c43bcba6bb9..0bc9fbeb8a05fc60c7320ff0ef6e95390f82200c 100644 --- a/packages/component-faraday-ui/src/ReviewersTable.js +++ b/packages/component-faraday-ui/src/ReviewersTable.js @@ -166,7 +166,6 @@ export default ReviewersTable // #region styles const Table = styled.table` border-collapse: collapse; - padding: ${th('gridUnit')}; & thead { border-bottom: 1px solid ${th('colorBorder')}; @@ -175,7 +174,7 @@ const Table = styled.table` & th, & td { border: none; - padding-left: ${th('gridUnit')}; + padding-left: calc(${th('gridUnit')} * 2); text-align: start; vertical-align: middle; diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js index cca9baae989cda6722630bc6a91e37984aa23b3b..50ae31b1d8799a3576d7c4e00f77fda1ada7d463 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js +++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.js @@ -10,6 +10,7 @@ import { ContextualBox, ReviewersTable, ReviewerReport, + InviteReviewers, ReviewerBreakdown, } from '../' @@ -34,7 +35,7 @@ const report = { ], } -const ReviewerDetails = ({ fragment }) => ( +const ReviewerDetails = ({ fragment, onInviteReviewer }) => ( <ContextualBox label="Reviewer details" rightChildren={<ReviewerBreakdown fitContent fragment={fragment} mr={1} />} @@ -62,7 +63,15 @@ const ReviewerDetails = ({ fragment }) => ( <Tag ml={1}>12</Tag> </TabButton> </TabsHeader> - {selectedTab === 0 && <ReviewersTable />} + {selectedTab === 0 && ( + <Fragment> + <InviteReviewers + modalKey="invite-reviewers" + onInvite={onInviteReviewer} + /> + <ReviewersTable /> + </Fragment> + )} {selectedTab === 1 && ( <Fragment> <ReviewerReport report={report} /> diff --git a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.md b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.md index 49bb54a7d348719cc44c2b822edcaf016d163d5c..8bfbd999d963d485d270504363724999d681034a 100644 --- a/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.md +++ b/packages/component-faraday-ui/src/contextualBoxes/ReviewerDetails.md @@ -77,7 +77,11 @@ const fragment = { }, ], } -; -<ReviewerDetails fragment={fragment} /> +;<ReviewerDetails + fragment={fragment} + onInviteReviewer={(reviewer, modalProps) => { + modalProps.setFetching(true) + }} +/> ``` diff --git a/packages/component-faraday-ui/src/index.js b/packages/component-faraday-ui/src/index.js index b186e2a8a42a0312a827520948661dfa5d57c348..88eb9e4be5129fb6851cb9f74ff01c2e35c24301 100644 --- a/packages/component-faraday-ui/src/index.js +++ b/packages/component-faraday-ui/src/index.js @@ -22,6 +22,7 @@ export { default as Footer } from './Footer' export { default as IconButton } from './IconButton' export { default as IconCard } from './IconCard' export { default as IconTooltip } from './IconTooltip' +export { default as InviteReviewers } from './InviteReviewers' export { default as Label } from './Label' export { default as ManuscriptCard } from './ManuscriptCard' export { default as ReviewerBreakdown } from './ReviewerBreakdown' diff --git a/packages/component-faraday-ui/src/manuscriptDetails/HandlingEditorAnswer.md b/packages/component-faraday-ui/src/manuscriptDetails/HandlingEditorAnswer.md deleted file mode 100644 index 21d5d620c87fbf2b1d69e8ff8c616e4a8cc75013..0000000000000000000000000000000000000000 --- a/packages/component-faraday-ui/src/manuscriptDetails/HandlingEditorAnswer.md +++ /dev/null @@ -1,21 +0,0 @@ -Handling Editor answer invitation. - -```js -const formValues = { - decision: 'decline', -}; - -<RemoteOpener> -{ - ({toggle, expanded}) => - <HandlingEditorAnswer - formValues={formValues} - expanded={expanded} - toggle={toggle} - onResponse={(values, { setFetching }) => { - setFetching(true) - }} - /> -} -</RemoteOpener> -``` diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js index e0511b97b0a7070469d2779023ead0e017deb310..205719b95fb817a3b67b0e0d8b18da2e807ca05d 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptMetadata.js @@ -1,5 +1,6 @@ import React, { Fragment } from 'react' import { isEmpty, get } from 'lodash' +import { withProps } from 'recompose' import { Text, @@ -9,6 +10,7 @@ import { } from 'pubsweet-component-faraday-ui' const ManuscriptMetadata = ({ + filesLabel, getSignedUrl, currentUser: { token }, fragment: { files = {}, conflicts = {}, metadata: { abstract = '' } }, @@ -34,12 +36,7 @@ const ManuscriptMetadata = ({ )} {!isEmpty(files) && ( <Item mb={1}> - <ContextualBox - label={`Files (${files.coverLetter.length + - files.manuscripts.length + - files.supplementary.length})`} - transparent - > + <ContextualBox label={filesLabel} transparent> <ManuscriptFileList files={files} getSignedUrl={getSignedUrl} @@ -51,4 +48,8 @@ const ManuscriptMetadata = ({ </Fragment> ) -export default ManuscriptMetadata +export default withProps(({ fragment: { files } }) => ({ + filesLabel: `Files (${get(files, 'manuscripts', []).length + + get(files, 'coverLetter', []).length + + get(files, 'supplementary', []).length})`, +}))(ManuscriptMetadata) diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index b1fc53ae09426250b0ebf3c4552d6cdd06e8875e..5d4688ff7b86b99f0edf4319051041e9bdc10bce 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -3,6 +3,7 @@ import styled from 'styled-components' import { isEmpty, get, last } from 'lodash' import { Text, + ReviewerDetails, ManuscriptHeader, ManuscriptAssignHE, ManuscriptMetadata, @@ -46,6 +47,7 @@ const ManuscriptLayout = ({ toggleHEResponse, heResponseExpanded, onHEResponse, + onInviteReviewer, }) => ( <Root pb={1}> {!isEmpty(collection) && !isEmpty(fragment) ? ( @@ -110,6 +112,11 @@ const ManuscriptLayout = ({ submitDecision={createRecommendation} /> )} + + <ReviewerDetails + fragment={fragment} + onInviteReviewer={onInviteReviewer} + /> </Fragment> ) : ( <Text>Loading...</Text> diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index fb18e691bd87ebc10877a2f9959d71c5e573b368..4936961edea1c0b285677627fc82b53a52c8e3ed 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -22,7 +22,10 @@ import { fromRenderProps, } from 'recompose' import { getSignedUrl } from 'pubsweet-components-faraday/src/redux/files' -import { reviewerDecision } from 'pubsweet-components-faraday/src/redux/reviewers' +import { + inviteReviewer, + reviewerDecision, +} from 'pubsweet-components-faraday/src/redux/reviewers' import { hasManuscriptFailure, clearCustomError, @@ -65,6 +68,7 @@ export default compose( ConnectPage(({ match }) => [ actions.getCollection({ id: match.params.project }), actions.getFragments({ id: match.params.project }), + actions.getUsers(), ]), connect( (state, { match }) => ({ @@ -232,6 +236,26 @@ export default compose( setModalError('Something went wrong...') }) }, + onInviteReviewer: ({ collection, fragment, fetchUpdatedCollection }) => ( + values, + { hideModal, setModalError, setFetching }, + ) => { + setFetching(true) + inviteReviewer({ + reviewerData: values, + fragmentId: fragment.id, + collectionId: collection.id, + }) + .then(() => { + setFetching(false) + hideModal() + fetchUpdatedCollection() + }) + .catch(() => { + setFetching(false) + setModalError('Something went wrong...') + }) + }, }), fromRenderProps(RemoteOpener, ({ toggle, expanded }) => ({ toggleAssignHE: toggle, diff --git a/packages/components-faraday/src/redux/reviewers.js b/packages/components-faraday/src/redux/reviewers.js index 415c8076a7fed3c6ef68c8dc57b8e4125b22d6ce..1c3212d7f4b913eb20b7ea06116934cd3c615900 100644 --- a/packages/components-faraday/src/redux/reviewers.js +++ b/packages/components-faraday/src/redux/reviewers.js @@ -118,28 +118,13 @@ export const getCollectionReviewers = ( } // #endregion -// #region Actions - invitations -export const inviteReviewer = ( - reviewerData, - collectionId, - fragmentId, -) => dispatch => { - dispatch(inviteRequest()) - return create( - `/collections/${collectionId}/fragments/${fragmentId}/invitations`, - { - ...reviewerData, - role: 'reviewer', - }, - ).then( - () => dispatch(inviteSuccess()), - err => { - dispatch(inviteError(get(JSON.parse(err.response), 'error'))) - throw err - }, - ) -} +export const inviteReviewer = ({ reviewerData, collectionId, fragmentId }) => + create(`/collections/${collectionId}/fragments/${fragmentId}/invitations`, { + ...reviewerData, + role: 'reviewer', + }) +// #region Actions - invitations export const setReviewerPassword = reviewerBody => dispatch => { dispatch(reviewerDecisionRequest()) return create(`/users/reset-password`, reviewerBody).then(r => { diff --git a/packages/hindawi-theme/src/elements/Menu.js b/packages/hindawi-theme/src/elements/Menu.js index a35f18829d176d0a214ddf1d14079bf662e6c41d..3f3878c1c89d55ecb6726163feea99d9ef3ea3e9 100644 --- a/packages/hindawi-theme/src/elements/Menu.js +++ b/packages/hindawi-theme/src/elements/Menu.js @@ -6,7 +6,6 @@ export default { background: ${th('colorBackgroundHue')}; height: calc(${th('gridUnit')} * 4); border-radius: ${th('borderRadius')}; - min-width: 120px; `, Value: css` border: none;