From a070004e7b607cf356332fdf1b0edbc3adb65948 Mon Sep 17 00:00:00 2001 From: simoleo89 Date: Sun, 6 Sep 2026 17:17:30 +0200 Subject: [PATCH] feat(admin): reorganize housekeeping and strengthen shared workflows --- src/app/admin/devops/cms-errors/page.tsx | 81 ++-- src/app/admin/devops/page.tsx | 2 +- src/app/admin/layout.tsx | 34 +- src/app/admin/page.tsx | 2 + .../studio/sync/catalog-export-client.tsx | 16 +- src/app/admin/users/show/[id]/page.tsx | 10 +- src/app/api/admin/search/route.ts | 201 +++++----- src/components/admin/admin-favorites.tsx | 106 +++++ src/components/admin/admin-mobile-wrapper.tsx | 10 +- src/components/admin/admin-sidebar-nav.tsx | 41 +- src/components/admin/admin-topbar.tsx | 7 +- src/components/admin/admin-work-queue.tsx | 104 +++++ src/components/admin/article-form.tsx | 364 ++++++++++-------- src/components/admin/data-table.tsx | 157 +++++--- src/components/admin/rich-text.tsx | 17 +- src/components/admin/search-dialog.tsx | 80 +++- src/components/admin/search-input.tsx | 11 +- .../admin/studio/furniture-jobs.tsx | 50 ++- .../admin/studio/use-furniture-jobs.ts | 14 +- src/hooks/use-server-action.ts | 25 +- src/hooks/use-unsaved-changes.ts | 50 +++ src/hooks/use-visible-polling.ts | 38 ++ src/i18n/housekeeping-messages.test.ts | 49 +++ src/lib/admin-nav.ts | 14 +- src/lib/admin-navigation.test.ts | 46 +++ src/lib/admin-navigation.ts | 180 +++++++++ src/lib/admin-search-permissions.test.ts | 89 +++++ src/lib/admin-table-state.test.ts | 17 + src/lib/admin-table-state.ts | 6 + src/lib/admin/navigation.ts | 32 ++ src/lib/furni/import-job-retry.test.ts | 25 ++ src/lib/furni/import-job-retry.ts | 10 + src/lib/staff-smoke-contract.test.ts | 8 +- src/messages/en.json | 113 +++++- src/messages/it.json | 120 +++++- 35 files changed, 1667 insertions(+), 462 deletions(-) create mode 100644 src/components/admin/admin-favorites.tsx create mode 100644 src/components/admin/admin-work-queue.tsx create mode 100644 src/hooks/use-unsaved-changes.ts create mode 100644 src/hooks/use-visible-polling.ts create mode 100644 src/i18n/housekeeping-messages.test.ts create mode 100644 src/lib/admin-navigation.test.ts create mode 100644 src/lib/admin-navigation.ts create mode 100644 src/lib/admin-search-permissions.test.ts create mode 100644 src/lib/admin-table-state.test.ts create mode 100644 src/lib/admin-table-state.ts create mode 100644 src/lib/admin/navigation.ts create mode 100644 src/lib/furni/import-job-retry.test.ts create mode 100644 src/lib/furni/import-job-retry.ts diff --git a/src/app/admin/devops/cms-errors/page.tsx b/src/app/admin/devops/cms-errors/page.tsx index ea19422350..375ab3fabb 100644 --- a/src/app/admin/devops/cms-errors/page.tsx +++ b/src/app/admin/devops/cms-errors/page.tsx @@ -1,4 +1,5 @@ import { redirect } from "next/navigation"; +import { getTranslations } from "next-intl/server"; import Link from "@/components/link"; import { ErrorStore } from "@/lib/error-monitor"; import { canAccess, getAdminContext, PERMS } from "@/lib/permissions"; @@ -11,6 +12,7 @@ export default async function CmsErrorsPage({ const { session, permissions } = await getAdminContext(); if (!canAccess(permissions, PERMS.DEVOPS_VIEW, session.user.rank)) redirect("/admin"); + const t = await getTranslations("pages.admin.cmsErrors"); const params = await searchParams; const query = (params.q ?? "").trim().slice(0, 200).toLowerCase(); let result: Awaited>; @@ -19,14 +21,15 @@ export default async function CmsErrorsPage({ } catch { return (
- Error storage could not be read. Check the CMS storage volume and - permissions. + {t("storageError")}
); } const filtered = result.records.filter( (r) => (!params.source || r.source === params.source) && + (params.status !== "open" || !r.resolved) && + (params.status !== "resolved" || r.resolved) && (!query || JSON.stringify(r).toLowerCase().includes(query)), ); const groups = new Map(); @@ -43,62 +46,62 @@ export default async function CmsErrorsPage({ ), ); const pageHref = (next: number) => - `?${new URLSearchParams({ q: params.q ?? "", source: params.source ?? "", page: String(next) })}`; + `?${new URLSearchParams({ q: params.q ?? "", source: params.source ?? "", status: params.status ?? "", page: String(next) })}`; return (
-

CMS error center

-

- Server and browser errors from the last 7 days. Browser reports are - unverified client observations. -

+

{t("title")}

+

{t("subtitle")}

DevOps - Emulator errors + {t("emulator")} - Refresh / clear filters + {t("refresh")}
+

- {filtered.length} occurrences · {groups.size} groups.{" "} - {result.truncated - ? "Showing the latest 1,000 events. Narrowing filters searches this retained window." - : ""}{" "} - Storage is limited to 10 MB per day; excess events remain in server logs - where available. + {t("counts", { count: filtered.length, groups: groups.size })}{" "} + {result.truncated ? t("truncated") : ""} {t("retention")}

{groups.size === 0 ? ( -
- No captured errors match these filters. Monitoring starts with this - deployment; older console logs are not imported. -
+
{t("empty")}
) : null} {[...groups.entries()] .slice((page - 1) * 25, page * 25) @@ -108,25 +111,24 @@ export default async function CmsErrorsPage({
- {r.resolved ? "Resolved" : "Open"} · {r.source} ·{" "} - {events.length} occurrences · {r.at} + {t(r.resolved ? "resolved" : "open")} · {r.source} ·{" "} + {t("occurrences", { count: events.length })} · {r.at}

{r.event}

{r.message}

- Reference: {r.id} + {t("reference")}: {r.id}

- Release: {r.release} + {t("release")}: {r.release}

 									{JSON.stringify(r.context, null, 2)}
 								
-									{r.stack ||
-										"No stack supplied. Use the reference or digest to correlate server logs."}
+									{r.stack || t("noStack")}
 								
{!r.resolved && canAccess(permissions, PERMS.DEVOPS_EDIT, session.user.rank) ? ( @@ -137,16 +139,16 @@ export default async function CmsErrorsPage({ value={r.fingerprint} />

- A new occurrence reopens the group automatically. + {t("reopenHint")}

) : null}
- Occurrence references + {t("references")}
    {events.map((e) => ( @@ -156,23 +158,20 @@ export default async function CmsErrorsPage({ ))}
-

- Browser stack traces may reference compiled chunks. This view - does not infer a root cause or include request bodies. -

+

{t("stackHint")}

); })} -