Spaces:
Running
Running
document.addEventListener('DOMContentLoaded', () => { | |
// UI Elements | |
const GotitB = document.querySelector(".explainChoix button"); | |
const explain = document.querySelector(".explainChoix"); | |
const SummarizeInput = document.querySelector(".SummarizeInput"); | |
const CaptionInput = document.querySelector(".CaptionInput"); | |
const fileUpload = document.getElementById('file-upload'); | |
const imageUpload = document.getElementById('image-upload'); | |
const fileBtn = document.getElementById('file-btn'); | |
const imageBtn = document.getElementById('image-btn'); | |
const convo = document.querySelector('.convo'); | |
// Hide explanation after click | |
GotitB.addEventListener("click", () => { | |
explain.style.opacity = "0"; | |
}); | |
// Handle mode switching | |
document.querySelectorAll('.select-options input[type="radio"]').forEach(radio => { | |
radio.addEventListener('change', (e) => { | |
if (e.target.checked) { | |
const selectedValue = e.target.value; | |
if (selectedValue === "Summarize") { | |
SummarizeInput.classList.add("active"); | |
SummarizeInput.classList.remove("innactive"); | |
CaptionInput.classList.remove("active"); | |
CaptionInput.classList.add("innactive"); | |
} else { | |
SummarizeInput.classList.add("innactive"); | |
SummarizeInput.classList.remove("active"); | |
CaptionInput.classList.remove("innactive"); | |
CaptionInput.classList.add("active"); | |
} | |
} | |
}); | |
}); | |
// File upload handlers | |
fileBtn.addEventListener('click', () => fileUpload.click()); | |
imageBtn.addEventListener('click', () => imageUpload.click()); | |
// Send button handlers | |
document.querySelectorAll('.sendingQA').forEach(button => { | |
button.addEventListener('click', async () => { | |
const isSummarizeMode = document.querySelector('input[name="option"]:checked').value === 'Summarize'; | |
if (isSummarizeMode) { | |
await handleSummarize(); | |
} else { | |
await handleCaption(); | |
} | |
}); | |
}); | |
// Handle document summarization | |
async function handleSummarize() { | |
const file = fileUpload.files[0]; | |
if (!file) { | |
displayError('Please upload a document first'); | |
return; | |
} | |
const length = document.querySelector('input[name="optionS"]:checked')?.value || 'medium'; | |
try { | |
// Show loading state | |
convo.innerHTML = ''; | |
displayFileInfo(file.name, 'document'); | |
displayThinkingMessage(); | |
// Call API | |
const result = await summarizeDocument(file, length); | |
// Display results | |
displaySummaryResult(file.name, result.summary, result.audio_url, result.pdf_url); | |
} catch (error) { | |
displayError(error.message || 'Failed to summarize document'); | |
} | |
} | |
// Handle image captioning | |
async function handleCaption() { | |
const file = imageUpload.files[0]; | |
if (!file) { | |
displayError('Please upload an image first'); | |
return; | |
} | |
try { | |
// Show loading state | |
convo.innerHTML = ''; | |
displayFileInfo(file.name, 'image'); | |
displayThinkingMessage(); | |
// Call API | |
const result = await captionImage(file); | |
// Display results | |
displayCaptionResult(file.name, result.answer, result.audio); | |
} catch (error) { | |
displayError(error.message || 'Failed to generate caption'); | |
} | |
} | |
// API Functions | |
async function summarizeDocument(file, length) { | |
const formData = new FormData(); | |
formData.append('file', file); | |
formData.append('length', length); | |
const response = await fetch('/summarize/', { | |
method: 'POST', | |
body: formData | |
}); | |
if (!response.ok) { | |
const error = await response.json(); | |
throw new Error(error.error || 'Summarization failed'); | |
} | |
return await response.json(); | |
} | |
async function captionImage(file) { | |
const formData = new FormData(); | |
formData.append('file', file); | |
const response = await fetch('/imagecaption/', { | |
method: 'POST', | |
body: formData | |
}); | |
if (!response.ok) { | |
const error = await response.json(); | |
throw new Error(error.error || 'Captioning failed'); | |
} | |
return await response.json(); | |
} | |
// UI Helper Functions | |
function displayFileInfo(filename, type) { | |
const bubble = document.createElement('div'); | |
bubble.className = 'bubble right'; | |
bubble.innerHTML = ` | |
<div class="label">You</div> | |
<div class="text">${type === 'document' ? '📄' : '🖼️'} ${filename}</div> | |
`; | |
convo.appendChild(bubble); | |
} | |
function displayThinkingMessage() { | |
const bubble = document.createElement('div'); | |
bubble.className = 'bubble left'; | |
bubble.innerHTML = ` | |
<div class="label">Aidan</div> | |
<div class="text"> | |
<div style="display:flex;align-items:center;gap:8px"> | |
<span>Processing your ${document.querySelector('input[name="option"]:checked').value.toLowerCase()}...</span> | |
<div class="loader"></div> | |
</div> | |
</div> | |
`; | |
convo.appendChild(bubble); | |
convo.scrollTop = convo.scrollHeight; | |
} | |
function displaySummaryResult(filename, summary, audioUrl, pdfUrl) { | |
// Remove thinking message | |
convo.removeChild(convo.lastChild); | |
const bubble = document.createElement('div'); | |
bubble.className = 'bubble left'; | |
bubble.innerHTML = ` | |
<div class="label">Aidan</div> | |
<div class="text"> | |
<strong>Summary:</strong><br><br> | |
${summary.replace(/\n/g, '<br>')} | |
<div class="action-buttons" style="margin-top: 10px; display: flex; gap: 10px;"> | |
${audioUrl ? ` | |
<button class="audio-control" data-audio="${audioUrl}"> | |
<i class="fa-solid fa-volume-high"></i> Audio | |
</button>` : ''} | |
${pdfUrl ? ` | |
<a href="${pdfUrl}" download="${filename.split('.')[0]}_summary.pdf" class="download-btn"> | |
<i class="fa-solid fa-download"></i> PDF | |
</a>` : ''} | |
</div> | |
</div> | |
`; | |
convo.appendChild(bubble); | |
setupAudioControls(); | |
convo.scrollTop = convo.scrollHeight; | |
} | |
function displayCaptionResult(filename, caption, audioUrl) { | |
// Remove thinking message | |
convo.removeChild(convo.lastChild); | |
const bubble = document.createElement('div'); | |
bubble.className = 'bubble left'; | |
bubble.innerHTML = ` | |
<div class="label">Aidan</div> | |
<div class="text"> | |
<strong>Caption:</strong><br><br> | |
${caption} | |
${audioUrl ? ` | |
<div class="action-buttons" style="margin-top: 10px;"> | |
<button class="audio-control" data-audio="${audioUrl}"> | |
<i class="fa-solid fa-volume-high"></i> Audio | |
</button> | |
</div>` : ''} | |
</div> | |
`; | |
convo.appendChild(bubble); | |
setupAudioControls(); | |
convo.scrollTop = convo.scrollHeight; | |
} | |
function setupAudioControls() { | |
document.querySelectorAll('.audio-control').forEach(button => { | |
const audioUrl = button.getAttribute('data-audio'); | |
const audio = new Audio(audioUrl); | |
const icon = button.querySelector('i'); | |
button.addEventListener('click', () => { | |
if (audio.paused) { | |
audio.play(); | |
icon.classList.remove('fa-volume-xmark'); | |
icon.classList.add('fa-volume-high'); | |
} else { | |
audio.pause(); | |
icon.classList.remove('fa-volume-high'); | |
icon.classList.add('fa-volume-xmark'); | |
} | |
}); | |
}); | |
} | |
function displayError(message) { | |
const bubble = document.createElement('div'); | |
bubble.className = 'bubble left'; | |
bubble.innerHTML = ` | |
<div class="label">Aidan</div> | |
<div class="text" style="color: #ef4444;"> | |
⚠️ ${message} | |
</div> | |
`; | |
convo.appendChild(bubble); | |
convo.scrollTop = convo.scrollHeight; | |
} | |
// Add loader CSS | |
const style = document.createElement('style'); | |
style.textContent = ` | |
.loader { | |
border: 2px solid #f3f3f3; | |
border-top: 2px solid #3b82f6; | |
border-radius: 50%; | |
width: 16px; | |
height: 16px; | |
animation: spin 1s linear infinite; | |
} | |
@keyframes spin { | |
0% { transform: rotate(0deg); } | |
100% { transform: rotate(360deg); } | |
} | |
.download-btn, .audio-control { | |
display: inline-flex; | |
align-items: center; | |
gap: 5px; | |
padding: 5px 10px; | |
background: #3b82f6; | |
color: white; | |
border: none; | |
border-radius: 5px; | |
cursor: pointer; | |
text-decoration: none; | |
font-size: 14px; | |
} | |
.download-btn:hover, .audio-control:hover { | |
background: #2563eb; | |
} | |
.bubble { | |
max-width: 80%; | |
padding: 12px 16px; | |
margin: 8px 0; | |
border-radius: 18px; | |
position: relative; | |
clear: both; | |
} | |
.bubble.left { | |
background: #f1f1f1; | |
float: left; | |
margin-right: auto; | |
} | |
.bubble.right { | |
background: #3b82f6; | |
color: white; | |
float: right; | |
margin-left: auto; | |
} | |
.label { | |
font-weight: bold; | |
font-size: 12px; | |
margin-bottom: 4px; | |
} | |
`; | |
document.head.appendChild(style); | |
}); |