refactor(cms): deduplicate shared admin components and fix studio batch completion
CI / check (push) Failing after 1m35s
CI / deploy (push) Skipped
CI / e2e (push) Skipped

- fix(studio): stop markBatchDone infinite recursion so batches complete
- refactor(api): merge api-response into api and drop the duplicate module
- refactor(media): extract shared media loader and URL validator
- refactor(ui): extract shared LoadingSpinner for site and admin groups
- refactor(dates): consolidate raw date formatting into formatDate util
- refactor(logs): share a single generic log-list loader across tables
- refactor(theme): merge both ColorField components and reuse contrast helpers
- refactor(import): extract shared ImportErrorBanner and SearchInput
- chore(): remove dead theme-editor-tabs after inlining tab components
This commit is contained in:
openhands committed 2026-09-05 20:58:42 +02:00
1 parent b12e405b34
commit 8c12fc6c60
93 files changed
+1447 -1005

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
import { sql } from "drizzle-orm";
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
@@ -1,8 +1,8 @@
import { promises as fs } from "node:fs";
import { hostname } from "node:os";
import path from "node:path";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permission-slugs";
import {
catalogStateRoot,
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { publicCatalogConfig } from "@/lib/services/catalog-git-config";
import {
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import {
catalogueAssetDirectories,
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import {
catalogueAssetDirectories,
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { loadCatalogItemsData } from "@/lib/services/catalog-items-loader";
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { getHabboGamedataHotel } from "@/lib/services/habbo-gamedata-hotel";
import { batchLookupByClassnames } from "@/lib/services/habbofurni";
+1 -1
View File
@@ -1,6 +1,6 @@
import { asc, count, eq, inArray, like, or } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { CatalogItemsBc, CatalogPages, CatalogPagesBc, db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import {
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { setCsrfCookie } from "@/lib/foundation/security";
export const GET = withAdmin({ requireCsrf: false }, async () => {
+1 -1
View File
@@ -1,6 +1,6 @@
import { asc, eq, like, or } from "drizzle-orm";
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { db, ItemsBase } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
@@ -1,7 +1,7 @@
import { promises as fs } from "node:fs";
import path from "node:path";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { getGamedataRoot } from "@/lib/services/furni-asset-dirs";
+1 -1
View File
@@ -1,7 +1,7 @@
import { promises as fs } from "node:fs";
import path from "node:path";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { getGamedataRoot } from "@/lib/services/furni-asset-dirs";
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { extractFurniIconPng } from "@/lib/services/clone-icon";
import { getSource } from "@/lib/services/clone-sources";
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { importClothingSet } from "@/lib/services/clothing-set-import";
@@ -1,5 +1,5 @@
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import {
getClothingSetList,
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { addSize32AllNitros } from "@/lib/services/repair-nitros";
@@ -1,8 +1,8 @@
import { existsSync, promises as fs } from "node:fs";
import path from "node:path";
import { eq } from "drizzle-orm";
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { db, ItemsBase } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import { getFurniAssetDirs } from "@/lib/services/furni-asset-dirs";
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { getSource } from "@/lib/services/clone-sources";
@@ -2,8 +2,8 @@ import { existsSync, promises as fs } from "node:fs";
import path from "node:path";
import { eq, sql } from "drizzle-orm";
import type { NextRequest } from "next/server";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db, ItemsBase } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
@@ -1,7 +1,7 @@
import { existsSync } from "node:fs";
import { asc, inArray, sql } from "drizzle-orm";
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { db, ItemsBase } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
import {
+1 -1
View File
@@ -1,8 +1,8 @@
import { existsSync, promises as fs } from "node:fs";
import path from "node:path";
import { eq, sql } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db, ItemsBase } from "@/lib/db";
import { normalizeClassname } from "@/lib/furni/classname";
import {
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { uploadSingleFurni } from "@/lib/services/upload-import";
@@ -1,5 +1,5 @@
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { verifyAndFixInteractionModesCount } from "@/lib/services/furni-import";
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import { runSseBatch } from "@/lib/services/import/core/sse-batch";
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { PERMS } from "@/lib/permissions";
import { logAudit } from "@/lib/services/audit";
import {
@@ -1,8 +1,8 @@
import { and, eq } from "drizzle-orm";
import { revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { AclModelRole, db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
+1 -1
View File
@@ -2,8 +2,8 @@ import { and, eq } from "drizzle-orm";
import type { ResultSetHeader } from "mysql2";
import { revalidateTag } from "next/cache";
import { NextResponse } from "next/server";
import { apiError } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError } from "@/lib/api-response";
import { AclModelPermission, AclModelRole, AclRole, db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
@@ -1,6 +1,6 @@
import { sql } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
+1 -1
View File
@@ -1,6 +1,6 @@
import { sql } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
+1 -1
View File
@@ -1,6 +1,6 @@
import { sql } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
+1 -1
View File
@@ -1,7 +1,7 @@
import { eq, like, or } from "drizzle-orm";
import { NextResponse } from "next/server";
import { apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiOk } from "@/lib/api-response";
import {
db,
Guilds,
+1 -1
View File
@@ -1,7 +1,7 @@
import { promises as fs } from "node:fs";
import { desc, eq } from "drizzle-orm";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { db, Soundtracks } from "@/lib/db";
import { logger } from "@/lib/logger";
import { PERMS } from "@/lib/permissions";
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { validateClassnames } from "@/lib/furni/studio-inspection";
import { PERMS } from "@/lib/permission-slugs";
import { stageFurnitureAttachment } from "@/lib/services/furni-attachment";
@@ -1,7 +1,7 @@
import { after } from "next/server";
import { z } from "zod";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { validateClassnames } from "@/lib/furni/studio-inspection";
import { PERMS } from "@/lib/permission-slugs";
import { redis } from "@/lib/redis";
+1 -1
View File
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { validateClassnames } from "@/lib/furni/studio-inspection";
import { PERMS } from "@/lib/permission-slugs";
import { inspectFurniture } from "@/lib/services/furniture-inspection";
@@ -1,8 +1,8 @@
import { promises as fs } from "node:fs";
import path from "node:path";
import sharp from "sharp";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import {
inspectNitroScales,
object,
@@ -1,8 +1,8 @@
import { createHash, randomUUID } from "node:crypto";
import { promises as fs } from "node:fs";
import path from "node:path";
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import { generateScale32 } from "@/lib/furni/nitro-scale32";
import { validateClassnames } from "@/lib/furni/studio-inspection";
import { PERMS } from "@/lib/permission-slugs";
@@ -1,5 +1,5 @@
import { apiError, apiOk } from "@/lib/api";
import { withAdmin } from "@/lib/api-handler";
import { apiError, apiOk } from "@/lib/api-response";
import type {
SourceAssetCheck,
SourceAssetItem,