Compare commits

..

No commits in common. "ea7eb4566519b0af6e568fa7b76b659fe8779dec" and "24281cd4911ee5e40097d247baedcf0be78c3cd9" have entirely different histories.

5 changed files with 50 additions and 125 deletions

View File

@ -14,12 +14,12 @@ import { atom, useAtomValue } from "jotai";
import { createQueryAtom } from "./utils/query.ts"; import { createQueryAtom } from "./utils/query.ts";
import { DiagnosticsCard } from "./components/DiagnosticsCard.tsx"; import { DiagnosticsCard } from "./components/DiagnosticsCard.tsx";
const identityStringQueryAtom = createQueryAtom("api/identity", { const statusStringQueryAtom = createQueryAtom("status_string", "api/status", {
refetchInterval: 500, refetchInterval: 500,
}); });
const identityStringAtom = atom((get) => { const statusStringAtom = atom((get) => {
const response = get(identityStringQueryAtom); const response = get(statusStringQueryAtom);
if (response.isPending || response.isError) { if (response.isPending || response.isError || !response.data.status) {
return "N/A"; return "N/A";
} }
return response.data.message; return response.data.message;
@ -36,14 +36,16 @@ const uptimeAtom = atom((get) => {
return response.data.uptime.toFixed(1); return response.data.uptime.toFixed(1);
}); });
function IdentityCard() { function StatusCard() {
const identityString = useAtomValue(identityStringAtom); const statusString = useAtomValue(statusStringAtom);
return ( return (
<Card className="padded h-100"> <Card className="padded">
<Card.Title>Identity</Card.Title> <Row>
<Card.Body> <p>Status:</p>
<div style={{ whiteSpace: "pre-line" }}>{identityString}</div> </Row>
</Card.Body> <Row>
<p>{statusString}</p>
</Row>
</Card> </Card>
); );
} }
@ -51,11 +53,13 @@ function IdentityCard() {
function UptimeCard() { function UptimeCard() {
const uptime = useAtomValue(uptimeAtom); const uptime = useAtomValue(uptimeAtom);
return ( return (
<Card className="padded h-100"> <Card className="padded">
<Card.Title>Uptime</Card.Title> <Row>
<Card.Body> <p>Uptime:</p>
</Row>
<Row>
<p>{uptime}s</p> <p>{uptime}s</p>
</Card.Body> </Row>
</Card> </Card>
); );
} }
@ -70,7 +74,7 @@ export function Home() {
<UptimeCard /> <UptimeCard />
</Col> </Col>
<Col> <Col>
<IdentityCard /> <StatusCard />
</Col> </Col>
</Row> </Row>
<Row className="vert-padded"> <Row className="vert-padded">

View File

@ -14,59 +14,35 @@ import { atom, useAtomValue } from "jotai";
import { createQueryAtom } from "./utils/query.ts"; import { createQueryAtom } from "./utils/query.ts";
import YAML from "yaml"; import YAML from "yaml";
const buildInfoQueryAtom = createQueryAtom("api/build_info"); const versionQueryAtom = createQueryAtom("api/build_info");
const buildInfoAtom = atom((get) => {
const buildInfo = get(buildInfoQueryAtom); const versionAtom = atom((get) => {
if (buildInfo.isPending) { const version = get(versionQueryAtom);
if (version.isPending) {
return "Loading..."; return "Loading...";
} }
if (buildInfo.isError) { if (version.isError) {
return "Error loading!"; return "Error loading!";
} }
if (!buildInfo.data.status) { if (!version.data.status) {
return "Can not find buildInfo"; return "Can not find version";
} }
return YAML.stringify(buildInfo.data.message); return YAML.stringify(version.data.message);
});
const versionNumberQueryAtom = createQueryAtom("api/version_number");
const versionNumberAtom = atom((get) => {
const versionNumber = get(versionNumberQueryAtom);
if (versionNumber.isPending || versionNumber.isError) {
return "...";
}
if (!versionNumber.data.status) {
return "Can not find version number.";
}
return versionNumber.data.version;
}); });
export function Version() { export function Version() {
let buildInfoText = useAtomValue(buildInfoAtom); let versionText = useAtomValue(versionAtom);
let versionText = useAtomValue(versionNumberAtom);
return ( return (
<div> <div>
<AppNav /> <AppNav />
<Container className="vert-padded"> <Container className="vert-padded">
<Row> <Card className="padded">
<Col> <Card.Title>project.yaml</Card.Title>
<Card className="padded"> <Card.Body>
<Card.Title>Version Number</Card.Title> <pre>{versionText}</pre>
<Card.Body>{versionText}</Card.Body> </Card.Body>
</Card> </Card>
</Col>
</Row>
<Row className="vert-padded">
<Col>
<Card className="padded">
<Card.Title>project.yaml</Card.Title>
<Card.Body>
<pre>{buildInfoText}</pre>
</Card.Body>
</Card>
</Col>
</Row>
</Container> </Container>
<Footer /> <Footer />
</div> </div>

View File

@ -11,67 +11,26 @@
import { AppNav, Footer } from "./components/AppNav.tsx"; import { AppNav, Footer } from "./components/AppNav.tsx";
import { Container, Row, Col, Card } from "react-bootstrap"; import { Container, Row, Col, Card } from "react-bootstrap";
import { MediaMtxPlayer } from "./external/MediaMtxPlayer.tsx"; import { MediaMtxPlayer } from "./external/MediaMtxPlayer.tsx";
import { atom, useAtomValue, useAtom } from "jotai"; import { atom, useAtomValue } from "jotai";
import { createQueryAtom } from "./utils/query.ts"; import { createQueryAtom } from "./utils/query.ts";
const tokenQueryAtom = createQueryAtom("api/mediamtx/login", { retry: true }); const tokenQueryAtom = createQueryAtom("api/mediamtx/login", { retry: true });
const tokenAtom = atom((get) => { const tokenAtom = atom((get) => {
const response = get(tokenQueryAtom); const response = get(tokenQueryAtom);
if (response.isPending || response.isError) { if (response.isPending || response.isError) {
console.log(response);
return null; return null;
} }
return response.data.token; return response.data.token;
}); });
const streamsQueryAtom = createQueryAtom("api/available_streams");
const streamsAtom = atom((get) => {
const response = get(streamsQueryAtom);
if (response.isPending || response.isError) {
return [];
}
return response.data.streams;
});
const videoDisplayPortAtom = atom((get) => {
const response = get(streamsQueryAtom);
if (response.isPending || response.isError) {
return null;
}
return response.data.port;
});
const selectedStreamAtom = atom("image");
const imageStreamURIAtom = atom((get) => {
const port = get(videoDisplayPortAtom);
const selectedStream = get(selectedStreamAtom);
if (port === null || selectedStream === null) {
return null;
}
const imageStreamURI =
"http://" +
window.location.hostname +
":" +
port +
"/" +
selectedStream +
"/whep";
return imageStreamURI;
});
export function Video() { export function Video() {
const streamName = "image"; const streamName = "image";
const imageStreamURI =
const imageStreamURI = useAtomValue(imageStreamURIAtom); "http://" + window.location.hostname + ":8889/" + streamName + "/whep";
const token = useAtomValue(tokenAtom); const token = useAtomValue(tokenAtom);
const availableStreams = useAtomValue(streamsAtom);
const [selectedStream, setSelectedStream] = useAtom(selectedStreamAtom);
const handleSelect = (event) => {
setSelectedStream(event.target.value);
};
return ( return (
<div> <div>
<AppNav /> <AppNav />
@ -81,21 +40,7 @@ export function Video() {
<Col lg={8}> <Col lg={8}>
<MediaMtxPlayer url={imageStreamURI} token={token} /> <MediaMtxPlayer url={imageStreamURI} token={token} />
</Col> </Col>
<Col lg={4}> <Col lg={4}>Showing stream: "{streamName}".</Col>
<p>Available Streams: </p>
{availableStreams.map((stream, index) => (
<div style={{ display: "flex", gap: "8px" }}>
<input
type="radio"
name="selected_stream"
value={stream}
checked={selectedStream === stream}
onChange={handleSelect}
/>
{stream}
</div>
))}
</Col>
</Row> </Row>
</Card> </Card>
</Container> </Container>

View File

@ -16,7 +16,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="/">
am_i_up J7s-Bridge
</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">

View File

@ -71,15 +71,11 @@ function LevelIndicator(props: Any) {
return <CircleFill color="grey" />; return <CircleFill color="grey" />;
} }
function TitleText(props: Any) { function MessageText(props: Any) {
if (props.message === "") { if (props.message === "") {
return <p>{props.name}</p>; return <div></div>;
} }
return ( return <div>Message: {props.message}</div>;
<p>
{props.name}: {props.message}
</p>
);
} }
function ValuesTable(props: Any) { function ValuesTable(props: Any) {
@ -107,9 +103,13 @@ function ValuesTable(props: Any) {
function StatusContent(props: Any) { function StatusContent(props: Any) {
const status = props.status; const status = props.status;
console.log(status);
return ( return (
<div> <div>
<TitleText name={status.name} message={status.message} /> <p>{status.name}</p>
<p>
<MessageText message={status.message} />
</p>
<p> <p>
<ValuesTable values={status.values} /> <ValuesTable values={status.values} />
</p> </p>