Textnotizen: neuer Punkt "Notizen (n)" am Auftrag, direkt unter der Sprachnotiz.
Liste mit Betreff, Vorschau und Zeitstempel; antippen oeffnet die Notiz zum Lesen und
Aendern, loeschen mit Rueckfrage. Gespeichert wird ueber api/note.php als
notiz_<betreff>_<datum>.txt im Auftragsordner - derselbe Weg wie bei der Sprachnotiz,
damit die Notiz auch im Dolibarr-Auftrag und in der Anhaenge-Spalte des Bericht-Editors
auftaucht. In "Weitere Dokumente" sind Notizen ausgefiltert, sie haetten dort doppelt
gestanden.
Fotokacheln laden jetzt serverseitige Thumbnails (photo.php?size=thumb) statt der
Originale: rund 10 KB statt mehrerer hundert KB je Kachel. Das <img> haengt direkt an
der URL statt an einer Blob-URL - damit greifen HTTP-Cache und loading="lazy"
tatsaechlich und der Browser laedt parallel. Vorher lief eine sequenzielle Schleife, die
jedes Foto komplett holte, bevor das naechste anfing, und im Fehlerfall ein zweites Mal.
Bericht-Seiten zeigen composite_path, wenn vorhanden - also das im Editor gebaute
Seitenbild mit Anmerkungen statt der Rohdatei. Raster-Layouts bekommen ein Kennzeichen
("4"); Seiten ohne Bildquelle zeigen keine Fehlerkachel mehr.
confirm/alert/prompt sind an allen zehn Stellen durch eigene Modale ersetzt
(confirmDialog/alertDialog/inputDialog). Browser-Dialoge zeigen in der installierten PWA
die Herkunfts-URL und wirken wie ein Systemfehler. Der Hardware-Zurueck-Button schliesst
sie als Abbruch.
Service Worker: eigener Cache baustelle-media (cache-first, LRU 300) fuer Thumbnails.
Vorher war ohne Netz kein einziges schon angesehenes Foto verfuegbar. Der Cache ueberlebt
Deploys bewusst und wird beim Abmelden geleert (CLEAR_MEDIA), damit keine Kundenfotos auf
dem Geraet zurueckbleiben.
Nebenbei behoben:
- .modal-header, .close-btn und .modal-body hatten ueberhaupt kein CSS, obwohl das Markup
sie nutzt (u. a. beim Loeschen eines Berichts) - der Schliessen-Knopf sass unter der
Ueberschrift statt daneben.
- Das Laden eines Thumbnails ueberschrieb den ganzen Kachel-Inhalt und nahm die Overlays
mit: Auswahl-Haekchen und Seitennummer verschwanden, sobald das Bild da war.
- manifest.webmanifest: share_target.action war eine absolute URL auf den Prod-Host und
lag damit ausserhalb des Scopes - der Browser verwarf das share_target komplett. Jetzt
relativ ("share.html"), funktioniert lokal und auf Prod.
ROADMAP.md neu angelegt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7 KiB
ROADMAP — Baustelle PWA
Stand: 2026-08-22 · Gegenstück: data/bericht (Modul-Version 1.5.1)
Die PWA hat kein eigenes Backend — alles läuft über custom/bericht/api/. Punkte, die eine
API-Änderung brauchen, sind mit [API] markiert und stehen zusätzlich in der ROADMAP des
Bericht-Moduls.
1. Nachgezogen aus Bericht 1.5.0 ✅ (2026-08-22, Modul 1.5.1)
Das Modul hatte mit 1.5.0 Infrastruktur bekommen, von der die PWA nichts hatte. Die Beschreibungen unten schildern jeweils den Zustand davor.
1.1 Echte Thumbnails statt Vollbilder ✅ [API]
Bis dahin lud die PWA für jede Kachel das komplette Foto:
loadThumbs()ruftapi.getPhotoBlobUrl(rel, 'small')auf →photo.php?size=smallphoto.phpliefert nur dann ein Thumbnail, wenn Dolibarr eines unterthumbs/<name>_small.<ext>vorgefertigt hat- Die PWA lädt ihre Fotos aber per
orders.php?action=upload_photohoch, und dort wird nievignette()aufgerufen → es existiert nie ein Thumb → es kommt immer das Original - Bei 30 Baustellenfotos sind das im Mobilfunknetz 30 × 0,5–1 MB (bei über die Dolibarr-Oberfläche hochgeladenen Originalen entsprechend mehr)
Das Modul kann das seit 1.5.0 längst: bericht_attachment_thumb($full, $maxside) in
lib/bericht.lib.php (GD, Cache unter bericht/thumbs/, EXIF-Rotation, Speicher-Notbremse).
api/photo.php lädt diese lib bereits.
- [API]
photo.phpumsize=thumb&w=<px>erweitern →bericht_attachment_thumb(), mit ETag aus mtime undCache-Control: private, max-age=…, immutable loadThumbs()umbauen:<img src="…api/photo.php?…&size=thumb">direkt setzen statt fetch → Blob → ObjectURL. Damit greifen HTTP-Cache undloading="lazy"wirklich; heute sind beide wirkungslos, weil der Blob schon vorher komplett geladen wird.- Sequenzielle Schleife auflösen —
for (const t of thumbs) { await … }lädt Foto für Foto nacheinander. Beim<img>-Weg erledigt der Browser das parallel von selbst. - Doppel-Ladung entfernen: schlägt
size=smallfehl, wird das Original noch einmal geladen.
1.2 Aufnahmezeit statt Dateidatum ✅ [API]
1.5.0 hat einen eigenen EXIF-Parser bekommen (bericht_jpeg_taken_at() /
bericht_file_taken_at()), weil im Prod-Container das exif-Modul fehlt. Der Editor sortiert
Anhänge damit nach Aufnahmezeit. orders.php?action=photos lieferte nur filemtime.
- [API]
taken_atje Datei ausgeben - Fotoliste nach Aufnahmezeit sortieren (Auswahl gemerkt, wie im Editor)
1.3 Seiten-Titel kommt nie an ✅ [API]
api/pages.php kann title einer Seite setzen, die PWA rendert ihn (page-title-badge,
openPageActionsModal(…, title)) — aber api/reports.php gibt title im pages-Array
nicht aus. Ein im Editor gesetzter Titel ist in der PWA also unsichtbar, und ein in der PWA
gesetzter Titel scheint nach dem Neuladen verschwunden.
- [API]
'title' => $p->titleinreports.phpergänzen (eine Zeile)
1.4 Bearbeitete Seiten und Raster-Layouts ✅ [API]
Seit 1.5.0 hat eine Seite composite_path (das im Editor gebaute Seitenbild) und layout
(single, grid_2, grid_4, before_after, title_only, …). Die PWA zeigt stur
source_path:
-
Nach Bearbeitung im Desktop-Editor zeigt die PWA weiter das Rohbild ohne Anmerkungen
-
Bei einer Rasterseite ist
source_pathnur eines von bis zu sechs Bildern -
Bei
title_onlygibt es gar keine Quelle → ❌-Kachel -
[API]
composite_pathinreports.phpmit ausgeben -
PWA zeigt
composite_path, wenn vorhanden, sonstsource_path -
Layout-Kennzeichen an der Kachel (z. B. „⊞ 4er-Raster"), damit klar ist, warum dort mehr drauf ist als das eine Foto
2. Verbesserungen unabhängig vom Modul
2.1 Browser-Dialoge raus (10 Stück) ✅
confirm() / alert() / prompt() widersprechen der Hausregel und sehen in der
Standalone-PWA auf Android wie ein Systemfehler aus. Ein sauberes Muster liegt schon vor:
das „Bericht löschen"-Modal in router.on('/reports/:id').
| Stelle | Zeile (vor dem Umbau) |
|---|---|
| PIN stimmt nicht überein | alert 295 |
| Bericht finalisieren | confirm 1111 |
| PIN-Schutz deaktivieren | confirm 1264 |
| Material-Eintrag löschen | confirm 1432 |
| Seite aus Bericht entfernen | confirm 1809 |
| Foto löschen | confirm 2701 |
| Nicht hochgeladenes Foto löschen | confirm 3019 |
| Mess-Skala: Länge eingeben | prompt 3409 |
| Ungültiges Längenformat | alert 3419 |
| „Zuerst kalibrieren" | alert 3440 |
- Eine
confirmDialog({title, text, danger})-Hilfsfunktion (Promise) +inputDialog()für die Längeneingabe, alle zehn Stellen darauf umstellen
2.2 Fotos offline sichtbar halten ✅
Der Service Worker reichte alles unter /custom/bericht/api/ ungecacht durch. Auf der Baustelle
ohne Netz ist damit kein einziges schon angesehenes Foto verfügbar.
- Eigener Runtime-Cache
baustelle-mediafürphoto.php-GETs, cache-first mit Größenbegrenzung (LRU, z. B. 200 Einträge). Die Thumb-URLs aus 1.1 sind dafür der richtige Kandidat — klein und unveränderlich. - Vom App-Shell-Cache getrennt halten, damit ein Deploy die Medien nicht wegräumt
3. Textnotizen ✅ (2026-08-22)
Getippte Notiz zum Auftrag — für alles, was man lieber schreibt als diktiert: Zählernummern, Absprachen, Maße.
- „📝 Notizen (n)" am Auftrag, direkt unter der Sprachnotiz
- Liste mit Betreff, zweizeiliger Vorschau und Zeitstempel; Antippen öffnet zum Lesen und Ändern, 🗑 löscht (mit Rückfrage)
- Editor: Betreff-Feld + Textfeld über die volle Höhe, Speichern über ✓ in der Kopfzeile, Rückfrage beim Verlassen mit ungespeicherten Änderungen
- Ablage als
notiz_<betreff>_<datum>.txtim Auftragsordner (api/note.php) — genau der Weg der Sprachnotiz. Damit auch im Dolibarr-Auftrag und in der Anhänge-Spalte des Bericht-Editors sichtbar. - Notizen sind aus „Weitere Dokumente" ausgefiltert — sie haben ihre eigene Sektion und stünden dort sonst doppelt
Nicht umgesetzt (und bewusst verworfen): eine Zeichenfläche für echte Handschrift. Am Handy ohne Stift ist das unbrauchbar.
Erledigt
2026-08-22
Abschnitte 1, 2 und 3 vollständig. Dazu nebenbei behoben:
.modal-header,.close-btnund.modal-bodyhatten überhaupt kein CSS, obwohl das Markup sie seit Längerem nutzt (u. a. beim Löschen eines Berichts) — der Schließen-Knopf saß dadurch unter der Überschrift statt daneben.- Das Laden eines Thumbnails überschrieb den kompletten Kachel-Inhalt (
t.innerHTML = …) und nahm die Overlays mit: Auswahl-Häkchen in der Mehrfachauswahl und Seitennummer der Bericht-Seiten waren weg, sobald das Bild da war. - Beim Abmelden bleiben keine Kundenfotos mehr auf dem Gerät (
CLEAR_MEDIAan den Service Worker +clearPhotoCache()).
Davor
Siehe README (Feature-Liste) und die Commit-Historie: SSO-Migration auf awlauth, WebAuthn-Login, Neuer-Auftrag-Formular, Live-Kamera mit Persist-First-Queue, Lieferschein-Unterschrift.