mirror of
https://github.com/henrygd/beszel.git
synced 2026-04-26 06:21:50 +02:00
updates
This commit is contained in:
@@ -11,7 +11,13 @@ import { RootDiskCharts, ExtraFsCharts } from "./system/charts/disk-charts"
|
||||
import { BandwidthChart, ContainerNetworkChart } from "./system/charts/network-charts"
|
||||
import { TemperatureChart, BatteryChart } from "./system/charts/sensor-charts"
|
||||
import { GpuPowerChart, GpuDetailCharts } from "./system/charts/gpu-charts"
|
||||
import { LazyContainersTable, LazyNetworkProbesTable, LazySmartTable, LazySystemdTable } from "./system/lazy-tables"
|
||||
import {
|
||||
LazyContainersTable,
|
||||
LazyNetworkProbesTable,
|
||||
LazySmartTable,
|
||||
LazySystemdTable,
|
||||
LazyNetworkProbesTableNew,
|
||||
} from "./system/lazy-tables"
|
||||
import { LoadAverageChart } from "./system/charts/load-average-chart"
|
||||
import { ContainerIcon, CpuIcon, HardDriveIcon, TerminalSquareIcon } from "lucide-react"
|
||||
import { GpuIcon } from "../ui/icons"
|
||||
@@ -147,7 +153,9 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
|
||||
{hasSystemd && <LazySystemdTable systemId={system.id} />}
|
||||
|
||||
<LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} />
|
||||
<LazyNetworkProbesTableNew systemId={system.id} />
|
||||
|
||||
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -195,7 +203,8 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
<SwapChart chartData={chartData} grid={grid} dataEmpty={dataEmpty} systemStats={systemStats} />
|
||||
{pageBottomExtraMargin > 0 && <div style={{ marginBottom: pageBottomExtraMargin }}></div>}
|
||||
</div>
|
||||
<LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} />
|
||||
<LazyNetworkProbesTableNew systemId={system.id} />
|
||||
{/* <LazyNetworkProbesTable system={system} chartData={chartData} grid={grid} probeStats={probeStats} /> */}
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="disk" forceMount className={activeTab === "disk" ? "contents" : "hidden"}>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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(() => {
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user