mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-10 13:15:25 +03:00
Update api to use json and add button to mark all as reviewed
This commit is contained in:
parent
8f28dc0b9c
commit
33e98b4043
@ -195,26 +195,10 @@ def review_summary():
|
|||||||
return jsonify([e for e in groups.dicts().iterator()])
|
return jsonify([e for e in groups.dicts().iterator()])
|
||||||
|
|
||||||
|
|
||||||
@ReviewBp.route("/review/<id>/viewed", methods=("POST",))
|
@ReviewBp.route("/reviews/viewed", methods=("POST",))
|
||||||
def set_reviewed(id):
|
def set_multiple_reviewed():
|
||||||
try:
|
json: dict[str, any] = request.get_json(silent=True) or {}
|
||||||
review: ReviewSegment = ReviewSegment.get(ReviewSegment.id == id)
|
list_of_ids = json.get("ids", "")
|
||||||
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/<ids>/viewed", methods=("POST",))
|
|
||||||
def set_multiple_reviewed(ids: str):
|
|
||||||
list_of_ids = ids.split(",")
|
|
||||||
|
|
||||||
if not list_of_ids or len(list_of_ids) == 0:
|
if not list_of_ids or len(list_of_ids) == 0:
|
||||||
return make_response(
|
return make_response(
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export default function ReviewActionGroup({
|
|||||||
|
|
||||||
const onMarkAsReviewed = useCallback(async () => {
|
const onMarkAsReviewed = useCallback(async () => {
|
||||||
const idList = selectedReviews.join(",");
|
const idList = selectedReviews.join(",");
|
||||||
await axios.post(`reviews/${idList}/viewed`);
|
await axios.post(`reviews/viewed`, { ids: idList });
|
||||||
setSelectedReviews([]);
|
setSelectedReviews([]);
|
||||||
pullLatestData();
|
pullLatestData();
|
||||||
}, [selectedReviews, setSelectedReviews, pullLatestData]);
|
}, [selectedReviews, setSelectedReviews, pullLatestData]);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const buttonVariants = cva(
|
|||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
default: "bg-selected text-primary-foreground hover:bg-opacity-60",
|
||||||
destructive:
|
destructive:
|
||||||
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||||
outline:
|
outline:
|
||||||
|
|||||||
@ -164,7 +164,7 @@ export default function Events() {
|
|||||||
|
|
||||||
const markItemAsReviewed = useCallback(
|
const markItemAsReviewed = useCallback(
|
||||||
async (review: ReviewSegment) => {
|
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) {
|
if (resp.status == 200) {
|
||||||
updateSegments(
|
updateSegments(
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import { LuFolderCheck } from "react-icons/lu";
|
|||||||
import { MdCircle } from "react-icons/md";
|
import { MdCircle } from "react-icons/md";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline";
|
import MotionReviewTimeline from "@/components/timeline/MotionReviewTimeline";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
type EventViewProps = {
|
type EventViewProps = {
|
||||||
reviewPages?: ReviewSegment[][];
|
reviewPages?: ReviewSegment[][];
|
||||||
@ -241,9 +242,7 @@ export default function EventView({
|
|||||||
aria-label="Select motion"
|
aria-label="Select motion"
|
||||||
>
|
>
|
||||||
<MdCircle className="size-2 md:mr-[10px] text-severity_motion" />
|
<MdCircle className="size-2 md:mr-[10px] text-severity_motion" />
|
||||||
<div className="hidden md:block">
|
<div className="hidden md:block">Motion</div>
|
||||||
Motion ∙ {reviewCounts.significant_motion}
|
|
||||||
</div>
|
|
||||||
</ToggleGroupItem>
|
</ToggleGroupItem>
|
||||||
</ToggleGroup>
|
</ToggleGroup>
|
||||||
|
|
||||||
@ -303,6 +302,7 @@ type DetectionReviewProps = {
|
|||||||
detection: ReviewSegment[];
|
detection: ReviewSegment[];
|
||||||
significant_motion: ReviewSegment[];
|
significant_motion: ReviewSegment[];
|
||||||
};
|
};
|
||||||
|
itemsToReview?: number;
|
||||||
relevantPreviews?: Preview[];
|
relevantPreviews?: Preview[];
|
||||||
pagingObserver: MutableRefObject<IntersectionObserver | null>;
|
pagingObserver: MutableRefObject<IntersectionObserver | null>;
|
||||||
selectedReviews: string[];
|
selectedReviews: string[];
|
||||||
@ -320,6 +320,7 @@ function DetectionReview({
|
|||||||
contentRef,
|
contentRef,
|
||||||
currentItems,
|
currentItems,
|
||||||
reviewItems,
|
reviewItems,
|
||||||
|
itemsToReview,
|
||||||
relevantPreviews,
|
relevantPreviews,
|
||||||
pagingObserver,
|
pagingObserver,
|
||||||
selectedReviews,
|
selectedReviews,
|
||||||
@ -359,6 +360,17 @@ function DetectionReview({
|
|||||||
[isValidating, pagingObserver, reachedEnd, loadNextPage],
|
[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
|
// timeline interaction
|
||||||
|
|
||||||
const { alignStartDateToTimeline } = useEventUtils(
|
const { alignStartDateToTimeline } = useEventUtils(
|
||||||
@ -453,7 +465,7 @@ function DetectionReview({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isValidating && currentItems == null && (
|
{(itemsToReview == 0 || (currentItems == null && !isValidating)) && (
|
||||||
<div className="size-full flex flex-col justify-center items-center">
|
<div className="size-full flex flex-col justify-center items-center">
|
||||||
<LuFolderCheck className="size-16" />
|
<LuFolderCheck className="size-16" />
|
||||||
There are no {severity.replace(/_/g, " ")} items to review
|
There are no {severity.replace(/_/g, " ")} items to review
|
||||||
@ -489,13 +501,23 @@ function DetectionReview({
|
|||||||
onClick={onSelectReview}
|
onClick={onSelectReview}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{lastRow && !reachedEnd && <ActivityIndicator />}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
) : severity != "alert" ? (
|
) : itemsToReview != 0 ? (
|
||||||
<div ref={lastReviewRef} />
|
<div ref={lastReviewRef} />
|
||||||
) : null}
|
) : null}
|
||||||
|
{currentItems && (
|
||||||
|
<div className="col-span-full flex justify-center items-center">
|
||||||
|
{reachedEnd ? (
|
||||||
|
<Button className="text-white" onClick={markAllReviewed}>
|
||||||
|
Mark all items as reviewed
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<ActivityIndicator />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-[55px] md:w-[100px] mt-2 overflow-y-auto no-scrollbar">
|
<div className="w-[55px] md:w-[100px] mt-2 overflow-y-auto no-scrollbar">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user