style: format code with prettier
Local Build and Deploy / deploy (push) Successful in 49s

This commit is contained in:
openhands committed 2026-07-12 21:07:34 +02:00
1 parent e85e4d74ea
commit 2e4ed76121
378 files changed
+22404 -20686

No files matched your search

+141 -146
View File
@@ -1,87 +1,87 @@
import dynamic from 'next/dynamic'
import { redirect } from 'next/navigation'
import { CatalogTree } from '@/components/admin/catalog-tree'
import { Prisma } from '@/generated/prisma/client'
import { calcPagination, parseListParams } from '@/lib/admin-helpers'
import { canAccess, getAdminContext, PERMS } from '@/lib/permissions'
import { prisma } from '@/lib/prisma'
import { CatalogActions } from './catalog-actions'
import { CatalogTable } from './catalog-table'
import { CatalogViewToggle } from './catalog-view-toggle'
import dynamic from "next/dynamic";
import { redirect } from "next/navigation";
import { CatalogTree } from "@/components/admin/catalog-tree";
import { Prisma } from "@/generated/prisma/client";
import { calcPagination, parseListParams } from "@/lib/admin-helpers";
import { canAccess, getAdminContext, PERMS } from "@/lib/permissions";
import { prisma } from "@/lib/prisma";
import { CatalogActions } from "./catalog-actions";
import { CatalogTable } from "./catalog-table";
import { CatalogViewToggle } from "./catalog-view-toggle";
const CatalogManagerDialog = dynamic(() =>
import('@/components/admin/catalog-manager/catalog-manager-dialog').then((m) => ({
import("@/components/admin/catalog-manager/catalog-manager-dialog").then((m) => ({
default: m.CatalogManagerDialog,
})),
)
);
export default async function CatalogPagesPage({
params: paramsPromise,
searchParams,
}: {
params: Promise<{ locale: string }>
searchParams: Promise<Record<string, string>>
params: Promise<{ locale: string }>;
searchParams: Promise<Record<string, string>>;
}) {
await paramsPromise
const { session, permissions } = await getAdminContext()
await paramsPromise;
const { session, permissions } = await getAdminContext();
if (!canAccess(permissions, PERMS.CATALOG_VIEW, session.user.rank)) {
redirect('/admin')
redirect("/admin");
}
const canEdit = canAccess(permissions, PERMS.CATALOG_EDIT, session.user.rank)
const canEdit = canAccess(permissions, PERMS.CATALOG_EDIT, session.user.rank);
const params = await searchParams
const sp = new URLSearchParams(params)
const { search, perPage, page, sort, order } = parseListParams(sp)
const viewMode = sp.get('view') || 'tree'
const catalogType = sp.get('catalog') || 'normal'
const params = await searchParams;
const sp = new URLSearchParams(params);
const { search, perPage, page, sort, order } = parseListParams(sp);
const viewMode = sp.get("view") || "tree";
const catalogType = sp.get("catalog") || "normal";
// ── Builder Club mode ──────────────────────────────────────────
type TreeNodeShape = {
id: number
caption: string
parentId: number
enabled: string
visible: string
iconImage: number
iconColor: number
pageLayout: string
childCount: number
itemCount: number
}
id: number;
caption: string;
parentId: number;
enabled: string;
visible: string;
iconImage: number;
iconColor: number;
pageLayout: string;
childCount: number;
itemCount: number;
};
if (catalogType === 'bc') {
if (catalogType === "bc") {
const [totalBcPages, totalBcItems, enabledBcPages] = await Promise.all([
prisma.catalogPagesBc.count(),
prisma.catalogItemsBc.count(),
prisma.catalogPagesBc.count({ where: { enabled: '1' } }),
])
prisma.catalogPagesBc.count({ where: { enabled: "1" } }),
]);
// ── BC tree view ──────────────────────────────────────────────
let bcRootPages: TreeNodeShape[] = []
if (viewMode === 'tree') {
let bcRootPages: TreeNodeShape[] = [];
if (viewMode === "tree") {
const bcRootRaw = await prisma.catalogPagesBc.findMany({
where: { OR: [{ parentId: -1 }, { parentId: 0 }] },
orderBy: { orderNum: 'asc' },
})
const bcRootIds = bcRootRaw.map((p) => p.id)
orderBy: { orderNum: "asc" },
});
const bcRootIds = bcRootRaw.map((p) => p.id);
const [bcChildCounts, bcItemCounts] = await Promise.all([
bcRootIds.length > 0
? prisma.catalogPagesBc.groupBy({
by: ['parentId'],
by: ["parentId"],
where: { parentId: { in: bcRootIds } },
_count: true,
})
: [],
bcRootIds.length > 0
? prisma.catalogItemsBc.groupBy({
by: ['pageId'],
by: ["pageId"],
where: { pageId: { in: bcRootIds } },
_count: true,
})
: [],
])
const bcChildMap = Object.fromEntries(bcChildCounts.map((c) => [c.parentId, c._count]))
const bcItemMap = Object.fromEntries(bcItemCounts.map((c) => [c.pageId, c._count]))
]);
const bcChildMap = Object.fromEntries(bcChildCounts.map((c) => [c.parentId, c._count]));
const bcItemMap = Object.fromEntries(bcItemCounts.map((c) => [c.pageId, c._count]));
bcRootPages = bcRootRaw.map((p) => ({
id: p.id,
caption: p.caption,
@@ -93,45 +93,45 @@ export default async function CatalogPagesPage({
pageLayout: p.pageLayout,
childCount: bcChildMap[p.id] ?? 0,
itemCount: bcItemMap[p.id] ?? 0,
}))
}));
}
// ── BC table view ─────────────────────────────────────────────
let bcRows: {
id: number
caption: string
parentId: number
parentCaption: string
pageLayout: string
enabled: string
visible: string
minRank: number
orderNum: number
itemCount: number
childCount: number
}[] = []
let bcPagination = { total: 0, page: 1, perPage, lastPage: 0 }
id: number;
caption: string;
parentId: number;
parentCaption: string;
pageLayout: string;
enabled: string;
visible: string;
minRank: number;
orderNum: number;
itemCount: number;
childCount: number;
}[] = [];
let bcPagination = { total: 0, page: 1, perPage, lastPage: 0 };
if (viewMode === 'table') {
const parentFilter = sp.get('parent')
const parentId = parentFilter !== null ? parseInt(parentFilter, 10) : undefined
if (viewMode === "table") {
const parentFilter = sp.get("parent");
const parentId = parentFilter !== null ? parseInt(parentFilter, 10) : undefined;
const where: Record<string, unknown> = {}
const hasParent = parentId !== undefined && !Number.isNaN(parentId)
const where: Record<string, unknown> = {};
const hasParent = parentId !== undefined && !Number.isNaN(parentId);
if (search) {
const pattern = { contains: search }
where.OR = [{ caption: pattern }]
const pattern = { contains: search };
where.OR = [{ caption: pattern }];
}
if (hasParent) where.parentId = parentId
if (hasParent) where.parentId = parentId;
// Prisma sort key is snake_case for BC model. Translate known keys.
const sortKeyMap: Record<string, string> = {
parentId: 'parentId',
pageLayout: 'pageLayout',
orderNum: 'orderNum',
}
const sortKey = sort ? (sortKeyMap[sort] ?? sort) : 'orderNum'
const orderBy = { [sortKey]: sort ? order : 'asc' }
parentId: "parentId",
pageLayout: "pageLayout",
orderNum: "orderNum",
};
const sortKey = sort ? (sortKeyMap[sort] ?? sort) : "orderNum";
const orderBy = { [sortKey]: sort ? order : "asc" };
const [pages, total] = await Promise.all([
prisma.catalogPagesBc.findMany({
@@ -141,23 +141,23 @@ export default async function CatalogPagesPage({
take: perPage,
}),
prisma.catalogPagesBc.count({ where }),
])
]);
bcPagination = calcPagination(total, page, perPage)
bcPagination = calcPagination(total, page, perPage);
const pageIds = pages.map((p) => p.id)
const parentIds = [...new Set(pages.map((p) => p.parentId).filter((id) => id > 0))]
const pageIds = pages.map((p) => p.id);
const parentIds = [...new Set(pages.map((p) => p.parentId).filter((id) => id > 0))];
const [childCounts, itemCounts, parentPages] = await Promise.all([
pageIds.length > 0
? prisma.catalogPagesBc.groupBy({
by: ['parentId'],
by: ["parentId"],
where: { parentId: { in: pageIds } },
_count: true,
})
: [],
pageIds.length > 0
? prisma.catalogItemsBc.groupBy({
by: ['pageId'],
by: ["pageId"],
where: { pageId: { in: pageIds } },
_count: true,
})
@@ -168,17 +168,16 @@ export default async function CatalogPagesPage({
select: { id: true, caption: true },
})
: [],
])
const childCountMap = Object.fromEntries(childCounts.map((c) => [c.parentId, c._count]))
const itemCountMap = Object.fromEntries(itemCounts.map((c) => [c.pageId, c._count]))
const parentNameMap = Object.fromEntries(parentPages.map((p) => [p.id, p.caption]))
]);
const childCountMap = Object.fromEntries(childCounts.map((c) => [c.parentId, c._count]));
const itemCountMap = Object.fromEntries(itemCounts.map((c) => [c.pageId, c._count]));
const parentNameMap = Object.fromEntries(parentPages.map((p) => [p.id, p.caption]));
bcRows = pages.map((p) => ({
id: p.id,
caption: p.caption,
parentId: p.parentId,
parentCaption:
p.parentId === -1 ? 'Root' : (parentNameMap[p.parentId] ?? `#${p.parentId}`),
parentCaption: p.parentId === -1 ? "Root" : (parentNameMap[p.parentId] ?? `#${p.parentId}`),
pageLayout: String(p.pageLayout),
enabled: String(p.enabled),
visible: String(p.visible),
@@ -186,7 +185,7 @@ export default async function CatalogPagesPage({
orderNum: p.orderNum,
itemCount: itemCountMap[p.id] ?? 0,
childCount: childCountMap[p.id] ?? 0,
}))
}));
}
return (
@@ -203,17 +202,13 @@ export default async function CatalogPagesPage({
{canEdit && <CatalogActions catalogType="bc" />}
</div>
</div>
{viewMode === 'tree' ? (
{viewMode === "tree" ? (
<CatalogTree rootPages={bcRootPages} catalogType="bc" />
) : (
<CatalogTable
data={{ rows: bcRows, ...bcPagination }}
canEdit={canEdit}
catalogType="bc"
/>
<CatalogTable data={{ rows: bcRows, ...bcPagination }} canEdit={canEdit} catalogType="bc" />
)}
</div>
)
);
}
// ── Normal catalog mode ────────────────────────────────────────
@@ -222,35 +217,35 @@ export default async function CatalogPagesPage({
const [totalPages, totalItems, enabledPages] = await Promise.all([
prisma.catalogPages.count(),
prisma.catalogItems.count(),
prisma.catalogPages.count({ where: { enabled: '1' } }),
])
prisma.catalogPages.count({ where: { enabled: "1" } }),
]);
// ── Tree view data ──────────────────────────────────────────────
let rootPages: TreeNodeShape[] = []
if (viewMode === 'tree') {
let rootPages: TreeNodeShape[] = [];
if (viewMode === "tree") {
const rootPagesRaw = await prisma.catalogPages.findMany({
where: { parentId: -1 },
orderBy: { orderNum: 'asc' },
})
const rootIds = rootPagesRaw.map((p) => p.id)
orderBy: { orderNum: "asc" },
});
const rootIds = rootPagesRaw.map((p) => p.id);
const [rootChildCounts, rootItemCounts] = await Promise.all([
rootIds.length > 0
? prisma.catalogPages.groupBy({
by: ['parentId'],
by: ["parentId"],
where: { parentId: { in: rootIds } },
_count: true,
})
: [],
rootIds.length > 0
? prisma.catalogItems.groupBy({
by: ['pageId'],
by: ["pageId"],
where: { pageId: { in: rootIds } },
_count: true,
})
: [],
])
const rootChildMap = Object.fromEntries(rootChildCounts.map((c) => [c.parentId, c._count]))
const rootItemMap = Object.fromEntries(rootItemCounts.map((c) => [c.pageId, c._count]))
]);
const rootChildMap = Object.fromEntries(rootChildCounts.map((c) => [c.parentId, c._count]));
const rootItemMap = Object.fromEntries(rootItemCounts.map((c) => [c.pageId, c._count]));
rootPages = rootPagesRaw.map((p) => ({
id: p.id,
caption: p.caption,
@@ -262,34 +257,34 @@ export default async function CatalogPagesPage({
pageLayout: p.pageLayout,
childCount: rootChildMap[p.id] ?? 0,
itemCount: rootItemMap[p.id] ?? 0,
}))
}));
}
// ── Table view data (skip if tree) ────────────────────────────
let rows: {
id: number
caption: string
parentId: number
parentCaption: string
pageLayout: string
enabled: string
visible: string
minRank: number
orderNum: number
itemCount: number
childCount: number
}[] = []
let pagination = { total: 0, page: 1, perPage, lastPage: 0 }
id: number;
caption: string;
parentId: number;
parentCaption: string;
pageLayout: string;
enabled: string;
visible: string;
minRank: number;
orderNum: number;
itemCount: number;
childCount: number;
}[] = [];
let pagination = { total: 0, page: 1, perPage, lastPage: 0 };
if (viewMode === 'table') {
const parentFilter = sp.get('parent')
const parentId = parentFilter !== null ? parseInt(parentFilter, 10) : undefined
if (viewMode === "table") {
const parentFilter = sp.get("parent");
const parentId = parentFilter !== null ? parseInt(parentFilter, 10) : undefined;
const where: Record<string, unknown> = {}
const hasParent = parentId !== undefined && !Number.isNaN(parentId)
const where: Record<string, unknown> = {};
const hasParent = parentId !== undefined && !Number.isNaN(parentId);
if (search) {
const searchPattern = `%${search}%`
const parentClause = hasParent ? Prisma.sql`AND cp.parentId = ${parentId}` : Prisma.empty
const searchPattern = `%${search}%`;
const parentClause = hasParent ? Prisma.sql`AND cp.parentId = ${parentId}` : Prisma.empty;
const matchedIds = await prisma.$queryRaw<{ id: number }[]>(Prisma.sql`
SELECT DISTINCT cp.id FROM catalog_pages cp
@@ -301,13 +296,13 @@ export default async function CatalogPagesPage({
OR ib.public_name LIKE ${searchPattern}
OR ib.item_name LIKE ${searchPattern})
${parentClause}
`)
where.id = { in: matchedIds.map((r) => r.id) }
`);
where.id = { in: matchedIds.map((r) => r.id) };
} else if (hasParent) {
where.parentId = parentId
where.parentId = parentId;
}
const orderBy = sort ? { [sort]: order } : { orderNum: 'asc' as const }
const orderBy = sort ? { [sort]: order } : { orderNum: "asc" as const };
const [pages, total] = await Promise.all([
prisma.catalogPages.findMany({
@@ -317,24 +312,24 @@ export default async function CatalogPagesPage({
take: perPage,
}),
prisma.catalogPages.count({ where }),
])
]);
pagination = calcPagination(total, page, perPage)
pagination = calcPagination(total, page, perPage);
// Count children and items per page, and resolve parent names in parallel
const pageIds = pages.map((p) => p.id)
const parentIds = [...new Set(pages.map((p) => p.parentId).filter((id) => id > 0))]
const pageIds = pages.map((p) => p.id);
const parentIds = [...new Set(pages.map((p) => p.parentId).filter((id) => id > 0))];
const [childCounts, itemCounts, parentPages] = await Promise.all([
pageIds.length > 0
? prisma.catalogPages.groupBy({
by: ['parentId'],
by: ["parentId"],
where: { parentId: { in: pageIds } },
_count: true,
})
: [],
pageIds.length > 0
? prisma.catalogItems.groupBy({
by: ['pageId'],
by: ["pageId"],
where: { pageId: { in: pageIds } },
_count: true,
})
@@ -345,16 +340,16 @@ export default async function CatalogPagesPage({
select: { id: true, caption: true },
})
: [],
])
const childCountMap = Object.fromEntries(childCounts.map((c) => [c.parentId, c._count]))
const itemCountMap = Object.fromEntries(itemCounts.map((c) => [c.pageId, c._count]))
const parentNameMap = Object.fromEntries(parentPages.map((p) => [p.id, p.caption]))
]);
const childCountMap = Object.fromEntries(childCounts.map((c) => [c.parentId, c._count]));
const itemCountMap = Object.fromEntries(itemCounts.map((c) => [c.pageId, c._count]));
const parentNameMap = Object.fromEntries(parentPages.map((p) => [p.id, p.caption]));
rows = pages.map((p) => ({
id: p.id,
caption: p.caption,
parentId: p.parentId,
parentCaption: p.parentId === -1 ? 'Root' : (parentNameMap[p.parentId] ?? `#${p.parentId}`),
parentCaption: p.parentId === -1 ? "Root" : (parentNameMap[p.parentId] ?? `#${p.parentId}`),
pageLayout: p.pageLayout,
enabled: p.enabled,
visible: p.visible,
@@ -362,7 +357,7 @@ export default async function CatalogPagesPage({
orderNum: p.orderNum,
itemCount: itemCountMap[p.id] ?? 0,
childCount: childCountMap[p.id] ?? 0,
}))
}));
}
return (
@@ -381,11 +376,11 @@ export default async function CatalogPagesPage({
</div>
</div>
{viewMode === 'tree' ? (
{viewMode === "tree" ? (
<CatalogTree rootPages={rootPages} catalogType="normal" />
) : (
<CatalogTable data={{ rows, ...pagination }} canEdit={canEdit} />
)}
</div>
)
);
}