diff --git a/AppImage/components/system-logs.tsx b/AppImage/components/system-logs.tsx index 980a066..4de227c 100644 --- a/AppImage/components/system-logs.tsx +++ b/AppImage/components/system-logs.tsx @@ -106,6 +106,9 @@ export function SystemLogs() { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false) + const [dateFilter, setDateFilter] = useState("now") + const [customDays, setCustomDays] = useState("1") + const getApiUrl = (endpoint: string) => { if (typeof window !== "undefined") { return `${window.location.protocol}//${window.location.hostname}:8008${endpoint}` @@ -179,7 +182,19 @@ export function SystemLogs() { const handleDownloadLogs = async (type = "system") => { try { - const hours = 48 + let hours = 48 + + if (filteredLogs.length > 0) { + const lastLog = filteredLogs[filteredLogs.length - 1] + const lastLogTime = new Date(lastLog.timestamp) + const now = new Date() + const diffMs = now.getTime() - lastLogTime.getTime() + const diffHours = Math.floor(diffMs / (1000 * 60 * 60)) + + // Download 48 hours from the last visible log + hours = 48 + } + let url = getApiUrl(`/api/logs/download?type=${type}&hours=${hours}`) // Apply filters if any are active @@ -190,6 +205,11 @@ export function SystemLogs() { url += `&service=${serviceFilter}` } + if (dateFilter !== "now") { + const daysAgo = dateFilter === "custom" ? Number.parseInt(customDays) : Number.parseInt(dateFilter) + url += `&since_days=${daysAgo}` + } + const response = await fetch(url) if (response.ok) { const blob = await response.blob() @@ -208,23 +228,31 @@ export function SystemLogs() { } const handleDownloadNotificationLog = async (notification: Notification) => { - // Added try { - // Download the complete log for this notification - const response = await fetch(getApiUrl(`/api/notifications/download?timestamp=${notification.timestamp}`)) - if (response.ok) { - const blob = await response.blob() - const url = window.URL.createObjectURL(blob) - const a = document.createElement("a") - a.href = url - a.download = `notification_${notification.timestamp.replace(/[:\s]/g, "_")}.log` - document.body.appendChild(a) - a.click() - window.URL.revokeObjectURL(url) - document.body.removeChild(a) - } + const blob = new Blob( + [ + `Notification Details\n`, + `==================\n\n`, + `Timestamp: ${notification.timestamp}\n`, + `Type: ${notification.type}\n`, + `Service: ${notification.service}\n`, + `Source: ${notification.source}\n\n`, + `Complete Message:\n`, + `${notification.message}\n`, + ], + { type: "text/plain" }, + ) + + const url = window.URL.createObjectURL(blob) + const a = document.createElement("a") + a.href = url + a.download = `notification_${notification.timestamp.replace(/[:\s]/g, "_")}.txt` + document.body.appendChild(a) + a.click() + window.URL.revokeObjectURL(url) + document.body.removeChild(a) } catch (err) { - console.error("[v0] Error downloading notification log:", err) + console.error("[v0] Error downloading notification:", err) } } @@ -294,6 +322,21 @@ export function SystemLogs() { } } + const getNotificationTypeColor = (type: string) => { + switch (type.toLowerCase()) { + case "error": + return "bg-red-500/10 text-red-500 border-red-500/20" + case "warning": + return "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" + case "info": + return "bg-blue-500/10 text-blue-500 border-blue-500/20" + case "success": + return "bg-green-500/10 text-green-500 border-green-500/20" + default: + return "bg-gray-500/10 text-gray-500 border-gray-500/20" + } + } + const logCounts = { total: logs.length, error: logs.filter((log) => ["error", "critical", "emergency", "alert"].includes(log.level)).length, @@ -552,6 +595,32 @@ export function SystemLogs() { + + + {dateFilter === "custom" && ( + setCustomDays(e.target.value)} + className="w-full sm:w-[120px] bg-background border-border" + min="1" + /> + )} +