Skip to content

Commit

Permalink
Merge pull request #728 from roflcoopter/feature/v3.0.0b1-fixes
Browse files Browse the repository at this point in the history
Feature/v3.0.0b1 fixes
  • Loading branch information
roflcoopter committed Apr 8, 2024
2 parents 59d89ae + d31f527 commit b2007ab
Show file tree
Hide file tree
Showing 24 changed files with 328 additions and 123 deletions.
3 changes: 2 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ ENV \
DEBIAN_FRONTEND=noninteractive \
S6_KEEP_ENV=1 \
S6_SERVICES_GRACETIME=30000 \
S6_KILL_GRACETIME=1000 \
S6_KILL_GRACETIME=30000 \
S6_KILL_FINISH_MAXTIME=30000 \
PATH=$PATH:/home/abc/bin \
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib \
PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.8/site-packages \
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/events/CameraPickerDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const CameraPickerDialog = ({
<DialogTitle>Cameras</DialogTitle>
<DialogContent onClick={handleClose}>
<EventsCameraGrid
variant="grid"
cameras={cameras}
changeSelectedCamera={changeSelectedCamera}
selectedCamera={selectedCamera}
Expand Down
63 changes: 31 additions & 32 deletions frontend/src/components/events/EventPlayerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ type PlayerCardProps = {
requestedTimestamp: number | null;
selectedTab: "events" | "timeline";
hlsRef: React.MutableRefObject<Hls | null>;
playerCardRef: React.RefObject<HTMLDivElement>;
};

export const PlayerCard = ({
Expand All @@ -126,35 +127,33 @@ export const PlayerCard = ({
requestedTimestamp,
selectedTab,
hlsRef,
}: PlayerCardProps) => {
const ref = useRef<HTMLDivElement>(null);
return (
<Card
ref={ref}
variant="outlined"
sx={{
marginBottom: "10px",
position: "relative",
}}
>
{camera && <CameraNameOverlay camera={camera} />}
<CardMedia>
{eventSource && selectedTab === "events" ? (
<EventPlayer source={eventSource} />
) : camera && requestedTimestamp && selectedTab === "timeline" ? (
<TimelinePlayer
containerRef={ref}
hlsRef={hlsRef}
camera={camera}
requestedTimestamp={requestedTimestamp}
/>
) : (
<VideoPlayerPlaceholder
aspectRatio={camera ? camera.width / camera.height : undefined}
text={camera ? "Select an event" : "Select a camera"}
/>
)}
</CardMedia>
</Card>
);
};
playerCardRef,
}: PlayerCardProps) => (
<Card
ref={playerCardRef}
variant="outlined"
sx={(theme) => ({
marginBottom: theme.margin,
position: "relative",
})}
>
{camera && <CameraNameOverlay camera={camera} />}
<CardMedia>
{eventSource && selectedTab === "events" ? (
<EventPlayer source={eventSource} />
) : camera && requestedTimestamp && selectedTab === "timeline" ? (
<TimelinePlayer
containerRef={playerCardRef}
hlsRef={hlsRef}
camera={camera}
requestedTimestamp={requestedTimestamp}
/>
) : (
<VideoPlayerPlaceholder
aspectRatio={camera ? camera.width / camera.height : undefined}
text={camera ? "Select an event" : "Select a camera"}
/>
)}
</CardMedia>
</Card>
);
24 changes: 23 additions & 1 deletion frontend/src/components/events/EventTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,35 @@ import Divider from "@mui/material/Divider";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import dayjs, { Dayjs } from "dayjs";
import { memo } from "react";
import { memo, useEffect } from "react";
import { forceCheck } from "react-lazyload";
import ServerDown from "svg/undraw/server_down.svg?react";

import { ErrorMessage } from "components/error/ErrorMessage";
import { EventTableItem } from "components/events/EventTableItem";
import { Loading } from "components/loading/Loading";
import { useRecordings } from "lib/api/recordings";
import { throttle } from "lib/helpers";
import * as types from "lib/types";

const useOnScroll = (parentRef: React.RefObject<HTMLDivElement>) => {
useEffect(() => {
const container = parentRef.current;
if (!container) return () => {};

const throttleForceCheck = throttle(() => {
forceCheck();
}, 100);
container.addEventListener("scroll", throttleForceCheck);

return () => {
container.removeEventListener("scroll", throttleForceCheck);
};
});
};

type EventTableProps = {
parentRef: React.RefObject<HTMLDivElement>;
camera: types.Camera | types.FailedCamera;
date: Dayjs | null;
selectedRecording: types.Recording | null;
Expand All @@ -21,6 +40,7 @@ type EventTableProps = {

export const EventTable = memo(
({
parentRef,
camera,
date,
selectedRecording,
Expand All @@ -34,6 +54,8 @@ export const EventTable = memo(
configOptions: { enabled: !!date },
});

useOnScroll(parentRef);

if (recordingsQuery.isError) {
return (
<ErrorMessage
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/events/EventTableItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const EventTableItem = ({
>
<LazyLoad
overflow
offset={100}
placeholder={
<VideoPlayerPlaceholder
aspectRatio={camera.width / camera.height}
Expand Down
110 changes: 106 additions & 4 deletions frontend/src/components/events/EventsCameraGrid.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,61 @@
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Grid from "@mui/material/Grid";
import Grow from "@mui/material/Grow";
import { useTheme } from "@mui/material/styles";
import { useEffect, useRef } from "react";

import { CameraCard } from "components/camera/CameraCard";
import { COLUMN_HEIGHT } from "components/events/timeline/utils";
import * as types from "lib/types";

type EventsCameraGridProps = {
const useResizeObserver = (
divRef: React.RefObject<HTMLDivElement>,
playerCardRef: React.RefObject<HTMLDivElement> | undefined,
) => {
const theme = useTheme();
const resizeObserver = useRef<ResizeObserver>();

useEffect(() => {
if (!divRef.current || !playerCardRef || !playerCardRef.current) {
return () => {};
}

resizeObserver.current = new ResizeObserver(() => {
if (!divRef.current || !playerCardRef.current) {
return;
}

divRef.current.style.maxHeight = `calc(${COLUMN_HEIGHT} - ${theme.headerHeight}px - ${theme.margin} - ${playerCardRef.current.offsetHeight}px)`;
});

resizeObserver.current.observe(playerCardRef.current);

return () => {
if (resizeObserver.current) {
resizeObserver.current.disconnect();
}
};
}, [divRef, playerCardRef, theme.headerHeight, theme.margin]);
};

type CameraGridProps = {
cameras: types.CamerasOrFailedCameras;
changeSelectedCamera: (
ev: React.MouseEvent<HTMLButtonElement, MouseEvent>,
camera: types.Camera | types.FailedCamera,
) => void;
selectedCamera: types.Camera | types.FailedCamera | null;
};
export function EventsCameraGrid({
function CameraGrid({
cameras,
changeSelectedCamera,
selectedCamera,
}: EventsCameraGridProps) {
}: CameraGridProps) {
const theme = useTheme();

return (
<Grid container spacing={1}>
<Grid container spacing={0.5}>
{cameras
? Object.keys(cameras)
.sort()
Expand Down Expand Up @@ -54,3 +89,70 @@ export function EventsCameraGrid({
</Grid>
);
}

type EventsCameraGridPropsCard = {
variant: "card";
playerCardRef: React.RefObject<HTMLDivElement>;
cameras: types.CamerasOrFailedCameras;
changeSelectedCamera: (
ev: React.MouseEvent<HTMLButtonElement, MouseEvent>,
camera: types.Camera | types.FailedCamera,
) => void;
selectedCamera: types.Camera | types.FailedCamera | null;
};
type EventsCameraGridPropsGrid = {
variant?: "grid";
cameras: types.CamerasOrFailedCameras;
changeSelectedCamera: (
ev: React.MouseEvent<HTMLButtonElement, MouseEvent>,
camera: types.Camera | types.FailedCamera,
) => void;
selectedCamera: types.Camera | types.FailedCamera | null;
};
type EventsCameraGridProps =
| EventsCameraGridPropsCard
| EventsCameraGridPropsGrid;
export function EventsCameraGrid(props: EventsCameraGridProps) {
const {
variant = "card",
cameras,
changeSelectedCamera,
selectedCamera,
} = props;

const playerCardRef =
variant === "card"
? (props as EventsCameraGridPropsCard).playerCardRef
: undefined;

const ref = useRef<HTMLDivElement>(null);
useResizeObserver(ref, playerCardRef);

if (variant === "grid") {
return (
<CameraGrid
cameras={cameras}
changeSelectedCamera={changeSelectedCamera}
selectedCamera={selectedCamera}
/>
);
}
return (
<Card
ref={ref}
variant="outlined"
sx={{
overflow: "auto",
overflowX: "hidden",
}}
>
<CardContent sx={{ padding: 0 }}>
<CameraGrid
cameras={cameras}
changeSelectedCamera={changeSelectedCamera}
selectedCamera={selectedCamera}
/>
</CardContent>
</Card>
);
}
16 changes: 12 additions & 4 deletions frontend/src/components/events/Layouts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { PlayerCard } from "components/events/EventPlayerCard";
import { EventTable } from "components/events/EventTable";
import { EventsCameraGrid } from "components/events/EventsCameraGrid";
import { TimelineTable } from "components/events/timeline/TimelineTable";
import { COLUMN_HEIGHT } from "components/events/timeline/utils";
import { insertURLParameter } from "lib/helpers";
import * as types from "lib/types";

Expand Down Expand Up @@ -162,6 +163,7 @@ const Tabs = ({
<TabPanel value="events" sx={{ padding: 0, paddingTop: "5px" }}>
{selectedCamera ? (
<EventTable
parentRef={parentRef}
camera={selectedCamera}
date={date}
selectedRecording={selectedRecording}
Expand Down Expand Up @@ -225,16 +227,18 @@ export const Layout = memo(
selectedTab,
setSelectedTab,
}: LayoutProps) => {
const theme = useTheme();
const parentRef = useRef<HTMLDivElement | null>(null);
const hlsRef = useRef<Hls | null>(null);
const playerCardRef = useRef<HTMLDivElement | null>(null);
return (
<Container style={{ display: "flex" }}>
<div
style={{
width: "100%",
display: "flex",
flexDirection: "column",
marginRight: "10px",
marginRight: theme.margin,
}}
>
<PlayerCard
Expand All @@ -243,8 +247,10 @@ export const Layout = memo(
requestedTimestamp={requestedTimestamp}
selectedTab={selectedTab}
hlsRef={hlsRef}
playerCardRef={playerCardRef}
/>
<EventsCameraGrid
playerCardRef={playerCardRef}
cameras={cameras}
changeSelectedCamera={changeSelectedCamera}
selectedCamera={selectedCamera}
Expand All @@ -253,12 +259,12 @@ export const Layout = memo(
<Card
ref={parentRef}
variant="outlined"
sx={(theme) => ({
sx={{
width: "650px",
height: `calc(98dvh - ${theme.headerHeight}px)`,
height: `calc(${COLUMN_HEIGHT} - ${theme.headerHeight}px)`,
overflow: "auto",
overflowX: "hidden",
})}
}}
>
<CardContent sx={{ padding: 0 }}>
<Tabs
Expand Down Expand Up @@ -303,6 +309,7 @@ export const LayoutSmall = memo(
const theme = useTheme();
const parentRef = useRef<HTMLDivElement | null>(null);
const hlsRef = useRef<Hls | null>(null);
const playerCardRef = useRef<HTMLDivElement | null>(null);

// Observe div height to calculate the height of the EventTable
const [height, setHeight] = useState();
Expand Down Expand Up @@ -331,6 +338,7 @@ export const LayoutSmall = memo(
requestedTimestamp={requestedTimestamp}
selectedTab={selectedTab}
hlsRef={hlsRef}
playerCardRef={playerCardRef}
/>
</div>
<Card
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/events/timeline/HoverLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const useSetPosition = (
if (y === 0) {
return;
}
const top = e.clientY;
const top = e.clientY + window.scrollY;

const dateAtCursor = getDateAtPosition(
y,
Expand Down
Loading

0 comments on commit b2007ab

Please sign in to comment.