2025-12-04 13:43:57 -07:00
|
|
|
const dropArea = document.getElementById('drop-area')
|
|
|
|
|
const fileInput = document.getElementById('fileElem')
|
|
|
|
|
|
|
|
|
|
// Prevent default drag behaviors
|
|
|
|
|
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
|
|
|
|
dropArea.addEventListener(eventName, preventDefaults, false)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function preventDefaults(e) {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
e.stopPropagation()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Highlight drop area on dragover
|
|
|
|
|
;['dragenter', 'dragover'].forEach(eventName => {
|
|
|
|
|
dropArea.addEventListener(eventName, () => dropArea.classList.add('highlight'), false)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
;['dragleave', 'drop'].forEach(eventName => {
|
|
|
|
|
dropArea.addEventListener(eventName, () => dropArea.classList.remove('highlight'), false)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Handle dropped files
|
|
|
|
|
dropArea.addEventListener('drop', e => {
|
|
|
|
|
const dt = e.dataTransfer
|
|
|
|
|
const files = dt.files
|
|
|
|
|
handleFiles(files)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Handle selected files from input
|
|
|
|
|
fileInput.addEventListener('change', e => {
|
|
|
|
|
handleFiles(fileInput.files)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function handleFiles(files) {
|
|
|
|
|
if (!files || files.length === 0) return
|
|
|
|
|
const file = files[0]
|
|
|
|
|
|
|
|
|
|
if (!file.name.endsWith('.zip')) {
|
|
|
|
|
alert('Please upload a ZIP file.')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uploadFile(file)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function uploadFile(file) {
|
|
|
|
|
const url = 'http://localhost:8000/upload'
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
formData.append('file', file)
|
|
|
|
|
|
|
|
|
|
dropArea.innerHTML = `<p>Uploading ${file.name}...</p>`
|
|
|
|
|
|
|
|
|
|
fetch(url, {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
body: formData
|
|
|
|
|
})
|
|
|
|
|
.then(async response => {
|
|
|
|
|
const contentType = response.headers.get('Content-Type')
|
|
|
|
|
|
|
|
|
|
// Check if content type includes text/plain (for QC failure report)
|
|
|
|
|
if (contentType && contentType.includes('text/plain')) {
|
|
|
|
|
// QC Failed - download report
|
|
|
|
|
const blob = await response.blob()
|
|
|
|
|
const link = document.createElement('a')
|
|
|
|
|
link.href = window.URL.createObjectURL(blob)
|
|
|
|
|
link.download = 'QC_report.txt'
|
|
|
|
|
link.click()
|
|
|
|
|
dropArea.innerHTML = `<p>QC failed. Report downloaded.</p>`
|
|
|
|
|
} else if (contentType && contentType.includes('application/json')) {
|
|
|
|
|
// QC Passed - show success and VerofyMapID input
|
|
|
|
|
const data = await response.json()
|
|
|
|
|
if (data.message === 'success') {
|
|
|
|
|
showVerofyMapIdInput()
|
|
|
|
|
} else {
|
|
|
|
|
dropArea.innerHTML = `<p>Unexpected response from server.</p>`
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Unknown response type, try to handle as text
|
|
|
|
|
const text = await response.text()
|
|
|
|
|
dropArea.innerHTML = `<p>Unexpected response: ${text.substring(0, 100)}</p>`
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
console.error('Upload error:', error)
|
|
|
|
|
dropArea.innerHTML = `<p>Upload failed. Check console.</p>`
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showVerofyMapIdInput() {
|
|
|
|
|
dropArea.innerHTML = `
|
|
|
|
|
<div style="padding: 20px;">
|
|
|
|
|
<p style="color: green; font-weight: bold; margin-bottom: 15px;">
|
|
|
|
|
Your files have passed QC!
|
|
|
|
|
</p>
|
2025-12-22 16:15:50 -07:00
|
|
|
<p style="margin-bottom: 15px; font-size: 14px;">
|
|
|
|
|
Please provide your Verofy credentials and Map ID to upload:
|
|
|
|
|
</p>
|
|
|
|
|
|
|
|
|
|
<div style="margin-bottom: 10px;">
|
|
|
|
|
<label style="display: block; margin-bottom: 5px; font-weight: bold;">Verofy Email:</label>
|
|
|
|
|
<input type="email" id="verofyEmail" placeholder="your.email@example.com"
|
|
|
|
|
style="padding: 8px; width: 300px; border: 1px solid #ccc; border-radius: 4px;" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div style="margin-bottom: 10px;">
|
|
|
|
|
<label style="display: block; margin-bottom: 5px; font-weight: bold;">Verofy Password:</label>
|
|
|
|
|
<input type="password" id="verofyPassword" placeholder="Your password"
|
|
|
|
|
style="padding: 8px; width: 300px; border: 1px solid #ccc; border-radius: 4px;" />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
|
|
|
<label style="display: block; margin-bottom: 5px; font-weight: bold;">Verofy Map ID:</label>
|
|
|
|
|
<input type="number" id="verofyMapId" placeholder="Enter Map ID (e.g., 15685)"
|
|
|
|
|
style="padding: 8px; width: 300px; border: 1px solid #ccc; border-radius: 4px;" />
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-12-04 13:43:57 -07:00
|
|
|
<button onclick="submitMapId()"
|
|
|
|
|
style="padding: 10px 20px; background: #007BFF; color: white; border: none; border-radius: 5px; cursor: pointer;">
|
2025-12-22 16:15:50 -07:00
|
|
|
Upload to Verofy
|
2025-12-04 13:43:57 -07:00
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-22 16:15:50 -07:00
|
|
|
async function submitMapId() {
|
|
|
|
|
const emailInput = document.getElementById('verofyEmail')
|
|
|
|
|
const passwordInput = document.getElementById('verofyPassword')
|
2025-12-04 13:43:57 -07:00
|
|
|
const mapIdInput = document.getElementById('verofyMapId')
|
2025-12-22 16:15:50 -07:00
|
|
|
|
|
|
|
|
const email = emailInput.value
|
|
|
|
|
const password = passwordInput.value
|
2025-12-04 13:43:57 -07:00
|
|
|
const mapId = mapIdInput.value
|
|
|
|
|
|
2025-12-22 16:15:50 -07:00
|
|
|
// Validate inputs
|
|
|
|
|
if (!email || email.trim() === '') {
|
|
|
|
|
alert('Please enter your Verofy email')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!password || password.trim() === '') {
|
|
|
|
|
alert('Please enter your Verofy password')
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-04 13:43:57 -07:00
|
|
|
if (!mapId || mapId.trim() === '') {
|
2025-12-22 16:15:50 -07:00
|
|
|
alert('Please enter a Verofy Map ID')
|
2025-12-04 13:43:57 -07:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-22 16:15:50 -07:00
|
|
|
// Show uploading status
|
2025-12-04 13:43:57 -07:00
|
|
|
dropArea.innerHTML = `
|
2025-12-22 16:15:50 -07:00
|
|
|
<p style="color: blue; font-weight: bold;">
|
|
|
|
|
Uploading to Verofy (Map ID: ${mapId})...<br/>
|
|
|
|
|
Please wait, this may take a few minutes.
|
2025-12-04 13:43:57 -07:00
|
|
|
</p>
|
|
|
|
|
`
|
|
|
|
|
|
2025-12-22 16:15:50 -07:00
|
|
|
// Send credentials and mapid to backend to trigger Verofy upload
|
|
|
|
|
try {
|
|
|
|
|
const response = await fetch('http://localhost:8000/push-to-verofy', {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
},
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
mapId: parseInt(mapId),
|
|
|
|
|
verofyEmail: email,
|
|
|
|
|
verofyPassword: password
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const data = await response.json()
|
|
|
|
|
|
|
|
|
|
if (response.ok && data.success) {
|
|
|
|
|
// Upload successful - show success message
|
|
|
|
|
dropArea.innerHTML = `
|
|
|
|
|
<p style="color: green; font-weight: bold;">
|
|
|
|
|
Success! Uploaded to Verofy Map ID ${mapId}.
|
|
|
|
|
</p>
|
|
|
|
|
<p style="font-size: 14px; margin-top: 10px;">
|
|
|
|
|
${JSON.stringify(data.uploaded, null, 2)}
|
|
|
|
|
</p>
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
// Show celebration overlay
|
|
|
|
|
showCelebration()
|
|
|
|
|
} else {
|
|
|
|
|
// Upload failed
|
|
|
|
|
dropArea.innerHTML = `
|
|
|
|
|
<p style="color: red; font-weight: bold;">
|
|
|
|
|
Failed to upload to Verofy
|
|
|
|
|
</p>
|
|
|
|
|
<p style="font-size: 14px; margin-top: 10px;">
|
|
|
|
|
Error: ${data.error || 'Unknown error'}
|
|
|
|
|
</p>
|
|
|
|
|
${data.details ? `<p style="font-size: 12px; margin-top: 5px;">${JSON.stringify(data.details)}</p>` : ''}
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('Upload error:', error)
|
|
|
|
|
dropArea.innerHTML = `
|
|
|
|
|
<p style="color: red; font-weight: bold;">
|
|
|
|
|
Upload failed. Check console for details.
|
|
|
|
|
</p>
|
|
|
|
|
<p style="font-size: 14px; margin-top: 10px;">
|
|
|
|
|
${error.message}
|
|
|
|
|
</p>
|
|
|
|
|
`
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showCelebration() {
|
2025-12-04 13:43:57 -07:00
|
|
|
// Create overlay with celebration image
|
|
|
|
|
const overlay = document.createElement('div')
|
|
|
|
|
overlay.id = 'celebrationOverlay'
|
|
|
|
|
overlay.style.cssText = `
|
|
|
|
|
position: fixed;
|
|
|
|
|
top: 0;
|
|
|
|
|
left: 0;
|
|
|
|
|
width: 100vw;
|
|
|
|
|
height: 100vh;
|
|
|
|
|
background: rgba(0, 0, 0, 0.7);
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
z-index: 10000;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
overlay.innerHTML = `
|
|
|
|
|
<img src="celebrate.png" alt="Celebration"
|
|
|
|
|
style="max-width: 80%; max-height: 80%; object-fit: contain;" />
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
// Remove overlay on click
|
|
|
|
|
overlay.addEventListener('click', () => {
|
|
|
|
|
overlay.remove()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
document.body.appendChild(overlay)
|
|
|
|
|
}
|