This commit is contained in:
1 parent
8efd032cc6
commit
df38dccbf1
735 files changed
+128321
-120870
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { ExternalLink, Server } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import { EmulatorSettingsForm } from "@/components/admin/emulator-settings-form";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
@@ -8,98 +8,99 @@ import { calcPagination } from "@/lib/admin-helpers";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
const TRANSLATION_KEY_PATTERNS = [
|
||||
"commands.description.%",
|
||||
"commands.keys.%",
|
||||
"commands.cmd_%",
|
||||
"wordfilter.%",
|
||||
"pet.%message%",
|
||||
"matchmaking.%message%",
|
||||
"message.%",
|
||||
"notification.%",
|
||||
"commands.description.%",
|
||||
"commands.keys.%",
|
||||
"commands.cmd_%",
|
||||
"wordfilter.%",
|
||||
"pet.%message%",
|
||||
"matchmaking.%message%",
|
||||
"message.%",
|
||||
"notification.%",
|
||||
] as const;
|
||||
|
||||
export default async function EmulatorTranslationsPage({
|
||||
searchParams,
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<Record<string, string | undefined>>;
|
||||
searchParams: Promise<Record<string, string | undefined>>;
|
||||
}) {
|
||||
const t = await getTranslations("pages.admin.translations.emulator");
|
||||
const sp = await searchParams;
|
||||
const search = sp.search || "";
|
||||
const group = sp.group || "";
|
||||
const perPage = Math.min(Math.max(parseInt(sp.perPage || "50", 10), 10), 200);
|
||||
const page = Math.max(parseInt(sp.page || "1", 10), 1);
|
||||
const t = await getTranslations("pages.admin.translations.emulator");
|
||||
const sp = await searchParams;
|
||||
const search = sp.search || "";
|
||||
const group = sp.group || "";
|
||||
const perPage = Math.min(Math.max(parseInt(sp.perPage || "50", 10), 10), 200);
|
||||
const page = Math.max(parseInt(sp.page || "1", 10), 1);
|
||||
|
||||
const patternFilters: Prisma.EmulatorSettingsWhereInput[] = TRANSLATION_KEY_PATTERNS.map((p) => ({
|
||||
key: { contains: p.replace(/%/g, "") },
|
||||
}));
|
||||
const patternFilters: Prisma.EmulatorSettingsWhereInput[] =
|
||||
TRANSLATION_KEY_PATTERNS.map((p) => ({
|
||||
key: { contains: p.replace(/%/g, "") },
|
||||
}));
|
||||
|
||||
const baseFilter: Prisma.EmulatorSettingsWhereInput = { OR: patternFilters };
|
||||
const baseFilter: Prisma.EmulatorSettingsWhereInput = { OR: patternFilters };
|
||||
|
||||
const conditions: Prisma.EmulatorSettingsWhereInput[] = [baseFilter];
|
||||
if (group) conditions.push({ key: { startsWith: `${group}.` } });
|
||||
if (search) {
|
||||
conditions.push({
|
||||
OR: [{ key: { contains: search } }, { value: { contains: search } }],
|
||||
});
|
||||
}
|
||||
const where: Prisma.EmulatorSettingsWhereInput = { AND: conditions };
|
||||
const conditions: Prisma.EmulatorSettingsWhereInput[] = [baseFilter];
|
||||
if (group) conditions.push({ key: { startsWith: `${group}.` } });
|
||||
if (search) {
|
||||
conditions.push({
|
||||
OR: [{ key: { contains: search } }, { value: { contains: search } }],
|
||||
});
|
||||
}
|
||||
const where: Prisma.EmulatorSettingsWhereInput = { AND: conditions };
|
||||
|
||||
const [settings, total, allKeys] = await Promise.all([
|
||||
prisma.emulatorSettings.findMany({
|
||||
where,
|
||||
orderBy: { key: "asc" },
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
prisma.emulatorSettings.count({ where }),
|
||||
prisma.emulatorSettings.findMany({
|
||||
where: baseFilter,
|
||||
select: { key: true },
|
||||
}),
|
||||
]);
|
||||
const [settings, total, allKeys] = await Promise.all([
|
||||
prisma.emulatorSettings.findMany({
|
||||
where,
|
||||
orderBy: { key: "asc" },
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
prisma.emulatorSettings.count({ where }),
|
||||
prisma.emulatorSettings.findMany({
|
||||
where: baseFilter,
|
||||
select: { key: true },
|
||||
}),
|
||||
]);
|
||||
|
||||
const groupCounts = new Map<string, number>();
|
||||
for (const { key } of allKeys) {
|
||||
const g = key.includes(".") ? key.split(".")[0] : "general";
|
||||
groupCounts.set(g, (groupCounts.get(g) ?? 0) + 1);
|
||||
}
|
||||
const allGroups = Array.from(groupCounts.entries())
|
||||
.map(([name, count]) => ({ name, count }))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const groupCounts = new Map<string, number>();
|
||||
for (const { key } of allKeys) {
|
||||
const g = key.includes(".") ? key.split(".")[0] : "general";
|
||||
groupCounts.set(g, (groupCounts.get(g) ?? 0) + 1);
|
||||
}
|
||||
const allGroups = Array.from(groupCounts.entries())
|
||||
.map(([name, count]) => ({ name, count }))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const pagination = calcPagination(total, page, perPage);
|
||||
const settingsMap = settings.map((s) => ({ key: s.key, value: s.value }));
|
||||
const pagination = calcPagination(total, page, perPage);
|
||||
const settingsMap = settings.map((s) => ({ key: s.key, value: s.value }));
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold flex items-center gap-2">
|
||||
<Server className="w-6 h-6" />
|
||||
{t("title")}
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">{t("subtitle")}</p>
|
||||
</div>
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link href="/admin/settings/emulator">
|
||||
<ExternalLink className="w-4 h-4 mr-1" />
|
||||
{t("fullSettings")}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between flex-wrap gap-2">
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold flex items-center gap-2">
|
||||
<Server className="w-6 h-6" />
|
||||
{t("title")}
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">{t("subtitle")}</p>
|
||||
</div>
|
||||
<Button asChild variant="outline" size="sm">
|
||||
<Link href="/admin/settings/emulator">
|
||||
<ExternalLink className="w-4 h-4 mr-1" />
|
||||
{t("fullSettings")}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="rounded-md border bg-muted/40 px-3 py-2 text-xs text-muted-foreground">
|
||||
{t("infoBox")}
|
||||
</div>
|
||||
<div className="rounded-md border bg-muted/40 px-3 py-2 text-xs text-muted-foreground">
|
||||
{t("infoBox")}
|
||||
</div>
|
||||
|
||||
<EmulatorSettingsForm
|
||||
settings={settingsMap}
|
||||
pagination={pagination}
|
||||
search={search}
|
||||
allGroups={allGroups}
|
||||
activeGroup={group}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
<EmulatorSettingsForm
|
||||
settings={settingsMap}
|
||||
pagination={pagination}
|
||||
search={search}
|
||||
allGroups={allGroups}
|
||||
activeGroup={group}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user