From 14e50a4711c8b35ae1da0f93e35a24471712dfd0 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Fri, 13 Sep 2024 15:12:25 -0500 Subject: [PATCH] navigate to history view from explore video tab --- frigate/api/review.py | 12 +++ .../overlay/detail/SearchDetailDialog.tsx | 75 ++++++++++++++----- 2 files changed, 68 insertions(+), 19 deletions(-) diff --git a/frigate/api/review.py b/frigate/api/review.py index 6bb2a4800..d391828d5 100644 --- a/frigate/api/review.py +++ b/frigate/api/review.py @@ -94,6 +94,18 @@ def review(): return jsonify([r for r in review]) +@ReviewBp.route("/review/event/") +def get_review_from_event(id: str): + try: + return model_to_dict( + ReviewSegment.get( + ReviewSegment.data["detections"].cast("text") % f'*"{id}"*' + ) + ) + except DoesNotExist: + return "Review item not found", 404 + + @ReviewBp.route("/review/") def get_review(id: str): try: diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx index 7417cb3c4..e4651d6dd 100644 --- a/web/src/components/overlay/detail/SearchDetailDialog.tsx +++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx @@ -27,7 +27,7 @@ import { baseUrl } from "@/api/baseUrl"; import { cn } from "@/lib/utils"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record"; -import { FaImage, FaRegListAlt, FaVideo } from "react-icons/fa"; +import { FaHistory, FaImage, FaRegListAlt, FaVideo } from "react-icons/fa"; import { FaRotate } from "react-icons/fa6"; import ObjectLifecycle from "./ObjectLifecycle"; import { @@ -37,6 +37,14 @@ import { MobilePageHeader, MobilePageTitle, } from "@/components/mobile/MobilePage"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { ReviewSegment } from "@/types/review"; +import { useNavigate } from "react-router-dom"; +import Chip from "@/components/indicators/Chip"; const SEARCH_TABS = [ "details", @@ -226,10 +234,10 @@ function ObjectDetailsTab({ // data - const [desc, setDesc] = useState(search?.description); + const [desc, setDesc] = useState(search?.data.description); // we have to make sure the current selected search item stays in sync - useEffect(() => setDesc(search?.description), [search]); + useEffect(() => setDesc(search?.data.description), [search]); const formattedDate = useFormattedTimestamp( search?.start_time ?? 0, @@ -279,7 +287,7 @@ function ObjectDetailsTab({ toast.error("Failed to update the description", { position: "top-center", }); - setDesc(search.description); + setDesc(search.data.description); }); }, [desc, search]); @@ -367,6 +375,11 @@ function VideoTab({ search, config }: VideoTabProps) { const endTime = useMemo(() => search.end_time ?? Date.now() / 1000, [search]); + const navigate = useNavigate(); + const { data: reviewItem } = useSWR([ + `review/event/${search.id}`, + ]); + const mainCameraAspect = useMemo(() => { const camera = config?.cameras?.[search.camera]; @@ -416,22 +429,46 @@ function VideoTab({ search, config }: VideoTabProps) { }, [mainCameraAspect]); return ( -
- {isLoading && ( - - )} -
- setIsLoading(false)} - /> +
+
+ {(isLoading || !reviewItem) && ( + + )} +
+ setIsLoading(false)} + /> +
+ {!isLoading && ( +
+ + + { + if (reviewItem?.id) { + const params = new URLSearchParams({ + id: reviewItem.id, + }).toString(); + navigate(`/review?${params}`); + } + }} + > + + + + View in History + +
+ )}
); }