diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-26 09:01:35 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-26 09:01:35 +0000 |
| commit | dac676e8284725c8ec6de08282fe08a9b519ccc8 (patch) | |
| tree | f3cd7adb5ddf7acad95d3946ce518913e3a9a232 /web/app.js | |
| parent | 909fa86bea1f55acc1ccb119e9509d2c724f6b5b (diff) | |
feat: show tasks and subtasks in story detail view
Story detail modal now fetches /api/stories/{id}/tasks and renders
top-level tasks as a numbered list with subtasks nested beneath, using
the same state emoji as the blocked/task views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'web/app.js')
| -rw-r--r-- | web/app.js | 39 |
1 files changed, 39 insertions, 0 deletions
@@ -3167,6 +3167,45 @@ function openStoryDetail(story) { addRow('Branch', story.branch_name); addRow('Created', story.created_at ? new Date(story.created_at).toLocaleString() : '—'); + // Load tasks for this story. + const tasksSection = document.createElement('div'); + tasksSection.className = 'story-detail-tasks'; + tasksSection.innerHTML = '<p class="task-meta">Loading tasks…</p>'; + body.appendChild(tasksSection); + + fetch(`${API_BASE}/api/stories/${story.id}/tasks`) + .then(r => r.ok ? r.json() : []) + .then(async tasks => { + tasksSection.innerHTML = ''; + const topLevel = tasks.filter(t => !t.parent_task_id); + if (topLevel.length === 0) { + tasksSection.innerHTML = '<p class="task-meta">No tasks yet.</p>'; + return; + } + const ol = document.createElement('ol'); + ol.className = 'story-detail-task-list'; + for (const t of topLevel) { + const li = document.createElement('li'); + li.className = `story-detail-task story-detail-task-${t.state.toLowerCase()}`; + li.textContent = `${STATE_EMOJI[t.state] || '•'} ${t.name}`; + const subs = tasks.filter(s => s.parent_task_id === t.id); + if (subs.length > 0) { + const ul = document.createElement('ul'); + ul.className = 'story-detail-subtask-list'; + for (const s of subs) { + const sli = document.createElement('li'); + sli.className = `subtask-item subtask-${s.state.toLowerCase()}`; + sli.textContent = `${STATE_EMOJI[s.state] || '•'} ${s.name}`; + ul.appendChild(sli); + } + li.appendChild(ul); + } + ol.appendChild(li); + } + tasksSection.appendChild(ol); + }) + .catch(() => { tasksSection.innerHTML = '<p class="task-meta">Could not load tasks.</p>'; }); + modal.showModal(); } |
