refactor(web): async routing

This commit is contained in:
Paul Armstrong 2021-02-07 13:46:05 -08:00 committed by Blake Blackshear
parent 24ec13e36d
commit 7aee28d080
14 changed files with 95 additions and 93 deletions

5
web/package-lock.json generated
View File

@ -1721,6 +1721,11 @@
"resolved": "https://registry.npmjs.org/preact/-/preact-10.5.9.tgz", "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.9.tgz",
"integrity": "sha512-X4m+4VMVINl/JFQKALOCwa3p8vhMAhBvle0hJ/W44w/WWfNb2TA7RNicDV3K2dNVs57f61GviEnVLiwN+fxiIg==" "integrity": "sha512-X4m+4VMVINl/JFQKALOCwa3p8vhMAhBvle0hJ/W44w/WWfNb2TA7RNicDV3K2dNVs57f61GviEnVLiwN+fxiIg=="
}, },
"preact-async-route": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/preact-async-route/-/preact-async-route-2.2.1.tgz",
"integrity": "sha512-8bg1007akXs3YDmzYT4McaTe6ji2FIzcc0/NTlu+vjJaKPNQ8lNG/HQ6LP+FoIxQ4m/KH5vvJCHJN5ADp2iNGA=="
},
"preact-router": { "preact-router": {
"version": "3.2.1", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/preact-router/-/preact-router-3.2.1.tgz", "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-3.2.1.tgz",

View File

@ -16,6 +16,7 @@
"postcss": "^8.2.2", "postcss": "^8.2.2",
"postcss-cli": "^8.3.1", "postcss-cli": "^8.3.1",
"preact": "^10.5.9", "preact": "^10.5.9",
"preact-async-route": "^2.2.1",
"preact-router": "^3.2.1", "preact-router": "^3.2.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"snowpack": "^3.0.11", "snowpack": "^3.0.11",

View File

@ -1,15 +1,11 @@
import * as Routes from './routes';
import { h } from 'preact'; import { h } from 'preact';
import ActivityIndicator from './components/ActivityIndicator'; import ActivityIndicator from './components/ActivityIndicator';
import AsyncRoute from 'preact-async-route';
import AppBar from './components/AppBar'; import AppBar from './components/AppBar';
import Camera from './Camera'; import Cameras from './routes/Cameras';
import CameraMap from './CameraMap';
import Cameras from './Cameras';
import Debug from './Debug';
import Event from './Event';
import Events from './Events';
import { Router } from 'preact-router'; import { Router } from 'preact-router';
import Sidebar from './Sidebar'; import Sidebar from './Sidebar';
import StyleGuide from './StyleGuide';
import Api, { FetchStatus, useConfig } from './api'; import Api, { FetchStatus, useConfig } from './api';
import { DarkModeProvider, DrawerProvider } from './context'; import { DarkModeProvider, DrawerProvider } from './context';
@ -29,12 +25,12 @@ export default function App() {
<Sidebar /> <Sidebar />
<div className="w-full flex-auto p-2 mt-24 px-4 min-w-0"> <div className="w-full flex-auto p-2 mt-24 px-4 min-w-0">
<Router> <Router>
<CameraMap path="/cameras/:camera/editor" /> <AsyncRoute path="/cameras/:camera/editor" getComponent={Routes.getCameraMap} />
<Camera path="/cameras/:camera" /> <AsyncRoute path="/cameras/:camera" getComponent={Routes.getCamera} />
<Event path="/events/:eventId" /> <AsyncRoute path="/events/:eventId" getComponent={Routes.getEvent} />
<Events path="/events" /> <AsyncRoute path="/events" getComponent={Routes.getEvents} />
<Debug path="/debug" /> <AsyncRoute path="/debug" getComponent={Routes.getDebug} />
{import.meta.env.NODE_ENV !== 'development' ? <StyleGuide path="/styleguide" /> : null} <AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
<Cameras default path="/" /> <Cameras default path="/" />
</Router> </Router>
</div> </div>

View File

@ -1,34 +0,0 @@
import { h } from 'preact';
import { useDarkMode } from './context';
import { useCallback } from 'preact/hooks';
export default function Settings() {
const { currentMode, persistedMode, setDarkMode } = useDarkMode();
const handleSelect = useCallback(
(event) => {
const mode = event.target.value;
setDarkMode(mode);
},
[setDarkMode]
);
return (
<div>
<label>
<span className="block uppercase text-sm">Dark mode</span>
<select className="border-solid border border-gray-500 rounded dark:text-gray-900" onChange={handleSelect}>
<option selected={persistedMode === 'media'} value="media">
Auto
</option>
<option selected={persistedMode === 'light'} value="light">
Light
</option>
<option selected={persistedMode === 'dark'} value="dark">
Dark
</option>
</select>
</label>
</div>
);
}

View File

@ -30,6 +30,12 @@ export default function Sidebar() {
<Destination href="/debug" text="Debug" /> <Destination href="/debug" text="Debug" />
<Separator /> <Separator />
<div className="flex flex-grow" /> <div className="flex flex-grow" />
{import.meta.env.MODE !== 'production' ? (
<Fragment>
<Destination href="/styleguide" text="Style Guide" />
<Separator />
</Fragment>
) : null}
<Destination className="self-end" href="https://blakeblackshear.github.io/frigate" text="Documentation" /> <Destination className="self-end" href="https://blakeblackshear.github.io/frigate" text="Documentation" />
<Destination className="self-end" href="https://github.com/blakeblackshear/frigate" text="GitHub" /> <Destination className="self-end" href="https://github.com/blakeblackshear/frigate" text="GitHub" />
</NavigationDrawer> </NavigationDrawer>

View File

@ -50,7 +50,7 @@ export default function CameraImage({ camera, onload, searchParams = '' }) {
); );
useEffect(() => { useEffect(() => {
if (!scaledHeight) { if (!scaledHeight || !canvasRef.current) {
return; return;
} }
img.src = `${apiHost}/api/${name}/latest.jpg?h=${scaledHeight}${searchParams ? `&${searchParams}` : ''}`; img.src = `${apiHost}/api/${name}/latest.jpg?h=${scaledHeight}${searchParams ? `&${searchParams}` : ''}`;

View File

@ -1,15 +1,15 @@
import { h } from 'preact'; import { h } from 'preact';
import AutoUpdatingCameraImage from './components/AutoUpdatingCameraImage'; import AutoUpdatingCameraImage from '../components/AutoUpdatingCameraImage';
import Button from './components/Button'; import Button from '../components/Button';
import Card from './components/Card'; import Card from '../components/Card';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Link from './components/Link'; import Link from '../components/Link';
import SettingsIcon from './icons/Settings'; import SettingsIcon from '../icons/Settings';
import Switch from './components/Switch'; import Switch from '../components/Switch';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { usePersistence } from './context'; import { usePersistence } from '../context';
import { useCallback, useContext, useMemo, useState } from 'preact/hooks'; import { useCallback, useContext, useMemo, useState } from 'preact/hooks';
import { useApiHost, useConfig } from './api'; import { useApiHost, useConfig } from '../api';
export default function Camera({ camera }) { export default function Camera({ camera }) {
const { data: config } = useConfig(); const { data: config } = useConfig();

View File

@ -1,8 +1,8 @@
import { h } from 'preact'; import { h } from 'preact';
import Card from './components/Card'; import Card from '../components/Card';
import Button from './components/Button'; import Button from '../components/Button';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Switch from './components/Switch'; import Switch from '../components/Switch';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'preact/hooks'; import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'preact/hooks';
import { useApiHost, useConfig } from './api'; import { useApiHost, useConfig } from './api';

View File

@ -1,11 +1,10 @@
import { h } from 'preact'; import { h } from 'preact';
import ActivityIndicator from './components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Card from './components/Card'; import Card from '../components/Card';
import CameraImage from './components/CameraImage'; import CameraImage from '../components/CameraImage';
import Events from './Events'; import Heading from '../components/Heading';
import Heading from './components/Heading';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { useConfig } from './api'; import { useConfig } from '../api';
import { useMemo } from 'preact/hooks'; import { useMemo } from 'preact/hooks';
export default function Cameras() { export default function Cameras() {

View File

@ -1,10 +1,10 @@
import { h } from 'preact'; import { h } from 'preact';
import ActivityIndicator from './components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Button from './components/Button'; import Button from '../components/Button';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Link from './components/Link'; import Link from '../components/Link';
import { FetchStatus, useConfig, useStats } from './api'; import { FetchStatus, useConfig, useStats } from '../api';
import { Table, Tbody, Thead, Tr, Th, Td } from './components/Table'; import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table';
import { useCallback, useEffect, useState } from 'preact/hooks'; import { useCallback, useEffect, useState } from 'preact/hooks';
export default function Debug() { export default function Debug() {

View File

@ -1,9 +1,9 @@
import { h, Fragment } from 'preact'; import { h, Fragment } from 'preact';
import ActivityIndicator from './components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Link from './components/Link'; import Link from '../components/Link';
import { FetchStatus, useApiHost, useEvent } from './api'; import { FetchStatus, useApiHost, useEvent } from '../api';
import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from './components/Table'; import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table';
export default function Event({ eventId }) { export default function Event({ eventId }) {
const apiHost = useApiHost(); const apiHost = useApiHost();

View File

@ -1,13 +1,13 @@
import { h } from 'preact'; import { h } from 'preact';
import ActivityIndicator from './components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Card from './components/Card'; import Card from '../components/Card';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Link from './components/Link'; import Link from '../components/Link';
import Select from './components/Select'; import Select from '../components/Select';
import produce from 'immer'; import produce from 'immer';
import { route } from 'preact-router'; import { route } from 'preact-router';
import { FetchStatus, useApiHost, useConfig, useEvents } from './api'; import { FetchStatus, useApiHost, useConfig, useEvents } from '../api';
import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from './components/Table'; import { Table, Thead, Tbody, Tfoot, Th, Tr, Td } from '../components/Table';
import { useCallback, useContext, useEffect, useMemo, useRef, useReducer, useState } from 'preact/hooks'; import { useCallback, useContext, useEffect, useMemo, useRef, useReducer, useState } from 'preact/hooks';
const API_LIMIT = 25; const API_LIMIT = 25;

View File

@ -1,12 +1,12 @@
import { h } from 'preact'; import { h } from 'preact';
import ArrowDropdown from './icons/ArrowDropdown'; import ArrowDropdown from '../icons/ArrowDropdown';
import ArrowDropup from './icons/ArrowDropup'; import ArrowDropup from '../icons/ArrowDropup';
import Card from './components/Card'; import Card from '../components/Card';
import Button from './components/Button'; import Button from '../components/Button';
import Heading from './components/Heading'; import Heading from '../components/Heading';
import Select from './components/Select'; import Select from '../components/Select';
import Switch from './components/Switch'; import Switch from '../components/Switch';
import TextField from './components/TextField'; import TextField from '../components/TextField';
import { useCallback, useState } from 'preact/hooks'; import { useCallback, useState } from 'preact/hooks';
export default function StyleGuide() { export default function StyleGuide() {

29
web/src/routes/index.js Normal file
View File

@ -0,0 +1,29 @@
export async function getCameraMap(url, cb, props) {
const module = await import('./CameraMap.jsx');
return module.default;
}
export async function getCamera(url, cb, props) {
const module = await import('./Camera.jsx');
return module.default;
}
export async function getEvent(url, cb, props) {
const module = await import('./Event.jsx');
return module.default;
}
export async function getEvents(url, cb, props) {
const module = await import('./Events.jsx');
return module.default;
}
export async function getDebug(url, cb, props) {
const module = await import('./Debug.jsx');
return module.default;
}
export async function getStyleGuide(url, cb, props) {
const module = await import('./StyleGuide.jsx');
return module.default;
}