Spaces:
Running
Running
| // Usage analytics functionality | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initUsageChart(); | |
| }); | |
| // Initialize usage chart | |
| function initUsageChart() { | |
| const ctx = document.getElementById('usage-chart').getContext('2d'); | |
| // Generate sample data for last 30 days | |
| const labels = []; | |
| const data = []; | |
| const threats = []; | |
| for (let i = 29; i >= 0; i--) { | |
| const date = new Date(); | |
| date.setDate(date.getDate() - i); | |
| labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })); | |
| // Generate realistic usage data | |
| const baseUsage = 80 + Math.random() * 40; | |
| const weekendFactor = (date.getDay() === 0 || date.getDay() === 6) ? 0.6 : 1; | |
| const dailyUsage = Math.floor(baseUsage * weekendFactor); | |
| data.push(dailyUsage); | |
| threats.push(Math.floor(dailyUsage * 0.4 + Math.random() * 20)); | |
| } | |
| new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: labels, | |
| datasets: [ | |
| { | |
| label: 'Documents Processed', | |
| data: data, | |
| borderColor: '#3b82f6', | |
| backgroundColor: 'rgba(59, 130, 246, 0.1)', | |
| fill: true, | |
| tension: 0.4 | |
| }, | |
| { | |
| label: 'Threats Removed', | |
| data: threats, | |
| borderColor: '#ef4444', | |
| backgroundColor: 'rgba(239, 68, 68, 0.1)', | |
| fill: true, | |
| tension: 0.4 | |
| } | |
| ] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| position: 'top', | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: true, | |
| grid: { | |
| color: 'rgba(0, 0, 0, 0.1)' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| color: 'rgba(0, 0, 0, 0.1)' | |
| } | |
| } | |
| }, | |
| elements: { | |
| point: { | |
| radius: 3, | |
| hoverRadius: 6 | |
| } | |
| } | |
| } | |
| }); | |
| } | |
| // Export usage data | |
| function exportUsageData() { | |
| const usageData = { | |
| period: 'Last 30 days', | |
| documentsProcessed: 2847, | |
| threatsRemoved: 1423, | |
| averageProcessingTime: 2.3, | |
| dataCleaned: '847 MB', | |
| threatBreakdown: { | |
| 'Zero-width characters': 687, | |
| 'Embedded JavaScript': 423, | |
| 'LSB steganography': 189, | |
| 'VBA macros': 124 | |
| }, | |
| fileTypeBreakdown: { | |
| 'PDF': 1245, | |
| 'DOCX': 867, | |
| 'Images': 432, | |
| 'PPTX': 203, | |
| 'Other': 100 | |
| } | |
| }; | |
| const csvContent = [ | |
| 'Metric,Value', | |
| `Documents Processed,${usageData.documentsProcessed}`, | |
| `Threats Removed,${usageData.threatsRemoved}`, | |
| `Average Processing Time,${usageData.averageProcessingTime}s`, | |
| `Data Cleaned,${usageData.dataCleaned}`, | |
| '', | |
| 'Threat Types,Count', | |
| ...Object.entries(usageData.threatBreakdown).map(([type, count]) => `${type},${count}`), | |
| '', | |
| 'File Types,Count', | |
| ...Object.entries(usageData.fileTypeBreakdown).map(([type, count]) => `${type},${count}`) | |
| ].join('\n'); | |
| const blob = new Blob([csvContent], { type: 'text/csv' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = `wash-usage-${new Date().toISOString().split('T')[0]}.csv`; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| URL.revokeObjectURL(url); | |
| Wash.showNotification('Usage data exported successfully', 'success'); | |
| } | |
| // Format number with commas | |
| function formatNumber(num) { | |
| return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); | |
| } | |
| // Calculate percentage change | |
| function calculatePercentageChange(current, previous) { | |
| if (previous === 0) return current > 0 ? 100 : 0; | |
| return ((current - previous) / previous * 100).toFixed(1); | |
| } |