Add session summary and switch inspection diagram docs
This commit is contained in:
parent
f2f9b65916
commit
6162b1b644
|
|
@ -0,0 +1,236 @@
|
||||||
|
# Session Summary: Duimstok PWA MVP Build
|
||||||
|
|
||||||
|
**Date:** 2026-04-16
|
||||||
|
**Project:** ProRail Duimstok-inspecties Bovenbouw
|
||||||
|
**Repo:** https://git.en-masse.nl/randy/duimstok.prorail.nl.git
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Monolithic HTML Refactor
|
||||||
|
|
||||||
|
**Goal:** Split a single-file app (`duimstok-wissel-gw-sw.html`, 1566 lines) into a layered DDD structure.
|
||||||
|
|
||||||
|
**What was done:**
|
||||||
|
- Created `src/Domain/`, `src/Application/`, `src/Infrastructure/` layers
|
||||||
|
- Converted ES modules to classic IIFE scripts attaching to `window.App.*` namespace
|
||||||
|
- Embedded CSV seed data as a string constant in `seedOrders.js` (no `fetch()` needed)
|
||||||
|
- Removed all inline styles (`style=""`) and inline event handlers (`onclick`, `oninput`, etc.)
|
||||||
|
- Replaced inline styles with CSS classes (`.flex-spacer`, `.cap-arrow.lg`, `.section-sub.sm`, `.fotonummers-cell`)
|
||||||
|
- Wired all event listeners via `addEventListener` in `main.js` and service modules
|
||||||
|
|
||||||
|
**Result:** 30 files, ~2163 lines. Runs by double-clicking `public/index.html` -- no server needed.
|
||||||
|
|
||||||
|
**File structure:**
|
||||||
|
|
||||||
|
```
|
||||||
|
01_Applicatie/
|
||||||
|
├── public/
|
||||||
|
│ ├── index.html
|
||||||
|
│ ├── css/ base.css, overview.css, form.css, modals.css, responsive.css
|
||||||
|
│ └── js/ namespace.js, main.js
|
||||||
|
└── src/
|
||||||
|
├── Domain/ sectionMap.js, scoring.js, orderParser.js
|
||||||
|
├── Application/ state.js, persistence.js, screens.js, photoService.js,
|
||||||
|
│ inspectionForm.js, orderOverview.js, xmlImport.js, exportService.js
|
||||||
|
└── Infrastructure/ utils.js, geolocation.js, db.js, seedOrders.js, csvLoader.js
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: PWA Research & Planning
|
||||||
|
|
||||||
|
**Prompt used:** "what are the next steps create a PWA version of this MVP, ideally with offline photo upload functionality which sync when back online. Whats the current supported state of PWA regarding these offline functionalities atm"
|
||||||
|
|
||||||
|
**Key findings:**
|
||||||
|
- Service Worker, Cache API, IndexedDB, Manifest, installability all work cross-browser (Chromium, Firefox, Safari/iOS 16.4+)
|
||||||
|
- Background Sync (`sync` event) only works on Chromium -- not Firefox, not Safari/iOS
|
||||||
|
- Periodic Background Sync: Chromium only (engagement-gated)
|
||||||
|
- Background Fetch: Chromium only
|
||||||
|
- Push notifications: universal for installed PWAs (iOS 16.4+)
|
||||||
|
- Persistent storage: universal, but Safari historically aggressive on eviction
|
||||||
|
|
||||||
|
**Key constraint:** iOS has no true background sync. Design around draining the queue when the user reopens the app and when the `online` event fires.
|
||||||
|
|
||||||
|
**6-step incremental plan identified:**
|
||||||
|
1. Installable shell (manifest + service worker cache)
|
||||||
|
2. Switch photo storage from data URLs to Blobs
|
||||||
|
3. Sync queue in IndexedDB
|
||||||
|
4. Trigger drain on every available signal (online event, app open, SW sync, manual button)
|
||||||
|
5. Persistent storage + install hint
|
||||||
|
6. Backend stub (Symfony controller for POST /api/inspections)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: PWA Scaffold Implementation
|
||||||
|
|
||||||
|
**Prompt used:** "Goal is still conversion later on to Symfony, but for now we do want the PWA functionality (add an additional installation and instruction screen for the PWA installation)"
|
||||||
|
|
||||||
|
**Constraint flagged:** PWA features require HTTPS or localhost -- they cannot work from `file://`.
|
||||||
|
|
||||||
|
**Resolution:** Dual-mode codebase:
|
||||||
|
- `file://` mode: app works exactly as before; PWA init gated by `location.protocol !== 'file:'` and quietly skipped
|
||||||
|
- `http://localhost` or deployed mode: service worker registers, app becomes installable, install screen shows platform-specific instructions
|
||||||
|
|
||||||
|
**Files created:**
|
||||||
|
- `public/manifest.webmanifest` -- app manifest with icons, standalone display, ProRail blue theme
|
||||||
|
- `public/sw.js` -- service worker with app shell precaching (cache-first for statics, network-first for API)
|
||||||
|
- `public/icons/icon.svg` -- SVG app icon (ProRail blue with white ruler lines)
|
||||||
|
- `public/css/install.css` -- styles for the install instruction screen
|
||||||
|
- `src/Application/pwa.js` -- service worker registration, `beforeinstallprompt` capture, standalone detection
|
||||||
|
- `src/Application/installScreen.js` -- platform-specific install instructions (Chrome/Edge, iOS Safari, Firefox, generic)
|
||||||
|
|
||||||
|
**HTML changes:**
|
||||||
|
- Added PWA meta tags (`theme-color`, `apple-mobile-web-app-capable`, manifest link, apple-touch-icon)
|
||||||
|
- Added "Installeren" button to overview toolbar
|
||||||
|
- Added `screen-install` section with back button and dynamic body
|
||||||
|
- Added `<link>` for `install.css`
|
||||||
|
- Added `<script>` tags for `pwa.js` and `installScreen.js`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Git Repository Setup
|
||||||
|
|
||||||
|
**Prompt used:** "ini git repo and commit and push, add files and folders, repo https://git.en-masse.nl/randy/duimstok.prorail.nl.git" + "to the develop branch"
|
||||||
|
|
||||||
|
**Decisions made:**
|
||||||
|
- Repo root: `01_Applicatie/` (app code only; ProRail reference PDFs/photos stay outside)
|
||||||
|
- Deleted old monolithic files: `duimstok-wissel-gw-sw.html` and backup copy
|
||||||
|
- Created `.gitignore` (DS_Store, Thumbs.db, editors, node_modules, env files)
|
||||||
|
- Created `README.md` with project structure documentation
|
||||||
|
- Created `_docs/.gitkeep`
|
||||||
|
|
||||||
|
**Git Flow applied:**
|
||||||
|
1. Initialized repo with `develop` branch -- baseline commit (README, .gitignore, _docs/)
|
||||||
|
2. Created `feature/initial-pwa-scaffold` branch off develop
|
||||||
|
3. Committed all app code (30 files, 2163 insertions)
|
||||||
|
4. Pushed `develop` (baseline only, no staging deploy triggered)
|
||||||
|
5. Pushed `feature/initial-pwa-scaffold` (feature branch, no deploy implications)
|
||||||
|
6. Suggested PR creation on Forgejo before merging to develop
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Photo Blob Storage Refactor
|
||||||
|
|
||||||
|
**Branch:** `feature/photo-blob-storage` (off `feature/initial-pwa-scaffold`)
|
||||||
|
|
||||||
|
**What changed:**
|
||||||
|
- Photos now stored as native `Blob` objects instead of base64 data URLs (~33% smaller)
|
||||||
|
- `photoSrc()` helper uses `URL.createObjectURL(blob)` for rendering thumbnails
|
||||||
|
- `URL.revokeObjectURL()` called on lightbox close and when replacing images (memory cleanup)
|
||||||
|
- Removed `readFileAsDataUrl()` from `utils.js` (no longer needed)
|
||||||
|
- Removed `dataUrlToBlob()` from `utils.js` (no longer needed)
|
||||||
|
- `db.js`: removed `JSON.parse(JSON.stringify(formData))` deep-clone -- IndexedDB handles Blobs natively
|
||||||
|
- `exportService.js`: downloads `p.blob` directly instead of converting from data URL
|
||||||
|
|
||||||
|
**Files changed:** `photoService.js`, `exportService.js`, `db.js`, `utils.js`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6: CSV Upload Persistence
|
||||||
|
|
||||||
|
**Branch:** `feature/csv-upload-persistence`
|
||||||
|
|
||||||
|
**What changed:**
|
||||||
|
- New IndexedDB object store `ordersCsv` (DB version bumped 3 -> 4)
|
||||||
|
- `db.js`: added `saveOrdersCsv(csvText)` and `loadOrdersCsv()` functions
|
||||||
|
- `csvLoader.js`: `loadOrdersFromUpload()` now returns `{ text, orders }` so raw CSV text gets persisted
|
||||||
|
- `main.js` init: loads stored CSV from IndexedDB, falls back to embedded seed data if none stored
|
||||||
|
- `main.js` upload handler: saves CSV text to IndexedDB after parsing
|
||||||
|
|
||||||
|
**Files changed:** `db.js`, `csvLoader.js`, `main.js`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 7: Persistent Storage Request
|
||||||
|
|
||||||
|
**Branch:** `feature/persistent-storage-request`
|
||||||
|
|
||||||
|
**What changed:**
|
||||||
|
- New file `src/Infrastructure/persistentStorage.js` with `isPersisted()` and `requestPersistence()`
|
||||||
|
- Calls `navigator.storage.persist()` after the first successful save (reduces iOS eviction risk)
|
||||||
|
- One-time flag `persistenceRequested` prevents repeated calls
|
||||||
|
- Updated SW cache version to `duimstok-v2`
|
||||||
|
- Added `persistentStorage.js` to both `index.html` script tags and SW precache list
|
||||||
|
|
||||||
|
**Files changed/created:** `persistentStorage.js` (new), `persistence.js`, `sw.js`, `index.html`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 8: Multi-Inspection Type Scoping (Not Yet Implemented)
|
||||||
|
|
||||||
|
**Prompt used:** "continue with question 1: spoor en overweg in map C:\...\04_Gegenereerd door SAP_incl WW_xslx_xlm\XML"
|
||||||
|
|
||||||
|
**Research done:**
|
||||||
|
- Read `_docs/switch-inspection-diagram.md` -- confirms existing wissel_GW photo layout
|
||||||
|
- Read SAP XML templates for Spoor and Overwegbevloering from reference folders
|
||||||
|
- Identified 3 inspection types: Wissel, Overwegbevloering, Spoor
|
||||||
|
|
||||||
|
**Proposed scope for `feature/inspection-type-routing`:**
|
||||||
|
1. Routing layer that derives type from `order.objectsoort`
|
||||||
|
2. Three form panels in `index.html`, shown based on type
|
||||||
|
3. Wissel: no visual change (existing 10-slot layout)
|
||||||
|
4. Overwegbevloering: stub form with photos section, no wissel diagram
|
||||||
|
5. Spoor: stub form emphasizing start/end-KM fields from CSV
|
||||||
|
6. Export works for all three types
|
||||||
|
|
||||||
|
**Status:** Scoped, awaiting answers to 3 questions before implementation.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Global Rules Established
|
||||||
|
|
||||||
|
These rules were added to `~/.claude/CLAUDE.md` during the session:
|
||||||
|
|
||||||
|
| Rule | Context |
|
||||||
|
|------|---------|
|
||||||
|
| **No backwards compatibility in MVPs** | User corrected fallback code for old photo data format |
|
||||||
|
| **No `Co-Authored-By: Claude` in commits** | User interrupted a commit that included the attribution line |
|
||||||
|
| **Git Flow workflow** | User requested: develop = staging, master = production, feature branches for all work |
|
||||||
|
| **`_docs/` for project documentation** | User requested: all docs in project root `_docs/` folder |
|
||||||
|
| **`file://` runnable MVPs** | User requested: must work by opening `public/index.html` directly |
|
||||||
|
| **Vanilla HTML/JS/CSS, no frameworks** | Pre-existing rule (maps to eventual Symfony/Twig conversion) |
|
||||||
|
| **DDD folder structure** | Pre-existing rule (Domain/Application/Infrastructure layers) |
|
||||||
|
| **Forgejo at git.en-masse.nl** | User specified as default remote host |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Shortcuts & Commands Used
|
||||||
|
|
||||||
|
| Command/Action | Purpose | Times Used |
|
||||||
|
|----------------|---------|------------|
|
||||||
|
| `/usage` | Check token consumption | 2x |
|
||||||
|
| `continue` | Resume after idle or interruption | Multiple |
|
||||||
|
| `merge` | Trigger merge-to-develop flow | Multiple |
|
||||||
|
| `yes` / `1` / `3` | Quick selection from numbered options | Multiple |
|
||||||
|
| Interrupted commits | Added global rules mid-flow (no co-author, no backwards compat) | 3x |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git History (Linear on develop)
|
||||||
|
|
||||||
|
```
|
||||||
|
b005193 Request persistent storage after first save
|
||||||
|
92ad6a9 Persist uploaded order CSVs across app restarts
|
||||||
|
e86aa5b Store photos as native Blobs instead of base64 data URLs
|
||||||
|
776bd63 Add PWA-ready MVP: split HTML/CSS/JS + DDD layering + service worker
|
||||||
|
367bbca Initial repo scaffold on develop
|
||||||
|
```
|
||||||
|
|
||||||
|
**Branch lifecycle:**
|
||||||
|
- All feature branches created off `develop` (or stacked off previous feature branch when develop was behind)
|
||||||
|
- All merged via fast-forward (`--ff-only`)
|
||||||
|
- All deleted (local + remote) after merge
|
||||||
|
- Only `develop` remains as active branch
|
||||||
|
- `master` not yet created (awaiting production readiness)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Open Items
|
||||||
|
|
||||||
|
- [ ] Manual verify: capture photo, render thumbnail, reload, check thumbnail persists, export produces valid JPG
|
||||||
|
- [ ] Manual verify: upload CSV, hard-reload, confirm modified orders still appear
|
||||||
|
- [ ] Implement `feature/inspection-type-routing` (Wissel/Overwegbevloering/Spoor forms)
|
||||||
|
- [ ] Create `master` branch when ready for production deployment
|
||||||
|
- [ ] Set up CI on Forgejo
|
||||||
|
- [ ] Backend stub (Symfony POST /api/inspections) to enable sync queue testing
|
||||||
|
- [ ] Authentication for inspectors (currently free-text name -- needs SSO/token discussion with ProRail)
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Switch Inspection Diagram (wissel_GW)
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
`06_Figuren_plaatjes/PDF/Plaatje wissel_GW.pdf`
|
||||||
|
|
||||||
|
A reference diagram used by the Duimstok inspection app to guide the user through photographing a railway switch (Dutch: *wissel*). The `GW` suffix refers to the switch type.
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
The diagram acts as an **interactive photo-capture template**. During an inspection, the user is expected to supply a photograph for each labeled camera position. The blue underlined labels in the PDF are hyperlinks — in the app they map to photo-upload slots.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
Top-down schematic of a single switch, split lengthwise into three color-coded zones:
|
||||||
|
|
||||||
|
| Zone | Color | Dutch label | Description |
|
||||||
|
|------|-------|-------------|-------------|
|
||||||
|
| 1 | Green | Puntstukgedeelte | Frog / crossing section — where the two rails converge |
|
||||||
|
| 2 | Turquoise | Middengedeelte | Middle section — closure rails between frog and points |
|
||||||
|
| 3 | Red | Tongbeweging | Switch-blade / point-motor section — contains the actuator mechanism |
|
||||||
|
|
||||||
|
## Camera positions
|
||||||
|
|
||||||
|
Eight eye/camera icons surround the switch, each tied to a photo slot:
|
||||||
|
|
||||||
|
- **Longitudinal (4×)** — "Overzichtsfoto" (overview photo) at the top-left, top-right, bottom-left, and bottom-right, taken along the track direction.
|
||||||
|
- **Transverse (6×)** — "Foto" (detail photo) on the left and right of each of the three zones, taken perpendicular to the track.
|
||||||
|
|
||||||
|
Total: **10 photo slots per switch inspection** (4 overviews + 6 details).
|
||||||
|
|
||||||
|
## Usage in the app
|
||||||
|
|
||||||
|
- Render the diagram as the visual index on the switch-inspection screen.
|
||||||
|
- Each hyperlink label corresponds to a photo slot in the inspection record.
|
||||||
|
- Slot identifiers should encode both **position** (top/bottom/left/right) and **zone** (frog/middle/blade) so the stored photos can be reassembled into the correct diagram positions in the report.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The diagram is language-dependent (Dutch labels). Any translation must preserve the zone semantics, not just the words.
|
||||||
|
- The actuator (two cylindrical elements at the bottom of the red zone) is drawn in place — detail photos of the *Tongbeweging* zone should capture this mechanism.
|
||||||
Loading…
Reference in New Issue