Skip to content

Commit b52bff6

Browse files
committed
Fix settings preservation in advanced settings panels
When updating individual fields in advanced settings panels like image moderation, ensure all other field values are preserved. The fix maintains proper field prefix handling when saving to the backend API.
1 parent e931448 commit b52bff6

2 files changed

Lines changed: 96 additions & 35 deletions

File tree

src/components/settings/panels/ImageModerationPanel.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const ImageModerationPanel: React.FC = () => {
1818
const [form] = Form.useForm();
1919
const [isUserEditing, setIsUserEditing] = useState(false);
2020

21+
// Add initial debug logging
22+
console.log('ImageModerationPanel - Initial settings:', settings);
23+
2124
// Update form values when settings change, but only if user isn't actively editing
2225
useEffect(() => {
2326
if (settings && !isUserEditing) {
@@ -62,6 +65,8 @@ const ImageModerationPanel: React.FC = () => {
6265
// Handle form value changes
6366
const handleValuesChange = (changedValues: Partial<SettingsGroupType<'image_moderation'>>) => {
6467
setIsUserEditing(true); // Mark that user is currently editing
68+
console.log('ImageModerationPanel - changedValues:', changedValues);
69+
console.log('ImageModerationPanel - current form values:', form.getFieldsValue());
6570
updateSettings(changedValues);
6671
};
6772

src/hooks/useGenericSettings.ts

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,43 @@ const useGenericSettings = <T extends SettingsGroupName>(
8080

8181
const updateSettings = useCallback((updatedSettings: Partial<SettingsGroupType<T>>) => {
8282
console.log(`Updating ${groupName} settings:`, updatedSettings);
83-
setSettings(prevSettings => {
84-
if (!prevSettings) {
85-
console.log(`No previous ${groupName} settings, using updated settings as initial`);
86-
return updatedSettings as SettingsGroupType<T>;
87-
}
88-
89-
// No special handling for image_moderation - treat all settings groups the same
90-
const newSettings = { ...prevSettings, ...updatedSettings };
91-
console.log(`New ${groupName} settings after update:`, newSettings);
92-
return newSettings;
93-
});
83+
84+
// For image_moderation, we need to handle prefixed keys properly
85+
if (groupName === 'image_moderation') {
86+
console.log('Handling image_moderation update with prefixed keys');
87+
88+
setSettings(prevSettings => {
89+
if (!prevSettings) {
90+
console.log(`No previous ${groupName} settings, using updated settings as initial`);
91+
return updatedSettings as SettingsGroupType<T>;
92+
}
93+
94+
// Create a deep copy of the previous settings
95+
const prevSettingsCopy = { ...prevSettings };
96+
97+
// Only update the changed fields, preserving all other fields
98+
const newSettings = { ...prevSettingsCopy, ...updatedSettings };
99+
100+
console.log(`Previous settings:`, prevSettingsCopy);
101+
console.log(`Updated fields:`, updatedSettings);
102+
console.log(`Merged settings:`, newSettings);
103+
104+
return newSettings;
105+
});
106+
} else {
107+
// For other settings groups, use the standard approach
108+
setSettings(prevSettings => {
109+
if (!prevSettings) {
110+
console.log(`No previous ${groupName} settings, using updated settings as initial`);
111+
return updatedSettings as SettingsGroupType<T>;
112+
}
113+
114+
// Standard merge of settings
115+
const newSettings = { ...prevSettings, ...updatedSettings };
116+
console.log(`New ${groupName} settings after update:`, newSettings);
117+
return newSettings;
118+
});
119+
}
94120
}, [groupName]);
95121

96122
const saveSettings = useCallback(async () => {
@@ -102,35 +128,65 @@ const useGenericSettings = <T extends SettingsGroupName>(
102128
try {
103129
setLoading(true);
104130
setError(null);
105-
131+
106132
// For image_moderation, we need to transform the prefixed keys back to unprefixed keys
107133
let dataToSave = settings;
108-
134+
109135
if (groupName === 'image_moderation') {
110-
// Map from prefixed to unprefixed keys
111-
const prefixMap: Record<string, string> = {
112-
'image_moderation_api': 'api',
113-
'image_moderation_check_interval': 'check_interval',
114-
'image_moderation_concurrency': 'concurrency',
115-
'image_moderation_enabled': 'enabled',
116-
'image_moderation_mode': 'mode',
117-
'image_moderation_temp_dir': 'temp_dir',
118-
'image_moderation_threshold': 'threshold',
119-
'image_moderation_timeout': 'timeout'
120-
};
121-
122-
// Create a new object with only the unprefixed keys
123-
const unprefixedSettings: Record<string, any> = {};
136+
console.log('Settings from state:', settings);
137+
138+
// First fetch current settings to preserve values not in the form
139+
console.log('Fetching current settings before saving...');
140+
const fetchResponse = await fetch(`${config.baseURL}/api/settings/${groupName}`, {
141+
headers: {
142+
'Authorization': `Bearer ${token}`,
143+
},
144+
});
145+
146+
if (!fetchResponse.ok) {
147+
throw new Error(`Failed to fetch current settings: ${fetchResponse.status}`);
148+
}
149+
150+
const currentData = await fetchResponse.json();
151+
const currentSettings = currentData[groupName] || {};
152+
console.log('Current settings from API:', currentSettings);
153+
154+
// After reviewing the backend code, we see it expects prefixed keys in the payload
155+
// Looking at ImageModerationSettings struct in the backend
156+
const prefixedSettings: Record<string, any> = {};
157+
158+
// Copy all existing prefixed settings from the backend
159+
Object.entries(currentSettings).forEach(([key, value]) => {
160+
const prefixedKey = `image_moderation_${key}`;
161+
prefixedSettings[prefixedKey] = value;
162+
});
163+
164+
// Update with changed values from the form
124165
const settingsObj = settings as Record<string, any>;
125-
126-
// Transform all prefixed keys to unprefixed keys
127-
Object.entries(prefixMap).forEach(([prefixedKey, unprefixedKey]) => {
128-
// Set the value in the unprefixed object, preserving the data type
129-
unprefixedSettings[unprefixedKey] = settingsObj[prefixedKey];
166+
167+
// Keep track of what fields are in the form
168+
const prefixedFormKeys = [
169+
'image_moderation_api',
170+
'image_moderation_check_interval',
171+
'image_moderation_concurrency',
172+
'image_moderation_enabled',
173+
'image_moderation_mode',
174+
'image_moderation_temp_dir',
175+
'image_moderation_threshold',
176+
'image_moderation_timeout'
177+
];
178+
179+
// Log and update each field
180+
prefixedFormKeys.forEach(prefixedKey => {
181+
if (prefixedKey in settingsObj && settingsObj[prefixedKey] !== undefined) {
182+
const unprefixedKey = prefixedKey.replace('image_moderation_', '');
183+
console.log(`Updating field: ${prefixedKey} from ${prefixedSettings[prefixedKey]} to ${settingsObj[prefixedKey]}`);
184+
prefixedSettings[prefixedKey] = settingsObj[prefixedKey];
185+
}
130186
});
131-
132-
console.log(`Transformed settings for backend (unprefixed keys):`, unprefixedSettings);
133-
dataToSave = unprefixedSettings as SettingsGroupType<T>;
187+
188+
console.log(`Final settings with prefixed keys for API:`, prefixedSettings);
189+
dataToSave = prefixedSettings as unknown as SettingsGroupType<T>;
134190
}
135191

136192
console.log(`Saving ${groupName} settings:`, dataToSave);

0 commit comments

Comments
 (0)