feat(library): ignore a release (do-not-monitor)
Add MonitoredRelease.ignored (migration add_release_ignored). The monitor's enqueue_due skips ignored releases, and they drop off the Wanted list — independent of `monitored`, so auto-monitor-future can't silently re-grab an album the user chose to ignore. - Worker enqueue_due: AND NOT mr.ignored. - /api/releases/[id] PATCH now accepts `ignored`; /api/wanted filters it out; artist detail exposes `ignored`. - UI: Ignore button on Wanted rows; discography shows an "Ignored" badge with an Ignore/Un-ignore toggle (monitor + search disabled while ignored). Worker + web tests added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ id:
|
||||
secondaryTypes: r.secondaryTypes,
|
||||
firstReleaseDate: r.firstReleaseDate,
|
||||
monitored: r.monitored,
|
||||
ignored: r.ignored,
|
||||
state: r.state,
|
||||
currentQualityClass: r.currentQualityClass,
|
||||
})),
|
||||
|
||||
@@ -22,9 +22,18 @@ describe("PATCH /api/releases/[id]", () => {
|
||||
expect((await prisma.monitoredRelease.findUnique({ where: { id: r.id } }))!.monitored).toBe(true);
|
||||
});
|
||||
|
||||
it("400s a non-boolean and 404s an unknown release", async () => {
|
||||
it("toggles ignored independently of monitored", async () => {
|
||||
const r = await seedRelease(true);
|
||||
const res = await PATCH(patchReq({ ignored: true }), ctx(r.id));
|
||||
expect(res.status).toBe(200);
|
||||
const row = (await prisma.monitoredRelease.findUnique({ where: { id: r.id } }))!;
|
||||
expect(row.ignored).toBe(true);
|
||||
expect(row.monitored).toBe(true); // ignore doesn't clear monitored
|
||||
});
|
||||
|
||||
it("400s when neither monitored nor ignored is a boolean, 404s an unknown release", async () => {
|
||||
const r = await seedRelease();
|
||||
expect((await PATCH(patchReq({ monitored: 1 }), ctx(r.id))).status).toBe(400);
|
||||
expect((await PATCH(patchReq({ monitored: true }), ctx("nope"))).status).toBe(404);
|
||||
expect((await PATCH(patchReq({ ignored: true }), ctx("nope"))).status).toBe(404);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,13 +9,16 @@ export async function PATCH(request: Request, { params }: { params: Promise<{ id
|
||||
} catch {
|
||||
return Response.json({ error: "invalid JSON" }, { status: 400 });
|
||||
}
|
||||
const { monitored } = (body ?? {}) as { monitored?: unknown };
|
||||
if (typeof monitored !== "boolean") {
|
||||
return Response.json({ error: "monitored (boolean) is required" }, { status: 400 });
|
||||
const { monitored, ignored } = (body ?? {}) as { monitored?: unknown; ignored?: unknown };
|
||||
if (typeof monitored !== "boolean" && typeof ignored !== "boolean") {
|
||||
return Response.json({ error: "monitored or ignored (boolean) is required" }, { status: 400 });
|
||||
}
|
||||
const data: { monitored?: boolean; ignored?: boolean } = {};
|
||||
if (typeof monitored === "boolean") data.monitored = monitored;
|
||||
if (typeof ignored === "boolean") data.ignored = ignored;
|
||||
try {
|
||||
const updated = await prisma.monitoredRelease.update({ where: { id }, data: { monitored } });
|
||||
return Response.json({ id: updated.id, monitored: updated.monitored });
|
||||
const updated = await prisma.monitoredRelease.update({ where: { id }, data });
|
||||
return Response.json({ id: updated.id, monitored: updated.monitored, ignored: updated.ignored });
|
||||
} catch (e) {
|
||||
if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2025") {
|
||||
return Response.json({ error: "not found" }, { status: 404 });
|
||||
|
||||
@@ -4,7 +4,7 @@ import { searchReleaseGroup } from "@/lib/musicbrainz";
|
||||
|
||||
export async function GET() {
|
||||
const items = await prisma.monitoredRelease.findMany({
|
||||
where: { monitored: true, state: { not: "fulfilled" } },
|
||||
where: { monitored: true, ignored: false, state: { not: "fulfilled" } },
|
||||
orderBy: [{ lastSearchedAt: { sort: "asc", nulls: "first" } }, { createdAt: "asc" }],
|
||||
});
|
||||
return Response.json({
|
||||
|
||||
Reference in New Issue
Block a user