Skip to content

Commit db3c406

Browse files
rcourtmanclaude
andcommitted
fix: resolve undefined property access error in settings modal
- Add safe default structure for configuration properties - Ensure currentConfig never remains undefined/null - Always render form even if config loading fails - Replace unsafe property access with safe variable references - Prevent "Cannot read properties of undefined (reading 'host')" errors 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent d26f4b6 commit db3c406

File tree

1 file changed

+32
-21
lines changed

1 file changed

+32
-21
lines changed

src/public/js/ui/settings.js

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,14 @@ PulseApp.ui.settings = (() => {
7272
// Load current configuration
7373
try {
7474
await loadCurrentConfig();
75-
renderConfigurationForm();
7675
} catch (error) {
7776
console.error('[Settings] Failed to load configuration:', error);
78-
body.innerHTML = `<div class="text-red-600 dark:text-red-400">Failed to load configuration: ${error.message}</div>`;
77+
// Initialize with empty config to prevent errors
78+
currentConfig = {};
7979
}
80+
81+
// Always render the form, even if config loading failed
82+
renderConfigurationForm();
8083
}
8184

8285
function closeModal() {
@@ -96,7 +99,8 @@ PulseApp.ui.settings = (() => {
9699
throw new Error(`HTTP ${response.status}`);
97100
}
98101

99-
currentConfig = await response.json();
102+
const configData = await response.json();
103+
currentConfig = configData || {}; // Ensure we never have null/undefined
100104
console.log('[Settings] Current config loaded:', currentConfig);
101105

102106
} catch (error) {
@@ -109,6 +113,13 @@ PulseApp.ui.settings = (() => {
109113
const body = document.getElementById('settings-modal-body');
110114
if (!body) return;
111115

116+
// Ensure currentConfig has a safe default structure
117+
const safeConfig = currentConfig || {};
118+
const proxmox = safeConfig.proxmox || {};
119+
const pbs = safeConfig.pbs || {};
120+
const advanced = safeConfig.advanced || {};
121+
const alerts = advanced.alerts || {};
122+
112123
const html = `
113124
<form id="settings-form" class="space-y-6">
114125
<!-- Proxmox VE Primary Endpoint -->
@@ -120,14 +131,14 @@ PulseApp.ui.settings = (() => {
120131
Host Address <span class="text-red-500">*</span>
121132
</label>
122133
<input type="text" name="PROXMOX_HOST" required
123-
value="${currentConfig.proxmox?.host || ''}"
134+
value="${proxmox.host || ''}"
124135
placeholder="https://proxmox.example.com:8006"
125136
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
126137
</div>
127138
<div>
128139
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Port</label>
129140
<input type="number" name="PROXMOX_PORT"
130-
value="${currentConfig.proxmox?.port || ''}"
141+
value="${proxmox.port || ''}"
131142
placeholder="8006"
132143
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
133144
</div>
@@ -136,7 +147,7 @@ PulseApp.ui.settings = (() => {
136147
Node Name
137148
</label>
138149
<input type="text" name="PROXMOX_NODE_NAME"
139-
value="${currentConfig.proxmox?.nodeName || ''}"
150+
value="${proxmox.nodeName || ''}"
140151
placeholder="Display name (optional)"
141152
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
142153
</div>
@@ -145,7 +156,7 @@ PulseApp.ui.settings = (() => {
145156
API Token ID <span class="text-red-500">*</span>
146157
</label>
147158
<input type="text" name="PROXMOX_TOKEN_ID" required
148-
value="${currentConfig.proxmox?.tokenId || ''}"
159+
value="${proxmox.tokenId || ''}"
149160
placeholder="root@pam!token-name"
150161
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
151162
</div>
@@ -159,7 +170,7 @@ PulseApp.ui.settings = (() => {
159170
</div>
160171
<div>
161172
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Enabled</label>
162-
<input type="checkbox" name="PROXMOX_ENABLED" ${currentConfig.proxmox?.enabled !== false ? 'checked' : ''}
173+
<input type="checkbox" name="PROXMOX_ENABLED" ${proxmox.enabled !== false ? 'checked' : ''}
163174
class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
164175
</div>
165176
</div>
@@ -184,14 +195,14 @@ PulseApp.ui.settings = (() => {
184195
<div>
185196
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Host Address</label>
186197
<input type="text" name="PBS_HOST"
187-
value="${currentConfig.pbs?.host || ''}"
198+
value="${pbs.host || ''}"
188199
placeholder="https://pbs.example.com:8007"
189200
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
190201
</div>
191202
<div>
192203
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Port</label>
193204
<input type="number" name="PBS_PORT"
194-
value="${currentConfig.pbs?.port || ''}"
205+
value="${pbs.port || ''}"
195206
placeholder="8007"
196207
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
197208
</div>
@@ -200,14 +211,14 @@ PulseApp.ui.settings = (() => {
200211
Node Name
201212
</label>
202213
<input type="text" name="PBS_NODE_NAME"
203-
value="${currentConfig.pbs?.nodeName || ''}"
214+
value="${pbs.nodeName || ''}"
204215
placeholder="PBS internal hostname"
205216
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
206217
</div>
207218
<div>
208219
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">API Token ID</label>
209220
<input type="text" name="PBS_TOKEN_ID"
210-
value="${currentConfig.pbs?.tokenId || ''}"
221+
value="${pbs.tokenId || ''}"
211222
placeholder="root@pam!token-name"
212223
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
213224
</div>
@@ -241,7 +252,7 @@ PulseApp.ui.settings = (() => {
241252
Metric Update Interval (ms)
242253
</label>
243254
<input type="number" name="PULSE_METRIC_INTERVAL_MS"
244-
value="${currentConfig.advanced?.metricInterval || ''}"
255+
value="${advanced.metricInterval || ''}"
245256
placeholder="2000 (default)"
246257
min="1000" max="60000"
247258
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
@@ -252,7 +263,7 @@ PulseApp.ui.settings = (() => {
252263
Discovery Interval (ms)
253264
</label>
254265
<input type="number" name="PULSE_DISCOVERY_INTERVAL_MS"
255-
value="${currentConfig.advanced?.discoveryInterval || ''}"
266+
value="${advanced.discoveryInterval || ''}"
256267
placeholder="30000 (default)"
257268
min="5000" max="300000"
258269
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
@@ -267,22 +278,22 @@ PulseApp.ui.settings = (() => {
267278
268279
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 mb-4">
269280
<label class="flex items-center">
270-
<input type="checkbox" name="ALERT_CPU_ENABLED" ${currentConfig.advanced?.alerts?.cpu?.enabled !== false ? 'checked' : ''}
281+
<input type="checkbox" name="ALERT_CPU_ENABLED" ${alerts.cpu?.enabled !== false ? 'checked' : ''}
271282
class="mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
272283
<span class="text-sm text-gray-700 dark:text-gray-300">CPU Alerts</span>
273284
</label>
274285
<label class="flex items-center">
275-
<input type="checkbox" name="ALERT_MEMORY_ENABLED" ${currentConfig.advanced?.alerts?.memory?.enabled !== false ? 'checked' : ''}
286+
<input type="checkbox" name="ALERT_MEMORY_ENABLED" ${alerts.memory?.enabled !== false ? 'checked' : ''}
276287
class="mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
277288
<span class="text-sm text-gray-700 dark:text-gray-300">Memory Alerts</span>
278289
</label>
279290
<label class="flex items-center">
280-
<input type="checkbox" name="ALERT_DISK_ENABLED" ${currentConfig.advanced?.alerts?.disk?.enabled !== false ? 'checked' : ''}
291+
<input type="checkbox" name="ALERT_DISK_ENABLED" ${alerts.disk?.enabled !== false ? 'checked' : ''}
281292
class="mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
282293
<span class="text-sm text-gray-700 dark:text-gray-300">Disk Alerts</span>
283294
</label>
284295
<label class="flex items-center">
285-
<input type="checkbox" name="ALERT_DOWN_ENABLED" ${currentConfig.advanced?.alerts?.down?.enabled !== false ? 'checked' : ''}
296+
<input type="checkbox" name="ALERT_DOWN_ENABLED" ${alerts.down?.enabled !== false ? 'checked' : ''}
286297
class="mr-2 h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
287298
<span class="text-sm text-gray-700 dark:text-gray-300">Down Alerts</span>
288299
</label>
@@ -294,7 +305,7 @@ PulseApp.ui.settings = (() => {
294305
CPU Threshold (%)
295306
</label>
296307
<input type="number" name="ALERT_CPU_THRESHOLD"
297-
value="${currentConfig.advanced?.alerts?.cpu?.threshold || ''}"
308+
value="${alerts.cpu?.threshold || ''}"
298309
placeholder="85 (default)"
299310
min="50" max="100"
300311
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
@@ -304,7 +315,7 @@ PulseApp.ui.settings = (() => {
304315
Memory Threshold (%)
305316
</label>
306317
<input type="number" name="ALERT_MEMORY_THRESHOLD"
307-
value="${currentConfig.advanced?.alerts?.memory?.threshold || ''}"
318+
value="${alerts.memory?.threshold || ''}"
308319
placeholder="90 (default)"
309320
min="50" max="100"
310321
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
@@ -314,7 +325,7 @@ PulseApp.ui.settings = (() => {
314325
Disk Threshold (%)
315326
</label>
316327
<input type="number" name="ALERT_DISK_THRESHOLD"
317-
value="${currentConfig.advanced?.alerts?.disk?.threshold || ''}"
328+
value="${alerts.disk?.threshold || ''}"
318329
placeholder="95 (default)"
319330
min="50" max="100"
320331
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">

0 commit comments

Comments
 (0)