From 4dcc1f9e90464eee0ae20e820e0451a10646ef6d Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 11 Feb 2025 22:15:13 -0500 Subject: [PATCH] Fix frontend reset script and visual tweaks --- inventory-server/scripts/full-reset.js | 19 ++- inventory-server/scripts/full-update.js | 15 +- inventory-server/src/routes/csv.js | 41 +++++- .../components/settings/DataManagement.tsx | 130 ++++++++++-------- 4 files changed, 140 insertions(+), 65 deletions(-) diff --git a/inventory-server/scripts/full-reset.js b/inventory-server/scripts/full-reset.js index 96d0439..9a6aff8 100644 --- a/inventory-server/scripts/full-reset.js +++ b/inventory-server/scripts/full-reset.js @@ -57,25 +57,36 @@ async function fullReset() { message: 'Step 1/3: Resetting database...' }); await runScript(path.join(__dirname, 'reset-db.js')); + outputProgress({ + status: 'complete', + operation: 'Database reset step complete', + message: 'Database reset finished, moving to import...' + }); // Step 2: Import from Production outputProgress({ - operation: 'Database reset complete', + operation: 'Starting import', message: 'Step 2/3: Importing from production...' }); await runScript(path.join(__dirname, 'import-from-prod.js')); + outputProgress({ + status: 'complete', + operation: 'Import step complete', + message: 'Import finished, moving to metrics calculation...' + }); // Step 3: Calculate Metrics outputProgress({ - operation: 'Import complete', + operation: 'Starting metrics calculation', message: 'Step 3/3: Calculating metrics...' }); await runScript(path.join(__dirname, 'calculate-metrics.js')); - + + // Final completion message outputProgress({ status: 'complete', operation: 'Full reset complete', - message: 'Successfully completed database reset, import, and metrics calculation' + message: 'Successfully completed all steps: database reset, import, and metrics calculation' }); } catch (error) { outputProgress({ diff --git a/inventory-server/scripts/full-update.js b/inventory-server/scripts/full-update.js index 1707deb..f689f72 100644 --- a/inventory-server/scripts/full-update.js +++ b/inventory-server/scripts/full-update.js @@ -57,18 +57,29 @@ async function fullUpdate() { message: 'Step 1/2: Importing from production...' }); await runScript(path.join(__dirname, 'import-from-prod.js')); + outputProgress({ + status: 'complete', + operation: 'Import step complete', + message: 'Import finished, moving to metrics calculation...' + }); // Step 2: Calculate Metrics outputProgress({ - operation: 'Import complete', + operation: 'Starting metrics calculation', message: 'Step 2/2: Calculating metrics...' }); await runScript(path.join(__dirname, 'calculate-metrics.js')); + outputProgress({ + status: 'complete', + operation: 'Metrics step complete', + message: 'Metrics calculation finished' + }); + // Final completion message outputProgress({ status: 'complete', operation: 'Full update complete', - message: 'Successfully completed import and metrics calculation' + message: 'Successfully completed all steps: import and metrics calculation' }); } catch (error) { outputProgress({ diff --git a/inventory-server/src/routes/csv.js b/inventory-server/src/routes/csv.js index 7adbb87..d0dfd06 100644 --- a/inventory-server/src/routes/csv.js +++ b/inventory-server/src/routes/csv.js @@ -85,8 +85,41 @@ function runScript(scriptPath, type, clients) { child.stdout.on('data', (data) => { const text = data.toString(); output += text; - // Send raw output directly - sendProgressToClients(clients, text); + + // Split by lines to handle multiple JSON outputs + const lines = text.split('\n'); + lines.filter(line => line.trim()).forEach(line => { + try { + // Try to parse as JSON but don't let it affect the display + const jsonData = JSON.parse(line); + // Only end the process if we get a final status + if (jsonData.status === 'complete' || jsonData.status === 'error' || jsonData.status === 'cancelled') { + if (jsonData.status === 'complete' && !jsonData.operation?.includes('complete')) { + // Don't close for intermediate completion messages + sendProgressToClients(clients, line); + return; + } + // Close only on final completion/error/cancellation + switch (type) { + case 'update': + activeFullUpdate = null; + break; + case 'reset': + activeFullReset = null; + break; + } + if (jsonData.status === 'error') { + reject(new Error(jsonData.error || 'Unknown error')); + } else { + resolve({ output }); + } + } + } catch (e) { + // Not JSON, just display as is + } + // Always send the raw line + sendProgressToClients(clients, line); + }); }); child.stderr.on('data', (data) => { @@ -110,10 +143,8 @@ function runScript(scriptPath, type, clients) { const error = `Script ${scriptPath} exited with code ${code}`; sendProgressToClients(clients, error); reject(new Error(error)); - } else { - sendProgressToClients(clients, `${type} completed successfully`); - resolve({ output }); } + // Don't resolve here - let the completion message from the script trigger the resolve }); child.on('error', (err) => { diff --git a/inventory/src/components/settings/DataManagement.tsx b/inventory/src/components/settings/DataManagement.tsx index f736640..42f7c07 100644 --- a/inventory/src/components/settings/DataManagement.tsx +++ b/inventory/src/components/settings/DataManagement.tsx @@ -181,25 +181,30 @@ export function DataManagement() { // Try to parse for status updates, but don't affect display try { const data = JSON.parse(event.data); - if ( - data.status === "complete" || - data.status === "error" || - data.status === "cancelled" - ) { - source.close(); - setEventSource(null); - setIsUpdating(false); + if (data.status === 'complete' || data.status === 'error' || data.status === 'cancelled') { + // Only close and reset state if this is the final completion message + if (data.operation === 'Full update complete' || + data.status === 'error' || + data.status === 'cancelled') { + source.close(); + setEventSource(null); + setIsUpdating(false); - if (data.status === "complete") { - toast.success("Update completed successfully"); - fetchHistory(); - } else if (data.status === "error") { - toast.error(`Update failed: ${data.error || "Unknown error"}`); - } else { - toast.warning("Update cancelled"); + if (data.status === 'complete') { + toast.success("Update completed successfully"); + fetchHistory(); + } else if (data.status === 'error') { + toast.error(`Update failed: ${data.error || 'Unknown error'}`); + } else { + toast.warning("Update cancelled"); + } + } + // For intermediate completions, just show a toast + else if (data.status === 'complete') { + toast.success(data.message || "Step completed"); } } - } catch (error) { + } catch (error) { // Not JSON, just display as is } }; @@ -246,25 +251,30 @@ export function DataManagement() { // Try to parse for status updates, but don't affect display try { const data = JSON.parse(event.data); - if ( - data.status === "complete" || - data.status === "error" || - data.status === "cancelled" - ) { - source.close(); - setEventSource(null); - setIsResetting(false); + if (data.status === 'complete' || data.status === 'error' || data.status === 'cancelled') { + // Only close and reset state if this is the final completion message + if (data.operation === 'Full reset complete' || + data.status === 'error' || + data.status === 'cancelled') { + source.close(); + setEventSource(null); + setIsResetting(false); - if (data.status === "complete") { - toast.success("Reset completed successfully"); - fetchHistory(); - } else if (data.status === "error") { - toast.error(`Reset failed: ${data.error || "Unknown error"}`); - } else { - toast.warning("Reset cancelled"); - } - } - } catch (error) { + if (data.status === 'complete') { + toast.success("Reset completed successfully"); + fetchHistory(); + } else if (data.status === 'error') { + toast.error(`Reset failed: ${data.error || 'Unknown error'}`); + } else { + toast.warning("Reset cancelled"); + } + } + // For intermediate completions, just show a toast + else if (data.status === 'complete') { + toast.success(data.message || "Step completed"); + } + } + } catch (error) { // Not JSON, just display as is } }; @@ -511,17 +521,23 @@ export function DataManagement() {
- {tableStatus.map((table) => ( -
- {table.table_name} - - {formatStatusTime(table.last_sync_timestamp)} - + {tableStatus.length > 0 ? ( + tableStatus.map((table) => ( +
+ {table.table_name} + + {formatStatusTime(table.last_sync_timestamp)} + +
+ )) + ) : ( +
+ No imports have been performed yet.
Run a full update or reset to import data.
- ))} + )}
@@ -532,17 +548,23 @@ export function DataManagement() {
- {moduleStatus.map((module) => ( -
- {module.module_name} - - {formatStatusTime(module.last_calculation_timestamp)} - + {moduleStatus.length > 0 ? ( + moduleStatus.map((module) => ( +
+ {module.module_name} + + {formatStatusTime(module.last_calculation_timestamp)} + +
+ )) + ) : ( +
+ No metrics have been calculated yet.
Run a full update or reset to calculate metrics.
- ))} + )}