summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/app.js39
-rw-r--r--web/style.css29
2 files changed, 68 insertions, 0 deletions
diff --git a/web/app.js b/web/app.js
index 882ddac..dfe6d4e 100644
--- a/web/app.js
+++ b/web/app.js
@@ -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;
+}