mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-19 14:48:22 +03:00
sanitize internal fields
This commit is contained in:
parent
223eb89dc4
commit
f25b69e3eb
@ -7,7 +7,10 @@ import axios from "axios";
|
|||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { ConfigForm } from "../ConfigForm";
|
import { ConfigForm } from "../ConfigForm";
|
||||||
import { useConfigOverride } from "@/hooks/use-config-override";
|
import {
|
||||||
|
useConfigOverride,
|
||||||
|
normalizeConfigValue,
|
||||||
|
} from "@/hooks/use-config-override";
|
||||||
import { useSectionSchema } from "@/hooks/use-config-schema";
|
import { useSectionSchema } from "@/hooks/use-config-schema";
|
||||||
import type { FrigateConfig } from "@/types/frigateConfig";
|
import type { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
@ -20,12 +23,15 @@ import {
|
|||||||
} from "react-icons/lu";
|
} from "react-icons/lu";
|
||||||
import Heading from "@/components/ui/heading";
|
import Heading from "@/components/ui/heading";
|
||||||
import get from "lodash/get";
|
import get from "lodash/get";
|
||||||
|
import unset from "lodash/unset";
|
||||||
|
import cloneDeep from "lodash/cloneDeep";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import {
|
import {
|
||||||
Collapsible,
|
Collapsible,
|
||||||
CollapsibleContent,
|
CollapsibleContent,
|
||||||
CollapsibleTrigger,
|
CollapsibleTrigger,
|
||||||
} from "@/components/ui/collapsible";
|
} from "@/components/ui/collapsible";
|
||||||
|
import { applySchemaDefaults } from "@/lib/config-schema";
|
||||||
|
|
||||||
export interface SectionConfig {
|
export interface SectionConfig {
|
||||||
/** Field ordering within the section */
|
/** Field ordering within the section */
|
||||||
@ -119,7 +125,7 @@ export function createConfigSection({
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Get current form data
|
// Get current form data
|
||||||
const formData = useMemo(() => {
|
const rawFormData = useMemo(() => {
|
||||||
if (!config) return {};
|
if (!config) return {};
|
||||||
|
|
||||||
if (level === "camera" && cameraName) {
|
if (level === "camera" && cameraName) {
|
||||||
@ -129,6 +135,36 @@ export function createConfigSection({
|
|||||||
return get(config, sectionPath) || {};
|
return get(config, sectionPath) || {};
|
||||||
}, [config, level, cameraName]);
|
}, [config, level, cameraName]);
|
||||||
|
|
||||||
|
const sanitizeSectionData = useCallback(
|
||||||
|
(data: Record<string, unknown>) => {
|
||||||
|
const normalized = normalizeConfigValue(data) as Record<
|
||||||
|
string,
|
||||||
|
unknown
|
||||||
|
>;
|
||||||
|
if (
|
||||||
|
!sectionConfig.hiddenFields ||
|
||||||
|
sectionConfig.hiddenFields.length === 0
|
||||||
|
) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleaned = cloneDeep(normalized);
|
||||||
|
sectionConfig.hiddenFields.forEach((path) => {
|
||||||
|
if (!path) return;
|
||||||
|
unset(cleaned, path);
|
||||||
|
});
|
||||||
|
return cleaned;
|
||||||
|
},
|
||||||
|
[sectionConfig.hiddenFields],
|
||||||
|
);
|
||||||
|
|
||||||
|
const formData = useMemo(() => {
|
||||||
|
const baseData = sectionSchema
|
||||||
|
? applySchemaDefaults(sectionSchema, rawFormData)
|
||||||
|
: rawFormData;
|
||||||
|
return sanitizeSectionData(baseData);
|
||||||
|
}, [rawFormData, sectionSchema, sanitizeSectionData]);
|
||||||
|
|
||||||
// Track if there are unsaved changes
|
// Track if there are unsaved changes
|
||||||
const hasChanges = useMemo(() => {
|
const hasChanges = useMemo(() => {
|
||||||
if (!pendingData) return false;
|
if (!pendingData) return false;
|
||||||
@ -136,9 +172,17 @@ export function createConfigSection({
|
|||||||
}, [formData, pendingData]);
|
}, [formData, pendingData]);
|
||||||
|
|
||||||
// Handle form data change
|
// Handle form data change
|
||||||
const handleChange = useCallback((data: Record<string, unknown>) => {
|
const handleChange = useCallback(
|
||||||
setPendingData(data);
|
(data: Record<string, unknown>) => {
|
||||||
}, []);
|
const sanitizedData = sanitizeSectionData(data);
|
||||||
|
if (isEqual(formData, sanitizedData)) {
|
||||||
|
setPendingData(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setPendingData(sanitizedData);
|
||||||
|
},
|
||||||
|
[formData, sanitizeSectionData],
|
||||||
|
);
|
||||||
|
|
||||||
// Handle save button click
|
// Handle save button click
|
||||||
const handleSave = useCallback(async () => {
|
const handleSave = useCallback(async () => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user