Tighten review format, badge finding counts, add per-finding fix button

This commit is contained in:
Ian Gulliver
2026-10-15 18:34:12 -07:00
parent 514a2580f7
commit c7f19f2537
12 changed files with 183 additions and 45 deletions
+12 -13
View File
@@ -8,7 +8,7 @@ import { openSwitcher } from "./navbar.js";
import { findTask, focusedProject, focusTab, on, onEach, state, tabs } from "./state.js";
import { mountPreview } from "./preview.js";
import { mountProject } from "./project.js";
import { isReviewEvent, mountReviews } from "./reviews.js";
import { isReviewEvent, latestFindingCount, mountReviews } from "./reviews.js";
import { mountTranscript } from "./task.js";
import { mountTerminal } from "./terminal.js";
@@ -60,6 +60,10 @@ export function taskPane(): HTMLElement {
let buttons: { tab: TaskTab; button: HTMLButtonElement }[] = [];
let drawn = "";
let waiting = 0;
let findings = 0;
const count = (t: TaskTab): number => (t === "inbox" ? waiting : t === "reviews" ? findings : 0);
const badge = (t: TaskTab) => count(t) > 0 && h("span", { class: "badge", title: t === "inbox" ? "inbox items" : "findings in the latest review" }, count(t));
const layout = () => {
for (const { button } of buttons) {
@@ -90,13 +94,13 @@ export function taskPane(): HTMLElement {
for (const { tab, button } of buttons) {
button.hidden = hidden.includes(tab);
}
const attention = hidden.includes("inbox");
more.classList.toggle("attention", attention);
replace(more, "More ▾", attention && h("span", { class: "badge", title: "inbox items" }, waiting));
const flagged = hidden.filter((t) => count(t) > 0);
more.classList.toggle("attention", flagged.length > 0);
replace(more, "More ▾", ...flagged.map(badge));
replace(
menu,
...hidden.map((t) => {
const b = h("button", { type: "button" }, views[t].label, t === "inbox" && h("span", { class: "badge", title: "inbox items" }, waiting));
const b = h("button", { type: "button" }, views[t].label, badge(t));
b.onclick = () => {
menu.hidePopover();
focusTab(t);
@@ -126,18 +130,13 @@ export function taskPane(): HTMLElement {
const first = state.focus.tabs.filter((t, i, all) => tabs.includes(t) && all.indexOf(t) === i);
const tab = state.focus.tab;
waiting = state.inbox.filter((item) => item.task_id === state.selectedTaskId).length;
findings = latestFindingCount(state.transcript);
const order = [...first, ...tabs.filter((t) => !first.includes(t))].filter(available);
const key = JSON.stringify([order, tab, waiting]);
const key = JSON.stringify([order, tab, waiting, findings]);
if (key !== drawn) {
drawn = key;
buttons = order.map((t) => {
const attention = t === "inbox" && waiting > 0;
const button = h(
"button",
{ class: [t === tab ? "active" : "", attention ? "attention" : ""].join(" ").trim() },
views[t].label,
attention && h("span", { class: "badge", title: "inbox items" }, waiting),
);
const button = h("button", { class: [t === tab ? "active" : "", count(t) > 0 ? "attention" : ""].join(" ").trim() }, views[t].label, badge(t));
button.onclick = () => focusTab(t);
return { tab: t, button };
});