100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
import UploadFileIcon from "@mui/icons-material/UploadFile";
|
|
import { Button, Tooltip, Typography } from "@mui/material";
|
|
import React from "react";
|
|
import { FileApi, UploadedFile } from "../../api/FileApi";
|
|
import { ServerApi } from "../../api/ServerApi";
|
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
|
import { useLoadingMessage } from "../../hooks/context_providers/LoadingMessageProvider";
|
|
import { useSnackbar } from "../../hooks/context_providers/SnackbarProvider";
|
|
|
|
// https://medium.com/@dprincecoder/creating-a-drag-and-drop-file-upload-component-in-react-a-step-by-step-guide-4d93b6cc21e0
|
|
|
|
export function UploadFileButton(p: {
|
|
onUploaded: (file: UploadedFile) => void;
|
|
label: string;
|
|
tooltip: string;
|
|
}): React.ReactElement {
|
|
const alert = useAlert();
|
|
const loadingMessage = useLoadingMessage();
|
|
const snackbar = useSnackbar();
|
|
|
|
const fileInput = React.useRef<HTMLInputElement>(null);
|
|
|
|
const [dragActive, setDragActive] = React.useState(false);
|
|
|
|
const forceFileSelect = () => fileInput.current?.click();
|
|
|
|
const dragEnter = () => {
|
|
setDragActive(true);
|
|
};
|
|
const dragLeave = () => {
|
|
setDragActive(false);
|
|
};
|
|
|
|
const handleUpload = async (file: File[]) => {
|
|
if (file.length < 1) return;
|
|
|
|
try {
|
|
loadingMessage.show("Uploading file...");
|
|
|
|
const result = await FileApi.UploadFile(file[0]);
|
|
|
|
snackbar("The file was successfully uploaded!");
|
|
|
|
p.onUploaded(result);
|
|
} catch (e) {
|
|
console.error("Failed to upload file!", e);
|
|
alert(`Failed to upload file! ${e}`);
|
|
} finally {
|
|
loadingMessage.hide();
|
|
}
|
|
};
|
|
|
|
const handleDrop = (ev: React.DragEvent) => {
|
|
ev.preventDefault();
|
|
handleUpload([...ev.dataTransfer.files]);
|
|
};
|
|
|
|
const handlefileChange = (ev: React.ChangeEvent) => {
|
|
ev.preventDefault();
|
|
if ((fileInput.current?.files?.length ?? 0) > 0) {
|
|
handleUpload([...fileInput.current!.files!]);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Tooltip
|
|
title={p.tooltip}
|
|
onDrop={handleDrop}
|
|
onDragOver={(event) => {
|
|
event.preventDefault();
|
|
}}
|
|
onDragEnter={dragEnter}
|
|
onDragLeave={dragLeave}
|
|
>
|
|
<Button
|
|
size="small"
|
|
startIcon={<UploadFileIcon fontSize="small" />}
|
|
variant={dragActive ? "outlined" : "text"}
|
|
onClick={forceFileSelect}
|
|
>
|
|
<input
|
|
ref={fileInput}
|
|
type="file"
|
|
accept={ServerApi.Config.constraints.file_allowed_types.join(",")}
|
|
style={{
|
|
border: "0",
|
|
height: "1px",
|
|
width: "1px",
|
|
padding: "0px",
|
|
position: "absolute",
|
|
clipPath: "inset(50%)",
|
|
}}
|
|
onChange={handlefileChange}
|
|
/>
|
|
<Typography variant="caption">{p.label}</Typography>
|
|
</Button>
|
|
</Tooltip>
|
|
);
|
|
}
|