document.addEventListener('DOMContentLoaded', function() { // DOM elements const uploadForm = document.getElementById('uploadForm'); const filenamesTextarea = document.getElementById('filenames'); const uploadBtn = document.getElementById('uploadBtn'); const clearBtn = document.getElementById('clearBtn'); const clearResultsBtn = document.getElementById('clearResultsBtn'); const resultsSection = document.getElementById('resultsSection'); const resultsContent = document.getElementById('resultsContent'); const loadingSection = document.getElementById('loadingSection'); const configBadge = document.getElementById('configBadge'); const healthBadge = document.getElementById('healthBadge'); // Initialize the application init(); async function init() { await checkConfiguration(); await checkHealth(); setupEventListeners(); setupKeyboardShortcuts(); } function setupEventListeners() { // Form submission uploadForm.addEventListener('submit', handleUpload); // Clear buttons clearBtn.addEventListener('click', clearForm); clearResultsBtn.addEventListener('click', clearResults); // Auto-resize textarea filenamesTextarea.addEventListener('input', autoResizeTextarea); // Real-time validation filenamesTextarea.addEventListener('input', validateInput); } function setupKeyboardShortcuts() { document.addEventListener('keydown', function(e) { // Ctrl+Enter or Cmd+Enter to submit if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { e.preventDefault(); if (!uploadBtn.disabled) { handleUpload(e); } } // Escape to clear results if (e.key === 'Escape') { clearResults(); } }); } async function handleUpload(e) { e.preventDefault(); const filenames = filenamesTextarea.value.trim(); if (!filenames) { showError('Please enter at least one filename'); return; } setLoading(true); clearResults(); try { const formData = new FormData(); formData.append('filenames', filenames); const response = await fetch('/upload', { method: 'POST', body: formData }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.detail || `HTTP ${response.status}`); } const data = await response.json(); displayResults(data.results); } catch (error) { console.error('Upload error:', error); showError(`Upload failed: ${error.message}`); } finally { setLoading(false); } } function displayResults(results) { if (!results) { showError('No results received from server'); return; } resultsContent.innerHTML = ''; // Split results by lines and process each const lines = results.split('\n').filter(line => line.trim()); lines.forEach(line => { const resultDiv = document.createElement('div'); resultDiv.className = 'result-line'; // Determine result type and apply appropriate styling if (line.includes('✅')) { resultDiv.classList.add('result-success'); } else if (line.includes('❌')) { resultDiv.classList.add('result-error'); } else if (line.includes('⏩')) { resultDiv.classList.add('result-info'); } else { resultDiv.classList.add('result-warning'); } resultDiv.textContent = line; resultsContent.appendChild(resultDiv); }); resultsSection.style.display = 'block'; resultsSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } function showError(message) { resultsContent.innerHTML = ''; const errorDiv = document.createElement('div'); errorDiv.className = 'result-line result-error'; errorDiv.textContent = `❌ ${message}`; resultsContent.appendChild(errorDiv); resultsSection.style.display = 'block'; } function setLoading(isLoading) { if (isLoading) { loadingSection.style.display = 'block'; uploadBtn.disabled = true; uploadBtn.querySelector('.btn-text').textContent = 'Processing...'; } else { loadingSection.style.display = 'none'; uploadBtn.disabled = false; uploadBtn.querySelector('.btn-text').textContent = 'Start Upload'; } } function clearForm() { filenamesTextarea.value = ''; filenamesTextarea.style.height = 'auto'; validateInput(); filenamesTextarea.focus(); } function clearResults() { resultsSection.style.display = 'none'; resultsContent.innerHTML = ''; } function autoResizeTextarea() { filenamesTextarea.style.height = 'auto'; filenamesTextarea.style.height = filenamesTextarea.scrollHeight + 'px'; } function validateInput() { const value = filenamesTextarea.value.trim(); uploadBtn.disabled = !value; if (value) { uploadBtn.classList.remove('btn-disabled'); } else { uploadBtn.classList.add('btn-disabled'); } } async function checkConfiguration() { try { const response = await fetch('/config'); const config = await response.json(); const allConfigured = Object.values(config).every(status => status.includes('✅')); if (allConfigured) { configBadge.textContent = 'Ready'; configBadge.className = 'status-badge success'; } else { configBadge.textContent = 'Incomplete'; configBadge.className = 'status-badge warning'; } } catch (error) { console.error('Config check failed:', error); configBadge.textContent = 'Error'; configBadge.className = 'status-badge error'; } } async function checkHealth() { try { const response = await fetch('/health'); const health = await response.json(); if (health.status === 'healthy') { healthBadge.textContent = 'Healthy'; healthBadge.className = 'status-badge success'; } else { healthBadge.textContent = 'Issues'; healthBadge.className = 'status-badge warning'; } } catch (error) { console.error('Health check failed:', error); healthBadge.textContent = 'Error'; healthBadge.className = 'status-badge error'; } } // Refresh status indicators every 30 seconds setInterval(() => { checkConfiguration(); checkHealth(); }, 30000); // Show keyboard shortcuts hint on first visit if (!localStorage.getItem('keyboardHintShown')) { setTimeout(() => { showKeyboardHint(); localStorage.setItem('keyboardHintShown', 'true'); }, 2000); } function showKeyboardHint() { const hint = document.createElement('div'); hint.className = 'keyboard-hint'; hint.innerHTML = '💡 Tip: Use Ctrl+Enter to upload, Esc to clear results'; document.body.appendChild(hint); setTimeout(() => hint.classList.add('show'), 100); setTimeout(() => { hint.classList.remove('show'); setTimeout(() => document.body.removeChild(hint), 300); }, 4000); } // Add some visual feedback for better UX uploadBtn.addEventListener('mouseenter', function() { if (!this.disabled) { this.style.transform = 'translateY(-2px)'; } }); uploadBtn.addEventListener('mouseleave', function() { this.style.transform = 'translateY(0)'; }); // Initialize textarea validation validateInput(); });