From 9cd249c561e2650e818cce2e182f4a2aed664aa8 Mon Sep 17 00:00:00 2001 From: "Andoni A." <14891798+andoniaf@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:59:47 +0100 Subject: [PATCH] fix(attack-paths): show findings at full opacity in filtered view When in filtered view, findings are part of the selected path and should be fully visible, not hidden with reduced opacity. - Add isFilteredView prop to AttackPathGraph component - Skip hiding findings when isFilteredView is true --- .../_components/graph/attack-path-graph.tsx | 22 +++++++++++-------- .../(workflow)/query-builder/page.tsx | 2 ++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/ui/app/(prowler)/attack-paths/(workflow)/query-builder/_components/graph/attack-path-graph.tsx b/ui/app/(prowler)/attack-paths/(workflow)/query-builder/_components/graph/attack-path-graph.tsx index 1962d6d511..137319f6a1 100644 --- a/ui/app/(prowler)/attack-paths/(workflow)/query-builder/_components/graph/attack-path-graph.tsx +++ b/ui/app/(prowler)/attack-paths/(workflow)/query-builder/_components/graph/attack-path-graph.tsx @@ -35,6 +35,7 @@ interface AttackPathGraphProps { data: AttackPathGraphData; onNodeClick?: (node: GraphNode) => void; selectedNodeId?: string | null; + isFilteredView?: boolean; ref?: Ref; } @@ -57,7 +58,7 @@ const HEXAGON_HEIGHT = 55; // Height for finding hexagons const AttackPathGraphComponent = forwardRef< AttackPathGraphRef, AttackPathGraphProps ->(({ data, onNodeClick, selectedNodeId }, ref) => { +>(({ data, onNodeClick, selectedNodeId, isFilteredView = false }, ref) => { const svgRef = useRef(null); const [zoomLevel, setZoomLevel] = useState(1); const zoomBehaviorRef = useRef | null>( @@ -303,15 +304,18 @@ const AttackPathGraphComponent = forwardRef< g.setDefaultEdgeLabel(() => ({})); // Initially hide finding nodes - they are shown when user clicks on a node + // In filtered view, show all nodes since they're already filtered to the selected path const initialHiddenNodes = new Set(); - data.nodes.forEach((node) => { - const isFinding = node.labels.some((label) => - label.toLowerCase().includes("finding"), - ); - if (isFinding) { - initialHiddenNodes.add(node.id); - } - }); + if (!isFilteredView) { + data.nodes.forEach((node) => { + const isFinding = node.labels.some((label) => + label.toLowerCase().includes("finding"), + ); + if (isFinding) { + initialHiddenNodes.add(node.id); + } + }); + } hiddenNodeIdsRef.current = initialHiddenNodes; // Create a map to store original node data diff --git a/ui/app/(prowler)/attack-paths/(workflow)/query-builder/page.tsx b/ui/app/(prowler)/attack-paths/(workflow)/query-builder/page.tsx index 9becff907a..a817b9a715 100644 --- a/ui/app/(prowler)/attack-paths/(workflow)/query-builder/page.tsx +++ b/ui/app/(prowler)/attack-paths/(workflow)/query-builder/page.tsx @@ -477,6 +477,7 @@ export default function AttackPathAnalysisPage() { data={graphState.data} onNodeClick={handleNodeClick} selectedNodeId={graphState.selectedNodeId} + isFilteredView={graphState.isFilteredView} /> {/* Node Detail Panel - Side by side */} @@ -545,6 +546,7 @@ export default function AttackPathAnalysisPage() { data={graphState.data} onNodeClick={handleNodeClick} selectedNodeId={graphState.selectedNodeId} + isFilteredView={graphState.isFilteredView} />