// Configuration Axios axios.defaults.baseURL = window.location.origin.includes('hf.space') ? window.location.origin : 'http://localhost:8000'; console.log("API base URL:", axios.defaults.baseURL); // Variables globales let uploadedFiles = []; const MAX_FILE_SIZE_MB = 50; const SUPPORTED_TYPES = ['pdf', 'docx', 'pptx', 'xlsx', 'jpg', 'jpeg', 'png']; // Éléments DOM const elements = { fileInput: document.getElementById('fileInput'), dropArea: document.getElementById('dropArea'), fileList: document.getElementById('fileList'), uploadStatus: document.getElementById('uploadStatus'), summaryFile: document.getElementById('summaryFile'), captionFile: document.getElementById('captionFile'), qaFile: document.getElementById('qaFile'), summarizeBtn: document.getElementById('summarizeBtn'), captionBtn: document.getElementById('captionBtn'), askBtn: document.getElementById('askBtn'), questionInput: document.getElementById('questionInput'), summaryResult: document.getElementById('summaryResult'), captionResult: document.getElementById('captionResult'), answerResult: document.getElementById('answerResult'), imagePreview: document.getElementById('imagePreview'), summarySpinner: document.getElementById('summarySpinner'), captionSpinner: document.getElementById('captionSpinner'), qaSpinner: document.getElementById('qaSpinner') }; // Initialisation document.addEventListener('DOMContentLoaded', () => { initVideoBackground(); setupEventListeners(); updateFileSelectors(); }); function initVideoBackground() { const video = document.getElementById('bg-video'); if (video) { try { video.playbackRate = 0.8; video.muted = true; video.playsInline = true; video.play().catch(e => console.log("Video play error:", e)); } catch (e) { console.log("Video initialization error:", e); } video.onerror = () => { document.body.style.background = "linear-gradient(135deg, #4a6fa5 0%, #166088 100%)"; }; } } function setupEventListeners() { // Gestion de l'upload if (elements.dropArea) { elements.dropArea.addEventListener('click', () => elements.fileInput.click()); elements.dropArea.addEventListener('dragover', handleDragOver); elements.dropArea.addEventListener('dragleave', handleDragLeave); elements.dropArea.addEventListener('drop', handleDrop); } elements.fileInput.addEventListener('change', handleFileSelect); // Boutons d'action if (elements.summarizeBtn) { elements.summarizeBtn.addEventListener('click', summarizeDocument); } if (elements.captionBtn) { elements.captionBtn.addEventListener('click', generateCaption); } if (elements.askBtn) { elements.askBtn.addEventListener('click', answerQuestion); } } // Gestion des fichiers function handleDragOver(e) { e.preventDefault(); elements.dropArea.style.borderColor = '#4a6fa5'; elements.dropArea.style.backgroundColor = 'rgba(74, 111, 165, 0.1)'; } function handleDragLeave() { elements.dropArea.style.borderColor = '#4a6fa5'; elements.dropArea.style.backgroundColor = 'rgba(74, 111, 165, 0.05)'; } function handleDrop(e) { e.preventDefault(); handleDragLeave(); if (e.dataTransfer.files.length) { elements.fileInput.files = e.dataTransfer.files; handleFiles(elements.fileInput.files); } } function handleFileSelect() { if (elements.fileInput.files.length) { handleFiles(elements.fileInput.files); } } async function handleFiles(files) { const validFiles = Array.from(files).filter(file => { const ext = file.name.split('.').pop().toLowerCase(); const isValidType = SUPPORTED_TYPES.includes(ext); const isValidSize = file.size <= MAX_FILE_SIZE_MB * 1024 * 1024; if (!isValidType) { showError(elements.uploadStatus, `Type non supporté: ${file.name}`); return false; } if (!isValidSize) { showError(elements.uploadStatus, `Fichier trop volumineux (max ${MAX_FILE_SIZE_MB}MB): ${file.name}`); return false; } return true; }); if (!validFiles.length) return; showLoading(elements.uploadStatus, `Upload de ${validFiles.length} fichier(s)...`); const formData = new FormData(); validFiles.forEach(file => formData.append('files', file)); try { const response = await axios.post('/api/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' }, timeout: 60000 }); uploadedFiles = [...uploadedFiles, ...response.data]; updateFileSelectors(); renderFileList(); showSuccess(elements.uploadStatus, `${validFiles.length} fichier(s) uploadé(s) avec succès !`); } catch (error) { handleUploadError(error); } finally { elements.fileInput.value = ''; } } function renderFileList() { if (!elements.fileList) return; if (uploadedFiles.length === 0) { elements.fileList.innerHTML = '

Aucun fichier uploadé

'; return; } elements.fileList.innerHTML = uploadedFiles.map(file => `
${getFileIcon(file.file_type)} ${file.file_name} ${file.file_type.toUpperCase()}
`).join(''); } function updateFileSelectors() { const selectors = [ { element: elements.summaryFile, types: ['pdf', 'docx', 'pptx', 'xlsx'] }, { element: elements.captionFile, types: ['jpg', 'jpeg', 'png'] }, { element: elements.qaFile, types: ['pdf', 'docx', 'pptx', 'xlsx', 'jpg', 'jpeg', 'png'] } ]; selectors.forEach(({ element, types }) => { if (!element) return; const currentValue = element.value; element.innerHTML = element.id === 'qaFile' ? '' : ``; uploadedFiles .filter(file => types.includes(file.file_type.toLowerCase())) .forEach(file => { const option = new Option( `${file.file_name} (${file.file_type.toUpperCase()})`, file.file_id ); element.add(option); }); element.value = currentValue; }); } // Fonctions de traitement async function summarizeDocument() { if (!elements.summaryFile || !elements.summaryResult) return; const fileId = elements.summaryFile.value; if (!fileId) { showError(elements.summaryResult, 'Veuillez sélectionner un document'); return; } showLoading(elements.summaryResult, 'Génération du résumé en cours...'); toggleSpinner(elements.summarySpinner, true); disableButton(elements.summarizeBtn, true); try { const response = await axios.post('/api/summarize', { file_id: fileId, max_length: 200 }, { timeout: 120000 }); elements.summaryResult.innerHTML = `

Résumé du document

${response.data.summary}
`; } catch (error) { handleProcessingError(error, elements.summaryResult, 'résumé'); } finally { toggleSpinner(elements.summarySpinner, false); disableButton(elements.summarizeBtn, false); } } async function generateCaption() { if (!elements.captionFile || !elements.captionResult) return; const fileId = elements.captionFile.value; if (!fileId) { showError(elements.captionResult, 'Veuillez sélectionner une image'); return; } // Afficher l'aperçu const file = uploadedFiles.find(f => f.file_id === fileId); if (file && elements.imagePreview) { try { const response = await axios.get(`/api/file/${fileId}`, { responseType: 'blob' }); const url = URL.createObjectURL(response.data); elements.imagePreview.innerHTML = `Image sélectionnée`; } catch (error) { console.error("Error loading image preview:", error); } } showLoading(elements.captionResult, 'Analyse de l\'image en cours...'); toggleSpinner(elements.captionSpinner, true); disableButton(elements.captionBtn, true); try { const response = await axios.post('/api/caption', { file_id: fileId }, { timeout: 60000 }); elements.captionResult.innerHTML = `

Description de l'image

${response.data.caption}

`; } catch (error) { handleProcessingError(error, elements.captionResult, 'description'); } finally { toggleSpinner(elements.captionSpinner, false); disableButton(elements.captionBtn, false); } } async function answerQuestion() { if (!elements.questionInput || !elements.answerResult) return; const question = elements.questionInput.value.trim(); if (!question) { showError(elements.answerResult, 'Veuillez saisir une question'); return; } const fileId = elements.qaFile ? elements.qaFile.value : null; showLoading(elements.answerResult, 'Recherche de la réponse...'); toggleSpinner(elements.qaSpinner, true); disableButton(elements.askBtn, true); try { const response = await axios.post('/api/answer', { question, file_id: fileId || undefined }, { timeout: 120000 }); elements.answerResult.innerHTML = `

Réponse

${response.data.answer}
`; } catch (error) { handleProcessingError(error, elements.answerResult, 'réponse'); } finally { toggleSpinner(elements.qaSpinner, false); disableButton(elements.askBtn, false); } } // Fonctions utilitaires function getFileIcon(fileType) { const icons = { pdf: '📄', docx: '📝', pptx: '📊', xlsx: '📈', jpg: '🖼️', jpeg: '🖼️', png: '🖼️' }; return icons[fileType.toLowerCase()] || '📁'; } function showLoading(element, message) { if (!element) return; element.innerHTML = `
${message}
`; } function showSuccess(element, message) { if (!element) return; element.innerHTML = `
✓ ${message}
`; if (element === elements.uploadStatus) { setTimeout(() => { element.innerHTML = ''; }, 3000); } } function showError(element, message) { if (!element) return; element.innerHTML = `
✗ ${message}
`; } function handleUploadError(error) { let message = 'Échec de l\'upload'; if (error.response) { message += `: ${error.response.data.detail || error.response.statusText}`; } else if (error.code === 'ECONNABORTED') { message = 'Délai d\'attente dépassé (60s) - essayez avec des fichiers plus petits'; } else if (error.message.includes('Network Error')) { message = 'Impossible de se connecter au serveur - vérifiez votre connexion'; } else { message += `: ${error.message}`; } showError(elements.uploadStatus, message); } function handleProcessingError(error, element, action) { let message = `Échec de la génération du ${action}`; if (error.response) { message += `: ${error.response.data.detail || error.response.statusText}`; } else if (error.code === 'ECONNABORTED') { message = `Délai d'attente dépassé pour le ${action}`; } else { message += `: ${error.message}`; } showError(element, message); } function toggleSpinner(spinnerElement, show) { if (spinnerElement) { spinnerElement.style.display = show ? 'block' : 'none'; } } function disableButton(buttonElement, disable) { if (buttonElement) { buttonElement.disabled = disable; buttonElement.style.opacity = disable ? 0.7 : 1; buttonElement.style.cursor = disable ? 'not-allowed' : 'pointer'; } } function openTab(tabName) { // Masquer tous les onglets document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); // Désactiver tous les boutons document.querySelectorAll('.tab-button').forEach(btn => { btn.classList.remove('active'); }); // Activer l'onglet sélectionné const tab = document.getElementById(tabName); if (tab) tab.classList.add('active'); // Activer le bouton sélectionné event.currentTarget.classList.add('active'); }