Formatting

This commit is contained in:
Carsten Graf
2025-07-12 17:06:42 +02:00
parent 337e12078b
commit 3b4c5d2b92
6 changed files with 1651 additions and 1462 deletions

View File

@@ -1,11 +1,11 @@
<!DOCTYPE html>
<!doctype html>
<html lang="de">
<head>
<!-- Meta Tags -->
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/x-icon" href="/pictures/favicon.ico">
<link rel="icon" type="image/x-icon" href="/pictures/favicon.ico" />
<!-- Stylesheets -->
<link rel="stylesheet" href="settings.css" />
<title>Ninjacross Timer - Einstellungen</title>
@@ -103,7 +103,7 @@
</div>
</form>
</div>
<!-- Times Management Section -->
<div class="section">
<h2>🏆 Zeiten verwalten</h2>
@@ -143,8 +143,14 @@
<!-- WiFi Configuration Section -->
<div class="section" id="wifiSection">
<h2>📡 WLAN-Konfiguration</h2>
<div id="wifiRestrictionNotice" class="restriction-notice" style="display: none;">
🔒 WLAN-Konfiguration ist nur mit Lizenz Level 3 oder höher verfügbar. Aktuelle Lizenz: Level <span id="currentLicenseLevel">0</span>
<div
id="wifiRestrictionNotice"
class="restriction-notice"
style="display: none"
>
🔒 WLAN-Konfiguration ist nur mit Lizenz Level 3 oder höher
verfügbar. Aktuelle Lizenz: Level
<span id="currentLicenseLevel">0</span>
</div>
<form id="wifiForm">
<div class="form-group">
@@ -176,8 +182,14 @@
<div class="section">
<h2>📍 Standort</h2>
<div id="locationRestrictionNotice" class="restriction-notice" style="display: none;">
🔒 Standort-Konfiguration ist nur mit Lizenz Level 3 oder höher verfügbar. Aktuelle Lizenz: Level <span id="currentLocationLicenseLevel">0</span>
<div
id="locationRestrictionNotice"
class="restriction-notice"
style="display: none"
>
🔒 Standort-Konfiguration ist nur mit Lizenz Level 3 oder höher
verfügbar. Aktuelle Lizenz: Level
<span id="currentLocationLicenseLevel">0</span>
</div>
<form id="locationForm">
<div class="form-group">
@@ -187,7 +199,11 @@
</select>
</div>
<div class="button-group">
<button type="submit" id="locationSubmitBtn" class="btn btn-primary">
<button
type="submit"
id="locationSubmitBtn"
class="btn btn-primary"
>
💾 Standort speichern
</button>
</div>
@@ -197,8 +213,13 @@
<!-- OTA Update Section -->
<div class="section">
<h2>🔄 OTA Update</h2>
<div id="otaRestrictionNotice" class="restriction-notice" style="display: none;">
🔒 OTA Updates sind nur mit Lizenz Level 2 oder höher verfügbar. Aktuelle Lizenz: Level <span id="currentLicenseLevel">0</span>
<div
id="otaRestrictionNotice"
class="restriction-notice"
style="display: none"
>
🔒 OTA Updates sind nur mit Lizenz Level 2 oder höher verfügbar.
Aktuelle Lizenz: Level <span id="currentLicenseLevel">0</span>
</div>
<div class="button-group">
<button
@@ -235,7 +256,9 @@
<div>Kanal: <span id="channel">Laden...</span></div>
<div>MAC-Adresse: <span id="macAddress">Laden...</span></div>
<div>Freier Speicher: <span id="freeMemory">Laden...</span></div>
<div>Verbundene Buttons: <span id="connectedButtons">Laden...</span></div>
<div>
Verbundene Buttons: <span id="connectedButtons">Laden...</span>
</div>
<div>Lizenz gültig: <span id="isLicenceValid">Laden...</span></div>
<div>Lizenz Level: <span id="licenceLevel">Laden...</span></div>
</div>
@@ -247,7 +270,12 @@
<form id="licenceForm">
<div class="form-group">
<label for="licencekey">Lizensschlüssel:</label>
<input type="password" id="licencekey" name="licence" value="Key" />
<input
type="password"
id="licencekey"
name="licence"
value="Key"
/>
</div>
<div class="button-group">
<button type="submit" class="btn btn-primary">
@@ -297,9 +325,8 @@
minute: "2-digit",
second: "2-digit",
});
document.getElementById(
"currentTime"
).textContent = `System Zeit: ${timeString}`;
document.getElementById("currentTime").textContent =
`System Zeit: ${timeString}`;
} else {
document.getElementById("currentTime").textContent =
"Aktuelle Zeit: Fehler beim Laden";
@@ -329,7 +356,7 @@
})
.catch((error) => {
console.log(
"Zeit konnte nicht geladen werden, verwende Browser-Zeit"
"Zeit konnte nicht geladen werden, verwende Browser-Zeit",
);
syncWithBrowserTime();
});
@@ -374,12 +401,13 @@
}
})
.catch((error) =>
showMessage("Verbindungsfehler beim Setzen der Zeit", "error")
showMessage("Verbindungsfehler beim Setzen der Zeit", "error"),
);
}
// Zeit setzen
document.getElementById("timeForm")
document
.getElementById("timeForm")
.addEventListener("submit", function (e) {
e.preventDefault();
@@ -410,14 +438,16 @@
}
})
.catch((error) =>
showMessage("Verbindungsfehler beim Setzen der Zeit", "error")
showMessage("Verbindungsfehler beim Setzen der Zeit", "error"),
);
});
document.getElementById("licenceForm").addEventListener("submit", function(e) {
e.preventDefault();
saveLicence();
});
document
.getElementById("licenceForm")
.addEventListener("submit", function (e) {
e.preventDefault();
saveLicence();
});
// Einstellungen laden
function loadSettings() {
@@ -429,7 +459,7 @@
data.maxTimeDisplay || 20;
})
.catch((error) =>
showMessage("Fehler beim Laden der Einstellungen", "error")
showMessage("Fehler beim Laden der Einstellungen", "error"),
);
}
@@ -448,14 +478,14 @@
(data.freeMemory || 0) + " Bytes";
document.getElementById("connectedButtons").textContent =
data.connectedButtons || 0;
document.getElementById("isLicenceValid").textContent =
data.valid || "";
document.getElementById("licenceLevel").textContent =
data.tier || "";
document.getElementById("isLicenceValid").textContent =
data.valid || "";
document.getElementById("licenceLevel").textContent =
data.tier || "";
// Check license level and update OTA button accordingly
updateOTAButtonAccess(data.tier || 0);
updateWifiButtonAccess(data.tier || 0)
updateWifiButtonAccess(data.tier || 0);
updateLocationAccess(data.tier || 0);
})
.catch((error) => console.log("Info konnte nicht geladen werden"));
@@ -469,7 +499,7 @@
loadLocations();
})
.catch((error) =>
showMessage("Fehler beim Laden der Lizenz", "error")
showMessage("Fehler beim Laden der Lizenz", "error"),
);
}
@@ -500,59 +530,77 @@
// WLAN-Einstellungen laden
function loadWifiSettings() {
fetch("/api/get-wifi")
.then(response => response.json())
.then(data => {
.then((response) => response.json())
.then((data) => {
document.getElementById("wifi-ssid").value = data.ssid || "";
document.getElementById("wifi-password").value = data.password || "";
document.getElementById("wifi-password").value =
data.password || "";
})
.catch(error => showMessage("Fehler beim Laden der WLAN-Einstellungen", "error"));
.catch((error) =>
showMessage("Fehler beim Laden der WLAN-Einstellungen", "error"),
);
}
// WLAN-Einstellungen beim Laden der Seite abrufen
window.addEventListener('load', loadWifiSettings);
window.addEventListener("load", loadWifiSettings);
// WLAN-Formular Handler
document.getElementById("wifiForm").addEventListener("submit", function(e) {
e.preventDefault();
const ssid = document.getElementById("wifi-ssid").value;
const password = document.getElementById("wifi-password").value;
if (!ssid) {
showMessage("Bitte WLAN-Namen eingeben", "error");
return;
}
if (!confirm("Der Server wird nach dem setzten neu gestartet. Fortsetzten?")) {
return;
}
fetch("/api/set-wifi", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `ssid=${encodeURIComponent(ssid)}&password=${encodeURIComponent(password)}`,
})
.then(response => response.json())
.then(data => {
if (data.success) {
showMessage("WLAN-Einstellungen erfolgreich gespeichert!", "success");
} else {
showMessage(data.error || "Fehler beim Speichern der WLAN-Einstellungen", "error");
}
})
.catch(error => showMessage("Verbindungsfehler", "error"));
});
document
.getElementById("wifiForm")
.addEventListener("submit", function (e) {
e.preventDefault();
const ssid = document.getElementById("wifi-ssid").value;
const password = document.getElementById("wifi-password").value;
if (!ssid) {
showMessage("Bitte WLAN-Namen eingeben", "error");
return;
}
if (
!confirm(
"Der Server wird nach dem setzten neu gestartet. Fortsetzten?",
)
) {
return;
}
fetch("/api/set-wifi", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: `ssid=${encodeURIComponent(ssid)}&password=${encodeURIComponent(password)}`,
})
.then((response) => response.json())
.then((data) => {
if (data.success) {
showMessage(
"WLAN-Einstellungen erfolgreich gespeichert!",
"success",
);
} else {
showMessage(
data.error || "Fehler beim Speichern der WLAN-Einstellungen",
"error",
);
}
})
.catch((error) => showMessage("Verbindungsfehler", "error"));
});
// Update OTA button access based on license level
function updateOTAButtonAccess(licenseLevel) {
const otaButton = document.getElementById("otaUpdateBtn");
const otarestrictionNotice = document.getElementById("otaRestrictionNotice");
const otacurrentLevelSpan = document.getElementById("currentLicenseLevel");
const otarestrictionNotice = document.getElementById(
"otaRestrictionNotice",
);
const otacurrentLevelSpan = document.getElementById(
"currentLicenseLevel",
);
const level = parseInt(licenseLevel) || 0;
if (level >= 2) {
// License level 2 or higher - enable OTA
otaButton.classList.remove("btn-disabled");
@@ -569,71 +617,91 @@
// MQTT Message publish function
function updateButtons() {
if (confirm("Update Buttons?")) {
fetch("/api/updateButtons", {
method: "GET"
})
.then((response) => {
if (response.status === 200) {
showMessage("Buttons führen das Update erfolgreich aus!", "success");
} else {
showMessage("Fehler beim Senden der MQTT Message", "error");
if (confirm("Update Buttons?")) {
fetch("/api/updateButtons", {
method: "GET",
})
.then((response) => {
if (response.status === 200) {
showMessage(
"Buttons führen das Update erfolgreich aus!",
"success",
);
} else {
showMessage("Fehler beim Senden der MQTT Message", "error");
}
})
.catch((error) =>
showMessage("Verbindungsfehler beim MQTT Publish", "error"),
);
}
})
.catch((error) => showMessage("Verbindungsfehler beim MQTT Publish", "error"));
}
}
}
function updateWifiButtonAccess(licenseLevel) {
const wifiSubmitBtn = document.getElementById("wifiSubmitBtn");
const wifiForm = document.getElementById("wifiForm");
const wifiRestrictionNotice = document.getElementById("wifiRestrictionNotice");
const wifiCurrentLevelSpan = document.getElementById("currentLicenseLevel");
const level = parseInt(licenseLevel) || 0;
if (level >= 3) {
// License level 3 or higher - enable form
wifiSubmitBtn.classList.remove("btn-disabled");
wifiSubmitBtn.disabled = false;
wifiForm.querySelectorAll('input').forEach(input => {
const wifiSubmitBtn = document.getElementById("wifiSubmitBtn");
const wifiForm = document.getElementById("wifiForm");
const wifiRestrictionNotice = document.getElementById(
"wifiRestrictionNotice",
);
const wifiCurrentLevelSpan = document.getElementById(
"currentLicenseLevel",
);
const level = parseInt(licenseLevel) || 0;
if (level >= 3) {
// License level 3 or higher - enable form
wifiSubmitBtn.classList.remove("btn-disabled");
wifiSubmitBtn.disabled = false;
wifiForm.querySelectorAll("input").forEach((input) => {
input.disabled = false;
});
wifiRestrictionNotice.style.display = "none";
} else {
// License level below 3 - disable form
wifiSubmitBtn.classList.add("btn-disabled");
wifiSubmitBtn.disabled = true;
wifiForm.querySelectorAll('input').forEach(input => {
});
wifiRestrictionNotice.style.display = "none";
} else {
// License level below 3 - disable form
wifiSubmitBtn.classList.add("btn-disabled");
wifiSubmitBtn.disabled = true;
wifiForm.querySelectorAll("input").forEach((input) => {
input.disabled = true;
});
wifiRestrictionNotice.style.display = "block";
wifiCurrentLevelSpan.textContent = level;
}
}
});
wifiRestrictionNotice.style.display = "block";
wifiCurrentLevelSpan.textContent = level;
}
}
// OTA Update function with license check
function performOTAUpdate() {
const otaButton = document.getElementById("otaUpdateBtn");
if (otaButton.disabled || otaButton.classList.contains("btn-disabled")) {
showMessage("OTA Update erfordert Lizenz Level 2 oder höher", "error");
if (
otaButton.disabled ||
otaButton.classList.contains("btn-disabled")
) {
showMessage(
"OTA Update erfordert Lizenz Level 2 oder höher",
"error",
);
return;
}
if (confirm("Möchten Sie wirklich ein OTA Update durchführen? Das Gerät wird während des Updates neu gestartet.")) {
window.location.href = '/update';
if (
confirm(
"Möchten Sie wirklich ein OTA Update durchführen? Das Gerät wird während des Updates neu gestartet.",
)
) {
window.location.href = "/update";
}
}
// Einstellungen speichern
document.getElementById("settingsForm")
document
.getElementById("settingsForm")
.addEventListener("submit", function (e) {
e.preventDefault();
const maxTime = parseInt(document.getElementById("maxTime").value);
const maxTimeDisplay = parseInt(
document.getElementById("maxTimeDisplay").value
document.getElementById("maxTimeDisplay").value,
);
fetch("/api/set-max-time", {
@@ -652,7 +720,7 @@
if (data.success) {
showMessage(
"Einstellungen erfolgreich gespeichert!",
"success"
"success",
);
} else {
showMessage("Fehler beim Speichern der Einstellungen", "error");
@@ -670,7 +738,7 @@
if (data.success) {
showMessage(
"Beste Zeiten erfolgreich zurückgesetzt!",
"success"
"success",
);
} else {
showMessage("Fehler beim Zurücksetzen", "error");
@@ -718,13 +786,11 @@
// Anlern-Anweisung aktualisieren
function updateLearningInstruction() {
if (learningStep < learningSteps.length) {
document.getElementById(
"learningInstruction"
).innerHTML = `Drücken Sie jetzt den Button für: <strong>${learningSteps[learningStep]}</strong>`;
document.getElementById("learningInstruction").innerHTML =
`Drücken Sie jetzt den Button für: <strong>${learningSteps[learningStep]}</strong>`;
}
}
// Anlern-Status abfragen
function pollLearningStatus() {
const pollInterval = setInterval(() => {
@@ -748,7 +814,7 @@
if (learningStep > 0) {
showMessage(
`${learningSteps[learningStep - 1]} erfolgreich angelernt!`,
"success"
"success",
);
}
}
@@ -770,13 +836,13 @@
if (data.success) {
showMessage(
"Button-Zuweisungen erfolgreich zurückgesetzt!",
"success"
"success",
);
loadSystemInfo();
} else {
showMessage(
"Fehler beim Zurücksetzen der Button-Zuweisungen",
"error"
"error",
);
}
})
@@ -806,48 +872,47 @@
alert(statusText);
})
.catch((error) =>
showMessage("Fehler beim Laden des Button-Status", "error")
showMessage("Fehler beim Laden des Button-Status", "error"),
);
}
//location functions
// Locations laden und Dropdown befüllen
// Locations laden und Dropdown befüllen
function loadLocations() {
const licence = document.getElementById("licencekey").value; // Get the licence key from the input field
fetch("http://db.reptilfpv.de:3000/api/location/", {
method: "GET",
headers: {
Authorization: `Bearer ${licence}`, // Add Bearer token using licenkey
},
})
.then((response) => response.json())
.then((data) => {
const licence = document.getElementById("licencekey").value; // Get the licence key from the input field
fetch("http://db.reptilfpv.de:3000/api/location/", {
method: "GET",
headers: {
Authorization: `Bearer ${licence}`, // Add Bearer token using licenkey
},
})
.then((response) => response.json())
.then((data) => {
const select = document.getElementById("locationSelect");
const select = document.getElementById("locationSelect");
// Vorhandene Optionen löschen (außer der ersten "Bitte wählen...")
while (select.children.length > 1) {
select.removeChild(select.lastChild);
}
// Vorhandene Optionen löschen (außer der ersten "Bitte wählen...")
while (select.children.length > 1) {
select.removeChild(select.lastChild);
// Neue Optionen aus Backend-Response hinzufügen
// Neue Optionen aus Backend-Response hinzufügen
data.forEach((location) => {
const option = document.createElement("option");
option.value = location.id;
option.textContent = location.name;
select.appendChild(option);
});
// Aktuell gespeicherten Standort laden
loadCurrentLocation();
})
.catch((error) => {
console.log("Locations konnten nicht geladen werden:", error);
showMessage("Fehler beim Laden der Locations", "error");
});
}
// Neue Optionen aus Backend-Response hinzufügen
// Neue Optionen aus Backend-Response hinzufügen
data.forEach((location) => {
const option = document.createElement("option");
option.value = location.id;
option.textContent = location.name;
select.appendChild(option);
});
// Aktuell gespeicherten Standort laden
loadCurrentLocation();
})
.catch((error) => {
console.log("Locations konnten nicht geladen werden:", error);
showMessage("Fehler beim Laden der Locations", "error");
});
}
// Aktuell gespeicherten Standort laden
function loadCurrentLocation() {
fetch("/api/get-location")
@@ -858,19 +923,26 @@
}
})
.catch((error) => {
console.log("Aktueller Standort konnte nicht geladen werden:", error);
console.log(
"Aktueller Standort konnte nicht geladen werden:",
error,
);
});
}
// Location-Zugriff basierend auf Lizenz-Level kontrollieren
function updateLocationAccess(licenseLevel) {
const locationSubmitBtn = document.getElementById("locationSubmitBtn");
const locationRestrictionNotice = document.getElementById("locationRestrictionNotice");
const locationCurrentLevelSpan = document.getElementById("currentLocationLicenseLevel");
const locationRestrictionNotice = document.getElementById(
"locationRestrictionNotice",
);
const locationCurrentLevelSpan = document.getElementById(
"currentLocationLicenseLevel",
);
const locationSelect = document.getElementById("locationSelect");
const level = parseInt(licenseLevel) || 0;
if (level >= 3) {
// Lizenz Level 3 oder höher - Form aktivieren
locationSubmitBtn.classList.remove("btn-disabled");
@@ -888,42 +960,51 @@
}
// Location Form Handler
document.getElementById("locationForm").addEventListener("submit", function(e) {
e.preventDefault();
const locationSubmitBtn = document.getElementById("locationSubmitBtn");
// Lizenz-Level prüfen
if (locationSubmitBtn.disabled || locationSubmitBtn.classList.contains("btn-disabled")) {
showMessage("Standort-Konfiguration erfordert Lizenz Level 3 oder höher", "error");
return;
}
const locationId = document.getElementById("locationSelect").value;
if (!locationId) {
showMessage("Bitte einen Standort auswählen", "error");
return;
}
// Standort an Backend senden
fetch("/api/set-location", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "locationId=" + encodeURIComponent(locationId),
})
.then((response) => response.json())
.then((data) => {
if (data.success) {
showMessage("Standort erfolgreich gespeichert!", "success");
} else {
showMessage("Fehler beim Speichern des Standorts", "error");
}
document
.getElementById("locationForm")
.addEventListener("submit", function (e) {
e.preventDefault();
const locationSubmitBtn =
document.getElementById("locationSubmitBtn");
// Lizenz-Level prüfen
if (
locationSubmitBtn.disabled ||
locationSubmitBtn.classList.contains("btn-disabled")
) {
showMessage(
"Standort-Konfiguration erfordert Lizenz Level 3 oder höher",
"error",
);
return;
}
const locationId = document.getElementById("locationSelect").value;
if (!locationId) {
showMessage("Bitte einen Standort auswählen", "error");
return;
}
// Standort an Backend senden
fetch("/api/set-location", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: "locationId=" + encodeURIComponent(locationId),
})
.catch((error) => showMessage("Verbindungsfehler", "error"));
});
.then((response) => response.json())
.then((data) => {
if (data.success) {
showMessage("Standort erfolgreich gespeichert!", "success");
} else {
showMessage("Fehler beim Speichern des Standorts", "error");
}
})
.catch((error) => showMessage("Verbindungsfehler", "error"));
});
// Status-Nachricht anzeigen
function showMessage(message, type) {