feat(reporting): Action Coverage chart + Archer Exception linking

Replace FP# Workflow chart with a 3-segment Action Coverage donut:
  - FP Request  — finding has an Ivanti FP# workflow
  - Archer Exception — note matches EXC-\d+ pattern
  - Pending — no action taken yet

Clicking a segment filters the findings table to that category with a
colored badge in the action bar (click again or ×  to clear).

Home page: each Archer ticket now has a filter icon button that navigates
directly to the Reporting page pre-filtered to findings whose notes
reference that EXC number. The EXC badge appears in the table action bar
with a one-click clear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 13:06:54 -06:00
parent a9404ff82a
commit 071aef96a1
2 changed files with 177 additions and 79 deletions

View File

@@ -179,6 +179,7 @@ export default function App() {
const [currentPage, setCurrentPage] = useState('home');
const [navOpen, setNavOpen] = useState(false);
const [calendarFilter, setCalendarFilter] = useState(null);
const [reportingExcFilter, setReportingExcFilter] = useState(null);
const [showAddCVE, setShowAddCVE] = useState(false);
const [showUserManagement, setShowUserManagement] = useState(false);
const [showAuditLog, setShowAuditLog] = useState(false);
@@ -963,8 +964,8 @@ export default function App() {
onClose={() => setNavOpen(false)}
currentPage={currentPage}
onNavigate={(page) => {
// Clear calendar filter when navigating directly via the nav drawer
if (page === 'reporting') setCalendarFilter(null);
// Clear contextual filters when navigating directly via the nav drawer
if (page === 'reporting') { setCalendarFilter(null); setReportingExcFilter(null); }
setCurrentPage(page);
}}
/>
@@ -1041,7 +1042,7 @@ export default function App() {
</div>
{/* Page content */}
{currentPage === 'reporting' && <ReportingPage filterDate={calendarFilter} />}
{currentPage === 'reporting' && <ReportingPage filterDate={calendarFilter} filterEXC={reportingExcFilter} />}
{currentPage === 'knowledge-base' && <KnowledgeBasePage />}
{currentPage === 'exports' && <ExportsPage />}
@@ -2332,16 +2333,23 @@ export default function App() {
>
{ticket.exc_number}
</a>
{canWrite() && (
<div className="flex gap-1">
<div className="flex gap-1">
<button
onClick={() => { setReportingExcFilter(ticket.exc_number); setCurrentPage('reporting'); }}
title="View findings referencing this ticket"
className="text-gray-400 hover:text-sky-400 transition-colors"
>
<Filter className="w-3 h-3" />
</button>
{canWrite() && (<>
<button onClick={() => handleEditArcherTicket(ticket)} className="text-gray-400 hover:text-purple-400 transition-colors">
<Edit2 className="w-3 h-3" />
</button>
<button onClick={() => handleDeleteArcherTicket(ticket)} className="text-gray-400 hover:text-intel-danger transition-colors">
<Trash2 className="w-3 h-3" />
</button>
</div>
)}
</>)}
</div>
</div>
<div className="text-xs text-white font-mono mb-1">{ticket.cve_id}</div>
<div className="text-xs text-gray-400">{ticket.vendor}</div>