Spaces:
Sleeping
Sleeping
| document.addEventListener('DOMContentLoaded', () => { | |
| console.log("DOM entièrement chargé et analysé. Initialisation du script."); | |
| const uploadForm = document.getElementById('upload-form'); | |
| const imageFilesInput = document.getElementById('image-files'); | |
| const messageArea = document.getElementById('message-area'); | |
| const progressContainer = document.getElementById('progress-container'); | |
| const progressBarFill = document.getElementById('progress-bar'); | |
| const progressTextElement = document.getElementById('progress-text'); | |
| if (!uploadForm || !imageFilesInput || !messageArea || !progressContainer || !progressBarFill || !progressTextElement) { | |
| const errorMsg = "Un ou plusieurs éléments d'interface utilisateur sont manquants. L'application ne peut pas fonctionner correctement. Veuillez vérifier les IDs dans les fichiers HTML et JS."; | |
| console.error(errorMsg); | |
| if (messageArea) { | |
| messageArea.textContent = errorMsg; | |
| messageArea.className = 'error'; | |
| } | |
| alert(errorMsg); | |
| return; | |
| } | |
| console.log("Tous les éléments DOM principaux ont été trouvés."); | |
| let progressInterval = null; // Pour l'animation de la barre | |
| uploadForm.addEventListener('submit', async (event) => { | |
| console.log("Événement 'submit' du formulaire capturé."); | |
| event.preventDefault(); | |
| console.log("event.preventDefault() a été appelé."); | |
| // Nettoyer l'intervalle précédent s'il existe | |
| if (progressInterval) { | |
| clearInterval(progressInterval); | |
| progressInterval = null; | |
| } | |
| try { | |
| messageArea.textContent = ''; | |
| messageArea.className = ''; | |
| const files = imageFilesInput.files; | |
| const numFiles = files.length; | |
| console.log(`Nombre de fichiers sélectionnés : ${numFiles}`); | |
| if (numFiles === 0) { | |
| messageArea.textContent = 'Veuillez sélectionner au moins une image.'; | |
| messageArea.classList.add('error'); | |
| console.warn("Aucun fichier sélectionné, soumission annulée."); | |
| return; | |
| } | |
| console.log("Configuration de la barre de progression..."); | |
| progressTextElement.textContent = `Préparation de ${numFiles} image(s)...`; | |
| progressBarFill.style.width = '0%'; // Réinitialiser | |
| progressBarFill.classList.remove('processing-animation'); // Assurer que l'ancienne classe d'animation est retirée | |
| progressBarFill.classList.remove('determinate'); | |
| progressBarFill.textContent = ''; | |
| progressContainer.style.display = 'block'; | |
| // Démarrer une progression visuelle (même si elle n'est pas parfaitement synchronisée) | |
| let currentProgress = 0; | |
| progressBarFill.style.width = '5%'; // Départ initial | |
| progressTextElement.textContent = `Traitement de ${numFiles} image(s) en cours... (Étape 1/3 Préparation)`; | |
| // Ajout de la classe pour une animation CSS douce vers 90% | |
| // L'animation CSS se chargera d'aller vers la largeur cible | |
| setTimeout(() => { | |
| progressBarFill.classList.add('processing-animation'); | |
| progressBarFill.style.width = '20%'; // Déclencheur pour l'animation CSS qui pourrait aller plus loin | |
| progressTextElement.textContent = `Traitement de ${numFiles} image(s) en cours... (Étape 2/3 Envoi et IA)`; | |
| }, 100); // Petit délai pour que le 5% initial soit rendu | |
| const formData = new FormData(); | |
| for (const file of files) { | |
| formData.append('files', file); | |
| } | |
| console.log("FormData construit."); | |
| console.log("Début de la requête fetch vers /api/upload-images/..."); | |
| const response = await fetch('/api/upload-images/', { | |
| method: 'POST', | |
| body: formData, | |
| }); | |
| console.log(`Réponse reçue du serveur : ${response.status} ${response.statusText}`); | |
| // Arrêter l'animation de progression "en cours" et préparer pour l'état final | |
| progressBarFill.classList.remove('processing-animation'); // Retirer l'animation en cours | |
| if (progressInterval) { // Au cas où un intervalle serait utilisé | |
| clearInterval(progressInterval); | |
| progressInterval = null; | |
| } | |
| if (response.ok) { | |
| console.log("Réponse OK. Traitement du blob ZIP."); | |
| progressTextElement.textContent = `Traitement de ${numFiles} image(s) terminé. Préparation du téléchargement... (Étape 3/3)`; | |
| progressBarFill.style.width = '95%'; // Presque terminé | |
| const blob = await response.blob(); | |
| const contentDisposition = response.headers.get('content-disposition'); | |
| let filename = "captions_output.zip"; | |
| if (contentDisposition) { | |
| const filenameMatch = contentDisposition.match(/filename="?(.+)"?/i); | |
| if (filenameMatch && filenameMatch.length === 2) | |
| filename = filenameMatch[1].replace(/^"|"$/g, ''); // Enlever les guillemets | |
| } | |
| console.log(`Nom du fichier ZIP à télécharger : ${filename}`); | |
| const link = document.createElement('a'); | |
| link.href = URL.createObjectURL(blob); | |
| link.download = filename; | |
| document.body.appendChild(link); | |
| link.click(); | |
| document.body.removeChild(link); | |
| URL.revokeObjectURL(link.href); | |
| console.log("Téléchargement du ZIP initié."); | |
| messageArea.textContent = `${numFiles} image(s) traitée(s). Le fichier ZIP '${filename}' est en cours de téléchargement.`; | |
| messageArea.classList.add('success'); | |
| progressBarFill.style.width = '100%'; | |
| progressBarFill.classList.add('determinate'); | |
| progressBarFill.textContent = 'Terminé !'; | |
| progressTextElement.textContent = "Opération terminée avec succès !"; | |
| console.log("Interface utilisateur mise à jour pour le succès."); | |
| } else { | |
| console.error(`Erreur HTTP : ${response.status} ${response.statusText}`); | |
| let errorDetail = `Erreur ${response.status}.`; | |
| try { | |
| const errorResult = await response.json(); | |
| if (errorResult && errorResult.detail) { | |
| errorDetail = errorResult.detail; | |
| } | |
| } catch (e) { | |
| const errorText = await response.text().catch(() => "Impossible de lire le corps de l'erreur."); | |
| errorDetail += ` ${errorText.substring(0, 300)}`; | |
| } | |
| messageArea.textContent = `Une erreur est survenue : ${errorDetail}`; | |
| console.error(`Détail de l'erreur du serveur : ${errorDetail}`); | |
| messageArea.classList.add('error'); | |
| if (progressContainer) progressContainer.style.display = 'none'; | |
| } | |
| } catch (error) { | |
| console.error('Erreur globale dans le gestionnaire de soumission :', error); | |
| messageArea.textContent = 'Une erreur critique est survenue dans le script client. Vérifiez la console du navigateur.'; | |
| messageArea.classList.add('error'); | |
| if (progressContainer) progressContainer.style.display = 'none'; | |
| if (progressInterval) { | |
| clearInterval(progressInterval); | |
| progressInterval = null; | |
| } | |
| progressBarFill.classList.remove('processing-animation'); | |
| } | |
| }); | |
| console.log("Gestionnaire d'événement 'submit' attaché."); | |
| }); |