More import optimizations + reset optimizations
This commit is contained in:
@@ -50,6 +50,7 @@ export function Settings() {
|
||||
const [isResetting, setIsResetting] = useState(false);
|
||||
const [updateProgress, setUpdateProgress] = useState<ImportProgress | null>(null);
|
||||
const [importProgress, setImportProgress] = useState<ImportProgress | null>(null);
|
||||
const [purchaseOrdersProgress, setPurchaseOrdersProgress] = useState<ImportProgress | null>(null);
|
||||
const [resetProgress, setResetProgress] = useState<ImportProgress | null>(null);
|
||||
const [eventSource, setEventSource] = useState<EventSource | null>(null);
|
||||
const [limits, setLimits] = useState<ImportLimits>({
|
||||
@@ -58,49 +59,48 @@ export function Settings() {
|
||||
purchaseOrders: 0
|
||||
});
|
||||
|
||||
// Helper function to update progress state
|
||||
const updateProgressState = (progressData: any) => {
|
||||
const operation = progressData.operation?.toLowerCase() || '';
|
||||
const progressUpdate = {
|
||||
status: progressData.status || 'running',
|
||||
operation: progressData.operation,
|
||||
current: progressData.current !== undefined ? Number(progressData.current) : undefined,
|
||||
total: progressData.total !== undefined ? Number(progressData.total) : undefined,
|
||||
rate: progressData.rate !== undefined ? Number(progressData.rate) : undefined,
|
||||
percentage: progressData.percentage,
|
||||
elapsed: progressData.elapsed,
|
||||
remaining: progressData.remaining,
|
||||
error: progressData.error,
|
||||
message: progressData.message,
|
||||
added: progressData.added,
|
||||
updated: progressData.updated,
|
||||
skipped: progressData.skipped,
|
||||
duration: progressData.duration
|
||||
};
|
||||
|
||||
if (operation.includes('products import completed')) {
|
||||
setImportProgress(null);
|
||||
} else if (operation.includes('products import')) {
|
||||
setImportProgress(prev => ({ ...prev, ...progressUpdate }));
|
||||
} else if (operation.includes('orders import') && !operation.includes('purchase')) {
|
||||
setImportProgress(prev => ({ ...prev, ...progressUpdate }));
|
||||
} else if (operation.includes('purchase orders import')) {
|
||||
setPurchaseOrdersProgress(prev => ({ ...prev, ...progressUpdate }));
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to connect to event source
|
||||
const connectToEventSource = useCallback((type: 'update' | 'import' | 'reset') => {
|
||||
if (eventSource) {
|
||||
eventSource.close();
|
||||
}
|
||||
|
||||
console.log('Connecting to event source:', type); // Debug log
|
||||
const source = new EventSource(`${config.apiUrl}/csv/${type}/progress`, {
|
||||
withCredentials: true
|
||||
});
|
||||
setEventSource(source);
|
||||
|
||||
source.onopen = () => {
|
||||
console.log('Event source connected:', type); // Debug log
|
||||
};
|
||||
|
||||
source.onerror = () => {
|
||||
console.log('Event source error:', type, source.readyState); // Debug log
|
||||
if (source.readyState === EventSource.CLOSED) {
|
||||
source.close();
|
||||
setEventSource(null);
|
||||
|
||||
// Only reset states if we're not in a completed state
|
||||
const progress = type === 'update' ? updateProgress :
|
||||
type === 'import' ? importProgress :
|
||||
resetProgress;
|
||||
|
||||
if (progress?.status !== 'complete') {
|
||||
// Reset the appropriate state based on type
|
||||
if (type === 'update') {
|
||||
setIsUpdating(false);
|
||||
setUpdateProgress(null);
|
||||
} else if (type === 'import') {
|
||||
setIsImporting(false);
|
||||
setImportProgress(null);
|
||||
} else if (type === 'reset') {
|
||||
setIsResetting(false);
|
||||
setResetProgress(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
source.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
@@ -108,44 +108,18 @@ export function Settings() {
|
||||
(typeof data.progress === 'string' ? JSON.parse(data.progress) : data.progress)
|
||||
: data;
|
||||
|
||||
// Update the appropriate progress state based on type
|
||||
const setProgress = type === 'update' ? setUpdateProgress :
|
||||
type === 'import' ? setImportProgress :
|
||||
setResetProgress;
|
||||
|
||||
// Also set the operation state if we're getting progress
|
||||
if (progressData.status === 'running') {
|
||||
if (type === 'update') setIsUpdating(true);
|
||||
else if (type === 'import') setIsImporting(true);
|
||||
else if (type === 'reset') setIsResetting(true);
|
||||
}
|
||||
|
||||
setProgress(prev => {
|
||||
// If we're getting a new operation, clear out old messages
|
||||
if (progressData.operation && progressData.operation !== prev?.operation) {
|
||||
return {
|
||||
status: progressData.status || 'running',
|
||||
operation: progressData.operation,
|
||||
current: progressData.current !== undefined ? Number(progressData.current) : undefined,
|
||||
total: progressData.total !== undefined ? Number(progressData.total) : undefined,
|
||||
rate: progressData.rate !== undefined ? Number(progressData.rate) : undefined,
|
||||
percentage: progressData.percentage,
|
||||
elapsed: progressData.elapsed,
|
||||
remaining: progressData.remaining,
|
||||
message: progressData.message,
|
||||
error: progressData.error,
|
||||
added: progressData.added,
|
||||
updated: progressData.updated,
|
||||
skipped: progressData.skipped,
|
||||
duration: progressData.duration
|
||||
};
|
||||
}
|
||||
|
||||
// Otherwise update existing state
|
||||
return {
|
||||
// Handle different types of progress
|
||||
if (type === 'import') {
|
||||
updateProgressState(progressData);
|
||||
} else {
|
||||
// For non-import operations, use the existing logic
|
||||
const setProgress = type === 'update' ? setUpdateProgress :
|
||||
type === 'reset' ? setResetProgress :
|
||||
setImportProgress;
|
||||
setProgress(prev => ({
|
||||
...prev,
|
||||
status: progressData.status || prev?.status || 'running',
|
||||
operation: progressData.operation || prev?.operation,
|
||||
status: progressData.status || 'running',
|
||||
operation: progressData.operation,
|
||||
current: progressData.current !== undefined ? Number(progressData.current) : prev?.current,
|
||||
total: progressData.total !== undefined ? Number(progressData.total) : prev?.total,
|
||||
rate: progressData.rate !== undefined ? Number(progressData.rate) : prev?.rate,
|
||||
@@ -158,8 +132,15 @@ export function Settings() {
|
||||
updated: progressData.updated !== undefined ? progressData.updated : prev?.updated,
|
||||
skipped: progressData.skipped !== undefined ? progressData.skipped : prev?.skipped,
|
||||
duration: progressData.duration || prev?.duration
|
||||
};
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
// Set operation state if we're getting progress
|
||||
if (progressData.status === 'running') {
|
||||
if (type === 'update') setIsUpdating(true);
|
||||
else if (type === 'import') setIsImporting(true);
|
||||
else if (type === 'reset') setIsResetting(true);
|
||||
}
|
||||
|
||||
if (progressData.status === 'complete') {
|
||||
source.close();
|
||||
@@ -172,6 +153,7 @@ export function Settings() {
|
||||
} else if (type === 'import') {
|
||||
setIsImporting(false);
|
||||
setImportProgress(null);
|
||||
setPurchaseOrdersProgress(null);
|
||||
} else if (type === 'reset') {
|
||||
setIsResetting(false);
|
||||
setResetProgress(null);
|
||||
@@ -196,7 +178,7 @@ export function Settings() {
|
||||
handleError(`${type.charAt(0).toUpperCase() + type.slice(1)}`, progressData.error || 'Unknown error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error parsing event data:', error); // Debug log
|
||||
console.error('Error parsing event data:', error);
|
||||
}
|
||||
};
|
||||
}, []); // Remove dependencies that might prevent initial connection
|
||||
@@ -339,7 +321,7 @@ export function Settings() {
|
||||
setImportProgress({ status: 'running', operation: 'Starting import process' });
|
||||
|
||||
try {
|
||||
// Connect to SSE for progress updates
|
||||
// Connect to SSE for progress updates first
|
||||
connectToEventSource('import');
|
||||
|
||||
// Make the import request
|
||||
@@ -354,20 +336,23 @@ export function Settings() {
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
if (data.error === 'Import already in progress') {
|
||||
// If there's already an import, just let the SSE connection handle showing progress
|
||||
return;
|
||||
// Only handle error if we don't have any progress yet
|
||||
if (!importProgress?.current && !purchaseOrdersProgress?.current) {
|
||||
throw new Error(data.error || 'Failed to start CSV import');
|
||||
}
|
||||
throw new Error(data.error || 'Failed to start CSV import');
|
||||
}
|
||||
} catch (error) {
|
||||
if (eventSource) {
|
||||
eventSource.close();
|
||||
setEventSource(null);
|
||||
// Only clean up if we don't have any progress
|
||||
if (!importProgress?.current && !purchaseOrdersProgress?.current) {
|
||||
if (eventSource) {
|
||||
eventSource.close();
|
||||
setEventSource(null);
|
||||
}
|
||||
setIsImporting(false);
|
||||
setImportProgress(null);
|
||||
setPurchaseOrdersProgress(null);
|
||||
handleError('Data import', error instanceof Error ? error.message : 'Unknown error');
|
||||
}
|
||||
setIsImporting(false);
|
||||
setImportProgress(null);
|
||||
handleError('Data import', error instanceof Error ? error.message : 'Unknown error');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -479,7 +464,11 @@ export function Settings() {
|
||||
if (error.includes('cancelled') ||
|
||||
error.includes('Process exited with code 143') ||
|
||||
error.includes('Operation cancelled') ||
|
||||
error.includes('500 Internal Server Error')) {
|
||||
error.includes('500 Internal Server Error') ||
|
||||
// Skip "Failed to start" errors if we have active progress
|
||||
(error.includes('Failed to start CSV import') && (importProgress || purchaseOrdersProgress)) ||
|
||||
// Skip connection errors if we have active progress
|
||||
(error.includes('Failed to fetch') && (importProgress || purchaseOrdersProgress))) {
|
||||
return;
|
||||
}
|
||||
toast.error(`${operation} failed: ${error}`);
|
||||
@@ -615,7 +604,29 @@ export function Settings() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isImporting && renderProgress(importProgress)}
|
||||
{isImporting && (
|
||||
<div className="space-y-4">
|
||||
{/* Show products progress */}
|
||||
{importProgress?.operation?.toLowerCase().includes('products') && (
|
||||
<div>
|
||||
{renderProgress(importProgress)}
|
||||
</div>
|
||||
)}
|
||||
{/* Show orders progress */}
|
||||
{importProgress?.operation?.toLowerCase().includes('orders import') &&
|
||||
!importProgress.operation.toLowerCase().includes('purchase') && (
|
||||
<div>
|
||||
{renderProgress(importProgress)}
|
||||
</div>
|
||||
)}
|
||||
{/* Show purchase orders progress */}
|
||||
{purchaseOrdersProgress && (
|
||||
<div>
|
||||
{renderProgress(purchaseOrdersProgress)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user