Skip to content
Snippets Groups Projects
SubmissionError.jsx 4.9 KiB
Newer Older
ahamelers's avatar
ahamelers committed
import React from 'react'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { Action, H2, CheckboxGroup } from '@pubsweet/ui'
import { Portal, CloseModal, Loading, LoadingIcon, Toggle } from '../ui'
ahamelers's avatar
ahamelers committed
import SubmissionErrorReport, {
  adminOptions,
  Fieldset,
} from '../SubmissionErrorReport'
Audrey Hamelers's avatar
Audrey Hamelers committed
import TaggerError from './TaggerError'
ahamelers's avatar
ahamelers committed

export const Option = styled.div`
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-between;
  min-height: calc(${th('gridUnit')} * 6);
  padding: ${th('gridUnit')} calc(${th('gridUnit')} * 3);
  & > * {
    margin: ${th('gridUnit')} auto;
  }
  @media screen and (max-width: 870px) {
    padding: ${th('gridUnit')} calc(${th('gridUnit')} * 4);
  }
`
const CheckList = styled(Fieldset)`
  div {
    flex-direction: row;
    flex-wrap: wrap;
    label {
      width: 50%;
    }
  }
`
const options = adminOptions
  .filter(o => !['title', 'english', 'grants'].includes(o.value))
ahamelers's avatar
ahamelers committed
  .reverse()

Audrey Hamelers's avatar
Audrey Hamelers committed
const submissionMessage = async (url, annotations) => {
  if (url && annotations) {
    const response = await fetch(url)
    const html = await response.text()
    const outer = document.createElement('div')
    const test = document.createElement('div')
    test.innerHTML = html
    outer.appendChild(test)
    const locate = annotations.map(a => {
      const loc = a.ranges[0].start
ahamelers's avatar
ahamelers committed
      const result = document.evaluate(
        loc,
        outer,
        null,
        XPathResult.FIRST_ORDERED_NODE_TYPE,
      )
Audrey Hamelers's avatar
Audrey Hamelers committed
      return {
ahamelers's avatar
ahamelers committed
        id: a.id,
Audrey Hamelers's avatar
Audrey Hamelers committed
        location: result.singleNodeValue
          ? `#${result.singleNodeValue.id}`
          : '[PDF?]',
Audrey Hamelers's avatar
Audrey Hamelers committed
        quote: a.quote,
        text: a.text,
      }
    })
    return locate
  }
}

ahamelers's avatar
ahamelers committed
class SubmissionError extends React.Component {
Audrey Hamelers's avatar
Audrey Hamelers committed
  state = {
    error: 'submission',
Audrey Hamelers's avatar
Audrey Hamelers committed
    checkedBoxes: [],
ahamelers's avatar
ahamelers committed
    formData: null,
Audrey Hamelers's avatar
Audrey Hamelers committed
  }
  componentDidUpdate(prevProps, prevState) {
ahamelers's avatar
ahamelers committed
    if (
      this.state.error !== prevState.error &&
      this.state.error === 'tagging'
    ) {
Audrey Hamelers's avatar
Audrey Hamelers committed
      this.withLocations()
    }
  }
  async withLocations() {
    const { annotations, manuscript } = this.props
    const html = manuscript.files.find(file => file.type === 'tempHTML')
    const locate = await submissionMessage(html && html.url, annotations)
    this.setState({ formData: locate })
  }
ahamelers's avatar
ahamelers committed
  render() {
Audrey Hamelers's avatar
Audrey Hamelers committed
    const { error, checkedBoxes, formData } = this.state
    const { annotations, manuscript, close } = this.props
Audrey Hamelers's avatar
Audrey Hamelers committed
    const html = manuscript.files.find(file => file.type === 'tempHTML')
ahamelers's avatar
ahamelers committed
    return (
      <Portal transparent>
        <CloseModal onClick={close} />
        <H2>Report Errors</H2>
        <Toggle>
          <Action
            className={error === 'submission' && 'current'}
            onClick={() => this.setState({ error: 'submission' })}
          >
ahamelers's avatar
ahamelers committed
            Return for user upload
          </Action>
          <Action
            className={error === 'tagging' && 'current'}
            onClick={() => this.setState({ error: 'tagging' })}
          >
            Return for tagging correction
          </Action>
        </Toggle>
        {(() => {
          switch (error) {
            case 'submission':
              return (
                <React.Fragment>
                  <p>
                    {`The submission will be routed back for triage when the requested changes are made.`}
                  </p>
                  <CheckList>
                    <label>Missing items</label>
                    <CheckboxGroup
                      onChange={c => this.setState({ checkedBoxes: c })}
                      options={options}
                      value={checkedBoxes}
                    />
                  </CheckList>
                  <SubmissionErrorReport
                    checkedBoxes={checkedBoxes}
                    close={close}
                    manuscript={manuscript}
                    teams={manuscript.teams}
                  />
                </React.Fragment>
              )
            case 'tagging':
              if (html && annotations) {
                return (
                  <React.Fragment>
                    {!formData ? (
                      <Loading>
                        <LoadingIcon />
                      </Loading>
                    ) : (
                        close={close}
                        formData={formData}
                    )}
                  </React.Fragment>
                )
              return (
                <React.Fragment>
                  <p>No errors reported.</p>
                  <TaggerError
                    close={close}
                    formData={[]}
                    manuscript={manuscript}
                  />
                </React.Fragment>
              )
            default:
              return null
          }
        })()}
      </Portal>
ahamelers's avatar
ahamelers committed
    )
  }
}

export default SubmissionError