minecluster/src/components/files/FilePreview.jsx

92 lines
2.8 KiB
JavaScript

import { useState, useEffect, memo } from "react";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme } from "@mui/material/styles";
import Button from "@mui/material/Button";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import Dialog from "@mui/material/Dialog";
import Toolbar from "@mui/material/Toolbar";
import TextEditor from "./TextEditor.jsx";
import { cairoAuthHeader } from "@mcl/util/auth.js";
const textFileTypes = ["properties", "txt", "yaml", "yml", "json", "env"];
const imageFileTypes = ["png", "jpeg", "jpg"];
export const supportedFileTypes = [...textFileTypes, ...imageFileTypes];
export function useFilePreview(isOpen = false) {
const [open, setOpen] = useState(isOpen);
const dialogToggle = () => setOpen(!open);
return [open, dialogToggle];
}
export default function FilePreview(props) {
const [fileText, setFileText] = useState();
const [modifiedText, setModifiedText] = useState();
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down("md"));
const { previewData, open, dialogToggle, server: serverId } = props;
const { fileData, name, filePath } = previewData ?? {};
const ext = name ? name.split(".").pop() : null;
const isTextFile = textFileTypes.includes(ext);
useEffect(() => {
onPreviewChange();
}, [fileData]);
const editorChange = (v) => setModifiedText(v);
async function onPreviewChange() {
if (!isTextFile) return;
const text = await fileData.text();
setFileText(text);
}
async function onSave() {
const formData = new FormData();
const blob = new Blob([modifiedText], { type: "plain/text" });
formData.append("file", blob, name);
formData.append("id", serverId);
formData.append("path", filePath);
await fetch("/api/files/upload", {
method: "POST",
body: formData,
headers: cairoAuthHeader(),
});
dialogToggle();
}
return (
<Dialog
sx={
fullScreen
? {}
: {
"& .mcl-MuiDialog-paper": {
width: "100%",
maxHeight: 525,
maxWidth: "80%",
},
}
}
maxWidth="xs"
open={open}
fullScreen={fullScreen}
>
<Toolbar sx={{ display: { sm: "none" } }} />
<DialogTitle>{name}</DialogTitle>
<DialogContent>
<TextEditor text={fileText} onChange={editorChange} />
</DialogContent>
<DialogActions>
<Button autoFocus onClick={dialogToggle}>
Close
</Button>
<Button variant="contained" autoFocus onClick={onSave}>
Save
</Button>
</DialogActions>
</Dialog>
);
}