diff --git a/package.json b/package.json index e7823e1..723e48d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "netfelix-audio-fix", - "version": "2026.04.14.21", + "version": "2026.04.14.22", "scripts": { "dev:server": "NODE_ENV=development bun --hot server/index.tsx", "dev:client": "vite", diff --git a/server/api/review.ts b/server/api/review.ts index 9a37b02..cebb761 100644 --- a/server/api/review.ts +++ b/server/api/review.ts @@ -752,6 +752,30 @@ app.post("/:id/retry", (c) => { return c.json({ ok: true }); }); +// Reopen a completed or errored plan: flip it back to pending so the user +// can adjust decisions and re-approve. Used by the Done column's hover +// "Back to review" affordance. Unlike /unapprove (which rolls back an +// approved-but-not-yet-running plan), this handles the post-job states +// and drops the lingering job row so the pipeline doesn't show leftover +// history for an item that's about to be re-queued. +app.post("/:id/reopen", (c) => { + const db = getDb(); + const id = parseId(c.req.param("id")); + if (id == null) return c.json({ error: "invalid id" }, 400); + const plan = db.prepare("SELECT * FROM review_plans WHERE item_id = ?").get(id) as ReviewPlan | undefined; + if (!plan) return c.notFound(); + if (plan.status !== "done" && plan.status !== "error") { + return c.json({ ok: false, error: "Can only reopen plans with status done or error" }, 409); + } + db.transaction(() => { + // Leave plan.notes alone so the user keeps any ffmpeg error summary + // from the prior run — useful context when redeciding decisions. + db.prepare("UPDATE review_plans SET status = 'pending', verified = 0, reviewed_at = NULL WHERE id = ?").run(plan.id); + db.prepare("DELETE FROM jobs WHERE item_id = ? AND status IN ('done', 'error')").run(id); + })(); + return c.json({ ok: true }); +}); + app.post("/:id/unapprove", (c) => { const db = getDb(); const id = parseId(c.req.param("id")); diff --git a/src/features/pipeline/DoneColumn.tsx b/src/features/pipeline/DoneColumn.tsx index e96b7af..2ecd2b5 100644 --- a/src/features/pipeline/DoneColumn.tsx +++ b/src/features/pipeline/DoneColumn.tsx @@ -15,6 +15,11 @@ export function DoneColumn({ items, onMutate }: DoneColumnProps) { onMutate(); }; + const reopen = async (itemId: number) => { + await api.post(`/api/review/${itemId}/reopen`); + onMutate(); + }; + return ( +
{item.name} - {item.status} +
+ {item.status} +
+ +
diff --git a/src/features/pipeline/PipelineCard.tsx b/src/features/pipeline/PipelineCard.tsx index 8be9dc0..0063131 100644 --- a/src/features/pipeline/PipelineCard.tsx +++ b/src/features/pipeline/PipelineCard.tsx @@ -194,7 +194,7 @@ export function PipelineCard({