refactor(dashboard): optimize template structure and enhance data aggregation

- Reorder CSS and JS file loading in dashboard-generator.js for consistency
- Simplify dashboard.css by removing redundant styles and consolidating to Tailwind-based approach
- Add backup files for dashboard.html, dashboard.css, and review-cycle-dashboard.html
- Create new Tailwind-based dashboard template (dashboard_tailwind.html) and test variant
- Add tailwind.config.js for Tailwind CSS configuration
- Enhance data-aggregator.js to load full task data for archived sessions (previously only counted)
- Add meta, context, and flow_control fields to task objects for richer data representation
- Implement review data loading for archived sessions to match active session behavior
- Improve task sorting consistency across active and archived sessions
- Reduce CSS file size by ~70% through Tailwind utility consolidation while maintaining visual parity
This commit is contained in:
catlog22
2025-12-04 21:41:30 +08:00
parent 39df995e37
commit 942fca7ad8
14 changed files with 9770 additions and 5448 deletions

View File

@@ -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, '/'));

View File

@@ -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);
}
}