Einstellungen -> Grundriss: Etagen, Raeume und Kacheln am Plan pflegen

Neuer Reiter mit Plan-Editor: Etagen anlegen, umbenennen, sortieren,
loeschen und als Standard markieren; Grundrissbild hochladen; Raeume mit
Name, Kuerzel und Thermostat-Zweig anlegen und bearbeiten; Kacheln im Plan
ziehen oder einen Raum ohne Kachel mit "Platzieren" und einem Klick setzen.
Loest tools/kachelpositionen.php ab - Raster, Geisterkachel und die
Umrechnung Mitte -> linke obere Ecke sind von dort uebernommen.

- restricted/grundriss.php: alle Pruefungen und Schreibzugriffe. Eine
  Etage mit Raeumen oder Automatiken laesst sich nicht loeschen, die
  Ablehnung nennt die Namen. Raeume loeschen laesst ihre Geraete ohne Raum.
- Grundrissbilder nach tiles/grundriss/ (beschreibbar, nicht im Git),
  nur PNG/JPEG/WebP, am Inhalt geprueft; SVG bewusst nicht. Prüfsumme im
  Dateinamen, alte hochgeladene Bilder werden weggeraeumt.
- ajax/settings.php: ?action=grundriss und sieben POST-Aktionen, jede
  antwortet mit dem ganzen neuen Stand.
- "Werte" springt in den Reiter Home-Kacheln und oeffnet die Kachel;
  Home-Kacheln und Geraete laden nach einer Grundriss-Aenderung nach.
- Startseite ohne Etage mit platziertem Raum: Hinweis auf die
  Einstellungen statt einer leeren Zeichenflaeche.
- README: Grundriss als Inhalt statt Code, neue Dateien und Endpunkte,
  Reihenfolge der Schema-Dateien fuer ein neues Haus.

Backend mit einer Probe-Etage durchgespielt (auch Fehlerfaelle, Upload,
Aufraeumen); Oberflaeche auf einer Probeseite mit echten Daten und
Zeiger-Ereignissen geprueft: Ziehen, Antippen, Platzieren, neuer Raum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 11:11:10 +02:00
co-authored by Claude Opus 5
parent 62a8af3fc6
commit 8d626abc6d
12 changed files with 1365 additions and 255 deletions
+133
View File
@@ -2606,3 +2606,136 @@ input[type='range']::-webkit-slider-runnable-track {
.floorBtn.active circle { stroke: #00788F; opacity: 1; }
.floorBtn.active text { fill: #e8ede9; opacity: 1; }
/* ===========================================================================
Einstellungen -> Grundriss (js/solar/grundriss.js)
Links der Plan, rechts die Formulare. Die Kachel im Plan sieht aus wie auf
der Startseite (restricted/home.php): dunkles Rechteck, weisse Schrift -
nur ohne Messwerte, dafuer mit Rand, wenn sie gewaehlt ist.
=========================================================================== */
.gr-etagen {
display: flex;
flex-wrap: wrap;
gap: .4rem;
margin-bottom: .9rem;
}
/* Eine Klasse mehr als Bootstrap: solar.css laedt vor AdminLTE. */
.gr-etagen .btn.gr-etage {
display: inline-flex;
align-items: baseline;
gap: .4rem;
border: 1px solid var(--ton-linie-satt, rgba(138, 148, 158, .38));
color: var(--ton-schrift-2, #9aa6ad);
}
.gr-etagen .btn.gr-etage.aktiv {
border-color: #00788F;
color: var(--ton-schrift, #e8ede9);
background: rgba(0, 120, 143, .18);
}
.gr-etage-code { font: 600 .9rem var(--font-anzeige); }
.gr-etage-name { font-size: .75rem; }
.gr-etage-std { font-size: .65rem; color: var(--ton-sonne, #f0b429); }
.gr-plan-huelle {
position: relative;
border-radius: var(--ton-radius-klein, .5rem);
overflow: hidden;
background: #0b0d10;
}
.gr-plan-huelle.platzieren .gr-plan { cursor: crosshair; }
.gr-plan-leer {
aspect-ratio: 4 / 3;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
text-align: center;
color: var(--ton-schrift-3, #6f7a81);
font-size: .85rem;
}
.gr-plan {
display: block;
width: 100%;
height: auto;
touch-action: none;
user-select: none;
}
.gr-ohne-bild {
fill: var(--ton-schrift-3, #6f7a81);
font: 12px sans-serif;
text-anchor: middle;
}
.gr-kachel { cursor: grab; }
.gr-kachel.zieht { cursor: grabbing; }
.gr-kachel rect {
fill: #0006;
stroke: #ffffff55;
stroke-width: .5;
}
.gr-kachel:hover rect { stroke: #ffffffaa; }
.gr-kachel.gewaehlt rect { stroke: var(--ton-sonne, #f0b429); stroke-width: 1; }
.gr-kachel text {
fill: #fff;
font: 4.8px sans-serif;
text-anchor: middle;
pointer-events: none;
}
.gr-geist rect {
fill: rgba(240, 180, 41, .28);
stroke: var(--ton-sonne, #f0b429);
stroke-width: .8;
pointer-events: none;
}
.gr-block {
border: 1px solid var(--ton-linie, rgba(138, 148, 158, .2));
border-radius: var(--ton-radius-klein, .5rem);
padding: .6rem .75rem;
margin-bottom: .6rem;
}
.gr-block-titel {
font-size: .7rem;
letter-spacing: .13em;
text-transform: uppercase;
color: var(--ton-schrift-3, #6f7a81);
margin-bottom: .35rem;
}
.gr-knoepfe {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: .35rem;
margin-top: .6rem;
}
/* Papierkorb wie in der Geraetetafel: erst rot, wenn man ihn anfasst. */
.gr-knoepfe .btn.gr-etage-weg,
.gr-knoepfe .btn.gr-raum-weg {
margin-left: auto;
color: var(--ton-schrift-3, #6f7a81);
}
.gr-knoepfe .btn.gr-etage-weg:hover,
.gr-knoepfe .btn.gr-raum-weg:hover { color: var(--ton-schlecht, #e06060); }
.gr-raeume { display: flex; flex-direction: column; gap: .15rem; }
.gr-raum {
display: flex;
align-items: center;
gap: .4rem;
padding: .1rem .3rem;
border-radius: .35rem;
}
.gr-raum.gewaehlt { background: rgba(240, 180, 41, .12); }
.gr-raum-name {
flex: 1 1 auto;
background: none;
border: 0;
padding: .2rem 0;
color: inherit;
font: inherit;
font-size: .88rem;
text-align: left;
cursor: pointer;
}
.gr-raum-stand { color: var(--ton-schrift-3, #6f7a81); font-size: .8rem; }
.gr-raum .btn.gr-platzieren { padding: 0 .45rem; font-size: .75rem; }