mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-20 15:18:21 +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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenu>
|
<DropdownMenu modal={false}>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" className="h-9 gap-2 font-normal">
|
<Button variant="outline" className="h-9 gap-2 font-normal">
|
||||||
{editingProfile ? (
|
{editingProfile ? (
|
||||||
|
|||||||
@ -1098,6 +1098,7 @@ export default function Settings() {
|
|||||||
async (camera: string, section: string, profile: string) => {
|
async (camera: string, section: string, profile: string) => {
|
||||||
try {
|
try {
|
||||||
await axios.put("config/set", {
|
await axios.put("config/set", {
|
||||||
|
requires_restart: 0,
|
||||||
config_data: {
|
config_data: {
|
||||||
cameras: {
|
cameras: {
|
||||||
[camera]: {
|
[camera]: {
|
||||||
@ -1197,16 +1198,31 @@ export default function Settings() {
|
|||||||
|
|
||||||
if (currentSectionKey === "masksAndZones") {
|
if (currentSectionKey === "masksAndZones") {
|
||||||
try {
|
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", {
|
await axios.put("config/set", {
|
||||||
|
requires_restart: 0,
|
||||||
config_data: {
|
config_data: {
|
||||||
cameras: {
|
cameras: {
|
||||||
[selectedCamera]: {
|
[selectedCamera]: {
|
||||||
profiles: {
|
profiles: {
|
||||||
[profileName]: {
|
[profileName]: deletePayload,
|
||||||
zones: "",
|
|
||||||
motion: { mask: "" },
|
|
||||||
objects: { mask: "", filters: "" },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1229,6 +1245,7 @@ export default function Settings() {
|
|||||||
[
|
[
|
||||||
selectedCamera,
|
selectedCamera,
|
||||||
currentSectionKey,
|
currentSectionKey,
|
||||||
|
config,
|
||||||
handleSelectProfile,
|
handleSelectProfile,
|
||||||
handleDeleteProfileSection,
|
handleDeleteProfileSection,
|
||||||
t,
|
t,
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
import get from "lodash/get";
|
import get from "lodash/get";
|
||||||
import cloneDeep from "lodash/cloneDeep";
|
import cloneDeep from "lodash/cloneDeep";
|
||||||
|
import merge from "lodash/merge";
|
||||||
import unset from "lodash/unset";
|
import unset from "lodash/unset";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import mergeWith from "lodash/mergeWith";
|
import mergeWith from "lodash/mergeWith";
|
||||||
@ -497,9 +498,33 @@ export function prepareSectionSavePayload(opts: {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Compute rawFormData (the current stored value for this section)
|
// 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;
|
let rawSectionValue: unknown;
|
||||||
if (level === "camera" && cameraName) {
|
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 {
|
} else {
|
||||||
rawSectionValue = get(config, sectionPath);
|
rawSectionValue = get(config, sectionPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -171,6 +171,7 @@ export default function ProfilesView({
|
|||||||
|
|
||||||
if (Object.keys(configData).length > 0) {
|
if (Object.keys(configData).length > 0) {
|
||||||
await axios.put("config/set", {
|
await axios.put("config/set", {
|
||||||
|
requires_restart: 0,
|
||||||
config_data: { cameras: configData },
|
config_data: { cameras: configData },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user