Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add draggable file upload component #690

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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",
4nalog marked this conversation as resolved.
Show resolved Hide resolved
"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