mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-11 05:35:25 +03:00
clean up
This commit is contained in:
parent
1ba4502b07
commit
f92de9af2e
@ -28,110 +28,36 @@ import { Link } from "react-router-dom";
|
||||
type MasksAndZoneProps = {
|
||||
selectedCamera: string;
|
||||
selectedZoneMask?: PolygonType[];
|
||||
isEditing: boolean;
|
||||
setIsEditing: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
unsavedChanges: boolean;
|
||||
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export default function MasksAndZones({
|
||||
selectedCamera,
|
||||
selectedZoneMask,
|
||||
isEditing,
|
||||
setIsEditing,
|
||||
unsavedChanges,
|
||||
setUnsavedChanges,
|
||||
}: MasksAndZoneProps) {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const [allPolygons, setAllPolygons] = useState<Polygon[]>([]);
|
||||
const [editingPolygons, setEditingPolygons] = useState<Polygon[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
// const [zoneObjects, setZoneObjects] = useState<ZoneObjects[]>([]);
|
||||
const [activePolygonIndex, setActivePolygonIndex] = useState<
|
||||
number | undefined
|
||||
>(undefined);
|
||||
const [hoveredPolygonIndex, setHoveredPolygonIndex] = useState<number | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
// const polygonTypes = [
|
||||
// "zone",
|
||||
// "motion_mask",
|
||||
// "object_mask",
|
||||
// undefined,
|
||||
// ] as const;
|
||||
|
||||
// type EditPaneType = (typeof polygonTypes)[number];
|
||||
const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined);
|
||||
|
||||
// const cameras = useMemo(() => {
|
||||
// if (!config) {
|
||||
// return [];
|
||||
// }
|
||||
|
||||
// return Object.values(config.cameras)
|
||||
// .filter((conf) => conf.ui.dashboard && conf.enabled)
|
||||
// .sort((aConf, bConf) => aConf.ui.order - bConf.ui.order);
|
||||
// }, [config]);
|
||||
|
||||
const cameraConfig = useMemo(() => {
|
||||
if (config && selectedCamera) {
|
||||
return config.cameras[selectedCamera];
|
||||
}
|
||||
}, [config, selectedCamera]);
|
||||
|
||||
// const saveZoneObjects = useCallback(
|
||||
// (camera: string, zoneName: string, newObjects?: string[]) => {
|
||||
// setZoneObjects((prevZoneObjects) =>
|
||||
// prevZoneObjects.map((zoneObject) => {
|
||||
// if (
|
||||
// zoneObject.camera === camera &&
|
||||
// zoneObject.zoneName === zoneName
|
||||
// ) {
|
||||
// console.log("found", camera, "with", zoneName);
|
||||
// console.log("new objects", newObjects);
|
||||
// console.log("new zoneobject", {
|
||||
// ...zoneObject,
|
||||
// objects: newObjects ?? [],
|
||||
// });
|
||||
// // Replace objects with newObjects if provided
|
||||
// return {
|
||||
// ...zoneObject,
|
||||
// objects: newObjects ?? [],
|
||||
// };
|
||||
// }
|
||||
// return zoneObject; // Keep original object
|
||||
// }),
|
||||
// );
|
||||
// },
|
||||
// [setZoneObjects],
|
||||
// );
|
||||
|
||||
// const saveZoneObjects = useCallback(
|
||||
// (camera: string, zoneName: string, objects?: string[]) => {
|
||||
// setZoneObjects((prevZoneObjects) => {
|
||||
// const updatedZoneObjects = prevZoneObjects.map((zoneObject) => {
|
||||
// if (
|
||||
// zoneObject.camera === camera &&
|
||||
// zoneObject.zoneName === zoneName
|
||||
// ) {
|
||||
// return { ...zoneObject, objects: objects || [] };
|
||||
// }
|
||||
// return zoneObject;
|
||||
// });
|
||||
// return updatedZoneObjects;
|
||||
// });
|
||||
// },
|
||||
// [setZoneObjects],
|
||||
// );
|
||||
|
||||
const [{ width: containerWidth, height: containerHeight }] =
|
||||
useResizeObserver(containerRef);
|
||||
|
||||
// const { width: detectWidth, height: detectHeight } = cameraConfig
|
||||
// ? cameraConfig.detect
|
||||
// : { width: 1, height: 1 };
|
||||
const aspectRatio = useMemo(() => {
|
||||
if (!config) {
|
||||
return undefined;
|
||||
@ -216,7 +142,6 @@ export default function MasksAndZones({
|
||||
{
|
||||
points: [],
|
||||
isFinished: false,
|
||||
// isUnsaved: true,
|
||||
type,
|
||||
typeIndex: 9999,
|
||||
name: "",
|
||||
@ -228,35 +153,27 @@ export default function MasksAndZones({
|
||||
};
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
// console.log("handling cancel");
|
||||
setEditPane(undefined);
|
||||
// console.log("all", allPolygons);
|
||||
// console.log("editing", editingPolygons);
|
||||
// setAllPolygons(allPolygons.filter((poly) => !poly.isUnsaved));
|
||||
setEditingPolygons([...allPolygons]);
|
||||
setActivePolygonIndex(undefined);
|
||||
setHoveredPolygonIndex(null);
|
||||
}, [allPolygons]);
|
||||
|
||||
const handleSave = useCallback(() => {
|
||||
// console.log("handling save");
|
||||
setAllPolygons([...(editingPolygons ?? [])]);
|
||||
|
||||
// setEditPane(undefined);
|
||||
setHoveredPolygonIndex(null);
|
||||
}, [editingPolygons]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(isLoading);
|
||||
console.log("edit pane", editPane);
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
if (!isLoading && editPane !== undefined) {
|
||||
console.log("setting");
|
||||
setActivePolygonIndex(undefined);
|
||||
setEditPane(undefined);
|
||||
}
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isLoading]);
|
||||
|
||||
const handleCopyCoordinates = useCallback(
|
||||
@ -276,8 +193,6 @@ export default function MasksAndZones({
|
||||
[allPolygons, scaledHeight, scaledWidth],
|
||||
);
|
||||
|
||||
// useEffect(() => {}, [editPane]);
|
||||
|
||||
useEffect(() => {
|
||||
if (cameraConfig && containerRef.current && scaledWidth && scaledHeight) {
|
||||
const zones = Object.entries(cameraConfig.zones).map(
|
||||
@ -295,7 +210,6 @@ export default function MasksAndZones({
|
||||
scaledHeight,
|
||||
),
|
||||
isFinished: true,
|
||||
// isUnsaved: false,
|
||||
color: zoneData.color,
|
||||
}),
|
||||
);
|
||||
@ -338,6 +252,7 @@ export default function MasksAndZones({
|
||||
: cameraConfig.objects.mask
|
||||
? [cameraConfig.objects.mask]
|
||||
: [];
|
||||
// TODO: check to see if this is necessary
|
||||
if (
|
||||
cameraConfig.objects.mask !== null &&
|
||||
cameraConfig.objects.mask !== undefined
|
||||
@ -360,28 +275,15 @@ export default function MasksAndZones({
|
||||
}));
|
||||
}
|
||||
|
||||
// if (globalObjectMasks && !Array.isArray(globalObjectMasks)) {
|
||||
// globalObjectMasks = [globalObjectMasks];
|
||||
// }
|
||||
|
||||
console.log("global", globalObjectMasks);
|
||||
|
||||
const globalObjectMasksCount = globalObjectMasks.length;
|
||||
|
||||
console.log("filters", cameraConfig.objects.filters);
|
||||
|
||||
let index = 0;
|
||||
|
||||
objectMasks = Object.entries(cameraConfig.objects.filters)
|
||||
.filter(([_, { mask }]) => mask || Array.isArray(mask))
|
||||
.filter(([, { mask }]) => mask || Array.isArray(mask))
|
||||
.flatMap(([objectName, { mask }]): Polygon[] => {
|
||||
console.log("index", index);
|
||||
console.log("outer", objectName, mask);
|
||||
|
||||
const maskArray = Array.isArray(mask) ? mask : mask ? [mask] : [];
|
||||
|
||||
return maskArray.flatMap((maskItem, subIndex) => {
|
||||
const maskItemString = maskItem;
|
||||
|
||||
const newMask = {
|
||||
type: "object_mask" as PolygonType,
|
||||
typeIndex: subIndex,
|
||||
@ -413,11 +315,6 @@ export default function MasksAndZones({
|
||||
});
|
||||
});
|
||||
|
||||
console.log(Object.entries(cameraConfig.objects.filters));
|
||||
|
||||
console.log("final object masks", objectMasks);
|
||||
|
||||
// console.log("setting all and editing");
|
||||
setAllPolygons([
|
||||
...zones,
|
||||
...motionMasks,
|
||||
@ -430,46 +327,18 @@ export default function MasksAndZones({
|
||||
...globalObjectMasks,
|
||||
...objectMasks,
|
||||
]);
|
||||
|
||||
// setZoneObjects(
|
||||
// Object.entries(cameraConfig.zones).map(([name, zoneData]) => ({
|
||||
// camera: cameraConfig.name,
|
||||
// zoneName: name,
|
||||
// objects: Object.keys(zoneData.filters),
|
||||
// })),
|
||||
// );
|
||||
}
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [cameraConfig, containerRef, scaledHeight, scaledWidth]);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("editing polygons changed:", editingPolygons);
|
||||
// }, [editingPolygons]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editPane === undefined) {
|
||||
setEditingPolygons([...allPolygons]);
|
||||
setIsEditing(false);
|
||||
// console.log("edit pane undefined, all", allPolygons);
|
||||
} else {
|
||||
setIsEditing(true);
|
||||
}
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setEditingPolygons, setIsEditing, allPolygons]);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(
|
||||
// "config zone objects",
|
||||
// Object.entries(cameraConfig.zones).map(([name, zoneData]) => ({
|
||||
// camera: cameraConfig.name,
|
||||
// zoneName: name,
|
||||
// objects: Object.keys(zoneData.filters),
|
||||
// })),
|
||||
// );
|
||||
// console.log("component zone objects", zoneObjects);
|
||||
// }, [zoneObjects]);
|
||||
}, [setEditingPolygons, allPolygons]);
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedCamera) {
|
||||
@ -586,12 +455,10 @@ export default function MasksAndZones({
|
||||
key={index}
|
||||
polygon={polygon}
|
||||
index={index}
|
||||
activePolygonIndex={activePolygonIndex}
|
||||
hoveredPolygonIndex={hoveredPolygonIndex}
|
||||
setHoveredPolygonIndex={setHoveredPolygonIndex}
|
||||
setActivePolygonIndex={setActivePolygonIndex}
|
||||
setEditPane={setEditPane}
|
||||
setAllPolygons={setAllPolygons}
|
||||
handleCopyCoordinates={handleCopyCoordinates}
|
||||
/>
|
||||
))}
|
||||
@ -658,12 +525,10 @@ export default function MasksAndZones({
|
||||
key={index}
|
||||
polygon={polygon}
|
||||
index={index}
|
||||
activePolygonIndex={activePolygonIndex}
|
||||
hoveredPolygonIndex={hoveredPolygonIndex}
|
||||
setHoveredPolygonIndex={setHoveredPolygonIndex}
|
||||
setActivePolygonIndex={setActivePolygonIndex}
|
||||
setEditPane={setEditPane}
|
||||
setAllPolygons={setAllPolygons}
|
||||
handleCopyCoordinates={handleCopyCoordinates}
|
||||
/>
|
||||
))}
|
||||
@ -729,12 +594,10 @@ export default function MasksAndZones({
|
||||
key={index}
|
||||
polygon={polygon}
|
||||
index={index}
|
||||
activePolygonIndex={activePolygonIndex}
|
||||
hoveredPolygonIndex={hoveredPolygonIndex}
|
||||
setHoveredPolygonIndex={setHoveredPolygonIndex}
|
||||
setActivePolygonIndex={setActivePolygonIndex}
|
||||
setEditPane={setEditPane}
|
||||
setAllPolygons={setAllPolygons}
|
||||
handleCopyCoordinates={handleCopyCoordinates}
|
||||
/>
|
||||
))}
|
||||
@ -743,85 +606,6 @@ export default function MasksAndZones({
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* <Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="w-[100px]">Name</TableHead>
|
||||
<TableHead className="max-w-[200px]">Coordinates</TableHead>
|
||||
<TableHead>Edit</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{allPolygons.map((polygon, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell className="font-medium">
|
||||
{polygon.name}
|
||||
</TableCell>
|
||||
<TableCell className="max-w-[200px] text-wrap">
|
||||
<code>
|
||||
{JSON.stringify(
|
||||
interpolatePoints(
|
||||
polygon.points,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
cameraConfig.detect.width,
|
||||
cameraConfig.detect.height,
|
||||
),
|
||||
null,
|
||||
0,
|
||||
)}
|
||||
</code>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div
|
||||
className="cursor-pointer"
|
||||
onClick={() => setActivePolygonIndex(index)}
|
||||
>
|
||||
<LuPencil className="size-4 text-white" />
|
||||
</div>
|
||||
<ZoneObjectSelector
|
||||
camera={polygon.camera}
|
||||
zoneName={polygon.name}
|
||||
allLabels={allLabels}
|
||||
updateLabelFilter={(objects) =>
|
||||
saveZoneObjects(polygon.camera, polygon.name, objects)
|
||||
}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div>
|
||||
scaled width: {scaledWidth}, scaled height: {scaledHeight},
|
||||
container width: {containerWidth}, container height:
|
||||
{containerHeight}
|
||||
</div>
|
||||
<ZoneControls
|
||||
camera={cameraConfig.name}
|
||||
polygons={allPolygons}
|
||||
setPolygons={setAllPolygons}
|
||||
activePolygonIndex={activePolygonIndex}
|
||||
setActivePolygonIndex={setActivePolygonIndex}
|
||||
/>
|
||||
<div className="flex flex-col justify-center items-center m-auto w-[30%] bg-secondary">
|
||||
<pre style={{ whiteSpace: "pre-wrap" }}>
|
||||
{JSON.stringify(
|
||||
allPolygons &&
|
||||
allPolygons.map((polygon) =>
|
||||
interpolatePoints(
|
||||
polygon.points,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
1,
|
||||
1,
|
||||
),
|
||||
),
|
||||
null,
|
||||
0,
|
||||
)}
|
||||
</pre>
|
||||
</div> */}
|
||||
</div>
|
||||
<div
|
||||
ref={containerRef}
|
||||
|
||||
@ -92,13 +92,6 @@ export default function MotionMaskEditPane({
|
||||
if (!scaledWidth || !scaledHeight || !polygon || !cameraConfig) {
|
||||
return;
|
||||
}
|
||||
// console.log("loitering time", loitering_time);
|
||||
// const alertsZones = config?.cameras[camera]?.review.alerts.required_zones;
|
||||
|
||||
// const detectionsZones =
|
||||
// config?.cameras[camera]?.review.detections.required_zones;
|
||||
|
||||
// console.log("out of try except", mutatedConfig);
|
||||
|
||||
const coordinates = flattenPoints(
|
||||
interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
@ -110,14 +103,11 @@ export default function MotionMaskEditPane({
|
||||
? 1
|
||||
: 0;
|
||||
|
||||
console.log("are we an array?", Array.isArray(cameraConfig.motion.mask));
|
||||
console.log("index", index);
|
||||
const editingMask = polygon.name.length > 0;
|
||||
|
||||
// editing existing mask, not creating a new one
|
||||
if (editingMask) {
|
||||
index = polygon.typeIndex;
|
||||
console.log("editing, index", index);
|
||||
}
|
||||
|
||||
const filteredMask = (
|
||||
@ -125,15 +115,8 @@ export default function MotionMaskEditPane({
|
||||
? cameraConfig.motion.mask
|
||||
: [cameraConfig.motion.mask]
|
||||
).filter((_, currentIndex) => currentIndex !== index);
|
||||
console.log("filtered", filteredMask);
|
||||
|
||||
// if (editingMask) {
|
||||
// if (index != null) {
|
||||
|
||||
// }
|
||||
// }
|
||||
filteredMask.splice(index, 0, coordinates);
|
||||
console.log("filtered after splice", filteredMask);
|
||||
|
||||
const queryString = filteredMask
|
||||
.map((pointsArray) => {
|
||||
@ -144,16 +127,6 @@ export default function MotionMaskEditPane({
|
||||
})
|
||||
.join("");
|
||||
|
||||
console.log("polygon", polygon);
|
||||
console.log(queryString);
|
||||
|
||||
// console.log(
|
||||
// `config/set?cameras.${polygon?.camera}.motion.mask=${coordinates}&${queryString}`,
|
||||
// );
|
||||
console.log("motion masks", cameraConfig.motion.mask);
|
||||
console.log("new coords", coordinates);
|
||||
// return;
|
||||
|
||||
axios
|
||||
.put(`config/set?${queryString}`, {
|
||||
requires_restart: 0,
|
||||
@ -163,7 +136,6 @@ export default function MotionMaskEditPane({
|
||||
toast.success(`${polygon.name || "Motion Mask"} has been saved.`, {
|
||||
position: "top-center",
|
||||
});
|
||||
// setChangedValue(false);
|
||||
updateConfig();
|
||||
} else {
|
||||
toast.error(`Failed to save config changes: ${res.statusText}`, {
|
||||
@ -180,23 +152,20 @@ export default function MotionMaskEditPane({
|
||||
.finally(() => {
|
||||
setIsLoading(false);
|
||||
});
|
||||
}, [updateConfig, polygon, scaledWidth, scaledHeight, setIsLoading]);
|
||||
}, [
|
||||
updateConfig,
|
||||
polygon,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
setIsLoading,
|
||||
cameraConfig,
|
||||
]);
|
||||
|
||||
function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
if (activePolygonIndex === undefined || !values || !polygons) {
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
// polygons[activePolygonIndex].name = values.name;
|
||||
// console.log("form values", values);
|
||||
// console.log(
|
||||
// "string",
|
||||
|
||||
// flattenPoints(
|
||||
// interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
// ).join(","),
|
||||
// );
|
||||
// console.log("active polygon", polygons[activePolygonIndex]);
|
||||
|
||||
saveToConfig();
|
||||
if (onSave) {
|
||||
|
||||
@ -33,6 +33,7 @@ import { LuExternalLink } from "react-icons/lu";
|
||||
|
||||
type MotionTunerProps = {
|
||||
selectedCamera: string;
|
||||
setUnsavedChanges: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
type MotionSettings = {
|
||||
@ -41,7 +42,10 @@ type MotionSettings = {
|
||||
improve_contrast?: boolean;
|
||||
};
|
||||
|
||||
export default function MotionTuner({ selectedCamera }: MotionTunerProps) {
|
||||
export default function MotionTuner({
|
||||
selectedCamera,
|
||||
setUnsavedChanges,
|
||||
}: MotionTunerProps) {
|
||||
const { data: config, mutate: updateConfig } =
|
||||
useSWR<FrigateConfig>("config");
|
||||
const [changedValue, setChangedValue] = useState(false);
|
||||
|
||||
@ -63,17 +63,6 @@ export default function ObjectMaskEditPane({
|
||||
}: ObjectMaskEditPaneProps) {
|
||||
const { data: config, mutate: updateConfig } =
|
||||
useSWR<FrigateConfig>("config");
|
||||
// const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
// const cameras = useMemo(() => {
|
||||
// if (!config) {
|
||||
// return [];
|
||||
// }
|
||||
|
||||
// return Object.values(config.cameras)
|
||||
// .filter((conf) => conf.ui.dashboard && conf.enabled)
|
||||
// .sort((aConf, bConf) => aConf.ui.order - bConf.ui.order);
|
||||
// }, [config]);
|
||||
|
||||
const polygon = useMemo(() => {
|
||||
if (polygons && activePolygonIndex !== undefined) {
|
||||
@ -129,22 +118,10 @@ export default function ObjectMaskEditPane({
|
||||
const saveToConfig = useCallback(
|
||||
async (
|
||||
{ objects: form_objects }: ObjectMaskFormValuesType, // values submitted via the form
|
||||
objects: string[],
|
||||
) => {
|
||||
if (!scaledWidth || !scaledHeight || !polygon || !cameraConfig) {
|
||||
return;
|
||||
}
|
||||
// console.log("loitering time", loitering_time);
|
||||
// const alertsZones = config?.cameras[camera]?.review.alerts.required_zones;
|
||||
|
||||
// const detectionsZones =
|
||||
// config?.cameras[camera]?.review.detections.required_zones;
|
||||
|
||||
// console.log("out of try except", mutatedConfig);
|
||||
|
||||
console.log("form objects:", form_objects);
|
||||
console.log("objects:", objects);
|
||||
console.log(cameraConfig.objects.filters);
|
||||
|
||||
const coordinates = flattenPoints(
|
||||
interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
@ -183,9 +160,6 @@ export default function ObjectMaskEditPane({
|
||||
index = polygon.typeIndex;
|
||||
}
|
||||
|
||||
console.log("are we an array?", Array.isArray(configObject));
|
||||
console.log("index", index);
|
||||
|
||||
// editing existing mask, not creating a new one
|
||||
if (editingMask) {
|
||||
index = polygon.typeIndex;
|
||||
@ -195,10 +169,7 @@ export default function ObjectMaskEditPane({
|
||||
Array.isArray(configObject) ? configObject : [configObject as string]
|
||||
).filter((_, currentIndex) => currentIndex !== index);
|
||||
|
||||
console.log("filtered", filteredMask);
|
||||
|
||||
filteredMask.splice(index, 0, coordinates);
|
||||
console.log("filtered after splice", filteredMask);
|
||||
}
|
||||
|
||||
queryString = filteredMask
|
||||
@ -212,18 +183,7 @@ export default function ObjectMaskEditPane({
|
||||
})
|
||||
.join("");
|
||||
|
||||
console.log("polygon", polygon);
|
||||
console.log(queryString);
|
||||
|
||||
// console.log(
|
||||
// `config/set?cameras.${polygon?.camera}.objects.mask=${coordinates}&${queryString}`,
|
||||
// );
|
||||
// console.log("object masks", cameraConfig.objects.mask);
|
||||
// console.log("new coords", coordinates);
|
||||
// return;
|
||||
|
||||
if (!queryString) {
|
||||
console.log("no query string");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -236,7 +196,6 @@ export default function ObjectMaskEditPane({
|
||||
toast.success(`${polygon.name || "Object Mask"} has been saved.`, {
|
||||
position: "top-center",
|
||||
});
|
||||
// setChangedValue(false);
|
||||
updateConfig();
|
||||
} else {
|
||||
toast.error(`Failed to save config changes: ${res.statusText}`, {
|
||||
@ -254,7 +213,14 @@ export default function ObjectMaskEditPane({
|
||||
setIsLoading(false);
|
||||
});
|
||||
},
|
||||
[updateConfig, polygon, scaledWidth, scaledHeight, setIsLoading],
|
||||
[
|
||||
updateConfig,
|
||||
polygon,
|
||||
scaledWidth,
|
||||
scaledHeight,
|
||||
setIsLoading,
|
||||
cameraConfig,
|
||||
],
|
||||
);
|
||||
|
||||
function onSubmit(values: z.infer<typeof formSchema>) {
|
||||
@ -262,21 +228,8 @@ export default function ObjectMaskEditPane({
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
// polygons[activePolygonIndex].name = values.name;
|
||||
// console.log("form values", values);
|
||||
// console.log(
|
||||
// "string",
|
||||
|
||||
// flattenPoints(
|
||||
// interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
// ).join(","),
|
||||
// );
|
||||
// console.log("active polygon", polygons[activePolygonIndex]);
|
||||
|
||||
saveToConfig(
|
||||
values as ObjectMaskFormValuesType,
|
||||
polygons[activePolygonIndex].objects,
|
||||
);
|
||||
saveToConfig(values as ObjectMaskFormValuesType);
|
||||
if (onSave) {
|
||||
onSave();
|
||||
}
|
||||
|
||||
31
web/src/components/settings/ObjectSettings.tsx
Normal file
31
web/src/components/settings/ObjectSettings.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { useMemo } from "react";
|
||||
import DebugCameraImage from "../camera/DebugCameraImage";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import useSWR from "swr";
|
||||
import ActivityIndicator from "../indicators/activity-indicator";
|
||||
|
||||
type ObjectSettingsProps = {
|
||||
selectedCamera?: string;
|
||||
};
|
||||
|
||||
export default function ObjectSettings({
|
||||
selectedCamera,
|
||||
}: ObjectSettingsProps) {
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
const cameraConfig = useMemo(() => {
|
||||
if (config && selectedCamera) {
|
||||
return config.cameras[selectedCamera];
|
||||
}
|
||||
}, [config, selectedCamera]);
|
||||
|
||||
if (!cameraConfig) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-50">
|
||||
<DebugCameraImage cameraConfig={cameraConfig} className="size-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -1,11 +1,11 @@
|
||||
import React, { useMemo, useRef, useState, useEffect } from "react";
|
||||
import PolygonDrawer from "./PolygonDrawer";
|
||||
import { Stage, Layer, Image, Text, Circle } from "react-konva";
|
||||
import { Stage, Layer, Image } from "react-konva";
|
||||
import Konva from "konva";
|
||||
import type { KonvaEventObject } from "konva/lib/Node";
|
||||
import { Polygon, PolygonType } from "@/types/canvas";
|
||||
import { useApiHost } from "@/api";
|
||||
import { getAveragePoint, flattenPoints } from "@/utils/canvasUtil";
|
||||
import { flattenPoints } from "@/utils/canvasUtil";
|
||||
|
||||
type PolygonCanvasProps = {
|
||||
camera: string;
|
||||
@ -203,7 +203,6 @@ export function PolygonCanvas({
|
||||
(polygon, index) =>
|
||||
(selectedZoneMask === undefined ||
|
||||
selectedZoneMask.includes(polygon.type)) && (
|
||||
<React.Fragment key={index}>
|
||||
<PolygonDrawer
|
||||
key={index}
|
||||
points={polygon.points}
|
||||
@ -212,45 +211,11 @@ export function PolygonCanvas({
|
||||
isHovered={index === hoveredPolygonIndex}
|
||||
isFinished={polygon.isFinished}
|
||||
color={polygon.color}
|
||||
name={polygon.name}
|
||||
handlePointDragMove={handlePointDragMove}
|
||||
handleGroupDragEnd={handleGroupDragEnd}
|
||||
handleMouseOverStartPoint={handleMouseOverStartPoint}
|
||||
handleMouseOutStartPoint={handleMouseOutStartPoint}
|
||||
/>
|
||||
{index === hoveredPolygonIndex && (
|
||||
<>
|
||||
<Circle
|
||||
x={
|
||||
getAveragePoint(flattenPoints(polygon.points)).x //-
|
||||
//(polygon.name.length * 16 * 0.6) / 2
|
||||
}
|
||||
y={
|
||||
getAveragePoint(flattenPoints(polygon.points)).y //-
|
||||
//16 / 2
|
||||
}
|
||||
radius={2}
|
||||
fill="red"
|
||||
/>
|
||||
<Text
|
||||
text={polygon.name}
|
||||
// align="left"
|
||||
// verticalAlign="top"
|
||||
align="center"
|
||||
verticalAlign="middle"
|
||||
x={
|
||||
getAveragePoint(flattenPoints(polygon.points)).x //-
|
||||
//(polygon.name.length * 16 * 0.6) / 2
|
||||
}
|
||||
y={
|
||||
getAveragePoint(flattenPoints(polygon.points)).y //-
|
||||
//16 / 2
|
||||
}
|
||||
fontSize={16}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</React.Fragment>
|
||||
),
|
||||
)}
|
||||
</Layer>
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { Line, Circle, Group, Text } from "react-konva";
|
||||
import {
|
||||
minMax,
|
||||
toRGBColorString,
|
||||
dragBoundFunc,
|
||||
getAveragePoint,
|
||||
} from "@/utils/canvasUtil";
|
||||
import { Line, Circle, Group } from "react-konva";
|
||||
import { minMax, toRGBColorString, dragBoundFunc } from "@/utils/canvasUtil";
|
||||
import type { KonvaEventObject } from "konva/lib/Node";
|
||||
import Konva from "konva";
|
||||
import { Vector2d } from "konva/lib/types";
|
||||
@ -17,7 +12,6 @@ type PolygonDrawerProps = {
|
||||
isHovered: boolean;
|
||||
isFinished: boolean;
|
||||
color: number[];
|
||||
name: string;
|
||||
handlePointDragMove: (e: KonvaEventObject<MouseEvent | TouchEvent>) => void;
|
||||
handleGroupDragEnd: (e: KonvaEventObject<MouseEvent | TouchEvent>) => void;
|
||||
handleMouseOverStartPoint: (
|
||||
@ -34,7 +28,6 @@ export default function PolygonDrawer({
|
||||
isActive,
|
||||
isHovered,
|
||||
isFinished,
|
||||
name,
|
||||
color,
|
||||
handlePointDragMove,
|
||||
handleGroupDragEnd,
|
||||
@ -93,8 +86,6 @@ export default function PolygonDrawer({
|
||||
[color],
|
||||
);
|
||||
|
||||
// console.log(groupRef.current?.height());
|
||||
|
||||
return (
|
||||
<Group
|
||||
name="polygon"
|
||||
@ -157,26 +148,6 @@ export default function PolygonDrawer({
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{groupRef.current && (
|
||||
<Text
|
||||
text={name}
|
||||
// align="left"
|
||||
// verticalAlign="top"
|
||||
width={groupRef.current.width()}
|
||||
height={groupRef.current.height()}
|
||||
align="center"
|
||||
verticalAlign="middle"
|
||||
x={
|
||||
getAveragePoint(flattenedPoints).x //-
|
||||
//(polygon.name.length * 16 * 0.6) / 2
|
||||
}
|
||||
y={
|
||||
getAveragePoint(flattenedPoints).y //-
|
||||
//16 / 2
|
||||
}
|
||||
fontSize={16}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@ -36,9 +36,7 @@ import { reviewQueries } from "@/utils/zoneEdutUtil";
|
||||
|
||||
type PolygonItemProps = {
|
||||
polygon: Polygon;
|
||||
setAllPolygons: React.Dispatch<React.SetStateAction<Polygon[]>>;
|
||||
index: number;
|
||||
activePolygonIndex: number | undefined;
|
||||
hoveredPolygonIndex: number | null;
|
||||
setHoveredPolygonIndex: (index: number | null) => void;
|
||||
setActivePolygonIndex: (index: number | undefined) => void;
|
||||
@ -48,9 +46,7 @@ type PolygonItemProps = {
|
||||
|
||||
export default function PolygonItem({
|
||||
polygon,
|
||||
setAllPolygons,
|
||||
index,
|
||||
activePolygonIndex,
|
||||
hoveredPolygonIndex,
|
||||
setHoveredPolygonIndex,
|
||||
setActivePolygonIndex,
|
||||
@ -60,6 +56,7 @@ export default function PolygonItem({
|
||||
const { data: config, mutate: updateConfig } =
|
||||
useSWR<FrigateConfig>("config");
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const cameraConfig = useMemo(() => {
|
||||
if (polygon?.camera && config) {
|
||||
@ -93,14 +90,11 @@ export default function PolygonItem({
|
||||
url = `cameras.${polygon.camera}.zones.${polygon.name}${alertQueries}${detectionQueries}`;
|
||||
}
|
||||
if (polygon.type == "motion_mask") {
|
||||
console.log("deleting", polygon.typeIndex);
|
||||
|
||||
const filteredMask = (
|
||||
Array.isArray(cameraConfig.motion.mask)
|
||||
? cameraConfig.motion.mask
|
||||
: [cameraConfig.motion.mask]
|
||||
).filter((_, currentIndex) => currentIndex !== polygon.typeIndex);
|
||||
console.log(filteredMask);
|
||||
|
||||
url = filteredMask
|
||||
.map((pointsArray) => {
|
||||
@ -115,21 +109,14 @@ export default function PolygonItem({
|
||||
// deleting last mask
|
||||
url = `cameras.${polygon?.camera}.motion.mask&`;
|
||||
}
|
||||
console.log(url);
|
||||
|
||||
// return;
|
||||
// url = `config/set?cameras.${polygon.camera}.motion.mask`;
|
||||
}
|
||||
|
||||
if (polygon.type == "object_mask") {
|
||||
console.log("deleting", polygon.typeIndex, polygon);
|
||||
let configObject;
|
||||
let globalMask = false;
|
||||
console.log("polygon objects", polygon.objects, !polygon.objects);
|
||||
|
||||
// global mask on camera for all objects
|
||||
if (!polygon.objects.length) {
|
||||
console.log("deleting global");
|
||||
configObject = cameraConfig.objects.mask;
|
||||
globalMask = true;
|
||||
} else {
|
||||
@ -152,28 +139,13 @@ export default function PolygonItem({
|
||||
Array.isArray(configObject) ? configObject : [configObject]
|
||||
).filter((_, currentIndex) => currentIndex !== polygon.typeIndex);
|
||||
} else {
|
||||
console.log("not globals config object:", configObject);
|
||||
|
||||
filteredMask = (
|
||||
Array.isArray(configObject) ? configObject : [configObject]
|
||||
)
|
||||
.filter((mask) => !globalObjectMasksArray.includes(mask))
|
||||
.filter((_, currentIndex) => {
|
||||
console.log(
|
||||
"current index",
|
||||
currentIndex,
|
||||
"global length:",
|
||||
globalObjectMasksArray.length,
|
||||
"polygon typeindex",
|
||||
polygon.typeIndex,
|
||||
);
|
||||
|
||||
return currentIndex !== polygon.typeIndex;
|
||||
});
|
||||
.filter((_, currentIndex) => currentIndex !== polygon.typeIndex);
|
||||
}
|
||||
|
||||
console.log("filtered:", filteredMask);
|
||||
|
||||
url = filteredMask
|
||||
.map((pointsArray) => {
|
||||
const coordinates = flattenPoints(
|
||||
@ -191,13 +163,10 @@ export default function PolygonItem({
|
||||
? `cameras.${polygon?.camera}.objects.mask&`
|
||||
: `cameras.${polygon?.camera}.objects.filters.${polygon.objects[0]}.mask`;
|
||||
}
|
||||
|
||||
console.log("url:", url);
|
||||
|
||||
// return;
|
||||
// url = `config/set?cameras.${polygon.camera}.motion.mask`;
|
||||
}
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
await axios
|
||||
.put(`config/set?${url}`, { requires_restart: 0 })
|
||||
.then((res) => {
|
||||
@ -205,7 +174,6 @@ export default function PolygonItem({
|
||||
toast.success(`${polygon?.name} has been deleted.`, {
|
||||
position: "top-center",
|
||||
});
|
||||
// setChangedValue(false);
|
||||
updateConfig();
|
||||
} else {
|
||||
toast.error(`Failed to save config changes: ${res.statusText}`, {
|
||||
@ -220,40 +188,13 @@ export default function PolygonItem({
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
// setIsLoading(false);
|
||||
setIsLoading(false);
|
||||
});
|
||||
},
|
||||
[updateConfig, cameraConfig],
|
||||
);
|
||||
|
||||
const reindexPolygons = (arr: Polygon[]): Polygon[] => {
|
||||
const typeCounters: { [type: string]: number } = {};
|
||||
|
||||
return arr.map((obj) => {
|
||||
if (!typeCounters[obj.type]) {
|
||||
typeCounters[obj.type] = 0;
|
||||
}
|
||||
|
||||
const newObj: Polygon = {
|
||||
...obj,
|
||||
typeIndex: typeCounters[obj.type],
|
||||
};
|
||||
typeCounters[obj.type]++;
|
||||
return newObj;
|
||||
});
|
||||
};
|
||||
|
||||
const handleDelete = (type: string, typeIndex: number) => {
|
||||
// setAllPolygons((oldPolygons) => {
|
||||
// console.log("old polygons", oldPolygons);
|
||||
// const filteredPolygons = oldPolygons.filter(
|
||||
// (polygon) =>
|
||||
// !(polygon.type === type && polygon.typeIndex === typeIndex),
|
||||
// );
|
||||
// console.log("filtered", filteredPolygons);
|
||||
// // console.log("reindexed", reindexPolygons(filteredPolygons));
|
||||
// return filteredPolygons;
|
||||
// });
|
||||
const handleDelete = () => {
|
||||
setActivePolygonIndex(undefined);
|
||||
saveToConfig(polygon);
|
||||
};
|
||||
@ -307,9 +248,7 @@ export default function PolygonItem({
|
||||
</AlertDialogDescription>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={() => handleDelete(polygon.type, polygon.typeIndex)}
|
||||
>
|
||||
<AlertDialogAction onClick={handleDelete}>
|
||||
Delete
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
@ -334,7 +273,10 @@ export default function PolygonItem({
|
||||
<DropdownMenuItem onClick={() => handleCopyCoordinates(index)}>
|
||||
Copy
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setDeleteDialogOpen(true)}>
|
||||
<DropdownMenuItem
|
||||
disabled={isLoading}
|
||||
onClick={() => setDeleteDialogOpen(true)}
|
||||
>
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
@ -378,7 +320,7 @@ export default function PolygonItem({
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer size-[15px]"
|
||||
onClick={() => setDeleteDialogOpen(true)}
|
||||
onClick={() => !isLoading && setDeleteDialogOpen(true)}
|
||||
>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
|
||||
@ -156,33 +156,6 @@ export default function ZoneEditPane({
|
||||
},
|
||||
});
|
||||
|
||||
// const [changedValue, setChangedValue] = useState(false);
|
||||
|
||||
// const requiredDetectionZones = useMemo(
|
||||
// () => cameraConfig?.review.detections.required_zones,
|
||||
// [cameraConfig],
|
||||
// );
|
||||
|
||||
// const requiredAlertZones = useMemo(
|
||||
// () => cameraConfig?.review.alerts.required_zones,
|
||||
// [cameraConfig],
|
||||
// );
|
||||
|
||||
// const [alertQueries, setAlertQueries] = useState("");
|
||||
// const [detectionQueries, setDetectionQueries] = useState("");
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("config updated!", config);
|
||||
// }, [config]);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("camera config updated!", cameraConfig);
|
||||
// }, [cameraConfig]);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log("required zones updated!", requiredZones);
|
||||
// }, [requiredZones]);
|
||||
|
||||
const saveToConfig = useCallback(
|
||||
async (
|
||||
{
|
||||
@ -198,11 +171,6 @@ export default function ZoneEditPane({
|
||||
if (!scaledWidth || !scaledHeight || !polygon) {
|
||||
return;
|
||||
}
|
||||
// console.log("loitering time", loitering_time);
|
||||
// const alertsZones = config?.cameras[camera]?.review.alerts.required_zones;
|
||||
|
||||
// const detectionsZones =
|
||||
// config?.cameras[camera]?.review.detections.required_zones;
|
||||
let mutatedConfig = config;
|
||||
|
||||
const renamingZone = zoneName != polygon.name && polygon.name != "";
|
||||
@ -231,8 +199,6 @@ export default function ZoneEditPane({
|
||||
|
||||
// Wait for the config to be updated
|
||||
mutatedConfig = await updateConfig();
|
||||
// console.log("this should be updated...", mutatedConfig.cameras);
|
||||
// console.log("check original config object...", config);
|
||||
} catch (error) {
|
||||
toast.error(`Failed to save config changes.`, {
|
||||
position: "top-center",
|
||||
@ -241,12 +207,9 @@ export default function ZoneEditPane({
|
||||
}
|
||||
}
|
||||
|
||||
// console.log("out of try except", mutatedConfig);
|
||||
|
||||
const coordinates = flattenPoints(
|
||||
interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
).join(",");
|
||||
// const foo = config.cameras["doorbell"].zones["outside"].objects;
|
||||
|
||||
let objectQueries = objects
|
||||
.map(
|
||||
@ -263,7 +226,6 @@ export default function ZoneEditPane({
|
||||
|
||||
// deleting objects
|
||||
if (!objectQueries && !same_objects && !renamingZone) {
|
||||
// console.log("deleting objects");
|
||||
objectQueries = `&cameras.${polygon?.camera}.zones.${zoneName}.objects`;
|
||||
}
|
||||
|
||||
@ -278,14 +240,6 @@ export default function ZoneEditPane({
|
||||
.required_zones || [],
|
||||
);
|
||||
|
||||
// console.log("object queries:", objectQueries);
|
||||
// console.log("alert queries:", alertQueries);
|
||||
// console.log("detection queries:", detectionQueries);
|
||||
|
||||
// console.log(
|
||||
// `config/set?cameras.${polygon?.camera}.zones.${name}.coordinates=${coordinates}&cameras.${polygon?.camera}.zones.${name}.inertia=${inertia}&cameras.${polygon?.camera}.zones.${name}.loitering_time=${loitering_time}${objectQueries}${alertQueries}${detectionQueries}`,
|
||||
// );
|
||||
|
||||
axios
|
||||
.put(
|
||||
`config/set?cameras.${polygon?.camera}.zones.${zoneName}.coordinates=${coordinates}&cameras.${polygon?.camera}.zones.${zoneName}.inertia=${inertia}&cameras.${polygon?.camera}.zones.${zoneName}.loitering_time=${loitering_time}${objectQueries}${alertQueries}${detectionQueries}`,
|
||||
@ -296,7 +250,6 @@ export default function ZoneEditPane({
|
||||
toast.success(`Zone (${zoneName}) has been saved.`, {
|
||||
position: "top-center",
|
||||
});
|
||||
// setChangedValue(false);
|
||||
updateConfig();
|
||||
} else {
|
||||
toast.error(`Failed to save config changes: ${res.statusText}`, {
|
||||
@ -330,16 +283,6 @@ export default function ZoneEditPane({
|
||||
return;
|
||||
}
|
||||
setIsLoading(true);
|
||||
// polygons[activePolygonIndex].name = values.name;
|
||||
// console.log("form values", values);
|
||||
// console.log(
|
||||
// "string",
|
||||
|
||||
// flattenPoints(
|
||||
// interpolatePoints(polygon.points, scaledWidth, scaledHeight, 1, 1),
|
||||
// ).join(","),
|
||||
// );
|
||||
// console.log("active polygon", polygons[activePolygonIndex]);
|
||||
|
||||
saveToConfig(
|
||||
values as ZoneFormValuesType,
|
||||
|
||||
@ -5,7 +5,6 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
// import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
|
||||
import MotionTuner from "@/components/settings/MotionTuner";
|
||||
@ -13,7 +12,6 @@ import MasksAndZones from "@/components/settings/MasksAndZones";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import useOptimisticState from "@/hooks/use-optimistic-state";
|
||||
import Logo from "@/components/Logo";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { FaVideo } from "react-icons/fa";
|
||||
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig";
|
||||
@ -22,6 +20,7 @@ import General from "@/components/settings/General";
|
||||
import FilterSwitch from "@/components/filter/FilterSwitch";
|
||||
import { ZoneMaskFilterButton } from "@/components/filter/ZoneMaskFilter";
|
||||
import { PolygonType } from "@/types/canvas";
|
||||
import ObjectSettings from "@/components/settings/ObjectSettings";
|
||||
|
||||
export default function Settings() {
|
||||
const settingsViews = [
|
||||
@ -37,7 +36,7 @@ export default function Settings() {
|
||||
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
// TODO: confirm leave page
|
||||
const [unsavedChanges, setUnsavedChanges] = useState(false);
|
||||
|
||||
const cameras = useMemo(() => {
|
||||
@ -50,7 +49,7 @@ export default function Settings() {
|
||||
.sort((aConf, bConf) => aConf.ui.order - bConf.ui.order);
|
||||
}, [config]);
|
||||
|
||||
const [selectedCamera, setSelectedCamera] = useState<string>();
|
||||
const [selectedCamera, setSelectedCamera] = useState<string>("");
|
||||
|
||||
const [filterZoneMask, setFilterZoneMask] = useState<PolygonType[]>();
|
||||
|
||||
@ -58,6 +57,8 @@ export default function Settings() {
|
||||
if (cameras.length) {
|
||||
setSelectedCamera(cameras[0].name);
|
||||
}
|
||||
// only run once
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
return (
|
||||
@ -77,7 +78,7 @@ export default function Settings() {
|
||||
{Object.values(settingsViews).map((item) => (
|
||||
<ToggleGroupItem
|
||||
key={item}
|
||||
className={`flex items-center justify-between gap-2 ${pageToggle == item ? "" : "*:text-gray-500"}`}
|
||||
className={`flex items-center justify-between gap-2 ${pageToggle == item ? "" : "*:text-muted-foreground"}`}
|
||||
value={item}
|
||||
aria-label={`Select ${item}`}
|
||||
>
|
||||
@ -105,19 +106,21 @@ export default function Settings() {
|
||||
</div>
|
||||
<div className="mt-2 flex flex-col items-start w-full h-full md:h-dvh md:pb-24">
|
||||
{page == "general" && <General />}
|
||||
{page == "objects" && <></>}
|
||||
{page == "objects" && (
|
||||
<ObjectSettings selectedCamera={selectedCamera} />
|
||||
)}
|
||||
{page == "masks / zones" && (
|
||||
<MasksAndZones
|
||||
selectedCamera={selectedCamera}
|
||||
selectedZoneMask={filterZoneMask}
|
||||
isEditing={isEditing}
|
||||
setIsEditing={setIsEditing}
|
||||
unsavedChanges={unsavedChanges}
|
||||
setUnsavedChanges={setUnsavedChanges}
|
||||
/>
|
||||
)}
|
||||
{page == "motion tuner" && (
|
||||
<MotionTuner selectedCamera={selectedCamera} />
|
||||
<MotionTuner
|
||||
selectedCamera={selectedCamera}
|
||||
setUnsavedChanges={setUnsavedChanges}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -10,24 +10,9 @@ export const reviewQueries = (
|
||||
let detectionQueries = "";
|
||||
let same_alerts = false;
|
||||
let same_detections = false;
|
||||
// const foo = config;
|
||||
|
||||
// console.log("config in func", config.cameras);
|
||||
// console.log("config as foo in func", foo.cameras);
|
||||
// console.log("cameraconfig in func", cameraConfig);
|
||||
// console.log("required zones in func", requiredZones);
|
||||
// console.log("name", name);
|
||||
// console.log("alerts", alertsZones);
|
||||
// console.log("detections", detectionsZones);
|
||||
// console.log(
|
||||
// "orig detections",
|
||||
// foo?.cameras[camera]?.review.detections.required_zones,
|
||||
// );
|
||||
|
||||
const alerts = new Set<string>(alertsZones || []);
|
||||
// config?.cameras[camera].review.alerts.required_zones.forEach((zone) => {
|
||||
// alerts.add(zone);
|
||||
// });
|
||||
|
||||
if (review_alerts) {
|
||||
alerts.add(name);
|
||||
} else {
|
||||
@ -40,9 +25,6 @@ export const reviewQueries = (
|
||||
.join("");
|
||||
|
||||
const detections = new Set<string>(detectionsZones || []);
|
||||
// config?.cameras[camera].review.detections.required_zones.forEach((zone) => {
|
||||
// detections.add(zone);
|
||||
// });
|
||||
|
||||
if (review_detections) {
|
||||
detections.add(name);
|
||||
@ -57,36 +39,10 @@ export const reviewQueries = (
|
||||
)
|
||||
.join("");
|
||||
|
||||
// console.log("dets set", detections);
|
||||
|
||||
// const updatedConfig = updateConfig({
|
||||
// ...config,
|
||||
// cameras: {
|
||||
// ...config.cameras,
|
||||
// [camera]: {
|
||||
// ...config.cameras[camera],
|
||||
// review: {
|
||||
// ...config.cameras[camera].review,
|
||||
// detection: {
|
||||
// ...config.cameras[camera].review.detection,
|
||||
// required_zones: [...detections],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
// console.log(updatedConfig);
|
||||
|
||||
// console.log("alert queries", alertQueries);
|
||||
// console.log("detection queries", detectionQueries);
|
||||
|
||||
if (!alertQueries && !same_alerts) {
|
||||
// console.log("deleting alerts");
|
||||
alertQueries = `&cameras.${camera}.review.alerts`;
|
||||
}
|
||||
if (!detectionQueries && !same_detections) {
|
||||
// console.log("deleting detection");
|
||||
detectionQueries = `&cameras.${camera}.review.detections`;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user