diff --git a/packages/component-helper-service/src/services/Fragment.js b/packages/component-helper-service/src/services/Fragment.js index 5f4dfbfb6f71d132969ea2075ad767d20bfb4662..f07543c772ed58d48839fd1ab46357f27eeb3a94 100644 --- a/packages/component-helper-service/src/services/Fragment.js +++ b/packages/component-helper-service/src/services/Fragment.js @@ -26,7 +26,7 @@ class Fragment { const { fragment } = this fragment.authors = fragment.authors || [] const author = { - userId: user.id, + id: user.id, firstName: user.firstName || '', lastName: user.lastName || '', email: user.email, diff --git a/packages/component-user-manager/src/routes/fragmentsUsers/delete.js b/packages/component-user-manager/src/routes/fragmentsUsers/delete.js index 5c696d281469fd2b8e7d8282f69fd1d90d8a44d5..907b689dea2cbd211b821187877ed0fd4c090b5d 100644 --- a/packages/component-user-manager/src/routes/fragmentsUsers/delete.js +++ b/packages/component-user-manager/src/routes/fragmentsUsers/delete.js @@ -18,9 +18,7 @@ module.exports = models => async (req, res) => { objectType: 'fragment', }) - fragment.authors = fragment.authors.filter( - author => author.userId !== userId, - ) + fragment.authors = fragment.authors.filter(author => author.id !== userId) await fragment.save() await teamHelper.removeTeamMember({ teamId: team.id, userId }) user.teams = user.teams.filter(userTeamId => team.id !== userTeamId) diff --git a/packages/component-user-manager/src/routes/fragmentsUsers/get.js b/packages/component-user-manager/src/routes/fragmentsUsers/get.js index 2d2b6f91af0def563ecebaacc0f4951a192c603f..75385a1b54016c0a31d95371206bb9ca353f04c7 100644 --- a/packages/component-user-manager/src/routes/fragmentsUsers/get.js +++ b/packages/component-user-manager/src/routes/fragmentsUsers/get.js @@ -27,7 +27,7 @@ module.exports = models => async (req, res) => { const membersData = members.map(async member => { const user = await models.User.find(member) const matchingAuthor = fragment.authors.find( - author => author.userId === user.id || author.id === user.id, + author => author.id === user.id, ) return { ...user, diff --git a/packages/component-user-manager/src/routes/fragmentsUsers/patch.js b/packages/component-user-manager/src/routes/fragmentsUsers/patch.js index 5cc1d38f95c8e30985dfe62457bdf5bcde3f6a13..dbdb663f478f095cfb24626dad95923cc427d62d 100644 --- a/packages/component-user-manager/src/routes/fragmentsUsers/patch.js +++ b/packages/component-user-manager/src/routes/fragmentsUsers/patch.js @@ -33,7 +33,7 @@ module.exports = models => async (req, res) => { } const user = await models.User.find(userId) const matchingAuthor = fragment.authors.find( - author => author.userId === user.id, + author => author.id === user.id, ) if (matchingAuthor === undefined) { return res.status(400).json({ diff --git a/packages/components-faraday/src/components/AuthorList/Author.js b/packages/components-faraday/src/components/AuthorList/Author.js index 5df7654e9b1ef7277a196a6981dbff69e8c2669b..8bfdf0ac941250cfd2d44ff75e24e5fb87fefbf9 100644 --- a/packages/components-faraday/src/components/AuthorList/Author.js +++ b/packages/components-faraday/src/components/AuthorList/Author.js @@ -27,10 +27,7 @@ export default ({ <Title>{parseAuthorType(isSubmitting, isCorresponding, index)}</Title> <ButtonContainer> {!isSubmitting && ( - <ClickableIcon - onClick={removeAuthor(id, email)} - title="Delete author" - > + <ClickableIcon onClick={removeAuthor(id)} title="Delete author"> <Icon size={3}>trash</Icon> </ClickableIcon> )} diff --git a/packages/components-faraday/src/components/AuthorList/AuthorAdder.js b/packages/components-faraday/src/components/AuthorList/AuthorAdder.js index 8736b65a6a0017c2ad10fdd9c018ad3164f88f4c..86b022531276137f5435090ae4ff25efbd3698b4 100644 --- a/packages/components-faraday/src/components/AuthorList/AuthorAdder.js +++ b/packages/components-faraday/src/components/AuthorList/AuthorAdder.js @@ -10,7 +10,6 @@ import { selectCurrentUser } from 'xpub-selectors' import { emailValidator } from '../utils' import { Spinner } from '../UIComponents/' import { - getAuthors, authorSuccess, authorFailure, getAuthorFetching, @@ -109,6 +108,7 @@ export default compose( const collectionId = get(match, 'params.project') const fragmentId = get(match, 'params.version') const isFirstAuthor = authors.length === 0 + addAuthor( { ...values, @@ -117,22 +117,11 @@ export default compose( }, collectionId, fragmentId, - ).then( - () => { - setEditMode(false)() - setTimeout(() => { - getAuthors(collectionId, fragmentId).then( - data => { - dispatch(authorSuccess()) - setFormAuthors(data) - }, - err => dispatch(authorFailure(err)), - ) - }, 10) - reset() - }, - err => dispatch(authorFailure(err)), - ) + ).then(authors => { + setEditMode(false)() + setFormAuthors(authors) + reset() + }) }, }), )(AuthorAdder) diff --git a/packages/components-faraday/src/components/AuthorList/AuthorEditor.js b/packages/components-faraday/src/components/AuthorList/AuthorEditor.js index 6a407a9831e5564871f533d033efebf542c89eeb..dc60ebd8bb94bf07cab15b832fc51655c58fc1c5 100644 --- a/packages/components-faraday/src/components/AuthorList/AuthorEditor.js +++ b/packages/components-faraday/src/components/AuthorList/AuthorEditor.js @@ -9,7 +9,6 @@ import { reduxForm, Field, change as changeForm } from 'redux-form' import { Spinner } from '../UIComponents' import { - getAuthors, editAuthor, authorSuccess, authorFailure, @@ -17,11 +16,14 @@ import { } from '../../redux/authors' import { ValidatedTextField, Label } from './FormItems' +import { authorKeys } from './utils' + const renderCheckbox = ({ input }) => ( <Checkbox checked={input.value} type="checkbox" {...input} /> ) const AuthorEdit = ({ + id, index, email, isFetching, @@ -31,7 +33,6 @@ const AuthorEdit = ({ parseAuthorType, isCorresponding, changeCorresponding, - ...rest }) => ( <Root> <Header> @@ -42,7 +43,7 @@ const AuthorEdit = ({ <Field component={renderCheckbox} name="edit.isCorresponding" - onChange={changeCorresponding(email)} + onChange={changeCorresponding(id)} /> <label>Corresponding</label> </Fragment> @@ -88,27 +89,19 @@ export default compose( state => ({ isFetching: getAuthorFetching(state), }), - { changeForm, authorSuccess, authorFailure }, + { changeForm, authorSuccess, authorFailure, editAuthor }, ), withProps(props => ({ initialValues: { - edit: pick(props, [ - 'id', - 'email', - 'lastName', - 'firstName', - 'affiliation', - 'isSubmitting', - 'isCorresponding', - ]), + edit: pick(props, authorKeys), }, })), withHandlers({ - changeCorresponding: ({ changeForm, setAsCorresponding }) => email => ( + changeCorresponding: ({ changeForm, setAsCorresponding }) => id => ( evt, newValue, ) => { - setAsCorresponding(email)() + setAsCorresponding(id)() changeForm('edit', 'edit.isCorresponding', newValue) }, }), @@ -119,27 +112,20 @@ export default compose( dispatch, { index, - authors, project, version, changeForm, + editAuthor, setAuthors, setAuthorEdit, }, ) => { const newAuthor = values.edit editAuthor(project.id, version.id, newAuthor.id, newAuthor).then( - () => { - getAuthors(project.id, version.id).then( - data => { - dispatch(authorSuccess()) - setAuthorEdit(-1)() - setAuthors(data) - }, - err => dispatch(authorFailure(err)), - ) + authors => { + setAuthorEdit(-1)() + setAuthors(authors) }, - err => dispatch(authorFailure(err)), ) }, }), diff --git a/packages/components-faraday/src/components/AuthorList/AuthorList.js b/packages/components-faraday/src/components/AuthorList/AuthorList.js index 2ce125819fd8e737f6f129f10bc5a5907a45b9b5..a67dbc403b32ebbde658a7a3488c30308502d387 100644 --- a/packages/components-faraday/src/components/AuthorList/AuthorList.js +++ b/packages/components-faraday/src/components/AuthorList/AuthorList.js @@ -1,4 +1,5 @@ import React from 'react' +import { get } from 'lodash' import { th } from '@pubsweet/ui' import PropTypes from 'prop-types' import { connect } from 'react-redux' @@ -6,8 +7,8 @@ import styled from 'styled-components' import { withRouter } from 'react-router-dom' import { compose, - lifecycle, withState, + withProps, getContext, withHandlers, } from 'recompose' @@ -16,7 +17,6 @@ import { SortableList } from 'pubsweet-component-sortable-list/src/components' import { addAuthor, - getAuthors, deleteAuthor, authorFailure, getAuthorError, @@ -91,6 +91,9 @@ export default compose( }, ), withState('authors', 'setAuthors', []), + withProps(({ version }) => ({ + authors: get(version, 'authors') || [], + })), withState('editMode', 'setEditMode', false), withState('editedAuthor', 'setEditedAuthor', -1), withHandlers({ @@ -103,9 +106,6 @@ export default compose( }, }), withHandlers({ - getAndSetFormAuthors: ({ setFormAuthors, project, version }) => () => { - getAuthors(project.id, version.id).then(setFormAuthors) - }, setAuthorEdit: ({ setEditedAuthor, changeForm }) => editedAuthor => e => { e && e.preventDefault && e.preventDefault() changeForm('wizard', 'editMode', editedAuthor > -1) @@ -139,38 +139,21 @@ export default compose( }, removeAuthor: ({ authors, + version, project, deleteAuthor, - authorFailure, setFormAuthors, - }) => (id, authorEmail) => () => { - deleteAuthor(project.id, id).then( - () => { - const newAuthors = authors.filter(a => a.id !== id) - setFormAuthors(newAuthors) - }, - err => authorFailure(err), - ) + }) => id => () => { + deleteAuthor(project.id, version.id, id).then(() => { + const newAuthors = authors.filter(a => a.id !== id) + setFormAuthors(newAuthors) + }) }, - setAsCorresponding: ({ authors, setFormAuthors }) => authorEmail => () => { - const newAuthors = authors.map( - a => - a.email === authorEmail - ? { - ...a, - isCorresponding: !a.isCorresponding, - } - : { ...a, isCorresponding: false }, - ) + setAsCorresponding: ({ authors, setFormAuthors }) => id => () => { + const newAuthors = authors.map(utils.setCorresponding(id)) setFormAuthors(newAuthors) }, }), - lifecycle({ - componentDidMount() { - const { getAndSetFormAuthors } = this.props - getAndSetFormAuthors() - }, - }), )(Authors) // #region styled-components diff --git a/packages/components-faraday/src/components/AuthorList/StaticList.js b/packages/components-faraday/src/components/AuthorList/StaticList.js index 19d0d5f1e41027871b3d79b5edf1ee47bdcee390..79d6d2fec293c087bf6a9555e74094db1f59a983 100644 --- a/packages/components-faraday/src/components/AuthorList/StaticList.js +++ b/packages/components-faraday/src/components/AuthorList/StaticList.js @@ -3,6 +3,8 @@ import React from 'react' import Author from './Author' export default ({ + version, + project, authors, editIndex, removeAuthor, @@ -19,7 +21,6 @@ export default ({ index === editIndex ? ( React.createElement(editComponent, { key: 'author-editor', - authors, index, initialValues: { edit: author, @@ -28,8 +29,9 @@ export default ({ setAuthorEdit, parseAuthorType, setAsCorresponding, + project, + version, ...author, - ...rest, }) ) : ( <Author @@ -38,7 +40,6 @@ export default ({ index={index} parseAuthorType={parseAuthorType} removeAuthor={removeAuthor} - setAsCorresponding={setAsCorresponding} {...rest} /> ), diff --git a/packages/components-faraday/src/components/AuthorList/utils.js b/packages/components-faraday/src/components/AuthorList/utils.js index 073245611713d637d94407c24cd88bf58e5bee84..2127775a2d2d30aa2907b1e4d941b5357a2b21e6 100644 --- a/packages/components-faraday/src/components/AuthorList/utils.js +++ b/packages/components-faraday/src/components/AuthorList/utils.js @@ -1,6 +1,6 @@ import { pick, isEmpty } from 'lodash' -const authorKeys = [ +export const authorKeys = [ 'id', 'email', 'lastName', @@ -11,4 +11,13 @@ const authorKeys = [ ] export const filterEmptyAuthors = author => !isEmpty(author) + export const getAuthorProperties = author => pick(author, authorKeys) + +export const setCorresponding = id => author => + author.id === id + ? { + ...author, + isCorresponding: true, + } + : { ...author, isCorresponding: false } diff --git a/packages/components-faraday/src/components/Files/Files.js b/packages/components-faraday/src/components/Files/Files.js index 3bf85519bc16e665a18fdbb36410cab86258a06c..9e884afdc347efbee174f2edb7d45986da8625f1 100644 --- a/packages/components-faraday/src/components/Files/Files.js +++ b/packages/components-faraday/src/components/Files/Files.js @@ -65,13 +65,25 @@ const Files = ({ changeList={changeList} dropSortableFile={dropSortableFile} files={get(files, 'coverLetter') || []} - isLast listId="coverLetter" maxFiles={1} moveItem={moveItem('coverLetter')} removeFile={removeFile('coverLetter')} title="Cover letter" /> + <FileSection + addFile={addFile('coverLetter')} + allowedFileExtensions={['pdf', 'doc', 'docx']} + changeList={changeList} + dropSortableFile={dropSortableFile} + files={get(files, 'response') || []} + isLast + listId="responseToReviewer" + maxFiles={1} + moveItem={moveItem('response')} + removeFile={removeFile('response')} + title="Response to reviewers" + /> </div> ) diff --git a/packages/components-faraday/src/redux/authors.js b/packages/components-faraday/src/redux/authors.js index 3330dff59d8e4fba49dc508ee7ded87a629f8f7f..0df800986795c366622ae75b44dfaaf25380b38c 100644 --- a/packages/components-faraday/src/redux/authors.js +++ b/packages/components-faraday/src/redux/authors.js @@ -5,6 +5,7 @@ import { remove, update, } from 'pubsweet-client/src/helpers/api' +import { handleError } from './utils' // constants const REQUEST = 'authors/REQUEST' @@ -25,28 +26,51 @@ export const authorSuccess = () => ({ type: SUCCESS, }) +export const getAuthors = (collectionId, fragmentId) => + apiGet(`/collections/${collectionId}/fragments/${fragmentId}/users`) + +export const editAuthor = ( + collectionId, + fragmentId, + userId, + body, +) => dispatch => { + dispatch(authorRequest()) + return update( + `/collections/${collectionId}/fragments/${fragmentId}/users/${userId}`, + body, + ).then( + () => + getAuthors(collectionId, fragmentId).then(authors => { + dispatch(authorSuccess()) + return authors + }, handleError(authorFailure, dispatch)), + handleError(authorFailure, dispatch), + ) +} + export const addAuthor = (author, collectionId, fragmentId) => dispatch => { dispatch(authorRequest()) return create(`/collections/${collectionId}/fragments/${fragmentId}/users`, { email: author.email, role: 'author', ...author, - }) + }).then( + () => + getAuthors(collectionId, fragmentId).then(data => { + dispatch(authorSuccess()) + return data + }, handleError(authorFailure, dispatch)), + handleError(authorFailure, dispatch), + ) } -export const deleteAuthor = (collectionId, userId) => dispatch => { +export const deleteAuthor = (collectionId, fragmentId, userId) => dispatch => { dispatch(authorRequest()) - return remove(`/collections/${collectionId}/users/${userId}`) -} - -export const editAuthor = (collectionId, fragmentId, userId, body) => - update( + return remove( `/collections/${collectionId}/fragments/${fragmentId}/users/${userId}`, - body, - ) - -export const getAuthors = (collectionId, fragmentId) => - apiGet(`/collections/${collectionId}/fragments/${fragmentId}/users`) + ).catch(handleError(authorFailure, dispatch)) +} export const getAuthorsTeam = collectionId => apiGet(`/teams?object.id=${collectionId}&group=author`).then(teams => diff --git a/packages/components-faraday/src/redux/utils.js b/packages/components-faraday/src/redux/utils.js index 14560f9260f6bfeec3f768e7a47b2c2147c1d111..9b69520a3a08d6c5ce66f312c2e21b18d1a4cc0e 100644 --- a/packages/components-faraday/src/redux/utils.js +++ b/packages/components-faraday/src/redux/utils.js @@ -9,3 +9,8 @@ export const orderReviewers = r => { return 1 } } + +export const handleError = (fn, dispatch = null) => err => { + typeof dispatch === 'function' ? dispatch(fn(err)) : fn(err) + throw err +}