diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/app.js | 39 | ||||
| -rw-r--r-- | web/style.css | 29 |
2 files changed, 68 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(); } diff --git a/web/style.css b/web/style.css index 1aa6627..c7e82ae 100644 --- a/web/style.css +++ b/web/style.css @@ -1924,3 +1924,32 @@ dialog label select:focus { .story-detail-body { padding: 0.25rem 0; } + +.story-detail-tasks { + margin-top: 1rem; + padding-top: 0.75rem; + border-top: 1px solid var(--border); +} + +.story-detail-task-list { + margin: 0.5rem 0 0; + padding-left: 1.25rem; + list-style: decimal; +} + +.story-detail-task-list > li { + padding: 0.2rem 0; + font-size: 0.9rem; +} + +.story-detail-subtask-list { + margin: 0.25rem 0 0.25rem 0.5rem; + padding-left: 1rem; + list-style: none; +} + +.story-detail-subtask-list li { + font-size: 0.85rem; + opacity: 0.85; + padding: 0.1rem 0; +} |
