Skip to content
This repository has been archived by the owner on Dec 6, 2024. It is now read-only.

Commit

Permalink
feat: Allow uploading a folder to My Studies (#475)
Browse files Browse the repository at this point in the history
  • Loading branch information
nguyen102 authored May 10, 2021
1 parent 31246b4 commit cb17d4b
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ const FileUpload = types
get name() {
return self.file ? self.file.name : '';
},
get fullFilePath() {
if (self.file) {
return self.file.webkitRelativePath ? self.file.webkitRelativePath : self.file.name;
}
return '';
},
get folder() {
if (self.file && self.file.webkitRelativePath) {
const regExpForReplacingFileName = new RegExp(`/${self.file.name}$`);
return self.file.webkitRelativePath.replace(regExpForReplacingFileName, '');
}
return '';
},
getFile() {
return self.file;
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import FileUploadGroup from '../FileUploadGroup';

describe('FileUploadGroup', () => {
const currentTimeFromEpoch = Date.now();
const fileName = 'sample.json';
const size = 0;
const file = {
lastModified: currentTimeFromEpoch,
lastModifiedDate: new Date(currentTimeFromEpoch),
name: fileName,
size,
type: 'application/json',
};

const resourceId = 'abcd';

function getFileUploadObject(fullFilePath) {
const fileWithTopLevelFolder = JSON.parse(JSON.stringify(file));
fileWithTopLevelFolder.webkitRelativePath = fullFilePath;

const fileUploadGroup = FileUploadGroup.create({ resourceId, state: 'PENDING' });

fileUploadGroup.add({ file: fileWithTopLevelFolder });

return fileUploadGroup.fileUploadObjects[0];
}

it('should handle top level folder correctly', () => {
const fileUploadObj = getFileUploadObject(`sampleFolder/${fileName}`);

// OPERATE & CHECK
expect(fileUploadObj.size).toEqual(size);
expect(fileUploadObj.name).toEqual(fileName);
expect(fileUploadObj.folder).toEqual('sampleFolder');
expect(fileUploadObj.fullFilePath).toEqual(`sampleFolder/${fileName}`);
});

it('should handle sub level folder correctly', () => {
// BUILD
const fileUploadObj = getFileUploadObject(`sampleFolder/subfolder/${fileName}`);

// OPERATE & CHECK
expect(fileUploadObj.size).toEqual(size);
expect(fileUploadObj.name).toEqual(fileName);
expect(fileUploadObj.folder).toEqual('sampleFolder/subfolder');
expect(fileUploadObj.fullFilePath).toEqual(`sampleFolder/subfolder/${fileName}`);
});

it('should handle uploading a file correctly', () => {
// BUILD
const fileUploadObj = getFileUploadObject('');

// OPERATE & CHECK
expect(fileUploadObj.size).toEqual(size);
expect(fileUploadObj.name).toEqual(fileName);
expect(fileUploadObj.folder).toEqual('');
expect(fileUploadObj.fullFilePath).toEqual(fileName);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import React from 'react';
import { decorate, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import PropTypes from 'prop-types';
import toastr from 'toastr';

import { Segment, Header, Divider, Button, Icon } from 'semantic-ui-react';
import uuidv4 from 'uuid/v4';
Expand Down Expand Up @@ -56,8 +57,22 @@ class FileDropZone extends React.Component {
});
}

handleSelectingFiles = event => {
if (this.props.onSelectFiles) {
const fileList = event.currentTarget.files || [];
if (fileList.length > this.props.maximumUploadFilesLimit) {
toastr.warning(
`There are currently ${fileList.length} files selected. Please select less than ${this.props.maximumUploadFilesLimit} files.`,
);
} else {
this.props.onSelectFiles([...fileList]);
}
}
};

render() {
const fileInputRef = React.createRef();
const folderInputRef = React.createRef();
const enabled = this.props.state === 'PENDING';
return (
<Segment
Expand Down Expand Up @@ -102,16 +117,23 @@ class FileDropZone extends React.Component {
hidden
multiple
onChange={event => {
if (this.props.onSelectFiles) {
const fileList = event.currentTarget.files || [];
this.props.onSelectFiles([...fileList]);
}
this.handleSelectingFiles(event);
}}
/>
<ReusableFileInput
ref={folderInputRef}
hidden
multiple
directory=""
webkitdirectory=""
onChange={event => {
this.handleSelectingFiles(event);
}}
/>
{this.props.state === 'PENDING' ? (
<>
<Icon name="upload" className="mb2" />
Drag and drop
Drag and drop files
<Divider horizontal>Or</Divider>
<Button
basic
Expand All @@ -122,7 +144,19 @@ class FileDropZone extends React.Component {
}
}}
>
Browse Files
Upload Files
</Button>
<Divider horizontal>Or</Divider>
<Button
basic
color="blue"
onClick={() => {
if (folderInputRef.current) {
folderInputRef.current.click();
}
}}
>
Upload Folder
</Button>
</>
) : this.props.state === 'UPLOADING' ? (
Expand All @@ -142,6 +176,7 @@ class FileDropZone extends React.Component {
}
}
FileDropZone.propTypes = {
maximumUploadFilesLimit: PropTypes.isRequired,
state: PropTypes.oneOf(['PENDING', 'UPLOADING', 'COMPLETE']).isRequired,
onSelectFiles: PropTypes.func,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import { Button, Grid, Header, Segment } from 'semantic-ui-react';

import { displayError, displaySuccess, displayWarning } from '@aws-ee/base-ui/dist/helpers/notification';

import toastr from 'toastr';
import StudyFileDropZone from './FileDropZone';
import FileUploadTable from './FileUploadTable';

const maximumUploadFilesLimit = 1000;
const FileUpload = observer(
({
files = [],
Expand All @@ -40,7 +42,11 @@ const FileUpload = observer(
return (
<Segment vertical>
<Header as="h3">Upload Files</Header>
<StudyFileDropZone state={state} onSelectFiles={onSelectFiles} />
<StudyFileDropZone
state={state}
onSelectFiles={onSelectFiles}
maximumUploadFilesLimit={maximumUploadFilesLimit}
/>
{files.length > 0 && (
<Segment>
<Grid>
Expand All @@ -57,7 +63,20 @@ const FileUpload = observer(
<Grid.Row>
<Grid.Column>
{state === 'PENDING' ? (
<Button floated="right" basic color="blue" onClick={onClickStartUpload}>
<Button
floated="right"
basic
color="blue"
onClick={() => {
if (files.length > maximumUploadFilesLimit) {
toastr.warning(
`There are currently ${files.length} files selected. Please select less than ${maximumUploadFilesLimit} files.`,
);
} else {
onClickStartUpload();
}
}}
>
Upload Files
</Button>
) : state === 'UPLOADING' ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const FileUploadToolbar = observer(({ file, state, onClickRemove, onClickCancel

const FileUploadRow = observer(({ file, state, onClickRemove, onClickCancel }) => (
<Table.Row>
<Table.Cell>{file.folder}</Table.Cell>
<Table.Cell>{file.name}</Table.Cell>
<Table.Cell>{prettyBytes(file.size)}</Table.Cell>
<Table.Cell>
Expand All @@ -76,6 +77,7 @@ const FileUploadTable = observer(({ files = [], state, onClickRemoveFile, onClic
<Table basic="very">
<Table.Header>
<Table.Row>
<Table.HeaderCell>Folder</Table.HeaderCell>
<Table.HeaderCell>Filename</Table.HeaderCell>
<Table.HeaderCell>Size</Table.HeaderCell>
<Table.HeaderCell>Status</Table.HeaderCell>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class UploadStudyFiles extends React.Component {
// Get presigned POST request
let uploadRequest;
try {
const presignResult = await getPresignedStudyUploadRequests(this.props.studyId, fileUpload.name);
uploadRequest = presignResult[fileUpload.name];
const presignResult = await getPresignedStudyUploadRequests(this.props.studyId, fileUpload.fullFilePath);
uploadRequest = presignResult[fileUpload.fullFilePath];
} catch (error) {
const errMessage = 'Error occurred obtaining presigned request';
console.error(`${errMessage}:`, error);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ To create a new Study, follow these steps:
7. Select the [**Project**](../accounts/projects/introduction) that this Study relates to in the **Project ID** drop down field.
8. Click the **Create Study** button.

Once you have created a Study you can start to upload files to it.
Once you have created a Study you can start to upload files to it. For more information on uploading files, click [here](./studies_page.md#creating-a-study-and-uploading-files).
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ To create a Study:
To upload files:

1. Click **Upload Files**.
2. Either drag and drop the files you want to upload, or click the **Browse Files** button to select the files to upload.
2. You can upload files either by dragging and dropping, or by clicking the **Upload Files** or **Upload Folder** button.

**Note**: The **Upload Files** button is not visible if you lack write permissions to the Study, or if the Study is external.

0 comments on commit cb17d4b

Please sign in to comment.