import React, { useState } from 'react'; import { AlertCircle, Clock, Database, FileX, Loader2, CheckCircle2, Hash, Copy, Download, Check } from 'lucide-react'; const MAX_DISPLAY_ROWS = 1000; export default function ResultTable({ result, loading, pollingProgress }) { const [copied, setCopied] = useState(false); // Normalize data let columns = []; let rows = []; if (result && !result.error) { if (result.rows && result.columns) { columns = result.columns; rows = result.rows; } else if (Array.isArray(result.data) && result.data.length > 0) { columns = Object.keys(result.data[0]); rows = result.data; } else if (Array.isArray(result) && result.length > 0) { columns = Object.keys(result[0]); rows = result; } } // Function to convert data to CSV const generateCSV = (cols, dataRows) => { const header = cols.join(','); const csvRows = dataRows.map(row => { return cols.map(col => { let val = Array.isArray(row) ? row[cols.indexOf(col)] : row[col]; if (val === null || val === undefined) val = ''; val = String(val).replace(/"/g, '""'); if (val.includes(',') || val.includes('"') || val.includes('\n')) { val = `"${val}"`; } return val; }).join(','); }); return [header, ...csvRows].join('\n'); }; // Download as CSV const handleDownloadCSV = (cols, dataRows) => { const csv = generateCSV(cols, dataRows); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.setAttribute('href', url); link.setAttribute('download', `query_result_${Date.now()}.csv`); document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }; // Auto-download if too many rows React.useEffect(() => { if (rows.length > MAX_DISPLAY_ROWS) { handleDownloadCSV(columns, rows); } }, [result]); // Copy to clipboard const handleCopy = (cols, dataRows) => { const csv = generateCSV(cols, dataRows); navigator.clipboard.writeText(csv).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }); }; // Loading state if (loading) { return (

{pollingProgress ? 'Esperando respuesta del agente remoto...' : 'Enviando comando...'}

{pollingProgress && (

Polling: {pollingProgress.attempts} / {pollingProgress.maxAttempts}

)}
); } // No result yet if (!result) { return (

Los resultados aparecerán aquí

); } // Error state if (result.error) { return (

Error en la ejecución

{result.error} {result.command_id && (

Command ID: #{result.command_id}

)}
); } // Success message (no data rows) if (rows.length === 0 && !result.error) { if (result.command_id || result.message) { return (

{result.message || 'Consulta ejecutada correctamente'}

{result.downloadUrl && (
Descargar Respaldo Ahora

El archivo se encuentra disponible en el servidor FTP especificado.

)} {result.command_id && !result.downloadUrl && (

Command ID: {result.command_id}

)}
); } return (

La consulta no devolvió resultados.

); } // Large dataset display if (rows.length > MAX_DISPLAY_ROWS) { return (

Resultado muy grande ({rows.length} filas)

Para mantener el rendimiento del navegador, los resultados que superan las {MAX_DISPLAY_ROWS} filas no se muestran en pantalla y se descargan automáticamente como CSV.

{result.command_id && (

Command ID: #{result.command_id}

)}
); } // Data table display - DARK THEME return (
{/* Stats Header */}
{result.command_id && ( {result.command_id} )} {result.stats?.row_count !== undefined && ( {result.stats.row_count} filas )} {result.stats?.duration && ( {result.stats.duration} )}
{/* Copy Button */} {/* Download CSV Button */} Completado
{/* Data Table */}
{columns.map((col, idx) => ( ))} {rows.map((row, rIdx) => ( {columns.map((col, cIdx) => { let val; if (Array.isArray(row)) { val = row[cIdx]; } else { val = row[col]; } return ( ); })} ))}
#{col}
{rIdx + 1} {val === null ? ( NULL ) : typeof val === 'object' ? ( {JSON.stringify(val)} ) : ( String(val) )}
); }