Add ability to link to review items directly (#11002)

* Fix action group icon colors

* Add ability to query specific review item

* Pull id search key and open recordings to review item
This commit is contained in:
Nicolas Mowen 2024-04-17 06:02:03 -06:00 committed by GitHub
parent ff823b87c8
commit a87cca23ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 6 deletions

View File

@ -8,6 +8,7 @@ from pathlib import Path
import pandas as pd
from flask import Blueprint, jsonify, make_response, request
from peewee import Case, DoesNotExist, fn, operator
from playhouse.shortcuts import model_to_dict
from frigate.models import Recordings, ReviewSegment
from frigate.util.builtin import get_tz_modifiers
@ -78,6 +79,14 @@ def review():
return jsonify([r for r in review])
@ReviewBp.route("/review/<id>")
def get_review(id: str):
try:
return model_to_dict(ReviewSegment.get(ReviewSegment.id == id))
except DoesNotExist:
return "Review item not found", 404
@ReviewBp.route("/review/summary")
def review_summary():
tz_name = request.args.get("timezone", default="utc", type=str)

View File

@ -56,7 +56,7 @@ export default function ReviewActionGroup({
onClearSelected();
}}
>
<FaCompactDisc />
<FaCompactDisc className="text-secondary-foreground" />
{isDesktop && <div className="text-primary">Export</div>}
</Button>
)}
@ -65,15 +65,15 @@ export default function ReviewActionGroup({
size="sm"
onClick={onMarkAsReviewed}
>
<FaCircleCheck />
<FaCircleCheck className="text-secondary-foreground" />
{isDesktop && <div className="text-primary">Mark as reviewed</div>}
</Button>
<Button
className="p-2 flex items-center gap-1"
className="p-2 flex items-center gap-2"
size="sm"
onClick={onDelete}
>
<HiTrash />
<HiTrash className="text-secondary-foreground" />
{isDesktop && <div className="text-primary">Delete</div>}
</Button>
</div>

View File

@ -1,4 +1,4 @@
import { useCallback, useMemo } from "react";
import { useCallback, useEffect, useMemo } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { usePersistence } from "./use-persistence";
@ -91,3 +91,30 @@ export function useHashState<S extends string>(): [
return [hash, setHash];
}
export function useSearchEffect(
key: string,
callback: (value: string) => void,
) {
const location = useLocation();
const param = useMemo(() => {
if (!location || !location.search || location.search.length == 0) {
return undefined;
}
const params = location.search.substring(1).split("&");
return params
.find((p) => p.includes("=") && p.split("=")[0] == key)
?.split("=");
}, [location, key]);
useEffect(() => {
if (!param) {
return;
}
callback(param[1]);
}, [param, callback]);
}

View File

@ -1,7 +1,7 @@
import ActivityIndicator from "@/components/indicators/activity-indicator";
import useApiFilter from "@/hooks/use-api-filter";
import { useTimezone } from "@/hooks/use-date-utils";
import { useOverlayState } from "@/hooks/use-overlay-state";
import { useOverlayState, useSearchEffect } from "@/hooks/use-overlay-state";
import { FrigateConfig } from "@/types/frigateConfig";
import { Preview } from "@/types/preview";
import { RecordingStartingPoint } from "@/types/record";
@ -33,6 +33,24 @@ export default function Events() {
const [recording, setRecording] =
useOverlayState<RecordingStartingPoint>("recording");
useSearchEffect("id", (reviewId: string) => {
axios
.get(`review/${reviewId}`)
.then((resp) => {
if (resp.status == 200 && resp.data) {
setRecording(
{
camera: resp.data.camera,
startTime: resp.data.start_time,
severity: resp.data.severity,
},
true,
);
}
})
.catch(() => {});
});
const [startTime, setStartTime] = useState<number>();
useEffect(() => {