claude-code-kanban 2.0.0-rc.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/package.json +1 -1
- package/public/index.html +245 -97
- package/server.js +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://www.npmjs.com/package/claude-code-kanban)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**[Live Demo & Docs](https://nikiforovall.blog/claude-code-kanban/)**
|
|
8
|
+
|
|
9
|
+
> Watch Claude Code work, in real time.
|
|
8
10
|
|
|
9
11
|

|
|
10
12
|
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -366,14 +366,49 @@
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
/* Live Updates */
|
|
369
|
+
.collapse-chevron {
|
|
370
|
+
width: 14px;
|
|
371
|
+
height: 14px;
|
|
372
|
+
stroke: var(--text-muted);
|
|
373
|
+
fill: none;
|
|
374
|
+
stroke-width: 2;
|
|
375
|
+
transition: transform 0.2s ease;
|
|
376
|
+
flex-shrink: 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.collapse-chevron.rotated {
|
|
380
|
+
transform: rotate(-90deg);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.collapsible-section {
|
|
384
|
+
transition: max-height 0.2s ease, padding 0.2s ease, opacity 0.2s ease;
|
|
385
|
+
overflow: hidden;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.collapsible-section.collapsed {
|
|
389
|
+
max-height: 0 !important;
|
|
390
|
+
padding-top: 0 !important;
|
|
391
|
+
padding-bottom: 0 !important;
|
|
392
|
+
opacity: 0;
|
|
393
|
+
overflow: hidden;
|
|
394
|
+
}
|
|
395
|
+
|
|
369
396
|
.live-updates {
|
|
370
|
-
padding: 0 16px
|
|
371
|
-
max-height:
|
|
397
|
+
padding: 0 16px 8px;
|
|
398
|
+
max-height: 140px;
|
|
372
399
|
overflow-y: auto;
|
|
400
|
+
transition: max-height 0.2s ease, padding 0.2s ease, opacity 0.2s ease;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.live-updates.collapsed {
|
|
404
|
+
max-height: 0;
|
|
405
|
+
padding: 0 16px;
|
|
406
|
+
overflow: hidden;
|
|
407
|
+
opacity: 0;
|
|
373
408
|
}
|
|
374
409
|
|
|
375
410
|
.live-empty {
|
|
376
|
-
padding:
|
|
411
|
+
padding: 8px;
|
|
377
412
|
text-align: center;
|
|
378
413
|
font-size: 11px;
|
|
379
414
|
color: var(--text-muted);
|
|
@@ -382,12 +417,12 @@
|
|
|
382
417
|
.live-item {
|
|
383
418
|
display: flex;
|
|
384
419
|
align-items: flex-start;
|
|
385
|
-
gap:
|
|
386
|
-
padding: 10px
|
|
420
|
+
gap: 8px;
|
|
421
|
+
padding: 6px 10px;
|
|
387
422
|
background: var(--bg-deep);
|
|
388
423
|
border: 1px solid transparent;
|
|
389
|
-
border-radius:
|
|
390
|
-
margin-bottom:
|
|
424
|
+
border-radius: 6px;
|
|
425
|
+
margin-bottom: 3px;
|
|
391
426
|
cursor: pointer;
|
|
392
427
|
transition: all 0.15s ease;
|
|
393
428
|
}
|
|
@@ -397,14 +432,14 @@
|
|
|
397
432
|
}
|
|
398
433
|
|
|
399
434
|
.live-item .pulse {
|
|
400
|
-
width:
|
|
401
|
-
height:
|
|
435
|
+
width: 6px;
|
|
436
|
+
height: 6px;
|
|
402
437
|
margin-top: 4px;
|
|
403
438
|
background: var(--accent);
|
|
404
439
|
border-radius: 50%;
|
|
405
440
|
flex-shrink: 0;
|
|
406
441
|
animation: pulse 2s ease-in-out infinite;
|
|
407
|
-
box-shadow: 0 0
|
|
442
|
+
box-shadow: 0 0 8px var(--accent-glow);
|
|
408
443
|
}
|
|
409
444
|
|
|
410
445
|
.live-item-content {
|
|
@@ -413,7 +448,7 @@
|
|
|
413
448
|
}
|
|
414
449
|
|
|
415
450
|
.live-item-action {
|
|
416
|
-
font-size:
|
|
451
|
+
font-size: 11px;
|
|
417
452
|
color: var(--text-primary);
|
|
418
453
|
white-space: nowrap;
|
|
419
454
|
overflow: hidden;
|
|
@@ -421,9 +456,9 @@
|
|
|
421
456
|
}
|
|
422
457
|
|
|
423
458
|
.live-item-session {
|
|
424
|
-
font-size:
|
|
459
|
+
font-size: 10px;
|
|
425
460
|
color: var(--text-tertiary);
|
|
426
|
-
margin-top:
|
|
461
|
+
margin-top: 1px;
|
|
427
462
|
white-space: nowrap;
|
|
428
463
|
overflow: hidden;
|
|
429
464
|
text-overflow: ellipsis;
|
|
@@ -2233,6 +2268,12 @@
|
|
|
2233
2268
|
color: var(--text-primary);
|
|
2234
2269
|
}
|
|
2235
2270
|
|
|
2271
|
+
.project-group-header.kb-selected {
|
|
2272
|
+
color: var(--text-primary);
|
|
2273
|
+
background: var(--bg-hover);
|
|
2274
|
+
border-radius: 4px;
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2236
2277
|
.project-group-header .group-chevron {
|
|
2237
2278
|
transition: transform 0.15s ease;
|
|
2238
2279
|
flex-shrink: 0;
|
|
@@ -2395,8 +2436,11 @@
|
|
|
2395
2436
|
|
|
2396
2437
|
<!-- Live Updates -->
|
|
2397
2438
|
<div class="sidebar-section">
|
|
2398
|
-
<div class="section-header">
|
|
2439
|
+
<div class="section-header" onclick="toggleLiveUpdates()" style="cursor: pointer;">
|
|
2399
2440
|
<span>Live Updates</span>
|
|
2441
|
+
<svg id="live-updates-chevron" class="collapse-chevron" viewBox="0 0 24 24">
|
|
2442
|
+
<path d="M6 9l6 6 6-6"/>
|
|
2443
|
+
</svg>
|
|
2400
2444
|
</div>
|
|
2401
2445
|
<div id="live-updates" class="live-updates">
|
|
2402
2446
|
<div class="live-empty">No active tasks</div>
|
|
@@ -2405,46 +2449,50 @@
|
|
|
2405
2449
|
|
|
2406
2450
|
<!-- Tasks -->
|
|
2407
2451
|
<div class="sidebar-section flex-1">
|
|
2408
|
-
<div class="section-header">
|
|
2452
|
+
<div class="section-header" onclick="toggleSection('sessions-filters', 'sessions-chevron')" style="cursor: pointer;">
|
|
2409
2453
|
<span>Sessions</span>
|
|
2410
|
-
<
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
<input
|
|
2414
|
-
id="search-input"
|
|
2415
|
-
type="text"
|
|
2416
|
-
class="search-input"
|
|
2417
|
-
placeholder="Search tasks, sessions, projects..."
|
|
2418
|
-
oninput="handleSearch(this.value)"
|
|
2419
|
-
/>
|
|
2420
|
-
<button id="search-clear-btn" class="search-clear" onclick="clearSearch()" title="Clear search" aria-label="Clear search">
|
|
2421
|
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2422
|
-
<path d="M18 6L6 18M6 6l12 12"/>
|
|
2423
|
-
</svg>
|
|
2424
|
-
</button>
|
|
2425
|
-
</div>
|
|
2426
|
-
<div class="filter-row">
|
|
2427
|
-
<select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
|
|
2428
|
-
<option value="">All Projects</option>
|
|
2429
|
-
</select>
|
|
2430
|
-
<select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
|
|
2431
|
-
<option value="all">All Sessions</option>
|
|
2432
|
-
<option value="active">Active Only</option>
|
|
2433
|
-
</select>
|
|
2454
|
+
<svg id="sessions-chevron" class="collapse-chevron" viewBox="0 0 24 24">
|
|
2455
|
+
<path d="M6 9l6 6 6-6"/>
|
|
2456
|
+
</svg>
|
|
2434
2457
|
</div>
|
|
2435
|
-
<div class="
|
|
2436
|
-
<
|
|
2437
|
-
<
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
<
|
|
2446
|
-
|
|
2447
|
-
|
|
2458
|
+
<div id="sessions-filters" class="collapsible-section">
|
|
2459
|
+
<div class="search-container">
|
|
2460
|
+
<input
|
|
2461
|
+
id="search-input"
|
|
2462
|
+
type="text"
|
|
2463
|
+
class="search-input"
|
|
2464
|
+
placeholder="Search tasks, sessions, projects..."
|
|
2465
|
+
oninput="handleSearch(this.value)"
|
|
2466
|
+
/>
|
|
2467
|
+
<button id="search-clear-btn" class="search-clear" onclick="clearSearch()" title="Clear search" aria-label="Clear search">
|
|
2468
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
2469
|
+
<path d="M18 6L6 18M6 6l12 12"/>
|
|
2470
|
+
</svg>
|
|
2471
|
+
</button>
|
|
2472
|
+
</div>
|
|
2473
|
+
<div class="filter-row">
|
|
2474
|
+
<select id="project-filter" class="filter-dropdown" onchange="filterByProject(this.value)" aria-label="Filter by project">
|
|
2475
|
+
<option value="">All Projects</option>
|
|
2476
|
+
</select>
|
|
2477
|
+
<select id="session-filter" class="filter-dropdown" onchange="filterBySessions(this.value)" aria-label="Filter by session status">
|
|
2478
|
+
<option value="all">All Sessions</option>
|
|
2479
|
+
<option value="active">Active Only</option>
|
|
2480
|
+
</select>
|
|
2481
|
+
</div>
|
|
2482
|
+
<div class="filter-row">
|
|
2483
|
+
<select id="session-limit" class="filter-dropdown" onchange="changeSessionLimit(this.value)" aria-label="Number of sessions to show">
|
|
2484
|
+
<option value="10">Show 10</option>
|
|
2485
|
+
<option value="20">Show 20</option>
|
|
2486
|
+
<option value="50">Show 50</option>
|
|
2487
|
+
<option value="all">Show All</option>
|
|
2488
|
+
</select>
|
|
2489
|
+
<button class="icon-btn reset-btn" onclick="resetState()" title="Reset all filters" aria-label="Reset all filters">
|
|
2490
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
|
|
2491
|
+
<path d="M3 12a9 9 0 1 1 9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/>
|
|
2492
|
+
<path d="M3 22v-6h6"/>
|
|
2493
|
+
</svg>
|
|
2494
|
+
</button>
|
|
2495
|
+
</div>
|
|
2448
2496
|
</div>
|
|
2449
2497
|
<div id="sessions-list" class="sessions-list"></div>
|
|
2450
2498
|
</div>
|
|
@@ -2943,6 +2991,18 @@
|
|
|
2943
2991
|
renderLiveUpdates(activeTasks);
|
|
2944
2992
|
}
|
|
2945
2993
|
|
|
2994
|
+
function toggleSection(containerId, chevronId) {
|
|
2995
|
+
const container = document.getElementById(containerId);
|
|
2996
|
+
const chevron = document.getElementById(chevronId);
|
|
2997
|
+
const collapsed = container.classList.toggle('collapsed');
|
|
2998
|
+
chevron.classList.toggle('rotated', collapsed);
|
|
2999
|
+
localStorage.setItem(containerId + 'Collapsed', collapsed);
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
function toggleLiveUpdates() {
|
|
3003
|
+
toggleSection('live-updates', 'live-updates-chevron');
|
|
3004
|
+
}
|
|
3005
|
+
|
|
2946
3006
|
function renderLiveUpdates(activeTasks) {
|
|
2947
3007
|
const container = document.getElementById('live-updates');
|
|
2948
3008
|
|
|
@@ -3536,7 +3596,7 @@
|
|
|
3536
3596
|
const id = `expand-${++_expandIdCounter}`;
|
|
3537
3597
|
const fontSize = opts.fontSize || '0.8rem';
|
|
3538
3598
|
const maxHeight = opts.maxHeight || '';
|
|
3539
|
-
const btn = `<button onclick="var f=document.getElementById('${id}'),t=this.parentElement.nextElementSibling,expand=f.style.display==='none';f.style.display=expand?'block':'none';t.style.display=expand?'none':'block';this.textContent=expand?'Show less':'Show more'" style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:${fontSize};text-decoration:underline">Show more</button>`;
|
|
3599
|
+
const btn = `<button onclick="var f=document.getElementById('${id}'),t=this.parentElement.nextElementSibling,expand=f.style.display==='none';f.style.display=expand?'block':'none';t.style.display=expand?'none':'block';this.textContent=expand?'Show less':'Show more'" style="background:none;border:none;color:var(--accent);cursor:pointer;font-size:${fontSize};text-decoration:underline;margin-left:6px">Show more</button>`;
|
|
3540
3600
|
const mhStyle = maxHeight ? `max-height:${maxHeight};` : '';
|
|
3541
3601
|
const full = `<pre id="${id}" class="msg-detail-pre" style="${mhStyle}overflow:auto;display:none">${fullHtml}</pre>`;
|
|
3542
3602
|
return { btn, full };
|
|
@@ -4047,29 +4107,34 @@
|
|
|
4047
4107
|
sessionsList.innerHTML = filteredSessions.map(renderSessionCard).join('');
|
|
4048
4108
|
}
|
|
4049
4109
|
|
|
4050
|
-
const
|
|
4051
|
-
const
|
|
4110
|
+
const navItems = getNavigableItems();
|
|
4111
|
+
const allSessions = getSessionItems();
|
|
4112
|
+
const activeIdx = allSessions.findIndex(el => el.classList.contains('active'));
|
|
4052
4113
|
if (activeIdx >= 0 && (selectedSessionIdx < 0 || sessionJustSelected)) {
|
|
4053
|
-
|
|
4054
|
-
|
|
4114
|
+
const navIdx = navItems.indexOf(allSessions[activeIdx]);
|
|
4115
|
+
selectedSessionIdx = navIdx >= 0 ? navIdx : 0;
|
|
4116
|
+
selectedSessionKbId = allSessions[activeIdx].dataset.sessionId || null;
|
|
4055
4117
|
sessionJustSelected = false;
|
|
4056
4118
|
}
|
|
4057
4119
|
|
|
4058
4120
|
if (selectedSessionKbId && focusZone === 'sidebar') {
|
|
4059
|
-
const restoredIdx =
|
|
4121
|
+
const restoredIdx = navItems.findIndex(el =>
|
|
4122
|
+
getKbId(el) === selectedSessionKbId
|
|
4123
|
+
);
|
|
4060
4124
|
if (restoredIdx >= 0) {
|
|
4061
4125
|
selectedSessionIdx = restoredIdx;
|
|
4062
|
-
|
|
4126
|
+
navItems[restoredIdx].classList.add('kb-selected');
|
|
4063
4127
|
} else {
|
|
4064
4128
|
selectedSessionIdx = -1;
|
|
4065
4129
|
selectedSessionKbId = null;
|
|
4066
4130
|
}
|
|
4067
4131
|
} else if (focusZone === 'sidebar' && selectedSessionIdx >= 0) {
|
|
4068
|
-
if (
|
|
4069
|
-
const clamped = Math.min(selectedSessionIdx,
|
|
4132
|
+
if (navItems.length > 0) {
|
|
4133
|
+
const clamped = Math.min(selectedSessionIdx, navItems.length - 1);
|
|
4070
4134
|
selectedSessionIdx = clamped;
|
|
4071
|
-
|
|
4072
|
-
|
|
4135
|
+
const el = navItems[clamped];
|
|
4136
|
+
selectedSessionKbId = getKbId(el);
|
|
4137
|
+
el.classList.add('kb-selected');
|
|
4073
4138
|
} else {
|
|
4074
4139
|
selectedSessionIdx = -1;
|
|
4075
4140
|
selectedSessionKbId = null;
|
|
@@ -4303,31 +4368,71 @@
|
|
|
4303
4368
|
}
|
|
4304
4369
|
}
|
|
4305
4370
|
|
|
4371
|
+
function getKbId(el) {
|
|
4372
|
+
return el.dataset.sessionId || el.dataset.groupPath || null;
|
|
4373
|
+
}
|
|
4374
|
+
|
|
4375
|
+
function getGroupSessionsContainer(header) {
|
|
4376
|
+
let el = header.nextElementSibling;
|
|
4377
|
+
while (el && !el.classList.contains('project-group-sessions')) el = el.nextElementSibling;
|
|
4378
|
+
return el;
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
function getNavigableItems() {
|
|
4382
|
+
const items = [];
|
|
4383
|
+
for (const el of sessionsList.children) {
|
|
4384
|
+
if (el.classList.contains('project-group-header')) {
|
|
4385
|
+
items.push(el);
|
|
4386
|
+
if (!collapsedProjectGroups.has(el.dataset.groupPath)) {
|
|
4387
|
+
const container = getGroupSessionsContainer(el);
|
|
4388
|
+
if (container) {
|
|
4389
|
+
for (const s of container.querySelectorAll('.session-item')) items.push(s);
|
|
4390
|
+
}
|
|
4391
|
+
}
|
|
4392
|
+
} else if (el.classList.contains('session-item')) {
|
|
4393
|
+
items.push(el);
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
return items;
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4306
4399
|
function getSessionItems() {
|
|
4307
4400
|
return Array.from(sessionsList.querySelectorAll('.session-item'));
|
|
4308
4401
|
}
|
|
4309
4402
|
|
|
4310
|
-
function
|
|
4311
|
-
const
|
|
4312
|
-
if (items.length === 0) return;
|
|
4313
|
-
const prev = sessionsList.querySelector('.session-item.kb-selected');
|
|
4403
|
+
function clearKbSelection() {
|
|
4404
|
+
const prev = sessionsList.querySelector('.kb-selected');
|
|
4314
4405
|
if (prev) prev.classList.remove('kb-selected');
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
function selectSessionByIndex(idx, items) {
|
|
4409
|
+
items = items || getNavigableItems();
|
|
4410
|
+
if (items.length === 0) return;
|
|
4411
|
+
clearKbSelection();
|
|
4315
4412
|
selectedSessionIdx = Math.max(0, Math.min(idx, items.length - 1));
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4413
|
+
const el = items[selectedSessionIdx];
|
|
4414
|
+
selectedSessionKbId = getKbId(el);
|
|
4415
|
+
el.classList.add('kb-selected');
|
|
4416
|
+
el.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
4319
4417
|
}
|
|
4320
4418
|
|
|
4321
|
-
function navigateSession(direction) {
|
|
4322
|
-
|
|
4419
|
+
function navigateSession(direction, items) {
|
|
4420
|
+
items = items || getNavigableItems();
|
|
4323
4421
|
if (items.length === 0) return;
|
|
4324
4422
|
if (selectedSessionIdx < 0) {
|
|
4325
|
-
selectSessionByIndex(0);
|
|
4423
|
+
selectSessionByIndex(0, items);
|
|
4326
4424
|
return;
|
|
4327
4425
|
}
|
|
4328
|
-
const
|
|
4426
|
+
const currentEl = items[selectedSessionIdx];
|
|
4427
|
+
let newIdx = selectedSessionIdx + direction;
|
|
4428
|
+
if (!currentEl || !currentEl.isConnected) {
|
|
4429
|
+
const restoredIdx = selectedSessionKbId
|
|
4430
|
+
? items.findIndex(el => getKbId(el) === selectedSessionKbId)
|
|
4431
|
+
: -1;
|
|
4432
|
+
newIdx = restoredIdx >= 0 ? restoredIdx : 0;
|
|
4433
|
+
}
|
|
4329
4434
|
if (newIdx >= 0 && newIdx < items.length) {
|
|
4330
|
-
selectSessionByIndex(newIdx);
|
|
4435
|
+
selectSessionByIndex(newIdx, items);
|
|
4331
4436
|
}
|
|
4332
4437
|
}
|
|
4333
4438
|
|
|
@@ -4338,26 +4443,56 @@
|
|
|
4338
4443
|
if (collapsed) collapsedProjectGroups.add(projectPath);
|
|
4339
4444
|
else collapsedProjectGroups.delete(projectPath);
|
|
4340
4445
|
header.classList.toggle('collapsed', collapsed);
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
if (el) el.classList.toggle('collapsed', collapsed);
|
|
4446
|
+
const container = getGroupSessionsContainer(header);
|
|
4447
|
+
if (container) container.classList.toggle('collapsed', collapsed);
|
|
4344
4448
|
try { localStorage.setItem('collapsedGroups', JSON.stringify([...collapsedProjectGroups])); } catch(_) {}
|
|
4345
4449
|
}
|
|
4346
4450
|
|
|
4347
|
-
function
|
|
4348
|
-
const items =
|
|
4451
|
+
function handleSidebarHorizontal(direction) {
|
|
4452
|
+
const items = getNavigableItems();
|
|
4349
4453
|
if (selectedSessionIdx < 0 || selectedSessionIdx >= items.length) return;
|
|
4350
|
-
const
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4454
|
+
const el = items[selectedSessionIdx];
|
|
4455
|
+
const isHeader = el.classList.contains('project-group-header');
|
|
4456
|
+
const collapse = direction < 0;
|
|
4457
|
+
|
|
4458
|
+
if (isHeader) {
|
|
4459
|
+
const groupPath = el.dataset.groupPath;
|
|
4460
|
+
const isCollapsed = collapsedProjectGroups.has(groupPath);
|
|
4461
|
+
if (collapse) {
|
|
4462
|
+
if (!isCollapsed) setGroupCollapsed(el, true);
|
|
4463
|
+
} else {
|
|
4464
|
+
if (isCollapsed) {
|
|
4465
|
+
setGroupCollapsed(el, false);
|
|
4466
|
+
} else {
|
|
4467
|
+
navigateSession(1);
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
} else {
|
|
4471
|
+
if (collapse) {
|
|
4472
|
+
const container = el.closest('.project-group-sessions');
|
|
4473
|
+
if (container) {
|
|
4474
|
+
let header = container.previousElementSibling;
|
|
4475
|
+
while (header && !header.classList.contains('project-group-header')) header = header.previousElementSibling;
|
|
4476
|
+
if (header) {
|
|
4477
|
+
const headerIdx = items.indexOf(header);
|
|
4478
|
+
if (headerIdx >= 0) selectSessionByIndex(headerIdx, items);
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
} else {
|
|
4482
|
+
activateSelectedSession(items);
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4355
4485
|
}
|
|
4356
4486
|
|
|
4357
|
-
function activateSelectedSession() {
|
|
4358
|
-
|
|
4359
|
-
if (selectedSessionIdx
|
|
4360
|
-
|
|
4487
|
+
function activateSelectedSession(items) {
|
|
4488
|
+
items = items || getNavigableItems();
|
|
4489
|
+
if (selectedSessionIdx < 0 || selectedSessionIdx >= items.length) return;
|
|
4490
|
+
const el = items[selectedSessionIdx];
|
|
4491
|
+
if (el.classList.contains('project-group-header')) {
|
|
4492
|
+
const groupPath = el.dataset.groupPath;
|
|
4493
|
+
setGroupCollapsed(el, !collapsedProjectGroups.has(groupPath));
|
|
4494
|
+
} else {
|
|
4495
|
+
el.click();
|
|
4361
4496
|
}
|
|
4362
4497
|
}
|
|
4363
4498
|
|
|
@@ -4365,8 +4500,7 @@
|
|
|
4365
4500
|
const sidebar = document.querySelector('.sidebar');
|
|
4366
4501
|
// Clear all zone visuals
|
|
4367
4502
|
sidebar.classList.remove('sidebar-focused');
|
|
4368
|
-
|
|
4369
|
-
if (prevSession) prevSession.classList.remove('kb-selected');
|
|
4503
|
+
clearKbSelection();
|
|
4370
4504
|
const selCard = document.querySelector('.task-card.selected');
|
|
4371
4505
|
if (selCard) selCard.classList.remove('selected');
|
|
4372
4506
|
|
|
@@ -4377,13 +4511,13 @@
|
|
|
4377
4511
|
localStorage.setItem('sidebar-collapsed', false);
|
|
4378
4512
|
}
|
|
4379
4513
|
sidebar.classList.add('sidebar-focused');
|
|
4380
|
-
const items =
|
|
4514
|
+
const items = getNavigableItems();
|
|
4381
4515
|
if (items.length > 0) {
|
|
4382
4516
|
const activeIdx = items.findIndex(el => el.classList.contains('active'));
|
|
4383
4517
|
if (activeIdx >= 0) {
|
|
4384
4518
|
selectSessionByIndex(activeIdx);
|
|
4385
4519
|
} else if (selectedSessionKbId) {
|
|
4386
|
-
const restoredIdx = items.findIndex(el => el
|
|
4520
|
+
const restoredIdx = items.findIndex(el => getKbId(el) === selectedSessionKbId);
|
|
4387
4521
|
selectSessionByIndex(restoredIdx >= 0 ? restoredIdx : 0);
|
|
4388
4522
|
} else {
|
|
4389
4523
|
selectSessionByIndex(0);
|
|
@@ -4860,6 +4994,10 @@
|
|
|
4860
4994
|
// Tab toggles focus zone
|
|
4861
4995
|
if (e.key === 'Tab') {
|
|
4862
4996
|
e.preventDefault();
|
|
4997
|
+
if (focusZone === 'sidebar') {
|
|
4998
|
+
const hasCards = document.querySelector('.task-card');
|
|
4999
|
+
if (!hasCards) return;
|
|
5000
|
+
}
|
|
4863
5001
|
setFocusZone(focusZone === 'board' ? 'sidebar' : 'board');
|
|
4864
5002
|
return;
|
|
4865
5003
|
}
|
|
@@ -4878,12 +5016,12 @@
|
|
|
4878
5016
|
}
|
|
4879
5017
|
if (e.key === 'h' || e.key === 'ArrowLeft') {
|
|
4880
5018
|
e.preventDefault();
|
|
4881
|
-
|
|
5019
|
+
handleSidebarHorizontal(-1);
|
|
4882
5020
|
return;
|
|
4883
5021
|
}
|
|
4884
5022
|
if (e.key === 'l' || e.key === 'ArrowRight') {
|
|
4885
5023
|
e.preventDefault();
|
|
4886
|
-
|
|
5024
|
+
handleSidebarHorizontal(1);
|
|
4887
5025
|
return;
|
|
4888
5026
|
}
|
|
4889
5027
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
@@ -4897,14 +5035,14 @@
|
|
|
4897
5035
|
}
|
|
4898
5036
|
if (e.key === 'p' || e.key === 'P') {
|
|
4899
5037
|
e.preventDefault();
|
|
4900
|
-
const highlighted = sessionsList.querySelector('.
|
|
5038
|
+
const highlighted = sessionsList.querySelector('.kb-selected');
|
|
4901
5039
|
const sid = highlighted?.dataset.sessionId || currentSessionId;
|
|
4902
5040
|
if (sid) openPlanForSession(sid);
|
|
4903
5041
|
return;
|
|
4904
5042
|
}
|
|
4905
5043
|
if (e.key === 'i' || e.key === 'I') {
|
|
4906
5044
|
e.preventDefault();
|
|
4907
|
-
const highlighted = sessionsList.querySelector('.
|
|
5045
|
+
const highlighted = sessionsList.querySelector('.kb-selected');
|
|
4908
5046
|
const sid = highlighted?.dataset.sessionId || currentSessionId;
|
|
4909
5047
|
if (sid) showSessionInfoModal(sid);
|
|
4910
5048
|
return;
|
|
@@ -4920,6 +5058,10 @@
|
|
|
4920
5058
|
const navKeys = ['j','k','h','l','ArrowUp','ArrowDown','ArrowLeft','ArrowRight'];
|
|
4921
5059
|
if (navKeys.includes(e.key)) {
|
|
4922
5060
|
e.preventDefault();
|
|
5061
|
+
if (!selectedTaskId && !document.querySelector('.task-card.selected')) {
|
|
5062
|
+
setFocusZone('sidebar');
|
|
5063
|
+
return;
|
|
5064
|
+
}
|
|
4923
5065
|
if (e.key === 'j' || e.key === 'ArrowDown') navigateVertical(1);
|
|
4924
5066
|
else if (e.key === 'k' || e.key === 'ArrowUp') navigateVertical(-1);
|
|
4925
5067
|
else if (e.key === 'h' || e.key === 'ArrowLeft') navigateHorizontal(-1);
|
|
@@ -5702,6 +5844,12 @@
|
|
|
5702
5844
|
|
|
5703
5845
|
// Init
|
|
5704
5846
|
loadTheme();
|
|
5847
|
+
['live-updates', 'sessions-filters'].forEach(id => {
|
|
5848
|
+
if (localStorage.getItem(id + 'Collapsed') === 'true') {
|
|
5849
|
+
document.getElementById(id).classList.add('collapsed');
|
|
5850
|
+
document.getElementById(id === 'live-updates' ? 'live-updates-chevron' : 'sessions-chevron').classList.add('rotated');
|
|
5851
|
+
}
|
|
5852
|
+
});
|
|
5705
5853
|
|
|
5706
5854
|
document.addEventListener('DOMContentLoaded', () => {
|
|
5707
5855
|
if (typeof marked !== 'undefined' && typeof hljs !== 'undefined') {
|
package/server.js
CHANGED
|
@@ -604,7 +604,7 @@ app.get('/api/sessions', async (req, res) => {
|
|
|
604
604
|
}
|
|
605
605
|
|
|
606
606
|
// Convert map to array and sort by most recently modified
|
|
607
|
-
sessions = Array.from(sessionsMap.values());
|
|
607
|
+
let sessions = Array.from(sessionsMap.values());
|
|
608
608
|
sessions.sort((a, b) => new Date(b.modifiedAt) - new Date(a.modifiedAt));
|
|
609
609
|
|
|
610
610
|
// Apply limit if specified, but always include pinned sessions
|