From 33e98b4043687b9d07821597611491146061c570 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Tue, 5 Mar 2024 14:29:27 -0700 Subject: [PATCH] Update api to use json and add button to mark all as reviewed --- frigate/api/review.py | 24 +++---------- .../components/filter/ReviewActionGroup.tsx | 2 +- web/src/components/ui/button.tsx | 2 +- web/src/pages/Events.tsx | 2 +- web/src/views/events/EventView.tsx | 34 +++++++++++++++---- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/frigate/api/review.py b/frigate/api/review.py index 2fdc1ef0e..34155ec5e 100644 --- a/frigate/api/review.py +++ b/frigate/api/review.py @@ -195,26 +195,10 @@ def review_summary(): return jsonify([e for e in groups.dicts().iterator()]) -@ReviewBp.route("/review//viewed", methods=("POST",)) -def set_reviewed(id): - try: - review: ReviewSegment = ReviewSegment.get(ReviewSegment.id == id) - except DoesNotExist: - return make_response( - jsonify({"success": False, "message": "Review " + id + " not found"}), 404 - ) - - review.has_been_reviewed = True - review.save() - - return make_response( - jsonify({"success": True, "message": "Reviewed " + id + " viewed"}), 200 - ) - - -@ReviewBp.route("/reviews//viewed", methods=("POST",)) -def set_multiple_reviewed(ids: str): - list_of_ids = ids.split(",") +@ReviewBp.route("/reviews/viewed", methods=("POST",)) +def set_multiple_reviewed(): + json: dict[str, any] = request.get_json(silent=True) or {} + list_of_ids = json.get("ids", "") if not list_of_ids or len(list_of_ids) == 0: return make_response( diff --git a/web/src/components/filter/ReviewActionGroup.tsx b/web/src/components/filter/ReviewActionGroup.tsx index 1453792f8..5e1a93185 100644 --- a/web/src/components/filter/ReviewActionGroup.tsx +++ b/web/src/components/filter/ReviewActionGroup.tsx @@ -22,7 +22,7 @@ export default function ReviewActionGroup({ const onMarkAsReviewed = useCallback(async () => { const idList = selectedReviews.join(","); - await axios.post(`reviews/${idList}/viewed`); + await axios.post(`reviews/viewed`, { ids: idList }); setSelectedReviews([]); pullLatestData(); }, [selectedReviews, setSelectedReviews, pullLatestData]); diff --git a/web/src/components/ui/button.tsx b/web/src/components/ui/button.tsx index 8e97b5778..28a234664 100644 --- a/web/src/components/ui/button.tsx +++ b/web/src/components/ui/button.tsx @@ -9,7 +9,7 @@ const buttonVariants = cva( { variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", + default: "bg-selected text-primary-foreground hover:bg-opacity-60", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", outline: diff --git a/web/src/pages/Events.tsx b/web/src/pages/Events.tsx index 9ca4986c3..c7564573c 100644 --- a/web/src/pages/Events.tsx +++ b/web/src/pages/Events.tsx @@ -164,7 +164,7 @@ export default function Events() { const markItemAsReviewed = useCallback( async (review: ReviewSegment) => { - const resp = await axios.post(`review/${review.id}/viewed`); + const resp = await axios.post(`reviews/viewed`, { ids: [review.id] }); if (resp.status == 200) { updateSegments( diff --git a/web/src/views/events/EventView.tsx b/web/src/views/events/EventView.tsx index 1b12952ee..495a10f30 100644 --- a/web/src/views/events/EventView.tsx +++ b/web/src/views/events/EventView.tsx @@ -35,6 +35,7 @@ import { LuFolderCheck } from "react-icons/lu"; import { MdCircle } from "react-icons/md"; import useSWR from "swr"; import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline"; +import { Button } from "@/components/ui/button"; type EventViewProps = { reviewPages?: ReviewSegment[][]; @@ -241,9 +242,7 @@ export default function EventView({ aria-label="Select motion" > -
- Motion ∙ {reviewCounts.significant_motion} -
+
Motion
@@ -303,6 +302,7 @@ type DetectionReviewProps = { detection: ReviewSegment[]; significant_motion: ReviewSegment[]; }; + itemsToReview?: number; relevantPreviews?: Preview[]; pagingObserver: MutableRefObject; selectedReviews: string[]; @@ -320,6 +320,7 @@ function DetectionReview({ contentRef, currentItems, reviewItems, + itemsToReview, relevantPreviews, pagingObserver, selectedReviews, @@ -359,6 +360,17 @@ function DetectionReview({ [isValidating, pagingObserver, reachedEnd, loadNextPage], ); + const markAllReviewed = useCallback(async () => { + if (!currentItems) { + return; + } + + await axios.post(`reviews/viewed`, { + ids: currentItems?.map((seg) => seg.id), + }); + pullLatestData(); + }, [currentItems, pullLatestData]); + // timeline interaction const { alignStartDateToTimeline } = useEventUtils( @@ -453,7 +465,7 @@ function DetectionReview({ /> )} - {!isValidating && currentItems == null && ( + {(itemsToReview == 0 || (currentItems == null && !isValidating)) && (
There are no {severity.replace(/_/g, " ")} items to review @@ -489,13 +501,23 @@ function DetectionReview({ onClick={onSelectReview} />
- {lastRow && !reachedEnd && } ); }) - ) : severity != "alert" ? ( + ) : itemsToReview != 0 ? (
) : null} + {currentItems && ( +
+ {reachedEnd ? ( + + ) : ( + + )} +
+ )}