Init diagnostics.
This commit is contained in:
1 parent
6d32d2d005
commit
4d2ba762f3
9 files changed
+2966
-4748
No files matched your search
@@ -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;
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user