mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-11 14:31:14 +03:00
add to camera management pane
This commit is contained in:
parent
6c5558271a
commit
0e56a1ee1c
@ -15,6 +15,7 @@ import CameraWizardDialog from "@/components/settings/CameraWizardDialog";
|
|||||||
import DeleteCameraDialog from "@/components/overlay/dialog/DeleteCameraDialog";
|
import DeleteCameraDialog from "@/components/overlay/dialog/DeleteCameraDialog";
|
||||||
import {
|
import {
|
||||||
LuCheck,
|
LuCheck,
|
||||||
|
LuCopy,
|
||||||
LuExternalLink,
|
LuExternalLink,
|
||||||
LuGripVertical,
|
LuGripVertical,
|
||||||
LuPencil,
|
LuPencil,
|
||||||
@ -22,6 +23,7 @@ import {
|
|||||||
LuRefreshCcw,
|
LuRefreshCcw,
|
||||||
LuTrash2,
|
LuTrash2,
|
||||||
} from "react-icons/lu";
|
} from "react-icons/lu";
|
||||||
|
import CloneCameraDialog from "@/components/settings/CloneCameraDialog";
|
||||||
import { Reorder, useDragControls } from "framer-motion";
|
import { Reorder, useDragControls } from "framer-motion";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { useDocDomain } from "@/hooks/use-doc-domain";
|
import { useDocDomain } from "@/hooks/use-doc-domain";
|
||||||
@ -88,6 +90,9 @@ export default function CameraManagementView({
|
|||||||
|
|
||||||
const [showWizard, setShowWizard] = useState(false);
|
const [showWizard, setShowWizard] = useState(false);
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
|
const [cloneSourceCamera, setCloneSourceCamera] = useState<string | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
|
||||||
// State for restart dialog when enabling a disabled camera
|
// State for restart dialog when enabling a disabled camera
|
||||||
const [restartDialogOpen, setRestartDialogOpen] = useState(false);
|
const [restartDialogOpen, setRestartDialogOpen] = useState(false);
|
||||||
@ -288,6 +293,7 @@ export default function CameraManagementView({
|
|||||||
onConfigChanged={updateConfig}
|
onConfigChanged={updateConfig}
|
||||||
onDragEnd={handleReorderDragEnd}
|
onDragEnd={handleReorderDragEnd}
|
||||||
setRestartDialogOpen={setRestartDialogOpen}
|
setRestartDialogOpen={setRestartDialogOpen}
|
||||||
|
onClone={setCloneSourceCamera}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Reorder.Group>
|
</Reorder.Group>
|
||||||
@ -307,6 +313,7 @@ export default function CameraManagementView({
|
|||||||
camera={camera}
|
camera={camera}
|
||||||
onConfigChanged={updateConfig}
|
onConfigChanged={updateConfig}
|
||||||
setRestartDialogOpen={setRestartDialogOpen}
|
setRestartDialogOpen={setRestartDialogOpen}
|
||||||
|
onClone={setCloneSourceCamera}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -364,6 +371,11 @@ export default function CameraManagementView({
|
|||||||
onClose={() => setRestartDialogOpen(false)}
|
onClose={() => setRestartDialogOpen(false)}
|
||||||
onRestart={() => sendRestart("restart")}
|
onRestart={() => sendRestart("restart")}
|
||||||
/>
|
/>
|
||||||
|
<CloneCameraDialog
|
||||||
|
open={cloneSourceCamera !== null}
|
||||||
|
onClose={() => setCloneSourceCamera(null)}
|
||||||
|
sourceCamera={cloneSourceCamera ?? ""}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -404,6 +416,7 @@ type ActiveCameraRowProps = {
|
|||||||
onConfigChanged: () => Promise<unknown>;
|
onConfigChanged: () => Promise<unknown>;
|
||||||
onDragEnd: () => void;
|
onDragEnd: () => void;
|
||||||
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
onClone: (camera: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function ActiveCameraRow({
|
function ActiveCameraRow({
|
||||||
@ -411,6 +424,7 @@ function ActiveCameraRow({
|
|||||||
onConfigChanged,
|
onConfigChanged,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
setRestartDialogOpen,
|
setRestartDialogOpen,
|
||||||
|
onClone,
|
||||||
}: ActiveCameraRowProps) {
|
}: ActiveCameraRowProps) {
|
||||||
const { t } = useTranslation(["views/settings"]);
|
const { t } = useTranslation(["views/settings"]);
|
||||||
const controls = useDragControls();
|
const controls = useDragControls();
|
||||||
@ -438,6 +452,22 @@ function ActiveCameraRow({
|
|||||||
cameraName={camera}
|
cameraName={camera}
|
||||||
onConfigChanged={onConfigChanged}
|
onConfigChanged={onConfigChanged}
|
||||||
/>
|
/>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="size-7"
|
||||||
|
aria-label={t("cameraManagement.clone.triggerAriaLabel", {
|
||||||
|
cameraName: camera,
|
||||||
|
})}
|
||||||
|
onClick={() => onClone(camera)}
|
||||||
|
>
|
||||||
|
<LuCopy className="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>{t("cameraManagement.clone.trigger")}</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
<CameraStatusSelect
|
<CameraStatusSelect
|
||||||
cameraName={camera}
|
cameraName={camera}
|
||||||
@ -453,13 +483,17 @@ type DisabledCameraRowProps = {
|
|||||||
camera: string;
|
camera: string;
|
||||||
onConfigChanged: () => Promise<unknown>;
|
onConfigChanged: () => Promise<unknown>;
|
||||||
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
setRestartDialogOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
onClone: (camera: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function DisabledCameraRow({
|
function DisabledCameraRow({
|
||||||
camera,
|
camera,
|
||||||
onConfigChanged,
|
onConfigChanged,
|
||||||
setRestartDialogOpen,
|
setRestartDialogOpen,
|
||||||
|
onClone,
|
||||||
}: DisabledCameraRowProps) {
|
}: DisabledCameraRowProps) {
|
||||||
|
const { t } = useTranslation(["views/settings"]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-row items-center justify-between">
|
<div className="flex flex-row items-center justify-between">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
@ -468,6 +502,22 @@ function DisabledCameraRow({
|
|||||||
cameraName={camera}
|
cameraName={camera}
|
||||||
onConfigChanged={onConfigChanged}
|
onConfigChanged={onConfigChanged}
|
||||||
/>
|
/>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="size-7"
|
||||||
|
aria-label={t("cameraManagement.clone.triggerAriaLabel", {
|
||||||
|
cameraName: camera,
|
||||||
|
})}
|
||||||
|
onClick={() => onClone(camera)}
|
||||||
|
>
|
||||||
|
<LuCopy className="size-3.5" />
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>{t("cameraManagement.clone.trigger")}</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
<CameraStatusSelect
|
<CameraStatusSelect
|
||||||
cameraName={camera}
|
cameraName={camera}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user