mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-01-16 00:09:14 +01:00
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:
parent
ff823b87c8
commit
a87cca23ea
@ -8,6 +8,7 @@ from pathlib import Path
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
from flask import Blueprint, jsonify, make_response, request
|
from flask import Blueprint, jsonify, make_response, request
|
||||||
from peewee import Case, DoesNotExist, fn, operator
|
from peewee import Case, DoesNotExist, fn, operator
|
||||||
|
from playhouse.shortcuts import model_to_dict
|
||||||
|
|
||||||
from frigate.models import Recordings, ReviewSegment
|
from frigate.models import Recordings, ReviewSegment
|
||||||
from frigate.util.builtin import get_tz_modifiers
|
from frigate.util.builtin import get_tz_modifiers
|
||||||
@ -78,6 +79,14 @@ def review():
|
|||||||
return jsonify([r for r in 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")
|
@ReviewBp.route("/review/summary")
|
||||||
def review_summary():
|
def review_summary():
|
||||||
tz_name = request.args.get("timezone", default="utc", type=str)
|
tz_name = request.args.get("timezone", default="utc", type=str)
|
||||||
|
@ -56,7 +56,7 @@ export default function ReviewActionGroup({
|
|||||||
onClearSelected();
|
onClearSelected();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FaCompactDisc />
|
<FaCompactDisc className="text-secondary-foreground" />
|
||||||
{isDesktop && <div className="text-primary">Export</div>}
|
{isDesktop && <div className="text-primary">Export</div>}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
@ -65,15 +65,15 @@ export default function ReviewActionGroup({
|
|||||||
size="sm"
|
size="sm"
|
||||||
onClick={onMarkAsReviewed}
|
onClick={onMarkAsReviewed}
|
||||||
>
|
>
|
||||||
<FaCircleCheck />
|
<FaCircleCheck className="text-secondary-foreground" />
|
||||||
{isDesktop && <div className="text-primary">Mark as reviewed</div>}
|
{isDesktop && <div className="text-primary">Mark as reviewed</div>}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="p-2 flex items-center gap-1"
|
className="p-2 flex items-center gap-2"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={onDelete}
|
onClick={onDelete}
|
||||||
>
|
>
|
||||||
<HiTrash />
|
<HiTrash className="text-secondary-foreground" />
|
||||||
{isDesktop && <div className="text-primary">Delete</div>}
|
{isDesktop && <div className="text-primary">Delete</div>}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useEffect, useMemo } from "react";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import { usePersistence } from "./use-persistence";
|
import { usePersistence } from "./use-persistence";
|
||||||
|
|
||||||
@ -91,3 +91,30 @@ export function useHashState<S extends string>(): [
|
|||||||
|
|
||||||
return [hash, setHash];
|
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]);
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
import useApiFilter from "@/hooks/use-api-filter";
|
import useApiFilter from "@/hooks/use-api-filter";
|
||||||
import { useTimezone } from "@/hooks/use-date-utils";
|
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 { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Preview } from "@/types/preview";
|
import { Preview } from "@/types/preview";
|
||||||
import { RecordingStartingPoint } from "@/types/record";
|
import { RecordingStartingPoint } from "@/types/record";
|
||||||
@ -33,6 +33,24 @@ export default function Events() {
|
|||||||
const [recording, setRecording] =
|
const [recording, setRecording] =
|
||||||
useOverlayState<RecordingStartingPoint>("recording");
|
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>();
|
const [startTime, setStartTime] = useState<number>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
Loading…
Reference in New Issue
Block a user