Display basic device information
This commit is contained in:
parent
7be81fe0e9
commit
1ce9ca3321
@ -139,6 +139,10 @@ pub async fn secure_server(energy_actor: EnergyActorAddr) -> anyhow::Result<()>
|
|||||||
"/web_api/devices/list_validated",
|
"/web_api/devices/list_validated",
|
||||||
web::get().to(devices_controller::list_validated),
|
web::get().to(devices_controller::list_validated),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/web_api/device/{id}",
|
||||||
|
web::get().to(devices_controller::get_single),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
"/web_api/device/{id}/validate",
|
"/web_api/device/{id}/validate",
|
||||||
web::post().to(devices_controller::validate_device),
|
web::post().to(devices_controller::validate_device),
|
||||||
|
@ -33,6 +33,18 @@ pub struct DeviceInPath {
|
|||||||
id: DeviceId,
|
id: DeviceId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a single device information
|
||||||
|
pub async fn get_single(actor: WebEnergyActor, id: web::Path<DeviceInPath>) -> HttpResult {
|
||||||
|
let Some(dev) = actor
|
||||||
|
.send(energy_actor::GetSingleDevice(id.id.clone()))
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(HttpResponse::NotFound().json("Requested device was not found!"));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(dev))
|
||||||
|
}
|
||||||
|
|
||||||
/// Validate a device
|
/// Validate a device
|
||||||
pub async fn validate_device(actor: WebEnergyActor, id: web::Path<DeviceInPath>) -> HttpResult {
|
pub async fn validate_device(actor: WebEnergyActor, id: web::Path<DeviceInPath>) -> HttpResult {
|
||||||
actor
|
actor
|
||||||
|
@ -12,6 +12,7 @@ import { HomeRoute } from "./routes/HomeRoute";
|
|||||||
import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
|
import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
|
||||||
import { PendingDevicesRoute } from "./routes/PendingDevicesRoute";
|
import { PendingDevicesRoute } from "./routes/PendingDevicesRoute";
|
||||||
import { DevicesRoute } from "./routes/DevicesRoute";
|
import { DevicesRoute } from "./routes/DevicesRoute";
|
||||||
|
import { DeviceRoute } from "./routes/DeviceRoute";
|
||||||
|
|
||||||
export function App() {
|
export function App() {
|
||||||
if (!AuthApi.SignedIn && !ServerApi.Config.auth_disabled)
|
if (!AuthApi.SignedIn && !ServerApi.Config.auth_disabled)
|
||||||
@ -21,8 +22,9 @@ export function App() {
|
|||||||
createRoutesFromElements(
|
createRoutesFromElements(
|
||||||
<Route path="*" element={<BaseAuthenticatedPage />}>
|
<Route path="*" element={<BaseAuthenticatedPage />}>
|
||||||
<Route path="" element={<HomeRoute />} />
|
<Route path="" element={<HomeRoute />} />
|
||||||
<Route path="devices" element={<DevicesRoute />} />
|
|
||||||
<Route path="pending_devices" element={<PendingDevicesRoute />} />
|
<Route path="pending_devices" element={<PendingDevicesRoute />} />
|
||||||
|
<Route path="devices" element={<DevicesRoute />} />
|
||||||
|
<Route path="dev/:id" element={<DeviceRoute />} />
|
||||||
<Route path="*" element={<NotFoundRoute />} />
|
<Route path="*" element={<NotFoundRoute />} />
|
||||||
</Route>
|
</Route>
|
||||||
)
|
)
|
||||||
|
@ -37,8 +37,8 @@ export interface Device {
|
|||||||
relays: DeviceRelay[];
|
relays: DeviceRelay[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DeviceURL(d: Device, edit: boolean = false): string {
|
export function DeviceURL(d: Device): string {
|
||||||
return `/dev/${d.id}${edit ? "/edit" : ""}`;
|
return `/dev/${encodeURIComponent(d.id)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DeviceApi {
|
export class DeviceApi {
|
||||||
@ -76,6 +76,18 @@ export class DeviceApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the information about a single device
|
||||||
|
*/
|
||||||
|
static async GetSingle(id: string): Promise<Device> {
|
||||||
|
return (
|
||||||
|
await APIClient.exec({
|
||||||
|
uri: `/device/${encodeURIComponent(id)}`,
|
||||||
|
method: "GET",
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a device
|
* Delete a device
|
||||||
*/
|
*/
|
||||||
|
102
central_frontend/src/routes/DeviceRoute.tsx
Normal file
102
central_frontend/src/routes/DeviceRoute.tsx
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { Device, DeviceApi } from "../api/DeviceApi";
|
||||||
|
import React from "react";
|
||||||
|
import { AsyncWidget } from "../widgets/AsyncWidget";
|
||||||
|
import { SolarEnergyRouteContainer } from "../widgets/SolarEnergyRouteContainer";
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableRow,
|
||||||
|
Typography,
|
||||||
|
} from "@mui/material";
|
||||||
|
|
||||||
|
export function DeviceRoute(): React.ReactElement {
|
||||||
|
const { id } = useParams();
|
||||||
|
const [device, setDevice] = React.useState<Device | undefined>();
|
||||||
|
|
||||||
|
const loadKey = React.useRef(1);
|
||||||
|
|
||||||
|
const load = async () => {
|
||||||
|
setDevice(await DeviceApi.GetSingle(id!));
|
||||||
|
};
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
loadKey.current += 1;
|
||||||
|
setDevice(undefined);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AsyncWidget
|
||||||
|
loadKey={loadKey.current}
|
||||||
|
errMsg="Failed to load device information"
|
||||||
|
load={load}
|
||||||
|
ready={!!device}
|
||||||
|
build={() => <DeviceRouteInner device={device!} onReload={reload} />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeviceRouteInner(p: {
|
||||||
|
device: Device;
|
||||||
|
onReload: () => void;
|
||||||
|
}): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<SolarEnergyRouteContainer label={`Device ${p.device.name}`}>
|
||||||
|
<GeneralDeviceInfo {...p} />
|
||||||
|
</SolarEnergyRouteContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function GeneralDeviceInfo(p: { device: Device }): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Typography variant="h6" style={{ padding: "6px" }}>
|
||||||
|
General device information
|
||||||
|
</Typography>
|
||||||
|
<Table size="small">
|
||||||
|
<TableBody>
|
||||||
|
<DeviceInfoProperty label="ID" value={p.device.id} />
|
||||||
|
<DeviceInfoProperty
|
||||||
|
label="Reference"
|
||||||
|
value={p.device.info.reference}
|
||||||
|
/>
|
||||||
|
<DeviceInfoProperty label="Version" value={p.device.info.version} />
|
||||||
|
<DeviceInfoProperty label="Name" value={p.device.name} />
|
||||||
|
<DeviceInfoProperty
|
||||||
|
label="Description"
|
||||||
|
value={p.device.description}
|
||||||
|
/>
|
||||||
|
<DeviceInfoProperty
|
||||||
|
label="Enabled"
|
||||||
|
value={p.device.enabled ? "YES" : "NO"}
|
||||||
|
/>
|
||||||
|
<DeviceInfoProperty
|
||||||
|
label="Maximum number of relays"
|
||||||
|
value={p.device.info.max_relays.toString()}
|
||||||
|
/>
|
||||||
|
<DeviceInfoProperty
|
||||||
|
label="Number of configured relays"
|
||||||
|
value={p.device.relays.length.toString()}
|
||||||
|
/>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DeviceInfoProperty(p: {
|
||||||
|
icon?: React.ReactElement;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<TableRow hover sx={{ "&:last-child td, &:last-child th": { border: 0 } }}>
|
||||||
|
<TableCell>{p.label}</TableCell>
|
||||||
|
<TableCell>{p.value}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user