feat(exports): build Exports page with 5 export cards

Replaces the placeholder with a fully functional exports page.

Backend:
- Add GET /api/cves/compliance endpoint reading from cve_document_status view

Frontend (ExportsPage.js):
1. Ivanti Host Findings — 4 sub-exports:
   - Full dump (all findings, all columns)
   - Pending Action (no FP# and no EXC in notes)
   - Overdue SLA (past due date or OVERDUE SLA status)
   - By Business Unit (multi-sheet XLSX, one sheet per BU)

2. FP Workflow Summary — one row per unique FP# ticket ID with state,
   finding count, affected hosts, BUs, and CVEs

3. CVE Database — status filter dropdown + CSV and XLSX format options

4. Archer Tickets — full EXC ticket list with linked CVEs and URLs

5. Document Compliance Report — per CVE/vendor doc coverage with
   "missing only" toggle to generate a gap list

All exports are lazy (data fetched on click), per-button loading states,
global dismissable error banner, auto-fit column widths in XLSX outputs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-18 11:39:26 -06:00
parent b58bd0650a
commit 906066c7fa
2 changed files with 469 additions and 23 deletions

View File

@@ -302,6 +302,17 @@ app.get('/api/cves/:cveId/vendors', requireAuth(db), (req, res) => {
});
// Compliance export — reads from cve_document_status view
app.get('/api/cves/compliance', requireAuth(db), (req, res) => {
db.all('SELECT * FROM cve_document_status ORDER BY cve_id, vendor', [], (err, rows) => {
if (err) {
console.error('Error fetching compliance data:', err);
return res.status(500).json({ error: 'Internal server error.' });
}
res.json(rows);
});
});
// Create new CVE entry - ALLOW MULTIPLE VENDORS (editor or admin)
app.post('/api/cves', requireAuth(db), requireRole('editor', 'admin'), (req, res) => {
const { cve_id, vendor, severity, description, published_date } = req.body;