feat(reporting): add BU Ownership column and per-column Excel-style filters

- buOwnership field extracted from assetCustomAttributes['1550_host_1'][0]
  and stored in SQLite cache; badge-styled cell (sky=STEAM, amber=ACCESS-ENG)
- All columns except Notes get a funnel filter button in the header
- FilterDropdown uses ReactDOM.createPortal + fixed positioning to escape
  overflowX:auto clipping; shows unique value checkboxes with search input,
  Select All, Clear, and a selected/total count footer
- Severity filter groups by vrrGroup label (CRITICAL/HIGH) not numeric value
- columnFilters state gates a useMemo filtered array before sorting
- Active filter count shown in panel header with amber badge; Clear Filters
  button appears in the toolbar when any filters are active
- Empty Set filter (Clear All) hides all rows, consistent with Excel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 13:03:17 -06:00
parent 8697ba4ef3
commit 1f36d302ea
2 changed files with 316 additions and 60 deletions

View File

@@ -124,6 +124,9 @@ function extractFinding(f) {
const rawDueDate = f.statusEmbedded?.dueDate || '';
const dueDate = rawDueDate ? rawDueDate.split('T')[0] : '';
// BU ownership: assetCustomAttributes['1550_host_1'] is an array like ["NTS-AEO-STEAM"]
const buOwnership = f.assetCustomAttributes?.['1550_host_1']?.[0] || '';
return {
id: String(f.id),
title: f.title || '',
@@ -135,7 +138,8 @@ function extractFinding(f) {
status: f.status || '',
slaStatus: f.slaStatus || '',
dueDate,
lastFoundOn: f.lastFoundOn || ''
lastFoundOn: f.lastFoundOn || '',
buOwnership
};
}