// Memory Module Detection QA Interface JavaScript
const API_BASE_URL = 'http://localhost:5001';
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}
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 {
const response = await fetch(`${API_BASE_URL}/detect/hardcoded?confidence=0.8`);
const result = await response.json();
hideLoading();
if (result.success) {
displayResults(result, 'Hardcoded Image Test');
} else {
alert(`Test failed: ${result.error}`);
}
} catch (error) {
hideLoading();
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 = `
${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:
` : ''}
`;
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';
}