diff --git a/ccw/src/core/dashboard-generator.js b/ccw/src/core/dashboard-generator.js index fc0f3601..4665c01b 100644 --- a/ccw/src/core/dashboard-generator.js +++ b/ccw/src/core/dashboard-generator.js @@ -7,8 +7,8 @@ const __dirname = dirname(__filename); // Bundled template paths const UNIFIED_TEMPLATE = join(__dirname, '../templates/dashboard.html'); -const CSS_FILE = join(__dirname, '../templates/dashboard.css'); const JS_FILE = join(__dirname, '../templates/dashboard.js'); +const CSS_FILE = join(__dirname, '../templates/dashboard.css'); const WORKFLOW_TEMPLATE = join(__dirname, '../templates/workflow-dashboard.html'); const REVIEW_TEMPLATE = join(__dirname, '../templates/review-cycle-dashboard.html'); @@ -41,9 +41,9 @@ export async function generateDashboard(data) { function generateFromUnifiedTemplate(data) { let html = readFileSync(UNIFIED_TEMPLATE, 'utf8'); - // Read CSS and JS files - const cssContent = existsSync(CSS_FILE) ? readFileSync(CSS_FILE, 'utf8') : ''; + // Read JS and CSS files let jsContent = existsSync(JS_FILE) ? readFileSync(JS_FILE, 'utf8') : ''; + let cssContent = existsSync(CSS_FILE) ? readFileSync(CSS_FILE, 'utf8') : ''; // Prepare complete workflow data const workflowData = { @@ -71,9 +71,9 @@ function generateFromUnifiedTemplate(data) { jsContent = jsContent.replace(/\{\{PROJECT_PATH\}\}/g, projectPath.replace(/\\/g, '/')); jsContent = jsContent.replace('{{RECENT_PATHS}}', JSON.stringify(recentPaths)); - // Inject CSS and JS into HTML template - html = html.replace('{{CSS_CONTENT}}', cssContent); + // Inject JS and CSS into HTML template html = html.replace('{{JS_CONTENT}}', jsContent); + html = html.replace('{{CSS_CONTENT}}', cssContent); // Also replace any remaining placeholders in HTML html = html.replace(/\{\{PROJECT_PATH\}\}/g, projectPath.replace(/\\/g, '/')); diff --git a/ccw/src/core/data-aggregator.js b/ccw/src/core/data-aggregator.js index aaa3f6e5..a3d480d1 100644 --- a/ccw/src/core/data-aggregator.js +++ b/ccw/src/core/data-aggregator.js @@ -102,7 +102,10 @@ async function processSession(session, isActive) { task_id: taskData.id || basename(taskFile, '.json'), title: taskData.title || 'Untitled Task', status: taskData.status || 'pending', - type: taskData.meta?.type || 'task' + type: taskData.meta?.type || 'task', + meta: taskData.meta || {}, + context: taskData.context || {}, + flow_control: taskData.flow_control || {} }); } catch { // Skip invalid task files @@ -120,11 +123,33 @@ async function processSession(session, isActive) { result.reviewSummary = loadReviewSummary(reviewDir); } } else { - // For archived, just count tasks + // For archived, also load tasks (same as active) const taskDir = join(session.path, '.task'); if (existsSync(taskDir)) { const taskFiles = await safeGlob('IMPL-*.json', taskDir); - result.taskCount = taskFiles.length; + for (const taskFile of taskFiles) { + try { + const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8')); + result.tasks.push({ + task_id: taskData.id || basename(taskFile, '.json'), + title: taskData.title || 'Untitled Task', + status: taskData.status || 'completed', // Archived tasks are usually completed + type: taskData.meta?.type || 'task' + }); + } catch { + // Skip invalid task files + } + } + // Sort tasks by ID + result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id)); + result.taskCount = result.tasks.length; + } + + // Check for review data in archived sessions too + const reviewDir = join(session.path, '.review'); + if (existsSync(reviewDir)) { + result.hasReview = true; + result.reviewSummary = loadReviewSummary(reviewDir); } } diff --git a/ccw/src/templates/dashboard.css b/ccw/src/templates/dashboard.css index 6217b7eb..5976b710 100644 --- a/ccw/src/templates/dashboard.css +++ b/ccw/src/templates/dashboard.css @@ -1,299 +1,41 @@ -/* CSS Variables */ -:root { - /* Background */ - --bg-primary: #f8f9fa; - --bg-secondary: #ffffff; - --bg-card: #ffffff; - --bg-sidebar: #f1f3f5; - --bg-hover: #e9ecef; +/* =================================== + Dashboard - Complementary Styles + ================================== */ - /* Text */ - --text-primary: #212529; - --text-secondary: #495057; - --text-muted: #868e96; +/* This file contains only essential CSS that cannot be achieved + with Tailwind utilities. All layout, colors, and basic styling + are handled by Tailwind classes in dashboard.html. - /* Accent */ - --accent-color: #228be6; - --accent-hover: #1c7ed6; - --accent-light: #e7f5ff; + CSS variables are defined inline in dashboard.html -
-