Allow deletion of history items (#9030)

* Allow deletion of history items

* Remove type
This commit is contained in:
Nicolas Mowen 2023-12-20 17:38:06 -07:00 committed by Blake Blackshear
parent 7bec162353
commit feb3ee0703
2 changed files with 96 additions and 10 deletions

View File

@ -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,16 +45,29 @@ export default function HistoryCard({
shouldAutoPlay={shouldAutoPlay}
/>
<div className="p-2">
<div className="text-sm flex">
<LuClock className="h-5 w-5 mr-2 inline" />
{formatUnixTimestampToDateTime(timeline.time, {
strftime_fmt:
config.ui.time_format == "24hour" ? "%H:%M:%S" : "%I:%M:%S %p",
time_style: "medium",
date_style: "medium",
})}
<div className="text-sm flex justify-between items-center">
<div>
<LuClock className="h-5 w-5 mr-2 inline" />
{formatUnixTimestampToDateTime(timeline.time, {
strftime_fmt:
config.ui.time_format == "24hour" ? "%H:%M:%S" : "%I:%M:%S %p",
time_style: "medium",
date_style: "medium",
})}
</div>
<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 align-center mt-1">
<div className="capitalize text-sm flex items-center mt-1">
<HiOutlineVideoCamera className="h-5 w-5 mr-2 inline" />
{timeline.camera.replaceAll("_", " ")}
</div>

View File

@ -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)}
/>
);
})}