diff --git a/packages/component-wizard/src/components/AuthorList.js b/packages/component-wizard/src/components/AuthorList.js new file mode 100644 index 0000000000000000000000000000000000000000..264be41596c24dddeb887612ec8b00031aef45cd --- /dev/null +++ b/packages/component-wizard/src/components/AuthorList.js @@ -0,0 +1,165 @@ +import React from 'react' +import { get } from 'lodash' +import classnames from 'classnames' +import { TextField, Menu } from '@pubsweet/ui' +import { compose, withState, withHandlers } from 'recompose' + +import classes from './AuthorList.local.scss' +import SortableList from './SortableList' + +const countries = [ + { label: 'Romania', value: 'ro' }, + { label: 'United Kingdom', value: 'uk' }, + { label: 'Germany', value: 'de' }, + { label: 'France', value: 'fr' }, +] + +const AuthorAdder = ({ + author: { firstName, middleName, lastName, email, affiliation, country }, + editAuthor, + addAuthor, +}) => ( + <div className={classnames(classes.adder)}> + <button onClick={addAuthor}>Add author</button> + <span className={classnames(classes.title)}>Author</span> + <div className={classnames(classes.row)}> + <TextField + label="First name" + onChange={editAuthor('firstName')} + value={firstName} + /> + <TextField + label="Midle name" + onChange={editAuthor('middleName')} + value={middleName} + /> + <TextField + label="Last name" + onChange={editAuthor('lastName')} + value={lastName} + /> + </div> + <div className={classnames(classes.row)}> + <TextField + label="Email" + onChange={editAuthor('email')} + type="email" + value={email} + /> + <TextField + label="Affiliation" + onChange={editAuthor('affiliation')} + value={affiliation} + /> + <Menu + onChange={editAuthor('country')} + options={countries} + value={country} + /> + </div> + </div> +) + +const Label = ({ label, value }) => ( + <div className={classnames(classes['label-container'])}> + <span className={classnames(classes.label)}>{label}</span> + <span className={classnames(classes.value)}>{value}</span> + </div> +) + +const Author = ({ + firstName, + middleName, + lastName, + email, + affiliation, + isDragging, + children, +}) => ( + <div className={classnames(classes.author)}> + <span className={classnames(classes.title)}>Author</span> + {!isDragging && ( + <div className={classnames(classes.row)}> + <Label label="First name" value={firstName} /> + <Label label="Middle name" value={middleName} /> + <Label label="Last name" value={lastName} /> + </div> + )} + {!isDragging && ( + <div className={classnames(classes.row)}> + <Label label="Email" value={email} /> + <Label label="Affiliation" value={affiliation} /> + <Label label="Affiliation" value={affiliation} /> + </div> + )} + </div> +) + +const Authors = ({ author, authors, moveAuthor, addAuthor, editAuthor }) => ( + <div> + <AuthorAdder + addAuthor={addAuthor} + author={author} + editAuthor={editAuthor} + /> + <SortableList items={authors} listItem={Author} moveItem={moveAuthor} /> + </div> +) + +export default compose( + withState('author', 'changeAuthor', { + firstName: '', + middleName: '', + lastName: '', + email: '', + affiliation: '', + country: 'ro', + }), + withState('authors', 'changeAuthors', [ + { + firstName: 'Razvan', + middleName: 'Petru', + lastName: 'Tudosa', + email: 'rzv@gmail.com', + affiliation: 'rock', + }, + { + firstName: 'Alexandru', + middleName: 'Ioan', + lastName: 'Munteanu', + email: 'alexmntn@gmail.com', + affiliation: 'rap', + }, + { + firstName: 'Bogdan', + middleName: 'Alexandru', + lastName: 'Cochior', + email: 'bog1@gmail.com', + affiliation: 'metal', + }, + ]), + withHandlers({ + addAuthor: ({ author, changeAuthors, changeAuthor }) => e => { + e.preventDefault() + changeAuthors(prevAuthors => [author, ...prevAuthors]) + changeAuthor(prev => ({ + firstName: '', + middleName: '', + lastName: '', + email: '', + affiliation: '', + country: 'ro', + })) + }, + moveAuthor: ({ changeAuthors }) => (dragIndex, hoverIndex) => { + changeAuthors(prev => SortableList.moveItem(prev, dragIndex, hoverIndex)) + }, + editAuthor: ({ changeAuthor }) => field => e => { + const v = get(e, 'target.value') || e + changeAuthor(prev => ({ + ...prev, + [field]: v, + })) + }, + }), +)(Authors) diff --git a/packages/component-wizard/src/components/AuthorList.local.scss b/packages/component-wizard/src/components/AuthorList.local.scss new file mode 100644 index 0000000000000000000000000000000000000000..56e988847b48eb9bca459c8780897358f2a4ea4b --- /dev/null +++ b/packages/component-wizard/src/components/AuthorList.local.scss @@ -0,0 +1,45 @@ +.row { + display: flex; + flex-direction: row; +} + +.author { + border: 1px solid #444; + + .title { + font-size: 16px; + font-weight: 600; + margin: 5px; + } + + .label-container { + display: flex; + flex: 1; + flex-direction: column; + margin: 5px; + + .label { + font-size: 14px; + font-weight: 300; + text-transform: uppercase; + } + + .value { + font-size: 16px; + font-weight: 600; + } + } +} + +.adder { + background-color: aquamarine; + display: flex; + flex-direction: column; + margin: 10px 0; + padding: 5px; + + .title { + font-size: 18px; + font-weight: 500; + } +} diff --git a/packages/component-wizard/src/components/Steps.js b/packages/component-wizard/src/components/Progress.js similarity index 96% rename from packages/component-wizard/src/components/Steps.js rename to packages/component-wizard/src/components/Progress.js index 0bee01f14197e15d902fa32713a894b9938a44de..b22a07f8b9061c0a5bd62d1b30177bc5f62ada0b 100644 --- a/packages/component-wizard/src/components/Steps.js +++ b/packages/component-wizard/src/components/Progress.js @@ -2,7 +2,7 @@ import React from 'react' import PropTypes from 'prop-types' import { compose, withHandlers, withContext, getContext } from 'recompose' -import classes from './Steps.local.scss' +import classes from './Progress.local.scss' const Separator = () => <div className={classes.separator} /> diff --git a/packages/component-wizard/src/components/Steps.local.scss b/packages/component-wizard/src/components/Progress.local.scss similarity index 92% rename from packages/component-wizard/src/components/Steps.local.scss rename to packages/component-wizard/src/components/Progress.local.scss index b02d38008a85111d12e7d65c701c74de051fa72f..3ac86ec244c9d2842e93f3b85ccf3ce48f28e8e7 100644 --- a/packages/component-wizard/src/components/Steps.local.scss +++ b/packages/component-wizard/src/components/Progress.local.scss @@ -3,7 +3,7 @@ display: flex; flex-direction: row; justify-content: space-between; - margin: 0 40px 40px 40px; + margin: 0 40px 70px 40px; min-width: 400px; } @@ -33,8 +33,9 @@ .stepTitle { font-size: 14px; - left: -40px; + left: -45px; position: absolute; + text-align: center; top: 25px; white-space: normal; width: 120px; diff --git a/packages/component-wizard/src/components/SortableList.js b/packages/component-wizard/src/components/SortableList.js index 1273b9e12bf1ef63d4b4747a1f000f0e79791986..95453bec0f48eeadffd7157c433c5d63821bda35 100644 --- a/packages/component-wizard/src/components/SortableList.js +++ b/packages/component-wizard/src/components/SortableList.js @@ -2,6 +2,9 @@ import React from 'react' import { compose } from 'recompose' import { findDOMNode } from 'react-dom' import { DragSource, DropTarget } from 'react-dnd' +import classnames from 'classnames' +import { Icon } from '@pubsweet/ui' +import classes from './SortableList.local.scss' const itemSource = { beginDrag(props) { @@ -31,14 +34,39 @@ const itemTarget = { if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { return } - moveItem(dragIndex, hoverIndex) + if (typeof moveItem === 'function') { + moveItem(dragIndex, hoverIndex) + } monitor.getItem().index = hoverIndex }, } -const Item = ({ connectDragSource, connectDropTarget, listItem, ...rest }) => - connectDragSource( - connectDropTarget(<div>{React.createElement(listItem, rest)}</div>), +const DragHandle = () => ( + <div className={classnames(classes['drag-handle'])}> + <Icon>chevron_up</Icon> + <Icon>chevron_down</Icon> + </div> +) + +const Item = ({ + connectDragPreview, + connectDragSource, + connectDropTarget, + listItem, + ...rest +}) => + connectDragPreview( + <div style={{ display: 'flex' }}> + {connectDragSource( + <div className={classnames(classes['drag-handle'])}> + <Icon>chevron_up</Icon> + <Icon>chevron_down</Icon> + </div>, + )} + {connectDropTarget( + <div style={{ flex: 1 }}>{React.createElement(listItem, rest)}</div>, + )} + </div>, ) const DecoratedItem = compose( @@ -48,6 +76,7 @@ const DecoratedItem = compose( })), DragSource('item', itemSource, (connect, monitor) => ({ connectDragSource: connect.dragSource(), + connectDragPreview: connect.dragPreview(), isDragging: monitor.isDragging(), })), )(Item) @@ -57,7 +86,7 @@ const SortableList = ({ items, moveItem, listItem }) => ( {items.map((item, i) => ( <DecoratedItem index={i} - key={item.name} + key={item.name || Math.random()} listItem={listItem} moveItem={moveItem} {...item} diff --git a/packages/component-wizard/src/components/SortableList.local.scss b/packages/component-wizard/src/components/SortableList.local.scss new file mode 100644 index 0000000000000000000000000000000000000000..41607ab0e84369690e3e1d24b2e2dccd241c0dda --- /dev/null +++ b/packages/component-wizard/src/components/SortableList.local.scss @@ -0,0 +1,5 @@ +.drag-handle { + display: flex; + flex-direction: column; + justify-content: center; +} diff --git a/packages/component-wizard/src/components/Wizard.js b/packages/component-wizard/src/components/Wizard.js index d6cb3b09b0ea3e58f2eaa24a05423a541606f19e..e13aaa0af9a8f49b80daf06f70615b55a1f3b86b 100644 --- a/packages/component-wizard/src/components/Wizard.js +++ b/packages/component-wizard/src/components/Wizard.js @@ -1,172 +1,27 @@ import React from 'react' -import PropTypes from 'prop-types' import classnames from 'classnames' -import { connect } from 'react-redux' -import { pick, debounce } from 'lodash' -import { reduxForm } from 'redux-form' -import { withJournal } from 'xpub-journal' -import { ConnectPage } from 'xpub-connect' -import { ValidatedField, Button } from '@pubsweet/ui' -import { selectCollection, selectFragment } from 'xpub-selectors' -import { - compose, - withHandlers, - withState, - getContext, - withContext, - withProps, -} from 'recompose' -import { actions } from 'pubsweet-client' import classes from './Wizard.local.scss' -import { Steps } from './' +import WizardFormStep from './WizardFormStep' +import Progress from './Progress' -const { Step } = Steps +const { Step } = Progress -const validate = values => { - const errors = {} - return errors -} - -const onChange = (values, dispatch, { project, version }) => { - dispatch( - actions.updateFragment(project, { - id: version.id, - rev: version.rev, - ...values, - }), - ) -} - -const WizardStep = ({ - children: stepChildren, - title, - buttons, - nextStep, - prevStep, - handleSubmit, - isFinal, - isFirst, - goBack, -}) => ( - <div className={classnames(classes.step)}> - <form - className={classnames(classes.form)} - name="metadata" - onSubmit={handleSubmit} - > - <h3>{title}</h3> - {stepChildren && - stepChildren.map( - ({ fieldId, validate, renderComponent: Comp, ...rest }) => ( - <ValidatedField - component={input => <Comp {...rest} {...input} />} - key={fieldId} - name={fieldId} - validate={validate} - /> - ), - )} - <div className={classnames(classes.buttons)}> - <Button onClick={isFirst ? goBack : prevStep}> - {isFirst ? 'Cancel' : 'Back'} - </Button> - <Button primary type="submit"> - {isFinal ? 'Finish' : 'Next'} - </Button> - </div> - </form> - </div> -) - -const FormStep = compose( - getContext({ - goBack: PropTypes.func, - isFinal: PropTypes.bool, - isFirst: PropTypes.bool, - project: PropTypes.object, - version: PropTypes.object, - wizard: PropTypes.object, - }), - withProps(({ version, wizard }) => ({ - initialValues: pick(version, wizard.formSectionKeys), - readonly: !!version.submitted, - })), - reduxForm({ - form: 'wizard', - destroyOnUnmount: false, - forceUnregisterOnUnmount: true, - validate, - onSubmit: (values, dispatch, { nextStep, isFinal }) => { - if (!isFinal) { - nextStep() - } - }, - onChange: debounce(onChange, 1000, { maxWait: 5000 }), - }), -)(WizardStep) - -const Wizard = ({ +export default ({ journal: { wizard: { showProgress, steps } }, getSteps, - step, nextStep, prevStep, - ...rest + step, }) => ( <div className={classnames(classes.container)}> {showProgress && ( - <Steps currentStep={step}> + <Progress currentStep={step}> {getSteps().map((step, index) => ( <Step index={index} key={step} title={step} /> ))} - </Steps> + </Progress> )} - <FormStep {...steps[step]} nextStep={nextStep} prevStep={prevStep} /> + <WizardFormStep {...steps[step]} nextStep={nextStep} prevStep={prevStep} /> </div> ) - -export default compose( - ConnectPage(({ match }) => [ - actions.getCollection({ id: match.params.project }), - actions.getFragment( - { id: match.params.project }, - { id: match.params.version }, - ), - ]), - connect((state, { match }) => { - const project = selectCollection(state, match.params.project) - const version = selectFragment(state, match.params.version) - - return { project, version } - }), - withJournal, - withState('step', 'changeStep', 0), - withHandlers({ - getSteps: ({ journal: { wizard: { steps } } }) => () => - steps.map(w => w.label), - nextStep: ({ changeStep, journal: { wizard: { steps } } }) => () => { - changeStep(step => (step === steps.length - 1 ? step : step + 1)) - }, - prevStep: ({ changeStep }) => () => - changeStep(step => (step <= 0 ? step : step - 1)), - }), - withContext( - { - goBack: PropTypes.func, - isFinal: PropTypes.bool, - isFirst: PropTypes.bool, - project: PropTypes.object, - version: PropTypes.object, - wizard: PropTypes.object, - }, - ({ history: { goBack }, step, project, version, journal: { wizard } }) => ({ - goBack, - isFinal: step === wizard.steps.length - 1, - isFirst: step === 0, - project, - version, - wizard, - }), - ), -)(Wizard) diff --git a/packages/component-wizard/src/components/Wizard.local.scss b/packages/component-wizard/src/components/Wizard.local.scss index f108dfb46bb426557ebc716d51e4b5e67abd6936..77e5cd336c2d3bbf7f6b870aff8fb1bf32c5d4b1 100644 --- a/packages/component-wizard/src/components/Wizard.local.scss +++ b/packages/component-wizard/src/components/Wizard.local.scss @@ -6,26 +6,3 @@ width: 900px; } -.step { - align-items: stretch; - border: 1px solid #222; - display: flex; - flex-direction: column; - justify-content: flex-start; - padding: 0 20px; - width: 700px; -} - -.form { - display: flex; - flex-direction: column; -} - -.buttons { - align-items: center; - align-self: center; - display: flex; - justify-content: space-around; - margin: 15px 0; - width: 400px; -} diff --git a/packages/component-wizard/src/components/WizardFormStep.js b/packages/component-wizard/src/components/WizardFormStep.js new file mode 100644 index 0000000000000000000000000000000000000000..e031cbc24ad30ce519016da036ffdbdca52b0f1e --- /dev/null +++ b/packages/component-wizard/src/components/WizardFormStep.js @@ -0,0 +1,55 @@ +import PropTypes from 'prop-types' +import { connect } from 'react-redux' +import { debounce, pick } from 'lodash' +import { actions } from 'pubsweet-client' +import { reduxForm, formValueSelector } from 'redux-form' +import { compose, getContext, withProps } from 'recompose' + +import WizardStep from './WizardStep' + +const wizardSelector = formValueSelector('wizard') + +const onChange = (values, dispatch, { project, version }) => { + dispatch( + actions.updateFragment(project, { + id: version.id, + rev: version.rev, + ...values, + }), + ) +} + +export default compose( + getContext({ + goBack: PropTypes.func, + isFinal: PropTypes.bool, + isFirst: PropTypes.bool, + project: PropTypes.object, + version: PropTypes.object, + wizard: PropTypes.object, + }), + withProps(({ version, wizard }) => ({ + initialValues: pick(version, wizard.formSectionKeys), + readonly: !!version.submitted, + })), + connect((state, { wizard: { formSectionKeys } }) => ({ + formValues: formSectionKeys.reduce( + (acc, el) => ({ + ...acc, + [el]: wizardSelector(state, el), + }), + {}, + ), + })), + reduxForm({ + form: 'wizard', + destroyOnUnmount: false, + forceUnregisterOnUnmount: true, + onSubmit: (values, dispatch, { nextStep, isFinal }) => { + if (!isFinal) { + nextStep() + } + }, + onChange: debounce(onChange, 1000, { maxWait: 5000 }), + }), +)(WizardStep) diff --git a/packages/component-wizard/src/components/WizardPage.js b/packages/component-wizard/src/components/WizardPage.js new file mode 100644 index 0000000000000000000000000000000000000000..1e60878690186a6fdb83a0929fad500a7276c140 --- /dev/null +++ b/packages/component-wizard/src/components/WizardPage.js @@ -0,0 +1,54 @@ +import PropTypes from 'prop-types' +import { connect } from 'react-redux' +import { actions } from 'pubsweet-client' +import { withJournal } from 'xpub-journal' +import { ConnectPage } from 'xpub-connect' +import { selectCollection, selectFragment } from 'xpub-selectors' +import { compose, withHandlers, withState, withContext } from 'recompose' + +import Wizard from './Wizard' + +export default compose( + ConnectPage(({ match }) => [ + actions.getCollection({ id: match.params.project }), + actions.getFragment( + { id: match.params.project }, + { id: match.params.version }, + ), + ]), + connect((state, { match }) => { + const project = selectCollection(state, match.params.project) + const version = selectFragment(state, match.params.version) + + return { project, version } + }), + withJournal, + withState('step', 'changeStep', 0), + withHandlers({ + getSteps: ({ journal: { wizard: { steps } } }) => () => + steps.map(w => w.label), + nextStep: ({ changeStep, journal: { wizard: { steps } } }) => () => { + changeStep(step => (step === steps.length - 1 ? step : step + 1)) + }, + prevStep: ({ changeStep }) => () => + changeStep(step => (step <= 0 ? step : step - 1)), + }), + withContext( + { + goBack: PropTypes.func, + isFinal: PropTypes.bool, + isFirst: PropTypes.bool, + project: PropTypes.object, + version: PropTypes.object, + wizard: PropTypes.object, + }, + ({ history: { goBack }, step, project, version, journal: { wizard } }) => ({ + goBack, + isFinal: step === wizard.steps.length - 1, + isFirst: step === 0, + project, + version, + wizard, + }), + ), +)(Wizard) diff --git a/packages/component-wizard/src/components/WizardStep.js b/packages/component-wizard/src/components/WizardStep.js new file mode 100644 index 0000000000000000000000000000000000000000..15af64420572a6286a5cad303624c1e4d64245f8 --- /dev/null +++ b/packages/component-wizard/src/components/WizardStep.js @@ -0,0 +1,61 @@ +import React from 'react' +import { get } from 'lodash' +import classnames from 'classnames' +import { ValidatedField, Button } from '@pubsweet/ui' + +import classes from './WizardStep.local.scss' + +import AuthorList from './AuthorList' + +export default ({ + children: stepChildren, + title, + buttons, + nextStep, + prevStep, + handleSubmit, + isFinal, + isFirst, + goBack, + formValues, +}) => ( + <div className={classnames(classes.step)}> + <form className={classnames(classes.form)} onSubmit={handleSubmit}> + <h3 className={classnames(classes.title)}>{title}</h3> + {stepChildren && + stepChildren.map( + ({ + fieldId, + validate, + dependsOn, + renderComponent: Comp, + ...rest + }) => { + if ( + dependsOn && + get(formValues, dependsOn.field) !== dependsOn.condition + ) { + return null + } + return ( + <ValidatedField + component={input => <Comp {...rest} {...input} />} + key={fieldId} + name={fieldId} + validate={validate} + /> + ) + }, + )} + <AuthorList /> + <div className={classnames(classes.buttons)}> + <Button onClick={isFirst ? goBack : prevStep}> + {isFirst ? 'Cancel' : 'Back'} + </Button> + <Button primary type="submit"> + {isFinal ? 'Finish' : 'Next'} + </Button> + </div> + </form> + </div> +) diff --git a/packages/component-wizard/src/components/WizardStep.local.scss b/packages/component-wizard/src/components/WizardStep.local.scss new file mode 100644 index 0000000000000000000000000000000000000000..1b69b7a3a10de57d2fc98531d1d5c2454ce9ac39 --- /dev/null +++ b/packages/component-wizard/src/components/WizardStep.local.scss @@ -0,0 +1,27 @@ +.step { + align-items: stretch; + border: 1px solid #222; + display: flex; + flex-direction: column; + justify-content: flex-start; + padding: 0 20px; + width: 700px; + + .title { + align-self: center; + } +} + +.form { + display: flex; + flex-direction: column; +} + +.buttons { + align-items: center; + align-self: center; + display: flex; + justify-content: space-around; + margin: 15px 0; + width: 400px; +} diff --git a/packages/component-wizard/src/components/index.js b/packages/component-wizard/src/components/index.js index e51f2b7f2ffa168113acd18b9894682b93cc8c69..710ecfaa0eddf11223519e338a929598aeffe755 100644 --- a/packages/component-wizard/src/components/index.js +++ b/packages/component-wizard/src/components/index.js @@ -1,4 +1,9 @@ -export { default as Steps } from './Steps' export { default as Wizard } from './Wizard' +export { default as Progress } from './Progress' export { default as Dropdown } from './Dropdown' +export { default as WizardPage } from './WizardPage' +export { default as WizardStep } from './WizardStep' export { default as SortableList } from './SortableList' +export { default as WizardFormStep } from './WizardFormStep' + +export { default as AuthorList } from './AuthorList' diff --git a/packages/xpub-faraday/app/app.js b/packages/xpub-faraday/app/app.js index fb7eae11ea0bf59533f689f99ac71e48b38a0ed4..6ca64de09e621859c51fcd7b0a9440c18ca96608 100644 --- a/packages/xpub-faraday/app/app.js +++ b/packages/xpub-faraday/app/app.js @@ -11,7 +11,7 @@ import * as journal from './config/journal' import Routes from './routes' const history = createHistory() -const store = configureStore(history, {}) +export const store = configureStore(history, {}) const theme = {} const render = () => { diff --git a/packages/xpub-faraday/app/config/journal/article-sections.js b/packages/xpub-faraday/app/config/journal/article-sections.js deleted file mode 100644 index ab5c5e94d62fc58cf8bb7b12a7ac462f1ddba050..0000000000000000000000000000000000000000 --- a/packages/xpub-faraday/app/config/journal/article-sections.js +++ /dev/null @@ -1,30 +0,0 @@ -export default [ - { - label: 'Cognitive Psychology', - value: 'cognitive-psychology', - }, - { - label: 'Social Psychology', - value: 'social-psychology', - }, - { - label: 'Personality Psychology', - value: 'personality-psychology', - }, - { - label: 'Developmental Psychology', - value: 'developmental-psychology', - }, - { - label: 'Clinical Psychology', - value: 'clinical-psychology', - }, - { - label: 'Organizational Behavior', - value: 'organizational-behavior', - }, - { - label: 'Methodology and Research Practice', - value: 'methodology', - }, -] diff --git a/packages/xpub-faraday/app/config/journal/article-types.js b/packages/xpub-faraday/app/config/journal/article-types.js deleted file mode 100644 index a5d08e5f9823fcce6aa1ff85435a1b798ac5629a..0000000000000000000000000000000000000000 --- a/packages/xpub-faraday/app/config/journal/article-types.js +++ /dev/null @@ -1,18 +0,0 @@ -export default [ - { - label: 'Original Research Report', - value: 'original-research', - }, - { - label: 'Review', - value: 'review', - }, - { - label: 'Opinion/Commentary', - value: 'opinion', - }, - { - label: 'Registered Report', - value: 'registered-report', - }, -] diff --git a/packages/xpub-faraday/app/config/journal/declarations.js b/packages/xpub-faraday/app/config/journal/declarations.js index 2f25fbee2e499dcc09f87585cc28e7b9b8af302b..c5372cd6d4f62e54b190b61eda7ba4f13c072410 100644 --- a/packages/xpub-faraday/app/config/journal/declarations.js +++ b/packages/xpub-faraday/app/config/journal/declarations.js @@ -27,30 +27,30 @@ export default { ], options: [ { - value: 'step2-1', + value: 'has-email', label: `I have the email addresses of all the co-authors of the manuscript.`, }, { - value: 'step2-2', + value: 'has-manuscript', label: 'I have the manuscript file in Microsoft Word or Adobe PDF format with the tables and figures integrated in the manuscript body.', }, { - value: 'step2-3', + value: 'has-efiles', label: 'I have the electronic files of any supplementary materials (e.g., datasets, images, audio, video) that I want to submit with the manuscript.', }, { - value: 'step2-4', + value: 'ok-article-processing', label: 'I am aware that accepted manuscripts are subject to Article Processing Charges.', }, { - value: 'step2-5', + value: 'has-orcid', label: `I'm aware that an ORCID ID is required for the corresponding author before the article can be published (if accepted). The ORCID ID should added via your user account.`, }, { - value: 'step2-6', + value: 'ok-institutional', label: '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.', }, diff --git a/packages/xpub-faraday/app/config/journal/index.js b/packages/xpub-faraday/app/config/journal/index.js index 6f766fe010681851881e41518ce6918f2a6d5382..fccf0c181b0ce99568dfa87bc07510ba18cbdd30 100644 --- a/packages/xpub-faraday/app/config/journal/index.js +++ b/packages/xpub-faraday/app/config/journal/index.js @@ -3,8 +3,8 @@ export { default as declarations } from './declarations' export { default as decisions } from './decisions' export { default as recommendations } from './recommendations' export { default as sections } from './sections' -export { default as articleSections } from './article-sections' -export { default as articleTypes } from './article-types' export { default as editors } from './editors' export { default as roles } from './roles' export { default as wizard } from './submit-wizard' +export { default as issueTypes } from './issues-types' +export { default as manuscriptTypes } from './manuscript-types' diff --git a/packages/xpub-faraday/app/config/journal/issues-types.js b/packages/xpub-faraday/app/config/journal/issues-types.js new file mode 100644 index 0000000000000000000000000000000000000000..d35ee4514b4bd0c83cf7349b08b7baf0755a0ffd --- /dev/null +++ b/packages/xpub-faraday/app/config/journal/issues-types.js @@ -0,0 +1,31 @@ +export default [ + { label: 'Regular Issues', value: 'regular-issue' }, + { + label: 'Analytical Method for High Energy Physics', + value: 'analytical-method', + }, + { + label: + 'Cosmic Strings: Fields in Thier Space-Time and Their Cosmological Signatures', + value: 'cosmic-strings', + }, + { + label: + 'Neutrino Physics in the Frontiers of Intensities and Very High Sensitivities 2018', + value: 'neutrino-physics', + }, + { + label: 'New Physics Landmarks: Dark Matters and Neutrino Masses', + value: 'new-physics-landmarks', + }, + { + label: + 'Properties of Chemical and Kinetic Freeze-Outs in High-Energy Nuclear Collisions', + value: 'properties-of-chemical', + }, + { + label: + 'Perspectives on Decay and Time Evolutions of Metastable States: From Particle Physics to Cosmology', + value: 'perspective-on-decay', + }, +] diff --git a/packages/xpub-faraday/app/config/journal/manuscript-types.js b/packages/xpub-faraday/app/config/journal/manuscript-types.js new file mode 100644 index 0000000000000000000000000000000000000000..a4a62ffd68469574c005b65c3194ac12f60bb826 --- /dev/null +++ b/packages/xpub-faraday/app/config/journal/manuscript-types.js @@ -0,0 +1,72 @@ +export default [ + { + label: 'Research', + value: 'research', + author: true, + peerReview: true, + abstractRequired: true, + }, + { + label: 'Review', + value: 'review', + author: true, + peerReview: true, + abstractRequired: true, + }, + { + label: 'Clinical study', + value: 'clinical-study', + author: true, + peerReview: true, + abstractRequired: true, + }, + { + label: 'Case report', + value: 'case-report', + author: true, + peerReview: true, + abstractRequired: true, + }, + { + label: 'Letter to the editor', + value: 'letter-to-editor', + author: true, + peerReview: false, + abstractRequired: false, + }, + { + label: 'Editorial', + value: 'editorial', + author: false, + peerReview: false, + abstractRequired: false, + }, + { + label: 'Corrigendum', + value: 'corrigendum', + author: false, + peerReview: false, + abstractRequired: false, + }, + { + label: 'Erratum', + value: 'erratum', + author: false, + peerReview: false, + abstractRequired: false, + }, + { + label: 'Expression of concern', + value: 'expression-of-concern', + author: false, + peerReview: false, + abstractRequired: true, + }, + { + label: 'Retraction', + value: 'retraction', + author: false, + peerReview: false, + abstractRequired: false, + }, +] diff --git a/packages/xpub-faraday/app/config/journal/metadata.js b/packages/xpub-faraday/app/config/journal/metadata.js index 422009e4150d333be600272d9bb0ba104c9d4f38..7d662e97b2b267abc000756cf3b2056e80d1f562 100644 --- a/packages/xpub-faraday/app/config/journal/metadata.js +++ b/packages/xpub-faraday/app/config/journal/metadata.js @@ -3,8 +3,3 @@ export default { name: 'Hindawi Faraday', logo: '/assets/hindawi-logo.png', } - -export const journal = { - label: 'Hindawi Faraday', - value: 'hindawi-faraday', -} diff --git a/packages/xpub-faraday/app/config/journal/submit-wizard.js b/packages/xpub-faraday/app/config/journal/submit-wizard.js index 0c0f29a29829d5d339498e21e3d08908ed1f5a52..9b138d17e0b2e4df06029f2f60ccd7221975ad4c 100644 --- a/packages/xpub-faraday/app/config/journal/submit-wizard.js +++ b/packages/xpub-faraday/app/config/journal/submit-wizard.js @@ -8,14 +8,22 @@ import { Supplementary, } from '@pubsweet/ui' import uploadFile from 'xpub-upload' -import { required, minChars } from 'xpub-validators' +import { required, minChars, minSize } from 'xpub-validators' -import { articleSections, declarations } from './' +import { declarations } from './' +import issueTypes from './issues-types' +import manuscriptTypes from './manuscript-types' + +import { requiredBasedOnType } from './wizard-validators' const min3Chars = minChars(3) +const declarationsMinSize = minSize(declarations.options.length) + const yesNoWithLabel = ({ label, ...rest }) => ( <div> - <label>{label}</label> + <label style={{ display: 'inline-block', marginBottom: 5, marginTop: 5 }}> + {label} + </label> <YesOrNo {...rest} /> </div> ) @@ -27,17 +35,11 @@ const journal = { export default { showProgress: true, - formSectionKeys: [ - 'metadata', - 'declarations', - 'suggestions', - 'notes', - 'files', - ], + formSectionKeys: ['metadata', 'declarations', 'conflicts', 'notes', 'files'], steps: [ { label: 'Journal details', - title: 'Jounal & Field Selection', + title: 'Journal & Field Selection', children: [ { fieldId: 'metadata.journal', @@ -48,19 +50,11 @@ export default { validate: [required], }, { - fieldId: 'subject', + fieldId: 'metadata.issue', renderComponent: Menu, - label: 'Subject area', - options: articleSections, - }, - { - fieldId: 'specialIssue', - renderComponent: Menu, - label: 'Special issue', - options: [ - { label: 'Special 2.1', value: 'dd21' }, - { label: 'Special 2.2', value: 'dd22' }, - ], + label: 'Issue', + options: issueTypes, + validate: [required], }, ], }, @@ -74,7 +68,7 @@ export default { fieldId: 'declarations', renderComponent: CheckboxGroup, options: declarations.options, - validate: [required], + validate: [required, declarationsMinSize], }, ], }, @@ -85,42 +79,41 @@ export default { 'Please provide the details of all the authors of this manuscript....', children: [ { - fieldId: 'step3-1', + fieldId: 'metadata.title', renderComponent: TitleEditor, placeholder: 'Manuscript title', title: 'Manuscript title', }, { - fieldId: 'step3-2', + fieldId: 'metadata.type', renderComponent: Menu, label: 'Manuscript type', - options: [ - { label: 'Type 1', value: 'type1' }, - { label: 'Type 2', value: 'type2' }, - ], + options: manuscriptTypes, + validate: [required], }, { - fieldId: 'step3-3', + fieldId: 'metadata.abstract', renderComponent: AbstractEditor, title: 'Abstract', placeholder: 'Write an abstract', + validate: [requiredBasedOnType], }, - // { - // fieldId: 'authors', - // renderComponent: 'sortable-list', - // label: 'Authors details', - // }, { - fieldId: 'step3-4', + fieldId: 'conflicts.hasConflicts', renderComponent: yesNoWithLabel, label: 'Is there a potential conflict of interest?', }, { - fieldId: 'step3-5', + dependsOn: { + field: 'conflicts.hasConflicts', + condition: 'yes', + }, + fieldId: 'conflicts.message', renderComponent: TextField, label: 'Conflict of interest details', validate: [required, min3Chars], }, + {}, ], }, { diff --git a/packages/xpub-faraday/app/config/journal/wizard-validators.js b/packages/xpub-faraday/app/config/journal/wizard-validators.js new file mode 100644 index 0000000000000000000000000000000000000000..9a9b0a9d4b086dda7d1efa2309355d0a1c14ceef --- /dev/null +++ b/packages/xpub-faraday/app/config/journal/wizard-validators.js @@ -0,0 +1,14 @@ +import { get } from 'lodash' + +import manuscriptTypes from './manuscript-types' + +const requiredTypes = manuscriptTypes + .filter(t => t.abstractRequired) + .map(t => t.value) + +export const requiredBasedOnType = (value, formValues) => { + if (requiredTypes.includes(get(formValues, 'metadata.type'))) { + return 'Required' + } + return undefined +} diff --git a/packages/xpub-faraday/app/routes.js b/packages/xpub-faraday/app/routes.js index dff1dde953e0d0b8c91dcdfe095bdc9c0681389f..4a15dc071cb4d5c16b955d73a5bdb609f88ca814 100644 --- a/packages/xpub-faraday/app/routes.js +++ b/packages/xpub-faraday/app/routes.js @@ -13,7 +13,7 @@ import { import DashboardPage from 'pubsweet-component-xpub-dashboard/src/components/DashboardPage' -import { Wizard } from 'pubsweet-component-wizard/src/components' +import { WizardPage } from 'pubsweet-component-wizard/src/components' // import { Wizard } from './component-wizard' @@ -23,7 +23,7 @@ const Routes = () => ( <PrivateRoute component={DashboardPage} exact path="/" /> <PrivateRoute component={LogoutPage} exact path="/logout" /> <PrivateRoute - component={Wizard} + component={WizardPage} exact path="/projects/:project/versions/:version/submit" /> diff --git a/packages/xpub-faraday/config/local-development.json b/packages/xpub-faraday/config/local-development.json deleted file mode 100644 index 2b249d74f689ff658c0aa3b7aa908226cc03e18e..0000000000000000000000000000000000000000 --- a/packages/xpub-faraday/config/local-development.json +++ /dev/null @@ -1,2 +0,0 @@ -{"pubsweet-server":{"secret":"702e1d23496c143026b634af15af57f5a88df7b7da9e3c24746da152d7068c72b98c692a09e76d5a618f2c2e473a8b6153bc4524a604290d04591eab9e0811e2"}} - diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js index d30f26928056ba4df3e15b7977c2ad657249525c..46db4f99f1ff03fd5d8c004ca6630f32f12e45af 100644 --- a/packages/xpub-faraday/config/validations.js +++ b/packages/xpub-faraday/config/validations.js @@ -18,23 +18,15 @@ module.exports = { source: Joi.string(), // TODO: move to a file metadata: Joi.object({ journal: Joi.string(), + issue: Joi.string(), title: Joi.string(), abstract: Joi.string(), - articleType: Joi.string(), - articleSection: Joi.array().items(Joi.string()), - // authors: Joi.array(), - keywords: Joi.array(), + type: Joi.string(), }), declarations: Joi.array(), - suggestions: Joi.object({ - reviewers: Joi.object({ - suggested: Joi.array().items(Joi.string()), - opposed: Joi.array().items(Joi.string()), - }), - editors: Joi.object({ - suggested: Joi.array().items(Joi.string()), - opposed: Joi.array().items(Joi.string()), - }), + conflicts: Joi.object({ + hasConflicts: Joi.any().valid(['yes', 'no']), + message: Joi.string(), }), files: Joi.object({ manuscript: Joi.object({