-
Notifications
You must be signed in to change notification settings - Fork 1
feat: add enhanced db settings UI info #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||||||||||||
| import DashChart from "@/components/DashChart"; | ||||||||||||||||||
| import DashRecentTickets from "@/components/DashRecentTickets"; | ||||||||||||||||||
| import TicketPieChart from "@/components/TicketPieChart"; | ||||||||||||||||||
| import prisma from "@/prisma/db"; | ||||||||||||||||||
| import prisma, { safeDbOperation } from "@/prisma/db"; | ||||||||||||||||||
|
|
||||||||||||||||||
| const STATUS_COLORS = { | ||||||||||||||||||
| OPEN: "#ef4444", | ||||||||||||||||||
|
|
@@ -16,18 +16,113 @@ const PRIORITY_COLORS = { | |||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| async function Dashboard() { | ||||||||||||||||||
| const tickets = await prisma.ticket.findMany({ | ||||||||||||||||||
| where: { NOT: [{ status: "DONE" }] }, | ||||||||||||||||||
| orderBy: { updated_at: "desc" }, | ||||||||||||||||||
| skip: 0, | ||||||||||||||||||
| take: 5, | ||||||||||||||||||
| include: { user: true }, | ||||||||||||||||||
| }); | ||||||||||||||||||
| // Safely fetch tickets with fallback | ||||||||||||||||||
| const ticketsResult = await safeDbOperation( | ||||||||||||||||||
| () => | ||||||||||||||||||
| prisma.ticket.findMany({ | ||||||||||||||||||
| where: { NOT: [{ status: "DONE" }] }, | ||||||||||||||||||
| orderBy: { updated_at: "desc" }, | ||||||||||||||||||
| skip: 0, | ||||||||||||||||||
| take: 5, | ||||||||||||||||||
| include: { user: true }, | ||||||||||||||||||
| }), | ||||||||||||||||||
| [] | ||||||||||||||||||
| ); | ||||||||||||||||||
|
|
||||||||||||||||||
| const groupTickets = await prisma.ticket.groupBy({ | ||||||||||||||||||
| by: ["status"], | ||||||||||||||||||
| _count: { id: true }, | ||||||||||||||||||
| }); | ||||||||||||||||||
| // Safely fetch group tickets for chart data | ||||||||||||||||||
| const groupTicketsResult = await safeDbOperation( | ||||||||||||||||||
| () => | ||||||||||||||||||
| prisma.ticket.groupBy({ | ||||||||||||||||||
| by: ["status"], | ||||||||||||||||||
| _count: { id: true }, | ||||||||||||||||||
| }), | ||||||||||||||||||
| [] | ||||||||||||||||||
| ); | ||||||||||||||||||
|
|
||||||||||||||||||
| // Safely fetch status distribution | ||||||||||||||||||
| const statusResult = await safeDbOperation( | ||||||||||||||||||
| () => | ||||||||||||||||||
| prisma.ticket.groupBy({ | ||||||||||||||||||
| by: ["status"], | ||||||||||||||||||
| _count: true, | ||||||||||||||||||
| }), | ||||||||||||||||||
| [] | ||||||||||||||||||
| ); | ||||||||||||||||||
|
|
||||||||||||||||||
| // Safely fetch priority distribution | ||||||||||||||||||
| const priorityResult = await safeDbOperation( | ||||||||||||||||||
| () => | ||||||||||||||||||
| prisma.ticket.groupBy({ | ||||||||||||||||||
| by: ["priority"], | ||||||||||||||||||
| _count: true, | ||||||||||||||||||
| }), | ||||||||||||||||||
| [] | ||||||||||||||||||
| ); | ||||||||||||||||||
|
|
||||||||||||||||||
| // Check if any database operation failed | ||||||||||||||||||
| const dbError = | ||||||||||||||||||
| ticketsResult.error || | ||||||||||||||||||
| groupTicketsResult.error || | ||||||||||||||||||
| statusResult.error || | ||||||||||||||||||
| priorityResult.error; | ||||||||||||||||||
|
|
||||||||||||||||||
| if (dbError) { | ||||||||||||||||||
| if (typeof window === "undefined") { | ||||||||||||||||||
| // Log detailed error server-side | ||||||||||||||||||
| // eslint-disable-next-line no-console | ||||||||||||||||||
| console.error("Database error:", dbError); | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+70
to
+74
|
||||||||||||||||||
| if (typeof window === "undefined") { | |
| // Log detailed error server-side | |
| // eslint-disable-next-line no-console | |
| console.error("Database error:", dbError); | |
| } | |
| // Log detailed error server-side | |
| // eslint-disable-next-line no-console | |
| console.error("Database error:", dbError); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,6 +8,87 @@ declare const globalThis: { | |||||||||||||||||
| prismaGlobal: ReturnType<typeof prismaClientSingleton>; | ||||||||||||||||||
| } & typeof global; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Cache database availability check to avoid repeated connection attempts | ||||||||||||||||||
| let dbAvailabilityCache: { available: boolean; lastChecked: number } | null = | ||||||||||||||||||
| null; | ||||||||||||||||||
| const DB_CHECK_CACHE_DURATION = 30000; // 30 seconds | ||||||||||||||||||
|
|
||||||||||||||||||
| // Clear the database availability cache (useful for testing or manual refresh) | ||||||||||||||||||
| export const clearDatabaseAvailabilityCache = (): void => { | ||||||||||||||||||
| dbAvailabilityCache = null; | ||||||||||||||||||
| }; | ||||||||||||||||||
|
|
||||||||||||||||||
| // Check if DATABASE_URL is available and database is reachable | ||||||||||||||||||
| export const isDatabaseAvailable = async (): Promise<boolean> => { | ||||||||||||||||||
| // First check if DATABASE_URL is set | ||||||||||||||||||
| if (!process.env.DATABASE_URL) { | ||||||||||||||||||
| return false; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| // Check cache first | ||||||||||||||||||
| const now = Date.now(); | ||||||||||||||||||
| if ( | ||||||||||||||||||
| dbAvailabilityCache && | ||||||||||||||||||
| now - dbAvailabilityCache.lastChecked < DB_CHECK_CACHE_DURATION | ||||||||||||||||||
| ) { | ||||||||||||||||||
| return dbAvailabilityCache.available; | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| try { | ||||||||||||||||||
| // Attempt to connect and perform a simple query | ||||||||||||||||||
| // Use a temporary PrismaClient instance for the availability check | ||||||||||||||||||
| const tempPrisma = new PrismaClient(); | ||||||||||||||||||
| await tempPrisma.$queryRaw`SELECT 1`; | ||||||||||||||||||
| await tempPrisma.$disconnect(); | ||||||||||||||||||
|
Comment on lines
+39
to
+42
|
||||||||||||||||||
| // Use a temporary PrismaClient instance for the availability check | |
| const tempPrisma = new PrismaClient(); | |
| await tempPrisma.$queryRaw`SELECT 1`; | |
| await tempPrisma.$disconnect(); | |
| // Use the shared PrismaClient instance for the availability check | |
| await prisma.$queryRaw`SELECT 1`; | |
| // No need to disconnect the shared PrismaClient instance here | |
| // (prisma.$disconnect() is handled on app shutdown) |
Uh oh!
There was an error while loading. Please reload this page.