Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SelectReviewer.jsx 9.79 KiB
import React from 'react'
import { ApolloConsumer } from 'react-apollo'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { TextField, RadioGroup, ErrorText, H2, H3, Icon } from '@pubsweet/ui'
import { LoadingIcon } from '../ui'
import { GET_USER } from './operations'

const Joi = require('joi')

const ReviewerForm = styled.div`
  margin-bottom: calc(${th('gridUnit')} * 6);
`
const Loading = styled.div`
  padding: calc(${th('gridUnit')} * 2) 0;
  width: 100%;
  justify-content: center;
  align-items: center;
  color: ${th('colorPrimary')};
  display: inline-flex;
`
const NewReviewerForm = styled.div`
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  & > * {
    padding: 0 calc(${th('gridUnit')} * 2);
    width: calc(${th('gridUnit')} * 42);
  }
`
const Alert = styled.div`
  display: flex;
  align-items: center;
  color: ${th('colorError')};
`

class SelectReviewer extends React.Component {
  state = {
    newFormDisabled: true,
    loading: true,
    options: [],
    name: '',
    surname: '',
    email: '',
    selected: '',
    nameErr: '',
    surnameErr: '',
    emailErr: '',
  }
  componentDidMount() {
    const {
      funding,
      submitter,
      currentUser,
      selectedReviewer: note,
    } = this.props
    const selectedReviewer = note ? JSON.parse(note.content) : null
    const { name: username } = submitter.alias
    if (funding && funding.length > 0) {
      let options = [
        {
          value: 'self',
          label: `${
            submitter.user.id === currentUser.id ? 'Me' : 'Manuscript Submitter'
          } (${username.title ? `${username.title} ` : ''}${
            username.givenNames
          } ${username.surname})`,
        },
      ]
      let selected = ''
      const emails = []
      options = options.concat(
        funding.reduce((opts, grant, i) => {
          const { pi } = grant
          const { email } = pi
          if (!emails.some(e => e === email)) {
            emails.push(email)
            opts.push({
              value: `pi-${i}`,
              label: `${pi.title ? `${pi.title} ` : ''} ${pi.givenNames} ${
                pi.surname
              } (PI:${grant.awardId})`,
            })
          }
          if (selectedReviewer && selectedReviewer.email === email) {
            selected = `pi-${i}`
          }
          return opts
        }, []),
      )
      options.push({
        value: 'new',
        label: 'Other reviewer',
      })
      let newState = {}
      if (selectedReviewer && selected === '') {
        if (selectedReviewer.id && currentUser.id === selectedReviewer.id) {
          selected = 'self'
        } else {
          selected = 'new'
          newState = {
            name: selectedReviewer.name.givenNames,
            surname: selectedReviewer.name.surname,
            email: selectedReviewer.email,
            newFormDisabled: false,
          }
        }
      }
      newState.selected = selected
      newState.loading = false
      newState.options = options
      this.setState(newState)
    } else {
      this.setState({ loading: false })
    }
  }
  setNameRef = nameInput => {
    this.nameInput = nameInput
  }
  render() {
    const {
      selected,
      name,
      surname,
      email,
      newFormDisabled,
      options,
      loading,
    } = this.state
    const { selectedReviewer } = this.props
    return (
      <ApolloConsumer>
        {client => {
          const updateValues = async () => {
            const validEmail = Joi.validate(
              email,
              Joi.string()
                .email({ minDomainAtoms: 2 })
                .required(),
            )
            const validName = Joi.validate(name, Joi.string().required())
            const validSurname = Joi.validate(surname, Joi.string().required())
            if (!validEmail.error && !validName.error && !validSurname.error) {
              const reviewer = {
                name: {
                  givenNames: name,
                  surname,
                },
                email,
              }
              const { data } = await client.query({
                query: GET_USER,
                variables: { email },
              })
              if (data.userByEmail) {
                reviewer.id = data.userByEmail.id
              }
              if (selectedReviewer) {
                this.props.changeNote({
                  id: selectedReviewer.id,
                  notesType: 'selectedReviewer',
                  content: JSON.stringify(reviewer),
                })
              } else {
                this.props.newNote({
                  notesType: 'selectedReviewer',
                  content: JSON.stringify(reviewer),
                })
              }
            }
            this.setState({
              nameErr: validName.error ? 'Given name is required.' : '',
              surnameErr: validSurname.error ? 'Surname is required.' : '',
              emailErr: validEmail.error ? 'Valid email is required.' : '',
            })
          }
          const setReviewer = async value => {
            if (value === 'new') {
              this.setState({ newFormDisabled: false }, () => {
                this.nameInput.querySelector('input').focus()
              })
            } else {
              let reviewer = {}
              this.setState({ newFormDisabled: true })
              if (value === 'self') {
                reviewer = {
                  id: this.props.currentUser.id,
                }
              } else {
                const index = value.substring(3)
                const { pi } = this.props.funding[index]
                reviewer = {
                  name: {
                    title: pi.title,
                    givenNames: pi.givenNames,
                    surname: pi.surname,
                  },
                  email: pi.email,
                }
                const { data } = await client.query({
                  query: GET_USER,
                  variables: { email: pi.email },
                })
                if (data.userByEmail) {
                  reviewer.id = data.userByEmail.id
                }
              }
              if (selectedReviewer) {
                this.props.changeNote({
                  id: selectedReviewer.id,
                  notesType: 'selectedReviewer',
                  content: JSON.stringify(reviewer),
                })
              } else {
                this.props.newNote({
                  notesType: 'selectedReviewer',
                  content: JSON.stringify(reviewer),
                })
              }
            }
          }
          return (
            <div>
              <H2>Reviewer</H2>
              <H3>Please designate a reviewer for the submission</H3>
              <p>
                {`The reviewer will be responsible for approving the web version of this manuscript. The reviewer must be an author of the manuscript.`}
              </p>
              {loading && (
                <Loading>
                  <LoadingIcon />
                </Loading>
              )}
              {options.length > 0 ? (
                <ReviewerForm>
                  <RadioGroup
                    name="reviewerGroup"
                    onChange={setReviewer}
                    options={options}
                    value={selected}
                  />
                  {!newFormDisabled && (
                    <NewReviewerForm>
                      <div ref={this.setNameRef}>
                        <TextField
                          disabled={newFormDisabled}
                          invalidTest={this.state.nameErr}
                          label="Given name(s)"
                          name="name"
                          onBlur={updateValues}
                          onChange={e =>
                            this.setState({ name: e.target.value })
                          }
                          value={name}
                        />
                        {this.state.nameErr && (
                          <ErrorText>{this.state.nameErr}</ErrorText>
                        )}
                      </div>
                      <div>
                        <TextField
                          disabled={newFormDisabled}
                          invalidTest={this.state.nameErr}
                          label="Surname"
                          name="surname"
                          onBlur={updateValues}
                          onChange={e =>
                            this.setState({ surname: e.target.value })
                          }
                          value={surname}
                        />
                        {this.state.surnameErr && (
                          <ErrorText>{this.state.surnameErr}</ErrorText>
                        )}
                      </div>
                      <div>
                        <TextField
                          disabled={newFormDisabled}
                          invalidTest={this.state.emailErr}
                          label="Email address"
                          name="email"
                          onBlur={updateValues}
                          onChange={e =>
                            this.setState({ email: e.target.value })
                          }
                          value={email}
                        />
                        {this.state.emailErr && (
                          <ErrorText>{this.state.emailErr}</ErrorText>
                        )}
                      </div>
                    </NewReviewerForm>
                  )}
                </ReviewerForm>
              ) : (
                <Alert>
                  <Icon color="currentColor">alert_circle</Icon>
                  {`Error: Grants must be entered before a reviewer can be selected.`}
                </Alert>
              )}
            </div>
          )
        }}
      </ApolloConsumer>
    )
  }
}

export default SelectReviewer