mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-26 19:06:11 +01:00
feat(web): layout & auto-update debug page
This commit is contained in:
parent
16121ffd00
commit
a3d6bf214c
@ -21,6 +21,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
routes: [{ match: 'routes', src: '.*', dest: '/index.html' }],
|
||||||
packageOptions: {
|
packageOptions: {
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
},
|
},
|
||||||
|
@ -24,9 +24,9 @@ export default function App() {
|
|||||||
<div />
|
<div />
|
||||||
) : (
|
) : (
|
||||||
<Config.Provider value={config}>
|
<Config.Provider value={config}>
|
||||||
<div className="md:flex flex-col md:flex-row md:min-h-screen w-full bg-gray-100 dark:bg-gray-800 ">
|
<div className="flex md:min-h-screen w-full bg-gray-100 dark:bg-gray-800">
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<div className="p-4">
|
<div className="p-4 min-w-0">
|
||||||
<Router>
|
<Router>
|
||||||
<CameraMap path="/cameras/:camera/editor" />
|
<CameraMap path="/cameras/:camera/editor" />
|
||||||
<Camera path="/cameras/:camera" />
|
<Camera path="/cameras/:camera" />
|
||||||
|
@ -1,16 +1,97 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import { ApiHost } from './context';
|
import Heading from './components/Heading';
|
||||||
import { useContext, useEffect, useState } from 'preact/hooks';
|
import Link from './components/Link';
|
||||||
|
import { ApiHost, Config } from './context';
|
||||||
|
import { Table, Tbody, Thead, Tr, Th, Td } from './components/Table';
|
||||||
|
import { useCallback, useContext, useEffect, useState } from 'preact/hooks';
|
||||||
|
|
||||||
export default function Debug() {
|
export default function Debug() {
|
||||||
const apiHost = useContext(ApiHost);
|
const apiHost = useContext(ApiHost);
|
||||||
const [config, setConfig] = useState({});
|
const config = useContext(Config);
|
||||||
|
const [stats, setStats] = useState({});
|
||||||
|
const [timeoutId, setTimeoutId] = useState(null);
|
||||||
|
|
||||||
useEffect(async () => {
|
const fetchStats = useCallback(async () => {
|
||||||
const response = await fetch(`${apiHost}/api/stats`);
|
const statsResponse = await fetch(`${apiHost}/api/stats`);
|
||||||
const data = response.ok ? await response.json() : {};
|
const stats = statsResponse.ok ? await statsResponse.json() : {};
|
||||||
setConfig(data);
|
setStats(stats);
|
||||||
|
setTimeoutId(setTimeout(fetchStats, 1000));
|
||||||
|
}, [setStats]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchStats();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <pre>{JSON.stringify(config, null, 2)}</pre>;
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
};
|
||||||
|
}, [timeoutId]);
|
||||||
|
|
||||||
|
const { detectors, detection_fps, service, ...cameras } = stats;
|
||||||
|
if (!service) {
|
||||||
|
return 'loading…';
|
||||||
|
}
|
||||||
|
|
||||||
|
const detectorNames = Object.keys(detectors);
|
||||||
|
const detectorDataKeys = Object.keys(detectors[detectorNames[0]]);
|
||||||
|
|
||||||
|
const cameraNames = Object.keys(cameras);
|
||||||
|
const cameraDataKeys = Object.keys(cameras[cameraNames[0]]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Heading>
|
||||||
|
Debug <span className="text-sm">{service.version}</span>
|
||||||
|
</Heading>
|
||||||
|
<Table className="w-full">
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>detector</Th>
|
||||||
|
{detectorDataKeys.map((name) => (
|
||||||
|
<Th>{name.replace('_', ' ')}</Th>
|
||||||
|
))}
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{detectorNames.map((detector, i) => (
|
||||||
|
<Tr index={i}>
|
||||||
|
<Td>{detector}</Td>
|
||||||
|
{detectorDataKeys.map((name) => (
|
||||||
|
<Td key={`${name}-${detector}`}>{detectors[detector][name]}</Td>
|
||||||
|
))}
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<Table className="w-full">
|
||||||
|
<Thead>
|
||||||
|
<Tr>
|
||||||
|
<Th>camera</Th>
|
||||||
|
{cameraDataKeys.map((name) => (
|
||||||
|
<Th>{name.replace('_', ' ')}</Th>
|
||||||
|
))}
|
||||||
|
</Tr>
|
||||||
|
</Thead>
|
||||||
|
<Tbody>
|
||||||
|
{cameraNames.map((camera, i) => (
|
||||||
|
<Tr index={i}>
|
||||||
|
<Td>
|
||||||
|
<Link href={`/cameras/${camera}`}>{camera}</Link>
|
||||||
|
</Td>
|
||||||
|
{cameraDataKeys.map((name) => (
|
||||||
|
<Td key={`${name}-${camera}`}>{cameras[camera][name]}</Td>
|
||||||
|
))}
|
||||||
|
</Tr>
|
||||||
|
))}
|
||||||
|
</Tbody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
<Heading size="sm">Config</Heading>
|
||||||
|
<pre className="font-mono overflow-y-scroll overflow-x-scroll max-h-96 rounded bg-white dark:bg-gray-900">
|
||||||
|
{JSON.stringify(config, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
|
|
||||||
export function Table({ children }) {
|
export function Table({ children, className }) {
|
||||||
return <table className="table-auto border-collapse text-gray-900 dark:text-gray-200">{children}</table>;
|
return (
|
||||||
|
<table className={`table-auto border-collapse text-gray-900 dark:text-gray-200 ${className}`}>{children}</table>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Thead({ children }) {
|
export function Thead({ children, className }) {
|
||||||
return <thead className="">{children}</thead>;
|
return <thead className={`${className}`}>{children}</thead>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tbody({ children }) {
|
export function Tbody({ children, className }) {
|
||||||
return <tbody className="">{children}</tbody>;
|
return <tbody className={`${className}`}>{children}</tbody>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tfoot({ children }) {
|
export function Tfoot({ children, className }) {
|
||||||
return <tfoot className="">{children}</tfoot>;
|
return <tfoot className={`${className}`}>{children}</tfoot>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Tr({ children, index }) {
|
export function Tr({ children, className, index }) {
|
||||||
return <tr className={`${index % 2 ? 'bg-gray-200 ' : ''}`}>{children}</tr>;
|
return <tr className={`${index % 2 ? 'bg-gray-200 ' : ''} ${className}`}>{children}</tr>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Th({ children }) {
|
export function Th({ children, className }) {
|
||||||
return <th className="border-b-2 border-gray-400 p-4 text-left">{children}</th>;
|
return <th className={`border-b-2 border-gray-400 p-4 text-left ${className}`}>{children}</th>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Td({ children }) {
|
export function Td({ children, className }) {
|
||||||
return <td className="p-4">{children}</td>;
|
return <td className={`p-4 ${className}`}>{children}</td>;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user