Spaces:
Sleeping
Sleeping
| import React, { | |
| ChangeEvent, | |
| useCallback, | |
| useContext, | |
| useEffect, | |
| useRef, | |
| useState, | |
| } from "react"; | |
| import axios from "axios"; | |
| import { useNavigate } from "react-router-dom"; | |
| import { Delete, UploadFile } from "@mui/icons-material"; | |
| import { | |
| Card, | |
| Box, | |
| CardContent, | |
| Typography, | |
| CardActions, | |
| Button, | |
| Modal, | |
| CircularProgress, | |
| } from "@mui/material"; | |
| import { ThemeSchemeContext, ThemeModeContext } from "../theme"; | |
| const AudioUploader = ({ ...props }) => { | |
| const { themeScheme } = useContext(ThemeSchemeContext); | |
| const { themeMode } = useContext(ThemeModeContext); | |
| const light = themeScheme[themeMode]; | |
| const navigate = useNavigate(); | |
| const [isVisible, setIsVisible] = useState(false); | |
| const [NextCard, setNextCard] = useState(false); | |
| const [isError, setIsError] = useState(false); | |
| const [audioFile, setAudioFile] = useState<File | null>(null); | |
| const [uploadStatus, setUploadStatus] = useState(""); | |
| const inputFile = useRef<HTMLInputElement | null>(null); | |
| const [modalOpen, setModalOpen] = useState(false); | |
| const onDragEnter = useCallback( | |
| (e: { stopPropagation: () => void; preventDefault: () => void }) => { | |
| setIsVisible(true); | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| return false; | |
| }, | |
| [] | |
| ); | |
| const onDragOver = useCallback( | |
| (e: { preventDefault: () => void; stopPropagation: () => void }) => { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| return false; | |
| }, | |
| [] | |
| ); | |
| const onDragLeave = useCallback( | |
| (e: { stopPropagation: () => void; preventDefault: () => void }) => { | |
| setIsVisible(false); | |
| e.stopPropagation(); | |
| e.preventDefault(); | |
| return false; | |
| }, | |
| [] | |
| ); | |
| const onDrop = useCallback( | |
| (e: { preventDefault: () => void; dataTransfer: any }) => { | |
| e.preventDefault(); | |
| setAudioFile(e.dataTransfer.files[0]); | |
| console.log("Files dropped: ", audioFile?.name); | |
| setNextCard(true); | |
| setIsVisible(false); | |
| return false; | |
| }, | |
| [] | |
| ); | |
| useEffect(() => { | |
| window.addEventListener("mouseup", onDragLeave); | |
| window.addEventListener("dragenter", onDragEnter); | |
| window.addEventListener("dragover", onDragOver); | |
| window.addEventListener("drop", onDrop); | |
| return () => { | |
| window.removeEventListener("mouseup", onDragLeave); | |
| window.removeEventListener("dragenter", onDragEnter); | |
| window.removeEventListener("dragover", onDragOver); | |
| window.removeEventListener("drop", onDrop); | |
| }; | |
| }, [onDragEnter, onDragLeave, onDragOver, onDrop]); | |
| const handleFileChange = (event: ChangeEvent<HTMLInputElement>) => { | |
| const file = event.target.files?.[0]; | |
| if (file) { | |
| setAudioFile(file); | |
| setNextCard(true); | |
| } | |
| }; | |
| const handleCloseModal = () => { | |
| setModalOpen(false); | |
| }; | |
| const onButtonClick = () => { | |
| // `current` points to the mounted file input element | |
| inputFile?.current?.click(); | |
| }; | |
| const handleUpload = async () => { | |
| if (audioFile) { | |
| try { | |
| const server = import.meta.env.VITE_API_URL; | |
| const form = new FormData(); | |
| if (audioFile) { | |
| setModalOpen(true); | |
| const blob = new Blob([audioFile], { | |
| type: "application/octet-stream", | |
| }); | |
| const audio_file = new File([blob], audioFile.name, { | |
| type: blob.type, | |
| }); | |
| form.append("file", audio_file); | |
| } | |
| const response = await axios.post( | |
| `${server}/upload/`, | |
| form, | |
| { | |
| headers: { Accept: "multipart/form-data" }, | |
| responseType: "blob", | |
| } | |
| ); | |
| setUploadStatus("Upload successful. Waiting for generation..."); | |
| console.log("Upload successful:", response); | |
| // Extract JSON from the blob | |
| const blobText = await response.data.text(); | |
| const jsonFromBlob = JSON.parse(blobText); | |
| // Assuming the 'id' property is part of the JSON | |
| const file_path = jsonFromBlob.file_path; | |
| const csv_file_path = jsonFromBlob.csv_path; | |
| const output_file_path = jsonFromBlob.output_file_path; | |
| // Store the ID in localStorage | |
| localStorage.setItem("file_path", file_path); | |
| // Store the ID in localStorage | |
| localStorage.setItem("csv_file_path", csv_file_path); | |
| // Store the ID in localStorage | |
| localStorage.setItem("output_file_path", output_file_path); | |
| // Start uploading | |
| navigate("/Results"); | |
| // setUploadStatus('Generation complete!'); | |
| } catch (error) { | |
| console.error("Error:", error); | |
| props.handleClose(); | |
| setIsError(true); | |
| setModalOpen(false); | |
| setNextCard(false); | |
| setUploadStatus(`Error: ${error}`); | |
| } | |
| } | |
| }; | |
| return ( | |
| <> | |
| <Box sx={{ display: "grid", gap: "1vh" }}> | |
| <PaletteSwatch | |
| title={uploadStatus} | |
| titleColor={light.errorContainer} | |
| onTitle={uploadStatus} | |
| onTitleColor={light.onErrorContainer} | |
| visible={isError} | |
| /> | |
| <Card variant={isVisible ? "outlined" : "filled"}> | |
| <Box sx={{ display: NextCard ? "none" : "inherit" }}> | |
| <CardContent sx={{ display: "grid", justifyItems: "center" }}> | |
| <Typography gutterBottom variant="h5" sx={{ pb: 3 }}> | |
| {isVisible | |
| ? "Drop here to upload" | |
| : "Drag a file to start inference"} | |
| </Typography> | |
| <UploadFile sx={{ fontSize: "35px", color: "inherit" }} /> | |
| </CardContent> | |
| <CardActions sx={{ display: "flex", justifyContent: "flex-end" }}> | |
| <input | |
| type="file" | |
| accept="audio/*" | |
| ref={inputFile} | |
| style={{ display: "none" }} | |
| onChange={handleFileChange} | |
| /> | |
| <Button | |
| variant="filled" | |
| size="small" | |
| onClick={() => onButtonClick()} | |
| > | |
| Upload | |
| </Button> | |
| </CardActions> | |
| </Box> | |
| <Box sx={{ display: NextCard ? "inherit" : "none" }}> | |
| <CardContent | |
| sx={{ | |
| display: "flex", | |
| justifyItems: "center", | |
| flexDirection: "column", | |
| alignItems: "flex-end", | |
| gap: "1vh", | |
| }} | |
| > | |
| <Box sx={{ mr: "1" }}> | |
| <Button | |
| variant="text" | |
| sx={{fontSize:"10px", marginTop:-2, marginRight:-1.5}} | |
| onClick={() => { | |
| setNextCard(false); | |
| setIsVisible(false); | |
| }} | |
| > | |
| <Delete /> | |
| </Button> | |
| </Box> | |
| <Typography fontFamily={"monospace"} fontSize={"15pt"}> | |
| {audioFile?.name} | |
| </Typography> | |
| </CardContent> | |
| <CardActions sx={{ display: "flex", justifyContent: "center" }}> | |
| <Button | |
| variant="filled" | |
| size="medium" | |
| onClick={() => handleUpload()} | |
| > | |
| Confirm | |
| </Button> | |
| </CardActions> | |
| </Box> | |
| </Card> | |
| <Modal | |
| open={modalOpen} | |
| onClose={handleCloseModal} | |
| aria-labelledby="modal-modal-title" | |
| aria-describedby="modal-modal-description" | |
| > | |
| <Box sx={style_modal}> | |
| <CircularProgress size={60} thickness={4} /> | |
| </Box> | |
| </Modal> | |
| </Box> | |
| </> | |
| ); | |
| }; | |
| export default AudioUploader; | |
| const PaletteSwatch = ({ onTitle, titleColor, onTitleColor, visible }: any) => { | |
| return ( | |
| <Box | |
| sx={{ | |
| p: 1.5, | |
| borderRadius: "10px", | |
| bgcolor: onTitleColor, | |
| color: titleColor, | |
| visibility: visible ? "visible" : "collapse", | |
| }} | |
| > | |
| <Typography fontSize={12} fontWeight={"bold"}> | |
| {onTitle} | |
| </Typography> | |
| </Box> | |
| ); | |
| }; | |
| const style_modal = { | |
| position: "absolute" as "absolute", | |
| top: "50%", | |
| left: "50%", | |
| transform: "translate(-50%, -50%)", | |
| color: "inherit", | |
| bgcolor: "background.paper", | |
| p: 4, | |
| borderRadius: "10px", | |
| display: "flex", | |
| justifyContent: "center", | |
| alignTtems: "center", | |
| }; | |