Skip to content

Commit 2953bae

Browse files
cdeustclaude
andcommitted
feat(viz): default landing = Knowledge; Graph tab gains warning banner
- ui/unified/js/state.js: activeView default = 'knowledge' - ui/unified-viz.html: hard-coded `active` class moved to Knowledge button; #cortex-graph-warn banner injected below the view toggle ("Graph may be unusable at this scale … Use Knowledge or Board for reliable browsing while we land the rewrite") with × dismiss - ui/unified/js/controls.js: default landing = knowledge; new _toggleGraphWarn(view) shows the banner only on Graph tab and honors the dismissed flag - ui/unified/js/polling.js: fetchGraph short-circuits unless activeView === 'graph'; subscribes to state:activeView so the graph fetch fires when the user clicks the Graph tab - inline phase loader (unified-viz.html): poll loop short-circuits unless the Graph tab is active, so Knowledge/Board users don't pay the L0..L6 phase-append cost Net effect: page lands on Knowledge (paged /api/memories, scales to any N), Graph stays available with an in-page warning, heavy graph work is deferred until the user explicitly opens the Graph tab. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b7a8f97 commit 2953bae

4 files changed

Lines changed: 87 additions & 14 deletions

File tree

ui/unified-viz.html

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,19 @@
9797
if(p.elapsed) document.getElementById('bp-elapsed').textContent = ' · '+p.elapsed.toFixed(1)+'s';
9898
}
9999

100+
function _activeViewIsGraph() {
101+
return window.JUG && JUG.state && JUG.state.activeView === 'graph';
102+
}
100103
function poll(){
104+
// Only do graph-build work while the user is on the Graph tab.
105+
// Knowledge / Board / Wiki users don't pay the cost.
106+
if (!_activeViewIsGraph()) {
107+
setTimeout(poll, 1500);
108+
return;
109+
}
101110
fetch('/api/graph/progress').then(function(r){ return r.ok ? r.json() : null; }).then(function(p){
102111
if(p){
103112
refreshBar(p);
104-
// Sequential append: iterate the server's phases dict in
105-
// insertion order (L0..L5, then L6:<proj1>..<projN>, then
106-
// L6_CROSS). Apply each one whose `ready` flag is true.
107113
var seq = Promise.resolve();
108114
var keys = Object.keys(p.phases || {});
109115
keys.forEach(function(k){
@@ -166,8 +172,8 @@
166172

167173
<div id="filter-bar">
168174
<span class="view-toggle">
169-
<button class="view-btn active" data-view="graph">Graph</button>
170-
<button class="view-btn" data-view="knowledge">Knowledge</button>
175+
<button class="view-btn" data-view="graph">Graph</button>
176+
<button class="view-btn active" data-view="knowledge">Knowledge</button>
171177
<button class="view-btn" data-view="wiki">Wiki</button>
172178
<button class="view-btn" data-view="timeline">Board</button>
173179
<button class="view-btn" data-view="sankey">Pipeline</button>
@@ -219,6 +225,39 @@
219225
<input type="text" id="search-box" placeholder="Search path, skill, command…">
220226
</div>
221227

228+
<!-- Graph-only warning banner. Shown directly below the view-toggle
229+
row when the Graph tab is active. The Graph view is enabled but
230+
can be unresponsive at scale — explain the situation in-line so
231+
users aren't confused if their browser hangs. Hidden by default;
232+
controls.js toggles display on view change. -->
233+
<div id="cortex-graph-warn" role="status"
234+
style="display:none;position:fixed;top:62px;left:50%;transform:translateX(-50%);z-index:200;
235+
max-width:760px;padding:8px 36px 8px 14px;
236+
background:linear-gradient(90deg,rgba(48,28,12,0.92),rgba(64,40,16,0.92));
237+
border:1px solid rgba(224,140,64,0.5);border-radius:5px;
238+
color:#FFE3B5;font:11.5px/1.45 -apple-system,Inter,system-ui,sans-serif;
239+
letter-spacing:0.2px;box-shadow:0 4px 14px rgba(0,0,0,0.4)">
240+
<span style="color:#FFB060;margin-right:6px"></span>
241+
<strong>Graph may be unusable at this scale.</strong>
242+
Due to performance issues we are currently investigating, opening the Graph
243+
view can freeze the browser when memory counts are high. We are actively
244+
working on it. Use <strong>Knowledge</strong> or <strong>Board</strong> for
245+
reliable browsing while we land the rewrite.
246+
<button id="cortex-graph-warn-close" aria-label="Dismiss"
247+
style="position:absolute;top:4px;right:6px;width:22px;height:22px;
248+
background:transparent;border:none;color:#FFB060;font-size:14px;
249+
cursor:pointer;line-height:1;padding:0">×</button>
250+
</div>
251+
<script>
252+
(function(){
253+
var b = document.getElementById('cortex-graph-warn-close');
254+
if (b) b.addEventListener('click', function() {
255+
var w = document.getElementById('cortex-graph-warn');
256+
if (w) { w.style.display = 'none'; w.dataset.dismissed = '1'; }
257+
});
258+
})();
259+
</script>
260+
222261
<div id="status-bar" class="hud-panel">
223262
<div class="status-dot"></div>
224263
<span id="status-text">Initializing</span>

ui/unified/js/controls.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,40 @@
33
document.addEventListener('DOMContentLoaded', function() {
44
// ── View toggle (Graph / Timeline) ──
55
var viewBtns = document.querySelectorAll('.view-toggle .view-btn[data-view]');
6+
function _toggleGraphWarn(view) {
7+
var w = document.getElementById('cortex-graph-warn');
8+
if (!w) return;
9+
if (view === 'graph' && w.dataset.dismissed !== '1') {
10+
w.style.display = '';
11+
} else {
12+
w.style.display = 'none';
13+
}
14+
}
615
viewBtns.forEach(function(btn) {
716
btn.addEventListener('click', function() {
817
viewBtns.forEach(function(b) { b.classList.remove('active'); });
918
btn.classList.add('active');
10-
var view = btn.dataset.view || 'graph';
19+
var view = btn.dataset.view || 'knowledge';
1120
JUG.state.activeView = view;
1221
toggleFilterBarVisibility(view);
22+
_toggleGraphWarn(view);
1323
});
1424
});
1525

16-
// Graph is the default landing view — the wiki is still under
17-
// active restructuring and the workflow graph is the canonical
18-
// answer to "what did Claude do in this project".
26+
// Knowledge is the default landing view — at high N the graph
27+
// payload + force simulation can freeze the browser, so we land
28+
// on the lazy-loaded Knowledge tab. Users can still click Graph;
29+
// the in-page warning banner above explains the trade-off.
1930
setTimeout(function() {
2031
JUG.state.activeView = '_init';
21-
JUG.state.activeView = 'graph';
22-
toggleFilterBarVisibility('graph');
32+
JUG.state.activeView = 'knowledge';
33+
toggleFilterBarVisibility('knowledge');
34+
_toggleGraphWarn('knowledge');
35+
// Sync the active class on the buttons (HTML hard-codes
36+
// active=graph; flip it to match the runtime default).
37+
viewBtns.forEach(function(b) {
38+
b.classList.toggle('active', b.dataset.view === 'knowledge');
39+
});
2340
}, 0);
2441

2542
// ── Filter buttons (source type) ──

ui/unified/js/polling.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
var abortController = null;
44

55
function fetchGraph() {
6+
// Lazy-load: only pay the multi-MB /api/graph cost when the
7+
// user is actually on the Graph tab. Knowledge / Board / Wiki
8+
// each own their own paged data path and don't need this.
9+
if (window.JUG && JUG.state && JUG.state.activeView !== 'graph') {
10+
updateStatus('Online — graph standby');
11+
hideLoading();
12+
return;
13+
}
614
if (abortController) abortController.abort();
715
abortController = new AbortController();
816
var signal = abortController.signal;
917

10-
// Single fetch — no batching. Domain dedup keeps node count manageable.
1118
fetch(JUG.API_URL, { signal: signal })
1219
.then(function(res) {
1320
if (!res.ok) throw new Error('HTTP ' + res.status);
@@ -134,7 +141,9 @@
134141
.map(function(v) { return String(v).padStart(2, '0'); }).join(':');
135142
}, 1000);
136143

137-
// Boot — delay initial fetch to let Three.js scene fully initialize
144+
// Boot — delay initial fetch. fetchGraph() short-circuits unless
145+
// activeView === 'graph', so this is cheap on Knowledge / Board /
146+
// Wiki landings.
138147
if (document.readyState === 'loading') {
139148
document.addEventListener('DOMContentLoaded', function() {
140149
setTimeout(fetchGraph, 500);
@@ -143,6 +152,14 @@
143152
setTimeout(fetchGraph, 500);
144153
}
145154

155+
// Trigger the graph fetch when the user actually switches to the
156+
// Graph tab (lazy-load semantics).
157+
if (window.JUG && JUG.on) {
158+
JUG.on('state:activeView', function(ev) {
159+
if (ev && ev.value === 'graph') setTimeout(fetchGraph, 50);
160+
});
161+
}
162+
146163
function _loadDiscussionBatch(batch) {
147164
var batchSize = 500;
148165
fetch(JUG.API_URL.replace('/api/graph', '/api/discussions') + '?batch=' + batch + '&batch_size=' + batchSize)

ui/unified/js/state.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
selectedId: null,
1818
zoomLevel: 'L0',
1919
lastData: null,
20-
activeView: 'graph',
20+
activeView: 'knowledge',
2121
domainFilter: '',
2222
emotionFilter: '',
2323
stageFilter: '',

0 commit comments

Comments
 (0)