Skip to content

Commit

Permalink
feat: add draggable file upload component (#690)
Browse files Browse the repository at this point in the history
* feat: add draggable file upload component

Signed-off-by: 4nalog <[email protected]>

* chore: add support for listening to file changes

Signed-off-by: 4nalog <[email protected]>

* refactor: extensible file upload input

Signed-off-by: 4nalog <[email protected]>

* refactor: rename component

Signed-off-by: 4nalog <[email protected]>

* chore: fix file upload props

Signed-off-by: 4nalog <[email protected]>

* chore: add comments for file upload component options

Signed-off-by: 4nalog <[email protected]>

---------

Signed-off-by: 4nalog <[email protected]>
  • Loading branch information
4nalog authored Feb 24, 2023
1 parent 797bcc2 commit 32cba38
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/console/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@flyteorg/console",
"version": "0.0.10",
"version": "0.0.11",
"description": "Flyteconsole main app module",
"main": "./dist/index.js",
"module": "./lib/index.js",
Expand Down Expand Up @@ -93,6 +93,7 @@
"prop-types": "15.6.0",
"query-string": "^6.5.0",
"react-chartjs-2": "^4.3.1",
"react-dropzone": "^14.2.3",
"react-flow-renderer": "10.3.8",
"react-ga4": "^1.4.1",
"react-intersection-observer": "^8.25.1",
Expand Down Expand Up @@ -120,6 +121,7 @@
"@types/pure-render-decorator": "^0.2.27",
"@types/react": "^16.9.34",
"@types/react-dom": "^16.9.7",
"@types/react-dropzone": "^5.1.0",
"@types/react-virtualized": "^9.21.4",
"@types/serve-static": "^1.7.31",
"@types/shallowequal": "^0.2.3"
Expand Down
50 changes: 50 additions & 0 deletions packages/console/src/components/common/FileUpload/FileItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { makeStyles, Theme } from '@material-ui/core';
import { Clear, Done } from '@material-ui/icons';
import React from 'react';

const useStyles = makeStyles((theme: Theme) => ({
container: {
background: theme.palette.grey[100],
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
gap: '8px',
alignItems: 'center',
width: '100%',
padding: theme.spacing(1, 0.5),
fontSize: 12,
},
icon: {
color: theme.palette.success.main,
},
fileName: {
flex: 1,
textAlign: 'left',
},
}));

interface Props {
file: File;
remove: () => void;
}

function FileItem({ file, remove }: Props) {
const styles = useStyles();

return (
<div className={styles.container}>
<Done className={styles.icon} />
<div className={styles.fileName}>{file.name}</div>
<Clear
onClick={e => {
e.preventDefault();
e.stopPropagation();

remove();
}}
/>
</div>
);
}

export default FileItem;
85 changes: 85 additions & 0 deletions packages/console/src/components/common/FileUpload/FileUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { makeStyles, Theme } from '@material-ui/core';
import React from 'react';
import { DropzoneProps, useDropzone } from 'react-dropzone';
import FileItem from './FileItem';

const useStyles = makeStyles((theme: Theme) => ({
container: {
margin: 'auto',
maxWidth: '536px',
color: theme.palette.grey[400],
cursor: 'pointer',
},
uploadContainer: {
width: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
gap: theme.spacing(0.5),
padding: theme.spacing(4, 3),
border: `0.5px dashed ${theme.palette.divider}`,
borderRadius: '4px',
},
filesContainer: {
width: '100%',
},
highlight: {
color: theme.palette.primary.main,
},
}));

/**
* For a list of available options, see https://react-dropzone.js.org/
*/
export interface FileUploadProps extends DropzoneProps {
files: File[];
setFiles: React.Dispatch<React.SetStateAction<File[]>>;
helpText?: React.ReactNode;
}

export function FileUpload({
files,
setFiles,
helpText,
...options
}: FileUploadProps) {
const styles = useStyles();
const { getRootProps, getInputProps } = useDropzone({
...options,
onDrop: (acceptedFiles, fileRejections, event) => {
setFiles(acceptedFiles);
options?.onDrop?.(acceptedFiles, fileRejections, event);
},
});

const removeFile = (fileIdx: number) => {
setFiles(files => files.filter((_, idx) => idx !== fileIdx));
};

const ctaText = files.length ? 'Replace file' : 'Upload a file';

return (
<div className={styles.container}>
<div {...getRootProps({ className: styles.uploadContainer })}>
<div className={styles.filesContainer}>
{files.map((file, idx) => (
<FileItem
file={file}
remove={() => removeFile(idx)}
key={file.name}
/>
))}
</div>
<div>
<span className={styles.highlight}>{ctaText}</span> or drag and drop
here
</div>
{helpText}
<input {...getInputProps()} />
</div>
</div>
);
}

export default FileUpload;
47 changes: 47 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,7 @@ __metadata:
"@types/pure-render-decorator": ^0.2.27
"@types/react": ^16.9.34
"@types/react-dom": ^16.9.7
"@types/react-dropzone": ^5.1.0
"@types/react-virtualized": ^9.21.4
"@types/serve-static": ^1.7.31
"@types/shallowequal": ^0.2.3
Expand Down Expand Up @@ -2168,6 +2169,7 @@ __metadata:
prop-types: 15.6.0
query-string: ^6.5.0
react-chartjs-2: ^4.3.1
react-dropzone: ^14.2.3
react-flow-renderer: 10.3.8
react-ga4: ^1.4.1
react-intersection-observer: ^8.25.1
Expand Down Expand Up @@ -5520,6 +5522,15 @@ __metadata:
languageName: node
linkType: hard

"@types/react-dropzone@npm:^5.1.0":
version: 5.1.0
resolution: "@types/react-dropzone@npm:5.1.0"
dependencies:
react-dropzone: "*"
checksum: 2b68fcf0153fb00e17088907490b823b6d81a29a02e615f820e347df2546f9318c5f025eeb33d575c648d01a14e55a19e528c32907608b5a7f727ff0e96b3923
languageName: node
linkType: hard

"@types/react-test-renderer@npm:>=16.9.0":
version: 18.0.0
resolution: "@types/react-test-renderer@npm:18.0.0"
Expand Down Expand Up @@ -7015,6 +7026,13 @@ __metadata:
languageName: node
linkType: hard

"attr-accept@npm:^2.2.2":
version: 2.2.2
resolution: "attr-accept@npm:2.2.2"
checksum: 496f7249354ab53e522510c1dc8f67a1887382187adde4dc205507d2f014836a247073b05e9d9ea51e2e9c7f71b0d2aa21730af80efa9af2d68303e5f0565c4d
languageName: node
linkType: hard

"autoprefixer@npm:^9.8.6":
version: 9.8.8
resolution: "autoprefixer@npm:9.8.8"
Expand Down Expand Up @@ -11370,6 +11388,15 @@ __metadata:
languageName: node
linkType: hard

"file-selector@npm:^0.6.0":
version: 0.6.0
resolution: "file-selector@npm:0.6.0"
dependencies:
tslib: ^2.4.0
checksum: 7d051b6e5d793f3c6e2ab287ba5e7c2c6a0971bccc9d56e044c8047ba483e18f60fc0b5771c951dc707c0d15f4f36ccb4f1f1aaf385d21ec8f7700dadf8325ba
languageName: node
linkType: hard

"file-system-cache@npm:^1.0.5":
version: 1.1.0
resolution: "file-system-cache@npm:1.1.0"
Expand Down Expand Up @@ -18516,6 +18543,19 @@ __metadata:
languageName: node
linkType: hard

"react-dropzone@npm:*, react-dropzone@npm:^14.2.3":
version: 14.2.3
resolution: "react-dropzone@npm:14.2.3"
dependencies:
attr-accept: ^2.2.2
file-selector: ^0.6.0
prop-types: ^15.8.1
peerDependencies:
react: ">= 16.8 || 18.0.0"
checksum: 174b744d5ca898cf3d84ec1aeb6cef5211c446697e45dc8ece8287a03d291f8d07253206d5a1247ef156fd385d65e7de666d4d5c2986020b8543b8f2434e8b40
languageName: node
linkType: hard

"react-element-to-jsx-string@npm:^14.3.4":
version: 14.3.4
resolution: "react-element-to-jsx-string@npm:14.3.4"
Expand Down Expand Up @@ -21273,6 +21313,13 @@ __metadata:
languageName: node
linkType: hard

"tslib@npm:^2.4.0":
version: 2.5.0
resolution: "tslib@npm:2.5.0"
checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1
languageName: node
linkType: hard

"tsutils@npm:^3.21.0":
version: 3.21.0
resolution: "tsutils@npm:3.21.0"
Expand Down

0 comments on commit 32cba38

Please sign in to comment.