@@ -7,6 +7,7 @@ PulseApp.ui.settings = (() => {
7
7
let latestReleaseData = null ; // Store the latest release data
8
8
let updateCache = new Map ( ) ; // Cache update check results to reduce API calls
9
9
let updateCheckTimeout = null ; // Debounce rapid channel changes
10
+ let formDataCache = { } ; // Store form data between tab switches
10
11
11
12
function init ( ) {
12
13
if ( isInitialized ) return ;
@@ -72,6 +73,9 @@ PulseApp.ui.settings = (() => {
72
73
}
73
74
74
75
function switchTab ( tabName ) {
76
+ // Preserve current form data before switching tabs
77
+ preserveCurrentFormData ( ) ;
78
+
75
79
activeTab = tabName ;
76
80
77
81
// Update tab buttons
@@ -92,6 +96,9 @@ PulseApp.ui.settings = (() => {
92
96
93
97
// Update content
94
98
renderTabContent ( ) ;
99
+
100
+ // Restore form data for the new tab
101
+ restoreFormData ( ) ;
95
102
}
96
103
97
104
async function openModal ( ) {
@@ -118,11 +125,17 @@ PulseApp.ui.settings = (() => {
118
125
function closeModal ( ) {
119
126
console . log ( '[Settings] Closing modal...' ) ;
120
127
128
+ // Preserve current form data before closing
129
+ preserveCurrentFormData ( ) ;
130
+
121
131
const modal = document . getElementById ( 'settings-modal' ) ;
122
132
if ( ! modal ) return ;
123
133
124
134
modal . classList . add ( 'hidden' ) ;
125
135
modal . classList . remove ( 'flex' ) ;
136
+
137
+ // Clear form data cache since modal is being closed
138
+ formDataCache = { } ;
126
139
}
127
140
128
141
async function loadConfiguration ( ) {
@@ -177,6 +190,11 @@ PulseApp.ui.settings = (() => {
177
190
178
191
container . innerHTML = `<form id="settings-form" class="space-y-6">${ content } </form>` ;
179
192
193
+ // Restore form data after content is rendered
194
+ setTimeout ( ( ) => {
195
+ restoreFormData ( ) ;
196
+ } , 0 ) ;
197
+
180
198
// Load existing additional endpoints for Proxmox and PBS tabs
181
199
if ( activeTab === 'proxmox' ) {
182
200
loadExistingPveEndpoints ( ) ;
@@ -1326,7 +1344,9 @@ PulseApp.ui.settings = (() => {
1326
1344
saveButton . textContent = 'Saving...' ;
1327
1345
1328
1346
try {
1329
- const config = collectFormData ( ) ;
1347
+ // Preserve current tab data before collecting all data
1348
+ preserveCurrentFormData ( ) ;
1349
+ const config = collectAllTabsData ( ) ;
1330
1350
1331
1351
const response = await fetch ( '/api/config' , {
1332
1352
method : 'POST' ,
@@ -1395,6 +1415,121 @@ PulseApp.ui.settings = (() => {
1395
1415
return config ;
1396
1416
}
1397
1417
1418
+ function collectAllTabsData ( ) {
1419
+ // Start with current form data and add cached data from other tabs
1420
+ const currentFormConfig = collectFormData ( ) ;
1421
+ const allConfig = { ...currentFormConfig } ;
1422
+
1423
+ // Merge data from all cached tabs
1424
+ Object . values ( formDataCache ) . forEach ( tabData => {
1425
+ Object . entries ( tabData ) . forEach ( ( [ name , value ] ) => {
1426
+ // Only use cached value if not already set from current form
1427
+ if ( ! allConfig . hasOwnProperty ( name ) ) {
1428
+ if ( typeof value === 'boolean' ) {
1429
+ allConfig [ name ] = value ? 'true' : 'false' ;
1430
+ } else {
1431
+ allConfig [ name ] = value ;
1432
+ }
1433
+ }
1434
+ } ) ;
1435
+ } ) ;
1436
+
1437
+ console . log ( '[Settings] Collected data from all tabs:' , allConfig ) ;
1438
+ return allConfig ;
1439
+ }
1440
+
1441
+ function preserveCurrentFormData ( ) {
1442
+ const form = document . getElementById ( 'settings-form' ) ;
1443
+ if ( ! form ) return ;
1444
+
1445
+ const formData = new FormData ( form ) ;
1446
+ const currentTabData = { } ;
1447
+
1448
+ // Store all form field values
1449
+ for ( const [ name , value ] of formData . entries ( ) ) {
1450
+ const field = form . querySelector ( `[name="${ name } "]` ) ;
1451
+ if ( field ) {
1452
+ if ( field . type === 'checkbox' ) {
1453
+ currentTabData [ name ] = field . checked ;
1454
+ } else {
1455
+ currentTabData [ name ] = value ;
1456
+ }
1457
+ }
1458
+ }
1459
+
1460
+ // Also store unchecked checkboxes
1461
+ const checkboxes = form . querySelectorAll ( 'input[type="checkbox"]' ) ;
1462
+ checkboxes . forEach ( checkbox => {
1463
+ if ( ! checkbox . checked && ! currentTabData . hasOwnProperty ( checkbox . name ) ) {
1464
+ currentTabData [ checkbox . name ] = false ;
1465
+ }
1466
+ } ) ;
1467
+
1468
+ // Only cache data if it contains meaningful configuration
1469
+ if ( hasSignificantConfiguration ( currentTabData , activeTab ) ) {
1470
+ formDataCache [ activeTab ] = currentTabData ;
1471
+ console . log ( `[Settings] Preserved data for tab '${ activeTab } ':` , currentTabData ) ;
1472
+ } else {
1473
+ // Clear cache for this tab if no significant data
1474
+ delete formDataCache [ activeTab ] ;
1475
+ console . log ( `[Settings] No significant data to preserve for tab '${ activeTab } ', cleared cache` ) ;
1476
+ }
1477
+ }
1478
+
1479
+ function hasSignificantConfiguration ( data , tabName ) {
1480
+ // Check if the data contains any non-empty, meaningful values
1481
+ if ( tabName === 'proxmox' ) {
1482
+ // For Proxmox tab, require at least a host to be considered significant
1483
+ return ! ! ( data . PROXMOX_HOST && data . PROXMOX_HOST . trim ( ) ) ||
1484
+ ! ! ( data . PROXMOX_HOST_2 && data . PROXMOX_HOST_2 . trim ( ) ) ||
1485
+ ! ! ( data . PROXMOX_HOST_3 && data . PROXMOX_HOST_3 . trim ( ) ) ;
1486
+ } else if ( tabName === 'pbs' ) {
1487
+ // For PBS tab, require at least a host to be considered significant
1488
+ return ! ! ( data . PBS_HOST && data . PBS_HOST . trim ( ) ) ||
1489
+ ! ! ( data . PBS_HOST_2 && data . PBS_HOST_2 . trim ( ) ) ||
1490
+ ! ! ( data . PBS_HOST_3 && data . PBS_HOST_3 . trim ( ) ) ;
1491
+ } else if ( tabName === 'alerts' ) {
1492
+ // For alerts tab, any threshold value or email/webhook config is significant
1493
+ return Object . keys ( data ) . some ( key => {
1494
+ const value = data [ key ] ;
1495
+ if ( typeof value === 'string' && value . trim ( ) ) return true ;
1496
+ if ( typeof value === 'boolean' && value ) return true ;
1497
+ if ( typeof value === 'number' && value > 0 ) return true ;
1498
+ return false ;
1499
+ } ) ;
1500
+ }
1501
+
1502
+ // For other tabs, check if any field has a non-empty value
1503
+ return Object . values ( data ) . some ( value => {
1504
+ if ( typeof value === 'string' && value . trim ( ) ) return true ;
1505
+ if ( typeof value === 'boolean' && value ) return true ;
1506
+ if ( typeof value === 'number' && value !== 0 ) return true ;
1507
+ return false ;
1508
+ } ) ;
1509
+ }
1510
+
1511
+ function restoreFormData ( ) {
1512
+ const form = document . getElementById ( 'settings-form' ) ;
1513
+ if ( ! form ) return ;
1514
+
1515
+ const savedData = formDataCache [ activeTab ] ;
1516
+ if ( ! savedData ) return ;
1517
+
1518
+ console . log ( `[Settings] Restoring data for tab '${ activeTab } ':` , savedData ) ;
1519
+
1520
+ // Restore form field values
1521
+ Object . entries ( savedData ) . forEach ( ( [ name , value ] ) => {
1522
+ const field = form . querySelector ( `[name="${ name } "]` ) ;
1523
+ if ( field ) {
1524
+ if ( field . type === 'checkbox' ) {
1525
+ field . checked = value === true || value === 'true' ;
1526
+ } else {
1527
+ field . value = value || '' ;
1528
+ }
1529
+ }
1530
+ } ) ;
1531
+ }
1532
+
1398
1533
function showMessage ( message , type = 'info' ) {
1399
1534
// Find or create message container within the current tab
1400
1535
let container = document . getElementById ( 'settings-message' ) ;
0 commit comments