mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-13 11:57:36 +03:00
fix profile save diff, masksAndZones delete, and config sync
This commit is contained in:
parent
7925d120ae
commit
3cdb40610f
@ -112,7 +112,7 @@ export function ProfileSectionDropdown({
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenu>
|
||||
<DropdownMenu modal={false}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" className="h-9 gap-2 font-normal">
|
||||
{editingProfile ? (
|
||||
|
||||
@ -1098,6 +1098,7 @@ export default function Settings() {
|
||||
async (camera: string, section: string, profile: string) => {
|
||||
try {
|
||||
await axios.put("config/set", {
|
||||
requires_restart: 0,
|
||||
config_data: {
|
||||
cameras: {
|
||||
[camera]: {
|
||||
@ -1197,16 +1198,31 @@ export default function Settings() {
|
||||
|
||||
if (currentSectionKey === "masksAndZones") {
|
||||
try {
|
||||
const profileData =
|
||||
config?.cameras?.[selectedCamera]?.profiles?.[profileName];
|
||||
if (!profileData) return;
|
||||
|
||||
// Only delete top-level keys that exist in the profile
|
||||
const deletePayload: Record<string, string> = {};
|
||||
if (profileData.zones !== undefined) {
|
||||
deletePayload.zones = "";
|
||||
}
|
||||
if (profileData.motion !== undefined) {
|
||||
deletePayload.motion = "";
|
||||
}
|
||||
if (profileData.objects !== undefined) {
|
||||
deletePayload.objects = "";
|
||||
}
|
||||
|
||||
if (Object.keys(deletePayload).length === 0) return;
|
||||
|
||||
await axios.put("config/set", {
|
||||
requires_restart: 0,
|
||||
config_data: {
|
||||
cameras: {
|
||||
[selectedCamera]: {
|
||||
profiles: {
|
||||
[profileName]: {
|
||||
zones: "",
|
||||
motion: { mask: "" },
|
||||
objects: { mask: "", filters: "" },
|
||||
},
|
||||
[profileName]: deletePayload,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1229,6 +1245,7 @@ export default function Settings() {
|
||||
[
|
||||
selectedCamera,
|
||||
currentSectionKey,
|
||||
config,
|
||||
handleSelectProfile,
|
||||
handleDeleteProfileSection,
|
||||
t,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
|
||||
import get from "lodash/get";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import merge from "lodash/merge";
|
||||
import unset from "lodash/unset";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import mergeWith from "lodash/mergeWith";
|
||||
@ -497,9 +498,33 @@ export function prepareSectionSavePayload(opts: {
|
||||
);
|
||||
|
||||
// Compute rawFormData (the current stored value for this section)
|
||||
// For profiles, merge base camera config with profile overrides (matching
|
||||
// what BaseSection displays in the form) so the diff only contains actual
|
||||
// user changes, not every field from the merged view.
|
||||
let rawSectionValue: unknown;
|
||||
if (level === "camera" && cameraName) {
|
||||
rawSectionValue = get(config.cameras?.[cameraName], sectionPath);
|
||||
if (profileInfo.isProfile) {
|
||||
const baseValue = get(
|
||||
config.cameras?.[cameraName],
|
||||
profileInfo.actualSection,
|
||||
);
|
||||
const profileOverrides = get(config.cameras?.[cameraName], sectionPath);
|
||||
if (
|
||||
profileOverrides &&
|
||||
typeof profileOverrides === "object" &&
|
||||
baseValue &&
|
||||
typeof baseValue === "object"
|
||||
) {
|
||||
rawSectionValue = merge(
|
||||
cloneDeep(baseValue),
|
||||
cloneDeep(profileOverrides),
|
||||
);
|
||||
} else {
|
||||
rawSectionValue = baseValue;
|
||||
}
|
||||
} else {
|
||||
rawSectionValue = get(config.cameras?.[cameraName], sectionPath);
|
||||
}
|
||||
} else {
|
||||
rawSectionValue = get(config, sectionPath);
|
||||
}
|
||||
|
||||
@ -171,6 +171,7 @@ export default function ProfilesView({
|
||||
|
||||
if (Object.keys(configData).length > 0) {
|
||||
await axios.put("config/set", {
|
||||
requires_restart: 0,
|
||||
config_data: { cameras: configData },
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user