Download docs/batch-processing.html from accessibilitychecker/AccessibilityCheckerBackend: direct link, hf CLI and curl.
- Browser
- Download file 13.9 kB
-
https://huggingface.co/spaces/accessibilitychecker/AccessibilityCheckerBackend/resolve/main/docs/batch-processing.html
- Command line
-
hf download hf://spaces/accessibilitychecker/AccessibilityCheckerBackend/docs/batch-processing.html
-
curl -L -o batch-processing.html https://huggingface.co/spaces/accessibilitychecker/AccessibilityCheckerBackend/resolve/main/docs/batch-processing.html
13.9 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Batch Document Processing</title> | |
| <style> | |
| body { font-family: Arial, sans-serif; max-width: 1200px; margin: 0 auto; padding: 20px; } | |
| .upload-area { border: 2px dashed #ccc; padding: 40px; text-align: center; margin: 20px 0; } | |
| .upload-area.dragover { border-color: #007cba; background-color: #f0f8ff; } | |
| .file-list { margin: 20px 0; } | |
| .file-item { padding: 10px; border: 1px solid #ddd; margin: 5px 0; display: flex; justify-content: space-between; align-items: center; } | |
| .file-item.processing { background-color: #fff3cd; } | |
| .file-item.success { background-color: #d4edda; } | |
| .file-item.error { background-color: #f8d7da; } | |
| .progress-bar { width: 100%; height: 20px; background-color: #f0f0f0; border-radius: 10px; overflow: hidden; margin: 10px 0; } | |
| .progress-fill { height: 100%; background-color: #007cba; transition: width 0.3s ease; } | |
| .results { margin: 20px 0; } | |
| .batch-history { margin: 30px 0; } | |
| .batch-item { padding: 15px; border: 1px solid #ddd; margin: 10px 0; border-radius: 5px; } | |
| button { padding: 10px 20px; margin: 5px; cursor: pointer; } | |
| .btn-primary { background-color: #007cba; color: white; border: none; } | |
| .btn-secondary { background-color: #6c757d; color: white; border: none; } | |
| .btn-danger { background-color: #dc3545; color: white; border: none; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Accessibility Checker - Batch Processing</h1> | |
| <div class="upload-section"> | |
| <h2>Upload Multiple Documents</h2> | |
| <div id="uploadArea" class="upload-area"> | |
| <p>Drop up to 10 DOCX files here, or click to select</p> | |
| <input type="file" id="fileInput" multiple accept=".docx" style="display: none;"> | |
| <button onclick="document.getElementById('fileInput').click()" class="btn-primary">Select Files</button> | |
| </div> | |
| <div id="fileList" class="file-list"></div> | |
| <div id="progressSection" style="display: none;"> | |
| <h3>Processing Files...</h3> | |
| <div class="progress-bar"> | |
| <div id="progressFill" class="progress-fill" style="width: 0%;"></div> | |
| </div> | |
| <div id="progressText">Preparing upload...</div> | |
| </div> | |
| <button id="uploadBtn" onclick="uploadFiles()" class="btn-primary" style="display: none;"> | |
| Upload and Process Files | |
| </button> | |
| </div> | |
| <div id="results" class="results" style="display: none;"> | |
| <h2>Processing Results</h2> | |
| <div id="resultsContent"></div> | |
| </div> | |
| <div class="batch-history"> | |
| <h2>Previous Batches</h2> | |
| <button onclick="loadBatchHistory()" class="btn-secondary">Load Batch History</button> | |
| <div id="batchHistory"></div> | |
| </div> | |
| <script> | |
| let selectedFiles = []; | |
| let sessionId = null; | |
| const API_BASE = window.location.origin; // Adjust as needed | |
| // Session management | |
| async function initializeSession() { | |
| try { | |
| const response = await fetch(`${API_BASE}/api/session`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| const data = await response.json(); | |
| sessionId = data.sessionId; | |
| console.log('Session initialized:', sessionId); | |
| // Start heartbeat to keep session alive | |
| startHeartbeat(); | |
| // Load existing session data | |
| loadSessionData(); | |
| } catch (error) { | |
| console.error('Failed to initialize session:', error); | |
| } | |
| } | |
| function startHeartbeat() { | |
| // Send heartbeat every 5 minutes | |
| setInterval(async () => { | |
| if (sessionId) { | |
| try { | |
| await fetch(`${API_BASE}/api/session`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'X-Session-ID': sessionId | |
| } | |
| }); | |
| } catch (error) { | |
| console.warn('Heartbeat failed:', error); | |
| } | |
| } | |
| }, 5 * 60 * 1000); // 5 minutes | |
| } | |
| async function loadSessionData() { | |
| if (!sessionId) return; | |
| try { | |
| const response = await fetch(`${API_BASE}/api/session?sessionId=${sessionId}`); | |
| const sessionData = await response.json(); | |
| // Display existing batches from this session | |
| displaySessionHistory(sessionData); | |
| } catch (error) { | |
| console.warn('Failed to load session data:', error); | |
| } | |
| } | |
| function displaySessionHistory(sessionData) { | |
| const historyDiv = document.getElementById('batchHistory'); | |
| if (sessionData.batches.length === 0) { | |
| historyDiv.innerHTML = '<p>No batches in this session yet.</p>'; | |
| return; | |
| } | |
| historyDiv.innerHTML = '<h3>This Session:</h3>' + | |
| sessionData.batches.map(batch => ` | |
| <div class="batch-item"> | |
| <h4>Batch ${batch.batchId}</h4> | |
| <p><strong>Files:</strong> ${batch.totalFiles} (${batch.successful} successful, ${batch.failed} failed)</p> | |
| <p><strong>Processed:</strong> ${new Date(batch.timestamp).toLocaleString()}</p> | |
| <button onclick="downloadBatch('${batch.batchId}')" class="btn-primary">Download</button> | |
| </div> | |
| `).join(''); | |
| } | |
| // Cleanup on page unload | |
| window.addEventListener('beforeunload', () => { | |
| // Note: Session will auto-expire after 1 hour of inactivity | |
| // No need to manually cleanup as the server handles it | |
| }); | |
| // File selection and drag/drop | |
| document.getElementById('fileInput').addEventListener('change', handleFileSelect); | |
| const uploadArea = document.getElementById('uploadArea'); | |
| uploadArea.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.add('dragover'); | |
| }); | |
| uploadArea.addEventListener('dragleave', () => { | |
| uploadArea.classList.remove('dragover'); | |
| }); | |
| uploadArea.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.remove('dragover'); | |
| const files = Array.from(e.dataTransfer.files).filter(f => f.name.endsWith('.docx')); | |
| handleFiles(files); | |
| }); | |
| function handleFileSelect(e) { | |
| const files = Array.from(e.target.files); | |
| handleFiles(files); | |
| } | |
| function handleFiles(files) { | |
| selectedFiles = files.slice(0, 10); // Limit to 10 files | |
| displayFileList(); | |
| document.getElementById('uploadBtn').style.display = selectedFiles.length > 0 ? 'block' : 'none'; | |
| } | |
| function displayFileList() { | |
| const fileList = document.getElementById('fileList'); | |
| if (selectedFiles.length === 0) { | |
| fileList.innerHTML = ''; | |
| return; | |
| } | |
| fileList.innerHTML = `<h3>Selected Files (${selectedFiles.length}):</h3>`; | |
| selectedFiles.forEach((file, index) => { | |
| const fileItem = document.createElement('div'); | |
| fileItem.className = 'file-item'; | |
| fileItem.innerHTML = ` | |
| <div> | |
| <strong>${file.name}</strong> | |
| <br><small>${(file.size / 1024).toFixed(1)} KB</small> | |
| </div> | |
| <button onclick="removeFile(${index})" class="btn-danger">Remove</button> | |
| `; | |
| fileList.appendChild(fileItem); | |
| }); | |
| } | |
| function removeFile(index) { | |
| selectedFiles.splice(index, 1); | |
| displayFileList(); | |
| document.getElementById('uploadBtn').style.display = selectedFiles.length > 0 ? 'block' : 'none'; | |
| } | |
| async function uploadFiles() { | |
| if (selectedFiles.length === 0 || !sessionId) return; | |
| document.getElementById('progressSection').style.display = 'block'; | |
| document.getElementById('uploadBtn').disabled = true; | |
| const formData = new FormData(); | |
| selectedFiles.forEach((file, index) => { | |
| formData.append(`file${index}`, file); | |
| }); | |
| try { | |
| updateProgress(10, 'Uploading files...'); | |
| const response = await fetch(`${API_BASE}/api/batch-upload`, { | |
| method: 'POST', | |
| headers: { | |
| 'X-Session-ID': sessionId | |
| }, | |
| body: formData | |
| }); | |
| updateProgress(90, 'Processing files...'); | |
| if (!response.ok) { | |
| throw new Error(`Upload failed: ${response.statusText}`); | |
| } | |
| const result = await response.json(); | |
| updateProgress(100, 'Complete!'); | |
| displayResults(result); | |
| // Refresh session data to show new batch | |
| loadSessionData(); | |
| // Clear selection | |
| selectedFiles = []; | |
| displayFileList(); | |
| document.getElementById('uploadBtn').style.display = 'none'; | |
| } catch (error) { | |
| console.error('Upload error:', error); | |
| updateProgress(0, `Error: ${error.message}`); | |
| } finally { | |
| document.getElementById('uploadBtn').disabled = false; | |
| setTimeout(() => { | |
| document.getElementById('progressSection').style.display = 'none'; | |
| }, 2000); | |
| } | |
| } | |
| function updateProgress(percent, text) { | |
| document.getElementById('progressFill').style.width = percent + '%'; | |
| document.getElementById('progressText').textContent = text; | |
| } | |
| function displayResults(result) { | |
| const resultsDiv = document.getElementById('results'); | |
| const resultsContent = document.getElementById('resultsContent'); | |
| resultsContent.innerHTML = ` | |
| <div class="batch-item"> | |
| <h3>Batch ${result.batchId}</h3> | |
| <p><strong>Total Files:</strong> ${result.summary.totalFiles}</p> | |
| <p><strong>Successful:</strong> ${result.summary.successful}</p> | |
| <p><strong>Failed:</strong> ${result.summary.failed}</p> | |
| <button onclick="downloadBatch('${result.batchId}')" class="btn-primary"> | |
| Download Remediated Files | |
| </button> | |
| <h4>File Details:</h4> | |
| <div class="file-list"> | |
| ${result.results.map(r => ` | |
| <div class="file-item ${r.success ? 'success' : 'error'}"> | |
| <div> | |
| <strong>${r.filename}</strong> | |
| ${r.success ? | |
| `<br><small>✓ Processed successfully</small>` : | |
| `<br><small>✗ Error: ${r.error}</small>` | |
| } | |
| </div> | |
| </div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| `; | |
| resultsDiv.style.display = 'block'; | |
| } | |
| async function downloadBatch(batchId) { | |
| if (sessionId) { | |
| window.open(`${API_BASE}/api/batch-download?batchId=${batchId}&sessionId=${sessionId}`, '_blank'); | |
| } | |
| } | |
| async function deleteBatch(batchId) { | |
| if (!confirm(`Delete batch ${batchId}?`)) return; | |
| try { | |
| const response = await fetch(`${API_BASE}/api/reports?batchId=${batchId}`, { | |
| method: 'DELETE' | |
| }); | |
| if (response.ok) { | |
| loadBatchHistory(); // Refresh the list | |
| } else { | |
| alert('Failed to delete batch'); | |
| } | |
| } catch (error) { | |
| console.error('Error deleting batch:', error); | |
| } | |
| } | |
| // Initialize session on page load | |
| initializeSession(); | |
| </script> | |
| </body> | |
| </html> |