Display the list of OTA updates in the frontend
This commit is contained in:
parent
2924d14281
commit
6cf7c2cae1
@ -49,3 +49,14 @@ pub fn get_ota_updates_for_platform(platform: OTAPlatform) -> anyhow::Result<Vec
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Get all the available OTA updates
|
||||
pub fn get_all_ota_updates() -> anyhow::Result<Vec<OTAUpdate>> {
|
||||
let mut out = vec![];
|
||||
|
||||
for p in OTAPlatform::supported_platforms() {
|
||||
out.append(&mut get_ota_updates_for_platform(*p)?)
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
@ -7,6 +7,13 @@ pub enum OTAPlatform {
|
||||
Wt32Eth01,
|
||||
}
|
||||
|
||||
impl OTAPlatform {
|
||||
/// Get the list of supported platforms
|
||||
pub fn supported_platforms() -> &'static [Self] {
|
||||
&[OTAPlatform::Wt32Eth01]
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for OTAPlatform {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let s = serde_json::to_string(&self).unwrap().replace('"', "");
|
||||
|
@ -191,7 +191,7 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
|
||||
"/web_api/ota/{platform}/{version}",
|
||||
web::post().to(ota_controller::upload_firmware),
|
||||
)
|
||||
// TODO : list all ota software updates
|
||||
.route("/web_api/ota", web::get().to(ota_controller::list_all_ota))
|
||||
.route(
|
||||
"/web_api/ota/{platform}",
|
||||
web::get().to(ota_controller::list_updates_platform),
|
||||
|
@ -10,7 +10,7 @@ use actix_multipart::form::MultipartForm;
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
pub async fn supported_platforms() -> HttpResult {
|
||||
Ok(HttpResponse::Ok().json(vec![OTAPlatform::Wt32Eth01]))
|
||||
Ok(HttpResponse::Ok().json(OTAPlatform::supported_platforms()))
|
||||
}
|
||||
|
||||
#[derive(Debug, MultipartForm)]
|
||||
@ -53,6 +53,11 @@ pub async fn upload_firmware(
|
||||
Ok(HttpResponse::Accepted().body("OTA update successfully saved."))
|
||||
}
|
||||
|
||||
/// Get the list of all OTA updates
|
||||
pub async fn list_all_ota() -> HttpResult {
|
||||
Ok(HttpResponse::Ok().json(ota_manager::get_all_ota_updates()?))
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct ListOTAPath {
|
||||
platform: OTAPlatform,
|
||||
|
10
central_frontend/package-lock.json
generated
10
central_frontend/package-lock.json
generated
@ -20,6 +20,7 @@
|
||||
"@types/semver": "^7.5.8",
|
||||
"date-and-time": "^3.6.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"filesize": "^10.1.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.26.2",
|
||||
@ -3232,6 +3233,15 @@
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/filesize": {
|
||||
"version": "10.1.6",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz",
|
||||
"integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">= 10.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
|
@ -22,6 +22,7 @@
|
||||
"@types/semver": "^7.5.8",
|
||||
"date-and-time": "^3.6.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"filesize": "^10.1.6",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.26.2",
|
||||
|
@ -1,5 +1,11 @@
|
||||
import { APIClient } from "./ApiClient";
|
||||
|
||||
export interface OTAUpdate {
|
||||
platform: string;
|
||||
version: string;
|
||||
file_size: number;
|
||||
}
|
||||
|
||||
export class OTAAPI {
|
||||
/**
|
||||
* Get the list of supported OTA platforms
|
||||
@ -30,4 +36,16 @@ export class OTAAPI {
|
||||
formData: fd,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of OTA updates
|
||||
*/
|
||||
static async ListOTAUpdates(): Promise<OTAUpdate[]> {
|
||||
return (
|
||||
await APIClient.exec({
|
||||
method: "GET",
|
||||
uri: "/ota",
|
||||
})
|
||||
).data;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,21 @@
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import {
|
||||
IconButton,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Tooltip,
|
||||
} from "@mui/material";
|
||||
import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer";
|
||||
import FileUploadIcon from "@mui/icons-material/FileUpload";
|
||||
import { UploadUpdateDialog } from "../dialogs/UploadUpdateDialog";
|
||||
import React from "react";
|
||||
import { OTAAPI } from "../api/OTAApi";
|
||||
import { OTAAPI, OTAUpdate } from "../api/OTAApi";
|
||||
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||
import { filesize } from "filesize";
|
||||
|
||||
export function OTARoute(): React.ReactElement {
|
||||
const [list, setList] = React.useState<string[] | undefined>();
|
||||
@ -24,10 +35,23 @@ export function OTARoute(): React.ReactElement {
|
||||
}
|
||||
|
||||
function _OTARoute(p: { platforms: Array<string> }): React.ReactElement {
|
||||
const key = React.useRef(1);
|
||||
const [showUploadDialog, setShowUploadDialog] = React.useState(false);
|
||||
|
||||
const [list, setList] = React.useState<undefined | OTAUpdate[]>();
|
||||
|
||||
const load = async () => {
|
||||
const list = await OTAAPI.ListOTAUpdates();
|
||||
list.sort((a, b) =>
|
||||
`${a.platform}#${a.version}`.localeCompare(`${b.platform}#${b.version}`)
|
||||
);
|
||||
list.reverse();
|
||||
setList(list);
|
||||
};
|
||||
|
||||
const reload = async () => {
|
||||
/*todo*/
|
||||
key.current += 1;
|
||||
setList(undefined);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -53,6 +77,38 @@ function _OTARoute(p: { platforms: Array<string> }): React.ReactElement {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<AsyncWidget
|
||||
loadKey={key.current}
|
||||
ready={!!list}
|
||||
errMsg="Failed to load the list of OTA updates!"
|
||||
load={load}
|
||||
build={() => <_OTAList list={list!} />}
|
||||
/>
|
||||
</SolarEnergyRouteContainer>
|
||||
);
|
||||
}
|
||||
|
||||
function _OTAList(p: { list: OTAUpdate[] }): React.ReactElement {
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{ minWidth: 650 }} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell align="center">Platform</TableCell>
|
||||
<TableCell align="center">Version</TableCell>
|
||||
<TableCell align="center">File size</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{p.list.map((row, num) => (
|
||||
<TableRow hover key={num}>
|
||||
<TableCell align="center">{row.platform}</TableCell>
|
||||
<TableCell align="center">{row.version}</TableCell>
|
||||
<TableCell align="center">{filesize(row.file_size)}</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user