From e1ae78829aca5fd7329dd0b5039b8c606dc90909 Mon Sep 17 00:00:00 2001 From: Alexandru Munteanu <alexandru.munt@gmail.com> Date: Wed, 30 May 2018 13:53:18 +0300 Subject: [PATCH] feat(eic-decision): show decision modal --- .../src/components/Dashboard/DashboardCard.js | 20 ++- .../src/components/MakeDecision/Decision.js | 55 ++++++ .../components/MakeDecision/DecisionForm.js | 160 ++++++++++++++++++ .../src/components/MakeDecision/index.js | 2 + .../MakeRecommendation/RecommendWizard.js | 1 - .../src/components/UIComponents/FormItems.js | 6 +- 6 files changed, 237 insertions(+), 7 deletions(-) create mode 100644 packages/components-faraday/src/components/MakeDecision/Decision.js create mode 100644 packages/components-faraday/src/components/MakeDecision/DecisionForm.js create mode 100644 packages/components-faraday/src/components/MakeDecision/index.js diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js index 9e724a3c4..33acb19dd 100644 --- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js +++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js @@ -4,14 +4,13 @@ import { connect } from 'react-redux' import PropTypes from 'prop-types' import { Button, Icon, th } from '@pubsweet/ui' import styled, { css, withTheme } from 'styled-components' -import { compose, getContext, withHandlers } from 'recompose' +import { compose, getContext, withHandlers, withProps } from 'recompose' import { withModal, ConfirmationModal, } from 'pubsweet-component-modal/src/components' import { DateParser } from 'pubsweet-components-faraday/src/components' import { AuthorsWithTooltip } from 'pubsweet-component-manuscript/src/molecules' -// import { AuthorsWithTooltip } from '@pubsweet/ui' import ZipFiles from '../Files/ZipFiles' import { InviteReviewers } from '../Reviewers/' @@ -21,6 +20,7 @@ import { ReviewerDecision, HandlingEditorSection } from './' import { parseVersion, parseJournalIssue, mapStatusToLabel } from './../utils' import { canMakeRecommendation } from '../../../../component-faraday-selectors/src' +import { Decision } from '../MakeDecision' import { ReviewerBreakdown } from '../Invitations' import { Recommendation } from '../MakeRecommendation' @@ -34,6 +34,7 @@ const DashboardCard = ({ invitation, currentUser, deleteProject, + heRecommendation, showAbstractModal, canInviteReviewers, showConfirmationModal, @@ -62,6 +63,10 @@ const DashboardCard = ({ /> </LeftDetails> <RightDetails flex={2}> + <Decision + heRecommendation={heRecommendation} + modalKey={`decide-${version.id}`} + /> {canMakeRecommendation && ( <Recommendation collectionId={project.id} @@ -186,7 +191,6 @@ export default compose( invitation: selectInvitation(state, project.id), canMakeRecommendation: canMakeRecommendation(state, project), })), - withHandlers({ canInviteReviewers: ({ currentUser, project }) => () => { const handlingEditor = get(project, 'handlingEditor') @@ -217,6 +221,16 @@ export default compose( }) }, }), + withProps( + ({ version: { recommendations = [] }, project: { handlingEditor } }) => ({ + heRecommendation: + recommendations.find( + r => + r.recommendationType === 'editorRecommendation' && + r.userId === get(handlingEditor, 'id'), + ) || {}, + }), + ), )(DashboardCard) // #region styled-components diff --git a/packages/components-faraday/src/components/MakeDecision/Decision.js b/packages/components-faraday/src/components/MakeDecision/Decision.js new file mode 100644 index 000000000..bdd6e7ba1 --- /dev/null +++ b/packages/components-faraday/src/components/MakeDecision/Decision.js @@ -0,0 +1,55 @@ +import React from 'react' +import { th } from '@pubsweet/ui' +import styled from 'styled-components' +import { compose, withHandlers } from 'recompose' + +import { + ConfirmationModal, + withModal2, +} from 'pubsweet-component-modal/src/components' + +import { DecisionForm } from './' + +const Decision = ({ showDecisionModal }) => ( + <Root onClick={showDecisionModal}>Make decision</Root> +) + +const ModalComponent = ({ type, ...rest }) => { + switch (type) { + case 'decision': + return <DecisionForm {...rest} /> + default: + return <ConfirmationModal {...rest} /> + } +} + +export default compose( + withModal2(() => ({ + modalComponent: ModalComponent, + })), + withHandlers({ + showDecisionModal: ({ showModal, hideModal, heRecommendation }) => () => { + showModal({ + type: 'decision', + hideModal, + heRecommendation, + }) + }, + }), +)(Decision) + +// #region styled components +const Root = styled.div` + align-items: center; + background-color: ${th('colorPrimary')}; + color: ${th('colorTextReverse')}; + cursor: pointer; + display: flex; + font-family: ${th('fontInterface')}; + font-size: ${th('fontSizeBaseSmall')}; + height: calc(${th('subGridUnit')} * 5); + justify-content: center; + padding: 0 calc(${th('subGridUnit')} * 2); + text-transform: uppercase; +` +// #endregion diff --git a/packages/components-faraday/src/components/MakeDecision/DecisionForm.js b/packages/components-faraday/src/components/MakeDecision/DecisionForm.js new file mode 100644 index 000000000..ecf851988 --- /dev/null +++ b/packages/components-faraday/src/components/MakeDecision/DecisionForm.js @@ -0,0 +1,160 @@ +import React from 'react' +import { get } from 'lodash' +import { connect } from 'react-redux' +import styled, { css } from 'styled-components' +import { reduxForm, formValueSelector } from 'redux-form' +import { compose, setDisplayName, withProps } from 'recompose' +import { th, Icon, Button, RadioGroup, ValidatedField } from '@pubsweet/ui' + +import { FormItems } from '../UIComponents' + +const { + Row, + Title, + Label, + RowItem, + Textarea, + Subtitle, + RootContainer, + FormContainer, +} = FormItems +const Form = RootContainer.withComponent(FormContainer) + +const decisionOptions = [ + { label: 'Publish', value: 'publish' }, + { label: 'Reject', value: 'reject' }, + { label: 'Return to Handling Editor', value: 'returnToHE' }, +] + +const DecisionForm = ({ + decision, + hideModal, + handleSubmit, + heRecommendation: { reason, message = '' }, +}) => ( + <Form onSubmit={handleSubmit}> + <IconButton onClick={hideModal}> + <Icon primary>x</Icon> + </IconButton> + <Title>Make decision</Title> + <CustomSubtitle> + Recommended to<BoldSubtitle>{reason}</BoldSubtitle> + </CustomSubtitle> + <Row> + <RowItem vertical> + <Label>Message from Handling Editor</Label> + <span>{message}</span> + </RowItem> + </Row> + <Row> + <RowItem vertical> + <Label>Your Decision</Label> + <ValidatedField + component={input => ( + <CustomRadioGroup> + <RadioGroup + name="decision" + options={decisionOptions} + {...input} + /> + </CustomRadioGroup> + )} + name="decision" + /> + </RowItem> + </Row> + {decision === 'returnToHE' && ( + <Row> + <RowItem vertical> + <Label>Comments for Handling Editor</Label> + <ValidatedField + component={input => <Textarea {...input} height={70} />} + name="messageToHE" + /> + </RowItem> + </Row> + )} + <Row> + <RowItem centered> + <Button onClick={hideModal}>Cancel</Button> + </RowItem> + <RowItem centered> + <Button primary type="submit"> + Submit + </Button> + </RowItem> + </Row> + </Form> +) + +const subtitleParser = t => { + switch (t) { + case 'major': + return 'Revise(major)' + case 'minor': + return 'Revise(minor)' + case 'reject': + return 'Reject' + case 'publish': + default: + return 'Publish' + } +} + +const selector = formValueSelector('eicDecision') +export default compose( + setDisplayName('DecisionForm'), + connect(state => ({ + decision: selector(state, 'decision'), + })), + withProps(({ heRecommendation: { recommendation = '', comments = [] } }) => ({ + heRecommendation: { + reason: subtitleParser(recommendation), + message: get(comments.find(c => c.public), 'content'), + }, + })), + reduxForm({ + form: 'eicDecision', + onSubmit: (values, dispatch, props) => { + // console.log('decision form', values, props) + }, + }), +)(DecisionForm) + +// #region styled-components +const defaultText = css` + color: ${th('colorText')}; + font-family: ${th('fontReading')}; + font-size: ${th('fontSizeBaseSmall')}; +` + +const IconButton = styled.div` + align-self: flex-end; + cursor: pointer; +` + +const CustomSubtitle = Subtitle.extend` + align-items: center; + display: flex; + flex-direction: row; + justify-content: center; +` + +const BoldSubtitle = Subtitle.extend` + font-weight: bold; + margin-left: 5px; +` + +const CustomRadioGroup = styled.div` + div { + flex-direction: row; + justify-content: space-between; + label { + span:last-child { + font-style: normal; + ${defaultText}; + } + } + } +` +// #endregion diff --git a/packages/components-faraday/src/components/MakeDecision/index.js b/packages/components-faraday/src/components/MakeDecision/index.js new file mode 100644 index 000000000..17309a7ef --- /dev/null +++ b/packages/components-faraday/src/components/MakeDecision/index.js @@ -0,0 +1,2 @@ +export { default as Decision } from './Decision' +export { default as DecisionForm } from './DecisionForm' diff --git a/packages/components-faraday/src/components/MakeRecommendation/RecommendWizard.js b/packages/components-faraday/src/components/MakeRecommendation/RecommendWizard.js index 28021cc18..a4e85febb 100644 --- a/packages/components-faraday/src/components/MakeRecommendation/RecommendWizard.js +++ b/packages/components-faraday/src/components/MakeRecommendation/RecommendWizard.js @@ -97,5 +97,4 @@ const IconButton = styled.div` align-self: flex-end; cursor: pointer; ` - // #endregion diff --git a/packages/components-faraday/src/components/UIComponents/FormItems.js b/packages/components-faraday/src/components/UIComponents/FormItems.js index c9b0ce220..844b841f2 100644 --- a/packages/components-faraday/src/components/UIComponents/FormItems.js +++ b/packages/components-faraday/src/components/UIComponents/FormItems.js @@ -17,14 +17,14 @@ export const Title = styled.div` font-family: ${th('fontHeading')}; font-size: ${th('fontSizeHeading5')}; font-weight: bold; - margin: 10px auto; + margin: ${th('subGridUnit')} auto; text-align: center; ` export const Subtitle = styled.div` font-family: ${th('fontReading')}; font-size: ${th('fontSizeBase')}; font-weight: normal; - margin: 10px auto; + margin: ${th('subGridUnit')} auto; text-align: center; ` @@ -32,7 +32,7 @@ export const Email = styled.div` font-family: ${th('fontReading')}; font-size: ${th('fontSizeBase')}; font-weight: normal; - margin: 10px auto; + margin: ${th('subGridUnit')} auto; text-align: center; ` -- GitLab