diff --git a/.gitignore b/.gitignore index a0f8767dc054599383f2ac91e7bc471b5b267175..705daea66123408f590797d9a2f5ae34923902ca 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ logs/* log.txt config.json packages/**/_build -packages/**/api/**/ \ No newline at end of file +packages/**/api/**/ +.vscode \ No newline at end of file diff --git a/packages/component-wizard/README.md b/packages/component-wizard/README.md new file mode 100644 index 0000000000000000000000000000000000000000..eb859bbd33ef85a468f3edff2562d906de3377a0 --- /dev/null +++ b/packages/component-wizard/README.md @@ -0,0 +1,116 @@ +Component based on `redux-form`. + +Submit form through a wizard (applicable for `Submit Manuscript` flow) using a configuration file. + +Configuration file must be under config `journal` (make use of `withJournal`) and exported with `wizard` key. + +`/xpub-collabra/app/config/journal/wizard.js` (see below file example) + + +### `Wizard.js` options +|Key|Description|Required|Default|Type| +| :---: | :---: | :---: | :---: | :---: | +| showProgress | Show progress bar | true | false | `bool` | +| submitText | Text to show on Submit button | false | 'Submit Manuscript' | `string` | +| backText | Text to show on Back button - Go back 1 step | false | 'Back' | `string` | +| nextText | Text to show on Back button - Go forward 1 step | false | 'Next' | `string` | +| cancelText | Text to show on Cancel button - Go to `/` | false | 'Back' | `string` | +| submissionRedirect | Path to redirect user after submitting the form. Passes as state `project` as project.id and `version` as version.id | false | `/` | `string` | +| confirmationModal | If present, component will be rendered as a modal before submitting the form. Accepts `toggleConfirming` to close the modal and must have 2 buttons for submit and close modal (see below) | false | none | `React Component` | +| formSectionKeys | Redux form data model. Keys to be saved on the form. | true | [] | `array` | +| dispatchFunctions | Functions to be dispatched in case a component needs a dispatched function (f.i. `uploadFile`) | true | none | `array` | +| steps | Each object in steps array represents a step in the form. In case of one-page form, just 1 step is needed. | true | none | `array` of `object` | + + +#### `Steps` options +|Key|Description|Required|Default|Type| +| :---: | :---: | :---: | :---: | :---: | +| label | Text on progress bar | false | '' | `string` | +| title | Text as title of the step | false | '' | `string` | +| subtitle | Text as info of the step | false | '' | `string` or `HTML` | +| children | Fields/Components to be rendered per each step | true | none | `array` of `object` | + + +#### `Steps children` options +|Key|Description|Required|Default|Type| +| :---: | :---: | :---: | :---: | :---: | +| fieldId | Path to the `redux-form` (f.i. for title in metadata use `metadata.title` ) | true | none | `string` | +| renderComponent | React Component to be rendered. Usually, a PubSweetUI component or custom component | true | none | `React Component` | +| validate | Array of custom validation per each field | false | none | `array` | +| `<props>` | Other props to be passed for that specific component | false | none | `label` `options` `placeholder` `title` `parse` `format` | + + + +#### ConfirmationModal.js +```js +const ConfirmationModal = ({ toggleConfirming }) => ( + <div> + <p>Explanatory text here</p> + <Button primary type="submit"> Submit your manuscript</Button> + <Button onClick={toggleConfirming}> get back to your submission (close modal)</Button> + </div> +) +``` + + +#### Example of `Wizard.js` for one-page form +```js +export default { + showProgress: false, + submitText: 'Submit your manuscript', + backText: 'Back', + cancelText: 'Cancel', + nextText: 'Next', + formSectionKeys: [ + 'metadata', + 'files', + ], + submissionRedirect: '/', + confirmationModal: ConfirmModal, + dispatchFunctions: [uploadFile], + steps: [ + { + label: 'Submission information', + title: 'Submission information', + subtitle: `We have ingested your manuscript. To access your manuscript in an editor, please view manuscript page. + <br/> To complete your submission, please answer the following questions. <br/> + The answers will be automatically saved.`, + children: [ + { + fieldId: 'metadata.title', + renderComponent: TitleEditor, + placeholder: 'Title', + title: 'Title', + validate: [required, minChars20, maxChars500], + }, + { + fieldId: 'metadata.abstract', + renderComponent: AbstractEditor, + title: 'Abstract', + placeholder: 'Write an abstract', + validate: [required, minChars100, maxChars5000], + }, + { + fieldId: 'label-authors', + renderComponent: Label, + label: 'Authors', + }, + { + fieldId: 'metadata.authors', + renderComponent: TextField, + title: 'Authors', + placeholder: 'Enter author names...', + format: join(), + parse: split(), + validate: [minSize1], + }, + { + fieldId: 'files.supplementary', + label: 'Upload supplementary materials', + renderComponent: Supplementary, + }, + ], + }, + ], +} +``` \ No newline at end of file diff --git a/packages/component-wizard/package.json b/packages/component-wizard/package.json index 59358018eb9dcf132d02035272ef0a66a4b887c9..36a5fc943c597269167a49556af5c480397dca86 100644 --- a/packages/component-wizard/package.json +++ b/packages/component-wizard/package.json @@ -5,6 +5,7 @@ "license": "MIT", "dependencies": { "@pubsweet/ui": "^0.1.1", + "moment": "^2.20.1", "prop-types": "^15.5.10", "react": "^15.6.1", "react-dnd": "^2.5.4", diff --git a/packages/component-wizard/src/components/AutosaveIndicator.js b/packages/component-wizard/src/components/AutosaveIndicator.js new file mode 100644 index 0000000000000000000000000000000000000000..2a134b9baa2d3d5b3a1646e7a18b2ad490e840ff --- /dev/null +++ b/packages/component-wizard/src/components/AutosaveIndicator.js @@ -0,0 +1,47 @@ +import React from 'react' +import moment from 'moment' +import classnames from 'classnames' +import { compose, withProps } from 'recompose' +import { Icon } from '@pubsweet/ui' + +import classes from './AutosaveIndicator.local.scss' + +const durationParser = lastUpdate => { + const today = moment() + const last = moment(lastUpdate) + const duration = moment.duration(today.diff(last)) + return `Last saved: ${duration.humanize()} ago.` +} + +const Indicator = ({ isVisibile, isFetching, error, lastUpdate }) => + isVisibile ? ( + <div className={classnames(classes.container)}> + {isFetching && ( + <div className={classnames(classes['icon-container'])}> + <div className={classnames(classes.rotate, classes.icon)}> + <Icon size={16}>refresh-cw</Icon> + </div> + <span>Saving changes...</span> + </div> + )} + + {!isFetching && lastUpdate && <span>{durationParser(lastUpdate)}</span>} + {!isFetching && + error && ( + <div className={classnames(classes['icon-container'])}> + <div className={classnames(classes.icon)}> + <Icon color="red" size={16}> + slash + </Icon> + </div> + <span className={classnames(classes['error-text'])}>{error}</span> + </div> + )} + </div> + ) : null + +export default compose( + withProps(({ isFetching, lastUpdate, error }) => ({ + isVisibile: Boolean(isFetching || lastUpdate || error), + })), +)(Indicator) diff --git a/packages/component-wizard/src/components/AutosaveIndicator.local.scss b/packages/component-wizard/src/components/AutosaveIndicator.local.scss new file mode 100644 index 0000000000000000000000000000000000000000..0b88db1af267bd05d439b592e801d45f9eb7e668 --- /dev/null +++ b/packages/component-wizard/src/components/AutosaveIndicator.local.scss @@ -0,0 +1,63 @@ +.container { + align-items: center; + display: flex; + justify-content: flex-end; + margin-bottom: 5px; +} + +@keyframes rotating { + from { + -o-transform: rotate(0deg); + -ms-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -o-transform: rotate(360deg); + -ms-transform: rotate(360deg); + -moz-transform: rotate(360deg); + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@-webkit-keyframes rotating { + from { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + + to { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +.rotate { + -webkit-animation: rotating 1.2s linear infinite; + -moz-animation: rotating 1.2s linear infinite; + -ms-animation: rotating 1.2s linear infinite; + -o-animation: rotating 1.2s linear infinite; + animation: rotating 1.2s linear infinite; +} + +.icon-container { + align-items: center; + display: flex; + padding: 5px; + + .icon { + align-items: center; + display: flex; + justify-content: center; + margin: 0 10px 0 0; + } +} + +.error-text { + color: red; + font-size: 14px; + font-weight: 400; +} diff --git a/packages/component-wizard/src/components/WizardFormStep.js b/packages/component-wizard/src/components/WizardFormStep.js index 128b78a4c58a210def58f7e6cbf98a1dadb2bc45..e7a608633d00bd88b6e68de484030e0454cfdff3 100644 --- a/packages/component-wizard/src/components/WizardFormStep.js +++ b/packages/component-wizard/src/components/WizardFormStep.js @@ -7,18 +7,26 @@ import { reduxForm, formValueSelector, SubmissionError } from 'redux-form' import WizardStep from './WizardStep' +import { + getAutosave, + autosaveRequest, + autosaveFailure, + autosaveSuccess, +} from '../redux/autosave' + const wizardSelector = formValueSelector('wizard') const onChange = ( values, dispatch, - { project, version, wizard: { formSectionKeys } }, + { project, version, wizard: { formSectionKeys }, setLoader }, prevValues, ) => { const prev = pick(prevValues, formSectionKeys) const newValues = pick(values, formSectionKeys) - // TODO: fix it if this sucks down the road + // TODO: fix this if it sucks down the road if (!isEqual(prev, newValues)) { + dispatch(autosaveRequest()) dispatch( actions.updateFragment(project, { id: version.id, @@ -26,10 +34,19 @@ const onChange = ( ...newValues, }), ) + .then(({ receivedAt }) => dispatch(autosaveSuccess(receivedAt))) + .catch(() => dispatch(autosaveFailure())) } } -const submitManuscript = (values, dispatch, project, version, history) => { +const submitManuscript = ( + values, + dispatch, + project, + version, + history, + redirectPath = '/', +) => { dispatch( actions.updateFragment(project, { id: version.id, @@ -48,7 +65,7 @@ const submitManuscript = (values, dispatch, project, version, history) => { ), ) .then(() => { - history.push('/') + history.push(redirectPath, { project: project.id, version: version.id }) }) .catch(error => { if (error.validationErrors) { @@ -60,12 +77,32 @@ const submitManuscript = (values, dispatch, project, version, history) => { const onSubmit = ( values, dispatch, - { nextStep, isFinal, history, project, version, ...rest }, + { + nextStep, + isFinal, + history, + project, + version, + confirmation, + wizard: { confirmationModal, submissionRedirect, formSectionKeys }, + toggleConfirmation, + ...rest + }, ) => { if (!isFinal) { nextStep() + } else if (confirmationModal && !confirmation) { + toggleConfirmation() } else { - submitManuscript(values, dispatch, project, version, history) + const newValues = pick(values, formSectionKeys) + submitManuscript( + newValues, + dispatch, + project, + version, + history, + submissionRedirect, + ) } } @@ -78,6 +115,8 @@ export default compose( version: PropTypes.object, wizard: PropTypes.object, dispatchFns: PropTypes.object, + confirmation: PropTypes.bool, + toggleConfirmation: PropTypes.func, }), withProps(({ version, wizard }) => ({ initialValues: pick(version, wizard.formSectionKeys), @@ -85,6 +124,7 @@ export default compose( })), connect((state, { wizard: { formSectionKeys } }) => ({ formValues: wizardSelector(state, ...formSectionKeys), + autosave: getAutosave(state), })), reduxForm({ form: 'wizard', diff --git a/packages/component-wizard/src/components/WizardPage.js b/packages/component-wizard/src/components/WizardPage.js index edc85ab088e30063f98ab106ffa843bde4bd0b1e..da00a100ed26da75cd2736e9887894704777bfbd 100644 --- a/packages/component-wizard/src/components/WizardPage.js +++ b/packages/component-wizard/src/components/WizardPage.js @@ -33,6 +33,7 @@ export default compose( }), ), withState('step', 'changeStep', 0), + withState('confirmation', 'setConfirmation', false), withHandlers({ getSteps: ({ journal: { wizard: { steps } } }) => () => steps.map(w => w.label), @@ -41,6 +42,8 @@ export default compose( }, prevStep: ({ changeStep }) => () => changeStep(step => (step <= 0 ? step : step - 1)), + toggleConfirmation: ({ setConfirmation }) => () => + setConfirmation(confirmation => !confirmation), }), withContext( { @@ -51,6 +54,8 @@ export default compose( version: PropTypes.object, wizard: PropTypes.object, dispatchFns: PropTypes.object, + confirmation: PropTypes.bool, + toggleConfirmation: PropTypes.func, }, ({ history, @@ -59,6 +64,8 @@ export default compose( version, journal: { wizard }, dispatchFns, + confirmation, + toggleConfirmation, }) => ({ history, isFinal: step === wizard.steps.length - 1, @@ -67,6 +74,8 @@ export default compose( version, wizard, dispatchFns, + confirmation, + toggleConfirmation, }), ), )(Wizard) diff --git a/packages/component-wizard/src/components/WizardStep.js b/packages/component-wizard/src/components/WizardStep.js index 973131942fdda1b3684f4a592c2e3d50ab3dfbf4..4df47c8bb20229c5515f7bb317d25ca9e050c51d 100644 --- a/packages/component-wizard/src/components/WizardStep.js +++ b/packages/component-wizard/src/components/WizardStep.js @@ -4,6 +4,7 @@ import classnames from 'classnames' import { ValidatedField, Button } from '@pubsweet/ui' import classes from './WizardStep.local.scss' +import AutosaveIndicator from './AutosaveIndicator' export default ({ children: stepChildren, @@ -19,6 +20,10 @@ export default ({ formValues, wizard, dispatchFns, + autosave, + confirmation, + toggleConfirmation, + wizard: { confirmationModal: ConfirmationModal }, ...rest }) => ( <div className={classnames(classes.step)}> @@ -73,6 +78,12 @@ export default ({ : `${wizard.nextText || 'Next'}`} </Button> </div> + {confirmation && ( + <div className={classnames(classes.modal)}> + <ConfirmationModal toggleConfirming={toggleConfirmation} /> + </div> + )} </form> + <AutosaveIndicator {...autosave} /> </div> ) diff --git a/packages/component-wizard/src/components/WizardStep.local.scss b/packages/component-wizard/src/components/WizardStep.local.scss index 48627e47b6862fd47c8ce036a35e72fd342d1ab2..8918f2a9853afac723a5d68b6a5e0e8bc22190ca 100644 --- a/packages/component-wizard/src/components/WizardStep.local.scss +++ b/packages/component-wizard/src/components/WizardStep.local.scss @@ -30,3 +30,15 @@ margin: 15px 0; width: 400px; } + +.modal { + align-items: center; + background: rgba(255, 255, 255, 0.95); + bottom: 0; + display: flex; + justify-content: center; + left: 0; + position: fixed; + right: 0; + top: 0; +} diff --git a/packages/component-wizard/src/components/countries.js b/packages/component-wizard/src/components/countries.js deleted file mode 100644 index 6e30f2654c1ff9664915051f40b60aebd421e702..0000000000000000000000000000000000000000 --- a/packages/component-wizard/src/components/countries.js +++ /dev/null @@ -1,998 +0,0 @@ -export default [ - { - value: 'AF', - label: 'Afghanistan', - }, - { - value: 'AX', - label: 'Åland Islands', - }, - { - value: 'AL', - label: 'Albania', - }, - { - value: 'DZ', - label: 'Algeria', - }, - { - value: 'AS', - label: 'American Samoa', - }, - { - value: 'AD', - label: 'Andorra', - }, - { - value: 'AO', - label: 'Angola', - }, - { - value: 'AI', - label: 'Anguilla', - }, - { - value: 'AQ', - label: 'Antarctica', - }, - { - value: 'AG', - label: 'Antigua and Barbuda', - }, - { - value: 'AR', - label: 'Argentina', - }, - { - value: 'AM', - label: 'Armenia', - }, - { - value: 'AW', - label: 'Aruba', - }, - { - value: 'AU', - label: 'Australia', - }, - { - value: 'AT', - label: 'Austria', - }, - { - value: 'AZ', - label: 'Azerbaijan', - }, - { - value: 'BS', - label: 'Bahamas', - }, - { - value: 'BH', - label: 'Bahrain', - }, - { - value: 'BD', - label: 'Bangladesh', - }, - { - value: 'BB', - label: 'Barbados', - }, - { - value: 'BY', - label: 'Belarus', - }, - { - value: 'BE', - label: 'Belgium', - }, - { - value: 'BZ', - label: 'Belize', - }, - { - value: 'BJ', - label: 'Benin', - }, - { - value: 'BM', - label: 'Bermuda', - }, - { - value: 'BT', - label: 'Bhutan', - }, - { - value: 'BO', - label: 'Bolivia, Plurinational State of', - }, - { - value: 'BQ', - label: 'Bonaire, Sint Eustatius and Saba', - }, - { - value: 'BA', - label: 'Bosnia and Herzegovina', - }, - { - value: 'BW', - label: 'Botswana', - }, - { - value: 'BV', - label: 'Bouvet Island', - }, - { - value: 'BR', - label: 'Brazil', - }, - { - value: 'IO', - label: 'British Indian Ocean Territory', - }, - { - value: 'BN', - label: 'Brunei Darussalam', - }, - { - value: 'BG', - label: 'Bulgaria', - }, - { - value: 'BF', - label: 'Burkina Faso', - }, - { - value: 'BI', - label: 'Burundi', - }, - { - value: 'KH', - label: 'Cambodia', - }, - { - value: 'CM', - label: 'Cameroon', - }, - { - value: 'CA', - label: 'Canada', - }, - { - value: 'CV', - label: 'Cape Verde', - }, - { - value: 'KY', - label: 'Cayman Islands', - }, - { - value: 'CF', - label: 'Central African Republic', - }, - { - value: 'TD', - label: 'Chad', - }, - { - value: 'CL', - label: 'Chile', - }, - { - value: 'CN', - label: 'China', - }, - { - value: 'CX', - label: 'Christmas Island', - }, - { - value: 'CC', - label: 'Cocos (Keeling) Islands', - }, - { - value: 'CO', - label: 'Colombia', - }, - { - value: 'KM', - label: 'Comoros', - }, - { - value: 'CG', - label: 'Congo', - }, - { - value: 'CD', - label: 'Congo, the Democratic Republic of the', - }, - { - value: 'CK', - label: 'Cook Islands', - }, - { - value: 'CR', - label: 'Costa Rica', - }, - { - value: 'CI', - label: "Côte d'Ivoire", - }, - { - value: 'HR', - label: 'Croatia', - }, - { - value: 'CU', - label: 'Cuba', - }, - { - value: 'CW', - label: 'Curaçao', - }, - { - value: 'CY', - label: 'Cyprus', - }, - { - value: 'CZ', - label: 'Czech Republic', - }, - { - value: 'DK', - label: 'Denmark', - }, - { - value: 'DJ', - label: 'Djibouti', - }, - { - value: 'DM', - label: 'Dominica', - }, - { - value: 'DO', - label: 'Dominican Republic', - }, - { - value: 'EC', - label: 'Ecuador', - }, - { - value: 'EG', - label: 'Egypt', - }, - { - value: 'SV', - label: 'El Salvador', - }, - { - value: 'GQ', - label: 'Equatorial Guinea', - }, - { - value: 'ER', - label: 'Eritrea', - }, - { - value: 'EE', - label: 'Estonia', - }, - { - value: 'ET', - label: 'Ethiopia', - }, - { - value: 'FK', - label: 'Falkland Islands (Malvinas)', - }, - { - value: 'FO', - label: 'Faroe Islands', - }, - { - value: 'FJ', - label: 'Fiji', - }, - { - value: 'FI', - label: 'Finland', - }, - { - value: 'FR', - label: 'France', - }, - { - value: 'GF', - label: 'French Guiana', - }, - { - value: 'PF', - label: 'French Polynesia', - }, - { - value: 'TF', - label: 'French Southern Territories', - }, - { - value: 'GA', - label: 'Gabon', - }, - { - value: 'GM', - label: 'Gambia', - }, - { - value: 'GE', - label: 'Georgia', - }, - { - value: 'DE', - label: 'Germany', - }, - { - value: 'GH', - label: 'Ghana', - }, - { - value: 'GI', - label: 'Gibraltar', - }, - { - value: 'GR', - label: 'Greece', - }, - { - value: 'GL', - label: 'Greenland', - }, - { - value: 'GD', - label: 'Grenada', - }, - { - value: 'GP', - label: 'Guadeloupe', - }, - { - value: 'GU', - label: 'Guam', - }, - { - value: 'GT', - label: 'Guatemala', - }, - { - value: 'GG', - label: 'Guernsey', - }, - { - value: 'GN', - label: 'Guinea', - }, - { - value: 'GW', - label: 'Guinea-Bissau', - }, - { - value: 'GY', - label: 'Guyana', - }, - { - value: 'HT', - label: 'Haiti', - }, - { - value: 'HM', - label: 'Heard Island and McDonald Islands', - }, - { - value: 'VA', - label: 'Holy See (Vatican City State)', - }, - { - value: 'HN', - label: 'Honduras', - }, - { - value: 'HK', - label: 'Hong Kong', - }, - { - value: 'HU', - label: 'Hungary', - }, - { - value: 'IS', - label: 'Iceland', - }, - { - value: 'IN', - label: 'India', - }, - { - value: 'ID', - label: 'Indonesia', - }, - { - value: 'IR', - label: 'Iran, Islamic Republic of', - }, - { - value: 'IQ', - label: 'Iraq', - }, - { - value: 'IE', - label: 'Ireland', - }, - { - value: 'IM', - label: 'Isle of Man', - }, - { - value: 'IL', - label: 'Israel', - }, - { - value: 'IT', - label: 'Italy', - }, - { - value: 'JM', - label: 'Jamaica', - }, - { - value: 'JP', - label: 'Japan', - }, - { - value: 'JE', - label: 'Jersey', - }, - { - value: 'JO', - label: 'Jordan', - }, - { - value: 'KZ', - label: 'Kazakhstan', - }, - { - value: 'KE', - label: 'Kenya', - }, - { - value: 'KI', - label: 'Kiribati', - }, - { - value: 'KP', - label: "Korea, Democratic People's Republic of", - }, - { - value: 'KR', - label: 'Korea, Republic of', - }, - { - value: 'KW', - label: 'Kuwait', - }, - { - value: 'KG', - label: 'Kyrgyzstan', - }, - { - value: 'LA', - label: "Lao People's Democratic Republic", - }, - { - value: 'LV', - label: 'Latvia', - }, - { - value: 'LB', - label: 'Lebanon', - }, - { - value: 'LS', - label: 'Lesotho', - }, - { - value: 'LR', - label: 'Liberia', - }, - { - value: 'LY', - label: 'Libya', - }, - { - value: 'LI', - label: 'Liechtenstein', - }, - { - value: 'LT', - label: 'Lithuania', - }, - { - value: 'LU', - label: 'Luxembourg', - }, - { - value: 'MO', - label: 'Macao', - }, - { - value: 'MK', - label: 'Macedonia, the Former Yugoslav Republic of', - }, - { - value: 'MG', - label: 'Madagascar', - }, - { - value: 'MW', - label: 'Malawi', - }, - { - value: 'MY', - label: 'Malaysia', - }, - { - value: 'MV', - label: 'Maldives', - }, - { - value: 'ML', - label: 'Mali', - }, - { - value: 'MT', - label: 'Malta', - }, - { - value: 'MH', - label: 'Marshall Islands', - }, - { - value: 'MQ', - label: 'Martinique', - }, - { - value: 'MR', - label: 'Mauritania', - }, - { - value: 'MU', - label: 'Mauritius', - }, - { - value: 'YT', - label: 'Mayotte', - }, - { - value: 'MX', - label: 'Mexico', - }, - { - value: 'FM', - label: 'Micronesia, Federated States of', - }, - { - value: 'MD', - label: 'Moldova, Republic of', - }, - { - value: 'MC', - label: 'Monaco', - }, - { - value: 'MN', - label: 'Mongolia', - }, - { - value: 'ME', - label: 'Montenegro', - }, - { - value: 'MS', - label: 'Montserrat', - }, - { - value: 'MA', - label: 'Morocco', - }, - { - value: 'MZ', - label: 'Mozambique', - }, - { - value: 'MM', - label: 'Myanmar', - }, - { - value: 'NA', - label: 'Namibia', - }, - { - value: 'NR', - label: 'Nauru', - }, - { - value: 'NP', - label: 'Nepal', - }, - { - value: 'NL', - label: 'Netherlands', - }, - { - value: 'NC', - label: 'New Caledonia', - }, - { - value: 'NZ', - label: 'New Zealand', - }, - { - value: 'NI', - label: 'Nicaragua', - }, - { - value: 'NE', - label: 'Niger', - }, - { - value: 'NG', - label: 'Nigeria', - }, - { - value: 'NU', - label: 'Niue', - }, - { - value: 'NF', - label: 'Norfolk Island', - }, - { - value: 'MP', - label: 'Northern Mariana Islands', - }, - { - value: 'NO', - label: 'Norway', - }, - { - value: 'OM', - label: 'Oman', - }, - { - value: 'PK', - label: 'Pakistan', - }, - { - value: 'PW', - label: 'Palau', - }, - { - value: 'PS', - label: 'Palestine, State of', - }, - { - value: 'PA', - label: 'Panama', - }, - { - value: 'PG', - label: 'Papua New Guinea', - }, - { - value: 'PY', - label: 'Paraguay', - }, - { - value: 'PE', - label: 'Peru', - }, - { - value: 'PH', - label: 'Philippines', - }, - { - value: 'PN', - label: 'Pitcairn', - }, - { - value: 'PL', - label: 'Poland', - }, - { - value: 'PT', - label: 'Portugal', - }, - { - value: 'PR', - label: 'Puerto Rico', - }, - { - value: 'QA', - label: 'Qatar', - }, - { - value: 'RE', - label: 'Réunion', - }, - { - value: 'RO', - label: 'Romania', - }, - { - value: 'RU', - label: 'Russian Federation', - }, - { - value: 'RW', - label: 'Rwanda', - }, - { - value: 'BL', - label: 'Saint Barthélemy', - }, - { - value: 'SH', - label: 'Saint Helena, Ascension and Tristan da Cunha', - }, - { - value: 'KN', - label: 'Saint Kitts and Nevis', - }, - { - value: 'LC', - label: 'Saint Lucia', - }, - { - value: 'MF', - label: 'Saint Martin (French part)', - }, - { - value: 'PM', - label: 'Saint Pierre and Miquelon', - }, - { - value: 'VC', - label: 'Saint Vincent and the Grenadines', - }, - { - value: 'WS', - label: 'Samoa', - }, - { - value: 'SM', - label: 'San Marino', - }, - { - value: 'ST', - label: 'Sao Tome and Principe', - }, - { - value: 'SA', - label: 'Saudi Arabia', - }, - { - value: 'SN', - label: 'Senegal', - }, - { - value: 'RS', - label: 'Serbia', - }, - { - value: 'SC', - label: 'Seychelles', - }, - { - value: 'SL', - label: 'Sierra Leone', - }, - { - value: 'SG', - label: 'Singapore', - }, - { - value: 'SX', - label: 'Sint Maarten (Dutch part)', - }, - { - value: 'SK', - label: 'Slovakia', - }, - { - value: 'SI', - label: 'Slovenia', - }, - { - value: 'SB', - label: 'Solomon Islands', - }, - { - value: 'SO', - label: 'Somalia', - }, - { - value: 'ZA', - label: 'South Africa', - }, - { - value: 'GS', - label: 'South Georgia and the South Sandwich Islands', - }, - { - value: 'SS', - label: 'South Sudan', - }, - { - value: 'ES', - label: 'Spain', - }, - { - value: 'LK', - label: 'Sri Lanka', - }, - { - value: 'SD', - label: 'Sudan', - }, - { - value: 'SR', - label: 'Surilabel', - }, - { - value: 'SJ', - label: 'Svalbard and Jan Mayen', - }, - { - value: 'SZ', - label: 'Swaziland', - }, - { - value: 'SE', - label: 'Sweden', - }, - { - value: 'CH', - label: 'Switzerland', - }, - { - value: 'SY', - label: 'Syrian Arab Republic', - }, - { - value: 'TW', - label: 'Taiwan, Province of China', - }, - { - value: 'TJ', - label: 'Tajikistan', - }, - { - value: 'TZ', - label: 'Tanzania, United Republic of', - }, - { - value: 'TH', - label: 'Thailand', - }, - { - value: 'TL', - label: 'Timor-Leste', - }, - { - value: 'TG', - label: 'Togo', - }, - { - value: 'TK', - label: 'Tokelau', - }, - { - value: 'TO', - label: 'Tonga', - }, - { - value: 'TT', - label: 'Trinidad and Tobago', - }, - { - value: 'TN', - label: 'Tunisia', - }, - { - value: 'TR', - label: 'Turkey', - }, - { - value: 'TM', - label: 'Turkmenistan', - }, - { - value: 'TC', - label: 'Turks and Caicos Islands', - }, - { - value: 'TV', - label: 'Tuvalu', - }, - { - value: 'UG', - label: 'Uganda', - }, - { - value: 'UA', - label: 'Ukraine', - }, - { - value: 'AE', - label: 'United Arab Emirates', - }, - { - value: 'UK', - label: 'United Kingdom', - }, - { - value: 'US', - label: 'United States', - }, - { - value: 'UM', - label: 'United States Minor Outlying Islands', - }, - { - value: 'UY', - label: 'Uruguay', - }, - { - value: 'UZ', - label: 'Uzbekistan', - }, - { - value: 'VU', - label: 'Vanuatu', - }, - { - value: 'VE', - label: 'Venezuela, Bolivarian Republic of', - }, - { - value: 'VN', - label: 'Viet Nam', - }, - { - value: 'VG', - label: 'Virgin Islands, British', - }, - { - value: 'VI', - label: 'Virgin Islands, U.S.', - }, - { - value: 'WF', - label: 'Wallis and Futuna', - }, - { - value: 'EH', - label: 'Western Sahara', - }, - { - value: 'YE', - label: 'Yemen', - }, - { - value: 'ZM', - label: 'Zambia', - }, - { - value: 'ZW', - label: 'Zimbabwe', - }, -] diff --git a/packages/component-wizard/src/components/index.js b/packages/component-wizard/src/components/index.js index 6fc7c641ca9fa351c3c8c0e8147281cfcfa49b0a..276990a4799cd9b46ff99e66ecfe34e15ca1388d 100644 --- a/packages/component-wizard/src/components/index.js +++ b/packages/component-wizard/src/components/index.js @@ -1,7 +1,6 @@ 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 AutosaveIndicator } from './AutosaveIndicator' diff --git a/packages/component-wizard/src/index.js b/packages/component-wizard/src/index.js index cb79e54391e79c2f4dbba4a5cf6710d9c4f3e79d..b43332ee55fa1efd10fa25e23eb759af7ccb18ea 100644 --- a/packages/component-wizard/src/index.js +++ b/packages/component-wizard/src/index.js @@ -3,7 +3,7 @@ module.exports = { components: [() => require('./components')], reducers: { wizardConversion: () => require('./redux/conversion').default, - authors: () => require('./redux/authors').default, + autosave: () => require('./redux/autosave').default, }, }, } diff --git a/packages/component-wizard/src/redux/autosave.js b/packages/component-wizard/src/redux/autosave.js new file mode 100644 index 0000000000000000000000000000000000000000..76f0507654722c8ac2bff395511fec6d3d239190 --- /dev/null +++ b/packages/component-wizard/src/redux/autosave.js @@ -0,0 +1,49 @@ +import { get } from 'lodash' + +export const AUTOSAVE_REQUEST = 'autosave/AUTOSAVE_REQUEST' +export const AUTOSAVE_FAILURE = 'autosave/AUTOSAVE_FAILURE' +export const AUTOSAVE_SUCCESS = 'autosave/AUTOSAVE_SUCCESS' + +export const autosaveRequest = () => ({ + type: AUTOSAVE_REQUEST, +}) + +export const autosaveFailure = () => ({ + type: AUTOSAVE_FAILURE, + error: 'Something went wrong...', +}) + +export const autosaveSuccess = lastUpdate => ({ + type: AUTOSAVE_SUCCESS, + lastUpdate, +}) + +const initialState = { + isFetching: false, + lastUpdate: null, + error: null, +} + +export const getAutosave = state => get(state, 'autosave') + +export default (state = initialState, action) => { + switch (action.type) { + case AUTOSAVE_REQUEST: + return { + ...initialState, + isFetching: true, + } + case AUTOSAVE_FAILURE: + return { + ...initialState, + error: action.error, + } + case AUTOSAVE_SUCCESS: + return { + ...initialState, + lastUpdate: action.lastUpdate, + } + default: + return state + } +} diff --git a/packages/component-wizard/src/redux/conversion.js b/packages/component-wizard/src/redux/conversion.js index f2bfbf51035014c8e6c84a6a6fd233519e9bca4a..e922af529d6c6454df3b8d1740ef47bf56147b6a 100644 --- a/packages/component-wizard/src/redux/conversion.js +++ b/packages/component-wizard/src/redux/conversion.js @@ -1,5 +1,4 @@ import { actions } from 'pubsweet-client' - /* constants */ export const CREATE_DRAFT_REQUEST = 'CREATE_DRAFT_REQUEST' diff --git a/packages/component-wizard/src/redux/index.js b/packages/component-wizard/src/redux/index.js index a0eee2ecd4a1e5776eea3e56ecc701cffe60897f..f767d735102b76804d7a5ba91ec0d08707d68bae 100644 --- a/packages/component-wizard/src/redux/index.js +++ b/packages/component-wizard/src/redux/index.js @@ -1,2 +1,2 @@ +export { default as autosave } from './autosave' export { default as conversion } from './conversion' -export { default as authors } from './authors' diff --git a/packages/components-faraday/package.json b/packages/components-faraday/package.json new file mode 100644 index 0000000000000000000000000000000000000000..3d216b81db74a068cc8e59fe5d5a46e3576a31f9 --- /dev/null +++ b/packages/components-faraday/package.json @@ -0,0 +1,19 @@ +{ + "name": "pubsweet-components-faraday", + "version": "0.0.1", + "main": "src", + "license": "MIT", + "dependencies": { + "@pubsweet/ui": "^0.1.1", + "moment": "^2.20.1", + "prop-types": "^15.5.10", + "react": "^15.6.1", + "react-dnd": "^2.5.4", + "react-dnd-html5-backend": "^2.5.4", + "react-dom": "^15.6.1", + "react-router-dom": "^4.2.2", + "recompose": "^0.26.0", + "redux": "^3.6.0", + "redux-form": "^7.0.3" + } +} diff --git a/packages/component-wizard/src/components/AuthorList/Author.js b/packages/components-faraday/src/components/AuthorList/Author.js similarity index 100% rename from packages/component-wizard/src/components/AuthorList/Author.js rename to packages/components-faraday/src/components/AuthorList/Author.js diff --git a/packages/component-wizard/src/components/AuthorList/AuthorAdder.js b/packages/components-faraday/src/components/AuthorList/AuthorAdder.js similarity index 97% rename from packages/component-wizard/src/components/AuthorList/AuthorAdder.js rename to packages/components-faraday/src/components/AuthorList/AuthorAdder.js index be4ffcb7fe54d503fceac1a586c721effafe38df..9c0b574daca8ad5fee00eb81e2a21f0563093f86 100644 --- a/packages/component-wizard/src/components/AuthorList/AuthorAdder.js +++ b/packages/components-faraday/src/components/AuthorList/AuthorAdder.js @@ -72,10 +72,8 @@ export default compose( if (!admin) { return { initialValues: { - author: { - email, - firstName: username, - }, + email, + firstName: username, }, } } diff --git a/packages/component-wizard/src/components/AuthorList/AuthorEditor.js b/packages/components-faraday/src/components/AuthorList/AuthorEditor.js similarity index 100% rename from packages/component-wizard/src/components/AuthorList/AuthorEditor.js rename to packages/components-faraday/src/components/AuthorList/AuthorEditor.js diff --git a/packages/component-wizard/src/components/AuthorList/AuthorList.js b/packages/components-faraday/src/components/AuthorList/AuthorList.js similarity index 97% rename from packages/component-wizard/src/components/AuthorList/AuthorList.js rename to packages/components-faraday/src/components/AuthorList/AuthorList.js index a542d73b0e469206ecfe437c02ec09d36499d41f..7a959a6f9423472fa2ff1960ca2d3f172890b28e 100644 --- a/packages/component-wizard/src/components/AuthorList/AuthorList.js +++ b/packages/components-faraday/src/components/AuthorList/AuthorList.js @@ -10,6 +10,7 @@ import { withState, } from 'recompose' import { change } from 'redux-form' +import { SortableList } from 'pubsweet-components-faraday/src/components' import { addAuthor, @@ -18,8 +19,6 @@ import { moveAuthors, } from '../../redux/authors' -import SortableList from '../SortableList' - import Author from './Author' import StaticList from './StaticList' import AuthorAdder from './AuthorAdder' @@ -66,7 +65,6 @@ const Authors = ({ <SortableList dragHandle={DragHandle} dropItem={dropItem} - editedAuthor={editedAuthor} items={authors} listItem={Author} moveItem={moveAuthor} diff --git a/packages/component-wizard/src/components/AuthorList/AuthorList.local.scss b/packages/components-faraday/src/components/AuthorList/AuthorList.local.scss similarity index 100% rename from packages/component-wizard/src/components/AuthorList/AuthorList.local.scss rename to packages/components-faraday/src/components/AuthorList/AuthorList.local.scss diff --git a/packages/component-wizard/src/components/AuthorList/FormItems.js b/packages/components-faraday/src/components/AuthorList/FormItems.js similarity index 100% rename from packages/component-wizard/src/components/AuthorList/FormItems.js rename to packages/components-faraday/src/components/AuthorList/FormItems.js diff --git a/packages/component-wizard/src/components/AuthorList/FormItems.local.scss b/packages/components-faraday/src/components/AuthorList/FormItems.local.scss similarity index 100% rename from packages/component-wizard/src/components/AuthorList/FormItems.local.scss rename to packages/components-faraday/src/components/AuthorList/FormItems.local.scss diff --git a/packages/component-wizard/src/components/AuthorList/StaticList.js b/packages/components-faraday/src/components/AuthorList/StaticList.js similarity index 96% rename from packages/component-wizard/src/components/AuthorList/StaticList.js rename to packages/components-faraday/src/components/AuthorList/StaticList.js index a0da937295e6a75cb60b8b0a28f4c44e42ff2b8c..ba44a4c67595fbd2fd5f58a6a7212553594cf2d8 100644 --- a/packages/component-wizard/src/components/AuthorList/StaticList.js +++ b/packages/components-faraday/src/components/AuthorList/StaticList.js @@ -10,6 +10,7 @@ export default ({ editComponent, setAuthorEdit, parseAuthorType, + ...rest }) => ( <div> {authors.map( @@ -32,6 +33,7 @@ export default ({ countryParser={countryParser} parseAuthorType={parseAuthorType} removeAuthor={removeAuthor} + {...rest} /> ), )} diff --git a/packages/component-wizard/src/components/AuthorList/index.js b/packages/components-faraday/src/components/AuthorList/index.js similarity index 100% rename from packages/component-wizard/src/components/AuthorList/index.js rename to packages/components-faraday/src/components/AuthorList/index.js diff --git a/packages/component-wizard/src/components/SortableList.js b/packages/components-faraday/src/components/SortableList/SortableList.js similarity index 91% rename from packages/component-wizard/src/components/SortableList.js rename to packages/components-faraday/src/components/SortableList/SortableList.js index b52ad3f7a4b8d487771521c18ba68e4a9c000a70..86f710b6db530e668b1454aab6ea5ca982a39685 100644 --- a/packages/component-wizard/src/components/SortableList.js +++ b/packages/components-faraday/src/components/SortableList/SortableList.js @@ -1,7 +1,8 @@ import React from 'react' import { compose } from 'recompose' import { findDOMNode } from 'react-dom' -import { DragSource, DropTarget } from 'react-dnd' +import HTML5Backend from 'react-dnd-html5-backend' +import { DragSource, DropTarget, DragDropContext } from 'react-dnd' const itemSource = { beginDrag(props) { @@ -36,8 +37,8 @@ const itemTarget = { } monitor.getItem().index = hoverIndex }, - drop({ dropItem }) { - if (dropItem && typeof dropItem === 'function') dropItem() + drop({ dropItem, index }) { + if (dropItem && typeof dropItem === 'function') dropItem(index) }, } @@ -47,7 +48,6 @@ const Item = ({ connectDropTarget, listItem, dragHandle, - isEditing, ...rest }) => dragHandle @@ -96,7 +96,6 @@ const SortableList = ({ <DecoratedItem dragHandle={dragHandle} index={i} - isEditing={rest.editedAuthor !== -1} key={item.name || Math.random()} listItem={listItem} moveItem={moveItem} @@ -125,4 +124,4 @@ SortableList.moveItem = (items, dragIndex, hoverIndex) => { ] } -export default SortableList +export default DragDropContext(HTML5Backend)(SortableList) diff --git a/packages/components-faraday/src/components/SortableList/SortableList.md b/packages/components-faraday/src/components/SortableList/SortableList.md new file mode 100644 index 0000000000000000000000000000000000000000..e6da217d33f181dc1fca556935a0f214ff3aeb2d --- /dev/null +++ b/packages/components-faraday/src/components/SortableList/SortableList.md @@ -0,0 +1,76 @@ +A sortable list implemented with `react-dnd`. + +## Props + +| Prop | Description | Required | Default | +| :--------: | :------------------------------------------------------------------------------------------------------------------------------------------: | :------: | :-------------------: | +| items | The items of the sortable list. | true | [] | +| listItem | A React component that will be rendered for each item of the list. Receives `isDragging`, `isOver` and all other props from the items array. | true | none | +| moveItem | Function to be called when moving an item through the list. SortableList will provide the dragIndex of hoverIndex of the items. | true | SortableList.moveItem | +| dragHandle | A React component for the drag handle. If not present, the whole item can be dragged. | false | none | +| dropItem | Function to be called when dropping an item. The index of the dragged item is passed. | false | none | + +## Usage + +### Pass in a list of users + +```js +const items = [ + {firstName: 'John', lastName: 'Doe'}, + {firstName: 'Michael', lastName: 'Jackson'}, + {firstName: 'David', lastName: 'Blaine'}, +] + +const Item = ({ isOver, isDragging, ...rest }) => + <div>`${rest.firstName} ${rest.lastName}`</div> + +<SortableList + items={items} + listItem={Item} + moveItem={(dragIndex, hoverIndex) => change items} + /> +``` + +### With custom drag handle +```js +const DragHandle = () => <div>Drag me!</div> + +const ItemWithDragHandle = ({ dragHandle, ...rest }) => <div> + {dragHandle} + <span>Rest of the content.</span> + </div> + +<SortableList + ... + listItem={ItemWithDragHandle} + dragHandle={DragHandle} + ... + /> +``` + +### How to move items around + +To move items of the parent container whenever `moveItem` function is called we can use the `SortableList.moveItem` helper. More info in the example below. + +```js +const Container = ({ moveItem, items }) => <div> + ... + <SortableList + items={items} + listItem={Item} + moveItem={moveItem} + /> + ... + </div> +``` +Enhanced using recompose +```js +const MoveExample = compose( + withState('items', 'setItems', [{name: 'John'}, {name: 'Nancy'}, {name: 'Adam'}]), + withHandlers({ + moveItem: ({ setItems, items }) => (dragIndex, hoverIndex) => { + setItems(prevItems => SortableList.moveItem(prevItems, dragIndex, hoverIndex)) + } + }) +)(Container) +``` diff --git a/packages/components-faraday/src/components/UIComponents/ConfirmationPage.js b/packages/components-faraday/src/components/UIComponents/ConfirmationPage.js new file mode 100644 index 0000000000000000000000000000000000000000..35cd479808558baf671252d8fa3227658c906add --- /dev/null +++ b/packages/components-faraday/src/components/UIComponents/ConfirmationPage.js @@ -0,0 +1,63 @@ +import React from 'react' +import classnames from 'classnames' +import { compose } from 'recompose' +import { connect } from 'react-redux' +import { Button } from '@pubsweet/ui' +import { get, isEmpty } from 'lodash' +import { withJournal } from 'xpub-journal' +import { getFragmentAuthors } from 'pubsweet-components-faraday/src/redux/authors' + +import classes from './UIComponents.local.scss' + +const ConfirmationPage = ({ + journal, + authors = [], + location: { state }, + history, +}) => { + const email = get(authors.find(a => a.isCorresponding), 'email') + return ( + <div className={classnames(classes.container)}> + {isEmpty(state) ? ( + <h2>Thank you for you submission</h2> + ) : ( + <div> + <h2>Thank You for Submitting Your Manuscript</h2> + <p> + Your manuscript has been successfully submitted to{' '} + <b>{journal.metadata.nameText}</b> and assigned the manuscript ID{' '} + <b> + {' '} + <a + href={`/projects/${state.project}/versions/${ + state.version + }/manuscript`} + > + {state.project} + </a> + </b>. + </p> + <p> + An acknowledgement email will be sent to {email} when our system has + finished processing the submission. At that point, you will be able + to track the status of your submission. Please note, this may take a + few minutes. + </p> + <p> + {`You can keep track of your submission's progress on your dashboard.`} + </p> + <Button onClick={() => history.push('/')} primary> + Go to Dashboard + </Button> + </div> + )} + </div> + ) +} + +export default compose( + withJournal, + connect((state, { location: { state: locationState } }) => ({ + authors: getFragmentAuthors(state, get(locationState, 'version')), + })), +)(ConfirmationPage) diff --git a/packages/component-wizard/src/components/Dropdown.js b/packages/components-faraday/src/components/UIComponents/Dropdown.js similarity index 100% rename from packages/component-wizard/src/components/Dropdown.js rename to packages/components-faraday/src/components/UIComponents/Dropdown.js diff --git a/packages/component-wizard/src/components/Dropdown.local.scss b/packages/components-faraday/src/components/UIComponents/Dropdown.local.scss similarity index 100% rename from packages/component-wizard/src/components/Dropdown.local.scss rename to packages/components-faraday/src/components/UIComponents/Dropdown.local.scss diff --git a/packages/xpub-faraday/app/config/Logo.js b/packages/components-faraday/src/components/UIComponents/Logo.js similarity index 100% rename from packages/xpub-faraday/app/config/Logo.js rename to packages/components-faraday/src/components/UIComponents/Logo.js diff --git a/packages/components-faraday/src/components/UIComponents/NotFound.js b/packages/components-faraday/src/components/UIComponents/NotFound.js new file mode 100644 index 0000000000000000000000000000000000000000..f0c04c2e25457aeac3160e029e81d6b83e6b48de --- /dev/null +++ b/packages/components-faraday/src/components/UIComponents/NotFound.js @@ -0,0 +1,23 @@ +import React from 'react' +import { Icon } from '@pubsweet/ui' +import classnames from 'classnames' + +import classes from './UIComponents.local.scss' + +const NotFound = ({ history }) => ( + <div className={classnames(classes.container)}> + <div> + <Icon size={32}>cloud-off</Icon> + </div> + <h2>The page cannot be found</h2> + <h3> + The page you are looking for might have been removed, had its name + changed, or is temporarily unavailable. + </h3> + <a href="#" onClick={history.goBack}> + Back + </a> + </div> +) + +export default NotFound diff --git a/packages/components-faraday/src/components/UIComponents/UIComponents.local.scss b/packages/components-faraday/src/components/UIComponents/UIComponents.local.scss new file mode 100644 index 0000000000000000000000000000000000000000..10255c4b467b541296f7332916e9f95fe0733440 --- /dev/null +++ b/packages/components-faraday/src/components/UIComponents/UIComponents.local.scss @@ -0,0 +1,9 @@ +.container { + margin: 0 auto; + text-align: center; + width: 70vw; + + a { + color: black; + } +} diff --git a/packages/components-faraday/src/components/UIComponents/index.js b/packages/components-faraday/src/components/UIComponents/index.js new file mode 100644 index 0000000000000000000000000000000000000000..8c2c826a28aa0777ba243088dec43647bbc965e4 --- /dev/null +++ b/packages/components-faraday/src/components/UIComponents/index.js @@ -0,0 +1,2 @@ +export { default as Logo } from './Logo' +export { default as Dropdown } from './Dropdown' diff --git a/packages/components-faraday/src/components/index.js b/packages/components-faraday/src/components/index.js new file mode 100644 index 0000000000000000000000000000000000000000..9a7465c876911d5e084438021aafb74431583ce4 --- /dev/null +++ b/packages/components-faraday/src/components/index.js @@ -0,0 +1,4 @@ +export { default as SortableList } from './SortableList/SortableList' +export { default as AuthorList } from './AuthorList/AuthorList' + +export { Dropdown, Logo } from './UIComponents' diff --git a/packages/components-faraday/src/index.js b/packages/components-faraday/src/index.js new file mode 100644 index 0000000000000000000000000000000000000000..b6f834c32bc4984c034dcb5aa84d084c5aaf27eb --- /dev/null +++ b/packages/components-faraday/src/index.js @@ -0,0 +1,8 @@ +module.exports = { + client: { + components: [() => require('./components')], + reducers: { + authors: () => require('./redux/authors').default, + }, + }, +} diff --git a/packages/component-wizard/src/redux/authors.js b/packages/components-faraday/src/redux/authors.js similarity index 100% rename from packages/component-wizard/src/redux/authors.js rename to packages/components-faraday/src/redux/authors.js diff --git a/packages/components-faraday/src/redux/index.js b/packages/components-faraday/src/redux/index.js new file mode 100644 index 0000000000000000000000000000000000000000..d080497581f9a23bcc33b4fe5f80d14f84a2a034 --- /dev/null +++ b/packages/components-faraday/src/redux/index.js @@ -0,0 +1 @@ +export { default as authors } from './authors' diff --git a/packages/components-faraday/webpack.config.js b/packages/components-faraday/webpack.config.js new file mode 100644 index 0000000000000000000000000000000000000000..4aa149ad2cbf750326137fc79ccd7e7685271ad3 --- /dev/null +++ b/packages/components-faraday/webpack.config.js @@ -0,0 +1,3 @@ +const webpackConfig = require('xpub-styleguide/src/webpack-config') + +module.exports = webpackConfig(__dirname) diff --git a/packages/xpub-faraday/app/config/journal/metadata.js b/packages/xpub-faraday/app/config/journal/metadata.js index a0dbaa538b1525826b7c0259d497302ef43e9516..f099501bf61de0aa128bbd2094665c4dfd1defb2 100644 --- a/packages/xpub-faraday/app/config/journal/metadata.js +++ b/packages/xpub-faraday/app/config/journal/metadata.js @@ -1,8 +1,9 @@ import React from 'react' -import Logo from '../Logo' +import { Logo } from 'pubsweet-components-faraday/src/components' export default { issn: '2474-7394', name: <Logo srcUrl="/assets/hindawi-logo.png" />, logo: '/assets/hindawi-logo.png', + nameText: 'Faraday Journal', } diff --git a/packages/xpub-faraday/app/config/journal/submit-wizard.js b/packages/xpub-faraday/app/config/journal/submit-wizard.js index 8a75432e4d84902eb7cf61f216e0194c5a2e693f..a235a4a7c12d0741e233e98c25f224ce80123809 100644 --- a/packages/xpub-faraday/app/config/journal/submit-wizard.js +++ b/packages/xpub-faraday/app/config/journal/submit-wizard.js @@ -9,7 +9,7 @@ import { } from '@pubsweet/ui' import uploadFileFn from 'xpub-upload' import { required, minChars, minSize } from 'xpub-validators' -import { AuthorList } from 'pubsweet-component-wizard/src/components/AuthorList' +import { AuthorList } from 'pubsweet-components-faraday/src/components' import { declarations } from './' import issueTypes from './issues-types' @@ -49,6 +49,7 @@ const uploadFile = input => uploadFileFn(input) export default { showProgress: true, formSectionKeys: ['metadata', 'declarations', 'conflicts', 'notes', 'files'], + submissionRedirect: '/confirmation-page', dispatchFunctions: [uploadFile], steps: [ { diff --git a/packages/xpub-faraday/app/routes.js b/packages/xpub-faraday/app/routes.js index 0faa342e6fd6458e78f2a08d27cc5da1ab52da68..36a635a46bcf18cea3dfc0711a2150609808eeaf 100644 --- a/packages/xpub-faraday/app/routes.js +++ b/packages/xpub-faraday/app/routes.js @@ -1,7 +1,5 @@ import React from 'react' -import { Route } from 'react-router-dom' -import { DragDropContext } from 'react-dnd' -import HTML5Backend from 'react-dnd-html5-backend' +import { Route, Switch } from 'react-router-dom' import App from 'pubsweet-component-xpub-app/src/components' @@ -14,19 +12,35 @@ import { import DashboardPage from 'pubsweet-component-xpub-dashboard/src/components/DashboardPage' import WizardPage from 'pubsweet-component-wizard/src/components/WizardPage' +import ManuscriptPage from 'pubsweet-component-xpub-manuscript/src/components/ManuscriptPage' +import ConfirmationPage from 'pubsweet-components-faraday/src/components/UIComponents/ConfirmationPage' +import NotFound from 'pubsweet-components-faraday/src/components/UIComponents/NotFound' const Routes = () => ( <App> - <Route component={LoginPage} exact path="/login" /> - <Route component={SignupPage} exact path="/signup" /> - <PrivateRoute component={DashboardPage} exact path="/" /> - <PrivateRoute component={LogoutPage} exact path="/logout" /> - <PrivateRoute - component={WizardPage} - exact - path="/projects/:project/versions/:version/submit" - /> + <Switch> + <Route component={LoginPage} exact path="/login" /> + <Route component={SignupPage} exact path="/signup" /> + <PrivateRoute component={DashboardPage} exact path="/" /> + <PrivateRoute + component={ConfirmationPage} + exact + path="/confirmation-page" + /> + <PrivateRoute component={LogoutPage} exact path="/logout" /> + <PrivateRoute + component={WizardPage} + exact + path="/projects/:project/versions/:version/submit" + /> + <PrivateRoute + component={ManuscriptPage} + exact + path="/projects/:project/versions/:version/manuscript" + /> + <Route component={NotFound} /> + </Switch> </App> ) -export default DragDropContext(HTML5Backend)(Routes) +export default Routes diff --git a/packages/xpub-faraday/config/components.json b/packages/xpub-faraday/config/components.json index d2f94630a129aac037beb019e7f000121cd6c0c1..0868d8175764a5d690eb3d27b3afa188bb22f895 100644 --- a/packages/xpub-faraday/config/components.json +++ b/packages/xpub-faraday/config/components.json @@ -4,5 +4,6 @@ "pubsweet-component-xpub-dashboard", "xpub-faraday-server", "pubsweet-component-ink-backend", - "pubsweet-component-wizard" + "pubsweet-component-wizard", + "pubsweet-components-faraday" ] diff --git a/packages/xpub-faraday/webpack/babel-includes.js b/packages/xpub-faraday/webpack/babel-includes.js index cf4c70690af26d8fec6abcbeb6b3ce54b5be6963..3a619ed559a51e70edc6d8501083bb4353fc7790 100644 --- a/packages/xpub-faraday/webpack/babel-includes.js +++ b/packages/xpub-faraday/webpack/babel-includes.js @@ -8,6 +8,7 @@ module.exports = [ /pubsweet-[^/]+\/src/, /xpub-[^/]+\/src/, /component-[^/]+\/src/, + /components-[^/]+\/src/, /wax-[^/]+\/src/, /@pubsweet\/[^/]+\/src/, ] diff --git a/yarn.lock b/yarn.lock index 978b7a328d4e6af8840c6568c9e5e9cfb67a36a8..653131550f0125810372583c353dda187e41f606 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6599,7 +6599,7 @@ modify-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2" -moment@2.x.x, moment@^2.18.1, moment@^2.6.0: +moment@2.x.x, moment@^2.18.1, moment@^2.20.1, moment@^2.6.0: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd"