From 043cf80839e1f6cea2b5b5640aa762d3cd17ccc1 Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munt@gmail.com>
Date: Thu, 31 May 2018 11:16:53 +0300
Subject: [PATCH] refactor(files): refactor duplicate code

---
 .../component-faraday-selectors/src/index.js  | 11 +++++
 .../src/components/Dashboard/DashboardCard.js | 12 ++----
 .../src/components/Files/Components.js        | 13 ++++++
 .../src/components/Files/FileDownload.js      | 43 +++----------------
 .../src/components/Files/FileItem.js          | 17 ++------
 .../src/components/Files/FilePreview.js       | 21 ++-------
 .../src/components/Files/ZipFiles.js          | 23 ++--------
 .../src/components/Files/index.js             |  3 ++
 .../src/components/Files/utils.js             | 18 ++++++++
 .../components-faraday/src/redux/reviewers.js | 12 ++++--
 10 files changed, 73 insertions(+), 100 deletions(-)
 create mode 100644 packages/components-faraday/src/components/Files/Components.js
 create mode 100644 packages/components-faraday/src/components/Files/utils.js

diff --git a/packages/component-faraday-selectors/src/index.js b/packages/component-faraday-selectors/src/index.js
index 58c0ed57c..22fdcf8f2 100644
--- a/packages/component-faraday-selectors/src/index.js
+++ b/packages/component-faraday-selectors/src/index.js
@@ -32,3 +32,14 @@ export const currentUserIs = ({ currentUser }, role) => {
       return false
   }
 }
+
+export const canInviteReviewers = ({ currentUser: { user } }, project) => {
+  const handlingEditor = get(project, 'handlingEditor')
+  const isAdmin = get(user, 'admin')
+  const isEic = get(user, 'editorInChief')
+  const isAccepted = get(handlingEditor, 'isAccepted')
+  const heId = get(handlingEditor, 'id')
+  return isAccepted && (user.id === heId || isAdmin || isEic)
+}
+
+export const getUserToken = ({ currentUser }) => get(currentUser, 'user.token')
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
index ca291175b..e4350c5d8 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
@@ -19,6 +19,7 @@ import { ReviewerDecision, HandlingEditorSection } from './'
 import { parseVersion, parseJournalIssue, mapStatusToLabel } from './../utils'
 import {
   currentUserIs,
+  canInviteReviewers,
   canMakeRecommendation,
 } from '../../../../component-faraday-selectors/src'
 
@@ -155,7 +156,7 @@ const DashboardCard = ({
                 project={project}
               />
             </LeftDetails>
-            {canInviteReviewers() && (
+            {canInviteReviewers && (
               <RightDetails flex={4}>
                 <ReviewerBreakdown
                   collectionId={project.id}
@@ -197,17 +198,10 @@ export default compose(
     isEIC: currentUserIs(state, 'adminEiC'),
     isHE: currentUserIs(state, 'handlingEditor'),
     invitation: selectInvitation(state, project.id),
+    canInviteReviewers: canInviteReviewers(state, project),
     canMakeRecommendation: canMakeRecommendation(state, project),
   })),
   withHandlers({
-    canInviteReviewers: ({ currentUser, project }) => () => {
-      const handlingEditor = get(project, 'handlingEditor')
-      const isAdmin = get(currentUser, 'admin')
-      const isEic = get(currentUser, 'editorInChief')
-      const isAccepted = get(handlingEditor, 'isAccepted')
-      const heId = get(handlingEditor, 'id')
-      return isAccepted && (currentUser.id === heId || isAdmin || isEic)
-    },
     showConfirmationModal: ({
       project,
       showModal,
diff --git a/packages/components-faraday/src/components/Files/Components.js b/packages/components-faraday/src/components/Files/Components.js
new file mode 100644
index 000000000..e9641ac01
--- /dev/null
+++ b/packages/components-faraday/src/components/Files/Components.js
@@ -0,0 +1,13 @@
+import { th } from '@pubsweet/ui'
+import styled from 'styled-components'
+
+export const IconButton = styled.div`
+  align-items: center;
+  cursor: pointer;
+  display: flex;
+  justify-content: center;
+  margin: 0 ${th('subGridUnit')};
+  &:hover {
+    opacity: 0.7;
+  }
+`
diff --git a/packages/components-faraday/src/components/Files/FileDownload.js b/packages/components-faraday/src/components/Files/FileDownload.js
index c44a1ff1e..3f73bf42e 100644
--- a/packages/components-faraday/src/components/Files/FileDownload.js
+++ b/packages/components-faraday/src/components/Files/FileDownload.js
@@ -1,40 +1,24 @@
 import React from 'react'
 import qs from 'querystring'
+import { Icon } from '@pubsweet/ui'
 import { connect } from 'react-redux'
-import styled from 'styled-components'
-import { Icon, th } from '@pubsweet/ui'
 import { compose, withHandlers } from 'recompose'
 
-const createAnchorElement = (file, filename) => {
-  const url = URL.createObjectURL(file)
-  const a = document.createElement('a')
-
-  a.href = url
-  a.download = filename
-  document.body.appendChild(a)
-
-  return {
-    a,
-    url,
-  }
-}
-
-const removeAnchorElement = (a, url) => {
-  document.body.removeChild(a)
-  URL.revokeObjectURL(url)
-}
+import { Components } from './'
+import { createAnchorElement, removeAnchorElement } from './utils'
+import { getUserToken } from '../../../../component-faraday-selectors'
 
 const FileDownload = ({ downloadFile }) => (
-  <IconButton onClick={downloadFile}>
+  <Components.IconButton onClick={downloadFile}>
     <Icon primary size={3}>
       download
     </Icon>
-  </IconButton>
+  </Components.IconButton>
 )
 
 export default compose(
   connect(state => ({
-    token: state.currentUser.user.token,
+    token: getUserToken(state),
   })),
   withHandlers({
     downloadFile: ({ fileId, token, fileName = 'file' }) => () => {
@@ -63,16 +47,3 @@ export default compose(
     },
   }),
 )(FileDownload)
-
-// #region styled-components
-const IconButton = styled.div`
-  align-items: center;
-  cursor: pointer;
-  display: flex;
-  justify-content: center;
-  margin: 0 ${th('subGridUnit')};
-  &:hover {
-    opacity: 0.7;
-  }
-`
-// #endregion
diff --git a/packages/components-faraday/src/components/Files/FileItem.js b/packages/components-faraday/src/components/Files/FileItem.js
index c1883929c..ba950f43b 100644
--- a/packages/components-faraday/src/components/Files/FileItem.js
+++ b/packages/components-faraday/src/components/Files/FileItem.js
@@ -3,7 +3,7 @@ import { last } from 'lodash'
 import { Icon, th } from '@pubsweet/ui'
 import styled, { css } from 'styled-components'
 
-import { FilePreview, FileDownload } from './'
+import { FilePreview, FileDownload, Components } from './'
 
 const parseFileSize = size => {
   const kbSize = size / 1000
@@ -42,11 +42,11 @@ const FileItem = ({
         <FileName>{name}</FileName>
         <FileSize>{parseFileSize(size)}</FileSize>
         {removeFile && (
-          <IconButton onClick={removeFile(id)}>
+          <Components.IconButton onClick={removeFile(id)}>
             <Icon primary size={3}>
               x
             </Icon>
-          </IconButton>
+          </Components.IconButton>
         )}
       </FileRoot>
     ) : (
@@ -126,17 +126,6 @@ const FileSize = FileName.extend`
   margin-left: ${th('subGridUnit')};
 `
 
-const IconButton = styled.div`
-  align-items: center;
-  cursor: pointer;
-  display: flex;
-  justify-content: center;
-  margin: 0 ${th('subGridUnit')};
-  &:hover {
-    opacity: 0.7;
-  }
-`
-
 const FileRoot = styled.div`
   align-items: center;
   border: ${th('borderDefault')};
diff --git a/packages/components-faraday/src/components/Files/FilePreview.js b/packages/components-faraday/src/components/Files/FilePreview.js
index d57fa6067..161781195 100644
--- a/packages/components-faraday/src/components/Files/FilePreview.js
+++ b/packages/components-faraday/src/components/Files/FilePreview.js
@@ -1,17 +1,17 @@
 import React from 'react'
+import { Icon } from '@pubsweet/ui'
 import { connect } from 'react-redux'
-import styled from 'styled-components'
-import { Icon, th } from '@pubsweet/ui'
 import { compose, withHandlers } from 'recompose'
 
+import { Components } from './'
 import { getSignedUrl } from '../../redux/files'
 
 const FilePreview = ({ previewFile }) => (
-  <IconButton onClick={previewFile}>
+  <Components.IconButton onClick={previewFile}>
     <Icon primary size={3}>
       eye
     </Icon>
-  </IconButton>
+  </Components.IconButton>
 )
 
 export default compose(
@@ -26,16 +26,3 @@ export default compose(
     },
   }),
 )(FilePreview)
-
-// #region styled-components
-const IconButton = styled.div`
-  align-items: center;
-  cursor: pointer;
-  display: flex;
-  justify-content: center;
-  margin: 0 ${th('subGridUnit')};
-  &:hover {
-    opacity: 0.7;
-  }
-`
-// #endregion
diff --git a/packages/components-faraday/src/components/Files/ZipFiles.js b/packages/components-faraday/src/components/Files/ZipFiles.js
index 0c268c410..00c8a54bd 100644
--- a/packages/components-faraday/src/components/Files/ZipFiles.js
+++ b/packages/components-faraday/src/components/Files/ZipFiles.js
@@ -7,25 +7,8 @@ import { compose, withHandlers, withState } from 'recompose'
 
 import { Spinner } from '../UIComponents/index'
 import { currentUserIsReviewer } from '../../redux/reviewers'
-
-const createAnchorElement = (file, filename) => {
-  const url = URL.createObjectURL(file)
-  const a = document.createElement('a')
-
-  a.href = url
-  a.download = filename
-  document.body.appendChild(a)
-
-  return {
-    a,
-    url,
-  }
-}
-
-const removeAnchorElement = (a, url) => {
-  document.body.removeChild(a)
-  URL.revokeObjectURL(url)
-}
+import { createAnchorElement, removeAnchorElement } from './utils'
+import { getUserToken } from '../../../../component-faraday-selectors'
 
 const ZipFiles = ({ disabled, fetching, children, downloadFiles }) => (
   <Root onClick={!disabled ? downloadFiles : null}>
@@ -40,7 +23,7 @@ const defaultFiles = [...reviewerFiles, 'coverLetter']
 
 const Zip = compose(
   connect((state, { collectionId }) => ({
-    token: state.currentUser.user.token,
+    token: getUserToken(state),
     isReviewer: currentUserIsReviewer(state, collectionId),
   })),
   withState('fetching', 'setFetching', false),
diff --git a/packages/components-faraday/src/components/Files/index.js b/packages/components-faraday/src/components/Files/index.js
index a4308c6b8..f44c5fae9 100644
--- a/packages/components-faraday/src/components/Files/index.js
+++ b/packages/components-faraday/src/components/Files/index.js
@@ -1,3 +1,6 @@
+import * as Components from './Components'
+
+export { Components }
 export { default as Files } from './Files'
 export { default as FileItem } from './FileItem'
 export { default as FilePicker } from './FilePicker'
diff --git a/packages/components-faraday/src/components/Files/utils.js b/packages/components-faraday/src/components/Files/utils.js
new file mode 100644
index 000000000..7f8d91c14
--- /dev/null
+++ b/packages/components-faraday/src/components/Files/utils.js
@@ -0,0 +1,18 @@
+export const createAnchorElement = (file, filename) => {
+  const url = URL.createObjectURL(file)
+  const a = document.createElement('a')
+
+  a.href = url
+  a.download = filename
+  document.body.appendChild(a)
+
+  return {
+    a,
+    url,
+  }
+}
+
+export const removeAnchorElement = (a, url) => {
+  document.body.removeChild(a)
+  URL.revokeObjectURL(url)
+}
diff --git a/packages/components-faraday/src/redux/reviewers.js b/packages/components-faraday/src/redux/reviewers.js
index 3f0a0d2d1..e21dae2a3 100644
--- a/packages/components-faraday/src/redux/reviewers.js
+++ b/packages/components-faraday/src/redux/reviewers.js
@@ -71,7 +71,7 @@ export const clearReviewersError = () => ({
   type: CLEAR_ERROR,
 })
 
-// selectors
+// #region Selectors
 export const selectReviewers = state => get(state, 'reviewers.reviewers') || []
 export const selectReviewersError = state => get(state, 'reviewers.error')
 export const selectFetchingReviewers = state =>
@@ -110,8 +110,9 @@ export const getCollectionReviewers = collectionId => dispatch => {
     err => dispatch(getReviewersError(err)),
   )
 }
+// #endregion
 
-// invitation actions
+// #region Actions - invitations
 export const inviteReviewer = (reviewerData, collectionId) => dispatch => {
   dispatch(inviteRequest())
   return create(`/collections/${collectionId}/invitations`, {
@@ -146,15 +147,15 @@ export const revokeReviewer = (invitationId, collectionId) => dispatch => {
     },
   )
 }
+// #endregion
 
-// reviewer decision actions
+// #region Actions - decision
 export const reviewerDecision = (
   invitationId,
   collectionId,
   agree = true,
 ) => dispatch => {
   dispatch(reviewerDecisionRequest())
-  // 'accept api call'
   return update(`/collections/${collectionId}/invitations/${invitationId}`, {
     isAccepted: agree,
   }).then(
@@ -191,7 +192,9 @@ export const reviewerDecline = (
     },
   )
 }
+// #endregion
 
+// #region Reducer
 export default (state = initialState, action = {}) => {
   switch (action.type) {
     case GET_REVIEWERS_REQUEST:
@@ -283,3 +286,4 @@ export default (state = initialState, action = {}) => {
       return state
   }
 }
+// #endregion
-- 
GitLab