@@ -258,7 +242,7 @@ export function DashboardTab({ selectedTema }: DashboardTabProps) {
{new Date(file.last_modified).toLocaleDateString(
- "es-ES",
+ "en-US",
{
year: "numeric",
month: "short",
diff --git a/frontend/src/components/DataroomView.tsx b/frontend/src/components/DataroomView.tsx
index df73bd7..3fe0b57 100644
--- a/frontend/src/components/DataroomView.tsx
+++ b/frontend/src/components/DataroomView.tsx
@@ -87,14 +87,12 @@ export function DataroomView({ onProcessingChange }: DataroomViewProps = {}) {
- {selectedTema
- ? `Dataroom: ${selectedTema}`
- : "Selecciona un dataroom"}
+ {selectedTema ? `Dataroom: ${selectedTema}` : "Select a dataroom"}
{selectedTema
- ? "Gestiona archivos, consulta métricas y chatea con IA sobre el contenido"
- : "Selecciona un dataroom de la barra lateral para comenzar"}
+ ? "Manage files, review metrics, and chat with AI about the content."
+ : "Pick a dataroom from the sidebar to get started."}
diff --git a/frontend/src/components/DeleteConfirmDialog.tsx b/frontend/src/components/DeleteConfirmDialog.tsx
index 3a03f4a..dbc7bc4 100644
--- a/frontend/src/components/DeleteConfirmDialog.tsx
+++ b/frontend/src/components/DeleteConfirmDialog.tsx
@@ -1,4 +1,4 @@
-import { Button } from '@/components/ui/button'
+import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
@@ -6,17 +6,17 @@ import {
DialogFooter,
DialogHeader,
DialogTitle,
-} from '@/components/ui/dialog'
-import { Trash2, AlertTriangle } from 'lucide-react'
+} from "@/components/ui/dialog";
+import { Trash2, AlertTriangle } from "lucide-react";
interface DeleteConfirmDialogProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- onConfirm: () => void
- title: string
- description: string
- fileList?: string[]
- loading?: boolean
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ onConfirm: () => void;
+ title: string;
+ description: string;
+ fileList?: string[];
+ loading?: boolean;
}
export function DeleteConfirmDialog({
@@ -26,7 +26,7 @@ export function DeleteConfirmDialog({
title,
description,
fileList,
- loading = false
+ loading = false,
}: DeleteConfirmDialogProps) {
return (
@@ -41,7 +41,7 @@ export function DeleteConfirmDialog({
{fileList && fileList.length > 0 && (
-
Archivos a eliminar:
+
Files to delete:
{fileList.map((filename, index) => (
@@ -59,17 +59,13 @@ export function DeleteConfirmDialog({
onClick={() => onOpenChange(false)}
disabled={loading}
>
- Cancelar
+ Cancel
-
- {loading ? 'Eliminando...' : 'Eliminar'}
+
+ {loading ? "Deleting…" : "Delete"}
- )
-}
\ No newline at end of file
+ );
+}
diff --git a/frontend/src/components/FilesTab.tsx b/frontend/src/components/FilesTab.tsx
index 6467b75..f1f51f7 100644
--- a/frontend/src/components/FilesTab.tsx
+++ b/frontend/src/components/FilesTab.tsx
@@ -60,7 +60,7 @@ export function FilesTab({
const [deleting, setDeleting] = useState(false);
const [downloading, setDownloading] = useState(false);
- // Estados para el modal de preview de PDF
+ // PDF preview modal state
const [previewModalOpen, setPreviewModalOpen] = useState(false);
const [previewFileUrl, setPreviewFileUrl] = useState(null);
const [previewFileName, setPreviewFileName] = useState("");
@@ -69,12 +69,12 @@ export function FilesTab({
);
const [loadingPreview, setLoadingPreview] = useState(false);
- // Estados para el modal de chunks
+ // Chunk viewer modal state
const [chunkViewerOpen, setChunkViewerOpen] = useState(false);
const [chunkFileName, setChunkFileName] = useState("");
const [chunkFileTema, setChunkFileTema] = useState("");
- // Estados para chunking
+ // LandingAI chunking state
const [chunkingConfigOpen, setChunkingConfigOpen] = useState(false);
const [chunkingFileName, setChunkingFileName] = useState("");
const [chunkingFileTema, setChunkingFileTema] = useState("");
@@ -123,10 +123,10 @@ export function FilesTab({
setDeleting(true);
if (fileToDelete) {
- // Eliminar archivo individual
+ // Delete single file
await api.deleteFile(fileToDelete, selectedTema || undefined);
} else {
- // Eliminar archivos seleccionados
+ // Delete selected files
const filesToDelete = Array.from(selectedFiles);
await api.deleteFiles(filesToDelete, selectedTema || undefined);
clearSelection();
@@ -159,9 +159,7 @@ export function FilesTab({
try {
setDownloading(true);
const filesToDownload = Array.from(selectedFiles);
- const zipName = selectedTema
- ? `${selectedTema}_archivos`
- : "archivos_seleccionados";
+ const zipName = selectedTema ? `${selectedTema}_files` : "selected_files";
await api.downloadMultipleFiles(
filesToDownload,
selectedTema || undefined,
@@ -234,7 +232,7 @@ export function FilesTab({
}
};
- // Filtrar archivos por término de búsqueda
+ // Filter files by search term
const filteredFiles = files.filter((file) =>
file.name.toLowerCase().includes(searchTerm.toLowerCase()),
);
@@ -250,7 +248,7 @@ export function FilesTab({
};
const formatDate = (dateString: string): string => {
- return new Date(dateString).toLocaleDateString("es-ES", {
+ return new Date(dateString).toLocaleDateString("en-US", {
year: "numeric",
month: "short",
day: "numeric",
@@ -262,15 +260,15 @@ export function FilesTab({
const getDeleteDialogProps = () => {
if (fileToDelete) {
return {
- title: "Eliminar archivo",
- message: `¿Estás seguro de que deseas eliminar el archivo "${fileToDelete}"?`,
+ title: "Delete file",
+ message: `Are you sure you want to delete "${fileToDelete}"?`,
fileList: [fileToDelete],
};
} else {
const filesToDelete = Array.from(selectedFiles);
return {
- title: "Eliminar archivos seleccionados",
- message: `¿Estás seguro de que deseas eliminar ${filesToDelete.length} archivo${filesToDelete.length > 1 ? "s" : ""}?`,
+ title: "Delete selected files",
+ message: `Are you sure you want to delete ${filesToDelete.length} file${filesToDelete.length > 1 ? "s" : ""}?`,
fileList: filesToDelete,
};
}
@@ -280,9 +278,7 @@ export function FilesTab({
return (
-
- Selecciona un dataroom para ver sus archivos
-
+
Select a dataroom to view its files
);
}
@@ -294,7 +290,7 @@ export function FilesTab({
- Procesando archivos con LandingAI...
+ Processing files with LandingAI…
@@ -305,7 +301,7 @@ export function FilesTab({
setSearchTerm(e.target.value)}
className="pl-10"
@@ -324,7 +320,7 @@ export function FilesTab({
className="gap-2"
>
- Descargar ({selectedFiles.size})
+ Download ({selectedFiles.size})
- Eliminar ({selectedFiles.size})
+ Delete ({selectedFiles.size})
>
)}
@@ -345,7 +341,7 @@ export function FilesTab({
className="gap-2"
>
- Subir archivo
+ Upload files
@@ -355,17 +351,17 @@ export function FilesTab({
{loading ? (
-
Cargando archivos...
+
Loading files…
) : filteredFiles.length === 0 ? (
{!selectedTema
- ? "Selecciona un dataroom para ver sus archivos"
+ ? "Select a dataroom to view its files"
: searchTerm
- ? "No se encontraron archivos"
- : "No hay archivos en este dataroom"}
+ ? "No files match your search"
+ : "This dataroom has no files yet"}
) : (
@@ -387,10 +383,10 @@ export function FilesTab({
}}
/>
-
Archivo
-
Tamaño
-
Modificado
-
Acciones
+
File
+
Size
+
Modified
+
Actions
@@ -418,7 +414,7 @@ export function FilesTab({
onClick={() => handlePreviewFile(file.name)}
disabled={loadingPreview}
className="h-8 w-8 p-0"
- title="Vista previa"
+ title="Preview"
>
@@ -427,7 +423,7 @@ export function FilesTab({
size="sm"
onClick={() => handleViewChunks(file.name)}
className="h-8 w-8 p-0"
- title="Ver chunks"
+ title="View chunks"
>
@@ -436,7 +432,7 @@ export function FilesTab({
size="sm"
onClick={() => handleStartChunking(file.name)}
className="h-8 w-8 p-0"
- title="Procesar con LandingAI"
+ title="Process with LandingAI"
>
@@ -446,7 +442,7 @@ export function FilesTab({
onClick={() => handleDownloadFile(file.name)}
disabled={downloading}
className="h-8 w-8 p-0"
- title="Descargar"
+ title="Download"
>
@@ -456,7 +452,7 @@ export function FilesTab({
onClick={() => handleDeleteFile(file.name)}
disabled={deleting}
className="h-8 w-8 p-0 text-red-600 hover:text-red-700 hover:bg-red-50"
- title="Eliminar"
+ title="Delete"
>
@@ -503,7 +499,7 @@ export function FilesTab({
tema={chunkFileTema}
/>
- {/* Modal de configuración de chunking con LandingAI */}
+ {/* LandingAI chunking config modal */}
setChunkingConfigOpen(false)}
diff --git a/frontend/src/components/PDFPreviewModal.tsx b/frontend/src/components/PDFPreviewModal.tsx
index 2002a5d..ed8e181 100644
--- a/frontend/src/components/PDFPreviewModal.tsx
+++ b/frontend/src/components/PDFPreviewModal.tsx
@@ -1,25 +1,20 @@
-import { useState, useEffect } from 'react'
+import { useState, useEffect } from "react";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
- DialogDescription
-} from '@/components/ui/dialog'
-import { Button } from '@/components/ui/button'
-import {
- Download,
- Loader2,
- FileText,
- ExternalLink
-} from 'lucide-react'
+ DialogDescription,
+} from "@/components/ui/dialog";
+import { Button } from "@/components/ui/button";
+import { Download, Loader2, FileText, ExternalLink } from "lucide-react";
interface PDFPreviewModalProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- fileUrl: string | null
- fileName: string
- onDownload?: () => void
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+ fileUrl: string | null;
+ fileName: string;
+ onDownload?: () => void;
}
export function PDFPreviewModal({
@@ -27,45 +22,40 @@ export function PDFPreviewModal({
onOpenChange,
fileUrl,
fileName,
- onDownload
+ onDownload,
}: PDFPreviewModalProps) {
- // Estado para manejar el loading del iframe
- const [loading, setLoading] = useState(true)
+ // Track iframe loading state
+ const [loading, setLoading] = useState(true);
- // Efecto para manejar el timeout del loading
+ // Hide loading if iframe never fires onLoad
useEffect(() => {
if (open && fileUrl) {
- setLoading(true)
+ setLoading(true);
- // Timeout para ocultar loading automáticamente después de 3 segundos
- // Algunos iframes no disparan onLoad correctamente
const timeout = setTimeout(() => {
- setLoading(false)
- }, 3000)
+ setLoading(false);
+ }, 3000);
- return () => clearTimeout(timeout)
+ return () => clearTimeout(timeout);
}
- }, [open, fileUrl])
+ }, [open, fileUrl]);
- // Manejar cuando el iframe termina de cargar
const handleIframeLoad = () => {
- setLoading(false)
- }
+ setLoading(false);
+ };
- // Abrir PDF en nueva pestaña
const openInNewTab = () => {
if (fileUrl) {
- window.open(fileUrl, '_blank')
+ window.open(fileUrl, "_blank");
}
- }
+ };
- // Reiniciar loading cuando cambia el archivo
const handleOpenChange = (open: boolean) => {
if (open) {
- setLoading(true)
+ setLoading(true);
}
- onOpenChange(open)
- }
+ onOpenChange(open);
+ };
return (
@@ -75,81 +65,68 @@ export function PDFPreviewModal({
{fileName}
-
- Vista previa del documento PDF
-
+ PDF preview
- {/* Barra de controles */}
+ {/* Controls */}
- Abrir en pestaña nueva
+ Open in new tab
- {/* Botón de descarga */}
+ {/* Download button */}
{onDownload && (
- Descargar
+ Download
)}
- {/* Área de visualización del PDF con iframe */}
-
+ {/* PDF iframe */}
+
{!fileUrl ? (
-
No se ha proporcionado un archivo para previsualizar
+
No file available for preview
) : (
<>
- {/* Indicador de carga */}
+ {/* Loading state */}
{loading && (
-
Cargando PDF...
+
Loading PDF…
)}
- {/*
- Iframe para mostrar el PDF
- El navegador maneja toda la visualización, zoom, scroll, etc.
- Esto muestra el PDF exactamente como se vería si lo abrieras directamente
- */}
>
)}
-
- {/* Footer con información */}
-
- {fileName}
-
- )
+ );
}
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx
index 55b8742..b390450 100644
--- a/frontend/src/components/Sidebar.tsx
+++ b/frontend/src/components/Sidebar.tsx
@@ -84,7 +84,7 @@ export function Sidebar({
const handleCreateDataroom = async () => {
const trimmed = newDataroomName.trim();
if (!trimmed) {
- setCreateError("El nombre es obligatorio");
+ setCreateError("Name is required");
return;
}
@@ -108,7 +108,7 @@ export function Sidebar({
setCreateError(
error instanceof Error
? error.message
- : "No se pudo crear el dataroom. Inténtalo nuevamente.",
+ : "Could not create the dataroom. Please try again.",
);
} finally {
setCreatingDataroom(false);
@@ -168,15 +168,15 @@ export function Sidebar({
tema: string,
e: React.MouseEvent
,
) => {
- e.stopPropagation(); // Evitar que se seleccione el tema al hacer clic en el icono
+ e.stopPropagation(); // Prevent selecting the dataroom when clicking delete
const confirmed = window.confirm(
- `¿Estás seguro de que deseas eliminar el dataroom "${tema}"?\n\n` +
- `Esto eliminará:\n` +
- `• El dataroom de la base de datos\n` +
- `• Todos los archivos del tema en Azure Blob Storage\n` +
- `• La colección "${tema}" en Qdrant (si existe)\n\n` +
- `Esta acción no se puede deshacer.`,
+ `Are you sure you want to delete the dataroom "${tema}"?\n\n` +
+ `This will remove:\n` +
+ `• The dataroom from the database\n` +
+ `• All files stored for this topic in Azure Blob Storage\n` +
+ `• The "${tema}" collection in Qdrant (if it exists)\n\n` +
+ `This action cannot be undone.`,
);
if (!confirmed) return;
@@ -191,10 +191,10 @@ export function Sidebar({
console.error(`Error deleting dataroom "${tema}":`, error);
// If dataroom deletion fails, fall back to legacy deletion
- // Eliminar todos los archivos del tema en Azure Blob Storage
+ // Delete all topic files in Azure Blob Storage
await api.deleteTema(tema);
- // Intentar eliminar la colección en Qdrant (si existe)
+ // Attempt to delete the Qdrant collection (if it exists)
try {
const collectionExists = await api.checkCollectionExists(tema);
if (collectionExists.exists) {
@@ -202,7 +202,7 @@ export function Sidebar({
}
} catch (collectionError) {
console.warn(
- `No se pudo eliminar la colección "${tema}" de Qdrant:`,
+ `Could not delete the "${tema}" collection from Qdrant:`,
collectionError,
);
}
@@ -216,9 +216,9 @@ export function Sidebar({
setSelectedTema(null);
}
} catch (error) {
- console.error(`Error eliminando dataroom "${tema}":`, error);
+ console.error(`Error deleting dataroom "${tema}":`, error);
alert(
- `Error al eliminar el dataroom: ${error instanceof Error ? error.message : "Error desconocido"}`,
+ `Unable to delete dataroom: ${error instanceof Error ? error.message : "Unknown error"}`,
);
} finally {
setDeletingTema(null);
@@ -251,9 +251,7 @@ export function Sidebar({
className="text-slate-400 hover:text-slate-100"
onClick={onToggleCollapse}
disabled={disabled}
- aria-label={
- collapsed ? "Expandir barra lateral" : "Contraer barra lateral"
- }
+ aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
>
{collapsed ? (
@@ -279,7 +277,7 @@ export function Sidebar({
)}
{renderWithTooltip(
- "Crear dataroom",
+ "Create",
- {!collapsed && Crear dataroom }
+ {!collapsed && Create }
,
)}
- {/* Lista de temas */}
+ {/* Dataroom list */}
{loading ? (
- {collapsed ? "..." : "Cargando..."}
+ {collapsed ? "..." : "Loading..."}
) : Array.isArray(temas) && temas.length > 0 ? (
temas.map((tema) => (
@@ -331,7 +329,7 @@ export function Sidebar({
onClick={(e) => handleDeleteTema(tema, e)}
disabled={deletingTema === tema || disabled}
className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 rounded hover:bg-red-500/20 opacity-0 group-hover:opacity-100 transition-opacity disabled:opacity-50"
- title="Eliminar dataroom y colección"
+ title="Delete dataroom and collection"
>
@@ -341,8 +339,8 @@ export function Sidebar({
) : (
{Array.isArray(temas) && temas.length === 0
- ? "No hay datarooms"
- : "Cargando datarooms..."}
+ ? "No datarooms found"
+ : "Loading datarooms..."}
)}
@@ -357,7 +355,7 @@ export function Sidebar({
>
{onNavigateToSchemas &&
renderWithTooltip(
- "Gestionar Schemas",
+ "Manage schemas",
- Gestionar Schemas
+ Manage Schemas
,
)}
{renderWithTooltip(
- "Actualizar datarooms",
+ "Refresh datarooms",
- Actualizar datarooms
+ Refresh datarooms
,
)}
@@ -403,14 +401,14 @@ export function Sidebar({
aria-describedby="create-dataroom-description"
>
- Crear dataroom
+ Create dataroom
- Define un nombre único para organizar tus archivos.
+ Choose a unique name to organize your files.