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
This commit is contained in:
Andoni A.
2026-01-12 16:59:47 +01:00
parent 00fe96a9f7
commit 9cd249c561
2 changed files with 15 additions and 9 deletions
@@ -35,6 +35,7 @@ interface AttackPathGraphProps {
data: AttackPathGraphData;
onNodeClick?: (node: GraphNode) => void;
selectedNodeId?: string | null;
isFilteredView?: boolean;
ref?: Ref<AttackPathGraphRef>;
}
@@ -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<SVGSVGElement>(null);
const [zoomLevel, setZoomLevel] = useState(1);
const zoomBehaviorRef = useRef<ZoomBehavior<SVGSVGElement, unknown> | 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<string>();
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
@@ -477,6 +477,7 @@ export default function AttackPathAnalysisPage() {
data={graphState.data}
onNodeClick={handleNodeClick}
selectedNodeId={graphState.selectedNodeId}
isFilteredView={graphState.isFilteredView}
/>
</div>
{/* 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}
/>
</div>