This commit is contained in:
2025-12-27 13:42:50 +01:00
parent c107ec9b5b
commit eed4a0e438
8 changed files with 100 additions and 51 deletions
+13 -1
View File
@@ -13,9 +13,21 @@ export async function read<T extends object>(
await fs.access(filePath); await fs.access(filePath);
} catch { } catch {
await fs.mkdir(dirPath, { recursive: true }); await fs.mkdir(dirPath, { recursive: true });
await fs.writeFile(filePath, JSON.stringify(template, null, 2), "utf-8"); await fs.writeFile(filePath, JSON.stringify(template(), null, 2), "utf-8");
} }
const content = await fs.readFile(filePath, "utf-8"); const content = await fs.readFile(filePath, "utf-8");
return JSON.parse(content); return JSON.parse(content);
} }
export async function write<T extends object>(
val: T,
fp: string,
...filePaths: string[]
) {
const filePath = path.join(process.cwd(), fp, ...filePaths);
const dirPath = path.dirname(filePath);
await fs.mkdir(dirPath, { recursive: true });
await fs.writeFile(filePath, JSON.stringify(val, null, 2), "utf-8");
}
View File
+23 -36
View File
@@ -16,6 +16,9 @@ import {
} from "lucide-react"; } from "lucide-react";
import { Progress } from "@/components/ui/progress"; import { Progress } from "@/components/ui/progress";
import Link from "next/link"; import Link from "next/link";
import { getLiveNodes, getNodes } from "@/core/client/node";
import { useEffect, useState } from "react";
import { Node, NodeLiveData } from "@/lib/types";
const recentDeployments = [ const recentDeployments = [
{ {
@@ -86,34 +89,13 @@ const applications = [
}, },
]; ];
const nodes = [
{
name: "node-01",
ip: "10.0.1.10",
cpu: 72,
memory: 68,
containers: 8,
status: "running" as const,
},
{
name: "node-02",
ip: "10.0.1.11",
cpu: 45,
memory: 52,
containers: 6,
status: "running" as const,
},
{
name: "node-03",
ip: "10.0.1.12",
cpu: 89,
memory: 85,
containers: 12,
status: "running" as const,
},
];
export default function OverviewPage() { export default function OverviewPage() {
const [nodes, setNodes] = useState<NodeLiveData[]>([]);
useEffect(() => {
getLiveNodes().then(setNodes);
}, []);
return ( return (
<DashboardLayout title="Overview" subtitle="System status and metrics"> <DashboardLayout title="Overview" subtitle="System status and metrics">
{/* Stats Grid */} {/* Stats Grid */}
@@ -246,7 +228,7 @@ export default function OverviewPage() {
> >
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-3 gap-2"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-3 gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<StatusIndicator status={node.status} /> <StatusIndicator status={node.liveData.status} />
<span className="font-mono text-sm">{node.name}</span> <span className="font-mono text-sm">{node.name}</span>
</div> </div>
<span className="text-xs text-muted-foreground font-mono"> <span className="text-xs text-muted-foreground font-mono">
@@ -256,20 +238,25 @@ export default function OverviewPage() {
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">CPU</span> <span className="text-muted-foreground">CPU</span>
<span className="font-mono">{node.cpu}%</span> <span className="font-mono">{node.liveData.cpu}%</span>
</div>
<Progress value={node.cpu} className="[&>div]:bg-chart-1" />
<div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">Memory</span>
<span className="font-mono">{node.memory}%</span>
</div> </div>
<Progress <Progress
value={node.memory} value={node.liveData.cpu}
className="[&>div]:bg-chart-1"
/>
<div className="flex items-center justify-between text-xs">
<span className="text-muted-foreground">Memory</span>
<span className="font-mono">{node.liveData.memory}%</span>
</div>
<Progress
value={node.liveData.memory}
className="w-full [&>div]:bg-chart-3" className="w-full [&>div]:bg-chart-3"
/> />
<div className="flex items-center justify-between text-xs pt-2 border-t border-border mt-2"> <div className="flex items-center justify-between text-xs pt-2 border-t border-border mt-2">
<span className="text-muted-foreground">Containers</span> <span className="text-muted-foreground">Containers</span>
<span className="font-mono">{node.containers}</span> <span className="font-mono">
{node.liveData.containers}
</span>
</div> </div>
</div> </div>
</div> </div>
+12
View File
@@ -0,0 +1,12 @@
"use server";
import axios from "axios";
import { Node } from "@/lib/types";
export async function getDocker(node: Node): Promise<{ version: string }> {
return await (
await axios.get(`http://${node.ip}:3000/api/get-docker`, {
headers: { Authorization: `ApiKey ${node.key}` },
})
).data;
}
-14
View File
@@ -1,14 +0,0 @@
"use server";
import axios from "axios";
export async function getDocker(
node_ip: string,
key: string
): Promise<{ version: string }> {
return await (
await axios.get(`http://${node_ip}:3000/api/get-docker`, {
headers: { Authorization: `ApiKey ${key}` },
})
).data;
}
+32
View File
@@ -0,0 +1,32 @@
"use server";
import { read, write } from "@/app/api/file";
import { Node, NodeLiveData } from "@/lib/types";
import axios from "axios";
export async function getNodes(): Promise<Node[]> {
return await read(() => [], "data", "nodes.json");
}
export async function setNodes(nodes: Node[]) {
await write(nodes, "data", "nodes.json");
}
export async function getNode(node_id: string): Promise<Node | undefined> {
const nodes = await read<Node[]>(() => [], "data", "nodes.json");
return nodes.find((v) => v.node_id === node_id);
}
export async function getLiveNodes(): Promise<NodeLiveData[]> {
const nodes = await read(() => [], "data", "nodes.json");
return await Promise.all(nodes.map(getLiveNode));
}
export async function getLiveNode(node: Node): Promise<NodeLiveData> {
const data = await (
await axios.get(`http://${node.ip}:3000/api/status`, {
headers: { Authorization: `ApiKey ${node.key}` },
})
).data;
return { ...node, liveData: data.liveData };
}
+20
View File
@@ -0,0 +1,20 @@
export interface Node {
name: string;
node_id: string;
ip: string;
key: string;
}
export interface NodeLiveData {
name: string;
node_id: string;
ip: string;
key: string;
liveData: {
status: "running" | "pending" | "error";
cpu: number;
memory: number;
disk: number;
containers: number;
};
}