Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
import { useState, useRef } from "react"; | |
import API_CONFIG from "../../../config/api"; | |
/** | |
* Hook personnalisé pour gérer la sélection et l'upload de documents | |
* @returns {Object} - Méthodes et états pour la gestion des documents | |
*/ | |
export const useDocumentSelection = (onStartGeneration) => { | |
const [isDragging, setIsDragging] = useState(false); | |
const [uploadStatus, setUploadStatus] = useState(null); | |
const [isLoading, setIsLoading] = useState(false); | |
const [sessionId, setSessionId] = useState(null); | |
const [selectedDocument, setSelectedDocument] = useState(null); | |
const [isDefaultDocument, setIsDefaultDocument] = useState(false); | |
const [urlInput, setUrlInput] = useState(""); | |
const [urlSelected, setUrlSelected] = useState(false); | |
const fileInputRef = useRef(null); | |
const handleDragOver = (e) => { | |
e.preventDefault(); | |
setIsDragging(true); | |
}; | |
const handleDragLeave = () => { | |
setIsDragging(false); | |
}; | |
const handleClick = () => { | |
// Lors d'un clic sur la zone de fichier, seulement ouvrir le dialogue de sélection | |
// mais ne pas réinitialiser les autres options avant que l'utilisateur ne sélectionne réellement un fichier | |
fileInputRef.current.click(); | |
}; | |
const handleFileChange = (e) => { | |
const file = e.target.files[0]; | |
if (!file) return; | |
// Maintenant que l'utilisateur a choisi un fichier, réinitialiser les autres options | |
setUrlInput(""); | |
setUrlSelected(false); | |
setIsDefaultDocument(false); | |
setSessionId(null); // Reset session ID until upload completes | |
// Check if it's a PDF, TXT, HTML or MD | |
if ( | |
!file.name.endsWith(".pdf") && | |
!file.name.endsWith(".txt") && | |
!file.name.endsWith(".html") && | |
!file.name.endsWith(".md") | |
) { | |
setUploadStatus({ | |
success: false, | |
message: "Only PDF, TXT, HTML and MD files are accepted", | |
}); | |
return { success: false, error: "Invalid file format" }; | |
} | |
// Check file size limit (3MB = 3145728 bytes) | |
if (file.size > 1048576 * 2) { | |
setUploadStatus({ | |
success: false, | |
message: "File size exceeds the 2MB limit", | |
}); | |
return { success: false, error: "File too large" }; | |
} | |
handleFileUpload(file); | |
return { success: true }; | |
}; | |
const handleFileUpload = async (file) => { | |
setIsLoading(true); | |
setUploadStatus(null); | |
// Réinitialiser les sélections précédentes | |
setSelectedDocument(null); | |
try { | |
const formData = new FormData(); | |
formData.append("file", file); | |
const response = await fetch(`${API_CONFIG.BASE_URL}/upload`, { | |
method: "POST", | |
body: formData, | |
}); | |
const result = await response.json(); | |
if (response.ok) { | |
setUploadStatus({ | |
success: true, | |
message: "File uploaded successfully", | |
}); | |
setSessionId(result.session_id); | |
setSelectedDocument({ name: file.name }); | |
// Fichier uploadé avec succès, donc on désactive les autres options | |
setIsDefaultDocument(false); | |
setUrlSelected(false); | |
return { success: true }; | |
} else { | |
setUploadStatus({ | |
success: false, | |
message: result.detail || "Upload failed", | |
}); | |
return { success: false, error: result.detail || "Upload failed" }; | |
} | |
} catch (error) { | |
setUploadStatus({ | |
success: false, | |
message: "Server connection error", | |
}); | |
return { success: false, error: "Server connection error" }; | |
} finally { | |
setIsLoading(false); | |
} | |
}; | |
const handleDrop = async (e) => { | |
e.preventDefault(); | |
setIsDragging(false); | |
// Réinitialiser les autres options | |
setUrlInput(""); | |
setUrlSelected(false); | |
setIsDefaultDocument(false); | |
fileInputRef.current.value = ""; | |
setSessionId(null); // Reset session ID until upload completes | |
const file = e.dataTransfer.files[0]; | |
if (!file) { | |
setUploadStatus({ | |
success: false, | |
message: "No file detected", | |
}); | |
return { success: false, error: "No file detected" }; | |
} | |
// Check if it's a PDF, TXT, HTML or MD | |
if ( | |
!file.name.endsWith(".pdf") && | |
!file.name.endsWith(".txt") && | |
!file.name.endsWith(".html") && | |
!file.name.endsWith(".md") | |
) { | |
setUploadStatus({ | |
success: false, | |
message: "Only PDF, TXT, HTML and MD files are accepted", | |
}); | |
return { success: false, error: "Invalid file format" }; | |
} | |
// Check file size limit (3MB = 3145728 bytes) | |
if (file.size > 1048576 * 3) { | |
setUploadStatus({ | |
success: false, | |
message: "File size exceeds the 3MB limit", | |
}); | |
return { success: false, error: "File too large" }; | |
} | |
handleFileUpload(file); | |
return { success: true }; | |
}; | |
const handleDefaultDocClick = (doc) => { | |
// Réinitialiser les autres options | |
setUrlInput(""); | |
setUrlSelected(false); | |
fileInputRef.current.value = ""; | |
// Set the selected document | |
setSelectedDocument(doc); | |
if (doc) { | |
setSessionId(doc.id); | |
setIsDefaultDocument(true); | |
} else { | |
// Si on désélectionne | |
setIsDefaultDocument(false); | |
setSessionId(null); | |
} | |
}; | |
const handleGenerateClick = () => { | |
if (onStartGeneration && sessionId) { | |
onStartGeneration(sessionId, isDefaultDocument); | |
} else if (!sessionId) { | |
setUploadStatus({ | |
success: false, | |
message: "Please select or upload a document first", | |
}); | |
} | |
}; | |
const handleUrlInputChange = async (e) => { | |
const url = e.target.value; | |
setUrlInput(url); | |
// Ne pas réinitialiser les autres options tant que l'URL n'est pas valide | |
// Vérification simple d'URL valide avec regex | |
const urlRegex = | |
/^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/; | |
if (url && urlRegex.test(url)) { | |
// URL valide, maintenant réinitialiser les autres options | |
setIsDefaultDocument(false); | |
fileInputRef.current.value = ""; | |
setUrlSelected(true); | |
// Si l'URL semble valide et a une longueur suffisante, on la traite | |
if (url.length > 10) { | |
await handleUrlUpload(url); | |
} | |
} else if (url && url.length > 5) { | |
// Si l'URL n'est pas valide mais que l'utilisateur a saisi quelque chose | |
setUrlSelected(false); | |
setUploadStatus({ | |
success: false, | |
message: "Please enter a valid URL", | |
}); | |
} else { | |
// Si le champ est vide ou presque vide, réinitialiser complètement | |
setUrlSelected(false); | |
// Si on avait déjà une URL sélectionnée avant et qu'on vide le champ | |
// il faut aussi réinitialiser le document sélectionné et la session | |
if (urlSelected) { | |
setSelectedDocument(null); | |
setSessionId(null); | |
} | |
} | |
}; | |
const handleUrlUpload = async (url) => { | |
setIsLoading(true); | |
setUploadStatus(null); | |
// Réinitialiser les sélections précédentes | |
setSelectedDocument(null); | |
setIsDefaultDocument(false); | |
try { | |
// Création d'un FormData pour envoyer l'URL | |
const formData = new FormData(); | |
formData.append("url", url); | |
const response = await fetch(`${API_CONFIG.BASE_URL}/upload-url`, { | |
method: "POST", | |
body: formData, | |
}); | |
const result = await response.json(); | |
if (response.ok) { | |
setUploadStatus({ | |
success: true, | |
message: "Content from URL uploaded successfully", | |
}); | |
setSessionId(result.session_id); | |
// Extraire le domaine racine de l'URL | |
let domain = url; | |
try { | |
// Utiliser URL API pour extraire le hostname | |
const urlObj = new URL( | |
url.startsWith("http") ? url : `https://${url}` | |
); | |
domain = urlObj.hostname; | |
} catch (e) { | |
console.log("Error parsing URL, using original:", e); | |
} | |
setSelectedDocument({ name: url, domain: domain }); | |
setUrlSelected(true); | |
return { success: true }; | |
} else { | |
setUploadStatus({ | |
success: false, | |
message: result.detail || "URL processing failed", | |
}); | |
return { | |
success: false, | |
error: result.detail || "URL processing failed", | |
}; | |
} | |
} catch (error) { | |
setUploadStatus({ | |
success: false, | |
message: "Server connection error", | |
}); | |
return { success: false, error: "Server connection error" }; | |
} finally { | |
setIsLoading(false); | |
} | |
}; | |
return { | |
// États | |
isDragging, | |
isLoading, | |
sessionId, | |
selectedDocument, | |
isDefaultDocument, | |
urlInput, | |
urlSelected, | |
uploadStatus, | |
fileInputRef, | |
// Gestionnaires d'événements | |
handleDragOver, | |
handleDragLeave, | |
handleClick, | |
handleFileChange, | |
handleDrop, | |
handleDefaultDocClick, | |
handleGenerateClick, | |
handleUrlInputChange, | |
// Setters pour les mises à jour externes | |
setUploadStatus, | |
}; | |
}; | |