mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-06 03:51:14 +03:00
add debug replay to detail actions menu
This commit is contained in:
parent
cb27e6ff1c
commit
d1b46706c9
@ -222,7 +222,7 @@
|
|||||||
"label": "Hide object path"
|
"label": "Hide object path"
|
||||||
},
|
},
|
||||||
"debugReplay": {
|
"debugReplay": {
|
||||||
"label": "Debug replay",
|
"label": "Debug Replay",
|
||||||
"aria": "View this tracked object in the debug replay view"
|
"aria": "View this tracked object in the debug replay view"
|
||||||
},
|
},
|
||||||
"more": {
|
"more": {
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { useMemo, useState } from "react";
|
import { useCallback, useMemo, useState } from "react";
|
||||||
|
import axios from "axios";
|
||||||
|
import { toast } from "sonner";
|
||||||
import { Event } from "@/types/event";
|
import { Event } from "@/types/event";
|
||||||
import { baseUrl } from "@/api/baseUrl";
|
import { baseUrl } from "@/api/baseUrl";
|
||||||
import { ReviewSegment, REVIEW_PADDING } from "@/types/review";
|
import { ReviewSegment, REVIEW_PADDING } from "@/types/review";
|
||||||
@ -12,6 +14,7 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
DropdownMenuPortal,
|
DropdownMenuPortal,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import { HiDotsHorizontal } from "react-icons/hi";
|
import { HiDotsHorizontal } from "react-icons/hi";
|
||||||
import { SearchResult } from "@/types/search";
|
import { SearchResult } from "@/types/search";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
@ -33,9 +36,14 @@ export default function DetailActionsMenu({
|
|||||||
setSearch,
|
setSearch,
|
||||||
setSimilarity,
|
setSimilarity,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { t } = useTranslation(["views/explore", "views/faceLibrary"]);
|
const { t } = useTranslation([
|
||||||
|
"views/explore",
|
||||||
|
"views/faceLibrary",
|
||||||
|
"views/replay",
|
||||||
|
]);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
const [isStarting, setIsStarting] = useState(false);
|
||||||
const isAdmin = useIsAdmin();
|
const isAdmin = useIsAdmin();
|
||||||
|
|
||||||
const clipTimeRange = useMemo(() => {
|
const clipTimeRange = useMemo(() => {
|
||||||
@ -49,6 +57,54 @@ export default function DetailActionsMenu({
|
|||||||
search.data?.type === "audio" ? null : [`review/event/${search.id}`],
|
search.data?.type === "audio" ? null : [`review/event/${search.id}`],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleDebugReplay = useCallback(() => {
|
||||||
|
setIsStarting(true);
|
||||||
|
|
||||||
|
axios
|
||||||
|
.post("debug_replay/start", {
|
||||||
|
camera: search.camera,
|
||||||
|
start_time: search.start_time,
|
||||||
|
end_time: search.end_time,
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 202 || response.status === 200) {
|
||||||
|
navigate("/replay");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
const errorMessage =
|
||||||
|
error.response?.data?.message ||
|
||||||
|
error.response?.data?.detail ||
|
||||||
|
"Unknown error";
|
||||||
|
|
||||||
|
if (error.response?.status === 409) {
|
||||||
|
toast.error(t("dialog.toast.alreadyActive", { ns: "views/replay" }), {
|
||||||
|
position: "top-center",
|
||||||
|
closeButton: true,
|
||||||
|
dismissible: false,
|
||||||
|
action: (
|
||||||
|
<a
|
||||||
|
href={`${baseUrl}replay`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
<Button>
|
||||||
|
{t("dialog.toast.goToReplay", { ns: "views/replay" })}
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast.error(t("dialog.toast.error", { error: errorMessage }), {
|
||||||
|
position: "top-center",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setIsStarting(false);
|
||||||
|
});
|
||||||
|
}, [navigate, search.camera, search.start_time, search.end_time, t]);
|
||||||
|
|
||||||
// don't render menu at all if no options are available
|
// don't render menu at all if no options are available
|
||||||
const hasSemanticSearchOption =
|
const hasSemanticSearchOption =
|
||||||
config?.semantic_search.enabled &&
|
config?.semantic_search.enabled &&
|
||||||
@ -172,6 +228,24 @@ export default function DetailActionsMenu({
|
|||||||
</div>
|
</div>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{search.has_clip && (
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="cursor-pointer"
|
||||||
|
aria-label={t("itemMenu.debugReplay.aria")}
|
||||||
|
disabled={isStarting}
|
||||||
|
onSelect={() => {
|
||||||
|
setIsOpen(false);
|
||||||
|
handleDebugReplay();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
{isStarting
|
||||||
|
? t("dialog.starting", { ns: "views/replay" })
|
||||||
|
: t("itemMenu.debugReplay.label")}
|
||||||
|
</span>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
</DropdownMenuPortal>
|
</DropdownMenuPortal>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user