feat(catalog): persist idempotent bulk operations and retryable deliveries
This commit is contained in:
1 parent
76e46d295c
commit
13665e0c3c
53 files changed
+1316
-76
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import Link from "@/components/link";
|
||||
import { DeliveryRetry } from "@/features/operations/retry-button";
|
||||
import { listEffects } from "@/features/operations/server";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
export default async function DeliveryPage() {
|
||||
const { session, permissions } = await getAdminContext();
|
||||
if (!canAccess(permissions, PERMS.DEVOPS_VIEW, session.user.rank))
|
||||
redirect("/admin");
|
||||
const editable = canAccess(permissions, PERMS.DEVOPS_EDIT, session.user.rank);
|
||||
const t = await getTranslations("pages.admin.deliveries");
|
||||
const items = await listEffects();
|
||||
return (
|
||||
<section className="min-w-0 space-y-4">
|
||||
<h1 className="text-2xl font-semibold">{t("title")}</h1>
|
||||
<p className="text-muted-foreground">{t("scope")}</p>
|
||||
<Link href="/admin/devops/deliveries" className="btn btn-outline">
|
||||
{t("refresh")}
|
||||
</Link>
|
||||
{!items.length ? (
|
||||
<p className="admin-card">{t("empty")}</p>
|
||||
) : (
|
||||
<ul className="space-y-3">
|
||||
{items.map((item) => (
|
||||
<li key={item.id} className="admin-card min-w-0 space-y-2">
|
||||
<div className="flex flex-wrap justify-between gap-3">
|
||||
<strong>
|
||||
{t(item.topic === "catalog.refresh" ? "hotel" : "export")}
|
||||
</strong>
|
||||
<span>{t(`states.${item.status}`)}</span>
|
||||
</div>
|
||||
<p className="break-all text-sm">
|
||||
{item.operationId} · {t("actor", { id: item.actorId })} ·{" "}
|
||||
{t("attempts", { count: item.attempts })}
|
||||
</p>
|
||||
{item.status === "failed" && <p>{t("retryError")}</p>}
|
||||
{editable && item.status === "failed" && (
|
||||
<DeliveryRetry id={item.id} />
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -54,6 +54,7 @@ export default async function DevOpsPage() {
|
||||
const t = await getTranslations("pages.admin.devops");
|
||||
const data = await getDevOpsData();
|
||||
const performance = await getTranslations("pages.admin.performance");
|
||||
const deliveries = await getTranslations("pages.admin.deliveries");
|
||||
const installation = await getTranslations("pages.admin.installation");
|
||||
|
||||
return (
|
||||
@@ -67,6 +68,9 @@ export default async function DevOpsPage() {
|
||||
<Link href="/admin/devops/performance" className="btn btn-outline">
|
||||
{performance("title")}
|
||||
</Link>
|
||||
<Link href="/admin/devops/deliveries" className="btn btn-outline">
|
||||
{deliveries("title")}
|
||||
</Link>
|
||||
{/* Status cards */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-5">
|
||||
<Card>
|
||||
|
||||
Reference in new issue
Block a user