const uploadZone = document.getElementById('uploadZone'); const fileInput = document.getElementById('fileInput'); const fileList = document.getElementById('fileList'); const startBtn = document.getElementById('startBtn'); const requirementInput = document.getElementById('requirementInput'); const statusDot = document.getElementById('statusDot'); const statusText = document.getElementById('statusText'); const logOutput = document.getElementById('logOutput'); const reportContainer = document.getElementById('reportContainer'); const galleryContainer = document.getElementById('galleryContainer'); let isRunning = false; let pollingInterval = null; let currentSessionId = null; // --- Upload Logic --- if (uploadZone) { uploadZone.addEventListener('dragover', (e) => { e.preventDefault(); uploadZone.classList.add('dragover'); }); uploadZone.addEventListener('dragleave', () => uploadZone.classList.remove('dragover')); uploadZone.addEventListener('drop', (e) => { e.preventDefault(); uploadZone.classList.remove('dragover'); handleFiles(e.dataTransfer.files); }); } if (fileInput) { fileInput.addEventListener('change', (e) => handleFiles(e.target.files)); } async function handleFiles(files) { if (files.length === 0) return; fileList.innerHTML = ''; const formData = new FormData(); for (const file of files) { formData.append('files', file); const fileItem = document.createElement('div'); fileItem.innerText = `📄 ${file.name}`; fileItem.style.fontSize = '0.8rem'; fileItem.style.color = '#fff'; fileList.appendChild(fileItem); } try { const res = await fetch('/api/upload', { method: 'POST', body: formData }); if (res.ok) { const data = await res.json(); console.log('Upload success:', data); } else { alert('Upload failed'); } } catch (e) { console.error(e); alert('Upload failed'); } } // --- Start Analysis --- if (startBtn) { startBtn.addEventListener('click', async () => { if (isRunning) return; const requirement = requirementInput.value.trim(); if (!requirement) { alert('Please enter analysis requirement'); return; } setRunningState(true); try { const res = await fetch('/api/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ requirement }) }); if (res.ok) { const data = await res.json(); currentSessionId = data.session_id; // Store Session ID console.log("Started Session:", currentSessionId); startPolling(); switchTab('logs'); } else { const err = await res.json(); alert('Failed to start: ' + err.detail); setRunningState(false); } } catch (e) { console.error(e); alert('Error starting analysis'); setRunningState(false); } }); } function setRunningState(running) { isRunning = running; startBtn.disabled = running; startBtn.innerHTML = running ? ' Running...' : ' Start Analysis'; if (running) { statusDot.className = 'dot running'; statusText.innerText = 'Analysis in Progress'; } else { statusDot.className = 'dot done'; statusText.innerText = 'Completed'; } } // --- Status Polling --- function startPolling() { if (pollingInterval) clearInterval(pollingInterval); if (!currentSessionId) return; pollingInterval = setInterval(async () => { try { const res = await fetch(`/api/status?session_id=${currentSessionId}`); if (!res.ok) return; const data = await res.json(); // Update Logs logOutput.innerText = data.log || "Waiting for logs..."; // Auto scroll to bottom const term = document.querySelector('.terminal-window'); if (term) term.scrollTop = term.scrollHeight; if (!data.is_running && isRunning) { // Just finished setRunningState(false); clearInterval(pollingInterval); if (data.has_report) { loadReport(); loadGallery(); // Load images when done switchTab('report'); } } } catch (e) { console.error('Polling error', e); } }, 2000); } async function loadReport() { if (!currentSessionId) return; try { const res = await fetch(`/api/report?session_id=${currentSessionId}`); const data = await res.json(); // Render Markdown reportContainer.innerHTML = marked.parse(data.content); // Fix images relative path for display if needed // The backend should return a base_path or we handle it here if (data.base_path) { // Backend already handled replacement? // The backend returns content with updated paths. } } catch (e) { reportContainer.innerHTML = '
Failed to load report.
'; console.error(e); } } async function loadGallery() { if (!currentSessionId) return; // Switch to gallery view logic if we were already there // But this is just data loading try { const res = await fetch(`/api/figures?session_id=${currentSessionId}`); const data = await res.json(); const galleryGrid = document.getElementById('galleryContainer'); if (!data.figures || data.figures.length === 0) { galleryGrid.innerHTML = `No images generated in this session.
${fig.description || 'No description'}
${fig.analysis ? `