Automatik-Editor als drei Baender, mit laufenden Werten
Das Akkordeon schloss beim Oeffnen die anderen Faecher - Ausloeser und
Aktion waren also nie gleichzeitig zu sehen, ausgerechnet bei einer
Regel, die genau daraus besteht. Und das mittlere Fach hiess
"Bedingungen", enthielt aber die Rahmenbedingungen; die echten standen
im ersten. Jetzt drei sichtbare Baender: Wenn, Wann, Dann, gebaut aus
.card mit farbigem Rand und .card-header.
Die Bedingungszeile magert von fuenf gleich schweren Kaesten auf zwei
ab. Das Geraet steht klein und matt ueber dem Messwert - es beantwortet
"woher", nicht "was" -, der Messwert ist Text mit gepunkteter Linie,
und nur Vergleich und Wert sehen noch wie Eingabefelder aus. Dort
steckt die Aussage der Bedingung, dort tippt man auch. Die Einheit
sitzt im Wertfeld statt in einem sechsten Kasten, der Papierkorb
erscheint erst beim Ueberfahren.
Neben jeder Bedingung laeuft ihr aktueller Wert mit. ?action=werte
liefert alle acht Sekunden {state_id: {value, unit}} aus actor_states -
bewusst von dort und nicht ueber MQTT, weil dort nur ein Teil der
Geraete auftaucht: die Jalousien haengen an der Tahoma-Box, die
gerechneten Werte an gar nichts. Das ersetzt den Satz, der frueher am
Ende stand und die Regel Wort fuer Wort nacherzaehlte: statt zu
wiederholen, was darueber steht, beantwortet die Zeile die Frage, die
man wirklich hat - warum laeuft die Automatik gerade nicht?
Bei time, date, datetime, deltatime und elapsed faellt der Browser
bewusst kein Urteil. Ob "Uhrzeit um 07:30" zutrifft, haengt am
Nachholfenster, am Tagesrand und bei elapsed am echten Abstand seit der
letzten Ausloesung - das steht im Runner. Es hier nachzubauen hiesse,
eine zweite Wahrheit zu pflegen, die auseinanderlaeuft. Diese Zeilen
bekommen einen gestrichelten Punkt statt einer Aussage.
Der Takt malt nur nach, statt neu zu bauen: renderConditions() ersetzt
den ganzen Block, damit waeren alle acht Sekunden eine offene
Geraeteliste weg und der Cursor aus einem Wertfeld, in das man gerade
tippt.
Der Rahmen steht zusammengefaltet da, solange nichts von der Vorgabe
abweicht - und das ist der Normalfall; vorher nahm er die meiste
Flaeche fuer den seltensten Inhalt. Aufgeklappt tauschen die drei
Vorlagen (taeglich, werktags, Wochenende) mit der Kurzfassung den
Platz. Sie stehen ausserhalb des Elements mit data-bs-toggle, und das
ist kein Zufall: Bootstrap haelt seinen Umschalter am Dokument in der
Capture-Phase, ein stopPropagation() im Knopf kaeme grundsaetzlich zu
spaet.
Getragen wird das von vier Variablen in solar.css, damit der Rest der
Seite mitzieht statt hinterherzuhinken: --ton-radius auf .875rem,
--ton-radius-klein neu auf .5rem (beide an Bootstraps
--bs-border-radius und -sm), --font-anzeige auf Poppins fuer alle
Ueberschriften. Poppins lag seit jeher unter assets/fonts und trug
bisher die vier Etagenknoepfe im Aussenplan - eine ganze Schrift fuer
vier Buchstaben. Fliesstext und Zahlenkolonnen bleiben beim Theme, weil
Poppins keine Tabellenziffern mitbringt.
Drei neue Klassen stehen absichtlich in solar.css und nicht im Editor.
.feld-als-text ist ein Auswahlfeld, das wie Text aussieht, bis man es
anfaehrt - dieselbe Not haben das Raum-Modal und die
Kachel-Einstellungen. .punkt ist an oder aus. .wert-jetzt ist die eine
echte Ausnahme und als einzelne Klasse auch als solche erkennbar. Der
Satz im Wann-Band braucht gar keine: .callout gibt es in AdminLTE, und
seine Toene kommen aus Bootstraps *-bg-subtle-Variablen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+266
-16
@@ -29,7 +29,22 @@
|
||||
--ton-sonne-rgb: 240, 180, 41;
|
||||
--ton-gut: #4caf7d;
|
||||
--ton-schlecht: #e06060;
|
||||
--ton-radius: .7rem;
|
||||
|
||||
/* Zwei Radien statt einem. Der grosse gilt fuer Flaechen (Karten, Modale,
|
||||
Eingabefelder), der kleine fuer alles, was in einer Reihe steht -
|
||||
Schalter, kleine Knoepfe, Abzeichen. Bootstrap kennt beide, benutzte
|
||||
bisher aber nur den grossen; der kleine stand auf seiner Vorgabe von
|
||||
.25rem und wirkte daneben eckig. */
|
||||
--ton-radius: .875rem;
|
||||
--ton-radius-klein: .5rem;
|
||||
|
||||
/* Die Anzeigeschrift. Poppins liegt seit jeher unter assets/fonts und trug
|
||||
bisher nur die Etagenknoepfe im Aussenplan - eine ganze Schrift fuer vier
|
||||
Buchstaben. Als Variable traegt sie jetzt alle Ueberschriften: waermer
|
||||
und eine Spur weniger technisch als die Source Sans 3 des Fliesstextes,
|
||||
ohne dass eine zweite Datei geladen wird. Zahlenkolonnen und Fliesstext
|
||||
bleiben unberuehrt - Poppins hat keine Tabellenziffern. */
|
||||
--font-anzeige: Poppins, system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
|
||||
/* ... und dieselben Werte dort, wo Bootstrap sie sucht. */
|
||||
--bs-body-bg: var(--ton-grund);
|
||||
@@ -43,11 +58,25 @@
|
||||
--bs-tertiary-bg: var(--ton-flaeche-2);
|
||||
--bs-border-color: var(--ton-linie-satt);
|
||||
--bs-border-radius: var(--ton-radius);
|
||||
--bs-border-radius-sm: var(--ton-radius-klein);
|
||||
--bs-link-color: var(--ton-sonne);
|
||||
--bs-link-hover-color: #ffc94d;
|
||||
--bs-heading-color: var(--ton-schrift);
|
||||
}
|
||||
|
||||
/* Ueberschriften in der Anzeigeschrift. Bewusst nur Ueberschriften: der
|
||||
Fliesstext und alle Zahlenkolonnen bleiben bei der Schrift des Themes,
|
||||
weil Poppins keine Tabellenziffern mitbringt und Messwerte sonst
|
||||
springen wuerden. */
|
||||
h1, h2, h3, h4, h5, h6,
|
||||
.h1, .h2, .h3, .h4, .h5, .h6,
|
||||
.card-title,
|
||||
.modal-title {
|
||||
font-family: var(--font-anzeige);
|
||||
font-weight: 600;
|
||||
letter-spacing: -.01em;
|
||||
}
|
||||
|
||||
/* Der Rumpf traegt zwei Grundfarben: die Seite und die Leisten drumherum.
|
||||
AdminLTE setzt sie ueber eigene Klassen, die hier auf denselben Ton
|
||||
gebracht werden - sonst steht eine Karte auf drei verschiedenen Grautoenen. */
|
||||
@@ -655,21 +684,242 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
}
|
||||
}
|
||||
|
||||
/* Editor der Automatiken. Eine Bedingungszeile traegt Geraet, Messwert,
|
||||
Vergleich, Wert, Einheit und den Papierkorb nebeneinander - auf einem
|
||||
Handy bleiben davon "Therm OG Bad" und "te" uebrig, weil die Felder in
|
||||
der input-group einfach mitschrumpfen. Unter 576 px bekommen deshalb
|
||||
Geraet und Messwert je eine eigene Zeile; Vergleich, Wert und Einheit
|
||||
sind kurz genug, um zusammen in die naechste zu passen. */
|
||||
@media (max-width: 575.98px) {
|
||||
/* Die input-group-Klasse muss mit in den Selektor: solar.css wird vor
|
||||
AdminLTE geladen, und Bootstraps ".input-group > .form-select" haette
|
||||
sonst dasselbe Gewicht und wuerde als spaeteres Blatt gewinnen. */
|
||||
.input-group.auto-zeile > .auto-geraet,
|
||||
.input-group.auto-zeile > .auto-messwert {
|
||||
flex: 1 1 100%;
|
||||
width: auto;
|
||||
/* --------------------------------------------------------------------------
|
||||
Drei Klassen, die der Automatik-Editor gebraucht hat - hier, nicht dort
|
||||
|
||||
Sie stehen absichtlich in der gemeinsamen Datei und nicht als Sonderfall
|
||||
im Editor. Zwei davon sind allgemein genug, um anderswo zu taugen; die
|
||||
dritte ist eine echte Ausnahme und als einzelne Klasse auch als solche
|
||||
erkennbar.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
/* Ein Auswahlfeld, das wie Text aussieht, bis man es anfaehrt.
|
||||
|
||||
Eine Bedingung hat sechs Bestandteile, aber nur zwei davon traegt man
|
||||
wirklich ein: Vergleich und Wert. Standen alle sechs als gleich schwere
|
||||
Kaesten nebeneinander, sagte nichts mehr, worauf es ankommt. Die
|
||||
gepunktete Linie sagt "anklickbar", ohne den Platz und das Gewicht eines
|
||||
Eingabefelds zu nehmen.
|
||||
|
||||
Bewusst allgemein: dieselbe Not haben das Raum-Modal und die
|
||||
Kachel-Einstellungen, wo ebenfalls jede Kleinigkeit in einem Kasten
|
||||
steht. Taugt fuer <select> wie fuer <button>. */
|
||||
.feld-als-text {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
max-width: 100%;
|
||||
padding: 0 0 1px;
|
||||
border: 0;
|
||||
border-bottom: 1px dashed var(--ton-linie-satt);
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.feld-als-text:hover,
|
||||
.feld-als-text:focus-visible {
|
||||
border-bottom-color: var(--bs-link-color);
|
||||
color: var(--bs-emphasis-color);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Ein Messwert, wie er in diesem Moment dasteht.
|
||||
|
||||
Steht neben einer Bedingung und beantwortet die Frage, die man wirklich
|
||||
hat: "warum laeuft die nicht?". Das ist die Ausnahme unter den dreien -
|
||||
Bedingungen gibt es sonst nirgends auf der Seite. */
|
||||
.wert-jetzt {
|
||||
font-size: .8125rem;
|
||||
color: var(--ton-schrift-3);
|
||||
font-variant-numeric: tabular-nums;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wert-jetzt b { font-weight: 400; color: var(--ton-schrift-2); }
|
||||
.wert-jetzt.erfuellt b { color: var(--ton-gut); }
|
||||
|
||||
/* Erfuellt oder noch nicht. Bewusst kein Rot: eine Bedingung, die gerade
|
||||
nicht zutrifft, ist der Normalfall und kein Fehler. */
|
||||
.punkt {
|
||||
display: inline-block;
|
||||
width: .7rem;
|
||||
height: .7rem;
|
||||
border: 1.5px solid var(--ton-schrift-3);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.punkt.an {
|
||||
border-color: var(--ton-gut);
|
||||
background: var(--ton-gut);
|
||||
}
|
||||
|
||||
/* Atmet leise, wo etwas mitlaeuft - ein Wort "live" daneben braucht es dann
|
||||
nicht. */
|
||||
.punkt.atmet { animation: punkt-atmen 2.4s ease-in-out infinite; }
|
||||
|
||||
@keyframes punkt-atmen {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: .35; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.punkt.atmet { animation: none; }
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Editor der Automatiken: die Bedingungszeile
|
||||
|
||||
Frueher eine input-group aus sechs gleich schweren Kaesten. Jetzt ein
|
||||
Raster, in dem Geraet und Messwert uebereinander stehen (das Geraet
|
||||
beantwortet "woher", nicht "was") und nur Vergleich und Wert noch wie
|
||||
Eingabefelder aussehen.
|
||||
|
||||
Auf schmalen Schirmen bricht die Zeile in zwei: oben, worum es geht,
|
||||
unten der Vergleich. Frueher schrumpften die Felder stattdessen mit, bis
|
||||
von "Thermostat OG Bad" ein "Therm" uebrig war.
|
||||
-------------------------------------------------------------------------- */
|
||||
.auto-zeile {
|
||||
display: grid;
|
||||
grid-template-columns: 1.75rem minmax(0, 1fr) 5.25rem 8rem 8.5rem .75rem 1.75rem;
|
||||
grid-template-areas: "sym was op wert jetzt punkt weg";
|
||||
gap: .625rem;
|
||||
align-items: center;
|
||||
padding: .45rem .55rem;
|
||||
border-radius: var(--ton-radius-klein);
|
||||
}
|
||||
|
||||
.auto-zeile:nth-of-type(even) { background: rgba(255, 255, 255, .022); }
|
||||
|
||||
.auto-zeile > .auto-symbol { grid-area: sym; color: var(--ton-schrift-2); }
|
||||
.auto-zeile > .auto-was { grid-area: was; min-width: 0; }
|
||||
.auto-zeile > .auto-op { grid-area: op; }
|
||||
.auto-zeile > .auto-wert { grid-area: wert; }
|
||||
.auto-zeile > .wert-jetzt { grid-area: jetzt; }
|
||||
.auto-zeile > .punkt { grid-area: punkt; }
|
||||
.auto-zeile > .auto-weg { grid-area: weg; }
|
||||
.auto-zeile > .auto-werte { grid-area: werte; }
|
||||
|
||||
/* Die Aktionszeile: dasselbe Raster, andere Spalten. Statt Vergleich, Wert
|
||||
und laufendem Messwert steht dort ein Block mit den Parametern des
|
||||
Kommandos - mal keiner ("Auf"), mal zwei ("Position+Neigung"). */
|
||||
.auto-zeile.tat {
|
||||
grid-template-columns: 1.75rem minmax(0, 1fr) auto 1.75rem;
|
||||
grid-template-areas: "sym was werte weg";
|
||||
}
|
||||
|
||||
/* Eine Zeile ohne Geraet: dann gibt es nur eines zu tun, und das darf die
|
||||
ganze Breite haben. Vergleich, Wert und der laufende Messwert gibt es in
|
||||
diesem Zustand noch gar nicht - ihre Spalten stuenden sonst nur leer
|
||||
herum, waehrend die eine Schaltflaeche in eine schmale Spalte gequetscht
|
||||
waere. */
|
||||
.auto-zeile.leer { grid-template-areas: "sym was was was was punkt weg"; }
|
||||
|
||||
/* Geraet klein und matt ueber dem Messwert - und trotzdem anklickbar. */
|
||||
.auto-was { display: flex; flex-direction: column; gap: .05rem; }
|
||||
|
||||
/* Nur in der Bedingungszeile: die Aktionszeile benutzt .auto-geraet
|
||||
weiterhin als vollwertige Auswahlflaeche und darf davon nichts
|
||||
abbekommen. */
|
||||
/* Nicht in der leeren Zeile: dort traegt derselbe Knopf zusaetzlich
|
||||
.feld-als-text und ist die einzige Handlung, die es gibt - klein und matt
|
||||
waere er dort genau die Falle, die er vorher war. Die Klasse .auto-geraet
|
||||
behaelt er trotzdem, weil daran haengt, WAS er ist: der Klick-Horcher
|
||||
erkennt ihn daran. Verhalten und Aussehen sind absichtlich zwei
|
||||
verschiedene Klassen. */
|
||||
.auto-was > .auto-geraet:not(.feld-als-text) {
|
||||
align-self: start;
|
||||
max-width: 100%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--ton-schrift-3);
|
||||
font-size: .72rem;
|
||||
line-height: 1.3;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.auto-was > .auto-geraet:not(.feld-als-text):hover,
|
||||
.auto-was > .auto-geraet:not(.feld-als-text):focus-visible {
|
||||
color: var(--bs-link-color);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.auto-messwert { align-self: start; }
|
||||
|
||||
/* Der Papierkorb erscheint erst beim Ueberfahren. Acht rote Knoepfe im
|
||||
Ruhezustand zogen alle Aufmerksamkeit auf die seltenste Handlung.
|
||||
Wo es kein Ueberfahren gibt, steht er dauerhaft da. */
|
||||
.auto-zeile > .auto-weg {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
color: var(--ton-schrift-3);
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease, color .15s ease;
|
||||
}
|
||||
|
||||
.auto-zeile:hover > .auto-weg,
|
||||
.auto-zeile:focus-within > .auto-weg { opacity: 1; }
|
||||
.auto-zeile > .auto-weg:hover { color: var(--ton-schlecht); }
|
||||
|
||||
@media (hover: none) {
|
||||
.auto-zeile > .auto-weg { opacity: 1; }
|
||||
}
|
||||
|
||||
/* Ein Segment je Bedingung, im Kopf des Bandes und ueber jeder Gruppe.
|
||||
Eine Zahl allein ("2 von 4") liest man, die Reihe sieht man. */
|
||||
.auto-segment {
|
||||
width: .8rem;
|
||||
height: .3rem;
|
||||
border-radius: .15rem;
|
||||
background: var(--ton-linie-satt);
|
||||
}
|
||||
|
||||
.auto-segment.an { background: var(--ton-gut); }
|
||||
|
||||
/* Was der Browser nicht entscheiden kann, bleibt hohl - siehe ZEITARTEN in
|
||||
autoActionFuncs.js. */
|
||||
.auto-segment.offen {
|
||||
background: none;
|
||||
box-shadow: inset 0 0 0 1px var(--ton-linie-satt);
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.auto-zeile {
|
||||
grid-template-columns: 1.75rem 5.25rem minmax(0, 1fr) .75rem 1.75rem;
|
||||
/* Drei Zeilen statt zwei: der laufende Wert quetschte sich sonst mit
|
||||
dem Wertfeld in dieselbe Reihe und blieb als "gerad…" stehen. Auf
|
||||
einem Handy ist Hoehe billig und Breite teuer. */
|
||||
grid-template-areas:
|
||||
"sym was was punkt weg"
|
||||
"sym op wert wert wert"
|
||||
"sym jetzt jetzt jetzt jetzt";
|
||||
row-gap: .35rem;
|
||||
}
|
||||
|
||||
.auto-zeile.leer { grid-template-areas: "sym was was punkt weg"; }
|
||||
|
||||
.auto-zeile.tat {
|
||||
grid-template-columns: 1.75rem minmax(0, 1fr) 1.75rem;
|
||||
grid-template-areas:
|
||||
"sym was weg"
|
||||
"sym werte werte";
|
||||
}
|
||||
|
||||
.auto-zeile.tat.leer { grid-template-areas: "sym was weg"; }
|
||||
}
|
||||
|
||||
/* Raum-Modal. Ein Kommando mit mehreren Parametern ("Position+Neigung")
|
||||
@@ -2335,7 +2585,7 @@ input[type='range']::-webkit-slider-runnable-track {
|
||||
}
|
||||
|
||||
.floorBtn text {
|
||||
font: 600 34px Poppins, system-ui, sans-serif;
|
||||
font: 600 34px var(--font-anzeige);
|
||||
fill: #9aa0a6;
|
||||
opacity: .8;
|
||||
transition: fill .25s ease, opacity .25s ease;
|
||||
|
||||
Reference in New Issue
Block a user