From 11dc407b3679480e04f52ac92c91d8a6cab47ade Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 12 Apr 2024 06:31:30 -0600 Subject: [PATCH] Further improve event loading (#10949) * Further improve loading * Add document titles to pages * Cleanup --- web/src/pages/ConfigEditor.tsx | 4 ++ web/src/pages/Events.tsx | 10 ++++ web/src/pages/Export.tsx | 6 +- web/src/pages/Live.tsx | 21 ++++++- web/src/pages/Logs.tsx | 4 ++ web/src/pages/NoMatch.tsx | 5 ++ web/src/pages/SubmitPlus.tsx | 6 +- web/src/pages/System.tsx | 6 +- web/src/views/events/EventView.tsx | 94 ++++++++++++++++-------------- 9 files changed, 108 insertions(+), 48 deletions(-) diff --git a/web/src/pages/ConfigEditor.tsx b/web/src/pages/ConfigEditor.tsx index eca6b8fc8..126d6c66a 100644 --- a/web/src/pages/ConfigEditor.tsx +++ b/web/src/pages/ConfigEditor.tsx @@ -17,6 +17,10 @@ type SaveOptions = "saveonly" | "restart"; function ConfigEditor() { const apiHost = useApiHost(); + useEffect(() => { + document.title = "Config Editor - Frigate"; + }, []); + const { data: config } = useSWR("config/raw"); const { theme, systemTheme } = useTheme(); diff --git a/web/src/pages/Events.tsx b/web/src/pages/Events.tsx index c9dac4460..6277c6994 100644 --- a/web/src/pages/Events.tsx +++ b/web/src/pages/Events.tsx @@ -29,10 +29,20 @@ export default function Events() { "severity", "alert", ); + const [recording, setRecording] = useOverlayState("recording"); + const [startTime, setStartTime] = useState(); + useEffect(() => { + if (recording) { + document.title = "Recordings - Frigate"; + } else { + document.title = `Review - Frigate`; + } + }, [recording, severity]); + // review filter const [reviewFilter, setReviewFilter, reviewSearchParams] = diff --git a/web/src/pages/Export.tsx b/web/src/pages/Export.tsx index dfd524e44..c3978aa6c 100644 --- a/web/src/pages/Export.tsx +++ b/web/src/pages/Export.tsx @@ -12,7 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import axios from "axios"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import useSWR from "swr"; type ExportItem = { @@ -25,6 +25,10 @@ function Export() { (url: string) => axios({ baseURL: baseUrl, url }).then((res) => res.data), ); + useEffect(() => { + document.title = "Export - Frigate"; + }, []); + // Search const [search, setSearch] = useState(""); diff --git a/web/src/pages/Live.tsx b/web/src/pages/Live.tsx index c29fbed3b..4be6b2c16 100644 --- a/web/src/pages/Live.tsx +++ b/web/src/pages/Live.tsx @@ -6,18 +6,37 @@ import { FrigateConfig } from "@/types/frigateConfig"; import LiveBirdseyeView from "@/views/live/LiveBirdseyeView"; import LiveCameraView from "@/views/live/LiveCameraView"; import LiveDashboardView from "@/views/live/LiveDashboardView"; -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import useSWR from "swr"; function Live() { const { data: config } = useSWR("config"); + // selection + const [selectedCameraName, setSelectedCameraName] = useHashState(); const [cameraGroup] = usePersistedOverlayState( "cameraGroup", "default" as string, ); + // document title + + useEffect(() => { + if (selectedCameraName) { + const capitalized = selectedCameraName + .split("_") + .map((text) => text[0].toUpperCase() + text.substring(1)); + document.title = `${capitalized.join(" ")} - Live - Frigate`; + } else if (cameraGroup && cameraGroup != "default") { + document.title = `${cameraGroup[0].toUpperCase()}${cameraGroup.substring(1)} - Live - Frigate`; + } else { + document.title = "Live - Frigate"; + } + }, [cameraGroup, selectedCameraName]); + + // settings + const includesBirdseye = useMemo(() => { if (config && cameraGroup && cameraGroup != "default") { return config.camera_groups[cameraGroup].cameras.includes("birdseye"); diff --git a/web/src/pages/Logs.tsx b/web/src/pages/Logs.tsx index 97e1f7c55..a2f5072cc 100644 --- a/web/src/pages/Logs.tsx +++ b/web/src/pages/Logs.tsx @@ -29,6 +29,10 @@ const ngSeverity = /(GET)|(POST)|(PUT)|(PATCH)|(DELETE)/; function Logs() { const [logService, setLogService] = useState("frigate"); + useEffect(() => { + document.title = `${logService[0].toUpperCase()}${logService.substring(1)} Stats - Frigate`; + }, [logService]); + // log data handling const [logRange, setLogRange] = useState({ start: 0, end: 0 }); diff --git a/web/src/pages/NoMatch.tsx b/web/src/pages/NoMatch.tsx index c3660928b..933794abb 100644 --- a/web/src/pages/NoMatch.tsx +++ b/web/src/pages/NoMatch.tsx @@ -1,6 +1,11 @@ import Heading from "@/components/ui/heading"; +import { useEffect } from "react"; function NoMatch() { + useEffect(() => { + document.title = "Not Found - Frigate"; + }, []); + return ( <> 404 diff --git a/web/src/pages/SubmitPlus.tsx b/web/src/pages/SubmitPlus.tsx index d1d6fc9c0..831b0370c 100644 --- a/web/src/pages/SubmitPlus.tsx +++ b/web/src/pages/SubmitPlus.tsx @@ -20,7 +20,7 @@ import { import { Event } from "@/types/event"; import { FrigateConfig } from "@/types/frigateConfig"; import axios from "axios"; -import { useCallback, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { isMobile } from "react-device-detect"; import { FaList, FaVideo } from "react-icons/fa"; import useSWR from "swr"; @@ -28,6 +28,10 @@ import useSWR from "swr"; export default function SubmitPlus() { const { data: config } = useSWR("config"); + useEffect(() => { + document.title = "Plus - Frigate"; + }, []); + // filters const [selectedCameras, setSelectedCameras] = useState(); diff --git a/web/src/pages/System.tsx b/web/src/pages/System.tsx index a38dc1b18..8693a30b1 100644 --- a/web/src/pages/System.tsx +++ b/web/src/pages/System.tsx @@ -1,6 +1,6 @@ import useSWR from "swr"; import { FrigateStats } from "@/types/stats"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import TimeAgo from "@/components/dynamic/TimeAgo"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { isDesktop, isMobile } from "react-device-detect"; @@ -22,6 +22,10 @@ function System() { const [pageToggle, setPageToggle] = useOptimisticState(page, setPage, 100); const [lastUpdated, setLastUpdated] = useState(Date.now() / 1000); + useEffect(() => { + document.title = `${pageToggle[0].toUpperCase()}${pageToggle.substring(1)} Stats - Frigate`; + }, [pageToggle]); + // stats collection const { data: statsSnapshot } = useSWR("stats", { diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index a1b568bbf..c6736e3a4 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -290,7 +290,7 @@ export default function EventView({ reviewItems={reviewItems} relevantPreviews={relevantPreviews} selectedReviews={selectedReviews} - itemsToReview={reviewCounts[severity]} + itemsToReview={reviewCounts[severityToggle]} severity={severity} filter={filter} timeRange={timeRange} @@ -533,7 +533,7 @@ function DetectionReview({ className="absolute left-1/2 -translate-x-1/2 z-50 pointer-events-none" contentRef={contentRef} reviewItems={currentItems} - itemsToReview={itemsToReview} + itemsToReview={loading ? 0 : itemsToReview} pullLatestData={pullLatestData} /> )} @@ -544,7 +544,7 @@ function DetectionReview({ )} - {currentItems?.length === 0 && ( + {!loading && currentItems?.length === 0 && (
There are no {severity.replace(/_/g, " ")}s to review @@ -555,50 +555,56 @@ function DetectionReview({ className="w-full mx-2 px-1 grid sm:grid-cols-2 md:grid-cols-3 3xl:grid-cols-4 gap-2 md:gap-4" ref={contentRef} > - {currentItems && - currentItems.map((value) => { - const selected = selectedReviews.includes(value.id); + {!loading && currentItems + ? currentItems.map((value) => { + const selected = selectedReviews.includes(value.id); - return ( -
-
- +
+ +
+
-
-
- ); - })} - {(currentItems?.length ?? 0) > 0 && (itemsToReview ?? 0) > 0 && ( -
- -
- )} + ); + }) + : Array(itemsToReview) + .fill(0) + .map(() => )} + {!loading && + (currentItems?.length ?? 0) > 0 && + (itemsToReview ?? 0) > 0 && ( +
+ +
+ )}