Auto-refresh tab content on switch
This commit is contained in:
1 parent
4bae4e9c08
commit
b7d1ae78db
1 file changed
+135
@@ -478,6 +478,12 @@
|
|||||||
<button class="tab-button" onclick="switchTab('search-tab', this)">Omni-Search</button>
|
<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('task-tab', this)">Task Board</button>
|
||||||
<button class="tab-button" onclick="switchTab('sticky-tab', this)">Sticky Notes</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>
|
<button class="tab-button" onclick="switchTab('activity-tab', this)">Live Activity</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -529,6 +535,50 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 id="activity-tab" class="tab-content">
|
||||||
<div class="panel activity-panel" style="flex:1; display:flex; flex-direction:column;">
|
<div class="panel activity-panel" style="flex:1; display:flex; flex-direction:column;">
|
||||||
<div id="activity-feed" style="flex:1;"></div>
|
<div id="activity-feed" style="flex:1;"></div>
|
||||||
@@ -549,9 +599,16 @@
|
|||||||
// Resize graph when becoming visible again
|
// Resize graph when becoming visible again
|
||||||
network.redraw();
|
network.redraw();
|
||||||
network.fit();
|
network.fit();
|
||||||
|
loadGraph();
|
||||||
} else if (tabId === 'activity-tab') {
|
} else if (tabId === 'activity-tab') {
|
||||||
const feed = document.getElementById('activity-feed');
|
const feed = document.getElementById('activity-feed');
|
||||||
feed.scrollTop = feed.scrollHeight;
|
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() {
|
async function loadVersion() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/api/version');
|
const res = await fetch('/api/version');
|
||||||
@@ -1005,6 +1138,7 @@
|
|||||||
loadTasks();
|
loadTasks();
|
||||||
loadStickyNotes();
|
loadStickyNotes();
|
||||||
loadActivityHistory();
|
loadActivityHistory();
|
||||||
|
loadAllExtras();
|
||||||
setupWS();
|
setupWS();
|
||||||
|
|
||||||
// Listen to theme toggle changes to update graph font colors
|
// Listen to theme toggle changes to update graph font colors
|
||||||
@@ -1015,6 +1149,7 @@
|
|||||||
loadGraph();
|
loadGraph();
|
||||||
loadTasks();
|
loadTasks();
|
||||||
loadStickyNotes();
|
loadStickyNotes();
|
||||||
|
loadAllExtras();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in new issue
Block a user