First pass diagnostics display.

This commit is contained in:
James Pace 2026-08-16 20:51:31 -04:00
parent 9d3767d68c
commit 1e16d0e482
5 changed files with 4892 additions and 2844 deletions

4484
.pnp.cjs generated

File diff suppressed because one or more lines are too long

1207
.pnp.loader.mjs generated

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,8 @@ export function Autonomy() {
const statusString = useAtomValue(statusStringAtom);
const latLong = useAtomValue(latLongAtom);
const imageStreamURI = "http://" + window.location.hostname + ":8889/image/whep";
const imageStreamURI =
"http://" + window.location.hostname + ":8889/image/whep";
return (
<div>
@ -68,7 +69,7 @@ export function Autonomy() {
<Row>
<Col lg={8}>
<WebRTCVideo
url={ imageStreamURI }
url={imageStreamURI}
controls
autoPlay
style={{ width: "100%", maxWidth: "800px" }}

View File

@ -38,30 +38,26 @@ const diagAtom = atom((get) => {
if (!diag.data.status) {
return "Failed to get diagnostic information.";
}
return diag.data.message
return diag.data.message;
});
export function Diagnostics() {
const diagnostics = useAtomValue(diagAtom);
const diagContent = () => {
if (typeof diagnostics === 'string' || diagnostics instanceof String)
{
return (<pre> {diagnostics} </pre>);
if (typeof diagnostics === "string" || diagnostics instanceof String) {
return <pre> {diagnostics} </pre>;
}
return (<TreeView data={diagnostics}/>);
return <TreeView data={diagnostics} />;
};
return (
<div>
<AppNav />
<Container className="vert-padded">
<Card className="padded">
<Card.Title>Diagnostics</Card.Title>
<Card.Body>
{diagContent()}
</Card.Body>
<Card.Body>{diagContent()}</Card.Body>
</Card>
</Container>
<Footer />

View File

@ -1,71 +1,153 @@
import React, { useState } from 'react';
import { ListGroup, Collapse } from 'react-bootstrap';
import React, { useState } from "react";
import { Button, ListGroup, Collapse, Card } from "react-bootstrap";
import {
Dash,
ChevronDown,
ChevronRight,
CircleFill,
} from "react-bootstrap-icons";
import Table from "react-bootstrap/Table";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
/*
const treeData = [
{
id: 1,
label: "Documents",
children: [
{ id: 2, label: "Resume.pdf" },
{ id: 3, label: "CoverLetter.pdf" }
]
},
{
id: 4,
label: "Pictures",
children: [
{ id: 5, label: "Vacation.jpg" }
]
}
];
*/
export function TreeView({ data })
{
export function TreeView(props: Any) {
const data = props.data;
return (
<ListGroup className="border-0">
{data.children.map(node => (
<TreeNode key={node.id} node={node} />
{data.children.map((node) => (
<SingleNode key={node.id} node={node} />
))}
</ListGroup>
);
};
}
function SingleNode({ node }) {
console.log(node);
function LevelIndicator(props: Any) {
const level = props.level;
if (level == "ERROR") {
return <CircleFill color="red" />;
}
if (level == "WARN") {
return <CircleFill color="orange" />;
}
if (level == "OK") {
return <CircleFill color="green" />;
}
return <CircleFill color="grey" />;
}
function MessageText(props: Any) {
if (props.message === "") {
return <div></div>;
}
return <div>Message: {props.message}</div>;
}
function ValuesTable(props: Any) {
const values = props.values;
if (Object.keys(values).length === 0) {
return <div></div>;
}
return (
<div>
{node.name} {node.level}
</div>
<Table>
<thead>
<th>Key</th>
<th>Value</th>
</thead>
<tbody>
{Object.entries(values).map(([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>{value}</td>
</tr>
))}
</tbody>
</Table>
);
}
function TreeNode({ node }) {
function StatusContent(props: Any) {
const status = props.status;
console.log(status);
return (
<Card.Body>
<Card.Title>
<LevelIndicator level={status.level} /> {status.name}
</Card.Title>
<Card.Text>
<MessageText message={status.message} />
</Card.Text>
<Card.Text>
<ValuesTable values={status.values} />
</Card.Text>
</Card.Body>
);
}
function DirectionIcon(props: Any) {
let icon = <ChevronRight />;
if (props.isOpen) {
icon = <ChevronDown />;
}
if (!props.hasChildren) {
icon = <Dash />;
}
return (
<Button variant="link" onClick={props.onClick}>
{icon}
</Button>
);
}
function ChildStatuses(props: Any) {
const isOpen = props.isOpen;
const node = props.node;
return (
<Collapse in={isOpen}>
<div>
<ListGroup className="ms-2 border-start">
{node.children.map((child) => (
<SingleNode key={child.id} node={child} />
))}
</ListGroup>
</div>
</Collapse>
);
}
function SingleNode(props: Any) {
const node = props.node;
const [isOpen, setIsOpen] = useState(false);
const hasChildren = node.children && node.children.length > 0;
const onClick = () => {
if(hasChildren) {
const openFunction = () => {
if (hasChildren) {
setIsOpen(!isOpen);
}
};
return (
<ListGroup.Item className="border-0 ps-3 py-1">
<div onClick={onClick}>
<SingleNode node={node.status} />
</div>
<Collapse in={isOpen}>
<div>
<ListGroup className="ms-2 border-start">
{node.children.map(child => (
<TreeNode key={child.id} node={child} />
))}
</ListGroup>
</div>
</Collapse>
<Card>
<Container>
<Row>
<Col xs={1}>
<DirectionIcon
isOpen={isOpen}
hasChildren={hasChildren}
onClick={openFunction}
/>
</Col>
<Col xs={"auto"}>
<StatusContent status={node.status} />
</Col>
</Row>
<Row>
<ChildStatuses isOpen={isOpen} node={node} />
</Row>
</Container>
</Card>
</ListGroup.Item>
);
};
}