summaryrefslogtreecommitdiff
path: root/web/app.js
diff options
context:
space:
mode:
Diffstat (limited to 'web/app.js')
-rw-r--r--web/app.js39
1 files changed, 38 insertions, 1 deletions
diff --git a/web/app.js b/web/app.js
index ad60f34..6bcdf57 100644
--- a/web/app.js
+++ b/web/app.js
@@ -163,7 +163,11 @@ function createTaskCard(task) {
footer.appendChild(acceptBtn);
footer.appendChild(rejectBtn);
} else if (task.state === 'BLOCKED') {
- renderQuestionFooter(task, footer);
+ if (task.question) {
+ renderQuestionFooter(task, footer);
+ } else {
+ renderSubtaskRollup(task.id, footer);
+ }
const cancelBtn = document.createElement('button');
cancelBtn.className = 'btn-cancel';
cancelBtn.textContent = 'Cancel';
@@ -728,6 +732,39 @@ function renderQuestionFooter(task, footer) {
}
}
+const STATE_EMOJI = {
+ PENDING: '⏳', QUEUED: '🕐', RUNNING: '⚡', COMPLETED: '✅',
+ FAILED: '❌', CANCELLED: '🚫', TIMED_OUT: '⏱', BUDGET_EXCEEDED: '💸',
+ READY: '👀', BLOCKED: '⏸',
+};
+
+async function renderSubtaskRollup(taskId, footer) {
+ footer.addEventListener('click', (e) => e.stopPropagation());
+ const container = document.createElement('div');
+ container.className = 'subtask-rollup';
+ footer.prepend(container);
+
+ try {
+ const res = await fetch(`${API_BASE}/api/tasks/${taskId}/subtasks`);
+ const subtasks = await res.json();
+ if (!subtasks || subtasks.length === 0) {
+ container.textContent = 'Waiting for subtasks…';
+ return;
+ }
+ const ul = document.createElement('ul');
+ ul.className = 'subtask-list';
+ for (const st of subtasks) {
+ const li = document.createElement('li');
+ li.className = `subtask-item subtask-${st.state.toLowerCase()}`;
+ li.textContent = `${STATE_EMOJI[st.state] || '•'} ${st.name}`;
+ ul.appendChild(li);
+ }
+ container.appendChild(ul);
+ } catch {
+ container.textContent = 'Could not load subtasks.';
+ }
+}
+
async function handleAnswer(taskId, answer, footer) {
const btns = footer.querySelectorAll('button, input');
btns.forEach(el => { el.disabled = true; });