Init diagnostics.

This commit is contained in:
James Pace 2026-08-14 17:50:07 -04:00
parent 6d32d2d005
commit 4d2ba762f3
9 changed files with 2966 additions and 4748 deletions

4439
.pnp.cjs generated

File diff suppressed because one or more lines are too long

1199
.pnp.loader.mjs generated

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
"prettier": "^3.8.1", "prettier": "^3.8.1",
"react": "^19.2.0", "react": "^19.2.0",
"react-bootstrap": "^2.10.10", "react-bootstrap": "^2.10.10",
"react-bootstrap-icons": "^1.11.6",
"react-dom": "^19.2.0", "react-dom": "^19.2.0",
"react-router-dom": "^7.13.1", "react-router-dom": "^7.13.1",
"yaml": "^2.8.2" "yaml": "^2.8.2"

View File

@ -14,6 +14,7 @@ import { Provider as JotaiProvider } from "jotai";
import { Home } from "./Home.tsx"; import { Home } from "./Home.tsx";
import { Autonomy } from "./Autonomy.tsx"; import { Autonomy } from "./Autonomy.tsx";
import { Version } from "./Version.tsx"; import { Version } from "./Version.tsx";
import { Diagnostics } from "./Diagnostics.tsx";
import "./App.css"; import "./App.css";
function App() { function App() {
@ -43,6 +44,10 @@ const router = createBrowserRouter([
path: "/autonomy", path: "/autonomy",
element: <Autonomy />, element: <Autonomy />,
}, },
{
path: "/diagnostics",
element: <Diagnostics />,
},
]); ]);
export default App; export default App;

70
src/Diagnostics.tsx Normal file
View File

@ -0,0 +1,70 @@
//
// Copyright 2026 James Pace
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, v. 2.0.
//
import { AppNav, Footer } from "./components/AppNav.tsx";
import { TreeView } from "./components/DiagnosticView.tsx";
import { Container, Row, Col, Card } from "react-bootstrap";
import { atom, useAtomValue } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";
const diagQueryFn = async () => {
const resp = await fetch("api/diagnostics");
if (!resp.ok) {
throw new Error("Network response was not ok");
}
return resp.json();
};
const diagQueryAtom = atomWithQuery(() => ({
queryKey: ["diagnostics"],
queryFn: diagQueryFn,
}));
const diagAtom = atom((get) => {
const diag = get(diagQueryAtom);
if (diag.isPending) {
return "Loading...";
}
if (diag.isError) {
return "Error loading!";
}
if (!diag.data.status) {
return "Failed to get diagnostic information.";
}
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}/>);
};
return (
<div>
<AppNav />
<Container className="vert-padded">
<Card className="padded">
<Card.Title>Diagnostics</Card.Title>
<Card.Body>
{diagContent()}
</Card.Body>
</Card>
</Container>
<Footer />
</div>
);
}

View File

@ -30,6 +30,9 @@ export function AppNav() {
<Nav.Link as={Link} to="/autonomy"> <Nav.Link as={Link} to="/autonomy">
Autonomy Autonomy
</Nav.Link> </Nav.Link>
<Nav.Link as={Link} to="/diagnostics">
Diagnostics
</Nav.Link>
</Nav> </Nav>
</Navbar.Collapse> </Navbar.Collapse>
</Container> </Container>

View File

@ -0,0 +1,71 @@
import React, { useState } from 'react';
import { ListGroup, Collapse } from 'react-bootstrap';
/*
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 })
{
return (
<ListGroup className="border-0">
{data.children.map(node => (
<TreeNode key={node.id} node={node} />
))}
</ListGroup>
);
};
function SingleNode({ node }) {
console.log(node);
return (
<div>
{node.name} {node.level}
</div>
);
}
function TreeNode({ node }) {
const [isOpen, setIsOpen] = useState(false);
const hasChildren = node.children && node.children.length > 0;
const onClick = () => {
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>
</ListGroup.Item>
);
};

View File

@ -1192,6 +1192,7 @@ __metadata:
prettier: "npm:^3.8.1" prettier: "npm:^3.8.1"
react: "npm:^19.2.0" react: "npm:^19.2.0"
react-bootstrap: "npm:^2.10.10" react-bootstrap: "npm:^2.10.10"
react-bootstrap-icons: "npm:^1.11.6"
react-dom: "npm:^19.2.0" react-dom: "npm:^19.2.0"
react-router-dom: "npm:^7.13.1" react-router-dom: "npm:^7.13.1"
typescript: "npm:~5.9.3" typescript: "npm:~5.9.3"
@ -2484,7 +2485,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"prop-types@npm:^15.6.2, prop-types@npm:^15.8.1": "prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
version: 15.8.1 version: 15.8.1
resolution: "prop-types@npm:15.8.1" resolution: "prop-types@npm:15.8.1"
dependencies: dependencies:
@ -2502,6 +2503,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"react-bootstrap-icons@npm:^1.11.6":
version: 1.11.6
resolution: "react-bootstrap-icons@npm:1.11.6"
dependencies:
prop-types: "npm:^15.7.2"
peerDependencies:
react: ">=16.8.6"
checksum: 10c0/4dfd75c980a4431032e7d861d52efeb18cb141e00300ae1cf055dcfcb1fd7689991d8b467c38f1103563662bbbd61aaf247093e7c04f6f1ad0aae86feff5047d
languageName: node
linkType: hard
"react-bootstrap@npm:^2.10.10": "react-bootstrap@npm:^2.10.10":
version: 2.10.10 version: 2.10.10
resolution: "react-bootstrap@npm:2.10.10" resolution: "react-bootstrap@npm:2.10.10"