import { defineQuery, views } from "$hatk"; import type { Gallery } from "$hatk"; import { hydrateGalleries } from "../hydrate/galleries.ts"; /** * The review queue: submissions the group has neither accepted nor declined. * * Anyone's, not only members': who is a member is not a public fact grain can * check. Whoever acts as the group decides; declining a stranger is one click. */ export default defineQuery("social.grain.unspecced.getGroupSubmissions", async (ctx) => { const { params, ok, db } = ctx; const limit = params.limit ?? 30; const rows = (await db.query( `SELECT s.uri, s.cid, s.gallery, s.created_at FROM "social.grain.group.submission" s LEFT JOIN _repos r ON r.did = s.did WHERE s."group" = $1 AND (r.status IS NULL OR r.status NOT IN ('takendown', 'deactivated', 'deleted')) AND NOT EXISTS (SELECT 1 FROM "social.grain.group.item" i WHERE i.did = s."group" AND i.gallery = s.gallery) AND NOT EXISTS (SELECT 1 FROM "social.grain.group.decline" d WHERE d.did = s."group" AND d.submission = s.uri) ORDER BY s.created_at DESC LIMIT $2`, [params.group, limit], )) as { uri: string; cid: string; gallery: string; created_at: string }[]; const galleries = await ctx.getRecords("social.grain.gallery", [ ...new Set(rows.map((r) => r.gallery)), ]); const galleryViews = await hydrateGalleries(ctx, [...galleries.values()]); const viewByUri = new Map(galleryViews.map((g) => [g.uri, g])); const submissions = rows.flatMap((r) => { const gallery = viewByUri.get(r.gallery); if (!gallery) return []; // the gallery was deleted; nothing to review return [ views.submissionView({ uri: r.uri, cid: r.cid, group: params.group, gallery, createdAt: r.created_at, }), ]; }); return ok({ submissions }); });