[STYLING] Adjusted formatting for options

This commit is contained in:
Dunemask 2023-12-22 21:10:06 -07:00
parent b45bfed63c
commit 2da6278ae7
12 changed files with 443 additions and 128 deletions

View file

@ -3,6 +3,7 @@ import k8s from "@kubernetes/client-node";
import { Rcon as RconClient } from "rcon-client"; import { Rcon as RconClient } from "rcon-client";
import stream from "stream"; import stream from "stream";
import { ERR, WARN } from "../../util/logging.js"; import { ERR, WARN } from "../../util/logging.js";
import { getServerEntry } from "../../database/queries/server-queries.js";
// Kubernetes Configuration // Kubernetes Configuration
const kc = new k8s.KubeConfig(); const kc = new k8s.KubeConfig();
@ -12,8 +13,9 @@ const namespace = process.env.MCL_SERVER_NAMESPACE;
// Retrieves logs from the minecraft server container // Retrieves logs from the minecraft server container
export async function webConsoleLogs(socket) { export async function webConsoleLogs(socket) {
const { serverName } = socket.mcs; const { serverId } = socket.mcs;
const podName = `mcl-${serverName}`; const server = await getServerEntry(serverId);
const podName = `mcl-${server.mclName}`;
const containerName = `${podName}-server`; const containerName = `${podName}-server`;
const podResponse = await k8sCore.listNamespacedPod(namespace); const podResponse = await k8sCore.listNamespacedPod(namespace);
const pods = podResponse.body.items.map((vp1) => vp1.metadata.name); const pods = podResponse.body.items.map((vp1) => vp1.metadata.name);
@ -41,14 +43,15 @@ export async function webConsoleLogs(socket) {
export async function webConsoleRcon(socket) { export async function webConsoleRcon(socket) {
if (socket.rconClient) if (socket.rconClient)
return VERB("RCON", "Socket already connected to RCON"); return VERB("RCON", "Socket already connected to RCON");
const rconSecret = `mcl-${socket.mcs.serverName}-rcon-secret`; const { serverId } = socket.mcs;
const server = await getServerEntry(serverId);
const rconSecret = `mcl-${server.mclName}-rcon-secret`;
const rconRes = await k8sCore.readNamespacedSecret(rconSecret, namespace); const rconRes = await k8sCore.readNamespacedSecret(rconSecret, namespace);
const rconPassword = Buffer.from( const rconPassword = Buffer.from(
rconRes.body.data["rcon-password"], rconRes.body.data["rcon-password"],
"base64", "base64",
).toString("utf8"); ).toString("utf8");
const { serverName } = socket.mcs; const rconHost = `mcl-${server.mclName}-rcon.${namespace}.svc.cluster.local`;
const rconHost = `mcl-${serverName}-rcon.${namespace}.svc.cluster.local`;
const rcon = new RconClient({ const rcon = new RconClient({
host: rconHost, host: rconHost,
port: 25575, port: 25575,

View file

@ -18,7 +18,7 @@ async function rconSend(socket, m) {
const socketConnect = async (io, socket) => { const socketConnect = async (io, socket) => {
VERB("WS", "Websocket connecting"); VERB("WS", "Websocket connecting");
socket.mcs = { serverName: socket.handshake.query.serverName }; socket.mcs = { serverId: socket.handshake.query.serverId };
try { try {
await webConsoleLogs(socket); await webConsoleLogs(socket);
await webConsoleRcon(socket); await webConsoleRcon(socket);

304
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -28,12 +28,15 @@
"@mui/material": "^5.14.20", "@mui/material": "^5.14.20",
"@tanstack/react-query": "^5.12.2", "@tanstack/react-query": "^5.12.2",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"chonky": "^2.3.2",
"chonky-icon-fontawesome": "^2.3.2",
"concurrently": "^8.2.2", "concurrently": "^8.2.2",
"nodemon": "^3.0.2", "nodemon": "^3.0.2",
"prettier": "^3.1.0", "prettier": "^3.1.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-router-dom": "^6.20.1", "react-router-dom": "^6.20.1",
"react-toastify": "^9.1.3",
"socket.io-client": "^4.7.2", "socket.io-client": "^4.7.2",
"vite": "^5.0.7" "vite": "^5.0.7"
}, },
@ -43,8 +46,6 @@
"basic-ftp": "^5.0.4", "basic-ftp": "^5.0.4",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"chonky": "^2.3.2",
"chonky-icon-fontawesome": "^2.3.2",
"express": "^4.18.2", "express": "^4.18.2",
"figlet": "^1.7.0", "figlet": "^1.7.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",

View file

@ -40,10 +40,16 @@ export default function MineclusterFiles(props) {
const updateFiles = () => { const updateFiles = () => {
const dir = dirStack.join("/"); const dir = dirStack.join("/");
getServerFiles(serverId, dir).then((f) => { getServerFiles(serverId, dir)
.then((f) => {
const files = f.map((fi) => ({ ...fi, id: `${dir}/${fi.name}` })); const files = f.map((fi) => ({ ...fi, id: `${dir}/${fi.name}` }));
setFiles(files ?? []); setFiles(files ?? []);
}); })
.catch(() =>
console.error(
"Couldn't update files, server likely hasn't started yet",
),
);
}; };
useEffect(() => { useEffect(() => {

View file

@ -0,0 +1,26 @@
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
const maxCpuSupported = 8;
export const cpuOptions = new Array(2 * maxCpuSupported)
.fill(0)
.map((v, i) => (i + 1) * 0.5);
export default function CpuOption(props) {
const { value, onChange } = props;
return (
<TextField
label="CPU"
onChange={onChange}
value={value}
select
required
SelectProps={{ MenuProps: { sx: { maxHeight: "20rem" } } }}
disabled // TODO: Enable on backend support
>
{cpuOptions.map((o, i) => (
<MenuItem value={o} key={i}>{`${o} CPU`}</MenuItem>
))}
</TextField>
);
}

View file

@ -0,0 +1,14 @@
import TextField from "@mui/material/TextField";
export default function HostOption(props) {
const { onChange } = props;
return (
<TextField
label="Host"
onChange={onChange}
helperText="Example: host.mydomain.com"
FormHelperTextProps={{ sx: { ml: 0 } }}
required
/>
);
}

View file

@ -0,0 +1,24 @@
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
const maxMemSupported = 10;
export const memoryOptions = new Array(2 * maxMemSupported)
.fill(0)
.map((v, i) => (i + 1) * 512);
export default function Option(props) {
const { value, onChange } = props;
return (
<TextField
label="Memory"
onChange={onChange}
value={value}
select
required
SelectProps={{ MenuProps: { sx: { maxHeight: "20rem" } } }}
>
{memoryOptions.map((o, i) => (
<MenuItem value={o} key={i}>{`${o / 1024} Gi`}</MenuItem>
))}
</TextField>
);
}

View file

@ -0,0 +1,14 @@
import TextField from "@mui/material/TextField";
export default function NameOption(props) {
const { onChange } = props;
return (
<TextField
label="Name"
onChange={onChange}
helperText="Example: My Survival World"
FormHelperTextProps={{ sx: { ml: 0 } }}
required
/>
);
}

View file

@ -0,0 +1,25 @@
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
const displayOption = (o) => o.charAt(0) + o.toLowerCase().slice(1);
export const serverTypeOptions = ["VANILLA", "FABRIC", "PAPER", "SPIGOT"];
export default function ServerTypeOption(props) {
const { value, onChange } = props;
return (
<TextField
label="Memory"
onChange={onChange}
value={value}
select
required
SelectProps={{ MenuProps: { sx: { maxHeight: "20rem" } } }}
>
{serverTypeOptions.map((o, i) => (
<MenuItem value={o} key={i}>
{displayOption(o)}
</MenuItem>
))}
</TextField>
);
}

View file

@ -0,0 +1,37 @@
import { useState, useEffect } from "react";
import TextField from "@mui/material/TextField";
import MenuItem from "@mui/material/MenuItem";
import { useVersionList } from "@mcl/queries";
export default function VersionOption(props) {
const { value, onChange } = props;
const versionList = useVersionList();
const [versions, setVersions] = useState(["latest"]);
useEffect(() => {
if (!versionList.data) return;
setVersions([
"latest",
...versionList.data.versions
.filter(({ type: releaseType }) => releaseType === "release")
.map(({ id }) => id),
]);
}, [versionList.data]);
return (
<TextField
label="Version"
onChange={onChange}
value={value}
select
required
SelectProps={{ MenuProps: { sx: { maxHeight: "20rem" } } }}
>
{versions.map((v, k) => (
<MenuItem value={v} key={k}>
{v}
</MenuItem>
))}
</TextField>
);
}

View file

@ -1,27 +1,37 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField"; import TextField from "@mui/material/TextField";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Chip from "@mui/material/Chip";
import Select from "@mui/material/Select";
import MenuItem from "@mui/material/MenuItem";
import InputLabel from "@mui/material/InputLabel";
import FormControl from "@mui/material/FormControl"; import FormControl from "@mui/material/FormControl";
import { useCreateServer, useVersionList } from "@mcl/queries"; import { useCreateServer } from "@mcl/queries";
import NameOption from "@mcl/components/server-options/NameOption.jsx";
import HostOption from "@mcl/components/server-options/HostOption.jsx";
import VersionOption from "@mcl/components/server-options/VersionOption.jsx";
import ServerTypeOption, {
serverTypeOptions,
} from "@mcl/components/server-options/ServerTypeOption.jsx";
import CpuOption, {
cpuOptions,
} from "@mcl/components/server-options/CpuOption.jsx";
import MemoryOption, {
memoryOptions,
} from "@mcl/components/server-options/MemoryOption.jsx";
const defaultServer = { const defaultServer = {
version: "latest", version: "latest",
serverType: "VANILLA", serverType: serverTypeOptions[0],
memory: "512", cpu: cpuOptions[0],
memory: memoryOptions[2], // 1.5GB
}; };
export default function Create() { export default function Create() {
const [spec, setSpec] = useState(defaultServer); const [spec, setSpec] = useState(defaultServer);
const nav = useNavigate(); const nav = useNavigate();
const versionList = useVersionList();
const [versions, setVersions] = useState(["latest"]);
const createServer = useCreateServer(spec); const createServer = useCreateServer(spec);
const updateSpec = (attr, val) => { const updateSpec = (attr, val) => {
@ -30,16 +40,6 @@ export default function Create() {
setSpec(s); setSpec(s);
}; };
useEffect(() => {
if (!versionList.data) return;
setVersions([
"latest",
...versionList.data.versions
.filter(({ type: releaseType }) => releaseType === "release")
.map(({ id }) => id),
]);
}, [versionList.data]);
const coreUpdate = (attr) => (e) => updateSpec(attr, e.target.value); const coreUpdate = (attr) => (e) => updateSpec(attr, e.target.value);
async function upsertSpec() { async function upsertSpec() {
@ -67,54 +67,15 @@ export default function Create() {
sx={{ width: "100%", maxWidth: "600px", margin: "auto" }} sx={{ width: "100%", maxWidth: "600px", margin: "auto" }}
> >
<FormControl fullWidth sx={{ mt: "2rem", display: "flex", gap: ".5rem" }}> <FormControl fullWidth sx={{ mt: "2rem", display: "flex", gap: ".5rem" }}>
<TextField <NameOption onChange={coreUpdate("name")} />
label="Name" <HostOption onChange={coreUpdate("host")} />
onChange={coreUpdate("name")} <VersionOption value={spec.version} onChange={coreUpdate("version")} />
helperText="Example: My Survival World" <ServerTypeOption
defaultValue={spec.name}
FormHelperTextProps={{ sx: { ml: 0 } }}
required
/>
<TextField
label="Host"
onChange={coreUpdate("host")}
helperText="Example: host.mydomain.com"
FormHelperTextProps={{ sx: { ml: 0 } }}
required
/>
<TextField
label="Version"
onChange={coreUpdate("version")}
value={spec.version}
select
required
SelectProps={{ MenuProps: { sx: { maxHeight: "20rem" } } }}
>
{versions.map((v, k) => (
<MenuItem value={v} key={k}>
{v}
</MenuItem>
))}
</TextField>
<TextField
label="Server Type"
onChange={coreUpdate("serverType")}
value={spec.serverType} value={spec.serverType}
select onChange={coreUpdate("serverType")}
required
>
<MenuItem value={"VANILLA"}>Vanilla</MenuItem>
<MenuItem value={"FABRIC"}>Fabric</MenuItem>
<MenuItem value={"PAPER"}>Paper</MenuItem>
<MenuItem value={"SPIGOT"}>Spigot</MenuItem>
</TextField>
<TextField
label="Memory"
onChange={coreUpdate("memory")}
defaultValue={spec.memory}
required
/> />
<CpuOption value={spec.cpu} onChange={coreUpdate("cpu")} />
<MemoryOption value={spec.memory} onChange={coreUpdate("memory")} />
<Button onClick={upsertSpec} variant="contained"> <Button onClick={upsertSpec} variant="contained">
Create Create
</Button> </Button>