From 75ba64019560021921fa3f03a957f550a557fc0a Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munt@gmail.com>
Date: Thu, 19 Jul 2018 14:07:12 +0300
Subject: [PATCH] new wizard

---
 .../src/components/NewStepOne.js              |   8 +
 .../src/components/NewWizard.js               | 306 ++++++++++++++++++
 .../component-wizard/src/components/index.js  |   3 +
 .../src/components/AuthorList/AuthorList.js   |   3 -
 .../src/components/Dashboard/DashboardCard.js |   4 +-
 .../src/components/UIComponents/FormItems.js  |  39 ++-
 .../src/components/index.js                   |   1 +
 packages/xpub-faraday/app/routes.js           |   7 +-
 8 files changed, 363 insertions(+), 8 deletions(-)
 create mode 100644 packages/component-wizard/src/components/NewStepOne.js
 create mode 100644 packages/component-wizard/src/components/NewWizard.js

diff --git a/packages/component-wizard/src/components/NewStepOne.js b/packages/component-wizard/src/components/NewStepOne.js
new file mode 100644
index 000000000..26cf57dfb
--- /dev/null
+++ b/packages/component-wizard/src/components/NewStepOne.js
@@ -0,0 +1,8 @@
+import React, { Fragment } from 'react'
+
+const NewStepOne = () => <Fragment>new step one here</Fragment>
+
+export default NewStepOne
+
+// #region styled-components
+// #endregion
diff --git a/packages/component-wizard/src/components/NewWizard.js b/packages/component-wizard/src/components/NewWizard.js
new file mode 100644
index 000000000..eef588df0
--- /dev/null
+++ b/packages/component-wizard/src/components/NewWizard.js
@@ -0,0 +1,306 @@
+import React, { Fragment } from 'react'
+import { connect } from 'react-redux'
+import { reduxForm } from 'redux-form'
+import { th } from '@pubsweet/ui-toolkit'
+import { actions } from 'pubsweet-client'
+import { withJournal } from 'xpub-journal'
+import { ConnectPage } from 'xpub-connect'
+import { required } from 'xpub-validators'
+import { DragDropContext } from 'react-dnd'
+import { get, debounce, omit } from 'lodash'
+import styled, { css } from 'styled-components'
+import HTML5Backend from 'react-dnd-html5-backend'
+import { selectCollection, selectFragment } from 'xpub-selectors'
+import { Icon, Checkbox, ValidatedField, Menu, Button } from '@pubsweet/ui'
+import { withStateHandlers, compose, toClass, withProps } from 'recompose'
+import {
+  Steps,
+  FormItems,
+  AuthorList,
+} from 'pubsweet-components-faraday/src/components'
+
+import { autosaveRequest } from '../redux/autosave'
+
+const {
+  Row,
+  Label,
+  Title,
+  RowItem,
+  Subtitle,
+  TextField,
+  TextAreaField,
+} = FormItems
+
+// #region StepOne
+const NewStepOne = () => (
+  <Fragment>
+    <Title>1. Pre-Submission Checklist</Title>
+    <Subtitle>
+      Before moving forward make sure you have all the required files prepared
+      and the items on the list below reviewed.
+    </Subtitle>
+    <Row justify="flex-start">
+      <Text>
+        I have the email addresses of all the co-authors of the manuscript.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I have the manuscript file in Microsoft Word or Adobe PDF format with
+        the tables and figures integrated in the manuscript body.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I have the electronic files of any supplementary materials (e.g.,
+        datasest, images, audio, video) that I want to submit with the
+        manuscript.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I am aware that accepted manuscripts are subject to{' '}
+        <a
+          href="https://www.google.com"
+          rel="noopener noreferrer"
+          target="_blank"
+        >
+          Article Processing Charges
+        </a>.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I am aware that an ORCID ID is required for the corresponding author
+        before the article can be published (if accepted). The ORCID ID should
+        be added via your user account.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I am aware that if my submission is covered by an institutional
+        membership, Hindawi will share details of the manuscript with the
+        administrator of the membership.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <Text>
+        I am aware of the Hindawi article processing charges tax of $1000.
+      </Text>
+    </Row>
+    <Row justify="flex-start">
+      <ValidatedField
+        component={input => (
+          <Checkbox
+            checked={input.value}
+            {...input}
+            label={`I've reviewed and understood all the above items.`}
+          />
+        )}
+        name="agree"
+        validate={[required]}
+      />
+    </Row>
+  </Fragment>
+)
+// #endregion
+
+// #region StepTwo
+const NewStepTwo = ({ version, project, manuscriptTypes }) => (
+  <Fragment>
+    <Title>2. Manuscript & Authors Details</Title>
+    <Subtitle>
+      Please provide the details of all the authors of this manuscript, in the
+      order that they appear on the manuscript. Your details are already
+      prefiled since, in order to submit a manuscript you must be one of the
+      authors.
+    </Subtitle>
+    <Row className="row">
+      <RowItem flex={3} vertical withRightMargin>
+        <Label>MANUSCRIPT TITLE*</Label>
+        <ValidatedField
+          component={input => <TextField {...input} />}
+          name="metadata.title"
+          validate={[required]}
+        />
+      </RowItem>
+      <RowItem vertical>
+        <Label>MANUSCRIPT TYPE*</Label>
+        <ValidatedField
+          component={input => <Menu options={manuscriptTypes} {...input} />}
+          name="metadata.type"
+          validate={[required]}
+        />
+      </RowItem>
+    </Row>
+    <Row className="row">
+      <RowItem vertical>
+        <Label>ABSTRACT*</Label>
+        <ValidatedField
+          component={TextAreaField}
+          name="metadata.abstract"
+          validate={[required]}
+        />
+      </RowItem>
+    </Row>
+    <Row className="row">
+      <RowItem vertical>
+        <Label>AUTHORS DETAILS*</Label>
+        <AuthorList
+          parentForm="submission"
+          project={project}
+          version={version}
+        />
+      </RowItem>
+    </Row>
+  </Fragment>
+)
+// #endregion
+
+const NewWizard = ({
+  step,
+  version,
+  project,
+  nextStep,
+  prevStep,
+  handleSubmit,
+  journal: { manuscriptTypes = [] },
+}) => (
+  <Fragment>
+    <Steps currentStep={step} margin="0 20px 60px 0">
+      <Steps.Step key="step-one" title="Pre-submission Checklist" />
+      <Steps.Step key="step-two" title="Manuscript & Author Details" />
+      <Steps.Step key="step-three" title="Files Upload" />
+    </Steps>
+
+    <StepRoot className="wizard-root">
+      <IconButton>
+        <Icon primary size={4}>
+          x
+        </Icon>
+      </IconButton>
+      {step === 0 && <NewStepOne />}
+      {step === 1 && (
+        <NewStepTwo
+          manuscriptTypes={manuscriptTypes}
+          project={project}
+          version={version}
+        />
+      )}
+      <Row centered>
+        <ButtonContainer>
+          <Button onClick={prevStep}>{`< BACK`}</Button>
+          <Button onClick={handleSubmit} primary>
+            {`NEXT STEP >`}
+          </Button>
+        </ButtonContainer>
+      </Row>
+    </StepRoot>
+  </Fragment>
+)
+
+const onChange = (values, dispatch, { project, version }) => {
+  const newValues = omit(values, ['agree', 'authorForm'])
+  dispatch(autosaveRequest())
+  dispatch(
+    actions.updateFragment(project, {
+      ...version,
+      ...newValues,
+    }),
+  )
+}
+
+// #region export
+export default compose(
+  ConnectPage(({ match }) => [
+    actions.getCollection({ id: match.params.project }),
+    actions.getFragment(
+      { id: match.params.project },
+      { id: match.params.version },
+    ),
+  ]),
+  withJournal,
+  connect((state, { match }) => ({
+    version: selectFragment(state, get(match, 'params.version')),
+    project: selectCollection(state, get(match, 'params.project')),
+  })),
+  withStateHandlers(
+    { step: 1 },
+    {
+      nextStep: ({ step }) => () => ({ step: step + 1 }),
+      prevStep: ({ step }) => () => ({ step: step - 1 }),
+    },
+  ),
+  withProps(({ version }) => ({
+    initialValues: {
+      metadata: get(version, 'metadata', {}),
+    },
+  })),
+  reduxForm({
+    form: 'submission',
+    onChange: debounce(onChange, 1000, { maxWait: 5000 }),
+    onSubmit: (values, dispatch, { step, nextStep }) => {
+      if (step < 2) {
+        nextStep()
+      }
+    },
+  }),
+  DragDropContext(HTML5Backend),
+  toClass,
+)(NewWizard)
+// #endregion
+
+// #region styled-components
+const defaultText = css`
+  color: ${th('colorPrimary')};
+  font-size: ${th('fontSizeBase')};
+  font-family: ${th('fontReading')};
+`
+const Text = styled.span`
+  ${defaultText};
+`
+
+const StepRoot = styled.div`
+  align-items: flex-start;
+  background-color: ${th('colorBackground')};
+  border: ${th('borderDefault')};
+  display: flex;
+  flex-direction: column;
+  padding: 30px;
+  position: relative;
+`
+
+const IconButton = styled.button`
+  align-items: center;
+  background-color: ${th('colorBackground')};
+  border: none;
+  color: ${th('colorPrimary')};
+  cursor: ${({ hide }) => (hide ? 'auto' : 'pointer')};
+  display: flex;
+  font-family: ${th('fontInterface')};
+  font-size: ${th('fontSizeBaseSmall')};
+  opacity: ${({ hide }) => (hide ? 0 : 1)};
+  text-align: left;
+
+  position: absolute;
+  top: 10px;
+  right: 10px;
+
+  &:active,
+  &:focus {
+    outline: none;
+  }
+  &:hover {
+    opacity: 0.7;
+  }
+`
+
+const ButtonContainer = styled.div`
+  align-items: center;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+
+  width: calc(${th('gridUnit')} * 14);
+`
+// #endregion
diff --git a/packages/component-wizard/src/components/index.js b/packages/component-wizard/src/components/index.js
index b24d781c5..ac086570d 100644
--- a/packages/component-wizard/src/components/index.js
+++ b/packages/component-wizard/src/components/index.js
@@ -1 +1,4 @@
 export { default as Wizard } from './WizardPage'
+export { default as NewWizard } from './NewWizard'
+
+export { default as NewStepOne } from './NewStepOne'
diff --git a/packages/components-faraday/src/components/AuthorList/AuthorList.js b/packages/components-faraday/src/components/AuthorList/AuthorList.js
index 2f070954f..84af49a62 100644
--- a/packages/components-faraday/src/components/AuthorList/AuthorList.js
+++ b/packages/components-faraday/src/components/AuthorList/AuthorList.js
@@ -1,7 +1,6 @@
 import React from 'react'
 import { get, isBoolean, isNumber } from 'lodash'
 import { th } from '@pubsweet/ui'
-import PropTypes from 'prop-types'
 import { connect } from 'react-redux'
 import styled from 'styled-components'
 import { withRouter } from 'react-router-dom'
@@ -10,7 +9,6 @@ import {
   compose,
   withState,
   withProps,
-  getContext,
   withHandlers,
   setDisplayName,
 } from 'recompose'
@@ -82,7 +80,6 @@ const Authors = ({
 
 export default compose(
   withRouter,
-  getContext({ version: PropTypes.object, project: PropTypes.object }),
   connect(
     (state, { project, parentForm = 'wizard' }) => ({
       error: getAuthorError(state),
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
index b3e877877..8b91784b6 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
@@ -92,7 +92,9 @@ const DashboardCard = ({
                   data-test="button-resume-submission"
                   onClick={() =>
                     history.push(
-                      `/projects/${project.id}/versions/${version.id}/submit`,
+                      `/new-wizard/projects/${project.id}/versions/${
+                        version.id
+                      }/submit`,
                     )
                   }
                 >
diff --git a/packages/components-faraday/src/components/UIComponents/FormItems.js b/packages/components-faraday/src/components/UIComponents/FormItems.js
index 5f9a14cd9..da5e726be 100644
--- a/packages/components-faraday/src/components/UIComponents/FormItems.js
+++ b/packages/components-faraday/src/components/UIComponents/FormItems.js
@@ -2,6 +2,13 @@ import React from 'react'
 import { th } from '@pubsweet/ui'
 import styled, { css } from 'styled-components'
 
+const borderColor = ({ theme, validationStatus = 'default' }) =>
+  ({
+    error: theme.colorError,
+    success: theme.colorSuccess,
+    default: theme.colorBorder,
+  }[validationStatus])
+
 const defaultText = css`
   color: ${th('colorText')};
   font-family: ${th('fontReading')};
@@ -65,6 +72,7 @@ export const Row = styled.div`
   justify-content: ${({ justify }) => justify || 'space-evenly'};
   margin: ${({ noMargin }) =>
     noMargin ? 0 : css`calc(${th('subGridUnit')} * 2) 0`};
+  width: 100%;
 
   label + div[role='alert'] {
     margin-top: 0;
@@ -82,6 +90,10 @@ export const RowItem = styled.div`
   & > div {
     flex: 1;
   }
+
+  div[role='alert'] {
+    margin-top: 0;
+  }
 `
 
 export const Label = styled.div`
@@ -115,7 +127,7 @@ export const Textarea = styled.textarea`
   outline: none;
   transition: all 300ms linear;
 
-  width: ${({ width }) => `${width || 500}px`};
+  width: ${({ width }) => `${width || '500px'}`};
   height: ${({ height }) => `${height || 150}px`};
 
   &:active,
@@ -149,13 +161,34 @@ export const PrivatePolicy = styled.div`
   text-align: justify;
 `
 
-export const TextAreaField = input => <Textarea {...input} height={70} />
+export const TextAreaField = input => (
+  <Textarea {...input} height={70} width="100%" />
+)
 
 export const LabelHeader = styled.div`
   color: ${th('colorPrimary')};
   font-family: ${th('fontHeading')};
   font-size: ${th('fontSizeBaseSmall')};
   margin: ${th('subGridUnit')} 0;
-  text-transform: uppercase;
   font-weight: bold;
+  text-transform: uppercase;
+`
+
+export const TextField = styled.input`
+  border: ${th('borderWidth')} ${th('borderStyle')} ${borderColor};
+
+  border-radius: ${th('borderRadius')};
+
+  font-family: inherit;
+  font-size: inherit;
+
+  height: calc(${th('gridUnit')} * 2);
+  padding: 0 calc(${th('gridUnit')} / 2);
+  width: 100%;
+
+  &::placeholder {
+    color: ${th('colorTextPlaceholder')};
+  }
+
+  ${th('cssOverrides.TextField.Input')};
 `
diff --git a/packages/components-faraday/src/components/index.js b/packages/components-faraday/src/components/index.js
index ddc29a62c..bc0fbc83d 100644
--- a/packages/components-faraday/src/components/index.js
+++ b/packages/components-faraday/src/components/index.js
@@ -2,6 +2,7 @@ import { Decision } from './MakeDecision'
 import * as Components from './UIComponents'
 import { Recommendation } from './MakeRecommendation'
 
+export { FormItems } from './UIComponents'
 export { default as Steps } from './Steps/Steps'
 export { default as Files } from './Files/Files'
 export { default as AppBar } from './AppBar/AppBar'
diff --git a/packages/xpub-faraday/app/routes.js b/packages/xpub-faraday/app/routes.js
index e06874ce6..b6d663162 100644
--- a/packages/xpub-faraday/app/routes.js
+++ b/packages/xpub-faraday/app/routes.js
@@ -2,7 +2,7 @@ import React from 'react'
 import { Route, Switch } from 'react-router-dom'
 import { AuthenticatedComponent } from 'pubsweet-client'
 
-import { Wizard } from 'pubsweet-component-wizard/src/components'
+import { Wizard, NewWizard } from 'pubsweet-component-wizard/src/components'
 import {
   UserProfilePage,
   ChangePasswordPage,
@@ -121,6 +121,11 @@ const Routes = () => (
 
       <Route component={ErrorPage} exact path="/error-page" />
       <Route component={InfoPage} exact path="/info-page" />
+      <PrivateRoute
+        component={NewWizard}
+        exact
+        path="/new-wizard/projects/:project/versions/:version/submit"
+      />
       <Route component={NotFound} />
     </Switch>
   </FaradayApp>
-- 
GitLab