feat(integration): WP-3 workflow filter integration

Apply workflow state filter to displayed issues using enrichment
data. Unenriched issues treated as 'new' for filtering. Pass
enrichments map to IssueList for data flow. Use workflowFilteredIssues
instead of raw filteredIssues.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Sondre Engebråten
2026-02-12 19:49:27 +01:00
co-authored by Claude Opus 4.6
parent b649b9b91f
commit cbbe06347c
2 changed files with 86 additions and 1 deletions
@@ -96,6 +96,15 @@ export function GitHubIssues({ onOpenSettings, onNavigateToTask }: GitHubIssuesP
const stateCounts = useEnrichmentStore((s) => s.getStateCounts());
const [workflowFilter, setWorkflowFilter] = useState<WorkflowState[]>([]);
// Apply workflow filter to issues
const workflowFilteredIssues = useMemo(() => {
if (workflowFilter.length === 0) return filteredIssues;
return filteredIssues.filter((issue) => {
const state = enrichments[String(issue.number)]?.triageState ?? 'new';
return workflowFilter.includes(state);
});
}, [filteredIssues, workflowFilter, enrichments]);
const [showInvestigateDialog, setShowInvestigateDialog] = useState(false);
const [selectedIssueForInvestigation, setSelectedIssueForInvestigation] =
useState<GitHubIssue | null>(null);
@@ -203,7 +212,7 @@ export function GitHubIssues({ onOpenSettings, onNavigateToTask }: GitHubIssuesP
{/* Issue List */}
<div className="w-1/2 border-r border-border flex flex-col">
<IssueList
issues={filteredIssues}
issues={workflowFilteredIssues}
selectedIssueNumber={selectedIssueNumber}
isLoading={isLoading}
isLoadingMore={isLoadingMore}
@@ -212,6 +221,7 @@ export function GitHubIssues({ onOpenSettings, onNavigateToTask }: GitHubIssuesP
onSelectIssue={selectIssue}
onInvestigate={handleInvestigate}
onLoadMore={!isSearchActive ? handleLoadMore : undefined}
enrichments={enrichments}
/>
</div>
@@ -0,0 +1,75 @@
import { describe, it, expect } from 'vitest';
import type { IssueEnrichment, WorkflowState } from '../../../../shared/types/enrichment';
/**
* Unit tests for the workflow filter logic extracted from GitHubIssues container.
* Tests the pure filtering function without React rendering.
*/
interface MinimalIssue {
number: number;
state: 'open' | 'closed';
title: string;
}
function applyWorkflowFilter(
issues: MinimalIssue[],
enrichments: Record<string, Partial<IssueEnrichment>>,
workflowFilter: WorkflowState[],
): MinimalIssue[] {
if (workflowFilter.length === 0) return issues;
return issues.filter((issue) => {
const state = (enrichments[String(issue.number)]?.triageState ?? 'new') as WorkflowState;
return workflowFilter.includes(state);
});
}
const issues: MinimalIssue[] = [
{ number: 1, state: 'open', title: 'Issue 1' },
{ number: 2, state: 'open', title: 'Issue 2' },
{ number: 3, state: 'closed', title: 'Issue 3' },
{ number: 4, state: 'open', title: 'Issue 4' },
{ number: 5, state: 'open', title: 'Issue 5' },
];
const enrichments: Record<string, Partial<IssueEnrichment>> = {
'1': { triageState: 'new' as WorkflowState },
'2': { triageState: 'triage' as WorkflowState },
'3': { triageState: 'done' as WorkflowState },
'4': { triageState: 'ready' as WorkflowState },
// Issue 5 has no enrichment — defaults to 'new'
};
describe('Workflow filter integration', () => {
it('empty filter shows all issues', () => {
const result = applyWorkflowFilter(issues, enrichments, []);
expect(result.length).toBe(5);
});
it('filter to new shows unenriched issues and new state', () => {
const result = applyWorkflowFilter(issues, enrichments, ['new']);
expect(result.map((i) => i.number)).toEqual([1, 5]);
});
it('filter to triage and ready shows matching issues', () => {
const result = applyWorkflowFilter(issues, enrichments, ['triage', 'ready']);
expect(result.map((i) => i.number)).toEqual([2, 4]);
});
it('filter to done includes closed issues with done state', () => {
const result = applyWorkflowFilter(issues, enrichments, ['done']);
expect(result.map((i) => i.number)).toEqual([3]);
});
it('combines with pre-filtered issues (simulating text search)', () => {
// Simulate text search already filtering to issues 1, 2, 3
const preFiltered = issues.filter((i) => i.number <= 3);
const result = applyWorkflowFilter(preFiltered, enrichments, ['new']);
expect(result.map((i) => i.number)).toEqual([1]);
});
it('returns empty when no issues match filter', () => {
const result = applyWorkflowFilter(issues, enrichments, ['in_progress']);
expect(result.length).toBe(0);
});
});