Can upload disk images on the server
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
151
virtweb_frontend/src/routes/DiskImagesRoute.tsx
Normal file
151
virtweb_frontend/src/routes/DiskImagesRoute.tsx
Normal file
@ -0,0 +1,151 @@
|
||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||
import {
|
||||
Button,
|
||||
IconButton,
|
||||
LinearProgress,
|
||||
Tooltip,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { filesize } from "filesize";
|
||||
import React from "react";
|
||||
import { DiskImage, DiskImageApi } from "../api/DiskImageApi";
|
||||
import { ServerApi } from "../api/ServerApi";
|
||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { FileInput } from "../widgets/forms/FileInput";
|
||||
import { VirtWebPaper } from "../widgets/VirtWebPaper";
|
||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
||||
|
||||
export function DiskImagesRoute(): React.ReactElement {
|
||||
const [list, setList] = React.useState<DiskImage[] | undefined>();
|
||||
|
||||
const loadKey = React.useRef(1);
|
||||
|
||||
const load = async () => {
|
||||
setList(await DiskImageApi.GetList());
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
loadKey.current += 1;
|
||||
setList(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<VirtWebRouteContainer label="Disk images">
|
||||
<AsyncWidget
|
||||
loadKey={loadKey.current}
|
||||
errMsg="Failed to load disk images list!"
|
||||
load={load}
|
||||
ready={list !== undefined}
|
||||
build={() => (
|
||||
<VirtWebRouteContainer
|
||||
label="Disk images management"
|
||||
actions={
|
||||
<span>
|
||||
<Tooltip title="Refresh Disk images list">
|
||||
<IconButton onClick={reload}>
|
||||
<RefreshIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<UploadDiskImageCard onFileUploaded={reload} />
|
||||
<DiskImageList list={list!} onReload={reload} />
|
||||
</VirtWebRouteContainer>
|
||||
)}
|
||||
/>
|
||||
</VirtWebRouteContainer>
|
||||
);
|
||||
}
|
||||
|
||||
function UploadDiskImageCard(p: {
|
||||
onFileUploaded: () => void;
|
||||
}): React.ReactElement {
|
||||
const alert = useAlert();
|
||||
const snackbar = useSnackbar();
|
||||
|
||||
const [value, setValue] = React.useState<File | null>(null);
|
||||
const [uploadProgress, setUploadProgress] = React.useState<number | null>(
|
||||
null
|
||||
);
|
||||
|
||||
const handleChange = (newValue: File | null) => {
|
||||
if (
|
||||
newValue &&
|
||||
newValue.size > ServerApi.Config.constraints.disk_image_max_size
|
||||
) {
|
||||
alert(
|
||||
`The file is too big (max size allowed: ${filesize(
|
||||
ServerApi.Config.constraints.disk_image_max_size
|
||||
)}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
newValue &&
|
||||
!ServerApi.Config.disk_images_mimetypes.includes(newValue.type)
|
||||
) {
|
||||
alert(`Selected file mimetype is not allowed! (${newValue.type})`);
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const upload = async () => {
|
||||
try {
|
||||
setUploadProgress(0);
|
||||
await DiskImageApi.Upload(value!, setUploadProgress);
|
||||
|
||||
setValue(null);
|
||||
snackbar("The file was successfully uploaded!");
|
||||
|
||||
p.onFileUploaded();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
await alert(`Failed to perform file upload! ${e}`);
|
||||
}
|
||||
|
||||
setUploadProgress(null);
|
||||
};
|
||||
|
||||
if (uploadProgress !== null) {
|
||||
return (
|
||||
<VirtWebPaper label="File upload" noHorizontalMargin>
|
||||
<Typography variant="body1">
|
||||
Upload in progress ({Math.floor(uploadProgress * 100)}%)...
|
||||
</Typography>
|
||||
<LinearProgress variant="determinate" value={uploadProgress * 100} />
|
||||
</VirtWebPaper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<VirtWebPaper label="Disk image upload" noHorizontalMargin>
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<FileInput
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
style={{ flex: 1 }}
|
||||
slotProps={{
|
||||
htmlInput: {
|
||||
accept: ServerApi.Config.disk_images_mimetypes.join(","),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
{value && <Button onClick={upload}>Upload</Button>}
|
||||
</div>
|
||||
</VirtWebPaper>
|
||||
);
|
||||
}
|
||||
|
||||
function DiskImageList(p: {
|
||||
list: DiskImage[];
|
||||
onReload: () => void;
|
||||
}): React.ReactElement {
|
||||
return <>todo</>;
|
||||
}
|
Reference in New Issue
Block a user