chore: formatting
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-03-05 16:26:47 +00:00
parent 7ba2659fbf
commit c6e4a9e3c9
4 changed files with 246 additions and 181 deletions

View File

@ -147,9 +147,9 @@ export class LNVpsApi {
}
async getVmTimeSeries(id: number) {
const { data } = await this.#handleResponse<ApiResponse<Array<TimeSeriesData>>>(
await this.#req(`/api/v1/vm/${id}/time-series`, "GET"),
);
const { data } = await this.#handleResponse<
ApiResponse<Array<TimeSeriesData>>
>(await this.#req(`/api/v1/vm/${id}/time-series`, "GET"));
return data;
}

View File

@ -61,7 +61,7 @@ const router = createBrowserRouter([
},
{
path: "/vm/graphs",
element: <VmGraphsPage />
element: <VmGraphsPage />,
},
{
path: "/tos",

View File

@ -32,7 +32,7 @@ export function VmBillingPage() {
useEffect(() => {
if (params["action"] === "renew" && login && state) {
renew()
renew();
}
}, [login, state, params, renew]);
@ -54,8 +54,9 @@ export function VmBillingPage() {
Expires: {expireDate.toDateString()} ({Math.floor(days)} days)
</div>
)}
{days < 0 && params["action"] !== "renew"
&& <div className="text-red-500 text-xl">Expired</div>}
{days < 0 && params["action"] !== "renew" && (
<div className="text-red-500 text-xl">Expired</div>
)}
{!payment && (
<div>
<AsyncButton onClick={renew}>Extend Now</AsyncButton>

View File

@ -2,7 +2,15 @@ import { Link, useLocation } from "react-router-dom";
import { TimeSeriesData, VmInstance } from "../api";
import useLogin from "../hooks/login";
import { useEffect, useState } from "react";
import { ResponsiveContainer, XAxis, YAxis, Tooltip, LineChart, Line, Legend } from "recharts";
import {
ResponsiveContainer,
XAxis,
YAxis,
Tooltip,
LineChart,
Line,
Legend,
} from "recharts";
export function VmGraphsPage() {
const { state } = useLocation() as { state?: VmInstance };
@ -14,7 +22,8 @@ export function VmGraphsPage() {
login?.api.getVmTimeSeries(state.id).then(setData);
}, [login]);
const maxRam = data?.reduce((acc, v) => {
const maxRam =
data?.reduce((acc, v) => {
const mb = v.memory_size / 1024 / 1024;
return acc < mb ? mb : acc;
}, 0) ?? 0;
@ -23,12 +32,15 @@ export function VmGraphsPage() {
const MB = 1024 * 1024;
function scaleLabel(v: number) {
switch (net_scale) {
case MB: return "MiB";
case KB: return "KiB";
case MB:
return "MiB";
case KB:
return "KiB";
}
return "B";
}
const net_scale = data?.reduce((acc, v) => {
const net_scale =
data?.reduce((acc, v) => {
const b = Math.max(v.net_in, v.net_out);
if (b > MB && b > acc) {
return MB;
@ -39,7 +51,8 @@ export function VmGraphsPage() {
}
}, 0) ?? 0;
const net_scale_label = scaleLabel(net_scale);
const disk_scale = data?.reduce((acc, v) => {
const disk_scale =
data?.reduce((acc, v) => {
const b = Math.max(v.disk_read, v.disk_write);
if (b > MB && b > acc) {
return MB;
@ -61,24 +74,39 @@ export function VmGraphsPage() {
DISK_READ: v.disk_read / disk_scale,
DISK_WRITE: v.disk_write / disk_scale,
}));
const toolTip = <Tooltip cursor={{ fill: "rgba(200,200,200,0.5)" }}
const toolTip = (
<Tooltip
cursor={{ fill: "rgba(200,200,200,0.5)" }}
content={({ active, payload }) => {
if (active && payload && payload.length) {
const data = payload[0].payload as TimeSeriesData;
return <div className="flex flex-col gap-2 bg-neutral-700 rounded-xl px-2 py-3">
return (
<div className="flex flex-col gap-2 bg-neutral-700 rounded-xl px-2 py-3">
<div>{data.timestamp}</div>
{payload.map((p) => <div>{p.name}: {Number(p.value).toFixed(2)}{p.unit}</div>)}
</div>;
{payload.map((p) => (
<div>
{p.name}: {Number(p.value).toFixed(2)}
{p.unit}
</div>
))}
</div>
);
}
}} />;
return <div className="flex flex-col gap-4">
}}
/>
);
return (
<div className="flex flex-col gap-4">
<Link to={"/vm"} state={state}>
&lt; Back
</Link>
<h2>CPU</h2>
<ResponsiveContainer height={200}>
<LineChart data={sortedData} margin={{ left: 0, right: 0 }} style={{ userSelect: "none" }}>
<LineChart
data={sortedData}
margin={{ left: 0, right: 0 }}
style={{ userSelect: "none" }}
>
<XAxis dataKey="timestamp" />
<YAxis unit="%" domain={[0, 100]} />
<Line type="monotone" dataKey="CPU" unit="%" dot={false} />
@ -87,7 +115,11 @@ export function VmGraphsPage() {
</ResponsiveContainer>
<h2>Memory</h2>
<ResponsiveContainer height={200}>
<LineChart data={sortedData} margin={{ left: 0, right: 0 }} style={{ userSelect: "none" }}>
<LineChart
data={sortedData}
margin={{ left: 0, right: 0 }}
style={{ userSelect: "none" }}
>
<XAxis dataKey="timestamp" />
<YAxis unit="MB" domain={[0, maxRam]} />
<Line type="monotone" dataKey="RAM" unit="MB" dot={false} />
@ -96,26 +128,58 @@ export function VmGraphsPage() {
</ResponsiveContainer>
<h2>Network</h2>
<ResponsiveContainer height={200}>
<LineChart data={sortedData} margin={{ left: 20, right: 0 }} style={{ userSelect: "none" }}>
<LineChart
data={sortedData}
margin={{ left: 20, right: 0 }}
style={{ userSelect: "none" }}
>
<XAxis dataKey="timestamp" />
<YAxis unit={`${net_scale_label}/s`} domain={[0, "auto"]} />
<Line type="monotone" dataKey="NET_IN" unit={`${net_scale_label}/s`} stroke="red" dot={false} />
<Line type="monotone" dataKey="NET_OUT" unit={`${net_scale_label}/s`} stroke="green" dot={false} />
<Line
type="monotone"
dataKey="NET_IN"
unit={`${net_scale_label}/s`}
stroke="red"
dot={false}
/>
<Line
type="monotone"
dataKey="NET_OUT"
unit={`${net_scale_label}/s`}
stroke="green"
dot={false}
/>
{toolTip}
<Legend />
</LineChart>
</ResponsiveContainer>
<h2>Disk</h2>
<ResponsiveContainer height={200}>
<LineChart data={sortedData} margin={{ left: 20, right: 0 }} style={{ userSelect: "none" }}>
<LineChart
data={sortedData}
margin={{ left: 20, right: 0 }}
style={{ userSelect: "none" }}
>
<XAxis dataKey="timestamp" />
<YAxis unit={`${disk_scale_label}/s`} domain={[0, "auto"]} />
<Line type="monotone" dataKey="DISK_READ" unit={`${disk_scale_label}/s`} stroke="red" dot={false} />
<Line type="monotone" dataKey="DISK_WRITE" unit={`${disk_scale_label}/s`} stroke="green" dot={false} />
<Line
type="monotone"
dataKey="DISK_READ"
unit={`${disk_scale_label}/s`}
stroke="red"
dot={false}
/>
<Line
type="monotone"
dataKey="DISK_WRITE"
unit={`${disk_scale_label}/s`}
stroke="green"
dot={false}
/>
{toolTip}
<Legend />
</LineChart>
</ResponsiveContainer>
</div>
);
}