Structured for prod
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
import Data from "../data";
|
||||||
|
|
||||||
|
export const users = new Data<{
|
||||||
|
[key: string]: { username: string; password: string };
|
||||||
|
}>("sentryx/users.json", { admin: { username: "admin", password: "admin" } });
|
||||||
|
|
||||||
|
export const sessions = new Data<{ [key: string]: string }>(
|
||||||
|
"sentryx/sessions.json",
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function validate(sessionId: string | null) {
|
||||||
|
return sessionId && sessions.data[sessionId] != undefined;
|
||||||
|
}
|
||||||
@@ -1,15 +1,7 @@
|
|||||||
import axios, { HttpStatusCode } from "axios";
|
import axios, { HttpStatusCode } from "axios";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import Data, { findKey } from "../data";
|
import Data, { findKey } from "../data";
|
||||||
|
import { sessions, users } from "./auth";
|
||||||
const users = new Data<{
|
|
||||||
[key: string]: { username: string; password: string };
|
|
||||||
}>("sentryx/users.json", { admin: { username: "admin", password: "admin" } });
|
|
||||||
|
|
||||||
const sessions = new Data<{ [key: string]: string }>(
|
|
||||||
"sentryx/sessions.json",
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
export async function POST(request: Request) {
|
||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
@@ -54,7 +46,3 @@ export async function GET(request: Request) {
|
|||||||
|
|
||||||
return NextResponse.json({ message: "ok" });
|
return NextResponse.json({ message: "ok" });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validate(sessionId: string | null) {
|
|
||||||
return sessionId && sessions.data[sessionId] != undefined;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { HttpStatusCode } from "axios";
|
import { HttpStatusCode } from "axios";
|
||||||
import { NextResponse } from "next/server";
|
import { NextResponse } from "next/server";
|
||||||
import { servers } from "../servers/route";
|
import { servers } from "../servers/servers";
|
||||||
import { validate } from "../auth/route";
|
import validate from "../auth/auth";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Vision: This will be
|
Vision: This will be
|
||||||
|
|||||||
@@ -2,56 +2,8 @@ import { NextResponse } from "next/server";
|
|||||||
import Data from "../data";
|
import Data from "../data";
|
||||||
import Server, { ServerAPI } from "@/types/server";
|
import Server, { ServerAPI } from "@/types/server";
|
||||||
import { HttpStatusCode } from "axios";
|
import { HttpStatusCode } from "axios";
|
||||||
import { validate } from "../auth/route";
|
import validate from "../auth/auth";
|
||||||
|
import { currentServers, deletes, servers, useServer } from "./servers";
|
||||||
const useServer = (server: ServerAPI, index: number) => {
|
|
||||||
const ws = new WebSocket(`ws://${server.ip}:5273`);
|
|
||||||
ws.onmessage = (msg) => {
|
|
||||||
try {
|
|
||||||
if (deletes.has(index) || !currentServers[index]) {
|
|
||||||
ws.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (msg.data === "Success") {return}
|
|
||||||
const data = JSON.parse(msg.data);
|
|
||||||
|
|
||||||
if (data.status) {
|
|
||||||
currentServers[index].status = data.status;
|
|
||||||
}
|
|
||||||
if (data.cpu) {
|
|
||||||
currentServers[index].cpu = data.cpu;
|
|
||||||
}
|
|
||||||
if (data.memory) {
|
|
||||||
currentServers[index].memory = data.memory;
|
|
||||||
}
|
|
||||||
if (data.disk) {
|
|
||||||
currentServers[index].storage = data.disk;
|
|
||||||
}
|
|
||||||
if (data.network) {
|
|
||||||
currentServers[index].network = data.network;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Error parsing WebSocket message:", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ws.onopen = () => ws.send("my-key");
|
|
||||||
};
|
|
||||||
|
|
||||||
const deletes = new Set<number>();
|
|
||||||
export const servers = new Data<ServerAPI[]>("sentryx/servers.json", []);
|
|
||||||
export var currentServers: Server[] = servers.data.map(
|
|
||||||
(s) =>
|
|
||||||
({
|
|
||||||
...s,
|
|
||||||
status: "offline",
|
|
||||||
cpu: 0,
|
|
||||||
memory: 0,
|
|
||||||
storage: 0,
|
|
||||||
network: 0,
|
|
||||||
} as Server)
|
|
||||||
);
|
|
||||||
|
|
||||||
servers.data.map(useServer);
|
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
export async function GET(request: Request) {
|
||||||
const { searchParams } = new URL(request.url);
|
const { searchParams } = new URL(request.url);
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import Server, { ServerAPI } from "@/types/server";
|
||||||
|
import Data from "../data";
|
||||||
|
|
||||||
|
export const useServer = (server: ServerAPI, index: number) => {
|
||||||
|
const ws = new WebSocket(`ws://${server.ip}:5273`);
|
||||||
|
ws.onmessage = (msg) => {
|
||||||
|
try {
|
||||||
|
if (deletes.has(index) || !currentServers[index]) {
|
||||||
|
ws.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg.data === "Success") {return}
|
||||||
|
const data = JSON.parse(msg.data);
|
||||||
|
|
||||||
|
if (data.status) {
|
||||||
|
currentServers[index].status = data.status;
|
||||||
|
}
|
||||||
|
if (data.cpu) {
|
||||||
|
currentServers[index].cpu = data.cpu;
|
||||||
|
}
|
||||||
|
if (data.memory) {
|
||||||
|
currentServers[index].memory = data.memory;
|
||||||
|
}
|
||||||
|
if (data.disk) {
|
||||||
|
currentServers[index].storage = data.disk;
|
||||||
|
}
|
||||||
|
if (data.network) {
|
||||||
|
currentServers[index].network = data.network;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error parsing WebSocket message:", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onopen = () => ws.send("my-key");
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deletes = new Set<number>();
|
||||||
|
export const servers = new Data<ServerAPI[]>("sentryx/servers.json", []);
|
||||||
|
export var currentServers: Server[] = servers.data.map(
|
||||||
|
(s) =>
|
||||||
|
({
|
||||||
|
...s,
|
||||||
|
status: "offline",
|
||||||
|
cpu: 0,
|
||||||
|
memory: 0,
|
||||||
|
storage: 0,
|
||||||
|
network: 0,
|
||||||
|
} as Server)
|
||||||
|
);
|
||||||
|
|
||||||
|
servers.data.map(useServer);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Progress } from "@/components/ui/progress";
|
||||||
|
|
||||||
|
export default function Summary({
|
||||||
|
value,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
value: number;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="justify-between flex">
|
||||||
|
<Label className="text-md">{children}</Label>
|
||||||
|
<Label className="text-md">{value}%</Label>
|
||||||
|
</div>
|
||||||
|
<Progress value={value} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
export default function SummaryCard({
|
||||||
|
children,
|
||||||
|
value,
|
||||||
|
icon,
|
||||||
|
className,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode;
|
||||||
|
value: string;
|
||||||
|
icon: React.ElementType;
|
||||||
|
className?: string;
|
||||||
|
}) {
|
||||||
|
const Icon = icon;
|
||||||
|
return (
|
||||||
|
<Card className="h-24 flex flex-row justify-between items-center gap-0 px-6">
|
||||||
|
<div className="">
|
||||||
|
<Label className="text-md font-bold text-foreground">{children}</Label>
|
||||||
|
<Label className={cn("text-2xl font-bold", className)}>{value}</Label>
|
||||||
|
</div>
|
||||||
|
<Icon className={cn("shrink-0", className)} size={32} />
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,61 +13,20 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import useSession from "@/hooks/useSession";
|
import useSession from "@/hooks/useSession";
|
||||||
import Server from "@/types/server";
|
import Server from "@/types/server";
|
||||||
import { toast } from "sonner";
|
import SummaryCard from "./SummaryCard";
|
||||||
|
|
||||||
export function generateHourlyData() {
|
function generateHourlyData() {
|
||||||
const result = [];
|
const result = [];
|
||||||
for (let hour = 24; hour >= 0; hour--) {
|
for (let hour = 24; hour >= 0; hour--) {
|
||||||
result.push({
|
result.push({
|
||||||
hour: hour,
|
hour: hour,
|
||||||
cpu: Math.floor(Math.random() * 20 + 30), // random CPU usage between 0-99
|
cpu: Math.floor(Math.random() * 20 + 30),
|
||||||
ram: Math.floor(Math.random() * 40 + 40), // random RAM usage between 0-99
|
ram: Math.floor(Math.random() * 40 + 40),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SummaryCard({
|
|
||||||
children,
|
|
||||||
value,
|
|
||||||
icon,
|
|
||||||
className,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
value: string;
|
|
||||||
icon: React.ElementType;
|
|
||||||
className?: string;
|
|
||||||
}) {
|
|
||||||
const Icon = icon;
|
|
||||||
return (
|
|
||||||
<Card className="h-24 flex flex-row justify-between items-center gap-0 px-6">
|
|
||||||
<div className="">
|
|
||||||
<Label className="text-md font-bold text-foreground">{children}</Label>
|
|
||||||
<Label className={cn("text-2xl font-bold", className)}>{value}</Label>
|
|
||||||
</div>
|
|
||||||
<Icon className={cn("shrink-0", className)} size={32} />
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function Summary({
|
|
||||||
value,
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
value: number;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col gap-2 w-full">
|
|
||||||
<div className="justify-between flex">
|
|
||||||
<Label className="text-md">{children}</Label>
|
|
||||||
<Label className="text-md">{value}%</Label>
|
|
||||||
</div>
|
|
||||||
<Progress value={value} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function average<T>(values: Array<T>, p: (v: T) => number) {
|
function average<T>(values: Array<T>, p: (v: T) => number) {
|
||||||
return values.length > 0
|
return values.length > 0
|
||||||
? values.reduce((sum, value) => sum + p(value), 0) / values.length
|
? values.reduce((sum, value) => sum + p(value), 0) / values.length
|
||||||
@@ -115,6 +74,7 @@ export default function Dashboard() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getServers();
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
console.log("Refreshing servers data...");
|
console.log("Refreshing servers data...");
|
||||||
getServers();
|
getServers();
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import Server from "@/types/server";
|
|||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||||
import Map from "./Map";
|
import Map from "./Map";
|
||||||
import NewServerDialog from "./NewServerDialog";
|
import NewServerDialog from "./NewServerDialog";
|
||||||
import { toast } from "sonner";
|
|
||||||
|
|
||||||
export default function Servers() {
|
export default function Servers() {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
|
|||||||
Reference in New Issue
Block a user