// Memory Module Detection QA Interface JavaScript const API_BASE_URL = 'http://localhost:5002'; let uploadedFile = null; // Initialize the application document.addEventListener('DOMContentLoaded', function() { initializeApp(); setupEventListeners(); }); function initializeApp() { checkApiStatus(); loadApiInfo(); } function setupEventListeners() { // File input change document.getElementById('fileInput').addEventListener('change', handleFileSelect); // Drag and drop const uploadArea = document.getElementById('uploadArea'); uploadArea.addEventListener('dragover', handleDragOver); uploadArea.addEventListener('dragleave', handleDragLeave); uploadArea.addEventListener('drop', handleDrop); // Click to upload (only on the upload area, not buttons inside it) uploadArea.addEventListener('click', function(event) { // Only trigger file input if clicking on the upload area itself, not buttons if (event.target === uploadArea || (event.target.closest('.upload-content') && !event.target.closest('button'))) { console.log('Upload area clicked, triggering file input'); const fileInput = document.getElementById('fileInput'); if (fileInput) { fileInput.click(); } } }); } async function checkApiStatus() { const statusElement = document.getElementById('apiStatus'); try { const response = await fetch(`${API_BASE_URL}/health`); if (response.ok) { const data = await response.json(); statusElement.className = 'status-indicator online'; statusElement.innerHTML = ' API Online'; } else { throw new Error('API not responding'); } } catch (error) { statusElement.className = 'status-indicator offline'; statusElement.innerHTML = ' API Offline'; } } async function loadApiInfo() { const apiInfoElement = document.getElementById('apiInfo'); try { const response = await fetch(`${API_BASE_URL}/api`); if (response.ok) { const data = await response.json(); displayApiInfo(data); } else { throw new Error('Failed to load API info'); } } catch (error) { apiInfoElement.innerHTML = '
Failed to load API information
'; } } function displayApiInfo(data) { const apiInfoElement = document.getElementById('apiInfo'); apiInfoElement.innerHTML = `

API Status

${data.message}

Version

${data.version}

Model Status

${data.model_loaded ? 'Loaded ✅' : 'Not Loaded ❌'}

Supported Formats

${data.supported_formats.join(', ')}

`; } function showUploadSection() { document.getElementById('uploadSection').style.display = 'block'; document.getElementById('uploadSection').scrollIntoView({ behavior: 'smooth' }); // Ensure the upload area is properly initialized initializeUploadArea(); } function initializeUploadArea() { const uploadArea = document.getElementById('uploadArea'); let fileInput = document.getElementById('fileInput'); // Completely recreate the file input element if (fileInput) { fileInput.remove(); } // Create a brand new file input const newFileInput = document.createElement('input'); newFileInput.type = 'file'; newFileInput.id = 'fileInput'; newFileInput.accept = 'image/*'; newFileInput.style.display = 'none'; newFileInput.multiple = false; // Insert the new file input into the DOM uploadArea.parentNode.insertBefore(newFileInput, uploadArea); // Clear any existing event listeners on upload area by cloning const newUploadArea = uploadArea.cloneNode(true); uploadArea.parentNode.replaceChild(newUploadArea, uploadArea); // Re-attach all event listeners to the new elements newFileInput.addEventListener('change', handleFileSelect); newUploadArea.addEventListener('dragover', handleDragOver); newUploadArea.addEventListener('dragleave', handleDragLeave); newUploadArea.addEventListener('drop', handleDrop); newUploadArea.addEventListener('click', function(event) { if (event.target === newUploadArea || (event.target.closest('.upload-content') && !event.target.closest('button'))) { console.log('Upload area clicked, triggering file input'); const currentFileInput = document.getElementById('fileInput'); if (currentFileInput) { currentFileInput.click(); } } }); console.log('Upload area completely reinitialized with fresh file input'); } function handleFileSelect(event) { console.log('File select event triggered'); const file = event.target.files[0]; if (file) { console.log('File selected:', file.name); handleFile(file); } else { console.log('No file selected'); } } function handleDragOver(event) { event.preventDefault(); event.stopPropagation(); event.currentTarget.classList.add('dragover'); } function handleDragLeave(event) { event.preventDefault(); event.stopPropagation(); event.currentTarget.classList.remove('dragover'); } function handleDrop(event) { event.preventDefault(); event.stopPropagation(); event.currentTarget.classList.remove('dragover'); const files = event.dataTransfer.files; if (files.length > 0) { handleFile(files[0]); } } function handleFile(file) { if (!file.type.startsWith('image/')) { alert('Please select an image file'); return; } uploadedFile = file; // Show file info with change file option const uploadArea = document.getElementById('uploadArea'); uploadArea.innerHTML = `

File selected: ${file.name}

Size: ${(file.size / 1024 / 1024).toFixed(2)} MB

`; // Show controls document.getElementById('uploadControls').style.display = 'block'; } function resetFileUpload() { uploadedFile = null; // Reset upload area HTML const uploadArea = document.getElementById('uploadArea'); uploadArea.innerHTML = `

Drag and drop an image here or click to select

Supported formats: PNG, JPG, JPEG, GIF, BMP

`; // Hide controls const uploadControls = document.getElementById('uploadControls'); uploadControls.style.display = 'none'; // Remove the "Upload Another" button if it exists const uploadAnotherBtn = uploadControls.querySelector('.upload-another'); if (uploadAnotherBtn) { uploadAnotherBtn.remove(); } // Hide results if showing document.getElementById('resultsSection').style.display = 'none'; // Reinitialize the upload area with fresh event listeners initializeUploadArea(); console.log('File upload reset completed'); } async function processUploadedImage() { if (!uploadedFile) { alert('Please select an image first'); return; } const confidence = 0.8; // Fixed 80% threshold showLoading('Processing uploaded image...'); try { const formData = new FormData(); formData.append('image', uploadedFile); formData.append('confidence', confidence); const response = await fetch(`${API_BASE_URL}/detect`, { method: 'POST', body: formData }); const result = await response.json(); hideLoading(); if (result.success) { displayResults(result, 'Uploaded Image Detection'); // Add option to upload another file addUploadAnotherOption(); } else { alert(`Detection failed: ${result.error}`); } } catch (error) { hideLoading(); alert(`Error: ${error.message}`); } } function addUploadAnotherOption() { const uploadControls = document.getElementById('uploadControls'); if (!uploadControls.querySelector('.upload-another')) { const uploadAnotherBtn = document.createElement('button'); uploadAnotherBtn.className = 'btn btn-secondary upload-another'; uploadAnotherBtn.style.marginLeft = '10px'; uploadAnotherBtn.innerHTML = ' Upload Another Image'; uploadAnotherBtn.onclick = resetFileUpload; uploadControls.appendChild(uploadAnotherBtn); } } async function testHardcodedImage() { showLoading('Testing hardcoded image...'); try { console.log(`Making request to: ${API_BASE_URL}/detect/hardcoded?confidence=0.8`); const response = await fetch(`${API_BASE_URL}/detect/hardcoded?confidence=0.8`); console.log('Response status:', response.status); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const result = await response.json(); console.log('Response data:', result); hideLoading(); if (result.success) { displayResults(result, 'Hardcoded Image Test'); } else { alert(`Test failed: ${result.error}`); } } catch (error) { hideLoading(); console.error('Hardcoded test error:', error); alert(`Error: ${error.message}`); } } function displayResults(result, title) { const resultsSection = document.getElementById('resultsSection'); const resultsContent = document.getElementById('resultsContent'); let detectionsHtml = ''; if (result.detections && result.detections.length > 0) { detectionsHtml = result.detections.map((detection, index) => `
Detection ${index + 1}: ${detection.class_name} ${(detection.confidence * 100).toFixed(1)}%
`).join(''); } else { detectionsHtml = '
No memory modules detected
'; } resultsContent.innerHTML = `

${title}

${new Date().toLocaleTimeString()}
${result.num_detections}
Detections
${(result.confidence_threshold * 100).toFixed(0)}%
Confidence
${result.success ? 'Success' : 'Failed'}
Status

Detected Memory Modules:

${detectionsHtml}
${result.annotated_image ? `

Annotated Image:

Annotated Result
` : ''}
`; resultsSection.style.display = 'block'; resultsSection.scrollIntoView({ behavior: 'smooth' }); } async function runAllTests() { showLoading('Running comprehensive tests...'); const testResults = []; // Test 1: API Health try { const response = await fetch(`${API_BASE_URL}/health`); const result = await response.json(); testResults.push({ name: 'API Health Check', success: response.ok && result.status === 'healthy', message: response.ok ? 'API is healthy' : 'API health check failed' }); } catch (error) { testResults.push({ name: 'API Health Check', success: false, message: `Error: ${error.message}` }); } // Test 2: Hardcoded Image try { const response = await fetch(`${API_BASE_URL}/detect/hardcoded`); const result = await response.json(); testResults.push({ name: 'Hardcoded Image Detection', success: result.success, message: result.success ? `Found ${result.num_detections} memory modules` : `Error: ${result.error}` }); } catch (error) { testResults.push({ name: 'Hardcoded Image Detection', success: false, message: `Error: ${error.message}` }); } // Test 3: API Information try { const response = await fetch(`${API_BASE_URL}/api`); const result = await response.json(); testResults.push({ name: 'API Information', success: response.ok && result.message, message: response.ok ? 'API info loaded successfully' : 'Failed to load API info' }); } catch (error) { testResults.push({ name: 'API Information', success: false, message: `Error: ${error.message}` }); } hideLoading(); displayTestResults(testResults); } function displayTestResults(testResults) { const testResultsSection = document.getElementById('testResultsSection'); const testResultsContent = document.getElementById('testResults'); const successCount = testResults.filter(test => test.success).length; const totalTests = testResults.length; const testsHtml = testResults.map(test => `

${test.name}

${test.message}

`).join(''); testResultsContent.innerHTML = `

Test Summary: ${successCount}/${totalTests} tests passed

${testsHtml} `; testResultsSection.style.display = 'block'; testResultsSection.scrollIntoView({ behavior: 'smooth' }); } function showLoading(message) { document.getElementById('loadingText').textContent = message; document.getElementById('loadingOverlay').style.display = 'flex'; } function hideLoading() { document.getElementById('loadingOverlay').style.display = 'none'; }