drop audio list tab, move per-item actions onto pipeline cards
All checks were successful
Build and Push Docker Image / build (push) Successful in 39s
All checks were successful
Build and Push Docker Image / build (push) Successful in 39s
The pipeline tab fully replaces the audio list: same items, better workflow. What the old list contributed (per-item details + skip/approve) now lives inline on each pipeline card. - delete src/routes/review/audio/index.tsx + src/features/review/AudioListPage.tsx - /review/ now redirects to /pipeline (was /review/audio, which no longer exists) - AudioDetailPage back link goes to /pipeline - nav: drop the Audio link - PipelineCard: three buttons on every card — Details (TanStack Link to /review/audio/$id — the detail route stays, it's how you drill in), Skip (POST /api/review/:id/skip), Approve (POST /api/review/:id/approve). Remove the old 'Approve up to here' button (it was computing against frontend ordering we don't want to maintain, and it was broken). - SeriesCard: drop onApproveUpTo, pass new approve/skip handlers through to each expanded episode card - server: remove now-unused POST /api/review/approve-batch (no callers)
This commit is contained in:
@@ -734,48 +734,6 @@ app.post("/:id/rescan", async (c) => {
|
||||
return c.json(detail);
|
||||
});
|
||||
|
||||
// ─── Pipeline: approve a batch of plan IDs ──────────────────────────────────
|
||||
//
|
||||
// The pipeline UI groups episodes into series cards and interleaves them
|
||||
// with movies in a frontend-specific order, so we can't reconstruct
|
||||
// "up to here" by re-running an ORDER BY on the server. The client knows
|
||||
// exactly which plans are visually before (and including) the clicked card
|
||||
// and sends them as an explicit list.
|
||||
|
||||
app.post("/approve-batch", async (c) => {
|
||||
const body = await c.req.json<{ planIds: unknown }>().catch(() => ({ planIds: null }));
|
||||
if (!Array.isArray(body.planIds) || !body.planIds.every((id) => typeof id === "number" && id > 0)) {
|
||||
return c.json({ error: "planIds must be an array of positive integers" }, 400);
|
||||
}
|
||||
const planIds = body.planIds as number[];
|
||||
if (planIds.length === 0) return c.json({ approved: 0 });
|
||||
const db = getDb();
|
||||
const toApprove = planIds;
|
||||
|
||||
// Only approve plans that are still pending and not noop. Skip silently
|
||||
// if a plan was already approved/skipped or doesn't exist — keeps batch
|
||||
// idempotent under concurrent edits.
|
||||
let approved = 0;
|
||||
for (const planId of toApprove) {
|
||||
const planRow = db
|
||||
.prepare(
|
||||
"SELECT id, item_id, status, is_noop, job_type FROM review_plans WHERE id = ? AND status = 'pending' AND is_noop = 0",
|
||||
)
|
||||
.get(planId) as { id: number; item_id: number; job_type: string } | undefined;
|
||||
if (!planRow) continue;
|
||||
db.prepare("UPDATE review_plans SET status = 'approved', reviewed_at = datetime('now') WHERE id = ?").run(planId);
|
||||
const detail = loadItemDetail(db, planRow.item_id);
|
||||
if (detail.item && detail.command) {
|
||||
db
|
||||
.prepare("INSERT INTO jobs (item_id, command, job_type, status) VALUES (?, ?, ?, 'pending')")
|
||||
.run(planRow.item_id, detail.command, planRow.job_type);
|
||||
approved++;
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({ approved });
|
||||
});
|
||||
|
||||
// ─── Pipeline: series language ───────────────────────────────────────────────
|
||||
|
||||
app.patch("/series/:seriesKey/language", async (c) => {
|
||||
|
||||
Reference in New Issue
Block a user