Skip to content

feat: Dependency Graph V2 - Impact Analysis & Visual Redesign#227

Merged
DevanshuNEU merged 10 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feat/dependency-graph-v2
Jan 27, 2026
Merged

feat: Dependency Graph V2 - Impact Analysis & Visual Redesign#227
DevanshuNEU merged 10 commits into
OpenCodeIntel:mainfrom
DevanshuNEU:feat/dependency-graph-v2

Conversation

@DevanshuNEU

@DevanshuNEU DevanshuNEU commented Jan 27, 2026

Copy link
Copy Markdown
Collaborator

Description

Complete redesign of the Dependency Graph with click-to-highlight impact analysis.

Changes

Core Impact Analysis

  • Click any node to see all files that depend on it (direct + transitive)
  • Risk scoring: Low/Medium/High/Critical based on dependent count
  • Impact panel: Slide-out panel showing affected files with click-to-navigate

Visual Improvements

  • Left-to-right layout (import flow direction)
  • Entry point indicators, file type icons, risk badges
  • Metrics bar: Total Files, Dependencies, Entry Points, Critical Files
  • Light mode + Dark mode support
  • Uses shadcn/ui components (Card, Button, Badge)

UX Features

  • Top 15 most important files by default
  • Show All / Tests toggles
  • Fast rebuild scripts (make f ~10s)

Commits

  • feat(dependency-graph): implement Phase 1 impact analysis
  • fix: container height for ReactFlow rendering
  • refactor: use shadcn components, lucide icons, light mode
  • feat: add dev.sh and Makefile for fast rebuilds

Summary by CodeRabbit

  • New Features

    • Rebuilt interactive dependency graph with node visuals, toolbar, impact panel, and expanded impact analysis (direct/transitive dependents, risk levels, entry points).
  • Performance

    • Frontend build tooling migrated to a faster runtime for quicker installs and builds.
  • Chores

    • Consolidated development/build targets into a compact set and added a simple dev CLI for common workflows.
  • Bug Fixes

    • Stabilized dashboard tab content height.

✏️ Tip: You can customize this high-level summary in your review settings.

- Add useImpactAnalysis hook for traversing dependents
- Add custom GraphNode component with risk badges and state styling
- Add ImpactPanel slide-out with direct/transitive dependents
- Add GraphToolbar with show all/filter controls
- Refactor to modular component structure
- Default to top 15 files by importance
- Click-to-highlight with cascade animation
- LR layout for better import flow visualization
@vercel

vercel Bot commented Jan 27, 2026

Copy link
Copy Markdown

@DevanshuNEU is attempting to deploy a commit to the Dev's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jan 27, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds a dev helper script, streamlines Makefile targets, switches the frontend Docker build to Bun, replaces the monolithic DependencyGraph component with a modular implementation (graph rendering, nodes, toolbar, impact analysis hook), and enforces a min-height for DashboardHome tabs.

Changes

Cohort / File(s) Summary
Build & Dev tooling
Makefile, dev.sh
Replaced legacy PHONY targets with a compact set (f, b, all, up, down, restart, logs, status, clean, help) and added dev.sh for rebuild, logs, restart, stop, status, and no-cache full rebuild workflows.
Frontend Docker build
frontend/Dockerfile
Switched builder from node:20-alpine to oven/bun:1; replaced npm steps with bun install (frozen lockfile) and bun run build; adjusted multi-stage copy into nginx, added HEALTHCHECK and CMD.
DependencyGraph (removed → modular)
frontend/src/components/DependencyGraph.tsx (removed), frontend/src/components/DependencyGraph/...
frontend/src/components/DependencyGraph/index.tsx, .../GraphNode.tsx, .../GraphToolbar.tsx, .../ImpactPanel.tsx, .../hooks/useImpactAnalysis.ts
Removed the single-file DependencyGraph.tsx and added a modular implementation: index.tsx (React Flow-based main component), GraphNode (custom node renderer), GraphToolbar (controls), ImpactPanel (impact UI), and useImpactAnalysis (graph metrics and dependents/imports API). Files implement layout, selection, metrics, and impact queries.
Dashboard layout
frontend/src/components/dashboard/DashboardHome.tsx
Added min-h-[700px] to the tab content container to stabilize tab layout height.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant User as User
participant DG as DependencyGraph UI
participant API as Backend API
participant IA as useImpactAnalysis
participant RF as ReactFlow

User->>DG: open graph view
DG->>API: fetch dependency graph JSON
API-->>DG: return graph data
DG->>IA: compute adjacency, fileMetrics, entryPoints
IA-->>DG: provide getDependents/getImports/topFiles
DG->>RF: render nodes & edges using GraphNode
User->>RF: click node
RF->>DG: selection event
DG->>IA: getDependents(selectedNode)
IA-->>DG: direct/transitive dependents & risk
DG->>RF: update styles and show ImpactPanel

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 I nibbled code and split the vine,

dev.sh hops, targets now align,
Bun bakes assets warm and fleet,
Nodes and impacts spring to meet,
A little rabbit claps its feet!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: a redesigned Dependency Graph component with V2 versioning, impact analysis functionality, and visual improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@frontend/Dockerfile`:
- Around line 19-20: The RUN line "RUN bun install --frozen-lockfile || bun
install" makes installs non-deterministic; instead, make the intent explicit by
checking for the presence of the lockfile (the COPY step uses "COPY package.json
bun.lock* ./") and run either "bun install --frozen-lockfile" when a bun.lock*
exists or fail the build (or explicitly run unfrozen install only when you
intentionally want that behavior). Update the Dockerfile around the COPY/CMD
block so the build fails on missing/outdated lockfile (or clearly branches based
on existence of bun.lock*) and replace the ambiguous "RUN bun install
--frozen-lockfile || bun install" with the explicit conditional or single
deterministic "bun install --frozen-lockfile" call referenced here.

In `@frontend/src/components/DependencyGraph/GraphNode.tsx`:
- Around line 32-82: getFileType currently collapses .json/.yaml and similar
into 'config' and never returns 'json', 'yaml' or 'markdown', so FILE_ICONS and
LANGUAGE_COLORS for those keys are unused; update the getFileType function to
detect extensions (.json -> 'json', .yaml/.yml -> 'yaml', .md/.markdown ->
'markdown') and return those specific strings, keep existing detection for
'test', 'config' (for generic config filenames), and language-based return for
'python'/'javascript'/'typescript' so the constants FILE_ICONS and
LANGUAGE_COLORS are actually applied.

In `@frontend/src/components/DependencyGraph/ImpactPanel.tsx`:
- Around line 1-116: The CollapsibleSection component's local isOpen state
(initialized from defaultOpen) doesn't update when switching files, so add a
useEffect inside CollapsibleSection that watches defaultOpen and files and calls
setIsOpen(defaultOpen) to sync the collapse state on prop changes; locate the
isOpen and setIsOpen usage in CollapsibleSection and ensure the effect runs when
either defaultOpen or files changes to reset the UI when a new file is selected.
🧹 Nitpick comments (9)
frontend/Dockerfile (1)

1-2: Pin the Bun base image to a concrete version/digest.
A floating tag like oven/bun:1 can change unexpectedly and break reproducibility.

Makefile (1)

4-38: Include all alias targets in .PHONY.
Ensures frontend, backend, up, logs-backend, and ps can’t be shadowed by files.

♻️ Proposed fix
-.PHONY: f b all logs restart down status clean help
+.PHONY: f frontend b backend all up down restart logs logs-backend status ps clean help
frontend/src/components/DependencyGraph/GraphToolbar.tsx (1)

2-2: Unused import: Filter

The Filter icon is imported but not used in the component. Consider removing it to keep imports clean.

-import { RotateCcw, Maximize2, Filter, Eye, EyeOff } from 'lucide-react'
+import { RotateCcw, Maximize2, Eye, EyeOff } from 'lucide-react'
frontend/src/components/DependencyGraph/index.tsx (4)

96-96: Consider typing rawGraphData instead of using any.

Using any loses type safety. Consider defining a proper type or reusing the GraphData interface from useImpactAnalysis.ts.

+interface GraphData {
+  nodes: Array<{ id: string; label?: string; language?: string; import_count?: number; imports?: number }>
+  edges: Array<{ source: string; target: string }>
+}
+
-const [rawGraphData, setRawGraphData] = useState<any>(null)
+const [rawGraphData, setRawGraphData] = useState<GraphData | null>(null)

This would also enable proper typing on lines 112, 137-140, 177-178, 238, 253, 264, and 293.


205-210: Missing fitView in dependency array.

The fitView function is used inside this effect but not listed in the dependency array. While fitView from useReactFlow is typically stable, omitting it may cause linting warnings or stale closure issues.

   useEffect(() => {
     if (nodes.length > 0) {
       const minZoom = nodes.length > 20 ? 0.5 : 0.3
       setTimeout(() => fitView({ padding: 0.2, duration: 300, minZoom }), 100)
     }
-  }, [showAll, showTests])
+  }, [showAll, showTests, fitView, nodes.length])

Note: Adding nodes.length would trigger fitView on every node change. If that's undesired, consider using a ref to track if this is a toggle-triggered change.


109-127: Dependency array includes unused impact.fileMetrics.

The visibleNodeIds memo depends on impact.fileMetrics (line 127), but the memo body only uses impact.isReady and impact.getTopFiles. Since getTopFiles is already memoized with fileMetrics as its dependency, this extra dependency may cause unnecessary recalculations.

-  }, [rawGraphData, impact.isReady, impact.fileMetrics, showAll, showTests])
+  }, [rawGraphData, impact.isReady, impact.getTopFiles, showAll, showTests])

Alternatively, if getTopFiles identity changes frequently, consider inlining the slice logic here.


302-303: Fixed height may limit responsiveness.

The graph container has a hardcoded 600px height. This works but may not adapt well to different viewport sizes. Consider using a responsive approach like calc(100vh - offset) or a CSS class if the design requirements allow flexibility.

frontend/src/components/DependencyGraph/hooks/useImpactAnalysis.ts (2)

73-97: Performance: Use Sets instead of arrays with includes() checks.

The directDependents.includes(depId) and transitiveDependents.includes(depId) calls (lines 89, 91) are O(n) operations inside a loop, leading to O(n²) complexity for large graphs. Using Sets for membership checks would be O(1).

♻️ Suggested improvement
 const getDependents = useCallback((fileId: string, maxDepth = Infinity): ImpactResult => {
-  const directDependents: string[] = []
-  const transitiveDependents: string[] = []
+  const directDependentsSet = new Set<string>()
+  const transitiveDependentsSet = new Set<string>()
   const visited = new Set<string>()

   function traverse(currentId: string, depth: number) {
     if (visited.has(currentId) || depth > maxDepth) return
     visited.add(currentId)

     const dependents = fileToDependents.get(currentId)
     if (!dependents) return

     dependents.forEach(depId => {
       if (depId === fileId) return // skip self
       
       if (depth === 0) {
-        if (!directDependents.includes(depId)) directDependents.push(depId)
+        directDependentsSet.add(depId)
       } else {
-        if (!transitiveDependents.includes(depId) && !directDependents.includes(depId)) {
-          transitiveDependents.push(depId)
+        if (!directDependentsSet.has(depId)) {
+          transitiveDependentsSet.add(depId)
         }
       }
       traverse(depId, depth + 1)
     })
   }

   traverse(fileId, 0)

+  const directDependents = Array.from(directDependentsSet)
+  const transitiveDependents = Array.from(transitiveDependentsSet)
   const allDependents = [...directDependents, ...transitiveDependents]

158-161: Consider using a Map for O(1) lookups.

getFileMetrics uses Array.find() which is O(n). Since it's called for every node during rendering (in index.tsx line 141), this becomes O(n²) for large graphs. A pre-computed Map would provide O(1) lookups.

♻️ Suggested improvement
+  // Pre-compute map for O(1) lookups
+  const fileMetricsMap = useMemo(() => {
+    return new Map(fileMetrics.map(f => [f.id, f]))
+  }, [fileMetrics])
+
   // Get metrics for a specific file
   const getFileMetrics = useCallback((fileId: string): FileMetrics | null => {
-    return fileMetrics.find(f => f.id === fileId) || null
-  }, [fileMetrics])
+    return fileMetricsMap.get(fileId) || null
+  }, [fileMetricsMap])

Comment thread frontend/Dockerfile Outdated
Comment thread frontend/src/components/DependencyGraph/GraphNode.tsx
Comment thread frontend/src/components/DependencyGraph/ImpactPanel.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@frontend/src/components/DependencyGraph/GraphNode.tsx`:
- Around line 44-53: LANGUAGE_COLORS is missing a 'markdown' entry so when
getFileType returns 'markdown' the lookup falls back to 'unknown'; update
LANGUAGE_COLORS to include a 'markdown' key with the appropriate Tailwind
classes (match the visual intent used in FILE_ICONS/FileText) so markdown files
use the intended styling; verify getFileType and the lookup at where
LANGUAGE_COLORS is referenced still work without further changes.
🧹 Nitpick comments (3)
frontend/src/components/DependencyGraph/GraphNode.tsx (1)

1-18: Unused icon imports.

AlertTriangle, Flame, CheckCircle2, and CircleAlert are imported but not used in this component. The local RISK_CONFIG only uses variant, label, and className properties—not icons. These icons are used in ImpactPanel.tsx instead.

♻️ Suggested fix
 import { 
   FileCode2, 
   FileJson, 
   FileText, 
   TestTube2, 
   Settings, 
-  File,
-  AlertTriangle,
-  Flame,
-  CheckCircle2,
-  CircleAlert
+  File
 } from 'lucide-react'
frontend/src/components/DependencyGraph/ImpactPanel.tsx (2)

245-252: Parameter naming inconsistency.

onAnalyzeInSearch is typed as (fileId: string) => void (line 28), but line 247 passes fullPath. While both are strings and likely equivalent in this context, the naming mismatch between fileId and fullPath could cause confusion for future maintainers.

Consider renaming the parameter type to match the actual usage:

-  onAnalyzeInSearch?: (fileId: string) => void
+  onAnalyzeInSearch?: (fullPath: string) => void

131-144: Consider adding aria-expanded for accessibility.

The collapsible section toggle would benefit from aria-expanded to convey state to screen readers.

♻️ Suggested enhancement
       <button
         onClick={() => setIsOpen(!isOpen)}
+        aria-expanded={isOpen}
         className="w-full flex items-center gap-2 text-left hover:bg-zinc-100 dark:hover:bg-zinc-800/50 -mx-2 px-2 py-1 rounded transition-colors"
       >

Comment thread frontend/src/components/DependencyGraph/GraphNode.tsx
@vercel

vercel Bot commented Jan 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
opencodeintel Ready Ready Preview, Comment Jan 27, 2026 9:35pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant