--- title: Workstreams --- # Workstreams ```js const workstreams = await FileAttachment("data/workstreams.json").json(); const data = Array.isArray(workstreams) ? workstreams : []; ``` ```js const domainFilter = view(Inputs.select( ["(all)", ...new Set(data.map(w => w.domain ?? "unknown"))], { label: "Domain" } )); const statusFilter = view(Inputs.select( ["(all)", "active", "blocked", "completed", "archived"], { label: "Status" } )); const ownerFilter = view(Inputs.text({ label: "Owner contains" })); ``` ```js const filtered = data.filter(w => (domainFilter === "(all)" || w.domain === domainFilter) && (statusFilter === "(all)" || w.status === statusFilter) && (!ownerFilter || (w.owner ?? "").toLowerCase().includes(ownerFilter.toLowerCase())) ); const STATUS_COLOR = { active: "green", blocked: "orange", completed: "blue", archived: "gray", }; display(Inputs.table(filtered.map(w => ({ Title: w.title, Domain: w.domain, Status: w.status, Owner: w.owner ?? "—", "Due": w.due_date ?? "—", "Updated": new Date(w.updated_at).toLocaleDateString(), })), { rows: 20, })); ``` ```js import * as Plot from "npm:@observablehq/plot"; display(Plot.plot({ title: "Workstream Status Distribution", marks: [ Plot.barX( Object.entries( filtered.reduce((acc, w) => { acc[w.status] = (acc[w.status] ?? 0) + 1; return acc; }, {}) ).map(([status, count]) => ({ status, count })), { y: "status", x: "count", fill: "status", tip: true } ), Plot.ruleX([0]), ], marginLeft: 80, width: 500, })); ```