Skip to content

Commit f9931c3

Browse files
committed
feat(frontend): add interactive severity filtering and bulk tree controls
1 parent fe9d0de commit f9931c3

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

apps/frontend/src/app/globals.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,11 @@ body {
471471
color: #a86a05;
472472
}
473473

474+
.pill-chip.is-active {
475+
box-shadow: 0 0 12px currentColor;
476+
transform: scale(1.05);
477+
}
478+
474479
.copy-button {
475480
gap: 8px;
476481
}

apps/frontend/src/app/page.tsx

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default function Home() {
1616
const [copied, setCopied] = useState(false);
1717
const [isDownloading, setIsDownloading] = useState(false);
1818
const [expandedCategories, setExpandedCategories] = useState<Set<string>>(new Set());
19+
const [severityFilter, setSeverityFilter] = useState<string | null>(null);
1920
const backendBaseUrl =
2021
process.env.NEXT_PUBLIC_BACKEND_URL ?? "http://127.0.0.1:7070";
2122

@@ -310,6 +311,14 @@ export default function Home() {
310311
setExpandedCategories(next);
311312
};
312313

314+
const expandAll = (categories: string[]) => {
315+
setExpandedCategories(new Set(categories));
316+
};
317+
318+
const collapseAll = () => {
319+
setExpandedCategories(new Set());
320+
};
321+
313322
return (
314323
<div className="page">
315324
<div className="page-glow page-glow--left" />
@@ -483,25 +492,47 @@ export default function Home() {
483492
</div>
484493

485494
<div className="result-card">
486-
<div className="result-header">Findings by severity</div>
495+
<div className="result-header">
496+
<span>Findings by severity</span>
497+
{severityFilter && (
498+
<button className="ghost-button" style={{ fontSize: "10px", padding: "2px 8px" }} onClick={() => setSeverityFilter(null)}>
499+
Clear filter
500+
</button>
501+
)}
502+
</div>
487503
<div className="pill-row">
488504
{Object.entries(summary.bySeverity).map(([name, count]) => (
489-
<div
505+
<button
490506
key={name}
491-
className={`pill-chip pill-chip--${name.toLowerCase()}`}
507+
className={`pill-chip pill-chip--${name.toLowerCase()} ${severityFilter === name ? "is-active" : ""}`}
508+
onClick={() => setSeverityFilter(severityFilter === name ? null : name)}
509+
style={{ border: severityFilter === name ? "1px solid currentColor" : "1px solid transparent", cursor: "pointer" }}
492510
>
493511
{name === "Error" ? <FiAlertCircle /> : <FiAlertTriangle />}
494512
<span>{name}</span>
495513
<strong>{count}</strong>
496-
</div>
514+
</button>
497515
))}
498516
</div>
499517
</div>
500518

501519
<div className="result-card">
502-
<div className="result-header">Findings Explorer</div>
520+
<div className="result-header">
521+
<span>Findings Explorer</span>
522+
<div className="pill-row">
523+
<button className="ghost-button" style={{ fontSize: "10px", padding: "2px 8px" }} onClick={() => expandAll(Object.keys(summary.findingsByCategory))}>
524+
Expand all
525+
</button>
526+
<button className="ghost-button" style={{ fontSize: "10px", padding: "2px 8px" }} onClick={collapseAll}>
527+
Collapse all
528+
</button>
529+
</div>
530+
</div>
503531
<div className="tree-view">
504-
{Object.entries(summary.findingsByCategory).sort().map(([category, items]) => {
532+
{Object.entries(summary.findingsByCategory).sort().map(([category, rawItems]) => {
533+
const items = severityFilter ? (rawItems as any[]).filter(i => i.severity === severityFilter) : (rawItems as any[]);
534+
if (items.length === 0) return null;
535+
505536
const isExpanded = expandedCategories.has(category);
506537
const catErrors = items.filter((i: any) => i.severity === "Error").length;
507538
return (
@@ -518,13 +549,13 @@ export default function Home() {
518549
</span>
519550
)}
520551
<span className="tree-badge">
521-
{items.length} items
552+
{items.length} {severityFilter ? severityFilter.toLowerCase() : "item"}s
522553
</span>
523554
</div>
524555
</div>
525556
{isExpanded && (
526557
<div className="tree-content">
527-
{(items as any[]).map((item, idx) => (
558+
{items.map((item, idx) => (
528559
<div key={idx} className="tree-finding">
529560
<div className="tree-finding-title">
530561
<strong>{item.rule_name}</strong>

0 commit comments

Comments
 (0)