From 9cc0265f9ec991a5e4c48f58082b1e35998bd610 Mon Sep 17 00:00:00 2001
From: Alf Eaton <eaton.alf@gmail.com>
Date: Mon, 3 Jul 2017 13:31:16 +0100
Subject: [PATCH] Add reviewers stories

---
 app/components/EditorList.js         |  3 +-
 app/components/Reviewers.js          | 96 ----------------------------
 app/components/ReviewersForm.js      | 47 ++++++++++++++
 app/components/ReviewersList.js      | 29 +++++++++
 app/containers/ReviewersContainer.js | 52 +++++++++++++++
 app/routes.jsx                       |  2 +-
 stories/data/projects.js             | 16 +++++
 stories/index.js                     | 21 +++++-
 8 files changed, 165 insertions(+), 101 deletions(-)
 delete mode 100644 app/components/Reviewers.js
 create mode 100644 app/components/ReviewersForm.js
 create mode 100644 app/components/ReviewersList.js
 create mode 100644 app/containers/ReviewersContainer.js

diff --git a/app/components/EditorList.js b/app/components/EditorList.js
index 2071ab878..bed8af1df 100644
--- a/app/components/EditorList.js
+++ b/app/components/EditorList.js
@@ -9,7 +9,8 @@ const EditorList = ({ project, roles }) => (
       const role = roles[id]
 
       return (
-        <LinkContainer key={id} to={`/projects/${project.id}/roles/editor/${id}`} style={{ textDecoration: 'none' }}>
+        <LinkContainer key={id} to={`/projects/${project.id}/roles/editor/${id}`}
+                       style={{ textDecoration: 'none' }}>
           <ListGroupItem header={role.user.name} className="clearfix">
             <span style={{ float: 'right' }}>{role.status || 'Pending'}</span>
           </ListGroupItem>
diff --git a/app/components/Reviewers.js b/app/components/Reviewers.js
deleted file mode 100644
index 75ed77803..000000000
--- a/app/components/Reviewers.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import React from 'react'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
-import { updateCollection } from 'pubsweet-client/src/actions/collections'
-import FRC from 'formsy-react-components'
-import { Button, ListGroup, ListGroupItem } from 'react-bootstrap'
-import uuid from 'uuid'
-import { LinkContainer } from 'react-router-bootstrap'
-
-class Reviewers extends React.Component {
-  addReviewer = user => {
-    const { project, updateCollection } = this.props
-
-    const { roles } = project
-    roles.reviewer = roles.reviewer || {}
-    roles.reviewer[uuid()] = { user }
-
-    updateCollection({
-      id: project.id,
-      roles
-    })
-
-    this.reviewerForm.reset()
-  }
-
-  render () {
-    const { project } = this.props
-
-    if (!project) return null
-
-    const { roles } = project
-
-    // TODO: only return reviewer details from the server to authorised users
-    // TODO: implement role status (+ invitations property?)
-
-    return (
-      <div className="content-metadata">
-        <h1>Reviewers</h1>
-
-        <div className="content-interactive">
-          <FRC.Form ref={form => (this.reviewerForm = form)} onSubmit={this.addReviewer} validateOnSubmit={true}
-                    layout="vertical">
-            <div>
-              <FRC.Input type="text" name="name" label="Reviewer name"/>
-            </div>
-
-            <div>
-              <FRC.Input type="email" name="email" label="Reviewer email"/>
-            </div>
-
-            <div style={{ marginTop: 20 }}>
-              <Button type="submit" bsStyle="primary">Save</Button>
-            </div>
-          </FRC.Form>
-        </div>
-
-        {roles.reviewer && (
-          <ListGroup style={{marginTop: 20}}>
-            {Object.keys(roles.reviewer).map(key => {
-              const role = roles.reviewer[key]
-
-              // TODO: use role.id instead of key
-
-              return (
-                <LinkContainer key={key} to={`/projects/${project.id}/roles/reviewer/${key}`} style={{textDecoration: 'none'}}>
-                  <ListGroupItem header={role.user.name} className="clearfix">
-                    <span>{role.user.email}</span>
-                    <span style={{float: 'right'}}>{role.status || 'Pending'}</span>
-                  </ListGroupItem>
-                </LinkContainer>
-              )
-            })}
-          </ListGroup>
-        )}
-      </div>
-    )
-  }
-}
-
-Reviewers.propTypes = {
-  params: PropTypes.object.isRequired,
-  project: PropTypes.object,
-  updateCollection: PropTypes.func.isRequired
-}
-
-export default connect(
-  (state, ownProps) => ({
-    // FIXME: not updating
-    project: state.collections.find(collection => {
-      return collection.id === ownProps.params.project
-    })
-  }),
-  {
-    updateCollection
-  }
-)(Reviewers)
diff --git a/app/components/ReviewersForm.js b/app/components/ReviewersForm.js
new file mode 100644
index 000000000..25db1f4c4
--- /dev/null
+++ b/app/components/ReviewersForm.js
@@ -0,0 +1,47 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import FRC from 'formsy-react-components'
+import { Button } from 'react-bootstrap'
+import uuid from 'uuid'
+
+class ReviewersForm extends React.Component {
+  addReviewer = user => {
+    const { project, updateCollection } = this.props
+
+    const { roles } = project
+    roles.reviewer = roles.reviewer || {}
+    roles.reviewer[uuid()] = { user }
+
+    updateCollection({
+      id: project.id,
+      roles
+    })
+
+    this.reviewerForm.reset()
+  }
+
+  render () {
+    return (
+      <FRC.Form ref={form => (this.reviewerForm = form)} onSubmit={this.addReviewer} validateOnSubmit={true} layout="vertical">
+        <div>
+          <FRC.Input type="text" name="name" label="Reviewer name"/>
+        </div>
+
+        <div>
+          <FRC.Input type="email" name="email" label="Reviewer email"/>
+        </div>
+
+        <div style={{ marginTop: 20 }}>
+          <Button type="submit" bsStyle="primary">Save</Button>
+        </div>
+      </FRC.Form>
+    )
+  }
+}
+
+ReviewersForm.propTypes = {
+  project: PropTypes.object,
+  updateCollection: PropTypes.func.isRequired
+}
+
+export default ReviewersForm
diff --git a/app/components/ReviewersList.js b/app/components/ReviewersList.js
new file mode 100644
index 000000000..d5adbbcf9
--- /dev/null
+++ b/app/components/ReviewersList.js
@@ -0,0 +1,29 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { ListGroup, ListGroupItem } from 'react-bootstrap'
+import { LinkContainer } from 'react-router-bootstrap'
+
+const ReviewersList = ({ project, roles }) => (
+  <ListGroup>
+    {Object.keys(roles).map(id => {
+      const role = roles[id]
+
+      return (
+        <LinkContainer key={id} to={`/projects/${project.id}/roles/reviewer/${id}`}
+                       style={{ textDecoration: 'none' }}>
+          <ListGroupItem header={role.user.name} className="clearfix">
+            <span>{role.user.email}</span>
+            <span style={{ float: 'right' }}>{role.status || 'Pending'}</span>
+          </ListGroupItem>
+        </LinkContainer>
+      )
+    })}
+  </ListGroup>
+)
+
+ReviewersList.propTypes = {
+  project: PropTypes.object,
+  roles: PropTypes.object.isRequired
+}
+
+export default ReviewersList
diff --git a/app/containers/ReviewersContainer.js b/app/containers/ReviewersContainer.js
new file mode 100644
index 000000000..80458bb0b
--- /dev/null
+++ b/app/containers/ReviewersContainer.js
@@ -0,0 +1,52 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { updateCollection } from 'pubsweet-client/src/actions/collections'
+import ReviewersForm from '../components/ReviewersForm'
+import ReviewersList from '../components/ReviewersList'
+
+class ReviewersContainer extends React.Component {
+  render () {
+    const { project, updateCollection } = this.props
+
+    if (!project) return null
+
+    const { roles } = project
+
+    // TODO: only return reviewer details from the server to authorised users
+    // TODO: implement role status (+ invitations property?)
+
+    return (
+      <div className="content-metadata">
+        <h1>Reviewers</h1>
+
+        <div className="content-interactive">
+          <ReviewersForm project={project} updateCollection={updateCollection}/>
+        </div>
+
+        {roles.reviewer && (
+          <ReviewersList project={project} roles={roles.reviewer}
+                         style={{ marginTop: 20 }}/>
+        )}
+      </div>
+    )
+  }
+}
+
+ReviewersContainer.propTypes = {
+  params: PropTypes.object.isRequired,
+  project: PropTypes.object,
+  updateCollection: PropTypes.func.isRequired
+}
+
+export default connect(
+  (state, ownProps) => ({
+    // FIXME: not updating
+    project: state.collections.find(collection => {
+      return collection.id === ownProps.params.project
+    })
+  }),
+  {
+    updateCollection
+  }
+)(ReviewersContainer)
diff --git a/app/routes.jsx b/app/routes.jsx
index 375f10c85..ceb3c2349 100644
--- a/app/routes.jsx
+++ b/app/routes.jsx
@@ -27,7 +27,7 @@ export default (
           <Route path="editors"
                  component={chunk(import('./containers/EditorsContainer'))}/>
           <Route path="reviewers"
-                 component={chunk(import('./components/Reviewers'))}/>
+                 component={chunk(import('./containers/ReviewersContainer'))}/>
           <Route path="roles/:roleType/:role"
                  component={chunk(import('./components/Role'))}/>
         </Route>
diff --git a/stories/data/projects.js b/stories/data/projects.js
index 2e4e1209c..f59ffdc0a 100644
--- a/stories/data/projects.js
+++ b/stories/data/projects.js
@@ -37,6 +37,22 @@ export default [
             name: 'Bar Bar'
           }
         }
+      },
+      reviewer: {
+        'user-baz': {
+          user: {
+            id: 'user-baz',
+            username: 'baz',
+            name: 'Baz Baz'
+          }
+        },
+        'user-qubit': {
+          user: {
+            id: 'user-qubit',
+            username: 'qubit',
+            name: 'Qubit Qubit'
+          }
+        }
       }
     },
     declarations: {
diff --git a/stories/index.js b/stories/index.js
index 6267b0cd9..7398170c5 100644
--- a/stories/index.js
+++ b/stories/index.js
@@ -24,6 +24,8 @@ import Snapshots from '../app/components/Snapshots'
 import Upload from '../app/components/Upload'
 import EditorList from '../app/components/EditorList'
 import EditorForm from '../app/components/EditorForm'
+import ReviewersForm from '../app/components/ReviewersForm'
+import ReviewersList from '../app/components/ReviewersList'
 
 // storiesOf('Welcome', module)
 //   .add('to Storybook', () => <Welcome showApp={linkTo('Button')} />)
@@ -32,7 +34,8 @@ const [importedProject, submittedProject] = projects
 
 storiesOf('Declarations', module)
   .add('questions', () => (
-    <DeclarationQuestions declarations={submittedProject.declarations} save={action('saved')}/>
+    <DeclarationQuestions declarations={submittedProject.declarations}
+                          save={action('saved')}/>
   ))
   .add('answers', () => (
     <DeclarationAnswers declarations={submittedProject.declarations}/>
@@ -40,10 +43,12 @@ storiesOf('Declarations', module)
 
 storiesOf('Editors', module)
   .add('form', () => (
-    <EditorForm project={submittedProject} updateCollection={action('update collection')}/>
+    <EditorForm project={submittedProject}
+                updateCollection={action('update editors')}/>
   ))
   .add('list', () => (
-    <EditorList project={submittedProject} roles={submittedProject.roles.editor}/>
+    <EditorList project={submittedProject}
+                roles={submittedProject.roles.editor}/>
   ))
 
 storiesOf('Project', module)
@@ -69,6 +74,16 @@ storiesOf('Remove Project', module)
     <RemoveProject onClick={action('remove')}/>
   ))
 
+storiesOf('Reviewers', module)
+  .add('form', () => (
+    <ReviewersForm project={submittedProject}
+                   updateCollection={action('update reviewers')}/>
+  ))
+  .add('list', () => (
+    <ReviewersList project={submittedProject}
+                   roles={submittedProject.roles.reviewer}/>
+  ))
+
 storiesOf('Roles Summary Item', module)
   .add('item', () => (
     <RolesSummaryItem label="Owner" url="#" user={{
-- 
GitLab