Skip to content

Commit d8417c9

Browse files
Merge pull request #15 from T0ine34/0.1.1-dev
This PR represents a major architectural refactoring and version update to "0.1.1 dev". The changes transform the application from a monolithic Flask-based server manager into a modular, event-driven system with a sophisticated inter-process communication bus. Key changes include: Complete architectural redesign with event-driven communication using a custom bus system Modular structure separating user interfaces, Minecraft server management, and core functionality Enhanced client-side interface with improved TypeScript structure and server management capabilities
2 parents 139131b + a6cb033 commit d8417c9

70 files changed

Lines changed: 4269 additions & 1127 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build_package.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
sys.argv.pop(idx) # remove --version
1717
sys.argv.pop(idx) # remove version value
1818

19-
print(f"{sys.executable} -m build {' '.join(sys.argv[1:])}")
20-
subprocess.run([sys.executable, "-m", "build"] + sys.argv[1:],
21-
check=True, stderr=sys.stderr, stdout=sys.stdout)
19+
cmd = [sys.executable, "-m", "build"] + sys.argv[1:]
20+
print(" ".join(cmd)) # Print the command for debugging
21+
subprocess.run(cmd, check=True, stderr=sys.stderr, stdout=sys.stdout)

client/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
@use './common.scss';
2-
@use './header.scss';
1+
@use '../common.scss';
32

43
main {
54
text-align: center;
Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
import ensure_token from "./ensure_token.js";
2-
import Cookies from "./cookie.js";
3-
import API from "./api.js";
1+
import ensure_token from "../scripts/ensure_token.js";
2+
import API from "../scripts/api.js";
43

54
ensure_token();
65

76
// fill the span #name with the username
87
API.get_user_info().then((response) => {
8+
if (!response) {
9+
console.error("No user info found.");
10+
alert("An error occurred while fetching user information.");
11+
return;
12+
}
913
console.log("User info response:", response);
1014
const {username} = response;
1115
const name = document.getElementById("name") as HTMLSpanElement;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</head>
88

99
<body>
10-
{{ insert("header") }}
10+
{{ insert("header/header") }}
1111
<main>
1212
<h1>Account Management</h1>
1313
<div id="account-info">

client/src/common.scss

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ main {
2626
}
2727

2828
button,
29-
input {
29+
input,
30+
select {
3031
background: $mc-button-bg-active;
3132
color: $mc-font-color;
3233
border: 2px solid $mc-button-border;
@@ -49,7 +50,6 @@ input {
4950
&.active {
5051
background: $mc-button-bg-active;
5152
border-color: $mc-button-border-hover;
52-
border-width: 3px;
5353
}
5454

5555
&[type="text"],

client/src/dashboard.template.html

Lines changed: 0 additions & 19 deletions
This file was deleted.

client/src/dashboard.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
@use './common.scss';
2-
@use './header.scss';
3-
1+
@use '../common.scss';
42

53
#server-list {
64
display: flex;
@@ -28,3 +26,23 @@
2826
}
2927
}
3028
}
29+
30+
#create-server-form {
31+
position: fixed;
32+
top: 0;
33+
left: 0;
34+
width: 50%;
35+
background-color: rgba(0, 0, 0, 0.75);
36+
display: block;
37+
align-items: center;
38+
z-index: 1000;
39+
margin-left: 20%;
40+
margin-top: 10%;
41+
padding: 5%;
42+
43+
& > * {
44+
display: block;
45+
width: 100%;
46+
margin: 20px 0;
47+
}
48+
}

client/src/dashboard/dashboard.ts

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import ensure_token from "../scripts/ensure_token.js";
2+
import API from "../scripts/api.js";
3+
import { AccessLevel, ServerInfo } from "../scripts/types.js";
4+
5+
ensure_token();
6+
7+
const server_list = document.getElementById("server-list") as HTMLUListElement;
8+
9+
10+
const status_colors: { [key: string]: string } = {
11+
"STOPPED" : "darkgray",
12+
"STARTING" : "orange",
13+
"RUNNING" : "lightgreen",
14+
"STOPPING" : "orange",
15+
"ERROR" : "red",
16+
"UNKNOWN" : "darkgray"
17+
};
18+
19+
async function get_user_access_level(): Promise<AccessLevel> {
20+
const user = await API.get_user_info();
21+
if (user) {
22+
return user.access_level;
23+
}
24+
return AccessLevel.USER; // Default access level if user not found
25+
}
26+
27+
28+
// fill the server list with the servers
29+
async function fill_server_list() {
30+
// clear the server list
31+
server_list.innerHTML = "";
32+
const servers = await API.get_server_list();
33+
34+
if (servers) {
35+
for (const server of servers) {
36+
const row = document.createElement("button");
37+
row.className = "server";
38+
let color : string = status_colors[server.status.toUpperCase()] || "darkgray";
39+
let online_text : string = server.status.charAt(0).toUpperCase() + server.status.slice(1).toLowerCase();
40+
41+
row.innerHTML = `
42+
<div class="server-name" style="color: ${color}">${server.name}</div>
43+
<div class="server-mc-version">minecraft ${server.mc_version}</div>
44+
`;
45+
46+
if (server.type != "vanilla") {
47+
row.innerHTML += `
48+
<div class="server-modloader-version">${server.type} ${server.modloader_version}</div>
49+
`;
50+
}
51+
else {
52+
row.innerHTML += `
53+
<div class="server-modloader-version"></div>
54+
`;
55+
}
56+
row.innerHTML +=
57+
`
58+
<div class="server-status" style="color: ${color}">${online_text}</div>
59+
`;
60+
row.addEventListener("click", () => {
61+
// open the server page
62+
window.location.href = `/app/server?s=${server.name}`;
63+
});
64+
server_list.appendChild(row);
65+
}
66+
}
67+
}
68+
69+
70+
function clear_select_options(selectElement: HTMLSelectElement) {
71+
selectElement.innerHTML = "<option value='void'></option>";
72+
}
73+
74+
async function update_modloader_versions(mc_version : string) {
75+
const modloaderVersionInput = document.getElementById('modloader-version') as HTMLSelectElement;
76+
const modloaderVersions = await API.get_forge_versions(mc_version);
77+
modloaderVersionInput.innerHTML = modloaderVersions.map(version => `<option value="${version}">${version}</option>`).join('');
78+
}
79+
80+
async function init_create_server_form() {
81+
const serverType = document.getElementById('server-type') as HTMLSelectElement;
82+
const modloaderGroup = document.getElementById('modloader-version-group') as HTMLDivElement;
83+
serverType.addEventListener('change', function() {
84+
if (serverType.value !== 'vanilla') {
85+
modloaderGroup.style.display = '';
86+
} else {
87+
modloaderGroup.style.display = 'none';
88+
}
89+
});
90+
// Trigger on page load
91+
if (serverType.value !== 'vanilla') {
92+
modloaderGroup.style.display = '';
93+
}
94+
95+
const mcVersionInput = document.getElementById('mc-version') as HTMLSelectElement;
96+
const mcVersions = await API.get_mc_versions();
97+
mcVersionInput.innerHTML = mcVersions.map(version => `<option value="${version}">${version}</option>`).join('');
98+
mcVersionInput.addEventListener('change', async function() {
99+
const selectedVersion = mcVersionInput.value;
100+
if (selectedVersion && selectedVersion !== 'void') {
101+
await update_modloader_versions(selectedVersion);
102+
} else {
103+
clear_select_options(document.getElementById('modloader-version') as HTMLSelectElement);
104+
}
105+
});
106+
107+
const serverPathInput = document.getElementById('server-path') as HTMLSelectElement;
108+
const serverPaths = await API.get_mc_server_dirs();
109+
serverPathInput.innerHTML = serverPaths.map(path => `<option value="${path}">${path}</option>`).join('');
110+
}
111+
112+
113+
function show_create_server_form() {
114+
const create_server_form = document.getElementById("create-server-form") as HTMLDivElement;
115+
create_server_form.style.display = "block";
116+
}
117+
function hide_create_server_form() {
118+
const create_server_form = document.getElementById("create-server-form") as HTMLDivElement;
119+
create_server_form.style.display = "none";
120+
}
121+
122+
async function on_create_server_button() {
123+
const access_level = await get_user_access_level();
124+
if (access_level >= AccessLevel.OPERATOR) {
125+
show_create_server_form();
126+
const create_server_form = document.getElementById("create-server-form") as HTMLFormElement;
127+
create_server_form.addEventListener("submit", async (event) => {
128+
event.preventDefault();
129+
const server_name = (document.getElementById("server-name") as HTMLInputElement).value;
130+
const server_type = (document.getElementById("server-type") as HTMLSelectElement).value;
131+
const server_path = (document.getElementById("server-path") as HTMLInputElement).value;
132+
const autostart = (document.getElementById("autostart") as HTMLInputElement).checked;
133+
const ram = (document.getElementById("ram") as HTMLInputElement).value;
134+
const mc_version = (document.getElementById("mc-version") as HTMLInputElement).value;
135+
const modloader_version = (document.getElementById("modloader-version") as HTMLInputElement).value;
136+
137+
const server_info: ServerInfo = {
138+
name: server_name,
139+
type: server_type,
140+
path: server_path,
141+
autostart: autostart,
142+
ram: parseInt(ram, 10), // Convert to integer
143+
mc_version: mc_version,
144+
modloader_version: modloader_version,
145+
started_at: null,
146+
};
147+
const success = await API.create_server(server_info);
148+
if (success) {
149+
hide_create_server_form();
150+
fill_server_list(); // Refresh the server list
151+
}
152+
});
153+
}
154+
else {
155+
alert("You do not have permission to create a server.");
156+
}
157+
}
158+
159+
async function init_misc() {
160+
const userInfo = await API.get_user_info();
161+
if (userInfo && userInfo.access_level >= AccessLevel.OPERATOR) {
162+
const createServerButton = document.createElement("button");
163+
createServerButton.id = "create-server-button";
164+
createServerButton.className = "button";
165+
createServerButton.innerText = "Create Server";
166+
createServerButton.addEventListener("click", on_create_server_button);
167+
const main = document.querySelector("main") as HTMLDivElement;
168+
main.appendChild(createServerButton);
169+
170+
const createServerCancelButton = document.getElementById("create-server-cancel") as HTMLButtonElement;
171+
createServerCancelButton.addEventListener("click", hide_create_server_form);
172+
}
173+
else{
174+
console.log(`User does not have permission to create a server (access level: ${userInfo?.access_level.valueOf()} < AccessLevel.OPERATOR (${AccessLevel.OPERATOR.valueOf()})).`);
175+
}
176+
}
177+
178+
179+
document.addEventListener("DOMContentLoaded", async () => {
180+
await init_create_server_form();
181+
await fill_server_list();
182+
await init_misc();
183+
});

0 commit comments

Comments
 (0)