import { baseUrl } from "@/api/baseUrl"; import ExportCard from "@/components/card/ExportCard"; import VideoPlayer from "@/components/player/VideoPlayer"; import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Button } from "@/components/ui/button"; import { Calendar } from "@/components/ui/calendar"; import { Card } from "@/components/ui/card"; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { DropdownMenuRadioGroup, DropdownMenuTrigger, DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuRadioItem, } from "@/components/ui/dropdown-menu"; import Heading from "@/components/ui/heading"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Toaster } from "@/components/ui/sonner"; import { FrigateConfig } from "@/types/frigateConfig"; import axios from "axios"; import { format } from "date-fns"; import { useCallback, useState } from "react"; import { DateRange } from "react-day-picker"; import { toast } from "sonner"; import useSWR from "swr"; type ExportItem = { name: string; }; function Export() { const { data: config } = useSWR("config"); const { data: exports, mutate } = useSWR( "exports/", (url: string) => axios({ baseURL: baseUrl, url }).then((res) => res.data), ); // Export States const [camera, setCamera] = useState(); const [playback, setPlayback] = useState(); const currentDate = new Date(); currentDate.setHours(0, 0, 0, 0); const [date, setDate] = useState({ from: currentDate, }); const [startTime, setStartTime] = useState("00:00:00"); const [endTime, setEndTime] = useState("23:59:59"); const [selectedClip, setSelectedClip] = useState(); const [deleteClip, setDeleteClip] = useState(); const onHandleExport = () => { if (!camera) { toast.error("A camera needs to be selected.", { position: "top-center" }); return; } if (!playback) { toast.error("A playback factor needs to be selected.", { position: "top-center", }); return; } if (!date?.from || !startTime || !endTime) { toast.error("A start and end time needs to be selected", { position: "top-center", }); return; } const startDate = new Date(date.from.getTime()); const [startHour, startMin, startSec] = startTime.split(":"); startDate.setHours( parseInt(startHour), parseInt(startMin), parseInt(startSec), 0, ); const start = startDate.getTime() / 1000; const endDate = new Date((date.to || date.from).getTime()); const [endHour, endMin, endSec] = endTime.split(":"); endDate.setHours(parseInt(endHour), parseInt(endMin), parseInt(endSec), 0); const end = endDate.getTime() / 1000; if (end <= start) { toast.error("The end time must be after the start time.", { position: "top-center", }); return; } axios .post(`export/${camera}/start/${start}/end/${end}`, { playback }) .then((response) => { if (response.status == 200) { toast.success( "Successfully started export. View the file in the /exports folder.", { position: "top-center" }, ); } mutate(); }) .catch((error) => { if (error.response?.data?.message) { toast.error( `Failed to start export: ${error.response.data.message}`, { position: "top-center" }, ); } else { toast.error(`Failed to start export: ${error.message}`, { position: "top-center", }); } }); }; const onHandleDelete = useCallback(() => { if (!deleteClip) { return; } axios.delete(`export/${deleteClip}`).then((response) => { if (response.status == 200) { setDeleteClip(undefined); mutate(); } }); }, [deleteClip, mutate]); return (
setDeleteClip(undefined)} > Delete Export Confirm deletion of {deleteClip}. Cancel setSelectedClip(undefined)} > Playback
Select A Camera {Object.keys(config?.cameras || {}).map((item) => ( {item.replaceAll("_", " ")} ))}
Select A Playback Factor Realtime Timelapse
setStartTime(e.target.value)} /> setEndTime(e.target.value)} />
{exports && ( Exports {Object.values(exports).map((item) => ( setSelectedClip(file)} onDelete={(file) => setDeleteClip(file)} /> ))} )}
); } export default Export;