fix config saving

This commit is contained in:
Josh Hawkins 2026-02-11 13:35:59 -06:00
parent 093a25e9ac
commit 9c43c73a3b
3 changed files with 33 additions and 9 deletions

View File

@ -57,6 +57,7 @@ import { StatusBarMessagesContext } from "@/context/statusbar-provider";
import {
cameraUpdateTopicMap,
buildOverrides,
buildConfigDataForPath,
sanitizeSectionData as sharedSanitizeSectionData,
requiresRestartForOverrides as sharedRequiresRestartForOverrides,
} from "@/utils/configUtil";
@ -507,12 +508,11 @@ export function ConfigSection({
const needsRestart = requiresRestartForOverrides(sanitizedOverrides);
const configData = buildConfigDataForPath(basePath, sanitizedOverrides);
await axios.put("config/set", {
requires_restart: needsRestart ? 1 : 0,
update_topic: updateTopic,
config_data: {
[basePath]: sanitizedOverrides,
},
config_data: configData,
});
// log save to console for debugging
// eslint-disable-next-line no-console
@ -625,14 +625,12 @@ export function ConfigSection({
? `cameras.${cameraName}.${sectionPath}`
: sectionPath;
const configData = "";
const configData = buildConfigDataForPath(basePath, "");
await axios.put("config/set", {
requires_restart: requiresRestart ? 0 : 1,
update_topic: updateTopic,
config_data: {
[basePath]: configData,
},
config_data: configData,
});
// log reset to console for debugging

View File

@ -83,7 +83,10 @@ import axios from "axios";
import { toast } from "sonner";
import { mutate } from "swr";
import { RJSFSchema } from "@rjsf/utils";
import { prepareSectionSavePayload } from "@/utils/configUtil";
import {
buildConfigDataForPath,
prepareSectionSavePayload,
} from "@/utils/configUtil";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import RestartDialog from "@/components/overlay/dialog/RestartDialog";
import SaveAllPreviewPopover, {
@ -764,10 +767,14 @@ export default function Settings() {
continue;
}
const configData = buildConfigDataForPath(
payload.basePath,
payload.sanitizedOverrides,
);
await axios.put("config/set", {
requires_restart: payload.needsRestart ? 1 : 0,
update_topic: payload.updateTopic,
config_data: { [payload.basePath]: payload.sanitizedOverrides },
config_data: configData,
});
// eslint-disable-next-line no-console

View File

@ -9,6 +9,7 @@ import cloneDeep from "lodash/cloneDeep";
import unset from "lodash/unset";
import isEqual from "lodash/isEqual";
import mergeWith from "lodash/mergeWith";
import set from "lodash/set";
import { isJsonObject } from "@/lib/utils";
import { applySchemaDefaults } from "@/lib/config-schema";
import { normalizeConfigValue } from "@/hooks/use-config-override";
@ -169,6 +170,24 @@ export function sanitizeSectionData(
return cleaned;
}
// ---------------------------------------------------------------------------
// buildConfigDataForPath — convert dotted path to nested config_data payload
// ---------------------------------------------------------------------------
// Converts a dotted path (e.g. "cameras.front_door.detect") and a value into
// a properly nested config_data object (e.g. { cameras: { front_door: { detect: value } } }).
// This ensures the backend's flatten_config_data function can correctly distinguish
// between path separators (dots in the path) and literal dots in keys
// (e.g. "frigate.foo.bar" in logger.logs).
export function buildConfigDataForPath(
path: string,
value: unknown,
): Record<string, unknown> {
const configData: Record<string, unknown> = {};
set(configData, path, value);
return configData;
}
// ---------------------------------------------------------------------------
// requiresRestartForOverrides — determine whether a restart is needed
// ---------------------------------------------------------------------------