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

6294
.pnp.cjs generated

File diff suppressed because one or more lines are too long

1225
.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,20 +38,18 @@ 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>);
}
return (<TreeView data={diagnostics}/>);
};
const diagContent = () => {
if (typeof diagnostics === "string" || diagnostics instanceof String) {
return <pre> {diagnostics} </pre>;
}
return <TreeView data={diagnostics} />;
};
return (
<div>
@ -59,9 +57,7 @@ export function Diagnostics() {
<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);
return (
<div>
{node.name} {node.level}
</div>
);
}
function TreeNode({ 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 (
<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 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) {
setIsOpen(!isOpen);
}
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>
);
};
}