Compare commits
No commits in common. "86870c4d2af5ece3d711add526765f57ee1ae50c" and "bb35a80e97912a40bdb228275a0e960aebde469a" have entirely different histories.
86870c4d2a
...
bb35a80e97
11
src/App.tsx
11
src/App.tsx
|
|
@ -2,9 +2,8 @@ import { useState } from "react";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import { Provider as JotaiProvider } from "jotai";
|
import { Provider as JotaiProvider } from "jotai";
|
||||||
import { Home } from "./Home.tsx";
|
import { Home } from "./Home.tsx";
|
||||||
import { Autonomy } from "./Autonomy.tsx";
|
|
||||||
import { Version } from "./Version.tsx";
|
import { Version } from "./Version.tsx";
|
||||||
import { WhoAmI } from "./WhoAmI.tsx";
|
import { Network } from "./Network.tsx";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
@ -27,17 +26,13 @@ const router = createBrowserRouter([
|
||||||
element: <Home />,
|
element: <Home />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/whoami",
|
path: "/network",
|
||||||
element: <WhoAmI />,
|
element: <Network />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/version",
|
path: "/version",
|
||||||
element: <Version />,
|
element: <Version />,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/autonomy",
|
|
||||||
element: <Autonomy />,
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ export function AppNav() {
|
||||||
<Navbar bg="dark" variant="dark" expand="sm" className="py-0">
|
<Navbar bg="dark" variant="dark" expand="sm" className="py-0">
|
||||||
<Container className="me-auto">
|
<Container className="me-auto">
|
||||||
<Navbar.Brand as={Link} to="/">
|
<Navbar.Brand as={Link} to="/">
|
||||||
J7s-Bridge
|
N-DRIVE
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
<Navbar.Toggle aria-controls="collapse-navbar-nav" />
|
<Navbar.Toggle aria-controls="collapse-navbar-nav" />
|
||||||
<Navbar.Collapse id="collapse-navbar-nav">
|
<Navbar.Collapse id="collapse-navbar-nav">
|
||||||
|
|
@ -17,11 +17,8 @@ export function AppNav() {
|
||||||
<Nav.Link as={Link} to="/version">
|
<Nav.Link as={Link} to="/version">
|
||||||
Version
|
Version
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
<Nav.Link as={Link} to="/whoami">
|
<Nav.Link as={Link} to="/network">
|
||||||
WhoAmI
|
Network
|
||||||
</Nav.Link>
|
|
||||||
<Nav.Link as={Link} to="/autonomy">
|
|
||||||
Autonomy
|
|
||||||
</Nav.Link>
|
</Nav.Link>
|
||||||
</Nav>
|
</Nav>
|
||||||
</Navbar.Collapse>
|
</Navbar.Collapse>
|
||||||
|
|
@ -31,5 +28,5 @@ export function AppNav() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return <p className="footer">Copyright 2026 James Pace</p>;
|
return <p className="footer">Made with {"<3"} by James Pace.</p>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
import { AppNav, Footer } from "./AppNav.tsx";
|
|
||||||
import { Container, Row, Col, Image, Card } from "react-bootstrap";
|
|
||||||
import { atom, useAtomValue } from "jotai";
|
|
||||||
import { atomWithQuery } from "jotai-tanstack-query";
|
|
||||||
|
|
||||||
const costmapImageQuery = async () => {
|
|
||||||
const resp = await fetch("api/costmap_image");
|
|
||||||
if (!resp.ok) {
|
|
||||||
throw new Error("Network response was not ok");
|
|
||||||
}
|
|
||||||
const blob = await resp.blob();
|
|
||||||
return URL.createObjectURL(blob);
|
|
||||||
};
|
|
||||||
const costmapImageQueryAtom = atomWithQuery(() => ({
|
|
||||||
queryKey: ["costmap_image"],
|
|
||||||
queryFn: costmapImageQuery,
|
|
||||||
refetchInterval: 1000, // 1s
|
|
||||||
}));
|
|
||||||
const costmapImageAtom = atom((get) => {
|
|
||||||
const response = get(costmapImageQueryAtom);
|
|
||||||
if (response.isPending) {
|
|
||||||
return <p>"Loading..."</p>;
|
|
||||||
}
|
|
||||||
if (response.isError) {
|
|
||||||
return <p>"Error loading!"</p>;
|
|
||||||
}
|
|
||||||
const costmapStyle = {
|
|
||||||
minHeight: "65svb",
|
|
||||||
};
|
|
||||||
return <Image src={response.data} fluid style={costmapStyle} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
const statusStringQuery = async () => {
|
|
||||||
const resp = await fetch("api/status");
|
|
||||||
if (!resp.ok) {
|
|
||||||
throw new Error("Network response was not ok");
|
|
||||||
}
|
|
||||||
return resp.json();
|
|
||||||
};
|
|
||||||
const statusStringQueryAtom = atomWithQuery(() => ({
|
|
||||||
queryKey: ["status_string"],
|
|
||||||
queryFn: statusStringQuery,
|
|
||||||
refetchInterval: 500, // 0.5s
|
|
||||||
}));
|
|
||||||
const statusStringAtom = atom((get) => {
|
|
||||||
const response = get(statusStringQueryAtom);
|
|
||||||
if (response.isPending || response.isError || !response.data.status) {
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
return response.data.message;
|
|
||||||
});
|
|
||||||
|
|
||||||
const latLongQuery = async () => {
|
|
||||||
const resp = await fetch("api/position");
|
|
||||||
if (!resp.ok) {
|
|
||||||
throw new Error("Network response was not ok");
|
|
||||||
}
|
|
||||||
return resp.json();
|
|
||||||
};
|
|
||||||
const latLongQueryAtom = atomWithQuery(() => ({
|
|
||||||
queryKey: ["latlong"],
|
|
||||||
queryFn: latLongQuery,
|
|
||||||
refetchInterval: 500, // 0.5s
|
|
||||||
}));
|
|
||||||
const latLongAtom = atom((get) => {
|
|
||||||
const response = get(latLongQueryAtom);
|
|
||||||
if (response.isPending || response.isError || !response.data.status) {
|
|
||||||
return "N/A";
|
|
||||||
}
|
|
||||||
return `(${response.data.latitude}, ${response.data.longitude})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
export function Autonomy() {
|
|
||||||
const costmapImage = useAtomValue(costmapImageAtom);
|
|
||||||
const statusString = useAtomValue(statusStringAtom);
|
|
||||||
const latLong = useAtomValue(latLongAtom);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<AppNav />
|
|
||||||
<Container className="vert-padded">
|
|
||||||
<Card className="padded">
|
|
||||||
<Row>
|
|
||||||
<Col lg={8}>{costmapImage}</Col>
|
|
||||||
<Col lg={4}>
|
|
||||||
<p>Status:</p>
|
|
||||||
<pre>{statusString}</pre>
|
|
||||||
<p>Latitude, Longitude:</p>
|
|
||||||
<pre>{latLong}</pre>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
</Container>
|
|
||||||
<Footer />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
38
src/Home.tsx
38
src/Home.tsx
|
|
@ -1,18 +1,40 @@
|
||||||
import { AppNav, Footer } from "./AppNav.tsx";
|
import { AppNav, Footer } from "./AppNav.tsx";
|
||||||
import { Container, Row, Col, Image, Card } from "react-bootstrap";
|
import { Container, Row, Col, Image } from "react-bootstrap";
|
||||||
import { atom, useAtomValue } from "jotai";
|
import { atom, useAtom } from "jotai";
|
||||||
import { atomWithQuery } from "jotai-tanstack-query";
|
import { atomWithQuery } from "jotai-tanstack-query";
|
||||||
|
|
||||||
|
const costmapImageQuery = async () => {
|
||||||
|
const resp = await fetch("api/costmap_image");
|
||||||
|
if (!resp.ok) {
|
||||||
|
throw new Error("Network response was not ok");
|
||||||
|
}
|
||||||
|
const blob = await resp.blob();
|
||||||
|
return URL.createObjectURL(blob);
|
||||||
|
};
|
||||||
|
|
||||||
|
const costmapImageAtom = atomWithQuery(() => ({
|
||||||
|
queryKey: ["costmap_image"],
|
||||||
|
queryFn: costmapImageQuery,
|
||||||
|
refetchInterval: 1000 // 1s
|
||||||
|
}));
|
||||||
|
|
||||||
export function Home() {
|
export function Home() {
|
||||||
|
const [{ data, isPending, isError }] = useAtom(costmapImageAtom);
|
||||||
|
|
||||||
|
let costmapImage = () => {
|
||||||
|
if (isPending) {
|
||||||
|
return (<p>"Loading..."</p>);
|
||||||
|
}
|
||||||
|
if (isError) {
|
||||||
|
return(<p>"Error!"</p>);
|
||||||
|
}
|
||||||
|
return (<Image src={data} />);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AppNav />
|
<AppNav />
|
||||||
<Container className="vert-padded">
|
<Container>
|
||||||
<Card className="padded">
|
{ costmapImage() }
|
||||||
<Row>
|
|
||||||
<p>Hello World!</p>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
</Container>
|
</Container>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { AppNav, Footer } from "./AppNav.tsx";
|
import { AppNav, Footer } from "./AppNav.tsx";
|
||||||
import { Container, Row, Col, Image } from "react-bootstrap";
|
import { Container, Row, Col, Image } from "react-bootstrap";
|
||||||
|
|
||||||
export function WhoAmI() {
|
export function Network() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AppNav />
|
<AppNav />
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { AppNav, Footer } from "./AppNav.tsx";
|
import { AppNav, Footer } from "./AppNav.tsx";
|
||||||
import { Container, Row, Col, Card } from "react-bootstrap";
|
import { Container, Row, Col, Card } from "react-bootstrap";
|
||||||
import { atom, useAtomValue } from "jotai";
|
import { atom, useAtom } from "jotai";
|
||||||
import { atomWithQuery } from "jotai-tanstack-query";
|
import { atomWithQuery } from "jotai-tanstack-query";
|
||||||
import YAML from "yaml";
|
import YAML from "yaml";
|
||||||
|
|
||||||
|
|
@ -12,27 +12,26 @@ const versionQueryFn = async () => {
|
||||||
return resp.json();
|
return resp.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
const versionQueryAtom = atomWithQuery(() => ({
|
const versionAtom = atomWithQuery(() => ({
|
||||||
queryKey: ["version"],
|
queryKey: ["version"],
|
||||||
queryFn: versionQueryFn,
|
queryFn: versionQueryFn,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const versionAtom = atom((get) => {
|
|
||||||
const version = get(versionQueryAtom);
|
|
||||||
if (version.isPending) {
|
|
||||||
return "Loading...";
|
|
||||||
}
|
|
||||||
if (version.isError) {
|
|
||||||
return "Error loading!";
|
|
||||||
}
|
|
||||||
if (!version.data.status) {
|
|
||||||
return "Can not find version";
|
|
||||||
}
|
|
||||||
return YAML.stringify(version.data.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
export function Version() {
|
export function Version() {
|
||||||
let versionText = useAtomValue(versionAtom);
|
const [{ data, isPending, isError }] = useAtom(versionAtom);
|
||||||
|
|
||||||
|
let versionText = () => {
|
||||||
|
if (isPending) {
|
||||||
|
return "Loading...";
|
||||||
|
}
|
||||||
|
if (isError) {
|
||||||
|
return "Error loading!";
|
||||||
|
}
|
||||||
|
if (!data.status) {
|
||||||
|
return "Can not find version";
|
||||||
|
}
|
||||||
|
return YAML.stringify(data.message);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -41,7 +40,7 @@ export function Version() {
|
||||||
<Card className="padded">
|
<Card className="padded">
|
||||||
<Card.Title>project.yaml</Card.Title>
|
<Card.Title>project.yaml</Card.Title>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<pre>{versionText}</pre>
|
<pre>{versionText()}</pre>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card>
|
</Card>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue