diff --git a/src/components/wrappers/dashboard/admin/notifications/logs/notification-log-modal.tsx b/src/components/wrappers/dashboard/admin/notifications/logs/notification-log-modal.tsx index 9888063d..a1395ca3 100644 --- a/src/components/wrappers/dashboard/admin/notifications/logs/notification-log-modal.tsx +++ b/src/components/wrappers/dashboard/admin/notifications/logs/notification-log-modal.tsx @@ -1,62 +1,235 @@ -"use client" -import {Eye} from "lucide-react"; - -import {useState} from "react"; +"use client"; import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger + Eye, + Braces, + Database, + AlertCircle, + Hash, + Server, + Sparkles, + ExternalLink, +} from "lucide-react"; +import { useState } from "react"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, } from "@/components/ui/dialog"; -import {Button} from "@/components/ui/button"; -import {Separator} from "@/components/ui/separator"; -import {NotificationLogWithRelations} from "@/db/services/notification-log"; +import { Button } from "@/components/ui/button"; +import { NotificationLogWithRelations } from "@/db/services/notification-log"; type NotificationLogModalProps = { - notificationLog: NotificationLogWithRelations; -} + notificationLog: NotificationLogWithRelations; +}; -export const NotificationLogModal = ({notificationLog}: NotificationLogModalProps) => { - const [open, setOpen] = useState(false); +const getTroubleshootingForError = (errorMsg?: any) => { + if (!errorMsg || String(errorMsg).toLowerCase() === "null") return null; - return ( - - - - - - - Notification details - - Details of the notification sent - - + const msg = String(errorMsg).toLowerCase(); -
-
- Title:{" "} - {notificationLog.content.title} -
-
- Message:{" "} - {notificationLog.content.message} -
+ if (msg.includes("database connection") || msg.includes("agent")) { + return { + title: "Agent Connection Issue", + resolution: + "It appears the agent cannot reach the database. Please ensure that your agent is actively running, your PostgreSQL credentials are correct, and port 5432 is open on your firewall.", + docLink: + "https://portabase.io/docs/agent/troubleshooting/agent-connection", + }; + } + + if (msg.includes("timeout")) { + return { + title: "Timeout", + resolution: + "The agent is taking too long to respond. This could be due to high server load, network issues, or a large database.", + docLink: "https://portabase.io/docs/agent/troubleshooting/timeout", + }; + } + + return { + title: "Unexpected Execution Error", + resolution: + "An unexpected error occurred during execution. Please review the raw system logs or contact support if the issue persists.", + docLink: "https://portabase.io/docs/agent/support", + }; +}; + +const getIconForKey = (key: string, value: any) => { + const isActualError = + key.toLowerCase().includes("error") && + value !== null && + String(value).toLowerCase() !== "null"; + + if (key.toLowerCase().includes("id")) + return ; + if (key.toLowerCase().includes("host")) + return ; + if (isActualError) + return ; + return ; +}; + +export const NotificationLogModal = ({ + notificationLog, +}: NotificationLogModalProps) => { + const [open, setOpen] = useState(false); + + const payloadError = notificationLog.payload?.error; + const troubleshooting = getTroubleshootingForError(payloadError); + + return ( + + + + + + + Notification Details + Execution logs and payload data + + +
+
+
+
+ +
+ + Event Trigger + +
+
+
+ + Title + + {notificationLog.content.title} +
+
+ + Message + + + {notificationLog.content.message} + +
+
+
+
+ +
+ + {notificationLog.payload && + Object.keys(notificationLog.payload).length > 0 && ( +
+
+ +
+
+
+
+ + JSON Payload + +
+
- {notificationLog.payload && ( - <> - -
- {JSON.stringify(notificationLog.payload, null, 2)} -
- - )} - - -
- ) -} \ No newline at end of file +
+ {Object.entries(notificationLog.payload).map( + ([key, value], index, arr) => { + const isActualError = + key === "error" && + value !== null && + String(value).toLowerCase() !== "null"; + + return ( +
+
+ {getIconForKey(key, value)} + {key} +
+
+ {isActualError ? ( + + {String(value)} + + ) : ( + + {String(value)} + + )} +
+
+ ); + }, + )} +
+ + {troubleshooting && ( +
+ )} +
+ )} + + {troubleshooting && ( + <> +
+ +
+
+ +
+
+
+ +
+ + Suggested Resolution + +
+
+ +
+

+ {troubleshooting.title} +

+

+ {troubleshooting.resolution} +

+ +
+
+ + )} +
+ +
+ ); +};