From 47e6b159034a0d6692b940cea2cf9a973679c83a Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munteanu@thinslices.com>
Date: Mon, 22 Jan 2018 14:22:40 +0200
Subject: [PATCH] Add edit on list items

---
 .../src/components/AuthorList.js              | 87 ++++++++++++++++---
 .../src/components/AuthorList.local.scss      | 12 +++
 .../src/components/SortableList.js            | 53 ++++++++---
 .../component-wizard/src/redux/authors.js     |  2 +-
 4 files changed, 127 insertions(+), 27 deletions(-)

diff --git a/packages/component-wizard/src/components/AuthorList.js b/packages/component-wizard/src/components/AuthorList.js
index d29102c1f..b5e78ab55 100644
--- a/packages/component-wizard/src/components/AuthorList.js
+++ b/packages/component-wizard/src/components/AuthorList.js
@@ -4,7 +4,6 @@ import classnames from 'classnames'
 import { connect } from 'react-redux'
 import { get } from 'lodash'
 import { reduxForm } from 'redux-form'
-import { actions } from 'pubsweet-client'
 import { required } from 'xpub-validators'
 import { withRouter } from 'react-router-dom'
 import { selectCurrentUser } from 'xpub-selectors'
@@ -125,6 +124,67 @@ const AuthorAdder = ({ authors, editMode, setEditMode, handleSubmit }) => (
   </div>
 )
 
+const AuthorEdit = ({ setAuthorEdit, handleSubmit }) => (
+  <div className={classnames(classes['editor-body'])}>
+    <div className={classnames(classes.row)}>
+      <ValidatedTextField isRequired label="First name" name="edit.firstName" />
+      <ValidatedTextField label="Middle name" name="edit.middleName" />
+      <ValidatedTextField isRequired label="Last name" name="edit.lastName" />
+    </div>
+
+    <div className={classnames(classes.row)}>
+      <ValidatedTextField
+        isRequired
+        label="Email"
+        name="edit.email"
+        validators={[emailValidator]}
+      />
+      <ValidatedTextField
+        isRequired
+        label="Affiliation"
+        name="edit.affiliation"
+      />
+      <MenuItem label="Country" name="edit.country" options={countries} />
+    </div>
+
+    <div className={classnames(classes['form-buttons'])}>
+      <Button onClick={setAuthorEdit(-1)}>Cancel</Button>
+      <Button onClick={handleSubmit} primary>
+        Save
+      </Button>
+    </div>
+  </div>
+)
+
+const Editor = compose(
+  withRouter,
+  getContext({ version: PropTypes.object, project: PropTypes.object }),
+  connect(
+    (state, { match: { params: { version } } }) => ({
+      authors: getFragmentAuthors(state, version),
+    }),
+    {
+      setAuthors,
+    },
+  ),
+  reduxForm({
+    form: 'edit',
+    onSubmit: (
+      values,
+      dispatch,
+      { setAuthorEdit, setAuthors, project, version, authors, index, ...rest },
+    ) => {
+      const newAuthors = [
+        ...authors.slice(0, index),
+        values.edit,
+        ...authors.slice(index + 1),
+      ]
+      setAuthors(newAuthors, version.id)
+      setTimeout(setAuthorEdit(-1), 100)
+    },
+  }),
+)(AuthorEdit)
+
 const Adder = compose(
   connect(state => ({
     currentUser: selectCurrentUser(state),
@@ -184,6 +244,7 @@ const Author = ({
   isCorresponding,
   setAsCorresponding,
   parseAuthorType,
+  ...rest
 }) => (
   <div
     className={classnames({
@@ -229,6 +290,12 @@ const Author = ({
           <Icon>mail</Icon>
         </div>
       )}
+      <div
+        className={classnames(classes.corresponding)}
+        onClick={rest.setAuthorEdit(rest.index)}
+      >
+        <Icon>edit-2</Icon>
+      </div>
     </div>
   </div>
 )
@@ -257,6 +324,7 @@ const Authors = ({
     <SortableList
       dragHandle={DragHandle}
       dropItem={dropItem}
+      editItem={Editor}
       items={authors}
       listItem={Author}
       moveItem={moveAuthor}
@@ -276,7 +344,6 @@ export default compose(
       addAuthor,
       setAuthors,
       moveAuthors,
-      updateFragment: actions.updateFragment,
     },
   ),
   lifecycle({
@@ -286,18 +353,17 @@ export default compose(
     },
   }),
   withState('editMode', 'setEditMode', false),
+  withState('editedAuthor', 'setEditedAuthor', -1),
   withHandlers({
+    setAuthorEdit: ({ setEditedAuthor }) => editedAuthor => e => {
+      e && e.preventDefault && e.preventDefault()
+      setEditedAuthor(prev => editedAuthor)
+    },
     setEditMode: ({ setEditMode }) => mode => e => {
       e && e.preventDefault()
       setEditMode(v => mode)
     },
-    dropItem: ({
-      updateFragment,
-      authors,
-      project,
-      version,
-      setAuthors,
-    }) => () => {
+    dropItem: ({ authors, project, version, setAuthors }) => () => {
       setAuthors(authors, version.id)
     },
     countryParser: () => countryCode =>
@@ -312,7 +378,6 @@ export default compose(
       moveAuthors,
       project,
       version,
-      updateFragment,
       match: { params },
     }) => (dragIndex, hoverIndex) => {
       const newAuthors = SortableList.moveItem(authors, dragIndex, hoverIndex)
@@ -320,7 +385,6 @@ export default compose(
     },
     removeAuthor: ({
       authors,
-      updateFragment,
       project,
       version,
       setAuthors,
@@ -330,7 +394,6 @@ export default compose(
     },
     setAsCorresponding: ({
       authors,
-      updateFragment,
       setAuthors,
       version,
       project,
diff --git a/packages/component-wizard/src/components/AuthorList.local.scss b/packages/component-wizard/src/components/AuthorList.local.scss
index cb4905b40..38c04b816 100644
--- a/packages/component-wizard/src/components/AuthorList.local.scss
+++ b/packages/component-wizard/src/components/AuthorList.local.scss
@@ -48,6 +48,18 @@
   }
 }
 
+.editor-body {
+  border: 1px solid #444;
+  margin: 10px 0;
+  padding: 10px;
+
+  .form-buttons {
+    display: flex;
+    justify-content: space-around;
+    margin: 15px 0 0 0;
+  }
+}
+
 .adder {
   display: flex;
   flex-direction: column;
diff --git a/packages/component-wizard/src/components/SortableList.js b/packages/component-wizard/src/components/SortableList.js
index c566f4c63..8a91c9e99 100644
--- a/packages/component-wizard/src/components/SortableList.js
+++ b/packages/component-wizard/src/components/SortableList.js
@@ -47,9 +47,13 @@ const Item = ({
   connectDropTarget,
   listItem,
   dragHandle,
+  isEditing,
   ...rest
-}) =>
-  dragHandle
+}) => {
+  if (isEditing) {
+    return <div style={{ flex: 1 }}>{React.createElement(listItem, rest)}</div>
+  }
+  return dragHandle
     ? connectDragPreview(
         connectDropTarget(
           <div style={{ flex: 1 }}>
@@ -69,6 +73,7 @@ const Item = ({
           <div style={{ flex: 1 }}>{React.createElement(listItem, rest)}</div>,
         ),
       )
+}
 
 const DecoratedItem = compose(
   DropTarget('item', itemTarget, (connect, monitor) => ({
@@ -82,19 +87,39 @@ const DecoratedItem = compose(
   })),
 )(Item)
 
-const SortableList = ({ items, moveItem, listItem, dragHandle, ...rest }) => (
+const SortableList = ({
+  items,
+  moveItem,
+  listItem,
+  dragHandle,
+  editItem,
+  ...rest
+}) => (
   <div>
-    {items.map((item, i) => (
-      <DecoratedItem
-        dragHandle={dragHandle}
-        index={i}
-        key={item.name || Math.random()}
-        listItem={listItem}
-        moveItem={moveItem}
-        {...item}
-        {...rest}
-      />
-    ))}
+    {items.map(
+      (item, i) =>
+        i === rest.editedAuthor ? (
+          React.createElement(editItem, {
+            key: item.name || Math.random(),
+            initialValues: {
+              edit: item,
+            },
+            index: i,
+            ...rest,
+          })
+        ) : (
+          <DecoratedItem
+            dragHandle={dragHandle}
+            index={i}
+            isEditing={rest.editedAuthor !== -1}
+            key={item.name || Math.random()}
+            listItem={listItem}
+            moveItem={moveItem}
+            {...item}
+            {...rest}
+          />
+        ),
+    )}
   </div>
 )
 
diff --git a/packages/component-wizard/src/redux/authors.js b/packages/component-wizard/src/redux/authors.js
index 18440cfd0..0ee3777b5 100644
--- a/packages/component-wizard/src/redux/authors.js
+++ b/packages/component-wizard/src/redux/authors.js
@@ -14,8 +14,8 @@ const _setAuthors = (authors, fragmentId) => ({
 
 // actions
 export const setAuthors = (authors, fragmentId) => dispatch => {
-  dispatch(_setAuthors(authors, fragmentId))
   dispatch(change('wizard', 'authors', authors))
+  dispatch(_setAuthors(authors, fragmentId))
 }
 
 export const moveAuthors = (authors, fragmentId) => dispatch => {
-- 
GitLab