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:
+256
-15
@@ -691,21 +691,6 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
Beschriftungen nicht nebeneinander - dann scrollt die Leiste seitwaerts,
|
||||
statt die Namen umzubrechen. Die durchgehende Linie unter den Reitern
|
||||
darf dabei nicht mitscrollen, sie gehoert an den unteren Rand. */
|
||||
.raum-tabs {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: none;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.raum-tabs::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
.raum-tabs .nav-link {
|
||||
padding: 0.3rem 0.7rem;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
/* Waehrend ein Kommando unterwegs ist. Ein "Zu" an einer Jalousie dauert
|
||||
ueber eine Minute; ohne sichtbare Sperre tippt man in der Zeit nach. */
|
||||
@@ -1022,6 +1007,71 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
--skoda-blech: 128, 138, 148; /* alles Unbeteiligte am Fahrzeug */
|
||||
}
|
||||
|
||||
/* --- Reiter --------------------------------------------------------------
|
||||
Eine Bauart fuer die ganze Seite: Einstellungen, Raum-Modal, Automatiken.
|
||||
Gebaut werden sie von restricted/reiter.php, umgeschaltet von Bootstrap.
|
||||
|
||||
Statt der Ordnerlaschen von Bootstrap eine Unterstreichung: die Laschen
|
||||
brauchen einen Rahmen um die Flaeche darunter, damit sie nicht in der Luft
|
||||
haengen - und der Rahmen ist genau das, was diese Oberflaeche sonst
|
||||
nirgends hat. Der aktive Reiter traegt die Akzentfarbe.
|
||||
|
||||
Jede Regel nennt .nav-tabs UND .reiter, obwohl .reiter allein die Leiste
|
||||
schon trifft. Das ist noetig, nicht schmueckend: adminlte.min.css wird nach
|
||||
dieser Datei geladen und bringt eigene Regeln fuer .nav-tabs .nav-link mit.
|
||||
Bei gleicher Spezifitaet gewaenne die spaetere - der aktive Reiter waere
|
||||
weiss statt bernstein. */
|
||||
.nav-tabs.reiter {
|
||||
border-bottom: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
gap: .1rem;
|
||||
}
|
||||
.nav-tabs.reiter .nav-link {
|
||||
border: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
border-radius: .35rem .35rem 0 0;
|
||||
padding: .45rem .9rem;
|
||||
color: var(--ton-schrift-2, #9aa6ad);
|
||||
background: transparent;
|
||||
transition: color .18s, background .18s, border-color .18s;
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.nav-tabs.reiter .nav-link:hover {
|
||||
background: rgba(138, 148, 158, .08);
|
||||
color: var(--ton-schrift, #e8ede9);
|
||||
border-bottom-color: var(--ton-linie-satt, rgba(138, 148, 158, .38));
|
||||
}
|
||||
}
|
||||
.nav-tabs.reiter .nav-link.active {
|
||||
background: transparent;
|
||||
color: var(--ton-sonne, #f0b429);
|
||||
border-bottom-color: var(--ton-sonne, #f0b429);
|
||||
}
|
||||
.nav-tabs.reiter .nav-link:focus-visible {
|
||||
outline: 2px solid var(--ton-sonne, #f0b429);
|
||||
outline-offset: -2px;
|
||||
}
|
||||
.nav-tabs.reiter .nav-link i { margin-right: .5rem; }
|
||||
|
||||
/* Schmale Fassung fuer enge Stellen (Raum-Modal): kleinere Reiter, die
|
||||
waagerecht scrollen statt umzubrechen - eine Zeile bleibt eine Zeile. */
|
||||
.nav-tabs.reiter-schmal {
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
.nav-tabs.reiter-schmal::-webkit-scrollbar { display: none; }
|
||||
.nav-tabs.reiter-schmal .nav-link {
|
||||
padding: .3rem .7rem;
|
||||
font-size: .8rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.nav-tabs.reiter-schmal .nav-link i { margin-right: .3rem; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.nav-tabs.reiter .nav-link { transition: none; }
|
||||
}
|
||||
|
||||
/* --- Aufbau der Fahrzeugkachel -------------------------------------------
|
||||
Links das Bild, rechts die Zahlen dazu. Die Kachel bricht um, sobald die
|
||||
Zahlenspalte unter 24rem faellt; das Bild behaelt dann seine Breite und
|
||||
@@ -1816,6 +1866,197 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
|
||||
.skoda-alter { font-size: .85rem; }
|
||||
|
||||
/* === Einstellungen: Werte auf den Home-Kacheln ===========================
|
||||
Eine Zeile je Raum, aufklappbar. Die Zeile zeigt im zugeklappten Zustand
|
||||
schon, was auf der Kachel steht - sonst muesste man zwanzig Raeume
|
||||
aufklappen, um einen zu finden. */
|
||||
|
||||
.kachel-etage { margin-bottom: 1.25rem; }
|
||||
.kachel-etage:last-child { margin-bottom: 0; }
|
||||
.kachel-etage-name {
|
||||
font-size: .7rem;
|
||||
letter-spacing: .13em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ton-schrift-3, #6f7a81);
|
||||
margin-bottom: .35rem;
|
||||
}
|
||||
|
||||
.kachel-zeile {
|
||||
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
border-radius: .5rem;
|
||||
margin-bottom: .4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.kachel-zeile.offen { border-color: var(--ton-linie-satt, rgba(138, 148, 158, .38)); }
|
||||
|
||||
.kachel-kopf {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .6rem;
|
||||
width: 100%;
|
||||
padding: .5rem .75rem;
|
||||
background: none;
|
||||
border: 0;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
@media (hover: hover) {
|
||||
.kachel-kopf:hover { background: rgba(138, 148, 158, .08); }
|
||||
}
|
||||
.kachel-kopf .pfeil {
|
||||
color: var(--ton-schrift-3, #6f7a81);
|
||||
transition: transform .18s;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.kachel-zeile.offen .kachel-kopf .pfeil { transform: rotate(90deg); }
|
||||
.kachel-kopf .name { min-width: 8rem; }
|
||||
.kachel-kopf .werte {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: .3rem;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.kachel-chip {
|
||||
font-size: .72rem;
|
||||
padding: .1rem .45rem;
|
||||
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
border-radius: 1rem;
|
||||
color: var(--ton-schrift-2, #9aa6ad);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.kachel-chip.leer { font-style: italic; }
|
||||
|
||||
.kachel-editor {
|
||||
padding: .25rem .75rem .75rem;
|
||||
border-top: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
}
|
||||
|
||||
/* Eine Wertzeile. Auf breiten Schirmen nebeneinander, auf dem Handy
|
||||
untereinander - die Felder sind zu kurz, um sie zu quetschen. */
|
||||
.kachel-wert {
|
||||
display: grid;
|
||||
grid-template-columns: 7.5rem minmax(10rem, 1fr) 7rem 5.5rem 4rem auto;
|
||||
gap: .4rem;
|
||||
align-items: center;
|
||||
padding: .5rem 0;
|
||||
border-bottom: 1px dashed var(--ton-linie, rgba(138, 148, 158, .2));
|
||||
}
|
||||
.kachel-wert:last-of-type { border-bottom: 0; }
|
||||
.kachel-wert .kw-schalter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.kachel-wert .kw-schalter label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .25rem;
|
||||
font-size: .78rem;
|
||||
color: var(--ton-schrift-2, #9aa6ad);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (max-width: 991.98px) {
|
||||
.kachel-wert {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.kachel-wert .kw-topic { grid-column: 1 / -1; }
|
||||
}
|
||||
|
||||
.kachel-fuss {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .75rem;
|
||||
margin-top: .75rem;
|
||||
}
|
||||
|
||||
/* === Geraetetafel (Einstellungen) ========================================
|
||||
Sechzig Zeilen, in denen die meiste Arbeit an einer Handvoll haengt: den
|
||||
Geraeten ohne Raum und denen, die seit Monaten schweigen. Beide sind
|
||||
markiert, damit man sie nicht suchen muss - der Rest bleibt ruhig. */
|
||||
.geraete-sieb {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .9rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
.geraete-sieb input[type="search"] { max-width: 22rem; }
|
||||
.geraete-sieb .form-check { flex: none; }
|
||||
|
||||
.geraete-tafel {
|
||||
max-height: calc(100vh - 22rem);
|
||||
min-height: 14rem;
|
||||
overflow-y: auto;
|
||||
border: 1px solid var(--bs-border-color, #2c3034);
|
||||
border-radius: .375rem;
|
||||
}
|
||||
/* Der Kopf bleibt beim Scrollen stehen - sonst raet man ab Zeile zwanzig,
|
||||
welche Spalte der Raum war. */
|
||||
.geraete-tafel thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background: var(--ton-flaeche-2, #2b3237);
|
||||
font-size: .72rem;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
color: var(--ton-schrift-3, #6f7a81);
|
||||
white-space: nowrap;
|
||||
}
|
||||
.geraete-tafel td { vertical-align: middle; }
|
||||
.geraete-tafel .name { line-height: 1.25; }
|
||||
.geraete-tafel .name .neben {
|
||||
display: block;
|
||||
font-size: .72rem;
|
||||
color: var(--ton-schrift-3, #6f7a81);
|
||||
}
|
||||
.geraete-tafel .raum { min-width: 11rem; }
|
||||
.geraete-tafel .raum select { min-width: 9rem; }
|
||||
.geraete-tafel .alter { color: var(--ton-schrift-2, #9aa4ab); white-space: nowrap; }
|
||||
.geraete-tafel .alter.lange { color: var(--ton-sonne, #f0b429); }
|
||||
/* Ohne Raum: eine Kante links statt einer eingefaerbten Zeile - Letzteres
|
||||
sieht bei zwanzig offenen Geraeten nach Fehler aus, ist aber nur Arbeit.
|
||||
Als ::before und nicht als border, weil Bootstrap Tabellenzellen im
|
||||
Hover mit einem inset-Schatten fuellt und den Rand damit ueberdeckt. */
|
||||
.geraete-tafel tr.ohne-raum td:first-child { position: relative; }
|
||||
.geraete-tafel tr.ohne-raum td:first-child::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0; top: 0; bottom: 0;
|
||||
width: 3px;
|
||||
background: var(--ton-sonne, #f0b429);
|
||||
}
|
||||
|
||||
/* Der Papierkorb haelt sich zurueck, bis man ihn braucht. */
|
||||
.geraete-tafel .geraet-weg {
|
||||
color: var(--ton-schrift-3, #6f7a81);
|
||||
border-color: transparent;
|
||||
line-height: 1;
|
||||
}
|
||||
.geraete-tafel .geraet-weg:hover:not(:disabled),
|
||||
.geraete-tafel .geraet-weg:focus-visible:not(:disabled) {
|
||||
color: var(--ton-schlecht, #e06060);
|
||||
border-color: var(--ton-schlecht, #e06060);
|
||||
}
|
||||
.geraete-tafel .geraet-weg:disabled { opacity: .25; }
|
||||
|
||||
.geraete-fuss {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: .75rem;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
.geraete-sieb { flex-wrap: wrap; }
|
||||
.geraete-sieb input[type="search"] { max-width: none; }
|
||||
.geraete-tafel { max-height: calc(100vh - 18rem); }
|
||||
}
|
||||
|
||||
/* === Protokollseite ======================================================
|
||||
Ein Log liest sich nur in einer Schrift mit fester Breite: die Zeitstempel
|
||||
stehen dann untereinander, und das Auge findet die Stelle, an der etwas
|
||||
|
||||
Reference in New Issue
Block a user