improved WebUI

This commit is contained in:
2025-08-12 14:21:53 +02:00
parent 546e4a1885
commit 8393f24ae2
3 changed files with 382 additions and 164 deletions

View File

@@ -8,11 +8,11 @@
<link rel="stylesheet" href="static/css/bootstrap.min.css">
<link rel="stylesheet" href="static/css/custom.css">
<link rel="stylesheet" href="static/css/tweaks.css">
<script src="static/js/jquery.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
<script src="static/js/websocket.js"></script>
<script src="static/js/dtc_table.js"></script>
<script src="static/js/script.js"></script>
<script src="static/js/jquery.min.js" defer></script>
<script src="static/js/bootstrap.min.js" defer></script>
<script src="static/js/websocket.js" defer></script>
<script src="static/js/dtc_table.js" defer></script>
<script src="static/js/script.js" defer></script>
<link rel="apple-touch-icon" sizes="180x180" href="static/img/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="static/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="static/img/favicon-16x16.png">
@@ -216,10 +216,7 @@
<div class="form-group row">
<label for="speedsource" class="control-label col-4">Schnittstelle</label>
<div class="col-8">
<select id="speedsource" class="set-wsevent data-speedsource select form-control">
<option value="Impuls">Impuls</option>
<option value="GPS">GPS</option>
<option value="CAN-Bus">CAN-Bus</option>
<select id="speedsource" class="set-wsevent data-speedsource select form-control">
</select>
</div>
</div>
@@ -298,8 +295,6 @@
<label for="cansource" class="control-label col-4">Model</label>
<div class="col-8">
<select id="cansource" class="set-wsevent data-cansource select form-control">
<option value="KTM 890 Adventure R (2021)">KTM 890 Adventure R (2021)</option>
<option value="KTM 1290 Superduke R (2023)">KTM 1290 Superduke R (2023)</option>
</select>
</div>
</div>
@@ -510,21 +505,26 @@
<table class="table">
<tbody>
<tr>
<th class="col-7" scope="col">Parameter</td>
<th class="col-5" scope="col">Value</td>
<th class="col-7" scope="col">Parameter</th>
<th class="col-5" scope="col">Value</th>
</tr>
<tr>
<td>Firmware Version</td>
<td>%SW_VERSION%</td>
<td class="data-fw-version"></td>
</tr>
<tr>
<td>Flash Version</td>
<td>%FS_VERSION%</td>
<td>Benötigte Flash Version</td>
<td class="data-req-flash-version"></td>
</tr>
<tr>
<td>Installierte Flash Version</td>
<td class="data-flash-version"></td>
</tr>
<tr>
<td>Git Revision</td>
<td>%GIT_REV%</td>
<td class="data-git-rev"></td>
</tr>
</tbody>
</table>
</p>
<!-- Div Group VersionInfo -->

View File

@@ -84,7 +84,6 @@ function onMessage(event) {
processDTCNotifications(dtcArray);
fillDTCTable(dtcArray);
} else if (data.startsWith("MAPPING_STATUS:")) {
const data_sliced = data.slice(15);
statusMapping = createMapping(data_sliced);
@@ -100,19 +99,15 @@ function onMessage(event) {
const data_sliced = data.slice(7);
const result = processDataString(data_sliced, staticMapping);
fillValuesToHTML(result);
console.log(result);
overlay.style.display = "none";
}
}
function createMapping(mappingString) {
const mappingArray = mappingString.split(";");
const mapping = [];
mappingArray.forEach((variable) => {
if (variable !== null) mapping.push(variable.trim());
});
return mapping;
return mappingString
.split(";")
.map((s) => s.trim())
.filter((s) => s !== "");
}
function processDataString(dataString, mapping) {
@@ -157,43 +152,136 @@ function do_resize(textbox) {
else textbox.rows = rows;
}
function fillValuesToHTML(dataset) {
for (var key in dataset) {
var key_prefixed = "data-" + key;
var elements = document.getElementsByClassName(key_prefixed);
// --- Globale Puffer für Select-Handling ---
const selectDesiredValue = Object.create(null); // keyBase -> desired value ("speedsource" -> "GPS")
const selectOptionsReady = Object.create(null); // keyBase -> true/false
if (elements.length > 0) {
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
function splitCsv(s) {
return (s || "")
.split(",")
.map((x) => x.trim())
.filter(Boolean);
}
if (element.type === "checkbox") {
// Wenn das Element ein Kontrollkästchen ist
element.checked = dataset[key] == 1 ? true : false;
} else if (element.tagName === "SELECT") {
// Wenn das Element ein Dropdown ist
setDropdownValue(element, dataset[key]);
} else if (element.classList.contains("progress-bar")) {
// Wenn das Element eine Fortschrittsleiste ist
updateProgressBar(element, dataset[key]);
} else if (element.classList.contains("hideable")) {
// Wenn das Element ein Settingsabschnitt-div ist
if (dataset[key] == 0) element.style.display = "none";
else element.style.display = "";
} else {
// Standardmäßig für Textfelder und andere Elemente
element.value = dataset[key];
}
}
}
function hasOption(selectEl, value) {
for (let i = 0; i < selectEl.options.length; i++) {
if (selectEl.options[i].value === value) return true;
}
return false;
}
function addOption(selectEl, value, selectIt = false) {
const o = document.createElement("option");
o.value = value;
o.textContent = value;
selectEl.appendChild(o);
if (selectIt) {
selectEl.value = value;
}
}
// Funktion zum Setzen des ausgewählten Werts für Dropdowns
function populateSelect(selectId, options, currentValue) {
const sel = document.getElementById(selectId);
if (!sel) return;
// 1) komplett ersetzen
sel.innerHTML = "";
options.forEach((opt) => addOption(sel, opt, false));
// 2) Zielwert bestimmen (currentValue > bereits gepuffert > vorhandener Wert > erste Option)
const wanted =
(currentValue && currentValue.length ? currentValue : null) ??
selectDesiredValue[selectId] ??
sel.value ??
(options[0] || "");
// 3) Falls gewünschte Option fehlt, hinzufügen
if (wanted && !hasOption(sel, wanted)) addOption(sel, wanted, false);
// 4) Setzen
sel.value = wanted;
// 5) Markieren: Optionen sind ready
selectOptionsReady[selectId] = true;
// Verbrauchte Wunschwerte löschen
delete selectDesiredValue[selectId];
}
// Robust: setzt den Wert; wenn Option fehlt, füge sie hinzu
function setDropdownValue(selectElement, value) {
for (var i = 0; i < selectElement.options.length; i++) {
if (selectElement.options[i].value === value) {
selectElement.selectedIndex = i;
break;
if (!value) return;
if (!hasOption(selectElement, value)) {
addOption(selectElement, value, false);
}
selectElement.value = value;
}
// Core: schreibt Werte in DOM, erkennt *-options und füllt Selects
function fillValuesToHTML(dataset) {
for (const key in dataset) {
const val = dataset[key];
// A) Optionen-Feld? (z.B. "speedsource-options")
if (key.endsWith("-options")) {
const base = key.slice(0, -"-options".length); // "speedsource"
const selectId = base; // ID = keyBase
populateSelect(
selectId,
splitCsv(val),
selectDesiredValue[selectId] || undefined
);
continue; // fertig mit diesem key
}
// B) Normales Feld
const key_prefixed = "data-" + key;
const elements = document.getElementsByClassName(key_prefixed);
if (elements.length === 0) continue;
for (let i = 0; i < elements.length; i++) {
const el = elements[i];
// Checkbox?
if (el.type === "checkbox") {
el.checked = val == 1;
continue;
}
// Select?
if (el.tagName === "SELECT") {
const selectId = el.id || key; // ID hat Vorrang, sonst key
// Wenn die Optionen für dieses Select noch NICHT bereit sind, Wunschwert puffern
if (!selectOptionsReady[selectId]) {
selectDesiredValue[selectId] = val;
// Sicherheitsnetz: falls doch schon Optionen existieren, sofort setzen
setDropdownValue(el, val);
} else {
// Optionen sind ready -> ganz normal setzen (ggf. Option ergänzen)
setDropdownValue(el, val);
}
continue;
}
// Progress-Bar?
if (el.classList.contains("progress-bar")) {
updateProgressBar(el, val);
continue;
}
// Hideable-Section?
if (el.classList.contains("hideable")) {
el.style.display = val == 0 ? "none" : "";
continue;
}
// Input/Textarea?
if ("value" in el) {
el.value = val;
continue;
}
// Fallback: content nodes (td, span, div)
el.textContent = val;
}
}
}
@@ -212,15 +300,15 @@ function showNotification(message, type) {
// Erstellen Sie ein Bootstrap-Alert-Element
var alertElement = $(
'<div class="alert alert-' +
type +
' alert-dismissible fade show notification" role="alert">' +
"<strong>" +
message +
"</strong>" +
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
'<span aria-hidden="true">&times;</span>' +
"</button>" +
"</div>"
type +
' alert-dismissible fade show notification" role="alert">' +
"<strong>" +
message +
"</strong>" +
'<button type="button" class="close" data-dismiss="alert" aria-label="Close">' +
'<span aria-hidden="true">&times;</span>' +
"</button>" +
"</div>"
);
// Fügen Sie das Alert-Element dem Container hinzu