mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 08:49:52 +03:00
129 lines
3.2 KiB
TypeScript
129 lines
3.2 KiB
TypeScript
import React, { FC, Fragment } from 'react';
|
|
import { useDropzone, DropzoneState } from 'react-dropzone';
|
|
|
|
import { makeStyles, createStyles } from '@material-ui/styles';
|
|
import CloudUploadIcon from '@material-ui/icons/CloudUpload';
|
|
import CancelIcon from '@material-ui/icons/Cancel';
|
|
import {
|
|
Theme,
|
|
Box,
|
|
Typography,
|
|
LinearProgress,
|
|
Button
|
|
} from '@material-ui/core';
|
|
|
|
interface SingleUploadStyleProps extends DropzoneState {
|
|
uploading: boolean;
|
|
}
|
|
|
|
const progressPercentage = (progress: ProgressEvent) =>
|
|
Math.round((progress.loaded * 100) / progress.total);
|
|
|
|
const getBorderColor = (theme: Theme, props: SingleUploadStyleProps) => {
|
|
if (props.isDragAccept) {
|
|
return theme.palette.success.main;
|
|
}
|
|
if (props.isDragReject) {
|
|
return theme.palette.error.main;
|
|
}
|
|
if (props.isDragActive) {
|
|
return theme.palette.info.main;
|
|
}
|
|
return theme.palette.grey[700];
|
|
};
|
|
|
|
const useStyles = makeStyles((theme: Theme) =>
|
|
createStyles({
|
|
dropzone: {
|
|
padding: theme.spacing(8, 2),
|
|
borderWidth: 2,
|
|
borderRadius: 2,
|
|
borderStyle: 'dashed',
|
|
color: theme.palette.grey[700],
|
|
transition: 'border .24s ease-in-out',
|
|
cursor: (props: SingleUploadStyleProps) =>
|
|
props.uploading ? 'default' : 'pointer',
|
|
width: '100%',
|
|
borderColor: (props: SingleUploadStyleProps) =>
|
|
getBorderColor(theme, props)
|
|
}
|
|
})
|
|
);
|
|
|
|
export interface SingleUploadProps {
|
|
onDrop: (acceptedFiles: File[]) => void;
|
|
onCancel: () => void;
|
|
accept?: string | string[];
|
|
uploading: boolean;
|
|
progress?: ProgressEvent;
|
|
}
|
|
|
|
const SingleUpload: FC<SingleUploadProps> = ({
|
|
onDrop,
|
|
onCancel,
|
|
accept,
|
|
uploading,
|
|
progress
|
|
}) => {
|
|
const dropzoneState = useDropzone({
|
|
onDrop,
|
|
accept,
|
|
disabled: uploading,
|
|
multiple: false
|
|
});
|
|
const { getRootProps, getInputProps } = dropzoneState;
|
|
const classes = useStyles({ ...dropzoneState, uploading });
|
|
|
|
const renderProgressText = () => {
|
|
if (uploading) {
|
|
if (progress?.lengthComputable) {
|
|
return `Uploading: ${progressPercentage(progress)}%`;
|
|
}
|
|
return 'Uploading\u2026';
|
|
}
|
|
return 'Drop file or click here';
|
|
};
|
|
|
|
const renderProgress = (progress?: ProgressEvent) => (
|
|
<LinearProgress
|
|
variant={
|
|
!progress || progress.lengthComputable ? 'determinate' : 'indeterminate'
|
|
}
|
|
value={
|
|
!progress
|
|
? 0
|
|
: progress.lengthComputable
|
|
? progressPercentage(progress)
|
|
: 0
|
|
}
|
|
/>
|
|
);
|
|
|
|
return (
|
|
<div {...getRootProps({ className: classes.dropzone })}>
|
|
<input {...getInputProps()} />
|
|
<Box flexDirection="column" display="flex" alignItems="center">
|
|
<CloudUploadIcon fontSize="large" />
|
|
<Typography variant="h6">{renderProgressText()}</Typography>
|
|
{uploading && (
|
|
<Fragment>
|
|
<Box width="100%" p={2}>
|
|
{renderProgress(progress)}
|
|
</Box>
|
|
<Button
|
|
startIcon={<CancelIcon />}
|
|
variant="contained"
|
|
color="secondary"
|
|
onClick={onCancel}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
</Fragment>
|
|
)}
|
|
</Box>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SingleUpload;
|