branch filtering

This commit is contained in:
James
2025-12-22 18:33:49 -05:00
parent ffcdbf7d75
commit 12a796bcbb
11 changed files with 591 additions and 44 deletions

View File

@@ -2,26 +2,37 @@ import { useMemo } from 'react';
import { Node, Edge } from '@xyflow/react';
import { Feature } from '@/store/app-store';
import { getBlockingDependencies } from '@automaker/dependency-resolver';
import { GraphFilterResult } from './use-graph-filter';
export interface TaskNodeData extends Feature {
isBlocked: boolean;
isRunning: boolean;
blockingDependencies: string[];
// Filter highlight states
isMatched?: boolean;
isHighlighted?: boolean;
isDimmed?: boolean;
}
export type TaskNode = Node<TaskNodeData, 'task'>;
export type DependencyEdge = Edge<{ sourceStatus: Feature['status']; targetStatus: Feature['status'] }>;
export type DependencyEdge = Edge<{
sourceStatus: Feature['status'];
targetStatus: Feature['status'];
isHighlighted?: boolean;
isDimmed?: boolean;
}>;
interface UseGraphNodesProps {
features: Feature[];
runningAutoTasks: string[];
filterResult?: GraphFilterResult;
}
/**
* Transforms features into React Flow nodes and edges
* Creates dependency edges based on feature.dependencies array
*/
export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps) {
export function useGraphNodes({ features, runningAutoTasks, filterResult }: UseGraphNodesProps) {
const { nodes, edges } = useMemo(() => {
const nodeList: TaskNode[] = [];
const edgeList: DependencyEdge[] = [];
@@ -30,11 +41,22 @@ export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps
// Create feature map for quick lookups
features.forEach((f) => featureMap.set(f.id, f));
// Extract filter state
const hasActiveFilter = filterResult?.hasActiveFilter ?? false;
const matchedNodeIds = filterResult?.matchedNodeIds ?? new Set<string>();
const highlightedNodeIds = filterResult?.highlightedNodeIds ?? new Set<string>();
const highlightedEdgeIds = filterResult?.highlightedEdgeIds ?? new Set<string>();
// Create nodes
features.forEach((feature) => {
const isRunning = runningAutoTasks.includes(feature.id);
const blockingDeps = getBlockingDependencies(feature, features);
// Calculate filter highlight states
const isMatched = hasActiveFilter && matchedNodeIds.has(feature.id);
const isHighlighted = hasActiveFilter && highlightedNodeIds.has(feature.id);
const isDimmed = hasActiveFilter && !highlightedNodeIds.has(feature.id);
const node: TaskNode = {
id: feature.id,
type: 'task',
@@ -44,6 +66,10 @@ export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps
isBlocked: blockingDeps.length > 0,
isRunning,
blockingDependencies: blockingDeps,
// Filter states
isMatched,
isHighlighted,
isDimmed,
},
};
@@ -55,8 +81,14 @@ export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps
// Only create edge if the dependency exists in current view
if (featureMap.has(depId)) {
const sourceFeature = featureMap.get(depId)!;
const edgeId = `${depId}->${feature.id}`;
// Calculate edge highlight states
const edgeIsHighlighted = hasActiveFilter && highlightedEdgeIds.has(edgeId);
const edgeIsDimmed = hasActiveFilter && !highlightedEdgeIds.has(edgeId);
const edge: DependencyEdge = {
id: `${depId}->${feature.id}`,
id: edgeId,
source: depId,
target: feature.id,
type: 'dependency',
@@ -64,6 +96,8 @@ export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps
data: {
sourceStatus: sourceFeature.status,
targetStatus: feature.status,
isHighlighted: edgeIsHighlighted,
isDimmed: edgeIsDimmed,
},
};
edgeList.push(edge);
@@ -73,7 +107,7 @@ export function useGraphNodes({ features, runningAutoTasks }: UseGraphNodesProps
});
return { nodes: nodeList, edges: edgeList };
}, [features, runningAutoTasks]);
}, [features, runningAutoTasks, filterResult]);
return { nodes, edges };
}