Merge main into recovery/corruption-incident-and-ui2-work
Fix merge conflicts intelligently: - package.json: Use main's test script pattern (tests/guards/*.test.mjs && tests/**/*.test.ts) - src/app/api/events/route.ts: Merge polling logic with telemetry event emission - src/hooks/use-beads-subscription.ts: Merge event type handling (issues/telemetry/activity) All changes preserve the new telemetry-based architecture while accepting main's improved test coverage patterns.
This commit is contained in:
commit
e74606da37
17 changed files with 454 additions and 49 deletions
|
|
@ -1,5 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import type { KanbanFilterOptions, KanbanStats } from '../../lib/kanban';
|
||||
|
|
@ -12,6 +13,7 @@ interface KanbanControlsProps {
|
|||
filters: KanbanFilterOptions;
|
||||
stats: KanbanStats;
|
||||
epics: BeadIssue[];
|
||||
issues: BeadIssue[];
|
||||
onFiltersChange: (filters: KanbanFilterOptions) => void;
|
||||
onNextActionable: () => void;
|
||||
nextActionableFeedback?: string | null;
|
||||
|
|
@ -21,6 +23,7 @@ export function KanbanControls({
|
|||
filters,
|
||||
stats,
|
||||
epics,
|
||||
issues,
|
||||
onFiltersChange,
|
||||
onNextActionable,
|
||||
nextActionableFeedback = null,
|
||||
|
|
@ -29,12 +32,24 @@ export function KanbanControls({
|
|||
'ui-field rounded-xl px-3 py-2.5 text-sm outline-none transition';
|
||||
|
||||
// Build bead counts map for EpicChipStrip
|
||||
const beadCounts = new Map<string, number>();
|
||||
for (const epic of epics) {
|
||||
// Count non-epic issues that belong to this epic
|
||||
const count = epic.dependencies?.filter(d => d.type === 'parent' && d.target === epic.id).length ?? 0;
|
||||
beadCounts.set(epic.id, count);
|
||||
}
|
||||
// Count non-epic issues that have this epic as their parent
|
||||
const beadCounts = useMemo(() => {
|
||||
const counts = new Map<string, number>();
|
||||
for (const epic of epics) {
|
||||
let count = 0;
|
||||
for (const issue of issues) {
|
||||
if (issue.issue_type === 'epic') continue;
|
||||
const parentDep = issue.dependencies.find(d => d.type === 'parent');
|
||||
const inferredParent = issue.id.includes('.') ? issue.id.split('.')[0] : null;
|
||||
const parentEpicId = parentDep?.target ?? inferredParent;
|
||||
if (parentEpicId === epic.id) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
counts.set(epic.id, count);
|
||||
}
|
||||
return counts;
|
||||
}, [epics, issues]);
|
||||
|
||||
return (
|
||||
<section className="grid gap-3">
|
||||
|
|
|
|||
|
|
@ -230,6 +230,7 @@ export function KanbanPage({
|
|||
filters={filters}
|
||||
stats={stats}
|
||||
epics={localIssues.filter((issue) => issue.issue_type === 'epic')}
|
||||
issues={localIssues}
|
||||
onFiltersChange={setFilters}
|
||||
onNextActionable={handleNextActionable}
|
||||
nextActionableFeedback={nextActionableFeedback}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue