mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Allow deletion of history items (#9030)
* Allow deletion of history items * Remove type
This commit is contained in:
parent
7bec162353
commit
feb3ee0703
@ -3,7 +3,7 @@ import PreviewThumbnailPlayer from "../player/PreviewThumbnailPlayer";
|
||||
import { Card } from "../ui/card";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import ActivityIndicator from "../ui/activity-indicator";
|
||||
import { LuClock } from "react-icons/lu";
|
||||
import { LuClock, LuTrash } from "react-icons/lu";
|
||||
import { HiOutlineVideoCamera } from "react-icons/hi";
|
||||
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
import {
|
||||
@ -16,6 +16,7 @@ type HistoryCardProps = {
|
||||
relevantPreview?: Preview;
|
||||
shouldAutoPlay: boolean;
|
||||
onClick?: () => void;
|
||||
onDelete?: () => void;
|
||||
};
|
||||
|
||||
export default function HistoryCard({
|
||||
@ -23,6 +24,7 @@ export default function HistoryCard({
|
||||
timeline,
|
||||
shouldAutoPlay,
|
||||
onClick,
|
||||
onDelete,
|
||||
}: HistoryCardProps) {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
@ -43,7 +45,8 @@ export default function HistoryCard({
|
||||
shouldAutoPlay={shouldAutoPlay}
|
||||
/>
|
||||
<div className="p-2">
|
||||
<div className="text-sm flex">
|
||||
<div className="text-sm flex justify-between items-center">
|
||||
<div>
|
||||
<LuClock className="h-5 w-5 mr-2 inline" />
|
||||
{formatUnixTimestampToDateTime(timeline.time, {
|
||||
strftime_fmt:
|
||||
@ -52,7 +55,19 @@ export default function HistoryCard({
|
||||
date_style: "medium",
|
||||
})}
|
||||
</div>
|
||||
<div className="capitalize text-sm flex align-center mt-1">
|
||||
<LuTrash
|
||||
className="w-5 h-5 m-1 cursor-pointer"
|
||||
stroke="#f87171"
|
||||
onClick={(e: Event) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (onDelete) {
|
||||
onDelete();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className="capitalize text-sm flex items-center mt-1">
|
||||
<HiOutlineVideoCamera className="h-5 w-5 mr-2 inline" />
|
||||
{timeline.camera.replaceAll("_", " ")}
|
||||
</div>
|
||||
|
@ -9,6 +9,16 @@ import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
import axios from "axios";
|
||||
import TimelinePlayerCard from "@/components/card/TimelinePlayerCard";
|
||||
import { getHourlyTimelineData } from "@/utils/historyUtil";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
|
||||
const API_LIMIT = 200;
|
||||
|
||||
@ -36,6 +46,7 @@ function History() {
|
||||
|
||||
const {
|
||||
data: timelinePages,
|
||||
mutate: updateHistory,
|
||||
size,
|
||||
setSize,
|
||||
isValidating,
|
||||
@ -86,6 +97,40 @@ function History() {
|
||||
[size, setSize, isValidating, isDone]
|
||||
);
|
||||
|
||||
const [itemsToDelete, setItemsToDelete] = useState<string[] | null>(null);
|
||||
const onDelete = useCallback(
|
||||
async (timeline: Card) => {
|
||||
if (timeline.entries.length > 1) {
|
||||
const uniqueEvents = new Set(
|
||||
timeline.entries.map((entry) => entry.source_id)
|
||||
);
|
||||
setItemsToDelete(new Array(...uniqueEvents));
|
||||
} else {
|
||||
const response = await axios.delete(
|
||||
`events/${timeline.entries[0].source_id}`
|
||||
);
|
||||
if (response.status === 200) {
|
||||
updateHistory();
|
||||
}
|
||||
}
|
||||
},
|
||||
[updateHistory]
|
||||
);
|
||||
const onDeleteMulti = useCallback(async () => {
|
||||
if (!itemsToDelete) {
|
||||
return;
|
||||
}
|
||||
|
||||
const responses = itemsToDelete.map(async (id) => {
|
||||
return axios.delete(`events/${id}`);
|
||||
});
|
||||
|
||||
if ((await responses[0]).status == 200) {
|
||||
updateHistory();
|
||||
setItemsToDelete(null);
|
||||
}
|
||||
}, [itemsToDelete, updateHistory]);
|
||||
|
||||
if (!config || !timelineCards || timelineCards.length == 0) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
@ -94,6 +139,31 @@ function History() {
|
||||
<>
|
||||
<Heading as="h2">Review</Heading>
|
||||
|
||||
<AlertDialog
|
||||
open={itemsToDelete != null}
|
||||
onOpenChange={(_) => setItemsToDelete(null)}
|
||||
>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{`Delete ${itemsToDelete?.length} events?`}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
This will delete all events associated with these objects.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel onClick={() => setItemsToDelete(null)}>
|
||||
Cancel
|
||||
</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
className="bg-red-500"
|
||||
onClick={() => onDeleteMulti()}
|
||||
>
|
||||
Delete
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
|
||||
<TimelinePlayerCard
|
||||
timeline={playback}
|
||||
onDismiss={() => setPlayback(undefined)}
|
||||
@ -167,6 +237,7 @@ function History() {
|
||||
onClick={() => {
|
||||
setPlayback(timeline);
|
||||
}}
|
||||
onDelete={() => onDelete(timeline)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
Loading…
Reference in New Issue
Block a user