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

4499
.pnp.cjs generated

File diff suppressed because one or more lines are too long

1205
.pnp.loader.mjs generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -14,6 +14,7 @@ import { Provider as JotaiProvider } from "jotai";
import { Home } from "./Home.tsx";
import { Autonomy } from "./Autonomy.tsx";
import { Version } from "./Version.tsx";
import { Diagnostics } from "./Diagnostics.tsx";
import "./App.css";
function App() {
@ -43,6 +44,10 @@ const router = createBrowserRouter([
path: "/autonomy",
element: <Autonomy />,
},
{
path: "/diagnostics",
element: <Diagnostics />,
},
]);
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">
Autonomy
</Nav.Link>
<Nav.Link as={Link} to="/diagnostics">
Diagnostics
</Nav.Link>
</Nav>
</Navbar.Collapse>
</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"
react: "npm:^19.2.0"
react-bootstrap: "npm:^2.10.10"
react-bootstrap-icons: "npm:^1.11.6"
react-dom: "npm:^19.2.0"
react-router-dom: "npm:^7.13.1"
typescript: "npm:~5.9.3"
@ -2484,7 +2485,7 @@ __metadata:
languageName: node
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
resolution: "prop-types@npm:15.8.1"
dependencies:
@ -2502,6 +2503,17 @@ __metadata:
languageName: node
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":
version: 2.10.10
resolution: "react-bootstrap@npm:2.10.10"