// DocTags Application State Management const appState = { activeTasks: {}, pollingInterval: null, generatedOutputs: { visualizer: null, extractor: false } }; // UI Helper Functions const ui = { show(elementId) { document.getElementById(elementId).classList.remove('hidden'); }, hide(elementId) { document.getElementById(elementId).classList.add('hidden'); }, setText(elementId, text) { document.getElementById(elementId).textContent = text; }, setHtml(elementId, html) { document.getElementById(elementId).innerHTML = html; }, getValue(elementId) { return document.getElementById(elementId).value; }, setValue(elementId, value) { document.getElementById(elementId).value = value; }, disable(elementId) { document.getElementById(elementId).disabled = true; }, enable(elementId) { document.getElementById(elementId).disabled = false; } }; // PDF Preview Functions function loadPDFPreview() { const pdfFile = ui.getValue('pdf_file'); const pageNum = ui.getValue('page_num'); if (!pdfFile) { ui.hide('pdf-preview-container'); return; } ui.setText('preview-page-num', pageNum); ui.setValue('preview-page-input', pageNum); const previewImg = document.getElementById('pdf-preview-image'); previewImg.src = `/pdf-preview/${encodeURIComponent(pdfFile)}/${pageNum}`; ui.show('pdf-preview-container'); previewImg.onerror = function() { this.alt = 'Failed to load PDF preview'; console.error('Failed to load PDF preview'); }; } function changePreviewPage(delta) { const currentPage = parseInt(ui.getValue('page_num')); const newPage = Math.max(1, currentPage + delta); ui.setValue('page_num', newPage); loadPDFPreview(); } function goToPreviewPage() { const pageInput = document.getElementById('preview-page-input'); const pageNum = parseInt(pageInput.value); if (pageNum && pageNum > 0) { ui.setValue('page_num', pageNum); loadPDFPreview(); } else { pageInput.value = ui.getValue('page_num'); } } // Tab Management function switchTab(tabName) { // Hide all tab contents and deactivate buttons document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active')); document.querySelectorAll('.tab-button').forEach(button => button.classList.remove('active')); // Show selected tab document.getElementById(tabName + '-tab').classList.add('active'); event.target.classList.add('active'); // Show previously generated content if (tabName === 'analyzer') { loadPDFPreview(); } else if (tabName === 'visualizer' && appState.generatedOutputs.visualizer) { document.getElementById('result-image').src = appState.generatedOutputs.visualizer + '?t=' + Date.now(); ui.show('image-container'); } else if (tabName === 'extractor' && appState.generatedOutputs.extractor) { loadExtractedImages(); } } // Progress Management function updateProgress(completedSteps) { for (let i = 1; i <= 3; i++) { const stepIndicator = document.getElementById(`step-${i}`); const connector = document.getElementById(`connector-${i}`); if (i <= completedSteps) { stepIndicator.classList.add('completed'); stepIndicator.classList.remove('active'); if (connector) connector.classList.add('completed'); } else if (i === completedSteps + 1) { stepIndicator.classList.add('active'); stepIndicator.classList.remove('completed'); } else { stepIndicator.classList.remove('completed', 'active'); if (connector) connector.classList.remove('completed'); } } } // Task Management function startPolling() { if (!appState.pollingInterval) { appState.pollingInterval = setInterval(pollTasks, 1000); } } function stopPolling() { if (Object.keys(appState.activeTasks).length === 0 && appState.pollingInterval) { clearInterval(appState.pollingInterval); appState.pollingInterval = null; } } async function pollTasks() { for (const taskId in appState.activeTasks) { try { const response = await fetch(`/task-status/${taskId}`); const data = await response.json(); // Debug log console.log(`Task ${taskId} status:`, data); updateTaskStatus(taskId, data); } catch (error) { console.error('Error polling task:', error); } } } function updateTaskStatus(taskId, data) { const taskInfo = appState.activeTasks[taskId]; const statusElement = document.getElementById(`${taskInfo.type}-status`); if (data.done) { if (data.success) { handleTaskSuccess(taskId, taskInfo, data, statusElement); } else { handleTaskFailure(taskId, data, statusElement); } delete appState.activeTasks[taskId]; stopPolling(); } else { ui.setHtml(`${taskInfo.type}-status`, '
Running...'); ui.show(`${taskInfo.type}-status`); } } function handleTaskSuccess(taskId, taskInfo, data, statusElement) { ui.setHtml(`${taskInfo.type}-status`, '✓ Completed successfully!'); ui.show(`${taskInfo.type}-status`); ui.enable(`${taskInfo.type}-btn`); // Display output ui.setText('output', data.output); ui.show('output'); // Handle specific task types if (taskInfo.type === 'visualizer' && data.image_file) { appState.generatedOutputs.visualizer = '/' + data.image_file; document.getElementById('result-image').src = appState.generatedOutputs.visualizer + '?t=' + Date.now(); ui.show('image-container'); } else if (taskInfo.type === 'extractor') { setTimeout(loadExtractedImages, 1000); } // Update progress const progressMap = { 'analyzer': 1, 'visualizer': 2, 'extractor': 3 }; updateProgress(progressMap[taskInfo.type]); // Enable next steps if (taskInfo.type === 'analyzer') { ui.enable('visualizer-btn'); } else if (taskInfo.type === 'visualizer') { ui.enable('extractor-btn'); } } function handleTaskFailure(taskId, data, statusElement) { const taskInfo = appState.activeTasks[taskId]; ui.setHtml(`${taskInfo.type}-status`, '✗ Failed: ' + (data.error || 'Unknown error') + ''); ui.show(`${taskInfo.type}-status`); ui.enable(`${taskInfo.type}-btn`); ui.setText('output', 'Error: ' + (data.error || 'Unknown error')); ui.show('output'); } // Script Execution async function runScript(script) { const pdfFile = ui.getValue('pdf_file'); const pageNum = ui.getValue('page_num'); const adjust = document.getElementById('adjust').checked; if (!pdfFile) { alert('Please select a PDF file'); return; } // Disable button and show status ui.disable(`${script}-btn`); ui.setHtml(`${script}-status`, 'Starting...'); ui.show(`${script}-status`); ui.hide('output'); // Reset outputs for analyzer if (script === 'analyzer') { ui.hide('image-container'); ui.hide('extracted-images-container'); appState.generatedOutputs = { visualizer: null, extractor: false }; ui.disable('visualizer-btn'); ui.disable('extractor-btn'); updateProgress(0); } // Create form data const formData = new FormData(); formData.append('pdf_file', pdfFile); formData.append('page_num', pageNum); formData.append('adjust', adjust); try { const response = await fetch(`/run-${script}`, { method: 'POST', body: formData }); const data = await response.json(); if (data.success && data.task_id) { appState.activeTasks[data.task_id] = { type: script, pageNum: pageNum }; startPolling(); ui.setText('output', data.message || 'Task started, please wait...'); ui.show('output'); } else { throw new Error(data.error || 'Failed to start task'); } } catch (error) { ui.setHtml(`${script}-status`, '✗ ' + error.message + ''); ui.enable(`${script}-btn`); ui.setText('output', 'Error: ' + error.message); ui.show('output'); } } // Image Gallery Functions async function loadExtractedImages() { const imageGallery = document.getElementById('extracted-images-gallery'); try { const response = await fetch('/results/pictures/index.html'); if (!response.ok) throw new Error('No extracted images found'); const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const imageCards = doc.querySelectorAll('.picture-card'); if (imageCards.length === 0) { imageGallery.innerHTML = '${captionText}
` : ''}${coordsText}
${data.cwd}${data.python_version}${data.missing_scripts.join(', ')}