mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-18 11:36:17 +00:00
Update AppImage
This commit is contained in:
@@ -9,8 +9,6 @@ import { ScrollArea } from "./ui/scroll-area"
|
|||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs"
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "./ui/dialog"
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "./ui/dialog"
|
||||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "./ui/sheet"
|
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "./ui/sheet"
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"
|
|
||||||
import { Calendar } from "./ui/calendar"
|
|
||||||
import {
|
import {
|
||||||
FileText,
|
FileText,
|
||||||
Search,
|
Search,
|
||||||
@@ -22,7 +20,7 @@ import {
|
|||||||
Database,
|
Database,
|
||||||
Activity,
|
Activity,
|
||||||
HardDrive,
|
HardDrive,
|
||||||
CalendarIcon,
|
Calendar,
|
||||||
RefreshCw,
|
RefreshCw,
|
||||||
Bell,
|
Bell,
|
||||||
Mail,
|
Mail,
|
||||||
@@ -31,8 +29,6 @@ import {
|
|||||||
CalendarDays,
|
CalendarDays,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
import { useState, useEffect } from "react"
|
import { useState, useEffect } from "react"
|
||||||
import type { DateRange } from "react-day-picker"
|
|
||||||
import { format } from "date-fns"
|
|
||||||
|
|
||||||
interface Log {
|
interface Log {
|
||||||
timestamp: string
|
timestamp: string
|
||||||
@@ -112,7 +108,6 @@ export function SystemLogs() {
|
|||||||
|
|
||||||
const [dateFilter, setDateFilter] = useState("now")
|
const [dateFilter, setDateFilter] = useState("now")
|
||||||
const [customDays, setCustomDays] = useState("1")
|
const [customDays, setCustomDays] = useState("1")
|
||||||
const [dateRange, setDateRange] = useState<DateRange | undefined>(undefined)
|
|
||||||
|
|
||||||
const getApiUrl = (endpoint: string) => {
|
const getApiUrl = (endpoint: string) => {
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
@@ -210,11 +205,7 @@ export function SystemLogs() {
|
|||||||
url += `&service=${serviceFilter}`
|
url += `&service=${serviceFilter}`
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dateFilter === "custom" && dateRange?.from && dateRange?.to) {
|
if (dateFilter !== "now") {
|
||||||
const fromDate = format(dateRange.from, "yyyy-MM-dd")
|
|
||||||
const toDate = format(dateRange.to, "yyyy-MM-dd")
|
|
||||||
url += `&from_date=${fromDate}&to_date=${toDate}`
|
|
||||||
} else if (dateFilter !== "now") {
|
|
||||||
const daysAgo = dateFilter === "custom" ? Number.parseInt(customDays) : Number.parseInt(dateFilter)
|
const daysAgo = dateFilter === "custom" ? Number.parseInt(customDays) : Number.parseInt(dateFilter)
|
||||||
url += `&since_days=${daysAgo}`
|
url += `&since_days=${daysAgo}`
|
||||||
}
|
}
|
||||||
@@ -446,12 +437,6 @@ export function SystemLogs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMinDate = () => {
|
|
||||||
const twoYearsAgo = new Date()
|
|
||||||
twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2)
|
|
||||||
return twoYearsAgo
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loading && logs.length === 0) {
|
if (loading && logs.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center h-64">
|
<div className="flex items-center justify-center h-64">
|
||||||
@@ -621,43 +606,19 @@ export function SystemLogs() {
|
|||||||
<SelectItem value="7">1 week ago</SelectItem>
|
<SelectItem value="7">1 week ago</SelectItem>
|
||||||
<SelectItem value="14">2 weeks ago</SelectItem>
|
<SelectItem value="14">2 weeks ago</SelectItem>
|
||||||
<SelectItem value="30">1 month ago</SelectItem>
|
<SelectItem value="30">1 month ago</SelectItem>
|
||||||
<SelectItem value="custom">Custom range</SelectItem>
|
<SelectItem value="custom">Custom days</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
|
|
||||||
{dateFilter === "custom" && (
|
{dateFilter === "custom" && (
|
||||||
<Popover>
|
<Input
|
||||||
<PopoverTrigger asChild>
|
type="number"
|
||||||
<Button
|
placeholder="Days ago"
|
||||||
variant="outline"
|
value={customDays}
|
||||||
className="w-full sm:w-[280px] justify-start text-left font-normal bg-background border-border"
|
onChange={(e) => setCustomDays(e.target.value)}
|
||||||
>
|
className="w-full sm:w-[120px] bg-background border-border"
|
||||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
min="1"
|
||||||
{dateRange?.from ? (
|
/>
|
||||||
dateRange.to ? (
|
|
||||||
<>
|
|
||||||
{format(dateRange.from, "LLL dd, y")} - {format(dateRange.to, "LLL dd, y")}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
format(dateRange.from, "LLL dd, y")
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<span>Pick a date range</span>
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent className="w-auto p-0" align="start">
|
|
||||||
<Calendar
|
|
||||||
initialFocus
|
|
||||||
mode="range"
|
|
||||||
defaultMonth={dateRange?.from}
|
|
||||||
selected={dateRange}
|
|
||||||
onSelect={setDateRange}
|
|
||||||
numberOfMonths={2}
|
|
||||||
disabled={(date) => date > new Date() || date < getMinDate()}
|
|
||||||
/>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Select value={levelFilter} onValueChange={setLevelFilter}>
|
<Select value={levelFilter} onValueChange={setLevelFilter}>
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import type * as React from "react"
|
|
||||||
import { ChevronLeft, ChevronRight } from "lucide-react"
|
|
||||||
import { DayPicker } from "react-day-picker"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
|
||||||
|
|
||||||
export type CalendarProps = React.ComponentProps<typeof DayPicker>
|
|
||||||
|
|
||||||
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
|
|
||||||
return (
|
|
||||||
<DayPicker
|
|
||||||
showOutsideDays={showOutsideDays}
|
|
||||||
className={cn("p-3", className)}
|
|
||||||
classNames={{
|
|
||||||
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
|
|
||||||
month: "space-y-4",
|
|
||||||
caption: "flex justify-center pt-1 relative items-center",
|
|
||||||
caption_label: "text-sm font-medium",
|
|
||||||
nav: "space-x-1 flex items-center",
|
|
||||||
nav_button: cn(
|
|
||||||
buttonVariants({ variant: "outline" }),
|
|
||||||
"h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
|
|
||||||
),
|
|
||||||
nav_button_previous: "absolute left-1",
|
|
||||||
nav_button_next: "absolute right-1",
|
|
||||||
table: "w-full border-collapse space-y-1",
|
|
||||||
head_row: "flex",
|
|
||||||
head_cell: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
|
|
||||||
row: "flex w-full mt-2",
|
|
||||||
cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
|
|
||||||
day: cn(buttonVariants({ variant: "ghost" }), "h-9 w-9 p-0 font-normal aria-selected:opacity-100"),
|
|
||||||
day_range_end: "day-range-end",
|
|
||||||
day_selected:
|
|
||||||
"bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
|
|
||||||
day_today: "bg-accent text-accent-foreground",
|
|
||||||
day_outside:
|
|
||||||
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
|
||||||
day_disabled: "text-muted-foreground opacity-50",
|
|
||||||
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
|
|
||||||
day_hidden: "invisible",
|
|
||||||
...classNames,
|
|
||||||
}}
|
|
||||||
components={{
|
|
||||||
IconLeft: ({ ...props }) => <ChevronLeft className="h-4 w-4" />,
|
|
||||||
IconRight: ({ ...props }) => <ChevronRight className="h-4 w-4" />,
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Calendar.displayName = "Calendar"
|
|
||||||
|
|
||||||
export { Calendar }
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
|
||||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
const Popover = PopoverPrimitive.Root
|
|
||||||
|
|
||||||
const PopoverTrigger = PopoverPrimitive.Trigger
|
|
||||||
|
|
||||||
const PopoverContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof PopoverPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
|
||||||
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
|
||||||
<PopoverPrimitive.Portal>
|
|
||||||
<PopoverPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
align={align}
|
|
||||||
sideOffset={sideOffset}
|
|
||||||
className={cn(
|
|
||||||
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</PopoverPrimitive.Portal>
|
|
||||||
))
|
|
||||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
|
||||||
|
|
||||||
export { Popover, PopoverTrigger, PopoverContent }
|
|
||||||
@@ -3408,14 +3408,20 @@ def api_logs_download():
|
|||||||
level = request.args.get('level', 'all')
|
level = request.args.get('level', 'all')
|
||||||
service = request.args.get('service', 'all')
|
service = request.args.get('service', 'all')
|
||||||
since_days = request.args.get('since_days', None)
|
since_days = request.args.get('since_days', None)
|
||||||
from_date = request.args.get('from_date', None)
|
|
||||||
to_date = request.args.get('to_date', None)
|
|
||||||
|
|
||||||
if from_date and to_date:
|
if since_days:
|
||||||
# Date format expected: YYYY-MM-DD
|
|
||||||
cmd = ['journalctl', '--since', from_date, '--until', f'{to_date} 23:59:59', '--no-pager']
|
|
||||||
elif since_days:
|
|
||||||
days = int(since_days)
|
days = int(since_days)
|
||||||
|
# Original code: cmd = ['journalctl', '--since', f'{days} days ago', '--until', f'{days - 1} days ago', '--no-pager']
|
||||||
|
# This logic seems incorrect if we want logs FROM since_days ago.
|
||||||
|
# Correct logic: logs from 'days' ago until 'now' (or 'days-1' ago for a specific 24h period)
|
||||||
|
# For simplicity and to keep the original intent of filtering *from* X days ago, let's use '--since'.
|
||||||
|
# If 'since_days' is 1, it means logs from yesterday until now.
|
||||||
|
# If 'since_days' is 2, it means logs from the day before yesterday until now.
|
||||||
|
# Let's assume 'since_days' means the number of *full 24-hour periods* to go back.
|
||||||
|
# So, if since_days = 1, we want logs from 24 hours ago.
|
||||||
|
# If since_days = 2, we want logs from 48 hours ago.
|
||||||
|
# The original '--until' logic was problematic. Let's simplify.
|
||||||
|
# If 'since_days' is provided, use it as the primary time filter.
|
||||||
cmd = ['journalctl', '--since', f'{days} days ago', '--no-pager']
|
cmd = ['journalctl', '--since', f'{days} days ago', '--no-pager']
|
||||||
else:
|
else:
|
||||||
cmd = ['journalctl', '--since', f'{hours} hours ago', '--no-pager']
|
cmd = ['journalctl', '--since', f'{hours} hours ago', '--no-pager']
|
||||||
|
|||||||
Reference in New Issue
Block a user