diff --git a/packages/component-faraday-ui/src/AuthorCard.js b/packages/component-faraday-ui/src/AuthorCard.js index 985084779395eb627c34d92c1b2270a02b692aee..51230df5157b402f30fba0cf0be3e5399d116ba9 100644 --- a/packages/component-faraday-ui/src/AuthorCard.js +++ b/packages/component-faraday-ui/src/AuthorCard.js @@ -84,6 +84,7 @@ const AuthorEdit = ({ author, editMode, listIndex, + isFetching, handleSubmit, toggleEditMode, }) => ( @@ -91,6 +92,7 @@ const AuthorEdit = ({ <AuthorTitle editMode={editMode} isCorresponding={author.isCorresponding} + isFetching={isFetching} isSubmitting={author.isSubmitting} listIndex={listIndex} saveChanges={handleSubmit} @@ -162,15 +164,16 @@ const Author = ({ author, listIndex, toggleEditMode }) => ( const AuthorCard = ({ item, + isOver, editMode, dragHandle, toggleEdit, + isDragging, + isFetching, index = null, saveNewAuthor, editExistingAuthor, authorEditorSubmit, - isOver, - isDragging, }) => ( <Root isDragging={isDragging} isOver={isOver}> {!editMode && @@ -180,6 +183,7 @@ const AuthorCard = ({ author={item} editExistingAuthor={editExistingAuthor} editMode={editMode} + isFetching={isFetching} listIndex={index} onSubmit={authorEditorSubmit} saveNewAuthor={saveNewAuthor} diff --git a/packages/component-faraday-ui/src/DownloadZipFiles.js b/packages/component-faraday-ui/src/DownloadZipFiles.js index 3244bb90c623ccfecf7441f86da5a76a1733214d..8e5d34d7c4251e31d7acc0efc995e8562554d40d 100644 --- a/packages/component-faraday-ui/src/DownloadZipFiles.js +++ b/packages/component-faraday-ui/src/DownloadZipFiles.js @@ -1,11 +1,6 @@ import React from 'react' -import { connect } from 'react-redux' import { Spinner } from '@pubsweet/ui' import { compose, withState } from 'recompose' -import { - getUserToken, - currentUserIsReviewer, -} from 'pubsweet-component-faraday-selectors' import { Item } from 'pubsweet-component-faraday-ui' import { withZipDownload } from './helpers' @@ -22,10 +17,6 @@ const DownloadZipFiles = ({ disabled, fetching, children, downloadFiles }) => ( ) export default compose( - connect((state, { collectionId }) => ({ - token: getUserToken(state), - isReviewer: currentUserIsReviewer(state, collectionId), - })), withState('fetching', 'setFetching', false), withZipDownload, )(DownloadZipFiles) diff --git a/packages/component-faraday-ui/src/DownloadZipFiles.md b/packages/component-faraday-ui/src/DownloadZipFiles.md index 82263d4563040a93ce1a5330497927de6dbd5bb9..05fe5d1b990eff67b4934f763aa4838aaab85467 100644 --- a/packages/component-faraday-ui/src/DownloadZipFiles.md +++ b/packages/component-faraday-ui/src/DownloadZipFiles.md @@ -4,10 +4,13 @@ Download manuscript package as zip const collection = {id: '', customId: ''}; const fragment = {id: ''}; + <DownloadZipFiles archiveName={`ID-${collection.customId}`} collectionId={collection.id} fragmentId={fragment.id} + isReviewer + token="abc-123" > <div>Download</div> </DownloadZipFiles> diff --git a/packages/component-faraday-ui/src/ManuscriptVersion.js b/packages/component-faraday-ui/src/ManuscriptVersion.js index f5d8d5493279292c9dc0b0565f3586d233e820d1..33de748b0e212aa6acd947fafa34550f3f9ba593 100644 --- a/packages/component-faraday-ui/src/ManuscriptVersion.js +++ b/packages/component-faraday-ui/src/ManuscriptVersion.js @@ -1,7 +1,6 @@ import React from 'react' import { get } from 'lodash' import { Menu } from '@pubsweet/ui' -import { withRouter } from 'react-router-dom' import { compose, withHandlers, withProps } from 'recompose' const ManuscriptVersion = ({ @@ -23,7 +22,6 @@ const ManuscriptVersion = ({ ) export default compose( - withRouter, withProps(({ collection = {} }) => ({ fragments: get(collection, 'fragments', []), })), diff --git a/packages/component-faraday-ui/src/ManuscriptVersion.md b/packages/component-faraday-ui/src/ManuscriptVersion.md index d740afec5d1308b0bdb3482d46a8dd7e4f7880ad..00e12ce334886136eb8308dd2c6b5fdc7a018e68 100644 --- a/packages/component-faraday-ui/src/ManuscriptVersion.md +++ b/packages/component-faraday-ui/src/ManuscriptVersion.md @@ -3,11 +3,17 @@ Manuscript version component ```js const history = { - push: () => alert('go to version') + push: v => console.log('go to version -> ', v) }; const fragment={}; -const collection={}; +const collection={ + fragments: ['1','2'], +}; -<ManuscriptVersion collection={collection} fragment={fragment} /> +<ManuscriptVersion + collection={collection} + history={history} + fragment={fragment} + /> ``` diff --git a/packages/component-faraday-ui/src/PreviewFile.md b/packages/component-faraday-ui/src/PreviewFile.md index 4bf363a9d882001409a5a754f456c43fcf0f622c..163e3ea0f26c8878f8345048dd5bac08367d3d92 100644 --- a/packages/component-faraday-ui/src/PreviewFile.md +++ b/packages/component-faraday-ui/src/PreviewFile.md @@ -1,7 +1,9 @@ Preview file in browser if possible ```js -const file = {}; +const file = { + name: 'cocojambo.pdf' +}; <PreviewFile file={file} /> ``` diff --git a/packages/component-faraday-ui/src/WizardAuthors.js b/packages/component-faraday-ui/src/WizardAuthors.js index b9fd96d6eb6caa0bab0b6e2465459abe35a9a346..caa95bd1e398562f89d3a5179244d52e0e708e42 100644 --- a/packages/component-faraday-ui/src/WizardAuthors.js +++ b/packages/component-faraday-ui/src/WizardAuthors.js @@ -1,6 +1,6 @@ import React, { Fragment } from 'react' -import { omit } from 'lodash' import styled from 'styled-components' +import { omit, isBoolean } from 'lodash' import { th } from '@pubsweet/ui-toolkit' import { compose, withState, withHandlers } from 'recompose' @@ -15,6 +15,27 @@ import { SortableList, } from './' +const castToBool = author => ({ + ...author, + isCorresponding: isBoolean(author.isCorresponding) && author.isCorresponding, +}) + +const parseEditedAuthors = (editedAuthor, authors) => { + const newAuthor = castToBool(editedAuthor) + + return authors.map( + a => + a.id === newAuthor.id + ? newAuthor + : { + ...a, + isCorresponding: newAuthor.isCorresponding + ? false + : a.isCorresponding, + }, + ) +} + const WizardAuthors = ({ error, moveAuthor, @@ -94,9 +115,8 @@ export default compose( setFormAuthors([...authors.filter(a => a.id !== 'newAuthor'), author]) }, editExistingAuthor: ({ authors, setFormAuthors }) => editedAuthor => { - setFormAuthors( - authors.map(a => (a.id === editedAuthor.id ? editedAuthor : a)), - ) + const newAuthors = parseEditedAuthors(editedAuthor, authors) + setFormAuthors(newAuthors) }, }), withHandlers({ @@ -112,7 +132,7 @@ export default compose( addAuthor( { ...omit(values, 'id'), - isSubmitting: authors.length === 0, + isSubmitting: authors.length === 1, }, project.id, version.id, diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js index 5ffa60c3dbc7dc64255862afefaab56ab1227258..ba3190e450b131c1e7a15d397502a421d2812891 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.js @@ -1,15 +1,7 @@ import React from 'react' import { get } from 'lodash' -import { connect } from 'react-redux' import { DateParser } from '@pubsweet/ui' -import { withRouter } from 'react-router-dom' import { compose, withHandlers } from 'recompose' -import { - canMakeDecision, - canMakeRecommendation, - canEditManuscript, - canOverrideTechnicalChecks, -} from 'pubsweet-component-faraday-selectors/src' import { Row, @@ -17,20 +9,21 @@ import { Text, ActionLink, IconButton, - DownloadZipFiles, PreviewFile, + DownloadZipFiles, ManuscriptVersion, } from 'pubsweet-component-faraday-ui' const ManuscriptDetailsTop = ({ history, - getSignedUrl, - collection = {}, - fragment = {}, goToEdit, + getSignedUrl, canEditManuscript, goToTechnicalCheck, canOverrideTechChecks, + fragment = {}, + collection = {}, + currentUser: { isReviewer, token }, }) => ( <Row alignItems="center" mb={1}> <Item alignItems="center" justify="flex-start"> @@ -69,25 +62,24 @@ const ManuscriptDetailsTop = ({ archiveName={`ID-${collection.customId}`} collectionId={collection.id} fragmentId={fragment.id} + isReviewer={isReviewer} + token={token} > <IconButton icon="download" iconSize={2} mr={3} secondary /> </DownloadZipFiles> <DateParser durationThreshold={0} timestamp={fragment.submitted || ''}> {timestamp => <Text mr={1}>Updated on {timestamp}</Text>} </DateParser> - <ManuscriptVersion collection={collection} fragment={fragment} /> + <ManuscriptVersion + collection={collection} + fragment={fragment} + history={history} + /> </Item> </Row> ) export default compose( - withRouter, - connect((state, { collection, fragment }) => ({ - canMakeDecision: canMakeDecision(state, collection, fragment), - canMakeRecommendation: canMakeRecommendation(state, collection, fragment), - canEditManuscript: canEditManuscript(state, collection, fragment), - canOverrideTechChecks: canOverrideTechnicalChecks(state, collection), - })), withHandlers({ goToEdit: ({ history }) => (collection, fragment) => () => { history.push( diff --git a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md index f4a1a46f7c94ed7eaec8a46e95e7af124af4860c..83b26fc585d2bd7fa43dc8a2e546e57bf3bda120 100644 --- a/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md +++ b/packages/component-faraday-ui/src/manuscriptDetails/ManuscriptDetailsTop.md @@ -6,10 +6,17 @@ const history = { }; const fragment={}; const collection={}; +const currentUser = { + isReviewer: true, + token: 'abc-123', +}; <ManuscriptDetailsTop collection={collection} + currentUser={currentUser} fragment={fragment} history={history} + canOverrideTechChecks + canEditManuscript /> ``` diff --git a/packages/component-manuscript/src/components/ManuscriptLayout.js b/packages/component-manuscript/src/components/ManuscriptLayout.js index 02f391c2d6fffc547f50901a81aed7d9bce58aa5..037e692e0e83631cdc689f4f96dc583f61e9cf83 100644 --- a/packages/component-manuscript/src/components/ManuscriptLayout.js +++ b/packages/component-manuscript/src/components/ManuscriptLayout.js @@ -13,25 +13,28 @@ const ManuscriptLayout = ({ currentUser, editorInChief, canMakeRevision, - editorialRecommendations, hasResponseToReviewers, + editorialRecommendations, journal = {}, - project = {}, - version = {}, + collection = {}, + fragment = {}, + permissions, }) => ( <Root> - {!isEmpty(project) && !isEmpty(version) ? ( + {!isEmpty(collection) && !isEmpty(fragment) ? ( <Fragment> <ManuscriptDetailsTop - collection={project} - fragment={version} + collection={collection} + currentUser={currentUser} + fragment={fragment} getSignedUrl={getSignedUrl} history={history} + {...permissions} /> <ManuscriptHeader - collection={project} + collection={collection} editorInChief={editorInChief} - fragment={version} + fragment={fragment} journal={journal} /> </Fragment> diff --git a/packages/component-manuscript/src/components/ManuscriptPage.js b/packages/component-manuscript/src/components/ManuscriptPage.js index b09fe2d5c3a1b7491b7ad99e394f68cb0116f7af..88f14ae12f0b56c6cf00ef861628351e56b5f41e 100644 --- a/packages/component-manuscript/src/components/ManuscriptPage.js +++ b/packages/component-manuscript/src/components/ManuscriptPage.js @@ -30,7 +30,15 @@ import { getHandlingEditors, selectHandlingEditors, } from 'pubsweet-components-faraday/src/redux/editors' -import { canMakeRevision } from 'pubsweet-component-faraday-selectors/src' +import { + getUserToken, + canMakeRevision, + canMakeDecision, + canEditManuscript, + canMakeRecommendation, + currentUserIsReviewer, + canOverrideTechnicalChecks, +} from 'pubsweet-component-faraday-selectors' import ManuscriptLayout from './ManuscriptLayout' import { parseSearchParams, redirectToError } from './utils' @@ -49,8 +57,8 @@ export default compose( currentUser: selectCurrentUser(state), handlingEditors: selectHandlingEditors(state), hasManuscriptFailure: hasManuscriptFailure(state), - version: selectFragment(state, match.params.version), - project: selectCollection(state, match.params.project), + fragment: selectFragment(state, match.params.version), + collection: selectCollection(state, match.params.project), editorialRecommendations: selectEditorialRecommendations( state, match.params.version, @@ -66,11 +74,22 @@ export default compose( updateVersion: actions.updateFragment, }, ), - connect((state, { project, version }) => ({ - canMakeRevision: canMakeRevision(state, project, version), + connect((state, { currentUser, collection, fragment }) => ({ + currentUser: { + ...currentUser, + token: getUserToken(state), + isReviewer: currentUserIsReviewer(state), + }, + canMakeRevision: canMakeRevision(state, collection, fragment), + permissions: { + canMakeDecision: canMakeDecision(state, collection, fragment), + canEditManuscript: canEditManuscript(state, collection, fragment), + canOverrideTechChecks: canOverrideTechnicalChecks(state, collection), + canMakeRecommendation: canMakeRecommendation(state, collection, fragment), + }, })), - ConnectPage(({ currentUser, handlingEditors, project }) => { - const he = get(project, 'handlingEditor') + ConnectPage(({ currentUser, handlingEditors, collection }) => { + const he = get(collection, 'handlingEditor') if ( !he && !handlingEditors.length && @@ -81,9 +100,9 @@ export default compose( return [] }), withHandlers({ - updateManuscript: ({ updateVersion, project, version }) => data => - updateVersion(project, { - id: version.id, + updateManuscript: ({ updateVersion, collection, fragment }) => data => + updateVersion(collection, { + id: fragment.id, ...data, }), setEditorInChief: ({ setEiC }) => eic => { @@ -130,9 +149,9 @@ export default compose( ) }, }), - withProps(({ version }) => ({ + withProps(({ fragment }) => ({ hasResponseToReviewers: - !isEmpty(get(version, 'files.responseToReviewers')) || - get(version, 'commentsToReviewers'), + !isEmpty(get(fragment, 'files.responseToReviewers')) || + get(fragment, 'commentsToReviewers'), })), )(ManuscriptLayout) diff --git a/packages/component-wizard/src/components/StepThree.js b/packages/component-wizard/src/components/StepThree.js index 344f00681324767612a4e4911f5c65a5cb48c5cd..b64c456455892699fde590e2d42bdb05ed5abf20 100644 --- a/packages/component-wizard/src/components/StepThree.js +++ b/packages/component-wizard/src/components/StepThree.js @@ -1,6 +1,7 @@ import React, { Fragment } from 'react' import { get } from 'lodash' import { Field } from 'redux-form' +import styled from 'styled-components' import { H2, Icon } from '@pubsweet/ui' import { Row, Text, WizardFiles } from 'pubsweet-component-faraday-ui' @@ -54,7 +55,7 @@ const StepThree = ({ export default StepThree // #region styles -const CustomH2 = H2.extend` +const CustomH2 = styled(H2)` margin: 0; ` // #endregion diff --git a/packages/component-wizard/src/components/SubmissionWizard.js b/packages/component-wizard/src/components/SubmissionWizard.js index fa83662dc92e5328269e49d7f21c73a79c553bf7..33cf84cff81ee5fbbdc1c94671086231741af789 100644 --- a/packages/component-wizard/src/components/SubmissionWizard.js +++ b/packages/component-wizard/src/components/SubmissionWizard.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { Fragment } from 'react' import { get } from 'lodash' import { connect } from 'react-redux' import styled from 'styled-components' @@ -7,8 +7,8 @@ import { actions } from 'pubsweet-client' import { withJournal } from 'xpub-journal' import { ConnectPage } from 'xpub-connect' import { DragDropContext } from 'react-dnd' -import { Button, Steps } from '@pubsweet/ui' import HTML5Backend from 'react-dnd-html5-backend' +import { Button, Spinner, Steps } from '@pubsweet/ui' import { selectCollection, selectFragment } from 'xpub-selectors' import { compose, @@ -28,11 +28,15 @@ import { getFormSyncErrors, change as changeForm, } from 'redux-form' -import { addAuthor } from 'pubsweet-components-faraday/src/redux/authors' +import { + addAuthor, + getAuthorFetching, +} from 'pubsweet-components-faraday/src/redux/authors' import { uploadFile, deleteFile, getSignedUrl, + getFileFetching, } from 'pubsweet-components-faraday/src/redux/files' import { wizardSteps } from './' @@ -50,6 +54,8 @@ const Wizard = ({ isFirstStep, handleSubmit, getButtonText, + isFilesFetching, + isAuthorsFetching, journal: { manuscriptTypes = [] }, ...rest }) => ( @@ -63,21 +69,27 @@ const Wizard = ({ <StepRoot className="wizard-step"> {wizardSteps[step].component({ manuscriptTypes, ...rest })} <Row justify="center" mt={2}> - {!isFirstStep && ( - <Button - data-test="submission-back" - mr={1} - onClick={prevStep} - >{`< BACK`}</Button> + {isAuthorsFetching || isFilesFetching ? ( + <Spinner /> + ) : ( + <Fragment> + {!isFirstStep && ( + <Button + data-test="submission-back" + mr={1} + onClick={prevStep} + >{`< BACK`}</Button> + )} + <Button + data-test="submission-next" + ml={isFirstStep ? 0 : 1} + onClick={handleSubmit} + primary + > + {getButtonText()} + </Button> + </Fragment> )} - <Button - data-test="submission-next" - ml={isFirstStep ? 0 : 1} - onClick={handleSubmit} - primary - > - {getButtonText()} - </Button> </Row> </StepRoot> </Root> @@ -103,6 +115,8 @@ export default compose( formSyncErrors: getFormSyncErrors('submission')(state), version: selectFragment(state, get(match, 'params.version')), project: selectCollection(state, get(match, 'params.project')), + isFilesFetching: getFileFetching(state), + isAuthorsFetching: getAuthorFetching(state) || getAutosaveFetching(state), }), { addAuthor, @@ -115,7 +129,7 @@ export default compose( }, ), withStateHandlers( - { step: 1 }, + { step: 0 }, { nextStep: ({ step }) => () => ({ step: Math.min(wizardSteps.length - 1, step + 1), diff --git a/packages/component-wizard/src/components/utils.js b/packages/component-wizard/src/components/utils.js index b5ddee1d0c7a024233fbe86af5cea134d328f8be..24cd3f2ae8e76ccbfc94d1aed12ce7a416ca67dd 100644 --- a/packages/component-wizard/src/components/utils.js +++ b/packages/component-wizard/src/components/utils.js @@ -89,9 +89,6 @@ export const onSubmit = ( hideModal, isEditMode, setModalError, - autosaveRequest, - autosaveSuccess, - autosaveFailure, submitManuscript, version: { id: fragmentId }, project: { id: collectionId, customId }, diff --git a/packages/components-faraday/src/redux/authors.js b/packages/components-faraday/src/redux/authors.js index d7012b20121648bacfdf32c4ddde5fb5c222d07e..c867b596751e0c7db39949b1cfa30077156c137c 100644 --- a/packages/components-faraday/src/redux/authors.js +++ b/packages/components-faraday/src/redux/authors.js @@ -50,8 +50,9 @@ export const deleteAuthor = (collectionId, fragmentId, userId) => dispatch => { export const getFragmentAuthors = (state, fragmentId) => get(state, `authors.${fragmentId}`, []) -export const getAuthorFetching = state => state.authors.isFetching -export const getAuthorError = state => state.authors.error +export const getAuthorFetching = state => + get(state, 'authors.isFetching', false) +export const getAuthorError = state => get(state, 'authors.error', null) const initialState = { isFetching: false, error: null } diff --git a/packages/components-faraday/src/redux/files.js b/packages/components-faraday/src/redux/files.js index 1ece0f82225f80925ba13bf47f60439de76c7d02..623177c8a4284d3641896c94c86ba1157805494e 100644 --- a/packages/components-faraday/src/redux/files.js +++ b/packages/components-faraday/src/redux/files.js @@ -1,4 +1,5 @@ -import request, { remove, get } from 'pubsweet-client/src/helpers/api' +import request, { remove, get as apiGet } from 'pubsweet-client/src/helpers/api' +import { get } from 'lodash' const initialState = { isFetching: { @@ -83,8 +84,12 @@ const removeSuccess = file => ({ }) // selectors -export const getRequestStatus = state => state.files.isFetching -export const getFileError = state => state.files.error +export const getRequestStatus = state => get(state, 'files.isFetching', false) +export const getFileFetching = state => + Object.values(get(state, 'files.isFetching', initialState.isFetching)).some( + v => v, + ) +export const getFileError = state => get(state, 'files.error', null) // thunked actions export const uploadFile = (file, type, fragment) => dispatch => { @@ -118,7 +123,7 @@ export const deleteFile = (fileId, type = 'manuscripts') => dispatch => { }) } -export const getSignedUrl = fileId => dispatch => get(`/files/${fileId}`) +export const getSignedUrl = fileId => dispatch => apiGet(`/files/${fileId}`) // reducer export default (state = initialState, action) => { diff --git a/packages/styleguide/src/Wrapper.js b/packages/styleguide/src/Wrapper.js index 467e2f5c80cdf9509efa625e430e043a56658957..b7641fe72a28e8c036b9fedafa11bf4160950165 100644 --- a/packages/styleguide/src/Wrapper.js +++ b/packages/styleguide/src/Wrapper.js @@ -6,6 +6,7 @@ import hindawiTheme from 'hindawi-theme' import { createLogger } from 'redux-logger' import { ThemeProvider } from 'styled-components' import { client } from 'pubsweet-component-modal' +import { BrowserRouter as Router } from 'react-router-dom' import { createStore, combineReducers, applyMiddleware } from 'redux' import withDragDropContext from './withDragDropContext' @@ -23,9 +24,11 @@ class Wrapper extends Component { render() { return ( <Provider store={store}> - <ThemeProvider theme={hindawiTheme}> - {this.props.children} - </ThemeProvider> + <Router> + <ThemeProvider theme={hindawiTheme}> + {this.props.children} + </ThemeProvider> + </Router> </Provider> ) } diff --git a/packages/xpub-faraday/config/default.js b/packages/xpub-faraday/config/default.js index daf2f46d9f92f960ea7d08dbb00a95331ab3caad..aebc901864fd5ce67fd587a4b69e4ee908129b3a 100644 --- a/packages/xpub-faraday/config/default.js +++ b/packages/xpub-faraday/config/default.js @@ -46,7 +46,7 @@ module.exports = { API_ENDPOINT: '/api', baseUrl: process.env.CLIENT_BASE_URL || 'http://localhost:3000', 'login-redirect': '/', - 'redux-log': false, // process.env.NODE_ENV !== 'production', + 'redux-log': true, // process.env.NODE_ENV !== 'production', theme: process.env.PUBSWEET_THEME, }, orcid: {