From 821fafd990920994753d47e58be745bf2d559557 Mon Sep 17 00:00:00 2001 From: Golwhit Date: Mon, 29 Dec 2025 23:18:10 -0600 Subject: [PATCH] Implement dynamic column reordering with numeric order field and realtime sync - Add order field to all columns in DEFAULT_SETTINGS (1-47) - Settings page: reorder columns via numeric input or up/down arrows, autosave after 400ms - Estimator table: render columns in order specified by order field, refresh on settings updates - Normalize column orders on load and realtime updates with fallback for missing order - Add logging to trace column order changes through settings and estimator pages - Reset button reinitializes all settings to defaults with proper column ordering - Table reload prevents concurrent requests to avoid PocketBase auto-cancellation --- appsettings.html | 185 +++++++++++++++----- estimatortable.html | 416 +++++++++++++++++++++++++++++--------------- server.ts | 6 +- 3 files changed, 424 insertions(+), 183 deletions(-) diff --git a/appsettings.html b/appsettings.html index 74b1217..2cc21cd 100644 --- a/appsettings.html +++ b/appsettings.html @@ -133,6 +133,8 @@ const APP_NAME = 'Estimator Job List'; let settingsRecordId = null; let currentSettings = null; + let autosaveTimer = null; + const AUTOSAVE_DELAY = 400; // Column names from schema const COLUMNS = [ @@ -153,8 +155,9 @@ rowHeight: 40, fontSize: 14, stripedRows: true, - columns: COLUMNS.map(col => ({ + columns: COLUMNS.map((col, idx) => ({ name: col, + order: idx + 1, readOnly: col === 'Active' || col === 'Due_Date_Counter' || col === 'Job_Number', width: col === 'Job_Number' ? 120 : col === 'Job_Full_Name' ? 250 : 150, visible: true, @@ -170,6 +173,79 @@ })) }; + function syncColumnOrderNumbers() { + if (!currentSettings || !Array.isArray(currentSettings.columns)) return; + currentSettings.columns = currentSettings.columns.map((col, idx) => ({ + ...col, + order: idx + 1 + })); + } + + async function reinitializeToDefaults() { + try { + // Create fresh settings from defaults + currentSettings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS)); + console.log('Reinitialized to defaults, saving...'); + + // Immediately save to PocketBase (not queued) + const jsonString = JSON.stringify(currentSettings); + await pb.collection('app_preferences_settings').update(settingsRecordId, { + app_json_prefs: jsonString, + app_txt_prefs: `Reset to defaults on ${new Date().toISOString()}` + }); + + console.log('Settings reset to defaults and saved'); + renderSettings(); + alert('Settings reset to defaults successfully!'); + } catch (error) { + console.error('Error reinitializing settings:', error); + alert('Error resetting to defaults: ' + error.message); + } + } + + function syncColumnOrderNumbers() { + if (!currentSettings || !Array.isArray(currentSettings.columns)) return; + currentSettings.columns = currentSettings.columns.map((col, idx) => ({ + ...col, + order: idx + 1 + })); + } + + function captureGlobalInputs() { + currentSettings.rowHeight = parseInt(document.getElementById('rowHeight').value); + currentSettings.fontSize = parseInt(document.getElementById('fontSize').value); + currentSettings.stripedRows = document.getElementById('stripedRows').checked; + } + + async function saveSettings(isAuto = false) { + try { + captureGlobalInputs(); + syncColumnOrderNumbers(); + console.log('Saving columns with orders:', currentSettings.columns.map(c => ({ name: c.name, order: c.order, visible: c.visible })).slice(0, 5)); + const jsonString = JSON.stringify(currentSettings); + await pb.collection('app_preferences_settings').update(settingsRecordId, { + app_json_prefs: jsonString, + app_txt_prefs: `Updated on ${new Date().toISOString()}` + }); + console.log('Settings saved to PocketBase successfully'); + if (!isAuto) { + alert('Settings saved successfully!'); + } + } catch (error) { + console.error('Error saving settings:', error); + if (!isAuto) { + alert('Error saving settings: ' + error.message + '. Please try again.'); + } + } + } + + function queueAutosave() { + if (autosaveTimer) { + clearTimeout(autosaveTimer); + } + autosaveTimer = setTimeout(() => saveSettings(true), AUTOSAVE_DELAY); + } + // Load settings from PocketBase async function loadSettings() { try { @@ -219,6 +295,7 @@ console.log('Created new record:', settingsRecordId); } + syncColumnOrderNumbers(); renderSettings(); document.getElementById('loadingIndicator').classList.add('hidden'); document.getElementById('settingsContainer').classList.remove('hidden'); @@ -227,6 +304,7 @@ console.error('Error details:', error.message, error.stack); alert('Error loading settings: ' + error.message + '. Using defaults.'); currentSettings = JSON.parse(JSON.stringify(DEFAULT_SETTINGS)); + syncColumnOrderNumbers(); renderSettings(); document.getElementById('loadingIndicator').classList.add('hidden'); document.getElementById('settingsContainer').classList.remove('hidden'); @@ -250,19 +328,32 @@ colDiv.innerHTML = `

${col.name}

- +
+
+ + +
+ +
-
+
+ +
+ + +