mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-14 23:25:25 +03:00
navigate to history view from explore video tab
This commit is contained in:
parent
346d65d8fb
commit
14e50a4711
@ -94,6 +94,18 @@ def review():
|
|||||||
return jsonify([r for r in review])
|
return jsonify([r for r in review])
|
||||||
|
|
||||||
|
|
||||||
|
@ReviewBp.route("/review/event/<id>")
|
||||||
|
def get_review_from_event(id: str):
|
||||||
|
try:
|
||||||
|
return model_to_dict(
|
||||||
|
ReviewSegment.get(
|
||||||
|
ReviewSegment.data["detections"].cast("text") % f'*"{id}"*'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except DoesNotExist:
|
||||||
|
return "Review item not found", 404
|
||||||
|
|
||||||
|
|
||||||
@ReviewBp.route("/review/<id>")
|
@ReviewBp.route("/review/<id>")
|
||||||
def get_review(id: str):
|
def get_review(id: str):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import { baseUrl } from "@/api/baseUrl";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||||
import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record";
|
import { ASPECT_VERTICAL_LAYOUT, ASPECT_WIDE_LAYOUT } from "@/types/record";
|
||||||
import { FaImage, FaRegListAlt, FaVideo } from "react-icons/fa";
|
import { FaHistory, FaImage, FaRegListAlt, FaVideo } from "react-icons/fa";
|
||||||
import { FaRotate } from "react-icons/fa6";
|
import { FaRotate } from "react-icons/fa6";
|
||||||
import ObjectLifecycle from "./ObjectLifecycle";
|
import ObjectLifecycle from "./ObjectLifecycle";
|
||||||
import {
|
import {
|
||||||
@ -37,6 +37,14 @@ import {
|
|||||||
MobilePageHeader,
|
MobilePageHeader,
|
||||||
MobilePageTitle,
|
MobilePageTitle,
|
||||||
} from "@/components/mobile/MobilePage";
|
} from "@/components/mobile/MobilePage";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import { ReviewSegment } from "@/types/review";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import Chip from "@/components/indicators/Chip";
|
||||||
|
|
||||||
const SEARCH_TABS = [
|
const SEARCH_TABS = [
|
||||||
"details",
|
"details",
|
||||||
@ -226,10 +234,10 @@ function ObjectDetailsTab({
|
|||||||
|
|
||||||
// data
|
// data
|
||||||
|
|
||||||
const [desc, setDesc] = useState(search?.description);
|
const [desc, setDesc] = useState(search?.data.description);
|
||||||
|
|
||||||
// we have to make sure the current selected search item stays in sync
|
// we have to make sure the current selected search item stays in sync
|
||||||
useEffect(() => setDesc(search?.description), [search]);
|
useEffect(() => setDesc(search?.data.description), [search]);
|
||||||
|
|
||||||
const formattedDate = useFormattedTimestamp(
|
const formattedDate = useFormattedTimestamp(
|
||||||
search?.start_time ?? 0,
|
search?.start_time ?? 0,
|
||||||
@ -279,7 +287,7 @@ function ObjectDetailsTab({
|
|||||||
toast.error("Failed to update the description", {
|
toast.error("Failed to update the description", {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
setDesc(search.description);
|
setDesc(search.data.description);
|
||||||
});
|
});
|
||||||
}, [desc, search]);
|
}, [desc, search]);
|
||||||
|
|
||||||
@ -367,6 +375,11 @@ function VideoTab({ search, config }: VideoTabProps) {
|
|||||||
|
|
||||||
const endTime = useMemo(() => search.end_time ?? Date.now() / 1000, [search]);
|
const endTime = useMemo(() => search.end_time ?? Date.now() / 1000, [search]);
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { data: reviewItem } = useSWR<ReviewSegment>([
|
||||||
|
`review/event/${search.id}`,
|
||||||
|
]);
|
||||||
|
|
||||||
const mainCameraAspect = useMemo(() => {
|
const mainCameraAspect = useMemo(() => {
|
||||||
const camera = config?.cameras?.[search.camera];
|
const camera = config?.cameras?.[search.camera];
|
||||||
|
|
||||||
@ -416,8 +429,9 @@ function VideoTab({ search, config }: VideoTabProps) {
|
|||||||
}, [mainCameraAspect]);
|
}, [mainCameraAspect]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div className="relative flex flex-col">
|
||||||
<div className={`aspect-video ${containerClassName}`}>
|
<div className={`aspect-video ${containerClassName}`}>
|
||||||
{isLoading && (
|
{(isLoading || !reviewItem) && (
|
||||||
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
|
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
|
||||||
)}
|
)}
|
||||||
<div className={videoClassName}>
|
<div className={videoClassName}>
|
||||||
@ -433,5 +447,28 @@ function VideoTab({ search, config }: VideoTabProps) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{!isLoading && (
|
||||||
|
<div className="absolute right-2 top-2 flex items-center">
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger>
|
||||||
|
<Chip
|
||||||
|
className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500"
|
||||||
|
onClick={() => {
|
||||||
|
if (reviewItem?.id) {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
id: reviewItem.id,
|
||||||
|
}).toString();
|
||||||
|
navigate(`/review?${params}`);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FaHistory className="size-4 text-white" />
|
||||||
|
</Chip>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent side="left">View in History</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user