Skip to content

Commit

Permalink
feat(upload): add drag and drop for uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
Christie Baker authored and Christie Baker committed Dec 5, 2018
1 parent 6fc29c3 commit a45ad71
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 25 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@
"raf/polyfill"
],
"testEnvironment": "jest-environment-jsdom-global",
"setupTestFrameworkScriptFile": "<rootDir>/jest.setup.js"
"setupTestFrameworkScriptFile": "<rootDir>/jest.setup.js",
"moduleNameMapper": {
".scss$": "babel-jest"
}
},
"babel": {
"env": {
Expand Down
87 changes: 69 additions & 18 deletions packages/upload/Upload.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import React, { Component, createRef, Fragment } from 'react';
import PropTypes from 'prop-types';
import UploadCore from '@availity/upload-core';
import { FormFeedback } from 'reactstrap';
import Dropzone from 'react-dropzone';
import map from 'lodash.map';
import FilePickerBtn from './FilePickerBtn';
import FileList from './FileList';
import './styles.scss';

const validationAttrs = ['min', 'max', 'required'];

Expand All @@ -20,21 +24,25 @@ class Upload extends Component {
multiple: PropTypes.bool,
children: PropTypes.func,
name: PropTypes.string,
showFileDrop: PropTypes.bool,
};

static defaultProps = {
multiple: true,
showFileDrop: false,
};

input = createRef();

files = [];
error = null;

state = {
files: [],
};

removeFile = fileId => {
this.error = null;
this.setState(({ files }) => {
const newFiles = files.filter(file => file.id !== fileId);
if (newFiles.length !== files.length) {
Expand All @@ -48,11 +56,10 @@ class Upload extends Component {
});
};

handleFileInputChange = event => {
const { files: selectedFilesList } = event.target;
setFiles = files => {
let selectedFiles = [];
for (let i = 0; i < selectedFilesList.length; i++) {
selectedFiles[i] = selectedFilesList[i];
for (let i = 0; i < files.length; i++) {
selectedFiles[i] = files[i];
}
if (
this.props.max &&
Expand All @@ -77,12 +84,27 @@ class Upload extends Component {
return upload;
})
);
this.error = null;
this.setState({ files: this.files });
};

handleFileInputChange = event => {
this.setFiles(event.target.selectedFiles);
};

onDrop = (acceptedFiles, rejectedFiles) => {
if (rejectedFiles && rejectedFiles.length > 0) {
const fileNames = map(rejectedFiles, 'name');
this.error = `Could not attach ${fileNames.slice().join(', ')}`;
}

this.setFiles(acceptedFiles);
};

reset = () => {
this.files = [];
this.setState({ files: [] });
this.error = null;
};

componentDidMount() {
Expand Down Expand Up @@ -134,31 +156,60 @@ class Upload extends Component {
allowedFileTypes,
maxSize,
children,
showFileDrop,
} = this.props;
const { files } = this.state;
return (

let fileAddArea;
const text = btnText || (
<Fragment>
<FileList files={files} onRemoveFile={this.removeFile}>
{children}
</FileList>
{(!max || files.length < max) && (
<i className="icon icon-plus-circle" title="Add File Icon" />
{files.length === 0 ? 'Add File' : 'Add Another File Attachment'}
</Fragment>
);

if (!max || files.length < max) {
if (showFileDrop) {
fileAddArea = (
<div>
<Dropzone
onDrop={this.onDrop}
multiple={multiple}
maxSize={maxSize}
className="file-drop"
activeClassName="file-drop-active"
>
<div>
<strong>Drag and Drop</strong>
</div>
{text}
</Dropzone>
<FormFeedback valid={!this.error} className="d-block">
{this.error}
</FormFeedback>
</div>
);
} else {
fileAddArea = (
<FilePickerBtn
onChange={this.handleFileInputChange}
color={files.length === 0 ? 'light' : 'link'}
multiple={multiple}
allowedFileTypes={allowedFileTypes}
maxSize={maxSize}
>
{btnText || (
<Fragment>
<i className="icon icon-plus-circle" title="Add File Icon" />
{files.length === 0
? 'Add File'
: 'Add Another File Attachment'}
</Fragment>
)}
{text}
</FilePickerBtn>
)}
);
}
}

return (
<Fragment>
<FileList files={files} onRemoveFile={this.removeFile}>
{children}
</FileList>
{fileAddArea}
</Fragment>
);
}
Expand Down
11 changes: 8 additions & 3 deletions packages/upload/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,23 @@
},
"peerDependencies": {
"@availity/upload-core": "^2.0.0",
"lodash.map": "4.6.0",
"react": "^16.3.0",
"reactstrap": "^5.0.0 || ^6.0.0",
"tus-js-client": "^1.5.1"
"react-dom": "^16.3.0",
"react-dropzone": "^7.0.1",
"reactstrap": "^6.0.0",
"tus-js-client": "1.5.1"
},
"dependencies": {
"prop-types": "^15.5.8"
},
"devDependencies": {
"@availity/upload-core": "^2.0.0",
"lodash.map": "4.6.0",
"react": "^16.3.0",
"react-dom": "^16.3.0",
"react-dropzone": "^7.0.1",
"reactstrap": "^6.0.0",
"tus-js-client": "^1.5.1"
"tus-js-client": "1.5.1"
}
}
16 changes: 16 additions & 0 deletions packages/upload/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.file-drop {
color: #464a4c;
text-align: center;
border: 1px dashed rgba(0, 0, 0, .15);
width: 8rem;
min-width: fit-content;
height: 8rem;
padding: 3rem 0;
}

.file-drop-active {
border: 1px solid #3960ed;
border-width: 2px;
background-color: #ebebeb;
border-radius: 5px;
}
25 changes: 22 additions & 3 deletions packages/upload/tests/Upload.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Upload', () => {
const instance = component.instance();
const file = new Buffer.from('hello world'.split('')); // eslint-disable-line new-cap
file.name = 'fileName.png';
const fileEvent = { target: { files: [file] } };
const fileEvent = { target: { selectedFiles: [file] } };
instance.handleFileInputChange(fileEvent);

expect(instance.files.length).toBe(1);
Expand All @@ -32,7 +32,7 @@ describe('Upload', () => {
const instance = component.instance();
const file = new Buffer.from('hello world'.split('')); // eslint-disable-line new-cap
file.name = 'fileName.png';
const fileEvent = { target: { files: [file] } };
const fileEvent = { target: { selectedFiles: [file] } };
instance.handleFileInputChange(fileEvent);

expect(instance.files.length).toBe(1);
Expand All @@ -54,11 +54,30 @@ describe('Upload', () => {
const instance = component.instance();
const file = new Buffer.from('hello world'.split('')); // eslint-disable-line new-cap
file.name = 'fileName.png';
const fileEvent = { target: { files: [file] } };
const fileEvent = { target: { selectedFiles: [file] } };
instance.handleFileInputChange(fileEvent);

expect(instance.files.length).toBe(1);
instance.removeFile(instance.files[0].id);
expect(mockFunc.mock.calls.length).toBe(1);
});

test('adds file via dropzone', () => {
const component = shallow(
<Upload clientId="a" bucketId="b" customerId="c" showFileDrop />
);
const instance = component.instance();
const file = new Buffer.from('hello world'.split('')); // eslint-disable-line new-cap
file.name = 'fileName.png';
instance.onDrop([file]);

expect(instance.files.length).toBe(1);
instance.removeFile(instance.files[0].id);

expect(instance.files.length).toBe(0);

instance.onDrop([], [file]);

expect(instance.files.length).toBe(0);
});
});

0 comments on commit a45ad71

Please sign in to comment.