Auto-refresh tab content on switch

This commit is contained in:
Riz Ashraf committed 2026-09-27 09:19:01 +01:00
1 parent 4bae4e9c08
commit b7d1ae78db
1 file changed
+135
+135
View File
@@ -478,6 +478,12 @@
<button class="tab-button" onclick="switchTab('search-tab', this)">Omni-Search</button>
<button class="tab-button" onclick="switchTab('task-tab', this)">Task Board</button>
<button class="tab-button" onclick="switchTab('sticky-tab', this)">Sticky Notes</button>
<button class="tab-button" onclick="switchTab('techdebt-tab', this)">Tech Debt</button>
<button class="tab-button" onclick="switchTab('adrs-tab', this)">Decisions (ADR)</button>
<button class="tab-button" onclick="switchTab('workspaces-tab', this)">Workspaces</button>
<button class="tab-button" onclick="switchTab('memos-tab', this)">Handoffs</button>
<button class="tab-button" onclick="switchTab('snippets-tab', this)">Snippets</button>
<button class="tab-button" onclick="switchTab('pr-tab', this)">PRs</button>
<button class="tab-button" onclick="switchTab('activity-tab', this)">Live Activity</button>
</div>
@@ -529,6 +535,50 @@
</div>
</div>
<div id="techdebt-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>Tech Debt</h2>
<div id="techdebt-container" style="display:flex; flex-direction:column; gap:15px; margin-bottom: 20px;"></div>
<h2 style="border-top: 1px solid var(--border-color); padding-top: 15px;">Resolved Error Patterns</h2>
<div id="errorfixes-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="adrs-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>Architecture Decision Records</h2>
<div id="adrs-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="workspaces-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>Context Workspaces</h2>
<div id="workspaces-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="memos-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>Handoff Memos & Milestones</h2>
<div id="memos-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="snippets-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>Snippets Library</h2>
<div id="snippets-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="pr-tab" class="tab-content">
<div class="panel" style="flex:1; display:flex; flex-direction:column; overflow-y:auto;">
<h2>PR Checklists</h2>
<div id="pr-container" style="display:flex; flex-direction:column; gap:15px;"></div>
</div>
</div>
<div id="activity-tab" class="tab-content">
<div class="panel activity-panel" style="flex:1; display:flex; flex-direction:column;">
<div id="activity-feed" style="flex:1;"></div>
@@ -549,9 +599,16 @@
// Resize graph when becoming visible again
network.redraw();
network.fit();
loadGraph();
} else if (tabId === 'activity-tab') {
const feed = document.getElementById('activity-feed');
feed.scrollTop = feed.scrollHeight;
} else if (tabId === 'task-tab') {
loadTasks();
} else if (tabId === 'sticky-tab') {
loadStickyNotes();
} else {
loadAllExtras();
}
}
@@ -986,6 +1043,82 @@
}
}
async function loadGenericList(endpoint, containerId, formatter) {
try {
const res = await fetch(endpoint);
const data = await res.json();
const container = document.getElementById(containerId);
if (!container) return;
if (!data || data.length === 0) {
container.innerHTML = '<div style="color:var(--text-secondary); padding:20px; text-align:center;">No items recorded.</div>';
return;
}
container.innerHTML = data.map(item => {
const date = item.timestamp ? new Date(item.timestamp * 1000).toLocaleString() : '';
return `<div class="task-card" style="border-left-color: #9b59b6;">
<div style="font-size:0.75em; color:var(--text-secondary); float:right;">${date}</div>
${formatter(item)}
</div>`;
}).join('');
} catch (err) {
console.error(`Failed to load ${endpoint}`, err);
}
}
function loadAllExtras() {
loadGenericList('/api/tech_debts', 'techdebt-container', item => `
<strong>${item.title}</strong>
<div>${item.description}</div>
<div style="margin-top:10px;">
<span style="background:var(--canvas-bg); padding:2px 6px; border-radius:4px; font-size:0.8em; margin-right:8px; border:1px solid var(--border-color);">Severity: ${item.severity || 'Medium'}</span>
<span style="background:var(--canvas-bg); padding:2px 6px; border-radius:4px; font-size:0.8em; border:1px solid var(--border-color);">Status: ${item.status || 'open'}</span>
</div>
`);
loadGenericList('/api/error_fixes', 'errorfixes-container', item => `
<strong>${item.error_message || 'Error'}</strong>
<div style="font-size:0.9em; margin-bottom:8px;"><em>Fix:</em> ${item.fix_description || ''}</div>
<div style="font-family:monospace; font-size:0.85em; color:#e74c3c;">Files: ${(item.files_changed || []).join(', ')}</div>
`);
loadGenericList('/api/adrs', 'adrs-container', item => `
<strong>${item.title}</strong>
<div style="font-size:0.9em; margin-bottom:8px;"><em>Context:</em> ${item.context || ''}</div>
<div style="font-size:0.9em; margin-bottom:8px;"><em>Decision:</em> ${item.decision || ''}</div>
<div style="font-size:0.9em;"><em>Consequences:</em> ${item.consequences || ''}</div>
`);
loadGenericList('/api/context_workspaces', 'workspaces-container', item => `
<strong>${item.name}</strong>
<div style="margin-bottom:8px;">${item.description || ''}</div>
<div style="font-family:monospace; font-size:0.85em; color:#3498db;">${(item.paths || []).join(', ')}</div>
`);
loadGenericList('/api/handoff_memos', 'memos-container', item => `
<strong>Memo from ${item.author || 'System'}</strong>
<div style="white-space:pre-wrap; font-size:0.9em; line-height:1.4;">${item.content || item.summary || ''}</div>
`);
loadGenericList('/api/snippets', 'snippets-container', item => `
<strong>${item.description || 'Snippet'}</strong>
<div style="margin-bottom:8px; font-size:0.8em;">Language: ${item.language || 'txt'} | Tags: ${(item.tags || []).join(', ')}</div>
<pre style="background:#111417; color:#d1d8e0; padding:10px; border-radius:4px; overflow-x:auto; font-size:0.85em;">${item.content || item.code || ''}</pre>
`);
loadGenericList('/api/pr_checklists', 'pr-container', item => `
<strong>${item.name || 'Checklist'}</strong>
<ul style="padding-left:20px; font-size:0.9em;">
${(item.items || []).map(i => {
const check = i.is_completed ? '☑' : '☐';
const strike = i.is_completed ? 'text-decoration:line-through; color:var(--text-secondary);' : '';
return `<li style="${strike}">${check} ${i.description}</li>`;
}).join('')}
</ul>
`);
}
async function loadVersion() {
try {
const res = await fetch('/api/version');
@@ -1005,6 +1138,7 @@
loadTasks();
loadStickyNotes();
loadActivityHistory();
loadAllExtras();
setupWS();
// Listen to theme toggle changes to update graph font colors
@@ -1015,6 +1149,7 @@
loadGraph();
loadTasks();
loadStickyNotes();
loadAllExtras();
}, 5000);
</script>
</body>