Watch
1
0
Fork
You've already forked RedFlag
0

fix: severity stats scoped to non-terminal statuses + consistent type icons (UI-DASHBOARD-AUDIT #2, #4)

This commit is contained in:
Fimeg 2026-06-11 08:45:27 -04:00
commit da455b77a5
2 changed files with 15 additions and 9 deletions

View file

@ -1264,10 +1264,10 @@ func (q *UpdateQueries) GetUpdateStatsFromState(agentID uuid.UUID) (*models.Upda
COUNT(*) FILTER (WHERE status = 'pending') as pending_updates,
COUNT(*) FILTER (WHERE status = 'installed') as installed_updates,
COUNT(*) FILTER (WHERE status = 'failed') as failed_updates,
COUNT(*) FILTER (WHERE severity = 'critical') as critical_updates,
COUNT(*) FILTER (WHERE severity = 'important') as important_updates,
COUNT(*) FILTER (WHERE severity = 'moderate') as moderate_updates,
COUNT(*) FILTER (WHERE severity = 'low') as low_updates
COUNT(*) FILTER (WHERE severity = 'critical' AND status NOT IN ('installed', 'failed', 'ignored')) as critical_updates,
COUNT(*) FILTER (WHERE severity = 'important' AND status NOT IN ('installed', 'failed', 'ignored')) as important_updates,
COUNT(*) FILTER (WHERE severity = 'moderate' AND status NOT IN ('installed', 'failed', 'ignored')) as moderate_updates,
COUNT(*) FILTER (WHERE severity = 'low' AND status NOT IN ('installed', 'failed', 'ignored')) as low_updates
FROM current_package_state
WHERE agent_id = $1
`
@ -1284,6 +1284,11 @@ func (q *UpdateQueries) GetUpdateStatsFromState(agentID uuid.UUID) (*models.Upda
func (q *UpdateQueries) GetAllUpdateStats() (*models.UpdateStats, error) {
stats := &models.UpdateStats{}
// Severity counts are scoped to non-terminal statuses: a package that is
// already installed, failed, or ignored is not "attention-worthy" severity
// on the dashboard. Counting them inflated the bars past 100% because the
// denominator (total_updates / pending_updates) is also scoped smaller.
// UI-DASHBOARD-AUDIT finding #2.
query := `
SELECT
COUNT(*) as total_updates,
@ -1291,10 +1296,10 @@ func (q *UpdateQueries) GetAllUpdateStats() (*models.UpdateStats, error) {
COUNT(*) FILTER (WHERE status = 'approved') as approved_updates,
COUNT(*) FILTER (WHERE status = 'installed') as installed_updates,
COUNT(*) FILTER (WHERE status = 'failed') as failed_updates,
COUNT(*) FILTER (WHERE severity = 'critical') as critical_updates,
COUNT(*) FILTER (WHERE severity = 'important') as high_updates,
COUNT(*) FILTER (WHERE severity = 'moderate') as moderate_updates,
COUNT(*) FILTER (WHERE severity = 'low') as low_updates
COUNT(*) FILTER (WHERE severity = 'critical' AND status NOT IN ('installed', 'failed', 'ignored')) as critical_updates,
COUNT(*) FILTER (WHERE severity = 'important' AND status NOT IN ('installed', 'failed', 'ignored')) as high_updates,
COUNT(*) FILTER (WHERE severity = 'moderate' AND status NOT IN ('installed', 'failed', 'ignored')) as moderate_updates,
COUNT(*) FILTER (WHERE severity = 'low' AND status NOT IN ('installed', 'failed', 'ignored')) as low_updates
FROM current_package_state
`

View file

@ -10,6 +10,7 @@ import {
Clock,
} from 'lucide-react';
import { useDashboardStats } from '@/hooks/useStats';
import { getPackageTypeIcon } from '@/lib/utils';
import { useServerKeySecurity } from '@/hooks/useSecurity';
import StackDriftPanel from '@/components/StackDriftPanel';
@ -63,7 +64,7 @@ const Dashboard: React.FC = () => {
const updateTypeBreakdown = Object.entries(stats?.updates_by_type ?? {}).map(([type, count]) => ({
type: type.charAt(0).toUpperCase() + type.slice(1),
value: count,
icon: type === 'apt' ? '📦' : type === 'docker' ? '🐳' : '📋',
icon: getPackageTypeIcon(type),
}));
return (