From 45be091bbbe2db664e3626323cc2a960555bca19 Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munt@gmail.com>
Date: Thu, 14 Jun 2018 10:05:06 +0300
Subject: [PATCH] fix(author-list): new api integration

---
 .../src/services/Fragment.js                  |  2 +-
 .../src/routes/fragmentsUsers/delete.js       |  4 +-
 .../src/routes/fragmentsUsers/get.js          |  2 +-
 .../src/routes/fragmentsUsers/patch.js        |  2 +-
 .../src/components/AuthorList/Author.js       |  5 +-
 .../src/components/AuthorList/AuthorAdder.js  | 23 +++------
 .../src/components/AuthorList/AuthorEditor.js | 38 +++++----------
 .../src/components/AuthorList/AuthorList.js   | 43 +++++------------
 .../src/components/AuthorList/StaticList.js   |  7 +--
 .../src/components/AuthorList/utils.js        | 11 ++++-
 .../src/components/Files/Files.js             | 14 +++++-
 .../components-faraday/src/redux/authors.js   | 48 ++++++++++++++-----
 .../components-faraday/src/redux/utils.js     |  5 ++
 13 files changed, 104 insertions(+), 100 deletions(-)

diff --git a/packages/component-helper-service/src/services/Fragment.js b/packages/component-helper-service/src/services/Fragment.js
index 5f4dfbfb6..f07543c77 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 5c696d281..907b689de 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 2d2b6f91a..75385a1b5 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 5cc1d38f9..dbdb663f4 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 5df7654e9..8bfdf0ac9 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 8736b65a6..86b022531 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 6a407a983..dc60ebd8b 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 2ce125819..a67dbc403 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 19d0d5f1e..79d6d2fec 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 073245611..2127775a2 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 3bf85519b..9e884afdc 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 3330dff59..0df800986 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 14560f926..9b69520a3 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
+}
-- 
GitLab