From f78a76ebf0226f2342881fee879b8e8743129154 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Thu, 17 Jul 2025 00:51:47 +0200 Subject: [PATCH] dashboard servers --- sentryx/servers.json | 21 ++++++ sentryx/sessions.json | 1 + src/app/Server.css | 140 +++++++++++++++++++++++++++++++++++ src/app/api/servers/route.ts | 38 +++++++++- src/app/dashboard/page.tsx | 123 ++++++++++++++++++++++++++---- src/app/dashboard/server.tsx | 75 +++++++++++++++++++ src/components/AppLayout.tsx | 2 +- src/hooks/useSession.ts | 2 +- src/lib/session.ts | 17 +++++ src/types/server.ts | 4 + 10 files changed, 405 insertions(+), 18 deletions(-) create mode 100644 sentryx/sessions.json create mode 100644 src/app/Server.css create mode 100644 src/app/dashboard/server.tsx diff --git a/sentryx/servers.json b/sentryx/servers.json index 71e3681..d7bc5e7 100644 --- a/sentryx/servers.json +++ b/sentryx/servers.json @@ -2,5 +2,26 @@ { "name": "Main Server", "ip": "10.7.1.2" + }, + { + "name": "Second Server", + "ip": "10.7.1.2" + }, + { + "name": "Second Server", + "ip": "10.7.1.2" + }, + { + "name": "Second Server", + "ip": "10.7.1.2" + }, + { + "name": "Second Server", + "ip": "10.7.1.2" + }, + { + "name": "Second Server", + "ip": "10.7.1.2" } + ] diff --git a/sentryx/sessions.json b/sentryx/sessions.json new file mode 100644 index 0000000..46e3549 --- /dev/null +++ b/sentryx/sessions.json @@ -0,0 +1 @@ +{"SESH-344d851e-01ea-4010-8c6a-6205b6772055":"admin","SESH-cc54eaab-a8b9-45d6-8be2-406e346581e8":"admin","SESH-909ab0b4-89e9-4a48-aa16-b8d257421651":"admin","SESH-a930805a-319b-4079-9f81-64a7026e271c":"admin","SESH-8902f651-201d-4493-b1f7-763512cff5b6":"admin"} \ No newline at end of file diff --git a/src/app/Server.css b/src/app/Server.css new file mode 100644 index 0000000..21a1869 --- /dev/null +++ b/src/app/Server.css @@ -0,0 +1,140 @@ +.server-container .server { + box-sizing: border-box; + background-color: var(--card-bg); + border-radius: 10px; + width: 100%; + height: 100%; + padding: 30px; +} + +.server-heading-inner { + display: flex; + gap: 10px; +} + +.server-icon { + padding: 0.5rem; + border-radius: 10px; + width: 20px; + height: 20px; + background-color: var(--server-icon-bg); + color: rgb(37 99 235); + margin-top: auto; + margin-bottom: auto; +} + +.server-heading-info { + display: flex; + flex-direction: column; + gap: 7px; +} + +.server-heading-info div div { + display: flex; + gap: 3px; + width: max-content; + padding-left: 10px; + padding-right: 10px; + padding-top: 3px; + padding-bottom: 3px; + border-radius: 10px; +} + +.server-heading-info div div svg { + margin-top: auto; + margin-bottom: auto; +} + +.server-heading-info div div p { + margin-top: auto; + margin-bottom: auto; + font-size: 14px; + color: currentColor; +} + +.server-heading-info div { + display: flex; + flex-direction: row; + gap: 10px; +} + +.server-heading-info div p { + margin: 0; + font-size: 14.5px; + margin-top: auto; + margin-bottom: auto; + color: rgb(100 116 139); +} + +.server-heading { + display: flex; + justify-content: space-between; +} + +.server-heading button { + margin: 0; + border: 0; + height: max-content; + width: max-content; + padding: 8px; + align-items: center; + background-color: transparent; + border-radius: 7px; + margin-top: auto; + margin-bottom: auto; + color: var(--fg); +} + +.server-heading button:hover { + background-color: var(--bg); +} + +.server-monitor h2 { + margin: 0; + padding: 0; + margin-bottom: 20px; + display: flex; + gap: 7px; +} + +.server-monitor h2 svg { + margin-top: auto; + margin-bottom: auto; +} + +.server-monitor div { + display: flex; + justify-content: space-between; +} + +.server-monitor div p { + margin-bottom: 8px; + font-size: 14px; + display: flex; + gap: 6px; +} + +.All { + color: var(--fg); + background-color: var(--bg); +} + +.Online { + color: var(--online); + background-color: var(--online-bg); +} + +.Offline { + color: var(--offline); + background-color: var(--offline-bg); +} + +.Warning { + color: var(--warning); + background-color: var(--warning-bg); +} + +.Maintenance { + color: var(--maintenance); + background-color: var(--maintenance-bg); +} diff --git a/src/app/api/servers/route.ts b/src/app/api/servers/route.ts index cb0a84e..f033783 100644 --- a/src/app/api/servers/route.ts +++ b/src/app/api/servers/route.ts @@ -1,9 +1,41 @@ import { NextResponse } from "next/server"; import Data from "../data"; -import { ServerAPI } from "@/types/server"; +import Server, { ServerAPI } from "@/types/server"; -const servers = new Data("sentryx/servers.json", "array"); +const servers = new Data("sentryx/servers.json", "array"); export async function GET(request: Request) { - return NextResponse.json({ message: "ok", servers: servers.data }); + const { searchParams } = new URL(request.url); + const query = searchParams.get("s"); + const currentServers = servers.data.map( + (s) => + ({ + ...s, + status: "online", + cpu: 20, + memory: 70, + storage: 40, + network: 30, + } as Server) + ); + + if (query) { + let tokens = (query || "").toLocaleLowerCase().split(" "); + + console.log(tokens); + + return NextResponse.json({ + message: "ok", + servers: currentServers.filter((s) => + tokens.some( + (t) => s.name.toLowerCase().includes(t) || s.status.includes(t) + ) + ), + }); + } + + return NextResponse.json({ + message: "ok", + servers: currentServers, + }); } diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 75c450e..2a842b7 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -6,6 +6,13 @@ import { cn } from "@/lib/utils"; import { CircleCheckBig, Cpu, MemoryStick, TriangleAlert } from "lucide-react"; import { ChartAreaGradient } from "./chart"; import { Progress } from "@/components/ui/progress"; +import getSession from "@/hooks/getSession"; +import ServerComponent from "./server"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { useEffect, useState } from "react"; +import useSession from "@/hooks/useSession"; +import Server from "@/types/server"; export function generateHourlyData() { const result = []; @@ -60,43 +67,133 @@ export function Summary({ ); } +function average(values: Array, p: (v: T) => number) { + return values.length > 0 + ? values.reduce((sum, value) => sum + p(value), 0) / values.length + : 0; +} + +const d = generateHourlyData(); + export default function Dashboard() { - // const session = await getSession(); - const d = generateHourlyData(); + const session = useSession(); + const [servers, setServers] = useState([]); + const [searchedServers, setSearchedServers] = useState([]); + const [serversQuery, setServersQuery] = useState(""); + const [serverData, setServerData] = useState({ + online: 0, + issues: 0, + cpu: 0, + memory: 0, + storage: 0, + network: 0, + }); + + useEffect(() => { + if (!session) return; + + session.getServers().then((servers) => { + setServers(servers); + setServerData({ + online: servers.reduce( + (sum, server) => (server.status == "online" ? sum + 1 : sum), + 0 + ), + issues: servers.reduce( + (sum, server) => (server.status == "warning" ? sum + 1 : sum), + 0 + ), + cpu: average(servers, (s) => s.cpu), + memory: average(servers, (s) => s.memory), + storage: average(servers, (s) => s.storage), + network: average(servers, (s) => s.network), + }); + }); + }, [session]); + + useEffect(() => { + const timeout = setTimeout(() => { + let tokens = serversQuery.toLowerCase().split(" "); + setSearchedServers( + servers.filter((s) => + tokens.some( + (t) => s.name.toLowerCase().includes(t) || s.status.includes(t) + ) + ) + ); + }, 30); + + return () => clearTimeout(timeout); + }, [serversQuery, servers]); + return (
- + Online Servers Online - + Issues - + Avg CPU Usage CPU - + Avg Memory Usage Memory
-
- - +
+
+ +
+ System Overview - Average CPU - Average Memory - Storage - Average Network + Average CPU + Average Memory + Storage + Average Network
+ + + + setServersQuery(e.currentTarget.value)} + placeholder="Search servers by name, location or IP..." + /> + + + + +
+ {searchedServers.map((s, i) => ( + + ))} +
); } diff --git a/src/app/dashboard/server.tsx b/src/app/dashboard/server.tsx new file mode 100644 index 0000000..5c8e173 --- /dev/null +++ b/src/app/dashboard/server.tsx @@ -0,0 +1,75 @@ +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Label } from "@/components/ui/label"; +import { Progress } from "@/components/ui/progress"; +import Server from "@/types/server"; +import { Cpu, HardDrive, MemoryStick, Network, Wifi } from "lucide-react"; + +function UsageBar({ + value, + Icon, + text, + color, +}: { + value: number; + Icon: React.ElementType; + text: string; + color: string; +}) { + return ( +
+
+ + +
+ +
+ ); +} + +export default function ServerComponent({ server }: { server: Server }) { + return ( + + + {server.name} + + {server.status[0].toUpperCase() + server.status.slice(1)} {" ยท "} + {server.ip} + + + + + + + + + + ); +} diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 043a71b..834c5ce 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -17,7 +17,7 @@ export default function AppLayout({ children }: { children: React.ReactNode }) {
-
{children}
+
{children}
diff --git a/src/hooks/useSession.ts b/src/hooks/useSession.ts index a4ee0ee..09dc378 100644 --- a/src/hooks/useSession.ts +++ b/src/hooks/useSession.ts @@ -24,7 +24,7 @@ export default function useSession() { console.log(e); router.replace("/login"); }); - }); + }, []); return session; } diff --git a/src/lib/session.ts b/src/lib/session.ts index 9649ae6..e9bb538 100644 --- a/src/lib/session.ts +++ b/src/lib/session.ts @@ -1,7 +1,24 @@ +import Server from "@/types/server"; +import axios from "axios"; + export default class Session { id: string; constructor(id: string) { this.id = id; } + + public async getServers(query?: string): Promise { + try { + return ( + (( + await axios.get(`/api/servers?s=${query || ""}`, { + params: { id: this.id }, + }) + ).data.servers as Server[]) || [] + ); + } catch { + return []; + } + } } diff --git a/src/types/server.ts b/src/types/server.ts index 610ee62..fafec22 100644 --- a/src/types/server.ts +++ b/src/types/server.ts @@ -5,4 +5,8 @@ export interface ServerAPI { export default interface Server extends ServerAPI { status: "online" | "offline" | "warning" | "maintenance"; + cpu: number; + memory: number; + storage: number; + network: number; }