// ============================================ // Network Security - Main JavaScript // ============================================ document.addEventListener('DOMContentLoaded', function() { initFileUpload(); initTrainingHandler(); initAnimations(); initDynamicWidths(); }); // ============================================ // Training Handler // ============================================ function initTrainingHandler() { const trainBtn = document.getElementById('train-btn'); if (!trainBtn) return; // Create Modal HTML if not exists if (!document.getElementById('success-modal')) { const modalHtml = ` `; document.body.insertAdjacentHTML('beforeend', modalHtml); // Modal Close Logic document.querySelector('.close-modal').addEventListener('click', () => { document.getElementById('success-modal').classList.remove('show'); // Optional: reload page when modal is closed to refresh any data // window.location.reload(); }); } trainBtn.addEventListener('click', async function() { if (!confirm('Are you sure you want to start model training? This may take a few minutes.')) { return; } const originalText = trainBtn.innerHTML; trainBtn.disabled = true; trainBtn.innerHTML = ' Training in Progress...'; try { showNotification('Training started. Please wait...', 'info'); const response = await fetch('/api/train', { method: 'POST' }); const data = await response.json(); if (response.ok) { // Show Modal const modal = document.getElementById('success-modal'); modal.classList.add('show'); // Reset button trainBtn.disabled = false; trainBtn.innerHTML = originalText; } else { throw new Error(data.detail || 'Training failed'); } } catch (error) { console.error('Training Error:', error); showNotification(`Training failed: ${error.message}`, 'error'); trainBtn.disabled = false; trainBtn.innerHTML = originalText; } }); } // ============================================ // File Upload Handling // ============================================ function initFileUpload() { const uploadZone = document.getElementById('upload-zone'); const fileInput = document.getElementById('file-input'); const fileInfo = document.getElementById('file-info'); const fileName = document.getElementById('file-name'); const removeBtn = document.getElementById('remove-file'); const submitBtn = document.getElementById('submit-btn'); const form = document.getElementById('upload-form'); if (!uploadZone) return; // Drag and drop ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { uploadZone.addEventListener(eventName, preventDefaults, false); }); function preventDefaults(e) { e.preventDefault(); e.stopPropagation(); } ['dragenter', 'dragover'].forEach(eventName => { uploadZone.addEventListener(eventName, () => { uploadZone.classList.add('dragover'); }, false); }); ['dragleave', 'drop'].forEach(eventName => { uploadZone.addEventListener(eventName, () => { uploadZone.classList.remove('dragover'); }, false); }); uploadZone.addEventListener('drop', handleDrop, false); function handleDrop(e) { const dt = e.dataTransfer; const files = dt.files; if (files.length > 0) { fileInput.files = files; handleFileSelect(files[0]); } } // File input change fileInput.addEventListener('change', function(e) { if (e.target.files.length > 0) { handleFileSelect(e.target.files[0]); } }); function handleFileSelect(file) { if (!file.name.endsWith('.csv')) { showNotification('Please upload a CSV file', 'error'); return; } fileName.textContent = file.name; uploadZone.style.display = 'none'; fileInfo.style.display = 'flex'; submitBtn.disabled = false; } // Remove file if (removeBtn) { removeBtn.addEventListener('click', function() { fileInput.value = ''; uploadZone.style.display = 'block'; fileInfo.style.display = 'none'; submitBtn.disabled = true; }); } // Form submit if (form) { form.addEventListener('submit', function(e) { submitBtn.innerHTML = ' Analyzing...'; submitBtn.disabled = true; }); } } // ============================================ // Notifications // ============================================ function showNotification(message, type = 'info') { const notification = document.createElement('div'); notification.className = `notification notification-${type}`; notification.innerHTML = ` ${message} `; document.body.appendChild(notification); setTimeout(() => { notification.classList.add('show'); }, 100); setTimeout(() => { notification.classList.remove('show'); setTimeout(() => notification.remove(), 300); }, 3000); } // ============================================ // Animations // ============================================ function initAnimations() { // Animate elements on scroll const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('animate-in'); observer.unobserve(entry.target); } }); }, observerOptions); document.querySelectorAll('.card').forEach(card => { observer.observe(card); }); // Animate metric circles document.querySelectorAll('.metric-circle').forEach(circle => { const progress = circle.style.getPropertyValue('--progress'); circle.style.setProperty('--progress', '0'); setTimeout(() => { circle.style.transition = 'all 1s ease-out'; circle.style.setProperty('--progress', progress); }, 300); }); } function initDynamicWidths() { const dynamicElements = document.querySelectorAll('[data-width]'); dynamicElements.forEach(el => { const width = el.getAttribute('data-width'); if (width) { // Apply immediately if it's not an animated element, or let CSS transitions handle it // We set it as a style property so the browser sees it as valid CSS setTimeout(() => { el.style.width = `${width}%`; }, 100); // Small delay to ensure transitions work if present } }); } // ============================================ // Utility Functions // ============================================ function formatNumber(num) { return new Intl.NumberFormat().format(num); } function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; }