Einstellungsseite: Reiter, Kachelwerte und Geraeteliste

Die Einstellungen bestanden aus einer einzigen langen Spalte mit den
Preistabellen. Sie bekommt Reiter, und darin zwei neue Flaechen: was die
Kacheln der Startseite anzeigen, und welche Geraete es ueberhaupt gibt.

Reiter gab es vorher dreimal in drei Ausfuehrungen - die Etagen ueber den
Automatismen mit eigenem switchTab(), die Geraetegruppen im Raum-Modal mit
eigener CSS-Klasse, und die Einstellungsseite noch einmal anders. Jetzt baut
restricted/reiter.php alle drei; umgeschaltet wird von Bootstrap, den offenen
Reiter merkt reiterMerken() in der Adresse.

Kachelwerte: was auf einer Kachel steht, stand fest in rooms.php. Die neue
Tabelle kachelWerte (solarLog_kacheln.sql) ueberschreibt das je Raum, die
Maske waehlt die Messwerte aus demselben Katalog wie der Automatik-Editor -
nach Etage sortiert, die Geraete des eigenen Raums oben. Fehlt die Tabelle,
zeigt jede Kachel weiter ihre Vorgabe.

Geraete: die Zuordnung Geraet -> Raum war ein Modal, erreichbar ueber ein
Zahnrad neben den Automatismen. Sie ist eine Einstellung und steht jetzt dort,
zusammen mit dem, was fehlte: seit wann ein Geraet nichts mehr meldet, in
welchen Automatiken es steckt, und ein Loeschknopf. Letzterer ist noetig, weil
der Suchlauf nichts loescht - er legt an und frischt auf, damit die Automatiken
ihre Zustands-Ids behalten; ein abgebautes Geraet bliebe sonst fuer immer
stehen. Geloescht wird nur, was in keiner Automatik vorkommt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 22:45:24 +02:00
co-authored by Claude Opus 5
parent 1b58579c22
commit 07bca5104e
15 changed files with 2058 additions and 226 deletions
-52
View File
@@ -800,58 +800,6 @@ function refreshAutomations(floor) {
});
}
/**
* Zuordnung Geraet -> Raum. Eigenes Modal, weil es kein Teil einer einzelnen
* Automatik ist, sondern einmal fuer alle gilt.
*/
function openRoomModal() {
document.getElementById("modal-title").innerHTML = "Geräte den Räumen zuordnen";
const alt = document.getElementById("modalSaveBtn");
const btn = alt.cloneNode(true);
alt.replaceWith(btn);
// Das Raum-Modal versteckt ihn; hier wird er gebraucht.
btn.hidden = false;
btn.addEventListener("click", speichereRaeume);
const dialog = document.querySelector("#modalEV .modal-dialog");
dialog.classList.add("modal-lg");
document.getElementById("modalEV").addEventListener("hidden.bs.modal",
() => dialog.classList.remove("modal-lg"), { once: true });
const koerper = document.getElementById("modal-body");
koerper.innerHTML = loadingHTML("Wird geladen...");
modalEV.show();
fetch("./ajax/AutoAction.php?action=rooms", {
method: "GET", headers: { "Requested-With-Ajax": "ajax" }
})
.then(a => a.text())
.then(html => {
koerper.innerHTML = html;
const tipps = document.getElementById("btnRoomTipps");
if (tipps) {
tipps.addEventListener("click", () => {
koerper.querySelectorAll("select[data-tipp]").forEach(s => {
if (!s.value) s.value = s.dataset.tipp;
});
tipps.disabled = true;
});
}
})
.catch(fehler => { koerper.innerHTML = "Konnte die Zuordnung nicht laden: " + fehler.message; });
}
function speichereRaeume() {
const rooms = {};
document.querySelectorAll("#modal-body select[data-actor]").forEach(s => {
rooms[s.dataset.actor] = s.value;
});
automationRequest("saveRooms", { rooms: rooms }).then(antwort => {
if (antwort.error) alert(antwort.error);
else modalEV.hide();
});
}
function toggleAutomation(id) {
automationRequest("toggle", { id: id }).then(antwort => {
if (antwort.error) alert(antwort.error);