aded apps (not functional yet)
This commit is contained in:
+1
-1
@@ -38,6 +38,6 @@ export default class Data<T> {
|
|||||||
mkdirSync(dir, { recursive: true });
|
mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
writeFileSync(this.file_path, JSON.stringify(this.data));
|
writeFileSync(this.file_path, JSON.stringify(this.data, undefined, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@/components/ui/card";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Progress } from "@/components/ui/progress";
|
||||||
|
import Session from "@/lib/session";
|
||||||
|
import Service, { AppService } from "@/types/service";
|
||||||
|
import { AppWindowMac } from "lucide-react";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function UsageBar({
|
||||||
|
value,
|
||||||
|
Icon,
|
||||||
|
text,
|
||||||
|
color,
|
||||||
|
}: {
|
||||||
|
value: number;
|
||||||
|
Icon: React.ElementType;
|
||||||
|
text: string;
|
||||||
|
color: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="justify-between flex">
|
||||||
|
<Label className="text-md flex justify-center">
|
||||||
|
<Icon size={16} color={color} /> {text}
|
||||||
|
</Label>
|
||||||
|
<Label className="text-md">{value}%</Label>
|
||||||
|
</div>
|
||||||
|
<Progress value={value} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatBytes(bytes: number, decimals = 2): string {
|
||||||
|
if (bytes === 0) return "0 Bytes";
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const dm = decimals < 0 ? 0 : decimals;
|
||||||
|
|
||||||
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
const size = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));
|
||||||
|
|
||||||
|
return `${size} ${sizes[i]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ByteUnit({
|
||||||
|
value,
|
||||||
|
Icon,
|
||||||
|
text,
|
||||||
|
color,
|
||||||
|
}: {
|
||||||
|
value: number;
|
||||||
|
Icon: React.ElementType;
|
||||||
|
text: string;
|
||||||
|
color: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2 w-full">
|
||||||
|
<div className="justify-between flex">
|
||||||
|
<Label className="text-md flex justify-center">
|
||||||
|
<Icon size={16} color={color} /> {text}
|
||||||
|
</Label>
|
||||||
|
<Label className="text-md">{formatBytes(value)}</Label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AppComponent({
|
||||||
|
service,
|
||||||
|
index,
|
||||||
|
app
|
||||||
|
}: {
|
||||||
|
service: Service;
|
||||||
|
app: AppService;
|
||||||
|
index: number;
|
||||||
|
}) {
|
||||||
|
const [deleteAlert, setDeleteAlert] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className="w-full transition-transform duration-500 hover:scale-102 hover:cursor-pointer !select-none border-accent border-2"
|
||||||
|
onClick={() => {
|
||||||
|
redirect(`/servers/${index}`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardHeader>
|
||||||
|
<div className="flex items-center gap-2 overflow-clip">
|
||||||
|
<div className="bg-muted text-muted-foreground p-1.5 rounded-md">
|
||||||
|
<AppWindowMac className="w-4.5 h-4.5 text-current my-auto" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<CardTitle>{app.name}</CardTitle>
|
||||||
|
|
||||||
|
{(service.description && <CardDescription className="flex justify-between">
|
||||||
|
<div><p className={service.active_state}>{service.active_state[0].toUpperCase() + service.active_state.slice(1)}</p> {service.description}</div>
|
||||||
|
{(service as any).cpu}
|
||||||
|
</CardDescription>)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="w-full flex flex-col gap-3.5">
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,10 @@ import { useEffect, useState } from "react";
|
|||||||
import ServiceComponent from "./service";
|
import ServiceComponent from "./service";
|
||||||
import ServerComponent from "@/app/dashboard/server";
|
import ServerComponent from "@/app/dashboard/server";
|
||||||
import Service, { AppService } from "@/types/service";
|
import Service, { AppService } from "@/types/service";
|
||||||
|
import AppComponent from "./AppComponent";
|
||||||
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
interface Server2 extends Server {
|
interface Server2 extends Server {
|
||||||
services: Service[],
|
services: Service[],
|
||||||
@@ -32,6 +36,25 @@ export default function ServerPage(params: { server: string }) {
|
|||||||
<div>
|
<div>
|
||||||
<ServerComponent server={server} session={session} index={index} nonInteractive />
|
<ServerComponent server={server} session={session} index={index} nonInteractive />
|
||||||
</div>
|
</div>
|
||||||
|
<Card className="">
|
||||||
|
<CardHeader className="flex">
|
||||||
|
<div>
|
||||||
|
<CardTitle>Sentryx Apps</CardTitle>
|
||||||
|
<CardDescription>Your Sentryx apps on this server</CardDescription>
|
||||||
|
</div>
|
||||||
|
<Button className="ml-auto" onClick={() => {
|
||||||
|
toast.warning("Functionality not added yet");
|
||||||
|
}}>Add</Button>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||||
|
{server.apps.map((a, i) => {
|
||||||
|
const srv = server.services.find(s => s.name == a.service);
|
||||||
|
return srv && <AppComponent key={i} service={srv} index={i} app={a} / >;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-5">
|
||||||
{server.services.map((a, i) => (
|
{server.services.map((a, i) => (
|
||||||
<ServiceComponent key={i} service={a} index={i} session={session} / >
|
<ServiceComponent key={i} service={a} index={i} session={session} / >
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
export interface AppService { name?: string, description?: string };
|
export interface AppService { name?: string, description?: string, service: string };
|
||||||
export default interface Service { name?: string, description?: string, active_state: string };
|
export default interface Service { name?: string, description?: string, active_state: string };
|
||||||
Reference in New Issue
Block a user