import { count, eq, ne } from "drizzle-orm"; import { getTranslations } from "next-intl/server"; import Link from "@/components/link"; import { collectOperations } from "@/lib/admin/operations-inbox"; import { db, WebsiteArticles, WebsiteHelpCenterTickets, WebsiteTicket, } from "@/lib/db"; import { ErrorStore } from "@/lib/error-monitor"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; import { ImportJobStore } from "@/lib/services/furni-job-store"; export async function OperationsInbox() { const { session, permissions } = await getAdminContext(); const allowed = (permission: string) => canAccess(permissions, permission, session.user.rank); const t = await getTranslations("pages.admin.operations"); const result = await collectOperations([ { source: "errors", allowed: allowed(PERMS.DEVOPS_VIEW), load: async () => { const { records } = await new ErrorStore().read(); const total = new Set( records .filter((record) => !record.resolved) .map((record) => record.fingerprint), ).size; return [ { id: "unresolved", source: "errors", count: total, severity: 3, href: "/admin/devops/cms-errors?status=open", }, ]; }, }, { source: "imports", allowed: allowed(PERMS.ASSETS_IMPORT), load: async () => { const jobs = await new ImportJobStore().list({ userId: Number(session.user.id), limit: 30, }); const total = jobs.filter( (job) => job.state === "interrupted" || job.items.some((item) => item.state === "failed"), ).length; return [ { id: "attention", source: "imports", count: total, severity: 2, href: "/admin/operations", }, ]; }, }, { source: "tickets", allowed: allowed(PERMS.TICKETS_VIEW), load: async () => { const [rows, helpRows] = await Promise.all([ db .select({ total: count() }) .from(WebsiteTicket) .where(ne(WebsiteTicket.status, "closed")), db .select({ total: count() }) .from(WebsiteHelpCenterTickets) .where(eq(WebsiteHelpCenterTickets.open, true)), ]); return [ { id: "open", source: "tickets", count: Number(rows[0]?.total ?? 0) + Number(helpRows[0]?.total ?? 0), severity: 1, href: "/admin/tickets", }, ]; }, }, { source: "publications", allowed: allowed(PERMS.NEWS_VIEW), load: async () => { const rows = await db .select({ total: count() }) .from(WebsiteArticles) .where(eq(WebsiteArticles.status, "draft")); return [ { id: "drafts", source: "publications", count: Number(rows[0]?.total ?? 0), severity: 0, href: "/admin/articles?status=draft", }, ]; }, }, ]); return (

{t("title")}

{t("hint")}

{result.items.length === 0 && result.unavailable.length === 0 ? (

{t("empty")}

) : null}
{result.items.map((item) => ( {t(item.source)} {item.count} ))}
{result.unavailable.map((source) => (

{t("unavailable", { source: t(source) })}

))} {allowed(PERMS.DEVOPS_VIEW) ? ( {t("installation")} ) : null}
); }