mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-15 15:45:27 +03:00
actions component in search footer thumbnail
This commit is contained in:
parent
403296fbec
commit
2a8a1a1b1b
@ -1,38 +1,10 @@
|
|||||||
import { useCallback, useState } from "react";
|
|
||||||
import TimeAgo from "../dynamic/TimeAgo";
|
import TimeAgo from "../dynamic/TimeAgo";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
|
|
||||||
import ActivityIndicator from "../indicators/activity-indicator";
|
|
||||||
import { SearchResult } from "@/types/search";
|
import { SearchResult } from "@/types/search";
|
||||||
import {
|
import ActivityIndicator from "../indicators/activity-indicator";
|
||||||
DropdownMenu,
|
import SearchResultActions from "../menu/SearchResultActions";
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/components/ui/dropdown-menu";
|
|
||||||
import {
|
|
||||||
AlertDialog,
|
|
||||||
AlertDialogAction,
|
|
||||||
AlertDialogCancel,
|
|
||||||
AlertDialogContent,
|
|
||||||
AlertDialogDescription,
|
|
||||||
AlertDialogFooter,
|
|
||||||
AlertDialogHeader,
|
|
||||||
AlertDialogTitle,
|
|
||||||
} from "../ui/alert-dialog";
|
|
||||||
import { LuCamera, LuDownload, LuMoreVertical, LuTrash2 } from "react-icons/lu";
|
|
||||||
import FrigatePlusIcon from "@/components/icons/FrigatePlusIcon";
|
|
||||||
import { FrigatePlusDialog } from "../overlay/dialog/FrigatePlusDialog";
|
|
||||||
import { Event } from "@/types/event";
|
|
||||||
import { FaArrowsRotate } from "react-icons/fa6";
|
|
||||||
import { baseUrl } from "@/api/baseUrl";
|
|
||||||
import axios from "axios";
|
|
||||||
import { toast } from "sonner";
|
|
||||||
import { MdImageSearch } from "react-icons/md";
|
|
||||||
import { isMobileOnly } from "react-device-detect";
|
|
||||||
import { buttonVariants } from "../ui/button";
|
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
type SearchThumbnailProps = {
|
type SearchThumbnailProps = {
|
||||||
@ -52,31 +24,7 @@ export default function SearchThumbnailFooter({
|
|||||||
}: SearchThumbnailProps) {
|
}: SearchThumbnailProps) {
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
|
||||||
// interactions
|
|
||||||
|
|
||||||
const [showFrigatePlus, setShowFrigatePlus] = useState(false);
|
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
|
||||||
axios
|
|
||||||
.delete(`events/${searchResult.id}`)
|
|
||||||
.then((resp) => {
|
|
||||||
if (resp.status == 200) {
|
|
||||||
toast.success("Tracked object deleted successfully.", {
|
|
||||||
position: "top-center",
|
|
||||||
});
|
|
||||||
refreshResults();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
toast.error("Failed to delete tracked object.", {
|
|
||||||
position: "top-center",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, [searchResult, refreshResults]);
|
|
||||||
|
|
||||||
// date
|
// date
|
||||||
|
|
||||||
const formattedDate = useFormattedTimestamp(
|
const formattedDate = useFormattedTimestamp(
|
||||||
searchResult.start_time,
|
searchResult.start_time,
|
||||||
config?.ui.time_format == "24hour" ? "%b %-d, %H:%M" : "%b %-d, %I:%M %p",
|
config?.ui.time_format == "24hour" ? "%b %-d, %H:%M" : "%b %-d, %I:%M %p",
|
||||||
@ -84,39 +32,6 @@ export default function SearchThumbnailFooter({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<AlertDialog
|
|
||||||
open={deleteDialogOpen}
|
|
||||||
onOpenChange={() => setDeleteDialogOpen(!deleteDialogOpen)}
|
|
||||||
>
|
|
||||||
<AlertDialogContent>
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>Confirm Delete</AlertDialogTitle>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
Are you sure you want to delete this tracked object?
|
|
||||||
</AlertDialogDescription>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
||||||
<AlertDialogAction
|
|
||||||
className={buttonVariants({ variant: "destructive" })}
|
|
||||||
onClick={handleDelete}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
|
||||||
</AlertDialogContent>
|
|
||||||
</AlertDialog>
|
|
||||||
<FrigatePlusDialog
|
|
||||||
upload={
|
|
||||||
showFrigatePlus ? (searchResult as unknown as Event) : undefined
|
|
||||||
}
|
|
||||||
onClose={() => setShowFrigatePlus(false)}
|
|
||||||
onEventUploaded={() => {
|
|
||||||
searchResult.plus_id = "submitted";
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full flex-row items-center justify-between",
|
"flex w-full flex-row items-center justify-between",
|
||||||
@ -135,95 +50,13 @@ export default function SearchThumbnailFooter({
|
|||||||
{formattedDate}
|
{formattedDate}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center justify-end gap-6 md:gap-4">
|
<div className="flex flex-row items-center justify-end gap-6 md:gap-4">
|
||||||
{!isMobileOnly &&
|
<SearchResultActions
|
||||||
config?.plus?.enabled &&
|
searchResult={searchResult}
|
||||||
searchResult.has_snapshot &&
|
findSimilar={findSimilar}
|
||||||
searchResult.end_time &&
|
refreshResults={refreshResults}
|
||||||
!searchResult.plus_id && (
|
showObjectLifecycle={showObjectLifecycle}
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<FrigatePlusIcon
|
|
||||||
className="size-5 cursor-pointer text-primary-variant hover:text-primary"
|
|
||||||
onClick={() => setShowFrigatePlus(true)}
|
|
||||||
/>
|
/>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Submit to Frigate+</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{config?.semantic_search?.enabled && (
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger>
|
|
||||||
<MdImageSearch
|
|
||||||
className="size-5 cursor-pointer text-primary-variant hover:text-primary"
|
|
||||||
onClick={findSimilar}
|
|
||||||
/>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>Find similar</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger>
|
|
||||||
<LuMoreVertical className="size-5 cursor-pointer text-primary-variant hover:text-primary" />
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align={"end"}>
|
|
||||||
{searchResult.has_clip && (
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<a
|
|
||||||
className="justify_start flex items-center"
|
|
||||||
href={`${baseUrl}api/events/${searchResult.id}/clip.mp4`}
|
|
||||||
download={`${searchResult.camera}_${searchResult.label}.mp4`}
|
|
||||||
>
|
|
||||||
<LuDownload className="mr-2 size-4" />
|
|
||||||
<span>Download video</span>
|
|
||||||
</a>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
{searchResult.has_snapshot && (
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<a
|
|
||||||
className="justify_start flex items-center"
|
|
||||||
href={`${baseUrl}api/events/${searchResult.id}/snapshot.jpg`}
|
|
||||||
download={`${searchResult.camera}_${searchResult.label}.jpg`}
|
|
||||||
>
|
|
||||||
<LuCamera className="mr-2 size-4" />
|
|
||||||
<span>Download snapshot</span>
|
|
||||||
</a>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={showObjectLifecycle}
|
|
||||||
>
|
|
||||||
<FaArrowsRotate className="mr-2 size-4" />
|
|
||||||
<span>View object lifecycle</span>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
|
|
||||||
{isMobileOnly &&
|
|
||||||
config?.plus?.enabled &&
|
|
||||||
searchResult.has_snapshot &&
|
|
||||||
searchResult.end_time &&
|
|
||||||
!searchResult.plus_id && (
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => setShowFrigatePlus(true)}
|
|
||||||
>
|
|
||||||
<FrigatePlusIcon className="mr-2 size-4 cursor-pointer text-primary" />
|
|
||||||
<span>Submit to Frigate+</span>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="cursor-pointer"
|
|
||||||
onClick={() => setDeleteDialogOpen(true)}
|
|
||||||
>
|
|
||||||
<LuTrash2 className="mr-2 size-4" />
|
|
||||||
<span>Delete</span>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user