ADD react router and reading from query params

Signed-off-by: Damian Krysta <damian@krysta.dev>
This commit is contained in:
Damian Krysta 2022-01-29 19:03:58 +01:00 committed by Scott Lamb
parent c9b1e49f3d
commit 2d517c28dc
6 changed files with 59 additions and 19 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.DS_Store .DS_Store
*.swp *.swp
/server/target /server/target
.idea

1
ui/.gitignore vendored
View File

@ -4,6 +4,7 @@
/node_modules /node_modules
/.pnp /.pnp
.pnp.js .pnp.js
/.idea
# testing # testing
/coverage /coverage

25
ui/package-lock.json generated
View File

@ -8518,6 +8518,14 @@
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ=="
}, },
"history": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz",
"integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==",
"requires": {
"@babel/runtime": "^7.7.6"
}
},
"hmac-drbg": { "hmac-drbg": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@ -14857,6 +14865,23 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
}, },
"react-router": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz",
"integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==",
"requires": {
"history": "^5.2.0"
}
},
"react-router-dom": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz",
"integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==",
"requires": {
"history": "^5.2.0",
"react-router": "6.2.1"
}
},
"react-scripts": { "react-scripts": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.3.tgz",

View File

@ -6,9 +6,9 @@
"@emotion/react": "^11.1.5", "@emotion/react": "^11.1.5",
"@emotion/styled": "^11.1.5", "@emotion/styled": "^11.1.5",
"@fontsource/roboto": "^4.2.1", "@fontsource/roboto": "^4.2.1",
"@mui/material": "^5.0.1",
"@mui/icons-material": "^5.0.1", "@mui/icons-material": "^5.0.1",
"@mui/lab": "^5.0.0-alpha.48", "@mui/lab": "^5.0.0-alpha.48",
"@mui/material": "^5.0.1",
"@mui/styles": "^5.0.1", "@mui/styles": "^5.0.1",
"@react-hook/resize-observer": "^1.2.0", "@react-hook/resize-observer": "^1.2.0",
"@types/jest": "^26.0.20", "@types/jest": "^26.0.20",
@ -20,6 +20,7 @@
"gzipper": "^5.0.0", "gzipper": "^5.0.0",
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-router-dom": "^6.2.1",
"react-scripts": "^4.0.3", "react-scripts": "^4.0.3",
"typescript": "^4.3.5" "typescript": "^4.3.5"
}, },

View File

@ -11,6 +11,7 @@ import { useSnackbars } from "./snackbars";
import { Camera, Session } from "./types"; import { Camera, Session } from "./types";
import ListActivity from "./List"; import ListActivity from "./List";
import AppBar from "@mui/material/AppBar"; import AppBar from "@mui/material/AppBar";
import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
import LiveActivity, { MultiviewChooser } from "./Live"; import LiveActivity, { MultiviewChooser } from "./Live";
import Drawer from "@mui/material/Drawer"; import Drawer from "@mui/material/Drawer";
import List from "@mui/material/List"; import List from "@mui/material/List";
@ -80,6 +81,20 @@ function App() {
} }
}; };
function fetchedCameras(cameras: Camera[] | null) {
if (cameras !== null && cameras.length >0) {
return (
<>
<Route path="" element={ <ListActivity cameras={cameras}
showSelectors={showListSelectors}
timeZoneName={timeZoneName!}
/>} />
<Route path="live" element={<LiveActivity cameras={cameras} layoutIndex={multiviewLayoutIndex} />} />
</>
);
}
}
useEffect(() => { useEffect(() => {
const abort = new AbortController(); const abort = new AbortController();
const doFetch = async (signal: AbortSignal) => { const doFetch = async (signal: AbortSignal) => {
@ -112,7 +127,6 @@ function App() {
}; };
}, [fetchSeq]); }, [fetchSeq]);
let activityMenu = null; let activityMenu = null;
let activityMain = null;
if (error === null && cameras !== null && cameras.length > 0) { if (error === null && cameras !== null && cameras.length > 0) {
switch (activity) { switch (activity) {
case "list": case "list":
@ -126,13 +140,6 @@ function App() {
<FilterList /> <FilterList />
</IconButton> </IconButton>
); );
activityMain = (
<ListActivity
cameras={cameras}
showSelectors={showListSelectors}
timeZoneName={timeZoneName!}
/>
);
break; break;
case "live": case "live":
activityMenu = ( activityMenu = (
@ -141,14 +148,11 @@ function App() {
onChoice={setMultiviewLayoutIndex} onChoice={setMultiviewLayoutIndex}
/> />
); );
activityMain = (
<LiveActivity cameras={cameras} layoutIndex={multiviewLayoutIndex} />
);
break; break;
} }
} }
return ( return (
<> <BrowserRouter>
<AppBar position="static"> <AppBar position="static">
<MoonfireMenu <MoonfireMenu
loginState={loginState} loginState={loginState}
@ -174,13 +178,14 @@ function App() {
<ListItemIcon> <ListItemIcon>
<ListIcon /> <ListIcon />
</ListItemIcon> </ListItemIcon>
<ListItemText primary="List view" /> <Link to="/"><ListItemText primary="List view" /></Link>
</ListItem> </ListItem>
<ListItem button key="live" onClick={() => clickActivity("live")}> <ListItem button key="live" onClick={() => clickActivity("live")}>
<ListItemIcon> <ListItemIcon>
<Videocam /> <Videocam />
</ListItemIcon> </ListItemIcon>
<ListItemText primary="Live view (experimental)" />
<Link to="/live"><ListItemText primary="Live view (experimental)" /></Link>
</ListItem> </ListItem>
</List> </List>
</Drawer> </Drawer>
@ -206,8 +211,10 @@ function App() {
</p> </p>
</Container> </Container>
)} )}
{activityMain} <Routes >
</> {fetchedCameras(cameras)}
</Routes>
</BrowserRouter>
); );
} }

View File

@ -8,6 +8,7 @@ import React, { useReducer } from "react";
import { Camera } from "../types"; import { Camera } from "../types";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
import { Theme } from "@mui/material/styles"; import { Theme } from "@mui/material/styles";
import {useSearchParams} from "react-router-dom";
export interface Layout { export interface Layout {
className: string; className: string;
@ -150,6 +151,7 @@ function selectedReducer(old: SelectedCameras, op: SelectOp): SelectedCameras {
* as possible. * as possible.
*/ */
const Multiview = (props: MultiviewProps) => { const Multiview = (props: MultiviewProps) => {
const [selected, updateSelected] = useReducer( const [selected, updateSelected] = useReducer(
selectedReducer, selectedReducer,
Array(MAX_CAMERAS).fill(null) Array(MAX_CAMERAS).fill(null)
@ -198,15 +200,18 @@ interface MonoviewProps {
/** A single pane of a Multiview, including its camera chooser. */ /** A single pane of a Multiview, including its camera chooser. */
const Monoview = (props: MonoviewProps) => { const Monoview = (props: MonoviewProps) => {
const [searchParams, setSearchParams] = useSearchParams();
const handleChange = (event: SelectChangeEvent<number | null>) => { const handleChange = (event: SelectChangeEvent<number | null>) => {
const { const {
target: { value }, target: { value },
} = event; } = event;
props.onSelect(typeof value === "string" ? parseInt(value) : value); props.onSelect(typeof value === "string" ? parseInt(value) : value);
}; };
const fromQueryOrFirst = searchParams.has('cam') ? Number.parseInt(searchParams.get('cam') as string, 10) : 0;
const chooser = ( const chooser = (
<Select <Select
value={props.cameraIndex == null ? undefined : props.cameraIndex} value={props.cameraIndex == null ? fromQueryOrFirst: props.cameraIndex}
onChange={handleChange} onChange={handleChange}
displayEmpty displayEmpty
size="small" size="small"
@ -227,7 +232,7 @@ const Monoview = (props: MonoviewProps) => {
</Select> </Select>
); );
return props.renderCamera( return props.renderCamera(
props.cameraIndex === null ? null : props.cameras[props.cameraIndex], props.cameraIndex === null ? props.cameras[fromQueryOrFirst] : props.cameras[props.cameraIndex],
chooser chooser
); );
}; };