This commit is contained in:
henrygd
2026-04-19 19:12:04 -04:00
parent 40da2b4358
commit ea19ef6334
13 changed files with 676 additions and 242 deletions

View File

@@ -35,6 +35,16 @@ export function LazySystemdTable({ systemId }: { systemId: string }) {
)
}
const NetworkProbesTableNew = lazy(() => import("@/components/network-probes-table/network-probes-table"))
export function LazyNetworkProbesTableNew({ systemId }: { systemId: string }) {
const { isIntersecting, ref } = useIntersectionObserver()
return (
<div ref={ref} className={cn(isIntersecting && "contents")}>
{isIntersecting && <NetworkProbesTableNew systemId={systemId} />}
</div>
)
}
const NetworkProbesTable = lazy(() => import("@/components/routes/system/network-probes"))
export function LazyNetworkProbesTable({

View File

@@ -49,10 +49,12 @@ export default function NetworkProbes({
const { t } = useLingui()
const fetchProbes = useCallback(() => {
pb.send<NetworkProbeRecord[]>("/api/beszel/network-probes", {
query: { system: systemId },
})
.then(setProbes)
pb.collection<NetworkProbeRecord>("network_probes")
.getList(0, 2000, {
fields: "id,name,target,protocol,port,interval,enabled,updated",
filter: systemId ? pb.filter("system={:system}", { system: systemId }) : undefined,
})
.then((res) => setProbes(res.items))
.catch(() => setProbes([]))
}, [systemId])
@@ -143,16 +145,13 @@ export default function NetworkProbes({
const deleteProbe = useCallback(
async (id: string) => {
try {
await pb.send("/api/beszel/network-probes", {
method: "DELETE",
query: { id },
})
fetchProbes()
} catch (err: any) {
toast({ variant: "destructive", title: t`Error`, description: err?.message })
await pb.collection("network_probes").delete(id)
// fetchProbes()
} catch (err: unknown) {
toast({ variant: "destructive", title: t`Error`, description: (err as Error)?.message })
}
},
[fetchProbes, toast, t]
[systemId, t]
)
const dataPoints: DataPoint<NetworkProbeStatsRecord>[] = useMemo(() => {

View File

@@ -1,156 +0,0 @@
import { useState } from "react"
import { Trans, useLingui } from "@lingui/react/macro"
import { pb } from "@/lib/api"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { PlusIcon } from "lucide-react"
import { useToast } from "@/components/ui/use-toast"
export function AddProbeDialog({ systemId, onCreated }: { systemId: string; onCreated: () => void }) {
const [open, setOpen] = useState(false)
const [protocol, setProtocol] = useState<string>("icmp")
const [target, setTarget] = useState("")
const [port, setPort] = useState("")
const [probeInterval, setProbeInterval] = useState("10")
const [name, setName] = useState("")
const [loading, setLoading] = useState(false)
const { toast } = useToast()
const { t } = useLingui()
const resetForm = () => {
setProtocol("icmp")
setTarget("")
setPort("")
setProbeInterval("10")
setName("")
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setLoading(true)
try {
await pb.send("/api/beszel/network-probes", {
method: "POST",
body: {
system: systemId,
name,
target,
protocol,
port: protocol === "tcp" ? Number(port) : 0,
interval: Number(probeInterval),
},
})
resetForm()
setOpen(false)
onCreated()
} catch (err: unknown) {
toast({ variant: "destructive", title: t`Error`, description: (err as Error)?.message })
} finally {
setLoading(false)
}
}
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button variant="outline" size="sm">
<PlusIcon className="size-4 me-1" />
<Trans>Add Probe</Trans>
</Button>
</DialogTrigger>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle>
<Trans>Add Network Probe</Trans>
</DialogTitle>
<DialogDescription>
<Trans>Configure ICMP, TCP, or HTTP latency monitoring from this agent.</Trans>
</DialogDescription>
</DialogHeader>
<form onSubmit={handleSubmit} className="grid gap-4">
<div className="grid gap-2">
<Label>
<Trans>Target</Trans>
</Label>
<Input
value={target}
onChange={(e) => setTarget(e.target.value)}
placeholder={protocol === "http" ? "https://example.com" : "1.1.1.1"}
required
/>
</div>
<div className="grid gap-2">
<Label>
<Trans>Protocol</Trans>
</Label>
<Select value={protocol} onValueChange={setProtocol}>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="icmp">ICMP</SelectItem>
<SelectItem value="tcp">TCP</SelectItem>
<SelectItem value="http">HTTP</SelectItem>
</SelectContent>
</Select>
</div>
{protocol === "tcp" && (
<div className="grid gap-2">
<Label>
<Trans>Port</Trans>
</Label>
<Input
type="number"
value={port}
onChange={(e) => setPort(e.target.value)}
placeholder="443"
min={1}
max={65535}
required
/>
</div>
)}
<div className="grid gap-2">
<Label>
<Trans>Interval (seconds)</Trans>
</Label>
<Input
type="number"
value={probeInterval}
onChange={(e) => setProbeInterval(e.target.value)}
min={1}
max={3600}
required
/>
</div>
<div className="grid gap-2">
<Label>
<Trans>Name (optional)</Trans>
</Label>
<Input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder={target || t`e.g. Cloudflare DNS`}
/>
</div>
<DialogFooter>
<Button type="submit" disabled={loading}>
{loading ? <Trans>Creating...</Trans> : <Trans>Create</Trans>}
</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
)
}