mirror of
https://github.com/khairul169/vaulterm.git
synced 2026-09-15 17:03:30 +07:00
feat: add server stats
This commit is contained in:
@@ -3,6 +3,8 @@ import Terminal from "./terminal";
|
||||
import VNCViewer from "./vncviewer";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { AppServer, useServer } from "@/stores/app";
|
||||
import { useWebsocketUrl } from "@/hooks/useWebsocket";
|
||||
import ServerStatsBar from "./server-stats-bar";
|
||||
|
||||
type SSHSessionProps = {
|
||||
type: "ssh";
|
||||
@@ -30,20 +32,25 @@ export type InteractiveSessionProps = {
|
||||
|
||||
const InteractiveSession = ({ type, params }: InteractiveSessionProps) => {
|
||||
const { token } = useAuthStore();
|
||||
const server = useServer();
|
||||
const query = new URLSearchParams({ ...params, sid: token || "" });
|
||||
const url = `${getBaseUrl(server)}/ws/term?${query}`;
|
||||
const ws = useWebsocketUrl({ ...params, sid: token || "" });
|
||||
const termUrl = ws("term");
|
||||
const statsUrl = ws("stats");
|
||||
|
||||
switch (type) {
|
||||
case "ssh":
|
||||
return <Terminal url={url} />;
|
||||
return (
|
||||
<>
|
||||
<Terminal url={termUrl} />
|
||||
<ServerStatsBar url={statsUrl} />
|
||||
</>
|
||||
);
|
||||
|
||||
case "pve":
|
||||
case "incus":
|
||||
return params.client === "vnc" ? (
|
||||
<VNCViewer url={url} />
|
||||
<VNCViewer url={termUrl} />
|
||||
) : (
|
||||
<Terminal url={url} />
|
||||
<Terminal url={termUrl} />
|
||||
);
|
||||
|
||||
default:
|
||||
@@ -51,8 +58,4 @@ const InteractiveSession = ({ type, params }: InteractiveSessionProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
function getBaseUrl(server?: AppServer | null) {
|
||||
return server?.url.replace("http://", "ws://") || "";
|
||||
}
|
||||
|
||||
export default InteractiveSession;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { View, Text, XStack, Separator } from "tamagui";
|
||||
import React, { useState } from "react";
|
||||
import { useWebSocket } from "@/hooks/useWebsocket";
|
||||
import Icons from "../ui/icons";
|
||||
|
||||
type Props = {
|
||||
url: string;
|
||||
};
|
||||
|
||||
const ServerStatsBar = ({ url }: Props) => {
|
||||
const [cpu, setCPU] = useState(0);
|
||||
const [memory, setMemory] = useState({ total: 0, used: 0, available: 0 });
|
||||
const [disk, setDisk] = useState({ total: "0", used: "0", percent: "0%" });
|
||||
const [network, setNetwork] = useState({ tx: 0, rx: 0 });
|
||||
|
||||
const { isConnected } = useWebSocket(url, {
|
||||
onMessage: (msg) => {
|
||||
const type = msg.substring(0, 1);
|
||||
const value = msg.substring(1);
|
||||
let values: string[];
|
||||
|
||||
switch (type) {
|
||||
case "\x01":
|
||||
setCPU(parseFloat(value));
|
||||
break;
|
||||
|
||||
case "\x02":
|
||||
values = value.split(",");
|
||||
const total = parseInt(values[0]) || 0;
|
||||
const available = parseInt(values[1]) || 0;
|
||||
const used = total - available;
|
||||
setMemory({ total, used, available });
|
||||
break;
|
||||
|
||||
case "\x03":
|
||||
values = value.split(",");
|
||||
setDisk({ total: values[0], used: values[1], percent: values[2] });
|
||||
break;
|
||||
|
||||
case "\x04":
|
||||
values = value.split(",");
|
||||
setNetwork({
|
||||
tx: parseInt(values[0]) || 0,
|
||||
rx: parseInt(values[1]) || 0,
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (!isConnected || !memory.total) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<XStack gap="$1" p="$2" alignItems="center">
|
||||
<XStack gap="$1" alignItems="center" minWidth={48}>
|
||||
<Icons name="desktop-tower" size={16} />
|
||||
<Text fontSize="$2">{Math.round(cpu)}%</Text>
|
||||
</XStack>
|
||||
|
||||
<Separator vertical h="100%" mx="$2" borderColor="$color" />
|
||||
<Icons name="memory" size={16} />
|
||||
<Text fontSize="$2">
|
||||
{memory.used} MB / {memory.total} MB (
|
||||
{Math.round((memory.used / memory.total) * 100) || 0}%)
|
||||
</Text>
|
||||
|
||||
<Separator vertical h="100%" mx="$2" borderColor="$color" />
|
||||
<Icons name="harddisk" size={16} />
|
||||
<Text fontSize="$2">
|
||||
{disk.used} / {disk.total} ({disk.percent})
|
||||
</Text>
|
||||
|
||||
<Separator vertical h="100%" mx="$2" borderColor="$color" />
|
||||
<Icons name="download" size={16} />
|
||||
<Text fontSize="$2">{network.rx} MB</Text>
|
||||
<Icons name="upload" size={16} />
|
||||
<Text fontSize="$2">{network.tx} MB</Text>
|
||||
</XStack>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerStatsBar;
|
||||
Reference in New Issue
Block a user