mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
- Add lucide.createIcons() calls in renderSessions, renderProjectOverview, renderMcpManager, renderHookManager, renderLiteTasks, showSessionDetailPage - Fixes issue where icons would not appear after page render
198 lines
8.0 KiB
JavaScript
198 lines
8.0 KiB
JavaScript
// ==========================================
|
|
// HOME VIEW - Dashboard Homepage
|
|
// ==========================================
|
|
|
|
function renderDashboard() {
|
|
// Show stats grid and search (may be hidden by MCP view)
|
|
showStatsAndSearch();
|
|
|
|
updateStats();
|
|
updateBadges();
|
|
updateCarousel();
|
|
renderSessions();
|
|
document.getElementById('generatedAt').textContent = workflowData.generatedAt || new Date().toISOString();
|
|
}
|
|
|
|
function showStatsAndSearch() {
|
|
const statsGrid = document.getElementById('statsGrid');
|
|
const searchInput = document.getElementById('searchInput');
|
|
if (statsGrid) statsGrid.style.display = '';
|
|
if (searchInput) searchInput.parentElement.style.display = '';
|
|
}
|
|
|
|
function hideStatsAndCarousel() {
|
|
const statsGrid = document.getElementById('statsGrid');
|
|
const searchInput = document.getElementById('searchInput');
|
|
if (statsGrid) statsGrid.style.display = 'none';
|
|
if (searchInput) searchInput.parentElement.style.display = 'none';
|
|
}
|
|
|
|
function updateStats() {
|
|
const stats = workflowData.statistics || {};
|
|
document.getElementById('statTotalSessions').textContent = stats.totalSessions || 0;
|
|
document.getElementById('statActiveSessions').textContent = stats.activeSessions || 0;
|
|
document.getElementById('statTotalTasks').textContent = stats.totalTasks || 0;
|
|
document.getElementById('statCompletedTasks').textContent = stats.completedTasks || 0;
|
|
}
|
|
|
|
function updateBadges() {
|
|
const active = workflowData.activeSessions || [];
|
|
const archived = workflowData.archivedSessions || [];
|
|
|
|
document.getElementById('badgeAll').textContent = active.length + archived.length;
|
|
document.getElementById('badgeActive').textContent = active.length;
|
|
document.getElementById('badgeArchived').textContent = archived.length;
|
|
|
|
// Lite Tasks badges
|
|
const liteTasks = workflowData.liteTasks || {};
|
|
document.getElementById('badgeLitePlan').textContent = liteTasks.litePlan?.length || 0;
|
|
document.getElementById('badgeLiteFix').textContent = liteTasks.liteFix?.length || 0;
|
|
|
|
// MCP badge - load async if needed
|
|
if (typeof loadMcpConfig === 'function') {
|
|
loadMcpConfig().then(() => {
|
|
if (typeof updateMcpBadge === 'function') {
|
|
updateMcpBadge();
|
|
}
|
|
}).catch(e => console.error('MCP badge update failed:', e));
|
|
}
|
|
}
|
|
|
|
function renderSessions() {
|
|
const container = document.getElementById('mainContent');
|
|
|
|
let sessions = [];
|
|
|
|
if (currentFilter === 'all' || currentFilter === 'active') {
|
|
sessions = sessions.concat((workflowData.activeSessions || []).map(s => ({ ...s, _isActive: true })));
|
|
}
|
|
if (currentFilter === 'all' || currentFilter === 'archived') {
|
|
sessions = sessions.concat((workflowData.archivedSessions || []).map(s => ({ ...s, _isActive: false })));
|
|
}
|
|
|
|
if (sessions.length === 0) {
|
|
container.innerHTML = `
|
|
<div class="empty-state" style="grid-column: 1/-1;">
|
|
<div class="empty-icon"><i data-lucide="inbox" class="w-12 h-12"></i></div>
|
|
<div class="empty-title">No Sessions Found</div>
|
|
<div class="empty-text">No workflow sessions match your current filter.</div>
|
|
</div>
|
|
`;
|
|
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = `<div class="sessions-grid">${sessions.map(session => renderSessionCard(session)).join('')}</div>`;
|
|
|
|
// Initialize Lucide icons after rendering
|
|
if (typeof lucide !== 'undefined') lucide.createIcons();
|
|
}
|
|
|
|
function renderSessionCard(session) {
|
|
const tasks = session.tasks || [];
|
|
const taskCount = session.taskCount || tasks.length;
|
|
const completed = tasks.filter(t => t.status === 'completed').length;
|
|
const progress = taskCount > 0 ? Math.round((completed / taskCount) * 100) : 0;
|
|
|
|
// Use _isActive flag set during rendering, default to true
|
|
const isActive = session._isActive !== false;
|
|
const date = session.created_at;
|
|
|
|
// Get session type badge
|
|
const sessionType = session.type || 'workflow';
|
|
const typeBadge = sessionType !== 'workflow' ? `<span class="session-type-badge ${sessionType}">${sessionType}</span>` : '';
|
|
|
|
// Store session data for modal
|
|
const sessionKey = `session-${session.session_id}`.replace(/[^a-zA-Z0-9-]/g, '-');
|
|
sessionDataStore[sessionKey] = session;
|
|
|
|
// Special rendering for review sessions
|
|
if (sessionType === 'review') {
|
|
return renderReviewSessionCard(session, sessionKey, typeBadge, isActive, date);
|
|
}
|
|
|
|
return `
|
|
<div class="session-card" onclick="showSessionDetailPage('${sessionKey}')">
|
|
<div class="session-header">
|
|
<div class="session-title">${escapeHtml(session.session_id || 'Unknown')}</div>
|
|
<div class="session-badges">
|
|
${typeBadge}
|
|
<span class="session-status ${isActive ? 'active' : 'archived'}">
|
|
${isActive ? 'ACTIVE' : 'ARCHIVED'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="session-body">
|
|
<div class="session-meta">
|
|
<span class="session-meta-item"><i data-lucide="calendar" class="w-3.5 h-3.5 inline mr-1"></i>${formatDate(date)}</span>
|
|
<span class="session-meta-item"><i data-lucide="list-checks" class="w-3.5 h-3.5 inline mr-1"></i>${taskCount} tasks</span>
|
|
</div>
|
|
${taskCount > 0 ? `
|
|
<div class="progress-container">
|
|
<span class="progress-label">Progress</span>
|
|
<div class="progress-bar-wrapper">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" style="width: ${progress}%"></div>
|
|
</div>
|
|
<span class="progress-text">${completed}/${taskCount} (${progress}%)</span>
|
|
</div>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
// Special card rendering for review sessions
|
|
function renderReviewSessionCard(session, sessionKey, typeBadge, isActive, date) {
|
|
// Calculate findings stats from reviewDimensions
|
|
const dimensions = session.reviewDimensions || [];
|
|
let totalFindings = 0;
|
|
let criticalCount = 0;
|
|
let highCount = 0;
|
|
let mediumCount = 0;
|
|
let lowCount = 0;
|
|
|
|
dimensions.forEach(dim => {
|
|
const findings = dim.findings || [];
|
|
totalFindings += findings.length;
|
|
criticalCount += findings.filter(f => f.severity === 'critical').length;
|
|
highCount += findings.filter(f => f.severity === 'high').length;
|
|
mediumCount += findings.filter(f => f.severity === 'medium').length;
|
|
lowCount += findings.filter(f => f.severity === 'low').length;
|
|
});
|
|
|
|
return `
|
|
<div class="session-card" onclick="showSessionDetailPage('${sessionKey}')">
|
|
<div class="session-header">
|
|
<div class="session-title">${escapeHtml(session.session_id || 'Unknown')}</div>
|
|
<div class="session-badges">
|
|
${typeBadge}
|
|
<span class="session-status ${isActive ? 'active' : 'archived'}">
|
|
${isActive ? 'ACTIVE' : 'ARCHIVED'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="session-body">
|
|
<div class="session-meta">
|
|
<span class="session-meta-item"><i data-lucide="calendar" class="w-3.5 h-3.5 inline mr-1"></i>${formatDate(date)}</span>
|
|
<span class="session-meta-item"><i data-lucide="search" class="w-3.5 h-3.5 inline mr-1"></i>${totalFindings} findings</span>
|
|
</div>
|
|
${totalFindings > 0 ? `
|
|
<div class="review-findings-summary">
|
|
<div class="findings-severity-row">
|
|
${criticalCount > 0 ? `<span class="finding-count critical"><i data-lucide="alert-circle" class="w-3 h-3 inline"></i> ${criticalCount}</span>` : ''}
|
|
${highCount > 0 ? `<span class="finding-count high"><i data-lucide="alert-triangle" class="w-3 h-3 inline"></i> ${highCount}</span>` : ''}
|
|
${mediumCount > 0 ? `<span class="finding-count medium"><i data-lucide="info" class="w-3 h-3 inline"></i> ${mediumCount}</span>` : ''}
|
|
${lowCount > 0 ? `<span class="finding-count low"><i data-lucide="check-circle" class="w-3 h-3 inline"></i> ${lowCount}</span>` : ''}
|
|
</div>
|
|
<div class="dimensions-info">
|
|
${dimensions.length} dimensions
|
|
</div>
|
|
</div>
|
|
` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|