Skip to content

Commit 4a0cc11

Browse files
committed
Fix settings form editing issues with isUserEditing state flag
- Added isUserEditing state to track when user is actively editing a form - Prevented form values from being overwritten during editing - Fixed issues in ContentFilterSettings, NestFeederSettings, OllamaSettings, XNostrSettings, WalletSettings, and panel components - Added custom save/reset handlers to manage editing state properly
1 parent b52bff6 commit 4a0cc11

15 files changed

Lines changed: 1772 additions & 142 deletions

src/components/settings/BaseSettingsPanel.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@ interface BaseSettingsPanelProps {
1313
loading: boolean;
1414
error: Error | null;
1515
children: React.ReactNode;
16+
extra?: React.ReactNode;
1617
}
1718

1819
const BaseSettingsPanel: React.FC<BaseSettingsPanelProps> = ({
1920
title,
2021
loading,
2122
error,
2223
children,
24+
extra,
2325
}) => {
2426
return (
25-
<StyledCard title={title}>
27+
<StyledCard
28+
title={title}
29+
extra={extra}
30+
>
2631
{error && (
2732
<Alert
2833
message="Error"

src/components/settings/ContentFilterSettings.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { Form, InputNumber, Switch, Select, Tooltip } from 'antd';
33
import { QuestionCircleOutlined } from '@ant-design/icons';
44
import useGenericSettings from '@app/hooks/useGenericSettings';
@@ -18,10 +18,11 @@ const ContentFilterSettings: React.FC = () => {
1818
} = useGenericSettings('content_filter');
1919

2020
const [form] = Form.useForm();
21+
const [isUserEditing, setIsUserEditing] = useState(false);
2122

22-
// Update form values when settings change
23+
// Update form values when settings change, but only if user isn't actively editing
2324
useEffect(() => {
24-
if (settings) {
25+
if (settings && !isUserEditing) {
2526
console.log('ContentFilterSettings - Received settings:', settings);
2627

2728
// Transform property names to match form field names
@@ -47,13 +48,20 @@ const ContentFilterSettings: React.FC = () => {
4748
console.log('ContentFilterSettings - Form values after set:', form.getFieldsValue());
4849
}, 100);
4950
}
50-
}, [settings, form]);
51+
}, [settings, form, isUserEditing]);
5152

5253
// Handle form value changes
5354
const handleValuesChange = (changedValues: Partial<SettingsGroupType<'content_filter'>>) => {
55+
setIsUserEditing(true); // Mark that user is currently editing
5456
updateSettings(changedValues);
5557
};
5658

59+
// Modified save function to reset the editing flag
60+
const handleSave = async () => {
61+
await saveSettings();
62+
setIsUserEditing(false); // Reset after saving
63+
};
64+
5765
// Available Nostr kind options for full text filtering
5866
const kindOptions = [
5967
{ value: 1, label: 'Kind 1 - Text Notes' },
@@ -68,15 +76,21 @@ const ContentFilterSettings: React.FC = () => {
6876
title="Content Filter Settings"
6977
loading={loading}
7078
error={error}
71-
onSave={saveSettings}
72-
onReset={fetchSettings}
79+
onSave={handleSave}
80+
onReset={() => {
81+
fetchSettings();
82+
setIsUserEditing(false);
83+
}}
7384
>
7485
<Form
7586
form={form}
7687
layout="vertical"
7788
onValuesChange={handleValuesChange}
7889
initialValues={settings || {}}
79-
onFinish={(values) => console.log('Form submitted with values:', values)}
90+
onFinish={(values) => {
91+
console.log('Form submitted with values:', values);
92+
setIsUserEditing(false);
93+
}}
8094
>
8195
<Form.Item
8296
name="content_filter_enabled"

src/components/settings/NestFeederSettings.tsx

Lines changed: 53 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React, { useEffect } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { Form, Input, InputNumber, Switch, Tooltip } from 'antd';
3-
import { QuestionCircleOutlined } from '@ant-design/icons';
3+
import { QuestionCircleOutlined, ApiOutlined } from '@ant-design/icons';
44
import useGenericSettings from '@app/hooks/useGenericSettings';
55
import { SettingsGroupType } from '@app/types/settings.types';
66
import BaseSettingsForm from './BaseSettingsForm';
@@ -16,28 +16,28 @@ const NestFeederSettings: React.FC = () => {
1616
} = useGenericSettings('nest_feeder');
1717

1818
const [form] = Form.useForm();
19+
const [isUserEditing, setIsUserEditing] = useState(false);
1920

20-
// Update form values when settings change
21+
// Update form values when settings change, but only if user isn't actively editing
2122
useEffect(() => {
22-
if (settings) {
23+
if (settings && !isUserEditing) {
2324
console.log('NestFeederSettings - Received settings:', settings);
2425

2526
// Transform property names to match form field names
26-
// The API returns properties without the prefix, but the form expects prefixed names
2727
const settingsObj = settings as Record<string, any>;
2828

2929
const formValues = {
3030
nest_feeder_enabled: settingsObj.enabled,
3131
nest_feeder_url: settingsObj.url,
32-
nest_feeder_timeout: typeof settingsObj.timeout === 'string'
33-
? parseInt(settingsObj.timeout)
34-
: settingsObj.timeout,
35-
nest_feeder_cache_size: typeof settingsObj.cache_size === 'string'
36-
? parseInt(settingsObj.cache_size)
32+
nest_feeder_cache_size: typeof settingsObj.cache_size === 'string'
33+
? parseInt(settingsObj.cache_size)
3734
: settingsObj.cache_size,
38-
nest_feeder_cache_ttl: typeof settingsObj.cache_ttl === 'string'
39-
? parseInt(settingsObj.cache_ttl)
40-
: settingsObj.cache_ttl
35+
nest_feeder_cache_ttl: typeof settingsObj.cache_ttl === 'string'
36+
? parseInt(settingsObj.cache_ttl)
37+
: settingsObj.cache_ttl,
38+
nest_feeder_timeout: typeof settingsObj.timeout === 'string'
39+
? parseInt(settingsObj.timeout)
40+
: settingsObj.timeout,
4141
};
4242

4343
console.log('NestFeederSettings - Transformed form values:', formValues);
@@ -48,27 +48,40 @@ const NestFeederSettings: React.FC = () => {
4848
console.log('NestFeederSettings - Form values after set:', form.getFieldsValue());
4949
}, 100);
5050
}
51-
}, [settings, form]);
51+
}, [settings, form, isUserEditing]);
5252

5353
// Handle form value changes
5454
const handleValuesChange = (changedValues: Partial<SettingsGroupType<'nest_feeder'>>) => {
55+
setIsUserEditing(true); // Mark that user is currently editing
5556
updateSettings(changedValues);
5657
};
5758

59+
// Modified save function to reset the editing flag
60+
const handleSave = async () => {
61+
await saveSettings();
62+
setIsUserEditing(false); // Reset after saving
63+
};
64+
5865
return (
5966
<BaseSettingsForm
6067
title="Nest Feeder Settings"
6168
loading={loading}
6269
error={error}
63-
onSave={saveSettings}
64-
onReset={fetchSettings}
70+
onSave={handleSave}
71+
onReset={() => {
72+
fetchSettings();
73+
setIsUserEditing(false);
74+
}}
6575
>
6676
<Form
6777
form={form}
6878
layout="vertical"
6979
onValuesChange={handleValuesChange}
7080
initialValues={settings || {}}
71-
onFinish={(values) => console.log('Form submitted with values:', values)}
81+
onFinish={(values) => {
82+
console.log('Form submitted with values:', values);
83+
setIsUserEditing(false);
84+
}}
7285
>
7386
<Form.Item
7487
name="nest_feeder_enabled"
@@ -82,68 +95,68 @@ const NestFeederSettings: React.FC = () => {
8295
name="nest_feeder_url"
8396
label={
8497
<span>
85-
Nest Feeder URL&nbsp;
86-
<Tooltip title="URL of the Nest Feeder service">
98+
API Endpoint&nbsp;
99+
<Tooltip title="URL of the Nest Feeder API">
87100
<QuestionCircleOutlined />
88101
</Tooltip>
89102
</span>
90103
}
91-
rules={[
92-
{ required: true, message: 'Please enter the Nest Feeder URL' },
93-
{ type: 'url', message: 'Please enter a valid URL' }
94-
]}
104+
rules={[{ required: true, message: 'Please enter the API endpoint' }]}
95105
>
96-
<Input placeholder="https://nest-feeder.example.com" />
106+
<Input
107+
prefix={<ApiOutlined />}
108+
placeholder="http://localhost:8000/feed"
109+
/>
97110
</Form.Item>
98111

99112
<Form.Item
100-
name="nest_feeder_timeout"
113+
name="nest_feeder_cache_size"
101114
label={
102115
<span>
103-
Timeout (seconds)&nbsp;
104-
<Tooltip title="Maximum time to wait for a response from the Nest Feeder service">
116+
Cache Size&nbsp;
117+
<Tooltip title="Maximum number of entries in the nest feeder cache">
105118
<QuestionCircleOutlined />
106119
</Tooltip>
107120
</span>
108121
}
109122
rules={[
110-
{ required: true, message: 'Please enter a timeout value' },
111-
{ type: 'number', min: 1, message: 'Value must be at least 1' }
123+
{ required: true, message: 'Please enter a cache size' },
124+
{ type: 'number', min: 100, message: 'Value must be at least 100' }
112125
]}
113126
>
114-
<InputNumber min={1} style={{ width: '100%' }} />
127+
<InputNumber min={100} style={{ width: '100%' }} />
115128
</Form.Item>
116129

117130
<Form.Item
118-
name="nest_feeder_cache_size"
131+
name="nest_feeder_cache_ttl"
119132
label={
120133
<span>
121-
Cache Size&nbsp;
122-
<Tooltip title="Maximum number of entries to store in the Nest Feeder cache">
134+
Cache TTL (seconds)&nbsp;
135+
<Tooltip title="Time to live for cache entries in seconds">
123136
<QuestionCircleOutlined />
124137
</Tooltip>
125138
</span>
126139
}
127140
rules={[
128-
{ required: true, message: 'Please enter a cache size' },
129-
{ type: 'number', min: 100, message: 'Value must be at least 100' }
141+
{ required: true, message: 'Please enter a cache TTL' },
142+
{ type: 'number', min: 1, message: 'Value must be at least 1' }
130143
]}
131144
>
132-
<InputNumber min={100} style={{ width: '100%' }} />
145+
<InputNumber min={1} style={{ width: '100%' }} />
133146
</Form.Item>
134147

135148
<Form.Item
136-
name="nest_feeder_cache_ttl"
149+
name="nest_feeder_timeout"
137150
label={
138151
<span>
139-
Cache TTL (seconds)&nbsp;
140-
<Tooltip title="Time to live for cache entries in seconds">
152+
Timeout (seconds)&nbsp;
153+
<Tooltip title="Timeout for API requests">
141154
<QuestionCircleOutlined />
142155
</Tooltip>
143156
</span>
144157
}
145158
rules={[
146-
{ required: true, message: 'Please enter a cache TTL' },
159+
{ required: true, message: 'Please enter a timeout value' },
147160
{ type: 'number', min: 1, message: 'Value must be at least 1' }
148161
]}
149162
>

src/components/settings/OllamaSettings.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useEffect } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { Form, Input, InputNumber, Select, Tooltip } from 'antd';
33
import { QuestionCircleOutlined } from '@ant-design/icons';
44
import useGenericSettings from '@app/hooks/useGenericSettings';
@@ -18,10 +18,11 @@ const OllamaSettings: React.FC = () => {
1818
} = useGenericSettings('ollama');
1919

2020
const [form] = Form.useForm();
21+
const [isUserEditing, setIsUserEditing] = useState(false);
2122

22-
// Update form values when settings change
23+
// Update form values when settings change, but only if user isn't actively editing
2324
useEffect(() => {
24-
if (settings) {
25+
if (settings && !isUserEditing) {
2526
console.log('OllamaSettings - Received settings:', settings);
2627

2728
// Transform property names to match form field names
@@ -44,13 +45,20 @@ const OllamaSettings: React.FC = () => {
4445
console.log('OllamaSettings - Form values after set:', form.getFieldsValue());
4546
}, 100);
4647
}
47-
}, [settings, form]);
48+
}, [settings, form, isUserEditing]);
4849

4950
// Handle form value changes
5051
const handleValuesChange = (changedValues: Partial<SettingsGroupType<'ollama'>>) => {
52+
setIsUserEditing(true); // Mark that user is currently editing
5153
updateSettings(changedValues);
5254
};
5355

56+
// Modified save function to reset the editing flag
57+
const handleSave = async () => {
58+
await saveSettings();
59+
setIsUserEditing(false); // Reset after saving
60+
};
61+
5462
// Common Ollama models
5563
const modelOptions = [
5664
{ value: 'llama2', label: 'Llama 2' },
@@ -74,15 +82,21 @@ const OllamaSettings: React.FC = () => {
7482
title="Ollama Settings"
7583
loading={loading}
7684
error={error}
77-
onSave={saveSettings}
78-
onReset={fetchSettings}
85+
onSave={handleSave}
86+
onReset={() => {
87+
fetchSettings();
88+
setIsUserEditing(false);
89+
}}
7990
>
8091
<Form
8192
form={form}
8293
layout="vertical"
8394
onValuesChange={handleValuesChange}
8495
initialValues={settings || {}}
85-
onFinish={(values) => console.log('Form submitted with values:', values)}
96+
onFinish={(values) => {
97+
console.log('Form submitted with values:', values);
98+
setIsUserEditing(false);
99+
}}
86100
>
87101
<Form.Item
88102
name="ollama_url"

0 commit comments

Comments
 (0)