fix: resolve critical bugs and improve admin panel reliability
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m0s

- Fix missing await in pets API route causing empty responses
- Fix updateSetting to use upsert pattern instead of update-only
- Create missing /api/admin/sounds/upload route (upload was broken)
- Wire bulk delete actions in catalog table
- Replace native confirm() with useConfirmDialog() across rooms and clone pages
- Add error logging to silent catch blocks in radio actions and audit route
- Add graceful degradation to devops health endpoint
- Add cache eviction to clone icon route to prevent memory leak
- Internationalize hardcoded Italian strings to English
- Remove placeholder created_at fields from prefix API responses
- Remove dead code and fix type errors in translations and import pages
- Standardize PERMS import path in analytics export route
This commit is contained in:
openhands committed 2026-08-06 18:32:55 +02:00
1 parent 6f53ca514d
commit 1b817fe434
19 files changed
+255 -89

No files matched your search

+17 -16
View File
@@ -4,6 +4,7 @@ import { eq } from "drizzle-orm";
import { revalidatePath } from "next/cache";
import { requirePermission } from "@/lib/admin/guard";
import { db, RadioBanners, RadioRanks, WebsiteSetting } from "@/lib/db";
import { logger } from "@/lib/logger";
import { PERMS } from "@/lib/permissions";
import { siteSettings } from "@/lib/services/site-settings";
@@ -50,8 +51,8 @@ export async function saveRadioSetting(formData: FormData): Promise<void> {
.values({ key, value, comment: comment || null })
.onDuplicateKeyUpdate({ set: { value } });
siteSettings.reload();
} catch {
// DB unavailable — fail soft so the action does not throw.
} catch (err) {
logger.error("Failed to save radio setting", { err, key });
}
revalidatePath("/admin/radio/settings");
}
@@ -81,8 +82,8 @@ export async function saveRadioSettings(formData: FormData): Promise<void> {
}),
);
siteSettings.reload();
} catch {
// Fail soft.
} catch (err) {
logger.error("Failed to bulk-save radio settings", { err, keys });
}
revalidatePath("/admin/radio/settings");
}
@@ -114,8 +115,8 @@ export async function createRadioBanner(formData: FormData): Promise<void> {
createdAt: now,
updatedAt: now,
});
} catch {
// Fail soft.
} catch (err) {
logger.error("Failed to create radio banner", { err, imagePath });
}
revalidatePath("/admin/radio/banners");
}
@@ -147,8 +148,8 @@ export async function updateRadioBanner(formData: FormData): Promise<void> {
updatedAt: new Date(),
})
.where(eq(RadioBanners.id, id));
} catch {
// Row may be gone; ignore.
} catch (err) {
logger.error("Failed to update radio banner", { err, id: String(id) });
}
revalidatePath("/admin/radio/banners");
}
@@ -159,8 +160,8 @@ export async function deleteRadioBanner(formData: FormData): Promise<void> {
if (id === null) return;
try {
await db.delete(RadioBanners).where(eq(RadioBanners.id, id));
} catch {
// Already deleted; ignore.
} catch (err) {
logger.error("Failed to delete radio banner", { err, id: String(id) });
}
revalidatePath("/admin/radio/banners");
}
@@ -186,8 +187,8 @@ export async function createRadioRank(formData: FormData): Promise<void> {
createdAt: now,
updatedAt: now,
});
} catch {
// Fail soft.
} catch (err) {
logger.error("Failed to create radio rank", { err, name });
}
revalidatePath("/admin/radio/ranks");
}
@@ -214,8 +215,8 @@ export async function updateRadioRank(formData: FormData): Promise<void> {
updatedAt: new Date(),
})
.where(eq(RadioRanks.id, id));
} catch {
// Row may be gone; ignore.
} catch (err) {
logger.error("Failed to update radio rank", { err, id: String(id) });
}
revalidatePath("/admin/radio/ranks");
}
@@ -226,8 +227,8 @@ export async function deleteRadioRank(formData: FormData): Promise<void> {
if (id === null) return;
try {
await db.delete(RadioRanks).where(eq(RadioRanks.id, id));
} catch {
// Already deleted; ignore.
} catch (err) {
logger.error("Failed to delete radio rank", { err, id: String(id) });
}
revalidatePath("/admin/radio/ranks");
}
+3 -3
View File
@@ -77,9 +77,9 @@ export async function updateSetting(formData: FormData): Promise<void> {
);
if (!key) return;
await db
.update(WebsiteSetting)
.set({ value })
.where(eq(WebsiteSetting.key, key));
.insert(WebsiteSetting)
.values({ key, value })
.onDuplicateKeyUpdate({ set: { value } });
await siteSettings.reload();
bustGamedataCachesIfNeeded(key);
revalidatePath("/admin/settings");