diff --git a/ccw/src/templates/dashboard-css/32-issue-manager.css b/ccw/src/templates/dashboard-css/32-issue-manager.css index 026f1fc6..7ea95e25 100644 --- a/ccw/src/templates/dashboard-css/32-issue-manager.css +++ b/ccw/src/templates/dashboard-css/32-issue-manager.css @@ -128,6 +128,29 @@ box-shadow: 0 4px 12px hsl(var(--foreground) / 0.08); } +/* Archived Issue Card */ +.issue-card.archived { + opacity: 0.85; + background: hsl(var(--muted) / 0.3); +} + +.issue-card.archived:hover { + opacity: 1; +} + +.issue-archived-badge { + display: inline-flex; + align-items: center; + padding: 0.125rem 0.375rem; + background: hsl(var(--muted)); + color: hsl(var(--muted-foreground)); + font-size: 0.625rem; + font-weight: 500; + border-radius: 0.25rem; + text-transform: uppercase; + letter-spacing: 0.025em; +} + .issue-card-header { display: flex; align-items: flex-start; diff --git a/ccw/src/templates/dashboard-js/views/issue-manager.js b/ccw/src/templates/dashboard-js/views/issue-manager.js index 4669c0eb..5afaac7a 100644 --- a/ccw/src/templates/dashboard-js/views/issue-manager.js +++ b/ccw/src/templates/dashboard-js/views/issue-manager.js @@ -6,6 +6,7 @@ // ========== Issue State ========== var issueData = { issues: [], + historyIssues: [], // Archived/completed issues from history queue: { tasks: [], solutions: [], conflicts: [], execution_groups: [], grouped_items: {} }, selectedIssue: null, selectedSolution: null, @@ -58,6 +59,18 @@ async function loadIssueData() { } } +async function loadIssueHistory() { + try { + const response = await fetch('/api/issues/history?path=' + encodeURIComponent(projectPath)); + if (!response.ok) throw new Error('Failed to load issue history'); + const data = await response.json(); + issueData.historyIssues = data.issues || []; + } catch (err) { + console.error('Failed to load issue history:', err); + issueData.historyIssues = []; + } +} + async function loadQueueData() { try { const response = await fetch('/api/queue?path=' + encodeURIComponent(projectPath)); @@ -93,10 +106,21 @@ function renderIssueView() { if (!container) return; const issues = issueData.issues || []; + const historyIssues = issueData.historyIssues || []; + // Apply both status and search filters - let filteredIssues = issueData.statusFilter === 'all' - ? issues - : issues.filter(i => i.status === issueData.statusFilter); + let filteredIssues; + if (issueData.statusFilter === 'all') { + filteredIssues = issues; + } else if (issueData.statusFilter === 'completed') { + // For 'completed' filter, include both current completed issues and archived history issues + const currentCompleted = issues.filter(i => i.status === 'completed'); + // Mark history issues as archived for visual distinction + const archivedIssues = historyIssues.map(i => ({ ...i, _isArchived: true })); + filteredIssues = [...currentCompleted, ...archivedIssues]; + } else { + filteredIssues = issues.filter(i => i.status === issueData.statusFilter); + } if (issueData.searchQuery) { const query = issueData.searchQuery.toLowerCase(); @@ -309,12 +333,15 @@ function renderIssueCard(issue) { failed: 'failed' }; + const isArchived = issue._isArchived; + return ` -