feat: topology, and improves handling

This commit is contained in:
2026-02-17 18:12:02 +07:00
parent e8dbefde43
commit d14f043e7c
145 changed files with 4213 additions and 2861 deletions

View File

@@ -6,7 +6,15 @@ import { useRouter } from "next/navigation";
import { ServerForm, type ServerFormData } from "@/components/server-form";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { api } from "@/lib/api";
import { api } from "@/lib/api-client";
const toDifficultyUppercase = (value: string): "PEACEFUL" | "EASY" | "NORMAL" | "HARD" => {
return value.toUpperCase() as "PEACEFUL" | "EASY" | "NORMAL" | "HARD";
};
const toModeUppercase = (value: string): "SURVIVAL" | "CREATIVE" | "ADVENTURE" | "SPECTATOR" => {
return value.toUpperCase() as "SURVIVAL" | "CREATIVE" | "ADVENTURE" | "SPECTATOR";
};
export default function CreateServerPage() {
const router = useRouter();
@@ -121,8 +129,8 @@ export default function CreateServerPage() {
jvm_opts: data.jvmOpts || undefined,
use_aikar_flags: data.useAikarFlags || undefined,
use_meowice_flags: data.useMeowiceFlags || undefined,
difficulty: data.difficulty,
game_mode: data.mode,
difficulty: toDifficultyUppercase(data.difficulty),
game_mode: toModeUppercase(data.mode),
max_players: data.maxPlayers ? Number(data.maxPlayers) : undefined,
pvp: data.pvp,
online_mode: data.onlineMode,

View File

@@ -7,7 +7,7 @@ import { useEffect, useState } from "react";
import { ServerForm, type ServerFormData, type ServerType } from "@/components/server-form";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { api } from "@/lib/api";
import { api } from "@/lib/api-client";
import { getReverseProxyApi } from "@/lib/api-helpers";
export default function EditServerPage() {
@@ -48,8 +48,7 @@ export default function EditServerPage() {
setError("Server not found");
setLoading(false);
} catch (err) {
console.error("Failed to fetch server:", err);
} catch (_err) {
setError("Failed to load server data");
setLoading(false);
}
@@ -81,11 +80,12 @@ export default function EditServerPage() {
return "survival";
};
const toServerType = (value?: string | null): ServerType => {
if (value === "VANILLA" || value === "CUSTOM") {
return value;
}
return "PAPER";
const toDifficultyUppercase = (value: string): "PEACEFUL" | "EASY" | "NORMAL" | "HARD" => {
return value.toUpperCase() as "PEACEFUL" | "EASY" | "NORMAL" | "HARD";
};
const toModeUppercase = (value: string): "SURVIVAL" | "CREATIVE" | "ADVENTURE" | "SPECTATOR" => {
return value.toUpperCase() as "SURVIVAL" | "CREATIVE" | "ADVENTURE" | "SPECTATOR";
};
const parseEnvVariables = (envVars?: Array<{ key: string; value: string }>) => {
@@ -205,8 +205,8 @@ export default function EditServerPage() {
jvm_opts: data.jvmOpts || undefined,
use_aikar_flags: data.useAikarFlags || undefined,
use_meowice_flags: data.useMeowiceFlags || undefined,
difficulty: data.difficulty,
game_mode: data.mode,
difficulty: toDifficultyUppercase(data.difficulty),
game_mode: toModeUppercase(data.mode),
max_players: data.maxPlayers ? Number(data.maxPlayers) : undefined,
pvp: data.pvp,
online_mode: data.onlineMode,

View File

@@ -1,5 +1,6 @@
"use client";
import type { ConnectionInfo, NormalServer, PodInfo, ReverseProxyServer } from "@minikura/api";
import {
AlertCircle,
Check,
@@ -25,15 +26,6 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
@@ -42,14 +34,10 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
import type { ConnectionInfo, NormalServer, PodInfo, ReverseProxyServer } from "@minikura/api";
import { api } from "@/lib/api-client";
import { getReverseProxyApi } from "@/lib/api-helpers";
import { api } from "@/lib/api";
// Server status component
function ServerStatusCell({ serverId, type }: { serverId: string; type: "normal" | "proxy" }) {
const [pods, setPods] = useState<PodInfo[]>([]);
const [loading, setLoading] = useState(true);
@@ -59,14 +47,13 @@ function ServerStatusCell({ serverId, type }: { serverId: string; type: "normal"
try {
const endpoint =
type === "normal"
? api.api.k8s["servers"]({ serverId }).pods.get
? api.api.k8s.servers({ serverId }).pods.get
: api.api.k8s["reverse-proxy"]({ serverId }).pods.get;
const res = await endpoint();
if (res.data) {
setPods(res.data as PodInfo[]);
}
} catch (error) {
console.error("Failed to fetch pods:", error);
} catch (_error) {
} finally {
setLoading(false);
}
@@ -93,9 +80,7 @@ function ServerStatusCell({ serverId, type }: { serverId: string; type: "normal"
}
const allRunning = pods.every((pod) => pod.status === "Running");
const readyCount = pods.filter(
(pod) => pod.ready === "1/1" || pod.ready === "1/1" || pod.ready === "1/1"
).length;
const readyCount = pods.filter((pod) => pod.ready === "1/1").length;
return (
<div className="flex items-center gap-2">
@@ -111,7 +96,6 @@ function ServerStatusCell({ serverId, type }: { serverId: string; type: "normal"
);
}
// Connection info component
function ConnectionInfoCell({ serverId, type }: { serverId: string; type: "normal" | "proxy" }) {
const [connectionInfo, setConnectionInfo] = useState<ConnectionInfo | null>(null);
const [loading, setLoading] = useState(true);
@@ -129,8 +113,7 @@ function ConnectionInfoCell({ serverId, type }: { serverId: string; type: "norma
if (res.data) {
setConnectionInfo(res.data as ConnectionInfo);
}
} catch (error) {
console.error("Failed to fetch connection info:", error);
} catch (_error) {
} finally {
setLoading(false);
}
@@ -213,8 +196,7 @@ export default function ServersPage() {
if (proxyRes.data) {
setReverseProxies(proxyRes.data as unknown as ReverseProxyServer[]);
}
} catch (error) {
console.error("Failed to fetch servers:", error);
} catch (_error) {
} finally {
setLoading(false);
}
@@ -236,9 +218,7 @@ export default function ServersPage() {
}
await fetchServers();
setDeleteTarget(null);
} catch (error) {
console.error("Failed to delete server:", error);
}
} catch (_error) {}
};
if (loading) {
@@ -270,7 +250,6 @@ export default function ServersPage() {
</Button>
</div>
{/* Normal Servers */}
<Card>
<CardHeader>
<div className="flex items-center gap-2">
@@ -360,7 +339,6 @@ export default function ServersPage() {
</CardContent>
</Card>
{/* Reverse Proxy Servers */}
<Card>
<CardHeader>
<div className="flex items-center gap-2">
@@ -448,7 +426,6 @@ export default function ServersPage() {
</CardContent>
</Card>
{/* Delete Confirmation Dialog */}
<Dialog open={!!deleteTarget} onOpenChange={() => setDeleteTarget(null)}>
<DialogContent>
<DialogHeader>