Skip to content
Snippets Groups Projects
SubmissionWizard.js 6.68 KiB
Newer Older
import React, { Fragment } from 'react'
Alexandru Munteanu's avatar
Alexandru Munteanu committed
import { connect } from 'react-redux'
import { th } from '@pubsweet/ui-toolkit'
import { actions } from 'pubsweet-client'
import { withJournal } from 'xpub-journal'
import { ConnectPage } from 'xpub-connect'
import { DragDropContext } from 'react-dnd'
import styled, { css } from 'styled-components'
Alexandru Munteanu's avatar
Alexandru Munteanu committed
import HTML5Backend from 'react-dnd-html5-backend'
import { Button, Spinner, Steps } from '@pubsweet/ui'
Alexandru Munteanu's avatar
Alexandru Munteanu committed
import { selectCollection, selectFragment } from 'xpub-selectors'
import {
  compose,
  toClass,
  withProps,
  withHandlers,
  withStateHandlers,
import { Row, MultiAction, IconButton } from 'pubsweet-component-faraday-ui'
import { withModal } from 'pubsweet-component-modal/src/components'
import { getUserToken } from 'pubsweet-component-faraday-selectors/src'
Alexandru Munteanu's avatar
Alexandru Munteanu committed
import {
  reduxForm,
  getFormValues,
  hasSubmitFailed,
  getFormSyncErrors,
  change as changeForm,
} from 'redux-form'
  getAuthorFetching,
} from 'pubsweet-components-faraday/src/redux/authors'
import {
  uploadFile,
  deleteFile,
  getSignedUrl,
} from 'pubsweet-components-faraday/src/redux/files'
Alexandru Munteanu's avatar
Alexandru Munteanu committed

import { wizardSteps } from './'
import { submitManuscript } from '../redux/conversion'
import { getAutosaveFetching } from '../redux/autosave'
import { onChange, onSubmit, setInitialValues, validate } from './utils'
Alexandru Munteanu's avatar
Alexandru Munteanu committed

Alexandru Munteanu's avatar
Alexandru Munteanu committed
  step,
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  prevStep,
  isLastStep,
  isFirstStep,
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  handleSubmit,
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  journal: { manuscriptTypes = [] },
    <Root className="wizard-root">
      <Steps currentStep={step}>
        {wizardSteps.map(({ stepTitle }) => (
          <Steps.Step key={stepTitle} title={stepTitle} />
        ))}
      </Steps>
Alexandru Munteanu's avatar
Alexandru Munteanu committed

      <StepRoot className="wizard-step" step={step}>
        {React.createElement(wizardSteps[step].component, {
          manuscriptTypes,
          journal,
          isAuthorsFetching,
          ...rest,
        })}
        <Row justify="center" mt={2}>
          {(isAuthorsFetching || isFilesFetching) && isLastStep ? (
            <Spinner />
          ) : (
            <Fragment>
              <Button
                data-test-id="submission-back"
                mr={1}
                onClick={isFirstStep ? history.goBack : prevStep}
              >
                <IconButton
                  fontIcon="arrowLeft"
                  mb={0.1}
                  paddingBottom={1.2}
                  paddingRight={0.9}
                />
                Back
              </Button>
              <Button
                data-test-id="submission-next"
                ml={isFirstStep ? 0 : 1}
                onClick={handleSubmit}
                primary
              >
                {getButtonText()}
                <IconButton
                  fontIcon="arrowRight"
                  mb={0.1}
                  paddingBottom={0.5}
                />
              </Button>
            </Fragment>
          )}
        </Row>
      </StepRoot>
    </Root>
  ) : (
    <Redirect to="/404" />
  )
Alexandru Munteanu's avatar
Alexandru Munteanu committed

// #region export
export default compose(
  ConnectPage(({ match }) => [
    actions.getCollection({ id: match.params.project }),
    actions.getFragment(
      { id: match.params.project },
      { id: match.params.version },
    ),
  ]),
  withJournal,
      token: getUserToken(state),
      isFetching: getAutosaveFetching(state),
      isFilesFetching: getFileFetching(state),
      reduxAuthorError: getAuthorError(state),
      formValues: getFormValues('submission')(state),
      submitFailed: hasSubmitFailed('submission')(state),
      formSyncErrors: getFormSyncErrors('submission')(state),
      fragment: selectFragment(state, get(match, 'params.version')),
      collection: selectCollection(state, get(match, 'params.project')),
      isAuthorsFetching: getAuthorFetching(state) || getAutosaveFetching(state),
      submitManuscript,
      updateFragment: actions.updateFragment,
    },
  ),
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  withStateHandlers(
    { step: 0, authorEditIndex: null },
Alexandru Munteanu's avatar
Alexandru Munteanu committed
    {
      nextStep: ({ step }) => () => ({
        step: Math.min(wizardSteps.length - 1, step + 1),
      }),
      prevStep: ({ step }) => () => ({ step: Math.max(0, step - 1) }),
      setAuthorEditIndex: () => index => ({
        authorEditIndex: index,
      }),
Alexandru Munteanu's avatar
Alexandru Munteanu committed
    },
  ),
  withProps(setInitialValues),
      submitFailed,
      formSyncErrors,
      isAuthorEdit: !isNull(authorEditIndex),
      isLastStep: step === wizardSteps.length - 1,
      isEditMode: get(location, 'state.editMode', false),
      filesError: submitFailed && get(formSyncErrors, 'files', ''),
      authorsError:
        (submitFailed && get(formSyncErrors, 'authors', '')) ||
        reduxAuthorError,
      isLastFragment:
        get(fragment, 'id', '') === last(get(collection, 'fragments', [])),
  withProps(({ status, isLastFragment }) => ({
    canEdit:
      isLastFragment && !(status === 'accepted' || status === 'rejected'),
  })),
  withHandlers({
    getButtonText: ({ isLastStep, isEditMode }) => () => {
      if (isEditMode && isLastStep) {
        return 'SAVE CHANGES'
      }
      return isLastStep ? `SUBMIT MANUSCRIPT` : `NEXT STEP`
  withModal(({ isFetching }) => ({
    isFetching,
    modalComponent: MultiAction,
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  reduxForm({
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  }),
  DragDropContext(HTML5Backend),
  toClass,
Alexandru Munteanu's avatar
Alexandru Munteanu committed
// #endregion

// #region styled-components
  align-items: center;
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  display: flex;
  flex-direction: column;
  padding-bottom: calc(${th('gridUnit')} * 3);
  margin: 0 auto;
const stepCSS = ({ step = 0 }) =>
  step === 1
    ? css`
        min-width: calc(${th('gridUnit')} * 96);
      `
    : css`
        width: calc(${th('gridUnit')} * 96);
      `

const StepRoot = styled.div`
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  align-items: center;
  background-color: ${th('wizard.colorBackground')};
  border-radius: ${th('borderRadius')};
  box-shadow: ${th('boxShadow')};
Alexandru Munteanu's avatar
Alexandru Munteanu committed
  display: flex;
  flex-direction: column;
  margin: ${th('gridUnit')} auto 0;
  padding: calc(${th('gridUnit')} * 5) calc(${th('gridUnit')} * 4);
  position: relative;
Alexandru Munteanu's avatar
Alexandru Munteanu committed
`
// #endregion