Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
HERecommendation.js 6.10 KiB
import React from 'react'
import PropTypes from 'prop-types'
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 showHEOptions = ({
  canHEMakeRecommendationToPublish,
  canHEOnlyReject,
}) => {
  if (canHEOnlyReject) {
    return [options[1]]
  } else if (!canHEMakeRecommendationToPublish) {
    return tail(options)
  }
  return options
}

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 = ({
  canHEMakeRecommendationToPublish,
  canHEOnlyReject,
  handleSubmit,
  formValues,
  highlight,
  ...rest
}) => (
  <ContextualBox
    expanded
    highlight={highlight}
    label="Your Editorial Recommendation"
    mb={2}
    {...rest}
  >
    <Root>
      <Row justify="flex-start">
        <ItemOverrideAlert
          data-test-id="editorial-recommendation-choose-options"
          flex={0}
          vertical
        >
          <Label required>Recommendation</Label>
          <ValidatedField
            component={input => (
              <Menu
                options={showHEOptions({
                  canHEMakeRecommendationToPublish,
                  canHEOnlyReject,
                })}
                {...input}
              />
            )}
            name="recommendation"
            validate={[required]}
          />
        </ItemOverrideAlert>
      </Row>
      {get(formValues, 'recommendation') === 'minor' ||
      get(formValues, 'recommendation') === 'major' ? (
        <Row mt={2}>
          <ResponsiveItem
            data-test-id="editorial-recommendation-message-for-author"
            mr={1}
            vertical
          >
            <Label>
              Message for Author <Text secondary>Optional</Text>
            </Label>
            <ValidatedField component={Textarea} name="public" />
          </ResponsiveItem>
        </Row>
      ) : (
        <ResponsiveRow mt={2}>
          <ResponsiveItem
            data-test-id="editorial-recommendation-message-for-author"
            mr={1}
            vertical
          >
            <Label>
              Message for Author <Text secondary>Optional</Text>
            </Label>
            <ValidatedField component={Textarea} name="public" />
          </ResponsiveItem>
          <ResponsiveItem
            data-test-id="editorial-recommendation-message-for-eic"
            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
          data-test-id="button-editorial-recommendation-submit"
          onClick={handleSubmit}
          primary
          size="medium"
        >
          {
            options.find(
              o => o.value === get(formValues, 'recommendation', 'publish'),
            ).button
          }
        </Button>
      </Row>
    </Root>
  </ContextualBox>
)

HERecommendation.propTypes = {
  /* Contains the values of the form inputs */
  formValues: PropTypes.object, //eslint-disable-line
  /* Handles the submission of the recommendation */
  handleSubmit: PropTypes.func,
  /* Specifies if the fragment has reviewer reports */
  hasReviewerReports: PropTypes.bool,
  /* Specifies if the contextual box should be highlighted */
  highlight: PropTypes.bool,
}

HERecommendation.defaultProps = {
  formValues: {},
  handleSubmit: () => {},
  hasReviewerReports: false,
  highlight: false,
}

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