Display the list of uploaded disk images
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import DeleteIcon from "@mui/icons-material/Delete";
|
||||||
|
import DownloadIcon from "@mui/icons-material/Download";
|
||||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -6,6 +8,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import { DataGrid, GridColDef } from "@mui/x-data-grid";
|
||||||
import { filesize } from "filesize";
|
import { filesize } from "filesize";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { DiskImage, DiskImageApi } from "../api/DiskImageApi";
|
import { DiskImage, DiskImageApi } from "../api/DiskImageApi";
|
||||||
@@ -13,6 +16,7 @@ import { ServerApi } from "../api/ServerApi";
|
|||||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
||||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
|
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
|
||||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
|
import { DateWidget } from "../widgets/DateWidget";
|
||||||
import { FileInput } from "../widgets/forms/FileInput";
|
import { FileInput } from "../widgets/forms/FileInput";
|
||||||
import { VirtWebPaper } from "../widgets/VirtWebPaper";
|
import { VirtWebPaper } from "../widgets/VirtWebPaper";
|
||||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
||||||
@@ -32,28 +36,28 @@ export function DiskImagesRoute(): React.ReactElement {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VirtWebRouteContainer label="Disk images">
|
<VirtWebRouteContainer
|
||||||
|
label="Disk images management"
|
||||||
|
actions={
|
||||||
|
<span>
|
||||||
|
<Tooltip title="Refresh Disk images list">
|
||||||
|
<IconButton onClick={reload}>
|
||||||
|
<RefreshIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
<AsyncWidget
|
<AsyncWidget
|
||||||
loadKey={loadKey.current}
|
loadKey={loadKey.current}
|
||||||
errMsg="Failed to load disk images list!"
|
errMsg="Failed to load disk images list!"
|
||||||
load={load}
|
load={load}
|
||||||
ready={list !== undefined}
|
ready={list !== undefined}
|
||||||
build={() => (
|
build={() => (
|
||||||
<VirtWebRouteContainer
|
<>
|
||||||
label="Disk images management"
|
|
||||||
actions={
|
|
||||||
<span>
|
|
||||||
<Tooltip title="Refresh Disk images list">
|
|
||||||
<IconButton onClick={reload}>
|
|
||||||
<RefreshIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<UploadDiskImageCard onFileUploaded={reload} />
|
<UploadDiskImageCard onFileUploaded={reload} />
|
||||||
<DiskImageList list={list!} onReload={reload} />
|
<DiskImageList list={list!} onReload={reload} />
|
||||||
</VirtWebRouteContainer>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</VirtWebRouteContainer>
|
</VirtWebRouteContainer>
|
||||||
@@ -148,5 +152,53 @@ function DiskImageList(p: {
|
|||||||
list: DiskImage[];
|
list: DiskImage[];
|
||||||
onReload: () => void;
|
onReload: () => void;
|
||||||
}): React.ReactElement {
|
}): React.ReactElement {
|
||||||
return <>todo</>;
|
const columns: GridColDef<(typeof p.list)[number]>[] = [
|
||||||
|
{ field: "file_name", headerName: "File name", flex: 3 },
|
||||||
|
{
|
||||||
|
field: "format",
|
||||||
|
headerName: "Format",
|
||||||
|
flex: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "file_size",
|
||||||
|
headerName: "File size",
|
||||||
|
flex: 1,
|
||||||
|
renderCell(params) {
|
||||||
|
return filesize(params.row.file_size);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "created",
|
||||||
|
headerName: "Created",
|
||||||
|
flex: 1,
|
||||||
|
renderCell(params) {
|
||||||
|
return <DateWidget time={params.row.created} />;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "actions",
|
||||||
|
headerName: "",
|
||||||
|
width: 120,
|
||||||
|
renderCell(params) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tooltip title="Download image">
|
||||||
|
<IconButton onClick={() => downloadIso(params.row)}>
|
||||||
|
<DownloadIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title="Delete file">
|
||||||
|
<IconButton onClick={() => deleteIso(params.row)}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataGrid getRowId={(c) => c.file_name} rows={p.list} columns={columns} />
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
13
virtweb_frontend/src/widgets/DateWidget.tsx
Normal file
13
virtweb_frontend/src/widgets/DateWidget.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export function DateWidget(p: { time: number }): React.ReactElement {
|
||||||
|
const date = new Date(p.time * 1000);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{pad(date.getDate())}/{pad(date.getMonth() + 1)}/{date.getFullYear()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pad(num: number): string {
|
||||||
|
return num.toString().padStart(2, "0");
|
||||||
|
}
|
Reference in New Issue
Block a user