chore(ops): strip redundant force-dynamic and probe Redis in ops health
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
3e584aadaf
commit
3ac5d6f4f6
60 files changed
+95
-114
No files matched your search
@@ -8,8 +8,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { EditAdDeleteButton } from "../ads-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function EditAd({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -8,8 +8,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { AdsTable } from "./ads-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminAds() {
|
||||
const { session, permissions } = await getAdminContext();
|
||||
if (!canAccess(permissions, PERMS.PAGES_VIEW, session.user.rank)) {
|
||||
|
||||
@@ -8,8 +8,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type ApplicationRow = {
|
||||
id: bigint;
|
||||
userId: number;
|
||||
|
||||
@@ -8,8 +8,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function EditArticle({
|
||||
params,
|
||||
searchParams,
|
||||
|
||||
@@ -10,8 +10,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminArticles({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Badges" };
|
||||
|
||||
export default async function AdminBadges({
|
||||
|
||||
@@ -10,8 +10,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminBans() {
|
||||
const { session, permissions } = await getAdminContext();
|
||||
if (!canAccess(permissions, PERMS.BANS_VIEW, session.user.rank)) {
|
||||
|
||||
@@ -5,8 +5,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Campaign = {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
@@ -6,8 +6,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Campaign = {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
@@ -8,8 +8,6 @@ import { loadCatalogItemsData } from "@/lib/services/catalog-items-loader";
|
||||
import { getAncestors } from "@/lib/services/catalog-tree";
|
||||
import { CatalogDetailTabs } from "./catalog-detail-tabs";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function CatalogEditPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -17,8 +17,6 @@ import { prisma } from "@/lib/prisma";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
import { CommandocentrumControls } from "./commandocentrum-controls";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
function decodeStacktrace(raw: unknown): string {
|
||||
if (raw == null) return "";
|
||||
try {
|
||||
@@ -66,6 +64,7 @@ export default async function CommandoCentrum() {
|
||||
]);
|
||||
|
||||
const dbOk = health.dbOk;
|
||||
const redisOk = health.redisOk;
|
||||
const emulatorOnline = health.emulatorOk;
|
||||
const onlineCount = onlineRoster.count;
|
||||
const onlineUsers = onlineRoster.users;
|
||||
@@ -175,6 +174,23 @@ export default async function CommandoCentrum() {
|
||||
detail={dbOk ? t("connectionHealthy") : t("unreachable")}
|
||||
state={dbOk ? "ok" : "danger"}
|
||||
/>
|
||||
<DiagnosticRow
|
||||
label="Redis"
|
||||
detail={
|
||||
redisOk === true
|
||||
? "PONG"
|
||||
: redisOk === false
|
||||
? "Unreachable"
|
||||
: "REDIS_URL not configured"
|
||||
}
|
||||
state={
|
||||
redisOk === true
|
||||
? "ok"
|
||||
: redisOk === false
|
||||
? "danger"
|
||||
: "warn"
|
||||
}
|
||||
/>
|
||||
<DiagnosticRow
|
||||
label={t("emulatorRcon")}
|
||||
detail={
|
||||
|
||||
@@ -30,6 +30,7 @@ async function getDevOpsData() {
|
||||
return {
|
||||
dbStatus: health.dbOk ? ("healthy" as const) : ("error" as const),
|
||||
dbLatency: health.dbLatencyMs,
|
||||
redisOk: health.redisOk,
|
||||
recentErrors,
|
||||
errorsToday,
|
||||
emuVersion: emuVersion?.value ?? "Unknown",
|
||||
@@ -49,7 +50,7 @@ export default async function DevOpsPage() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Status cards */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-5">
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Database</CardTitle>
|
||||
@@ -67,6 +68,33 @@ export default async function DevOpsPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Redis</CardTitle>
|
||||
<Server className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Badge
|
||||
variant={
|
||||
data.redisOk === false
|
||||
? "destructive"
|
||||
: data.redisOk === true
|
||||
? "default"
|
||||
: "secondary"
|
||||
}
|
||||
>
|
||||
{data.redisOk === true
|
||||
? "Healthy"
|
||||
: data.redisOk === false
|
||||
? "Error"
|
||||
: "Not configured"}
|
||||
</Badge>
|
||||
<p className="text-xs text-muted-foreground mt-1">
|
||||
Cache / rate limits / sessions
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">Emulator</CardTitle>
|
||||
|
||||
@@ -9,8 +9,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const TEXTS_LIMIT = 300;
|
||||
|
||||
export default async function AdminEmulator() {
|
||||
|
||||
@@ -7,8 +7,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminGuildDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -11,8 +11,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminGuildsPage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function EditHelpQuestion({
|
||||
params,
|
||||
searchParams,
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminHelpQuestions() {
|
||||
const { session, permissions } = await getAdminContext();
|
||||
if (!canAccess(permissions, PERMS.PAGES_VIEW, session.user.rank)) {
|
||||
|
||||
@@ -8,8 +8,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { AdminHelpTicketDetail } from "./admin-help-ticket-detail";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminHelpTicketDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { type HelpTicketRow, HelpTicketsTable } from "./help-tickets-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminHelpTicketsPage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -6,8 +6,6 @@ import { prisma } from "@/lib/prisma";
|
||||
import { getAuditLogs } from "@/lib/services/audit";
|
||||
import { AuditSection, ExportSection } from "./client";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminHousekeeping({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -12,8 +12,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type IpRow = {
|
||||
id: bigint;
|
||||
ipAddress: string;
|
||||
|
||||
@@ -6,8 +6,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { ItemsBaseEditForm } from "./items-base-edit-form";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function ItemsBaseDetailPage({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { StaffActivitiesTable } from "./staff-activities-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const SORT_MAP: Record<string, "createdAt" | "userId" | "action"> = {
|
||||
when: "createdAt",
|
||||
staff: "userId",
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const KEYS = [
|
||||
"maintenance_enabled",
|
||||
"maintenance_message",
|
||||
|
||||
@@ -12,8 +12,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminMarketplacePage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -7,8 +7,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { type CfhRow, CfhTable } from "./cfh-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function CfhListPage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -13,8 +13,6 @@ import { activeBanWhere } from "@/lib/bans";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type RankCount = { rank: number; count: number };
|
||||
|
||||
export default async function AdminDashboard() {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { calcPagination, parseListParams } from "@/lib/admin-helpers";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminPhotos({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -9,8 +9,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Radio API Keys" };
|
||||
|
||||
type ApiKey = {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Radio AutoDJ" };
|
||||
|
||||
type Track = {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Banner = {
|
||||
id: bigint;
|
||||
userId: bigint;
|
||||
|
||||
@@ -6,8 +6,6 @@ import { resolveHotelName } from "@/lib/hotel-name";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
import { EmbedSnippet } from "./embed-snippet";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Radio Embed" };
|
||||
|
||||
export default async function AdminRadioEmbedPage() {
|
||||
|
||||
@@ -3,8 +3,6 @@ import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type History = {
|
||||
id: bigint;
|
||||
userId: bigint;
|
||||
|
||||
@@ -5,8 +5,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Shout = {
|
||||
id: bigint;
|
||||
userId: bigint;
|
||||
|
||||
@@ -2,8 +2,6 @@ import { getTranslations } from "next-intl/server";
|
||||
import { DiagnosticRow, StatusCard } from "@/components/admin/dashboard";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Radio Monitoring" };
|
||||
|
||||
const FETCH_TIMEOUT_MS = 4000;
|
||||
|
||||
@@ -5,8 +5,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { formatDate } from "@/lib/format-date";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Shout = {
|
||||
id: bigint;
|
||||
userId: bigint;
|
||||
|
||||
@@ -4,8 +4,6 @@ import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Radio Points" };
|
||||
|
||||
const DEFAULTS = {
|
||||
|
||||
@@ -8,8 +8,6 @@ import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Rank = {
|
||||
id: bigint;
|
||||
name: string;
|
||||
|
||||
@@ -7,8 +7,6 @@ import { StatusCard } from "@/components/admin/dashboard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type Field = { key: string; comment: string };
|
||||
type Group = { title: string; fields: Field[] };
|
||||
|
||||
|
||||
@@ -11,8 +11,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const CURRENCY_TYPES = ["diamonds", "credits", "duckets", "points"];
|
||||
|
||||
export default async function AdminRareValues() {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { AdvancedSettingsPanel } from "./advanced-settings-panel";
|
||||
import { FIELD_DEFAULTS, MANAGED_SETTING_KEYS } from "./cms-settings-config";
|
||||
import { CmsSettingsForm } from "./cms-settings-form";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const metadata = { title: "CMS Settings" };
|
||||
|
||||
export default async function AdminSettings() {
|
||||
|
||||
@@ -7,8 +7,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function EditShopArticle({
|
||||
params,
|
||||
}: {
|
||||
|
||||
@@ -12,8 +12,6 @@ import { formatDate } from "@/lib/format-date";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const PAID_STATUS = new Set(["completed", "paid", "success", "approved"]);
|
||||
const RECENT_ORDERS = 25;
|
||||
|
||||
|
||||
@@ -6,8 +6,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
type TeamRow = {
|
||||
id: bigint;
|
||||
rankName: string;
|
||||
|
||||
@@ -15,7 +15,6 @@ import { listCustomThemes } from "@/lib/theme-custom-store";
|
||||
import { FONTS, PRESETS } from "@/lib/theme-presets";
|
||||
import { ColorField } from "./color-field";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const metadata = { title: "Theme" };
|
||||
|
||||
const COLOR_FIELDS: {
|
||||
|
||||
@@ -10,8 +10,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { type TicketRow, TicketsTable } from "./tickets-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function AdminTicketsPage({
|
||||
searchParams,
|
||||
}: {
|
||||
|
||||
@@ -8,8 +8,6 @@ import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { type TransactionRow, TransactionsTable } from "./transactions-table";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
const PAID_STATUS = ["completed", "paid", "success", "approved"] as const;
|
||||
const FAILED_STATUS = [
|
||||
"failed",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
/**
|
||||
* Legacy URL — the canonical edit UI lives at /admin/users/edit/[id]
|
||||
* and is gated by PERMS.USERS_EDIT.
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
export const metadata = { title: "VPN" };
|
||||
|
||||
const PROVIDERS: { value: string; label: string }[] = [
|
||||
|
||||
@@ -11,8 +11,6 @@ import { Button } from "@/components/ui/button";
|
||||
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export const metadata = { title: "Writeable boxes" };
|
||||
|
||||
export default async function AdminWriteableBoxes() {
|
||||
|
||||
Reference in new issue
Block a user