mc-server-manager/api/app/index.html

189 lines
7.2 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>MC-Server-Manager</title>
<style>
.server-listing {
border: 3px solid black;
padding: 0.5em;
}
.server-listing + .server-listing {
margin-top: 10px;
}
.server-listing h3 {
margin: 0 0 0.5em 0;
}
.server-listing p {
margin: 0.5em 0 0.5em 0;
}
</style>
</head>
<body>
<h1>MC-Server-Manager</h1>
<p>
On this site, you'll see a list of available servers. If you've got the
correct credentials, you may request to turn on a server if it has
automatically shut off due to inactivity.
</p>
<hr>
<div id="servers-container">
<!-- This container will be populated with the list of available servers. -->
</div>
<dialog id="request-dialog">
<!-- This dialog opens when the user clicks to request to start a server. -->
<p>
Request to start the selected server.
</p>
<div style="margin-bottom: 0.5em">
<label for="client-key-input">Enter your client key:</label>
<input type="password" name="client-key" id="client-key-input"/>
</div>
<div style="margin-bottom: 0.5em">
<label for="server-identifier-input">Server Identifier</label>
<input type="text" name="server-identifier" id="server-identifier-input" disabled/>
</div>
<button onclick="submitServerRequest()">Submit</button>
<button onclick="closeRequestDialog()">Cancel</button>
</dialog>
<dialog id="message-dialog">
<!-- This dialog is used to show generic messages in the <p> tag below. -->
<p></p>
<button onclick="document.getElementById('message-dialog').close()">Close</button>
</dialog>
<script>
async function getServers() {
const response = await fetch("/api/servers");
return await response.json();
}
function makeServerListingDiv(serverObj) {
const div = document.createElement("div");
div.className = "server-listing";
const header = document.createElement("h3");
header.innerText = serverObj.name;
div.appendChild(header);
const description = document.createElement("p");
description.innerText = serverObj.description;
div.appendChild(description);
const playersList = document.createElement("p");
let text = "Players: ";
if (serverObj.playerNames.length == 0) {
text += "None";
} else {
for (let i = 0; i < serverObj.playerNames.length; i++) {
text += serverObj.playerNames[i];
if (i + 1 < serverObj.playerNames.length) {
text += ", ";
}
}
}
playersList.innerText = text;
div.appendChild(playersList);
const onlineIndicator = document.createElement("p");
onlineIndicator.innerText = serverObj.online ? "Online" : "Offline";
if (serverObj.online) {
onlineIndicator.style = "color: green";
} else {
onlineIndicator.style = "color: red";
}
div.appendChild(onlineIndicator);
if (serverObj.startupRequested) {
const startupRequestedIndicator = document.createElement("p");
startupRequestedIndicator.innerText = "Startup has been requested. Server should start shortly.";
startupRequestedIndicator.style = "font-style: italic";
div.appendChild(startupRequestedIndicator);
}
if (!serverObj.online && !serverObj.startupRequested) {
const requestButton = document.createElement("button");
requestButton.innerText = "Request to start this server";
requestButton.addEventListener("click", () => openRequestDialog(serverObj.identifier));
div.appendChild(requestButton);
}
return div;
}
function openRequestDialog(serverIdentifier) {
const serverIdentifierInput = document.getElementById("server-identifier-input");
serverIdentifierInput.value = serverIdentifier;
const dialog = document.getElementById("request-dialog");
dialog.showModal();
}
function closeRequestDialog() {
const dialog = document.getElementById("request-dialog");
dialog.close();
const clientKeyInput = document.getElementById("client-key-input");
clientKeyInput.value = "";
}
async function submitServerRequest() {
const serverIdentifier = document.getElementById("server-identifier-input").value;
const clientKey = document.getElementById("client-key-input").value;
if (typeof(serverIdentifier) !== "string" || typeof(clientKey) !== "string") {
return;
}
const dialog = document.getElementById("request-dialog");
closeRequestDialog();
try {
const response = await fetch(`/api/servers/${serverIdentifier}/requests`, {
method: "POST",
headers: {
"X-Client-Key": clientKey
}
});
if (!response.ok) {
showMessageDialog("The request was rejected: " + response.status);
} else {
showMessageDialog("The request was submitted.");
}
} catch (error) {
showMessageDialog("Failed to submit request: " + error);
}
}
function showMessageDialog(message) {
const dialog = document.getElementById("message-dialog");
const p = dialog.children[0];
p.innerText = message;
dialog.showModal();
window.setTimeout(() => dialog.close(), 3000);
}
async function refreshServers() {
const containerDiv = document.getElementById("servers-container");
try {
const servers = await getServers();
containerDiv.replaceChildren(...servers.map(s => makeServerListingDiv(s)));
} catch (error) {
console.error("Failed to fetch servers from the API.", error);
const errorMessage = document.createElement("p");
errorMessage.innerText = "Failed to fetch servers from the API. " + error;
errorMessage.style = "color: red";
containerDiv.replaceChildren(errorMessage);
}
}
refreshServers();
window.setInterval(refreshServers, 3000);
// Add a key listener to the dialog's password field, so pressing ENTER submits the form.
const keyInput = document.getElementById("client-key-input");
keyInput.addEventListener("keydown", (ev) => {
if (ev.code === "Enter") {
submitServerRequest();
}
})
</script>
</body>
</html>