--- title: Workstream --- ```js import {API} from "../components/config.js"; import {fieldRow} from "../components/field-help.js"; ``` ```js const wsId = observable.params.id; const [raw, taskRows, workplanIndex] = await Promise.all([ fetch(`${API}/workstreams/${wsId}`) .then(r => r.ok ? r.json() : r.json().then(e => ({error: e.detail ?? `HTTP ${r.status}`}))) .catch(e => ({error: String(e)})), fetch(`${API}/tasks/?workstream_id=${wsId}&limit=1000`) .then(r => r.ok ? r.json() : []) .catch(() => []), fetch(`${API}/workstreams/workplan-index`) .then(r => r.ok ? r.json() : {workstreams: {}}) .catch(() => ({workstreams: {}})), ]); ``` ```js if (raw.error) { display(html`
⚠️ ${raw.error}
`); } else { const workplan = (workplanIndex.workstreams ?? {})[wsId] ?? {}; const name = raw.title || raw.slug || wsId; const shortName = name.length > 60 ? name.slice(0, 60) + "…" : name; display(html`

Workstream · ${shortName}

`); display(html`

← Overview  |  ← Workstreams  |  ← Token Cost

`); display(html`
Status${raw.status ?? "—"}
Workplan${workplan.filename ?? "not file-backed"}
Tasks${taskRows.length}
`); const statusOrder = {blocked: 0, in_progress: 1, todo: 2, done: 3, cancelled: 4}; const sortedTasks = [...taskRows].sort((a, b) => { const statusCompare = (statusOrder[a.status] ?? 9) - (statusOrder[b.status] ?? 9); if (statusCompare !== 0) return statusCompare; return (a.title ?? "").localeCompare(b.title ?? ""); }); display(html`

Tasks

`); if (sortedTasks.length === 0) { display(html`

No tasks are attached to this workstream.

`); } else { display(html`${sortedTasks.map(t => html``)}
StatusPriorityTaskHuman
${t.status} ${t.priority ?? "—"} ${t.title ?? t.id} ${t.needs_human ? "yes" : ""}
`); } const FIELD_ORDER = [ "id","slug","title","status","topic_id","repo_id","repo_goal_id", "created_at","updated_at", ]; const rows = FIELD_ORDER.map(k => fieldRow(k, raw[k] ?? null)); for (const k of Object.keys(raw)) { if (!FIELD_ORDER.includes(k)) rows.push(fieldRow(k, raw[k])); } display(html`${rows}
`); } ```