diff --git a/app/api.py b/app/api.py
index 9f6b1db..649d9c2 100644
--- a/app/api.py
+++ b/app/api.py
@@ -313,7 +313,7 @@ def modrinth_search():
f"https://api.modrinth.com/v2/search",
params={
"query": query,
- "facets": f'[["project_type:{category}"],["versions:{version}"]]',
+ "facets": f'[["project_type:{category}"],["categories:{server_type}"],["versions:{version}"]]',
"limit": 10
}
)
diff --git a/app/docker_utils.py b/app/docker_utils.py
index 3b3f295..e139217 100644
--- a/app/docker_utils.py
+++ b/app/docker_utils.py
@@ -89,6 +89,7 @@ def start_server(username):
environment = {
"EULA": "TRUE",
"SERVER_PORT": ports[0],
+ "ENABLE_RCON": "TRUE",
"MOTD": f"Serwer użytkownika §9{username}",
"TYPE": server_type,
"VERSION": server_version,
diff --git a/app/static/js/config.js b/app/static/js/config.js
new file mode 100644
index 0000000..aaf9ee4
--- /dev/null
+++ b/app/static/js/config.js
@@ -0,0 +1,52 @@
+function loadConfig() {
+ fetch(`/api/config?username=${username}`)
+ .then(response => response.json())
+ .then(data => {
+ const cfg = data.config;
+ document.getElementById("server-type").value = data.type;
+ document.getElementById("server-version").value = data.version;
+ document.getElementById("max-players").value = cfg["max-players"];
+ document.getElementById("pvp").checked = cfg["pvp"];
+ document.getElementById("difficulty").value = cfg["difficulty"];
+ document.getElementById("online-mode").checked = cfg["online-mode"];
+ document.getElementById("spawn-monsters").checked = cfg["spawn-monsters"];
+ document.getElementById("spawn-animals").checked = cfg["spawn-animals"];
+ document.getElementById("allow-nether").checked = cfg["allow-nether"];
+ document.getElementById("max-build-height").value = cfg["max-build-height"];
+ document.getElementById("view-distance").value = cfg["view-distance"];
+ })
+ .catch(err => {
+ console.error("Błąd wczytywania konfiguracji: ", err);
+ alert("Nie udało się załadować konfiguracji serwera.");
+ });
+}
+
+document.querySelector('[onclick="showTab(\'config\')"]').addEventListener('click', loadConfig);
+
+function saveConfig() {
+ const config = {
+ type: document.getElementById("server-type").value,
+ version: document.getElementById("server-version").value,
+ max_players: document.getElementById("max-players").value,
+ pvp: document.getElementById("pvp").checked,
+ difficulty: document.getElementById("difficulty").value,
+ online_mode: document.getElementById("online-mode").checked,
+ spawn_monsters: document.getElementById("spawn-monsters").checked,
+ spawn_animals: document.getElementById("spawn-animals").checked,
+ allow_nether: document.getElementById("allow-nether").checked,
+ max_build_height: document.getElementById("max-build-height").value,
+ view_distance: document.getElementById("view-distance").value
+ };
+
+ fetch('/api/config', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username, config })
+ }).then(res => res.json()).then(data => {
+ if (data.success) {
+ alert("Konfiguracja została zapisana!");
+ } else {
+ alert("Błąd zapisywania konfiguracji.");
+ }
+ });
+}
\ No newline at end of file
diff --git a/app/static/js/console.js b/app/static/js/console.js
new file mode 100644
index 0000000..b8fedbf
--- /dev/null
+++ b/app/static/js/console.js
@@ -0,0 +1,23 @@
+function sendCommand() {
+ const input = $("console-command");
+ const command = input.value.trim();
+ if (!command) return;
+
+ fetch('/api/command', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username, command })
+ }).then(res => {
+ if (!res.ok) throw new Error("Nie udało się wysłać komendy.");
+ input.value = '';
+ }).catch(err => {
+ alert("Błąd wysyłania komendy.");
+ console.error(err);
+ });
+}
+
+function loadLogs() {
+ fetch(`/api/logs?username=${username}`)
+ .then(r => r.json())
+ .then(data => { $("console-log").textContent = data.logs; });
+}
\ No newline at end of file
diff --git a/app/static/js/controls.js b/app/static/js/controls.js
new file mode 100644
index 0000000..ccacd78
--- /dev/null
+++ b/app/static/js/controls.js
@@ -0,0 +1,19 @@
+function sendAction(action) {
+ fetch(`/api/${action}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username })
+ }).then(r => r.json()).then(console.log);
+}
+
+function deleteServer() {
+ if (!confirm("Na pewno chcesz usunąć swój serwer? Tej operacji nie można cofnąć!")) return;
+ fetch('/api/delete', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username })
+ })
+ .then(res => res.ok ? res.json() : res.text().then(t => { throw new Error(t); }))
+ .then(data => { alert(data.message); location.reload(); })
+ .catch(err => { alert("Błąd usuwania serwera."); console.error(err); });
+}
\ No newline at end of file
diff --git a/app/static/js/files.js b/app/static/js/files.js
new file mode 100644
index 0000000..8036b12
--- /dev/null
+++ b/app/static/js/files.js
@@ -0,0 +1,123 @@
+function loadFileList(path = '') {
+ currentPath = path;
+ $("current-path").textContent = "/" + path;
+ fetch(`/api/files?username=${username}&path=${encodeURIComponent(path)}`)
+ .then(r => r.json())
+ .then(data => {
+ const list = $("file-list");
+ list.innerHTML = '';
+ if (path) {
+ list.innerHTML += `
⬅️ ..`;
+ }
+ data.sort((a, b) => a.name.localeCompare(b.name));
+ data.forEach(entry => {
+ const itemPath = path ? `${path}/${entry.name}` : entry.name;
+ const html = entry.is_dir
+ ? `📁 ${entry.name}
+
+
+
+ `
+ : `📄 ${entry.name}
+
+
+
+
+
+
+ `;
+ list.innerHTML += html;
+ });
+ });
+}
+
+function deleteItem(path) {
+ if (!confirm(`Czy na pewno chcesz usunąć: ${path}?`)) return;
+
+ fetch('/api/files/delete', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ username, path })
+ })
+ .then(res => res.json())
+ .then(data => {
+ if (data.success) {
+ loadFileList(currentPath);
+ } else {
+ alert("Błąd podczas usuwania: " + (data.error || "Nieznany"));
+ }
+ })
+ .catch(err => {
+ console.error(err);
+ alert("Błąd połączenia z serwerem.");
+ });
+}
+
+document.querySelector('[onclick="showTab(\'files\')"]').addEventListener('click', () => loadFileList());
+
+const dropZone = document.getElementById('drop-zone');
+const fileInput = document.getElementById('file-input');
+const progressBar = document.getElementById('progress-bar');
+const progressWrapper = document.getElementById('upload-progress');
+
+dropZone.addEventListener('click', () => fileInput.click());
+
+dropZone.addEventListener('dragover', e => {
+ e.preventDefault();
+ dropZone.classList.add('dragover');
+});
+
+dropZone.addEventListener('dragleave', e => {
+ e.preventDefault();
+ dropZone.classList.remove('dragover');
+});
+
+dropZone.addEventListener('drop', e => {
+ e.preventDefault();
+ dropZone.classList.remove('dragover');
+ handleFiles(e.dataTransfer.files);
+});
+
+fileInput.addEventListener('change', () => {
+ handleFiles(fileInput.files);
+});
+
+function handleFiles(files) {
+ if (!files.length) return;
+
+ const formData = new FormData();
+ for (const file of files) {
+ formData.append('files', file);
+ }
+ formData.append('username', username);
+ formData.append('path', currentPath);
+
+ progressWrapper.classList.remove('hidden');
+ progressBar.style.width = '0%';
+
+ const xhr = new XMLHttpRequest();
+ xhr.open('POST', `/api/files/upload?username=${username}&path=${encodeURIComponent(currentPath)}`);
+
+ xhr.upload.addEventListener('progress', e => {
+ if (e.lengthComputable) {
+ const percent = (e.loaded / e.total) * 100;
+ progressBar.style.width = `${percent}%`;
+ }
+ });
+
+ xhr.onload = () => {
+ progressWrapper.classList.add('hidden');
+ if (xhr.status === 200) {
+ loadFileList(currentPath);
+ } else {
+ alert("Upload się nie udał.");
+ }
+ };
+
+ xhr.onerror = () => {
+ progressWrapper.classList.add('hidden');
+ alert("Upload się nie udał.");
+ };
+
+ xhr.send(formData);
+}
\ No newline at end of file
diff --git a/app/static/js/mods.js b/app/static/js/mods.js
index 0d5a016..75bf257 100644
--- a/app/static/js/mods.js
+++ b/app/static/js/mods.js
@@ -1,52 +1,51 @@
- function searchMods() {
- const query = document.getElementById("mod-search").value;
- fetch('/api/config')
- .then(response => response.json())
- .then(configData => {
- console.log(configData);
- if (configData.success) {
- const serverType = configData.type;
- const serverVersion = configData.version;
- if (serverType && serverVersion) {
- fetch(`/api/modrinth/search?query=${encodeURIComponent(query)}&type=${serverType}&version=${serverVersion}`)
- .then(r => r.json())
- .then(data => {
- const results = document.getElementById("mod-results");
- results.innerHTML = "";
- data.hits.forEach(mod => {
- const modEl = document.createElement("div");
- modEl.innerHTML = `
- ${mod.title} - Zainstaluj
`;
- results.appendChild(modEl);
- });
+function searchMods() {
+ const query = document.getElementById("mod-search").value;
+ fetch('/api/config')
+ .then(response => response.json())
+ .then(configData => {
+ console.log(configData);
+ if (configData.success) {
+ const serverType = configData.type;
+ const serverVersion = configData.version;
+ if (serverType && serverVersion) {
+ fetch(`/api/modrinth/search?query=${encodeURIComponent(query)}&type=${serverType}&version=${serverVersion}`)
+ .then(r => r.json())
+ .then(data => {
+ const results = document.getElementById("mod-results");
+ results.innerHTML = "";
+ data.hits.forEach(mod => {
+ const modEl = document.createElement("div");
+ modEl.innerHTML = `
+ ${mod.title} - Zainstaluj
`;
+ results.appendChild(modEl);
});
- } else {
- console.error('Server type or version not available');
- }
+ });
} else {
- console.error('Server config not found');
+ console.error('Server type or version not available');
}
- })
- .catch(err => {
- console.error('Error fetching server config:', err);
- });
- }
-
- function installMod(projectId) {
- const serverType = document.getElementById("server-type").value;
- const username = "{{ username }}";
- fetch('/api/modrinth/download', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ project_id: projectId, username, type: serverType })
- })
- .then(r => r.json())
- .then(data => {
- if (data.success) {
- alert(`Zainstalowano: ${data.file}`);
- loadFileList();
} else {
- alert("Nie udało się zainstalować moda.");
+ console.error('Server config not found');
}
+ })
+ .catch(err => {
+ console.error('Error fetching server config:', err);
});
- }
\ No newline at end of file
+}
+
+function installMod(projectId) {
+ const serverType = document.getElementById("server-type").value;
+ fetch('/api/modrinth/download', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ project_id: projectId, username, type: serverType })
+ })
+ .then(r => r.json())
+ .then(data => {
+ if (data.success) {
+ alert(`Zainstalowano: ${data.file}`);
+ loadFileList();
+ } else {
+ alert("Nie udało się zainstalować moda.");
+ }
+ });
+}
\ No newline at end of file
diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html
index 0b6ceff..8e26203 100644
--- a/app/templates/dashboard.html
+++ b/app/templates/dashboard.html
@@ -1,17 +1,16 @@
{% extends "layout.html" %}
{% block content %}
-
Twój serwer Minecraft
-
-
+
+
@@ -117,7 +116,6 @@
@@ -128,6 +126,12 @@
+
+
+
+
+
+