Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SubmissionError.jsx 4.97 KiB
import React from 'react'
import styled from 'styled-components'
import { th } from '@pubsweet/ui-toolkit'
import { Action, H2, CheckboxGroup } from '@pubsweet/ui'
import { Portal, Close, CloseButton, Loading, LoadingIcon, Toggle } from '../ui'
import SubmissionErrorReport, {
  adminOptions,
  Fieldset,
} from '../SubmissionErrorReport'
import TaggerError from './TaggerError'

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))
  .reverse()

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
      const result = document.evaluate(
        loc,
        outer,
        null,
        XPathResult.FIRST_ORDERED_NODE_TYPE,
      )
      return {
        id: a.id,
        location: result.singleNodeValue
          ? `#${result.singleNodeValue.id}`
          : '[PDF?]',
        quote: a.quote,
        text: a.text,
      }
    })
    return locate
  }
}

class SubmissionError extends React.Component {
  state = {
    error: 'submission',
    checkedBoxes: [],
    formData: null,
  }
  componentDidUpdate(prevProps, prevState) {
    if (
      this.state.error !== prevState.error &&
      this.state.error === 'tagging'
    ) {
      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 })
  }
  render() {
    const { error, checkedBoxes, formData } = this.state
    const { annotations, manuscript, close } = this.props
    const html = manuscript.files.find(file => file.type === 'tempHTML')
    return (
      <Portal transparent>
        <Close style={{ margin: 0 }}>
          <CloseButton onClick={close} />
        </Close>
        <H2>Report Errors</H2>
        <Toggle>
          <Action
            className={error === 'submission' && 'current'}
            onClick={() => this.setState({ error: 'submission' })}
          >
            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>
                    ) : (
                      <TaggerError
                        close={close}
                        formData={formData}
                        manuscript={manuscript}
                      />
                    )}
                  </React.Fragment>
                )
              }
              return (
                <React.Fragment>
                  <p>No errors reported.</p>
                  <TaggerError
                    close={close}
                    formData={[]}
                    manuscript={manuscript}
                  />
                </React.Fragment>
              )
            default:
              return null
          }
        })()}
      </Portal>
    )
  }
}

export default SubmissionError