fix(bi): add environment distribution breakdown to explain count discrepancies
Problem: Users noticed environment counts don't add up to total - Total (All Environments): 868 - Development: 400 - Production: 300 - 400 + 300 = 700 ≠ 868 Root cause: Some audit logs have no environment field (null/undefined) - These records ARE counted in "All Environments" - These records are NOT counted when filtering by "Development" or "Production" Solution: - Added "Environment Distribution" section showing breakdown - Displays: Development, Production, and Unspecified counts - Shows warning when unspecified records exist - Makes it clear why filtered totals may not match grand total Technical details: - Frontend filtering in audit-analytics.js - Backend query uses: query.environment = environment (exact match only) - Missing environment fields excluded from filtered results 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8c3ca56e2a
commit
e99c85c4f2
2 changed files with 67 additions and 0 deletions
|
|
@ -151,6 +151,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Environment Distribution (shows why totals may not match filtered views) -->
|
||||
<div id="environment-distribution" class="bg-white rounded-lg shadow-sm border border-gray-200 p-4 mb-6">
|
||||
<h4 class="text-sm font-semibold text-gray-700 mb-3 flex items-center">
|
||||
<svg class="w-4 h-4 mr-2 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
||||
</svg>
|
||||
Environment Distribution
|
||||
</h4>
|
||||
<div id="environment-stats" class="grid grid-cols-3 gap-3 text-sm">
|
||||
<!-- Populated by JS -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Business Intelligence Section -->
|
||||
<div class="bg-gradient-to-r from-purple-50 to-blue-50 rounded-lg shadow-sm border-2 border-purple-200 p-6 mb-8">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
|
|
|
|||
|
|
@ -138,6 +138,60 @@ function updateSummaryCards() {
|
|||
|
||||
document.getElementById('violations-count').textContent = violationsCount;
|
||||
document.getElementById('services-count').textContent = servicesSet.size || 0;
|
||||
|
||||
// Environment distribution breakdown
|
||||
updateEnvironmentDistribution();
|
||||
}
|
||||
|
||||
// Update environment distribution display
|
||||
function updateEnvironmentDistribution() {
|
||||
const environmentStats = {
|
||||
development: 0,
|
||||
production: 0,
|
||||
unspecified: 0
|
||||
};
|
||||
|
||||
auditData.forEach(d => {
|
||||
if (d.environment === 'development') {
|
||||
environmentStats.development++;
|
||||
} else if (d.environment === 'production') {
|
||||
environmentStats.production++;
|
||||
} else {
|
||||
environmentStats.unspecified++;
|
||||
}
|
||||
});
|
||||
|
||||
const total = auditData.length;
|
||||
const statsEl = document.getElementById('environment-stats');
|
||||
|
||||
statsEl.innerHTML = `
|
||||
<div class="text-center p-2 bg-blue-50 border border-blue-200 rounded">
|
||||
<div class="font-semibold text-blue-700">Development</div>
|
||||
<div class="text-2xl font-bold text-blue-900">${environmentStats.development}</div>
|
||||
<div class="text-xs text-blue-600">${total > 0 ? ((environmentStats.development / total) * 100).toFixed(1) : 0}%</div>
|
||||
</div>
|
||||
<div class="text-center p-2 bg-green-50 border border-green-200 rounded">
|
||||
<div class="font-semibold text-green-700">Production</div>
|
||||
<div class="text-2xl font-bold text-green-900">${environmentStats.production}</div>
|
||||
<div class="text-xs text-green-600">${total > 0 ? ((environmentStats.production / total) * 100).toFixed(1) : 0}%</div>
|
||||
</div>
|
||||
<div class="text-center p-2 bg-amber-50 border border-amber-200 rounded">
|
||||
<div class="font-semibold text-amber-700">Unspecified</div>
|
||||
<div class="text-2xl font-bold text-amber-900">${environmentStats.unspecified}</div>
|
||||
<div class="text-xs text-amber-600">${total > 0 ? ((environmentStats.unspecified / total) * 100).toFixed(1) : 0}%</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Show warning if there are unspecified records
|
||||
if (environmentStats.unspecified > 0) {
|
||||
const warningHTML = `
|
||||
<div class="col-span-3 mt-2 p-2 bg-amber-50 border border-amber-300 rounded text-xs text-amber-900">
|
||||
<strong>⚠️ Note:</strong> ${environmentStats.unspecified} record(s) have no environment field.
|
||||
These are included in "All Environments" but excluded when filtering by Development or Production.
|
||||
</div>
|
||||
`;
|
||||
statsEl.innerHTML += warningHTML;
|
||||
}
|
||||
}
|
||||
|
||||
// Render Business Intelligence
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue