[FEATURE] Cleaned up terminal display
This commit is contained in:
parent
4959d6c1fe
commit
a804a6e98b
7 changed files with 36 additions and 25 deletions
|
@ -26,9 +26,13 @@ export async function webConsoleLogs(socket) {
|
||||||
|
|
||||||
const log = new k8s.Log(kc);
|
const log = new k8s.Log(kc);
|
||||||
const logStream = new stream.PassThrough();
|
const logStream = new stream.PassThrough();
|
||||||
logStream.on("data", (chunk) =>
|
var logstreamBuffer = "";
|
||||||
socket.emit("push", Buffer.from(chunk).toString()),
|
logStream.on("data", (chunk) => {
|
||||||
);
|
const bufferString = Buffer.from(chunk).toString();
|
||||||
|
if (!bufferString.includes("\n")) return (logstreamBuffer += bufferString);
|
||||||
|
const clientChunks = `${logstreamBuffer}${bufferString}`.split("\n");
|
||||||
|
for (var c of clientChunks) socket.emit("push", c);
|
||||||
|
});
|
||||||
log
|
log
|
||||||
.log(namespace, mcsPods[0], containerName, logStream, {
|
.log(namespace, mcsPods[0], containerName, logStream, {
|
||||||
follow: true,
|
follow: true,
|
||||||
|
|
|
@ -67,7 +67,7 @@ function createBackupSecret(serverSpec) {
|
||||||
`endpoint = ${backupHost}`,
|
`endpoint = ${backupHost}`,
|
||||||
`acl = private`,
|
`acl = private`,
|
||||||
`no_check_bucket = true`,
|
`no_check_bucket = true`,
|
||||||
`no_check_container = true`
|
`no_check_container = true`,
|
||||||
].join("\n");
|
].join("\n");
|
||||||
backupYaml.data["rclone.conf"] = Buffer.from(rcloneConfig).toString("base64");
|
backupYaml.data["rclone.conf"] = Buffer.from(rcloneConfig).toString("base64");
|
||||||
return backupYaml;
|
return backupYaml;
|
||||||
|
|
|
@ -17,7 +17,6 @@ const cairoAuthenticate = async (token) => {
|
||||||
// Middleware
|
// Middleware
|
||||||
const cairoAuthHandler = (req, res, next) => {
|
const cairoAuthHandler = (req, res, next) => {
|
||||||
if (!req.token) return res.status(401).send("Cairo auth required!");
|
if (!req.token) return res.status(401).send("Cairo auth required!");
|
||||||
VERB("AUTH", `${MCL_CAIRO_URL}/api/user/info`);
|
|
||||||
cairoAuthenticate(req.token)
|
cairoAuthenticate(req.token)
|
||||||
.then((authData) => (req.cairoId = authData.id))
|
.then((authData) => (req.cairoId = authData.id))
|
||||||
.then(() => next())
|
.then(() => next())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "minecluster",
|
"name": "minecluster",
|
||||||
"version": "0.0.1-alpha.0",
|
"version": "0.0.1-alpha.1",
|
||||||
"description": "Minecraft Server management using Kubernetes",
|
"description": "Minecraft Server management using Kubernetes",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
"start": "node dist/app.js",
|
"start": "node dist/app.js",
|
||||||
"dev:server": "nodemon dist/app.js",
|
"dev:server": "nodemon dist/app.js",
|
||||||
"dev:react": "vite",
|
"dev:react": "vite",
|
||||||
"kub": "nodemon lib/k8s.js",
|
"lint": "npx prettier -w src lib vite.config.js",
|
||||||
"start:dev": "concurrently -k \"MCL_DEV_PORT=52025 npm run dev:server\" \" MCL_VITE_DEV_PORT=52000 MCL_VITE_BACKEND_URL=http://localhost:52025 npm run dev:react\" -n s,v -p -c green,yellow",
|
"start:dev": "concurrently -k \"MCL_DEV_PORT=52025 npm run dev:server\" \" MCL_VITE_DEV_PORT=52000 MCL_VITE_BACKEND_URL=http://localhost:52025 npm run dev:react\" -n s,v -p -c green,yellow",
|
||||||
"start:dev:garden": "concurrently -k \"npm run dev:server\" \"npm run dev:react\" -n s,v -p -c green,yellow"
|
"start:dev:garden": "concurrently -k \"npm run dev:server\" \"npm run dev:react\" -n s,v -p -c green,yellow"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState } from "react";
|
||||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
|
@ -19,22 +19,19 @@ export default function RconDialog(props) {
|
||||||
const { server, open, dialogToggle } = props;
|
const { server, open, dialogToggle } = props;
|
||||||
const { name: serverName, id: serverId } = server ?? {};
|
const { name: serverName, id: serverId } = server ?? {};
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const fullScreen = useMediaQuery(theme.breakpoints.down("sm"));
|
const fullScreen = useMediaQuery(theme.breakpoints.down("md"));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
sx={
|
fullWidth
|
||||||
fullScreen
|
maxWidth="lg"
|
||||||
? {}
|
|
||||||
: { "& .mcl-MuiDialog-paper": { width: "80%", maxHeight: 555 } }
|
|
||||||
}
|
|
||||||
maxWidth="xs"
|
|
||||||
open={open}
|
open={open}
|
||||||
fullScreen={fullScreen}
|
fullScreen={fullScreen}
|
||||||
|
PaperProps={!fullScreen ? { sx: { height: "60%" } } : undefined}
|
||||||
>
|
>
|
||||||
<Toolbar sx={{ display: { sm: "none" } }} />
|
<Toolbar sx={{ display: { md: "none" } }} />
|
||||||
<DialogTitle>RCON - {serverName}</DialogTitle>
|
<DialogTitle>RCON - {serverName}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent sx={{ height: "100%" }}>
|
||||||
<RconView serverId={serverId} />
|
<RconView serverId={serverId} />
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from "react";
|
||||||
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 TextField from "@mui/material/TextField";
|
import TextField from "@mui/material/TextField";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
import RconSocket from "./RconSocket.js";
|
import RconSocket from "./RconSocket.js";
|
||||||
import "@mcl/css/rcon.css";
|
import "@mcl/css/rcon.css";
|
||||||
|
|
||||||
|
@ -39,16 +40,27 @@ export default function RconView(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box sx={{ height: "100%", display: "flex", flexWrap: "wrap" }}>
|
||||||
<div className="rconLogsWrapper" ref={logsRef}>
|
<Box
|
||||||
|
className="rconLogsWrapper"
|
||||||
|
ref={logsRef}
|
||||||
|
style={{
|
||||||
|
padding: "1rem",
|
||||||
|
backgroundColor: "rgba(0,0,0,.815)",
|
||||||
|
color: "white",
|
||||||
|
borderRadius: "4px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
{logs.map((v, k) => (
|
{logs.map((v, k) => (
|
||||||
<Box key={k}>
|
<Box key={k}>
|
||||||
{v}
|
<Typography variant="subtitle2">{v}</Typography>
|
||||||
<br />
|
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</div>
|
</Box>
|
||||||
<Box className="rconActions">
|
<Box
|
||||||
|
className="rconActions"
|
||||||
|
sx={{ marginTop: "auto", paddingTop: "1rem" }}
|
||||||
|
>
|
||||||
<TextField
|
<TextField
|
||||||
id="outlined-basic"
|
id="outlined-basic"
|
||||||
label="Command"
|
label="Command"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
.rconLogsWrapper {
|
.rconLogsWrapper {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
max-height: 20rem;
|
max-height: calc(100% - 6rem);
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
.rconActions {
|
.rconActions {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue