mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-01-22 20:18:30 +03:00
Add ability to select case in export dialog
This commit is contained in:
parent
a10ea1f28e
commit
c2952b89c1
@ -48,6 +48,10 @@
|
|||||||
"name": {
|
"name": {
|
||||||
"placeholder": "Name the Export"
|
"placeholder": "Name the Export"
|
||||||
},
|
},
|
||||||
|
"case": {
|
||||||
|
"label": "Case",
|
||||||
|
"placeholder": "Select a case"
|
||||||
|
},
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
"selectOrExport": "Select or Export",
|
"selectOrExport": "Select or Export",
|
||||||
|
|||||||
@ -22,7 +22,14 @@ import useSWR from "swr";
|
|||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
|
||||||
import { TimezoneAwareCalendar } from "./ReviewActivityCalendar";
|
import { TimezoneAwareCalendar } from "./ReviewActivityCalendar";
|
||||||
import { SelectSeparator } from "../ui/select";
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectSeparator,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "../ui/select";
|
||||||
import { isDesktop, isIOS, isMobile } from "react-device-detect";
|
import { isDesktop, isIOS, isMobile } from "react-device-detect";
|
||||||
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
import { Drawer, DrawerContent, DrawerTrigger } from "../ui/drawer";
|
||||||
import SaveExportOverlay from "./SaveExportOverlay";
|
import SaveExportOverlay from "./SaveExportOverlay";
|
||||||
@ -31,6 +38,7 @@ import { baseUrl } from "@/api/baseUrl";
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { GenericVideoPlayer } from "../player/GenericVideoPlayer";
|
import { GenericVideoPlayer } from "../player/GenericVideoPlayer";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { ExportCase } from "@/types/export";
|
||||||
|
|
||||||
const EXPORT_OPTIONS = [
|
const EXPORT_OPTIONS = [
|
||||||
"1",
|
"1",
|
||||||
@ -67,6 +75,9 @@ export default function ExportDialog({
|
|||||||
}: ExportDialogProps) {
|
}: ExportDialogProps) {
|
||||||
const { t } = useTranslation(["components/dialog"]);
|
const { t } = useTranslation(["components/dialog"]);
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
const [selectedCaseId, setSelectedCaseId] = useState<string | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
const onStartExport = useCallback(() => {
|
const onStartExport = useCallback(() => {
|
||||||
if (!range) {
|
if (!range) {
|
||||||
@ -89,6 +100,7 @@ export default function ExportDialog({
|
|||||||
{
|
{
|
||||||
playback: "realtime",
|
playback: "realtime",
|
||||||
name,
|
name,
|
||||||
|
export_case_id: selectedCaseId || undefined,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@ -102,6 +114,7 @@ export default function ExportDialog({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
setName("");
|
setName("");
|
||||||
|
setSelectedCaseId(undefined);
|
||||||
setRange(undefined);
|
setRange(undefined);
|
||||||
setMode("none");
|
setMode("none");
|
||||||
}
|
}
|
||||||
@ -118,10 +131,11 @@ export default function ExportDialog({
|
|||||||
{ position: "top-center" },
|
{ position: "top-center" },
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}, [camera, name, range, setRange, setName, setMode, t]);
|
}, [camera, name, range, selectedCaseId, setRange, setName, setMode, t]);
|
||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
const handleCancel = useCallback(() => {
|
||||||
setName("");
|
setName("");
|
||||||
|
setSelectedCaseId(undefined);
|
||||||
setMode("none");
|
setMode("none");
|
||||||
setRange(undefined);
|
setRange(undefined);
|
||||||
}, [setMode, setRange]);
|
}, [setMode, setRange]);
|
||||||
@ -190,8 +204,10 @@ export default function ExportDialog({
|
|||||||
currentTime={currentTime}
|
currentTime={currentTime}
|
||||||
range={range}
|
range={range}
|
||||||
name={name}
|
name={name}
|
||||||
|
selectedCaseId={selectedCaseId}
|
||||||
onStartExport={onStartExport}
|
onStartExport={onStartExport}
|
||||||
setName={setName}
|
setName={setName}
|
||||||
|
setSelectedCaseId={setSelectedCaseId}
|
||||||
setRange={setRange}
|
setRange={setRange}
|
||||||
setMode={setMode}
|
setMode={setMode}
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
@ -207,8 +223,10 @@ type ExportContentProps = {
|
|||||||
currentTime: number;
|
currentTime: number;
|
||||||
range?: TimeRange;
|
range?: TimeRange;
|
||||||
name: string;
|
name: string;
|
||||||
|
selectedCaseId?: string;
|
||||||
onStartExport: () => void;
|
onStartExport: () => void;
|
||||||
setName: (name: string) => void;
|
setName: (name: string) => void;
|
||||||
|
setSelectedCaseId: (caseId: string | undefined) => void;
|
||||||
setRange: (range: TimeRange | undefined) => void;
|
setRange: (range: TimeRange | undefined) => void;
|
||||||
setMode: (mode: ExportMode) => void;
|
setMode: (mode: ExportMode) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
@ -218,14 +236,17 @@ export function ExportContent({
|
|||||||
currentTime,
|
currentTime,
|
||||||
range,
|
range,
|
||||||
name,
|
name,
|
||||||
|
selectedCaseId,
|
||||||
onStartExport,
|
onStartExport,
|
||||||
setName,
|
setName,
|
||||||
|
setSelectedCaseId,
|
||||||
setRange,
|
setRange,
|
||||||
setMode,
|
setMode,
|
||||||
onCancel,
|
onCancel,
|
||||||
}: ExportContentProps) {
|
}: ExportContentProps) {
|
||||||
const { t } = useTranslation(["components/dialog"]);
|
const { t } = useTranslation(["components/dialog"]);
|
||||||
const [selectedOption, setSelectedOption] = useState<ExportOption>("1");
|
const [selectedOption, setSelectedOption] = useState<ExportOption>("1");
|
||||||
|
const { data: cases } = useSWR<ExportCase[]>("cases");
|
||||||
|
|
||||||
const onSelectTime = useCallback(
|
const onSelectTime = useCallback(
|
||||||
(option: ExportOption) => {
|
(option: ExportOption) => {
|
||||||
@ -320,6 +341,44 @@ export function ExportContent({
|
|||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
<div className="my-4">
|
||||||
|
<Label className="text-sm text-secondary-foreground">
|
||||||
|
{t("export.case.label", { defaultValue: "Case (optional)" })}
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={selectedCaseId || "none"}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
setSelectedCaseId(value === "none" ? undefined : value)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-2">
|
||||||
|
<SelectValue
|
||||||
|
placeholder={t("export.case.placeholder", {
|
||||||
|
defaultValue: "Select a case (optional)",
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem
|
||||||
|
value="none"
|
||||||
|
className="cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
{t("label.none", { ns: "common" })}
|
||||||
|
</SelectItem>
|
||||||
|
{cases
|
||||||
|
?.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
.map((caseItem) => (
|
||||||
|
<SelectItem
|
||||||
|
key={caseItem.id}
|
||||||
|
value={caseItem.id}
|
||||||
|
className="cursor-pointer hover:bg-accent hover:text-accent-foreground"
|
||||||
|
>
|
||||||
|
{caseItem.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
{isDesktop && <SelectSeparator className="my-4 bg-secondary" />}
|
{isDesktop && <SelectSeparator className="my-4 bg-secondary" />}
|
||||||
<DialogFooter
|
<DialogFooter
|
||||||
className={isDesktop ? "" : "mt-3 flex flex-col-reverse gap-4"}
|
className={isDesktop ? "" : "mt-3 flex flex-col-reverse gap-4"}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user