-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Radial cluster connections #3394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev6
Are you sure you want to change the base?
Conversation
generated by cursor using claude-4.5-sonnet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds support for radial cluster graph visualization to the connections view, introducing a third field for hierarchical display and a graph type selector to switch between force-directed and radial cluster layouts.
Key Changes
- Added optional third field input for hierarchical connections visualization
- Implemented graph type selector to toggle between force-directed and radial cluster visualizations
- Enhanced backend API to support three-level hierarchical data processing
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| Connections.vue | Added third field input, graph type selector, and radial cluster visualization implementation |
| apiConnections.js | Modified backend processing to support optional third field and three-level hierarchical data structures |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| .text(d => d.data.nodeData.id + this.calculateNodeLabelSuffix(d.data.nodeData)); | ||
| }, | ||
| convertToHierarchy: function (graphNodes, graphLinks) { | ||
| const hasThirdLevel = graphNodes.some(n => n.level === 3); |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using some() to check for level 3 nodes could be inefficient for large datasets. Consider tracking this state during data processing instead of iterating through all nodes.
| // Build hierarchy based on parent relationships | ||
| graphNodes.forEach(n => { | ||
| const hierarchyNode = nodeMap.get(n.pos); | ||
| if (n.level === 1) { | ||
| // Level 1 nodes go directly under root | ||
| rootChildren.push(hierarchyNode); | ||
| } else if (n.level === 2 && n.parent !== undefined) { | ||
| // Level 2 nodes go under their level 1 parent | ||
| const parentNode = graphNodes.find(p => p.pos === graphLinks.find(l => l.target === n.pos)?.source); | ||
| if (parentNode) { | ||
| const parentHierarchyNode = nodeMap.get(parentNode.pos); | ||
| if (parentHierarchyNode) { | ||
| parentHierarchyNode.children.push(hierarchyNode); | ||
| } | ||
| } | ||
| } else if (n.level === 3 && n.parent !== undefined) { | ||
| // Level 3 nodes go under their level 2 parent | ||
| const parentNode = graphNodes.find(p => p.pos === graphLinks.find(l => l.target === n.pos)?.source); | ||
| if (parentNode) { | ||
| const parentHierarchyNode = nodeMap.get(parentNode.pos); | ||
| if (parentHierarchyNode) { | ||
| parentHierarchyNode.children.push(hierarchyNode); | ||
| } | ||
| } |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nested find() operations within a loop create O(n³) complexity. Consider building a lookup map for parent relationships to improve performance.
| // Build hierarchy based on parent relationships | |
| graphNodes.forEach(n => { | |
| const hierarchyNode = nodeMap.get(n.pos); | |
| if (n.level === 1) { | |
| // Level 1 nodes go directly under root | |
| rootChildren.push(hierarchyNode); | |
| } else if (n.level === 2 && n.parent !== undefined) { | |
| // Level 2 nodes go under their level 1 parent | |
| const parentNode = graphNodes.find(p => p.pos === graphLinks.find(l => l.target === n.pos)?.source); | |
| if (parentNode) { | |
| const parentHierarchyNode = nodeMap.get(parentNode.pos); | |
| if (parentHierarchyNode) { | |
| parentHierarchyNode.children.push(hierarchyNode); | |
| } | |
| } | |
| } else if (n.level === 3 && n.parent !== undefined) { | |
| // Level 3 nodes go under their level 2 parent | |
| const parentNode = graphNodes.find(p => p.pos === graphLinks.find(l => l.target === n.pos)?.source); | |
| if (parentNode) { | |
| const parentHierarchyNode = nodeMap.get(parentNode.pos); | |
| if (parentHierarchyNode) { | |
| parentHierarchyNode.children.push(hierarchyNode); | |
| } | |
| } | |
| // Build lookup map from target pos to source pos for fast parent lookup | |
| const linkParentMap = new Map(); | |
| graphLinks.forEach(l => { | |
| linkParentMap.set(l.target, l.source); | |
| }); | |
| // Build hierarchy based on parent relationships | |
| graphNodes.forEach(n => { | |
| const hierarchyNode = nodeMap.get(n.pos); | |
| if (n.level === 1) { | |
| // Level 1 nodes go directly under root | |
| rootChildren.push(hierarchyNode); | |
| } else if ((n.level === 2 || n.level === 3) && n.parent !== undefined) { | |
| // Level 2 and 3 nodes go under their parent | |
| const parentPos = linkParentMap.get(n.pos); | |
| if (parentPos !== undefined) { | |
| const parentHierarchyNode = nodeMap.get(parentPos); | |
| if (parentHierarchyNode) { | |
| parentHierarchyNode.children.push(hierarchyNode); | |
| } | |
| } |
| } | ||
| } else if (n.level === 3 && n.parent !== undefined) { | ||
| // Level 3 nodes go under their level 2 parent | ||
| const parentNode = graphNodes.find(p => p.pos === graphLinks.find(l => l.target === n.pos)?.source); |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate nested find() operations for level 3 nodes. This should use the same optimization as suggested for level 2 nodes.
| function doProcess (vsrc, vdst, f, fields, resultId) { | ||
| function doProcess (vsrc, vdst, vthird, f, fields, resultId) { | ||
| if (ArkimeUtil.isPP(vsrc) || ArkimeUtil.isPP(vdst)) { return; } | ||
| if (vthird && ArkimeUtil.isPP(vthird)) { return; } |
Copilot
AI
Oct 14, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validation for vthird should be consistent with vsrc and vdst checks. Consider extracting this into a helper function to avoid code duplication.
License
I confirm that this contribution is made under an Apache 2.0 license and that I have the authority necessary to make this contribution on behalf of its copyright owner.