Wenn die Kundin drei Nachrichten hintereinander schickt, musste man den Auftrag
bisher jedes Mal neu heraussuchen. Jetzt stehen die letzten drei benutzten
Aufträge unter "Zuletzt benutzt" ganz oben.
Wurde einer davon in den letzten 30 Minuten benutzt, ist er vorausgewählt und
der Knopf ist sofort scharf ("In SO2608-0044 ablegen") — die zweite und dritte
Ladung kosten damit einen einzigen Tipp. Nach Ablauf der 30 Minuten steht der
Auftrag nur noch als Schnellzugriff da, ohne Vorauswahl: eine dauerhafte
Vorauswahl würde irgendwann still im Auftrag von vorgestern landen, und die
Auftragsnummer steht deshalb auch immer im Knopftext.
Die Merkliste (IndexedDB 'share_recent_orders') wird beim erfolgreichen Ablegen
fortgeschrieben, neuester zuerst, ohne Duplikate, maximal drei Einträge.
Kartenaufbau und Auswahl-Logik liegen jetzt in gemeinsamen Helfern
(karteHtml/bindeKarten/waehleAuftrag), damit Schnellzugriff und Suchtreffer
denselben Auftrag synchron markieren.
Lokal durchgespielt: erste Ladung ohne Merkliste (keine Vorauswahl), zweite
direkt danach (vorausgewählt, ein Tipp, landet im selben Auftrag), und ein
drei Stunden alter Eintrag (Schnellzugriff sichtbar, aber Knopf grau).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.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.
4. Teilen aus WhatsApp ✅ (2026-08-30)
Bilder und Beschreibungstexte, die die Kundin per WhatsApp schickt, landen direkt im Auftrag. Vorher endete jeder Teilen-Vorgang in einer Sackgasse:
-
share.htmlfragteapi.getToken()— ein JWT in IndexedDB, das es seit der SSO-Umstellung gar nicht mehr gibt (api.login()legt nur nochuserab, die Sitzung steckt im HttpOnly-Cookieawl_sso). Ergebnis: immer „Bitte zuerst anmelden", und der Weg „Zur App" verwarf das Geteilte. -
Der Service Worker sicherte nur Dateien. Ein Text-Share (oder Bild + Bildunterschrift) schrieb nichts in IndexedDB → „Keine geteilten Fotos gefunden".
-
Anmeldung über
api/verify.php(Cookie) statt über das nicht mehr existierende Token -
Anmelden in der Teilen-Seite (Passwort + Passkey) — das Geteilte bleibt dabei gesichert
-
Service Worker sichert
title,textundurlmit; Weiterleitung auch ohne Datei -
Auswahl-Seite: Bildvorschau, Betreff + Text zum Nachbessern, Auftragssuche (ohne Suchbegriff die offenen Aufträge, mit Suchbegriff alle)
-
Ablegen: Bilder über die normale Upload-Queue (Persist-First), Text als Notiz über
api/note.php. Schlägt die Notiz fehl (kein Netz), bleibt der Text gesichert und der Vorgang ist wiederholbar -
Banner in der App, wenn noch etwas Geteiltes unabgelegt bereitliegt
-
Mehrere Nachrichten hintereinander: die letzten drei Aufträge stehen unter „Zuletzt benutzt" oben; innerhalb von 30 Minuten ist der letzte vorausgewählt (danach nur noch Schnellzugriff — eine Dauer-Vorauswahl würde irgendwann im falschen Auftrag landen)
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.