A634579's picture
Here’s the exact UI spec you can screenshot and throw straight to your dev/design team right now. It’s deliberately minimal, developer-first, and converts like crazy.
f49d1e7 verified
// 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);
}