Spaces:
Sleeping
Sleeping
| // Function to show the selected section and hide the others | |
| function showSection(sectionId) { | |
| // Show the selected section (in case it was hidden) | |
| const activeSection = document.getElementById(sectionId); | |
| if (activeSection) { | |
| activeSection.style.display = 'block'; | |
| // Scroll to the section smoothly | |
| activeSection.scrollIntoView({ | |
| behavior: 'smooth', | |
| block: 'start' // Aligns the section at the top of the viewport | |
| }); | |
| } | |
| } | |
| function showCards() { | |
| // Show cards section | |
| document.querySelector('.cards').style.display = 'grid'; // or 'flex' depending on your layout | |
| // Hide all tool sections | |
| const sections = document.querySelectorAll('.tool-section'); | |
| sections.forEach(section => { | |
| section.style.display = 'none'; | |
| }); | |
| // Scroll to top | |
| window.scrollTo({ top: 0, behavior: 'smooth' }); | |
| } | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Set up card click handlers | |
| document.querySelectorAll('.card').forEach(card => { | |
| card.addEventListener('click', function() { | |
| const sectionId = this.getAttribute('onclick').match(/'([^']+)'/)[1]; | |
| showSection(sectionId); | |
| }); | |
| }); | |
| // Hide all tool sections by default | |
| const sections = document.querySelectorAll('.tool-section'); | |
| sections.forEach(section => { | |
| section.style.display = 'none'; | |
| }); | |
| // Show first section by default | |
| showSection('document-image-analysis'); | |
| // Helper functions | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| function highlight(element) { | |
| element.classList.add('highlight'); | |
| } | |
| function unhighlight(element) { | |
| element.classList.remove('highlight'); | |
| } | |
| function isValidFileType(file, types, extensions) { | |
| return types.includes(file.type) || extensions.some(ext => file.name.endsWith(ext)); | |
| } | |
| function getFileIcon(file) { | |
| if (file.type.startsWith('image/')) return '🖼️'; | |
| if (file.type === 'application/pdf') return '📄'; | |
| if (file.type.includes('wordprocessingml')) return '📝'; | |
| if (file.type.includes('spreadsheetml') || file.type === 'text/csv') return '📊'; | |
| return '📁'; | |
| } | |
| function formatFileSize(bytes) { | |
| if (bytes === 0) return '0 Bytes'; | |
| const k = 1024; | |
| const sizes = ['Bytes', 'KB', 'MB', 'GB']; | |
| const i = Math.floor(Math.log(bytes) / Math.log(k)); | |
| return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; | |
| } | |
| function showError(element, message) { | |
| element.textContent = message; | |
| element.classList.remove('hidden'); | |
| } | |
| function hideError(element) { | |
| element.classList.add('hidden'); | |
| } | |
| function setLoading(button, isLoading, loadingText = 'Processing...') { | |
| const btnText = button.querySelector('span:not(.spinner)'); | |
| const spinner = button.querySelector('.spinner'); | |
| button.disabled = isLoading; | |
| btnText.textContent = isLoading ? loadingText : btnText.dataset.defaultText; | |
| spinner.classList.toggle('hidden', !isLoading); | |
| } | |
| // Document Analysis Section Setup | |
| const summarizeDropArea = document.getElementById('upload-area'); | |
| const summarizeFileInput = document.getElementById('file-input'); | |
| const summarizePreview = document.getElementById('file-preview'); | |
| const textInput = document.getElementById('text-input'); | |
| const summarizeBtn = document.getElementById('summarize-btn'); | |
| const summarizeResult = document.getElementById('result-content'); | |
| const summarizeError = document.getElementById('error-message'); | |
| const languageSelect = document.getElementById('language-select'); | |
| // Store default button text | |
| summarizeBtn.querySelector('span').dataset.defaultText = 'Summarize Document'; | |
| // Set up drag and drop for file upload | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| summarizeDropArea.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| summarizeDropArea.addEventListener(eventName, () => highlight(summarizeDropArea), false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| summarizeDropArea.addEventListener(eventName, () => unhighlight(summarizeDropArea), false); | |
| }); | |
| summarizeDropArea.addEventListener('drop', handleDrop, false); | |
| summarizeDropArea.addEventListener('click', (e) => { | |
| if (e.target === summarizeDropArea) { | |
| summarizeFileInput.click(); | |
| } | |
| }); | |
| summarizeFileInput.addEventListener('change', handleFileSelect); | |
| textInput.addEventListener('input', validateInputs); | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleFiles(files); | |
| } | |
| function handleFileSelect(e) { | |
| const files = e.target.files; | |
| if (files.length) { | |
| handleFiles(files); | |
| } | |
| } | |
| function handleFiles(files) { | |
| const file = files[0]; | |
| const validTypes = [ | |
| 'application/pdf', | |
| 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | |
| 'text/plain', | |
| 'image/jpeg', | |
| 'image/png' | |
| ]; | |
| const validExtensions = ['.pdf', '.docx', '.txt']; | |
| if (!isValidFileType(file, validTypes, validExtensions)) { | |
| showError(summarizeError, "Unsupported file type. Please upload PDF, DOCX, TXT, or image files."); | |
| return; | |
| } | |
| summarizePreview.innerHTML = ` | |
| <div class="file-info"> | |
| <span class="file-icon">${getFileIcon(file)}</span> | |
| <div> | |
| <strong>${file.name}</strong> | |
| <span>${formatFileSize(file.size)}</span> | |
| </div> | |
| </div> | |
| `; | |
| validateInputs(); | |
| } | |
| function validateInputs() { | |
| const hasFile = summarizeFileInput.files.length > 0; | |
| const hasText = textInput.value.trim() !== ''; | |
| summarizeBtn.disabled = !(hasFile || hasText); | |
| } | |
| // Summarize button click handler | |
| summarizeBtn.addEventListener('click', async () => { | |
| const file = summarizeFileInput.files[0]; | |
| const text = textInput.value.trim(); | |
| const language = languageSelect.value; | |
| if (!file && !text) { | |
| showError(summarizeError, "Please upload a file or enter text"); | |
| return; | |
| } | |
| try { | |
| setLoading(summarizeBtn, true); | |
| hideError(summarizeError); | |
| summarizeResult.textContent = ''; | |
| const formData = new FormData(); | |
| if (file) formData.append('file', file); | |
| if (text) formData.append('text', text); | |
| formData.append('language', language); | |
| const response = await fetch('/summarize', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json(); | |
| throw new Error(error.detail || "Failed to summarize content"); | |
| } | |
| const result = await response.json(); | |
| summarizeResult.textContent = result.summary; | |
| } catch (error) { | |
| showError(summarizeError, error.message); | |
| console.error("Summarization error:", error); | |
| } finally { | |
| setLoading(summarizeBtn, false); | |
| } | |
| }); | |
| // Question Answering Section Setup | |
| const qaDropArea = document.getElementById('qa-upload-area'); | |
| const qaFileInput = document.getElementById('qa-file-input'); | |
| const qaPreview = document.getElementById('qa-file-preview'); | |
| const qaQuestionInput = document.getElementById('qa-question'); | |
| const qaSubmitBtn = document.getElementById('qa-submit-btn'); | |
| const qaResult = document.getElementById('qa-answer'); | |
| const qaError = document.getElementById('qa-error-message'); | |
| const qaLanguageSelect = document.getElementById('qa-language'); | |
| // Store default button text | |
| qaSubmitBtn.querySelector('span').dataset.defaultText = 'Get Answer'; | |
| // Setup event listeners | |
| if (qaDropArea && qaFileInput) { | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| qaDropArea.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| qaDropArea.addEventListener(eventName, () => highlight(qaDropArea), false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| qaDropArea.addEventListener(eventName, () => unhighlight(qaDropArea), false); | |
| }); | |
| qaDropArea.addEventListener('drop', handleQADrop, false); | |
| // Question Answering Section | |
| qaDropArea.addEventListener('click', (e) => { | |
| if (e.target === qaDropArea) { | |
| qaFileInput.click(); | |
| } | |
| }); | |
| qaFileInput.addEventListener('change', handleQAFileSelect); | |
| } | |
| if (qaQuestionInput && qaSubmitBtn) { | |
| qaQuestionInput.addEventListener('input', validateQAInputs); | |
| qaSubmitBtn.addEventListener('click', handleQASubmit); | |
| } | |
| function handleQADrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleQAFiles(files); | |
| } | |
| function handleQAFileSelect(e) { | |
| const files = e.target.files; | |
| if (files.length) { | |
| handleQAFiles(files); | |
| } | |
| } | |
| function handleQAFiles(files) { | |
| const file = files[0]; | |
| const validTypes = [ | |
| 'application/pdf', | |
| 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', | |
| 'text/plain' | |
| ]; | |
| const validExtensions = ['.pdf', '.docx', '.txt']; | |
| if (!isValidFileType(file, validTypes, validExtensions)) { | |
| showError(qaError, "Unsupported file type. Please upload PDF, DOCX, or TXT files."); | |
| return; | |
| } | |
| qaPreview.innerHTML = ` | |
| <div class="file-info"> | |
| <span class="file-icon">${getFileIcon(file)}</span> | |
| <div> | |
| <strong>${file.name}</strong> | |
| <span>${formatFileSize(file.size)}</span> | |
| </div> | |
| </div> | |
| `; | |
| validateQAInputs(); | |
| } | |
| function validateQAInputs() { | |
| const hasFile = qaFileInput.files.length > 0; | |
| const hasQuestion = qaQuestionInput.value.trim() !== ''; | |
| qaSubmitBtn.disabled = !(hasFile && hasQuestion); | |
| } | |
| async function handleQASubmit() { | |
| const file = qaFileInput.files[0]; | |
| const question = qaQuestionInput.value.trim(); | |
| const language = qaLanguageSelect.value; | |
| if (!file) { | |
| showError(qaError, "Please upload a document first"); | |
| return; | |
| } | |
| if (!question) { | |
| showError(qaError, "Please enter your question"); | |
| return; | |
| } | |
| try { | |
| setLoading(qaSubmitBtn, true); | |
| hideError(qaError); | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| formData.append('question', question); | |
| formData.append('language', language); | |
| const response = await fetch('/qa', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json(); | |
| throw new Error(error.detail || "Failed to get answer"); | |
| } | |
| const result = await response.json(); | |
| displayQAResult(result); | |
| } catch (error) { | |
| showError(qaError, error.message); | |
| console.error("QA Error:", error); | |
| } finally { | |
| setLoading(qaSubmitBtn, false); | |
| } | |
| } | |
| function displayQAResult(result) { | |
| qaResult.textContent = result.answer; | |
| } | |
| // Data Visualization Section Setup | |
| const dataDropArea = document.getElementById('data-upload-area'); | |
| const dataFileInput = document.getElementById('data-file-input'); | |
| const dataPreview = document.getElementById('data-file-preview'); | |
| const visualizeBtn = document.getElementById('visualize-btn'); | |
| const visualizationPrompt = document.getElementById('visualization-prompt'); | |
| const chartTypeSelect = document.getElementById('chart-type-select'); | |
| const visualizationResult = document.getElementById('visualization-results'); | |
| const visualizationError = document.getElementById('visualization-error'); | |
| const visualizationImage = document.getElementById('generated-visualization'); | |
| const pythonCodeOutput = document.getElementById('python-code-output'); | |
| const dataPreviewContainer = document.getElementById('data-preview-container'); | |
| const copyCodeBtn = document.getElementById('copy-code-btn'); | |
| // Store default button text | |
| visualizeBtn.querySelector('span').dataset.defaultText = 'Generate Visualization'; | |
| // Setup drag and drop for data visualization | |
| if (dataDropArea && dataFileInput) { | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dataDropArea.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dataDropArea.addEventListener(eventName, () => highlight(dataDropArea), false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dataDropArea.addEventListener(eventName, () => unhighlight(dataDropArea), false); | |
| }); | |
| dataDropArea.addEventListener('drop', handleDataDrop, false); | |
| // Data Visualization Section | |
| dataDropArea.addEventListener('click', (e) => { | |
| if (e.target === dataDropArea) { | |
| dataFileInput.click(); | |
| } | |
| }); | |
| dataFileInput.addEventListener('change', handleDataFileSelect); | |
| } | |
| if (visualizeBtn) { | |
| visualizeBtn.addEventListener('click', handleVisualizationSubmit); | |
| } | |
| if (copyCodeBtn) { | |
| copyCodeBtn.addEventListener('click', copyPythonCode); | |
| } | |
| function handleDataDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| handleDataFiles(files); | |
| } | |
| function handleDataFileSelect(e) { | |
| const files = e.target.files; | |
| if (files.length) { | |
| handleDataFiles(files); | |
| } | |
| } | |
| function handleDataFiles(files) { | |
| const file = files[0]; | |
| const validTypes = [ | |
| 'application/vnd.ms-excel', | |
| 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', | |
| 'text/csv' | |
| ]; | |
| const validExtensions = ['.xlsx', '.xls', '.csv']; | |
| if (!isValidFileType(file, validTypes, validExtensions)) { | |
| showVisualizationError("Unsupported file type. Please upload Excel or CSV files."); | |
| return; | |
| } | |
| dataPreview.innerHTML = ` | |
| <div class="file-info"> | |
| <span class="file-icon">${getFileIcon(file)}</span> | |
| <div> | |
| <strong>${file.name}</strong> | |
| <span>${formatFileSize(file.size)}</span> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| async function handleVisualizationSubmit() { | |
| const file = dataFileInput.files[0]; | |
| const prompt = visualizationPrompt.value.trim(); | |
| const chartType = chartTypeSelect.value; | |
| if (!file) { | |
| showVisualizationError("Please upload a file first"); | |
| return; | |
| } | |
| try { | |
| setLoading(visualizeBtn, true, 'Generating...'); | |
| hideVisualizationError(); | |
| visualizationResult.classList.add('hidden'); | |
| const formData = new FormData(); | |
| formData.append('file', file); | |
| formData.append('request', prompt); | |
| formData.append('chart_type', chartType); | |
| const response = await fetch('/generate-visualization', { | |
| method: 'POST', | |
| body: formData | |
| }); | |
| if (!response.ok) { | |
| const error = await response.json(); | |
| throw new Error(error.detail || "Failed to generate visualization"); | |
| } | |
| const result = await response.json(); | |
| displayVisualizationResult(result); | |
| } catch (error) { | |
| showVisualizationError(error.message); | |
| console.error("Visualization error:", error); | |
| } finally { | |
| setLoading(visualizeBtn, false); | |
| } | |
| } | |
| function displayVisualizationResult(result) { | |
| visualizationImage.src = result.image_url; | |
| pythonCodeOutput.textContent = result.python_code; | |
| // Display data preview | |
| dataPreviewContainer.innerHTML = ` | |
| <p>Columns: ${result.columns.join(', ')}</p> | |
| <small>Note: Only showing first few rows of data</small> | |
| `; | |
| visualizationResult.classList.remove('hidden'); | |
| } | |
| function showVisualizationError(message) { | |
| visualizationError.textContent = message; | |
| visualizationError.classList.remove('hidden'); | |
| } | |
| function hideVisualizationError() { | |
| visualizationError.classList.add('hidden'); | |
| } | |
| function copyPythonCode() { | |
| const code = pythonCodeOutput.textContent; | |
| navigator.clipboard.writeText(code) | |
| .then(() => { | |
| copyCodeBtn.textContent = 'Copied!'; | |
| setTimeout(() => { | |
| copyCodeBtn.textContent = 'Copy Code'; | |
| }, 2000); | |
| }) | |
| .catch(err => { | |
| console.error('Failed to copy code:', err); | |
| }); | |
| } | |
| }); |