From 4eea4d9d1a8ed4f18f3a4e83169d3580f3a21fab Mon Sep 17 00:00:00 2001
From: Alexandru Munteanu <alexandru.munteanu@thinslices.com>
Date: Tue, 6 Feb 2018 16:01:27 +0200
Subject: [PATCH] Add error handling on file upload failure

---
 .../src/components/Files/FileDropzone.js      | 12 -------
 .../components/Files/FileDropzone.local.scss  | 12 -------
 .../src/components/Files/FileSection.js       |  5 +--
 .../components/Files/FileSection.local.scss   | 13 +++++++
 .../src/components/Files/Files.js             | 33 +++++++++++++-----
 .../src/components/Files/Files.local.scss     | 34 ++++---------------
 .../components-faraday/src/redux/files.js     | 16 ++++++---
 7 files changed, 59 insertions(+), 66 deletions(-)
 delete mode 100644 packages/components-faraday/src/components/Files/FileDropzone.js
 delete mode 100644 packages/components-faraday/src/components/Files/FileDropzone.local.scss

diff --git a/packages/components-faraday/src/components/Files/FileDropzone.js b/packages/components-faraday/src/components/Files/FileDropzone.js
deleted file mode 100644
index 8fe3b9a53..000000000
--- a/packages/components-faraday/src/components/Files/FileDropzone.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React from 'react'
-import classnames from 'classnames'
-
-import classes from './FileDropzone.local.scss'
-
-const FileDropzone = ({ label }) => (
-  <div className={classnames(classes.dropzone)}>
-    <span>{label}</span>
-  </div>
-)
-
-export default FileDropzone
diff --git a/packages/components-faraday/src/components/Files/FileDropzone.local.scss b/packages/components-faraday/src/components/Files/FileDropzone.local.scss
deleted file mode 100644
index fccfe9120..000000000
--- a/packages/components-faraday/src/components/Files/FileDropzone.local.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-.dropzone {
-  align-items: center;
-  display: flex;
-  height: 60px;
-  justify-content: center;
-  margin: 10px 0;
-
-  span {
-    color: #888;
-    font-size: 14px;
-  }
-}
diff --git a/packages/components-faraday/src/components/Files/FileSection.js b/packages/components-faraday/src/components/Files/FileSection.js
index f495196cc..45fc23817 100644
--- a/packages/components-faraday/src/components/Files/FileSection.js
+++ b/packages/components-faraday/src/components/Files/FileSection.js
@@ -12,7 +12,6 @@ import {
 
 import FileItem from './FileItem'
 import FilePicker from './FilePicker'
-import FileDropzone from './FileDropzone'
 import classes from './FileSection.local.scss'
 
 const DragHandle = () => (
@@ -92,7 +91,9 @@ const FileSection = ({
           previewFile={previewFile}
           removeFile={removeFile}
         />
-        <FileDropzone label="Drag files here or use the add button." />
+        <div className={classnames(classes.dropzone)}>
+          <span>Drag files here or use the add button.</span>
+        </div>
       </div>,
     ),
   )
diff --git a/packages/components-faraday/src/components/Files/FileSection.local.scss b/packages/components-faraday/src/components/Files/FileSection.local.scss
index 709f425a0..fc117bfe4 100644
--- a/packages/components-faraday/src/components/Files/FileSection.local.scss
+++ b/packages/components-faraday/src/components/Files/FileSection.local.scss
@@ -60,3 +60,16 @@
 .is-over {
   background-color: #ddd;
 }
+
+.dropzone {
+  align-items: center;
+  display: flex;
+  height: 60px;
+  justify-content: center;
+  margin: 10px 0;
+
+  span {
+    color: #888;
+    font-size: 14px;
+  }
+}
diff --git a/packages/components-faraday/src/components/Files/Files.js b/packages/components-faraday/src/components/Files/Files.js
index f61eaca9b..57fff441e 100644
--- a/packages/components-faraday/src/components/Files/Files.js
+++ b/packages/components-faraday/src/components/Files/Files.js
@@ -1,6 +1,7 @@
 import React from 'react'
 import { get } from 'lodash'
 import PropTypes from 'prop-types'
+import classnames from 'classnames'
 import { connect } from 'react-redux'
 import { withRouter } from 'react-router-dom'
 import { change as changeForm } from 'redux-form'
@@ -15,12 +16,14 @@ import {
 import { SortableList } from 'pubsweet-components-faraday/src/components'
 
 import FileSection from './FileSection'
+import classes from './Files.local.scss'
 
 import {
   uploadFile,
   deleteFile,
   getRequestStatus,
   getSignedUrl,
+  getFileError,
 } from '../../redux/files'
 
 const Files = ({
@@ -31,9 +34,20 @@ const Files = ({
   changeList,
   dropSortableFile,
   previewFile,
+  error,
   ...rest
 }) => (
   <div>
+    {error && (
+      <div
+        className={classnames({
+          [classes['error-container']]: true,
+          [classes.hidden]: !error,
+        })}
+      >
+        Error uploading file, please try again.
+      </div>
+    )}
     <FileSection
       addFile={addFile('manuscripts')}
       allowedFileExtensions={['pdf', 'doc', 'docx']}
@@ -83,6 +97,7 @@ export default compose(
   connect(
     state => ({
       isFetching: getRequestStatus(state),
+      error: getFileError(state),
     }),
     {
       changeForm,
@@ -142,14 +157,16 @@ export default compose(
       changeForm,
       version,
     }) => type => file => {
-      uploadFile(file, type, version.id).then(fileResponse => {
-        const newFiles = {
-          ...files,
-          [type]: [...files[type], fileResponse],
-        }
-        setFiles(newFiles)
-        changeForm('wizard', 'files', newFiles)
-      })
+      uploadFile(file, type, version.id)
+        .then(file => {
+          const newFiles = {
+            ...files,
+            [type]: [...files[type], file],
+          }
+          setFiles(newFiles)
+          changeForm('wizard', 'files', newFiles)
+        })
+        .catch(e => console.error(`Couldn't upload file.`, e))
     },
     moveItem: ({ moveFiles, files, setFiles }) => type => (
       dragIndex,
diff --git a/packages/components-faraday/src/components/Files/Files.local.scss b/packages/components-faraday/src/components/Files/Files.local.scss
index 5e6d16ca9..a51a8ec0d 100644
--- a/packages/components-faraday/src/components/Files/Files.local.scss
+++ b/packages/components-faraday/src/components/Files/Files.local.scss
@@ -1,30 +1,10 @@
-.file-item {
-  align-items: center;
-  border: 1px solid black;
+.error-container {
+  color: firebrick;
   display: flex;
-  margin: 5px;
-
-  .info {
-    border-right: 1px solid black;
-    display: flex;
-    flex: 1;
-    padding: 2px 0;
-  }
-
-  .buttons {
-    align-items: center;
-    display: flex;
-    justify-content: center;
-    margin: 0 5px;
-
-    button {
-      border: none;
-      cursor: pointer;
+  justify-content: flex-end;
+  margin: 5px 0;
+}
 
-      &:active,
-      &:focus {
-        outline: none;
-      }
-    }
-  }
+.hidden {
+  opacity: 0;
 }
diff --git a/packages/components-faraday/src/redux/files.js b/packages/components-faraday/src/redux/files.js
index 9c319f1b3..e2679c4df 100644
--- a/packages/components-faraday/src/redux/files.js
+++ b/packages/components-faraday/src/redux/files.js
@@ -56,22 +56,28 @@ const removeFailure = error => ({
   error,
 })
 
-const removeSuccess = () => ({
+const removeSuccess = file => ({
   type: REMOVE_SUCCESS,
+  file,
 })
 
 // selectors
 export const getRequestStatus = state => state.files.isFetching
+export const getFileError = state => state.files.error
 
 // thunked actions
 export const uploadFile = (file, type, fragmentId) => dispatch => {
   dispatch(uploadRequest(type))
-  return request('/aws', createFileData(file, type, fragmentId))
-    .then(r => {
+  return request('/aws', createFileData(file, type, fragmentId)).then(
+    r => {
       dispatch(uploadSuccess())
       return r
-    })
-    .catch(err => dispatch(uploadFailure(err.message)))
+    },
+    error => {
+      dispatch(uploadFailure(error))
+      throw error
+    },
+  )
 }
 
 export const deleteFile = fileId => dispatch => {
-- 
GitLab