import React, { useState } from 'react'; import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, IconButton, Checkbox, Button, Chip, Dialog, DialogTitle, DialogContent, DialogActions, Typography, Tooltip, } from '@mui/material'; import { Download as DownloadIcon, Delete as DeleteIcon, Error as ErrorIcon } from '@mui/icons-material'; import { File, FileStatus } from '../types/file'; import { api } from '../services/api'; interface FileListProps { files: File[]; onFileStatusChange: () => void; } const FileList: React.FC = ({ files, onFileStatusChange }) => { const [selectedFiles, setSelectedFiles] = useState([]); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [fileToDelete, setFileToDelete] = useState(null); const handleSelectFile = (fileId: string) => { setSelectedFiles((prev) => prev.includes(fileId) ? prev.filter((id) => id !== fileId) : [...prev, fileId] ); }; const handleSelectAll = () => { setSelectedFiles((prev) => prev.length === files.length ? [] : files.map((file) => file.id) ); }; const handleDownload = async (fileId: string) => { try { console.log('=== FRONTEND DOWNLOAD START ==='); console.log('File ID:', fileId); const file = files.find((f) => f.id === fileId); console.log('File object:', file); const blob = await api.downloadFile(fileId); console.log('Blob received:', blob); console.log('Blob type:', blob.type); console.log('Blob size:', blob.size); const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; // Match backend behavior: change extension to .md const originalFilename = file?.filename || 'downloaded-file'; const filenameWithoutExt = originalFilename.replace(/\.[^/.]+$/, ''); // Remove extension const downloadFilename = `${filenameWithoutExt}.md`; console.log('Original filename:', originalFilename); console.log('Filename without extension:', filenameWithoutExt); console.log('Download filename:', downloadFilename); a.download = downloadFilename; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); document.body.removeChild(a); console.log('=== FRONTEND DOWNLOAD END ==='); } catch (error) { console.error('Error downloading file:', error); } }; const handleDownloadSelected = async () => { for (const fileId of selectedFiles) { await handleDownload(fileId); } }; const handleDeleteClick = (fileId: string) => { setFileToDelete(fileId); setDeleteDialogOpen(true); }; const handleDeleteConfirm = async () => { if (fileToDelete) { try { await api.deleteFile(fileToDelete); onFileStatusChange(); } catch (error) { console.error('Error deleting file:', error); } } setDeleteDialogOpen(false); setFileToDelete(null); }; const handleDeleteCancel = () => { setDeleteDialogOpen(false); setFileToDelete(null); }; const getStatusColor = (status: FileStatus) => { switch (status) { case FileStatus.SUCCESS: return 'success'; case FileStatus.FAILED: return 'error'; case FileStatus.PROCESSING: return 'warning'; default: return 'default'; } }; return (
0 && selectedFiles.length < files.length} onChange={handleSelectAll} /> Filename Status Created At Finished At Actions {files.map((file) => ( handleSelectFile(file.id)} /> {file.filename} {file.status === FileStatus.FAILED && file.error_message && (
{file.error_message.length > 50 ? `${file.error_message.substring(0, 50)}...` : file.error_message }
)}
{new Date(file.created_at).toLocaleString()} {(file.status === FileStatus.SUCCESS || file.status === FileStatus.FAILED) ? new Date(file.updated_at).toLocaleString() : '—'} handleDeleteClick(file.id)} size="small" color="error" sx={{ mr: 1 }} > {file.status === FileStatus.SUCCESS && ( handleDownload(file.id)} size="small" color="primary" > )}
))}
Confirm Delete Are you sure you want to delete this file? This action cannot be undone.
); }; export default FileList;