Display the list of ISO files
This commit is contained in:
parent
e7d5747b99
commit
08b59b6f67
@ -8,6 +8,7 @@ use actix_web::{web, HttpResponse};
|
||||
use futures_util::StreamExt;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
#[derive(Debug, MultipartForm)]
|
||||
pub struct UploadIsoForm {
|
||||
@ -105,3 +106,23 @@ pub async fn upload_from_url(req: web::Json<DownloadFromURLReq>) -> HttpResult {
|
||||
|
||||
Ok(HttpResponse::Accepted().finish())
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct IsoFile {
|
||||
filename: String,
|
||||
size: u64,
|
||||
}
|
||||
|
||||
/// Get ISO files list
|
||||
pub async fn get_list() -> HttpResult {
|
||||
let mut list = vec![];
|
||||
for entry in AppConfig::get().iso_storage_path().read_dir()? {
|
||||
let entry = entry?;
|
||||
list.push(IsoFile {
|
||||
filename: entry.file_name().to_string_lossy().to_string(),
|
||||
size: entry.path().metadata()?.size(),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(list))
|
||||
}
|
||||
|
@ -108,6 +108,7 @@ async fn main() -> std::io::Result<()> {
|
||||
"/api/iso/upload_from_url",
|
||||
web::post().to(iso_controller::upload_from_url),
|
||||
)
|
||||
.route("/api/iso/list", web::get().to(iso_controller::get_list))
|
||||
})
|
||||
.bind(&AppConfig::get().listen_address)?
|
||||
.run()
|
||||
|
48
virtweb_frontend/package-lock.json
generated
48
virtweb_frontend/package-lock.json
generated
@ -15,6 +15,7 @@
|
||||
"@mdi/react": "^1.6.1",
|
||||
"@mui/icons-material": "^5.14.7",
|
||||
"@mui/material": "^5.14.7",
|
||||
"@mui/x-data-grid": "^6.12.1",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -3589,6 +3590,31 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/@mui/x-data-grid": {
|
||||
"version": "6.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.12.1.tgz",
|
||||
"integrity": "sha512-lSY1dFBv6yh2ffkkWeMM9c0ajpwIWn/da/ec0kY8OfLa79Hboh53mN09nopylZO8MHJGfDlPvduwuWcgWs+zFw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.22.11",
|
||||
"@mui/utils": "^5.14.7",
|
||||
"clsx": "^2.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"reselect": "^4.1.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/mui"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@mui/material": "^5.4.1",
|
||||
"@mui/system": "^5.4.1",
|
||||
"react": "^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||
"version": "5.1.1-v1",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||
@ -15303,6 +15329,11 @@
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||
},
|
||||
"node_modules/reselect": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.4",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
|
||||
@ -20424,6 +20455,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mui/x-data-grid": {
|
||||
"version": "6.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@mui/x-data-grid/-/x-data-grid-6.12.1.tgz",
|
||||
"integrity": "sha512-lSY1dFBv6yh2ffkkWeMM9c0ajpwIWn/da/ec0kY8OfLa79Hboh53mN09nopylZO8MHJGfDlPvduwuWcgWs+zFw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.22.11",
|
||||
"@mui/utils": "^5.14.7",
|
||||
"clsx": "^2.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"reselect": "^4.1.8"
|
||||
}
|
||||
},
|
||||
"@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||
"version": "5.1.1-v1",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||
@ -28769,6 +28812,11 @@
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
|
||||
},
|
||||
"reselect": {
|
||||
"version": "4.1.8",
|
||||
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
|
||||
"integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.4",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
|
||||
|
@ -10,6 +10,7 @@
|
||||
"@mdi/react": "^1.6.1",
|
||||
"@mui/icons-material": "^5.14.7",
|
||||
"@mui/material": "^5.14.7",
|
||||
"@mui/x-data-grid": "^6.12.1",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { APIClient } from "./ApiClient";
|
||||
|
||||
export interface IsoFile {
|
||||
filename: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export class IsoFilesApi {
|
||||
/**
|
||||
* Upload a new ISO file to the server
|
||||
@ -29,4 +34,16 @@ export class IsoFilesApi {
|
||||
jsonData: { url: url, filename: filename },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iso files list
|
||||
*/
|
||||
static async GetList(): Promise<IsoFile[]> {
|
||||
return (
|
||||
await APIClient.exec({
|
||||
method: "GET",
|
||||
uri: "/iso/list",
|
||||
})
|
||||
).data;
|
||||
}
|
||||
}
|
||||
|
@ -2,22 +2,44 @@ import { Button, LinearProgress, TextField, Typography } from "@mui/material";
|
||||
import { filesize } from "filesize";
|
||||
import { MuiFileInput } from "mui-file-input";
|
||||
import React from "react";
|
||||
import { IsoFilesApi } from "../api/IsoFilesApi";
|
||||
import { IsoFile, IsoFilesApi } from "../api/IsoFilesApi";
|
||||
import { ServerApi } from "../api/ServerApi";
|
||||
import { useAlert } from "../hooks/providers/AlertDialogProvider";
|
||||
import { useSnackbar } from "../hooks/providers/SnackbarProvider";
|
||||
import { VirtWebPaper } from "../widgets/VirtWebPaper";
|
||||
import { VirtWebRouteContainer } from "../widgets/VirtWebRouteContainer";
|
||||
import { useLoadingMessage } from "../hooks/providers/LoadingMessageProvider";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { DataGrid, GridColDef, GridRowsProp } from "@mui/x-data-grid";
|
||||
|
||||
export function IsoFilesRoute(): React.ReactElement {
|
||||
const [list, setList] = React.useState<IsoFile[] | undefined>();
|
||||
|
||||
const loadKey = React.useRef(1);
|
||||
|
||||
const load = async () => {
|
||||
setList(await IsoFilesApi.GetList());
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
loadKey.current += 1;
|
||||
setList(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
<VirtWebRouteContainer label="ISO files management">
|
||||
<UploadIsoFileCard onFileUploaded={() => alert("file uploaded!")} />
|
||||
<UploadIsoFileFromUrlCard
|
||||
onFileUploaded={() => alert("file uploaded!")}
|
||||
/>
|
||||
</VirtWebRouteContainer>
|
||||
<AsyncWidget
|
||||
loadKey={loadKey.current}
|
||||
errMsg="Failed to load ISO files list!"
|
||||
load={load}
|
||||
ready={list !== undefined}
|
||||
build={() => (
|
||||
<VirtWebRouteContainer label="ISO files management">
|
||||
<UploadIsoFileCard onFileUploaded={reload} />
|
||||
<UploadIsoFileFromUrlCard onFileUploaded={reload} />
|
||||
<IsoFilesList list={list!} onReload={reload} />
|
||||
</VirtWebRouteContainer>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -145,3 +167,38 @@ function UploadIsoFileFromUrlCard(p: {
|
||||
</VirtWebPaper>
|
||||
);
|
||||
}
|
||||
|
||||
function IsoFilesList(p: {
|
||||
list: IsoFile[];
|
||||
onReload: () => void;
|
||||
}): React.ReactElement {
|
||||
if (p.list.length === 0)
|
||||
return (
|
||||
<Typography variant="body1" style={{ textAlign: "center" }}>
|
||||
No ISO file uploaded for now.
|
||||
</Typography>
|
||||
);
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
{ field: "filename", headerName: "File name", flex: 3 },
|
||||
{
|
||||
field: "size",
|
||||
headerName: "File size",
|
||||
flex: 1,
|
||||
renderCell(params) {
|
||||
return filesize(params.row.size);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<VirtWebPaper label="Files list">
|
||||
<DataGrid
|
||||
getRowId={(c) => c.filename}
|
||||
rows={p.list}
|
||||
columns={columns}
|
||||
autoHeight={true}
|
||||
/>
|
||||
</VirtWebPaper>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user