Commit Graph
24 Commits
Author SHA1 Message Date
Mathieu Moran 3916f9879e feat: FEAT-05 — DTC history sync to remote server
- Server: dtc_events table (migrate_phase27_dtc.sql), db.py helpers
  (upsert_dtc_snapshot, list_dtc_events, delete_dtc_event)
- Server API: POST /api/v1/dtc/batch (device auth), GET/DELETE /api/v1/portal/dtc
- Server portal: /dtc page with code, description, MIL, status, timestamps, delete
- Server nav: DTC history in sidebar + mobile bottom nav
- Pi: _upload_dtc_snapshot() in app_upload.py — uploads when snapshot changes,
  skips when OBD disconnected or unchanged
2026-08-12 01:23:23 -04:00
Mathieu Moran 0b2162a595 style: odometer field uses plaintext display — no stepper arrows, grey background 2026-08-11 23:44:05 -04:00
Mathieu Moran d35cea367f fix: odometer sync is Pi→Server only — portal displays read-only value from DB 2026-08-11 22:14:46 -04:00
Mathieu Moran 44cd8bd192 feat: odometer_baseline field on server portal device settings page 2026-08-11 19:52:51 -04:00
Mathieu Moran 3202045654 fix: restore separate checkbox+ID cells, add matching headers (8 columns server) 2026-08-11 15:25:29 -04:00
Mathieu Moran e8c5bfec9a fix: put checkbox inside date cell — both Pi and server now share same 6-column layout 2026-08-11 15:22:05 -04:00
Mathieu Moran 22f4ae2e69 fix: merge ID into date cell, add empty checkbox header — columns now align 2026-08-11 15:17:51 -04:00
Mathieu Moran 5713417f4f Server: restore checkbox + batch-delete. Conditional ID (server only) and checkbox via data-show-id/data-batch-delete-url. 2026-08-11 15:11:12 -04:00
Mathieu Moran 2ee4862edd Remove checkbox column and batch-delete from trip history 2026-08-11 15:05:40 -04:00
Mathieu Moran 23ac6c218b feat: add trip ID column (#18517) to history table on Pi and server 2026-08-11 14:58:25 -04:00
Mathieu Moran bdc7a9afb7 fix(phase26): server trip delete persists across recompute + batch delete with checkboxes 2026-08-11 04:18:58 -04:00
Mathieu Moran c5c478bef6 fix(phase26): add Pi trip deletion (BUG-08) 2026-08-11 02:07:59 -04:00
Mathieu MoranandCopilot 675bffb4a4 feat: add server-side device deletion
- add portal API and UI action to delete non-default devices
- protect the configured portal default device from deletion
- document that trip/history pages still scope to the single DEVICE_NAME

Co-authored-by: Copilot <[email protected]>
2026-08-10 18:09:15 -04:00
Mathieu MoranandCopilot ba682fbf3a feat: add multi-device provisioning and local remote-config UI
- add multi-device portal device management, key rotation, and sync request APIs
- add Pi settings UI for remote server URL, device name, and API key
- add local test-connection and sync-now actions
- make upload and config sync reuse dynamic shared credentials
- add Phase 25.5c migration and docs updates

Co-authored-by: Copilot <[email protected]>
2026-08-10 18:02:09 -04:00
Mathieu MoranandCopilot 585da18225 feat: add remote device settings portal and Pi hot reload
- add /settings/device portal page and portal device-config GET endpoint
- add portal navigation and client-side device settings editor UI
- hot-reload Account/Car display config after local saves and server syncs
- document portal workflow and Phase 25.5b completion
- add runtime reload tests for account, car, and sync callback

Co-authored-by: Copilot <[email protected]>
2026-08-10 17:34:22 -04:00
Mathieu MoranandCopilot 8f8c03a26a fix: server odometer stat shows 0 when no odometer data exists
COALESCE(MAX(odometer), 0) returned 0 when all tracking rows have NULL
odometer (expected before the car is connected — PID 0xA6 likely unsupported
on 2013 Yaris). Now returns NULL which the overview JS renders as '—'.

Co-authored-by: Copilot <[email protected]>
2026-08-10 05:58:22 -04:00
Mathieu MoranandCopilot f90a5e5826 fix: switch server portal map tiles to CARTO (OSM was rate-limiting/blocking)
OSM tile.openstreetmap.org was returning grey tiles on the portal (likely
rate-limiting the Cloudflare tunnel egress IP). Switch to CARTO Voyager
tiles which are free, CDN-backed, and don't have the same restrictions.

Also add data-tile-subdomains attribute support in history.js so tile
provider subdomains can be configured per-deployment.

Co-authored-by: Copilot <[email protected]>
2026-08-10 05:51:18 -04:00
Mathieu MoranandCopilot c287ab67a3 fix: map zoom limits configurable per-deployment via data attributes
Pi offline tiles only cover zoom 8-15; OSM live tiles support 0-19.
history.js now reads data-min-zoom/data-max-zoom from the #history-map div
instead of hardcoding 3/19. Pi template caps to 8-15 (prevents blank tiles
at extreme zooms), server template allows full 3-19 OSM range.

Co-authored-by: Copilot <[email protected]>
2026-08-10 05:42:04 -04:00
Mathieu MoranandCopilot 21e44a8586 Fix server sidebar collapsed state: hide badge and user footer text
- sidebar-env-badge hidden when collapsed
- sidebar-user-text collapses like nav link spans
- User icon stays centered when collapsed via sidebar-user-footer flex

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:56:44 -04:00
Mathieu MoranandCopilot b172b89318 Simplify delete confirmation to native window.confirm
Bootstrap Modal async was unreliable. Replace with synchronous
window.confirm() which always works and needs no dependencies.

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:52:03 -04:00
Mathieu MoranandCopilot 7aa9ffda16 Add delete with confirmation for trips and dashcam
- Confirmation modal in server base.html (window.confirmDelete promise helper)
- Trip delete: trash button in Replay column (server-only via data-deletable on
  trip-list div), DELETE /api/v1/portal/trip/<id>, removes computed trip only
  (raw tracking_points kept)
- Dashcam delete: trash button next to download, DELETE /api/v1/portal/dashcam/<id>,
  removes from DB + disk (best-effort file removal)
- history.js: delete button gated on data-deletable='1' attribute; click handler
  intercepts before replay logic
- db.py: delete_trip(), delete_dashcam_file() helpers

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:40:22 -04:00
Mathieu MoranandCopilot a13d74e18e Fix remote portal map tiles and geocode
- history.js reads tile URL from data-tile-url attribute on #history-map div,
  falling back to local offline tiles (Pi behavior unchanged)
- server history.html sets data-tile-url to live OSM tiles
- maxZoom raised to 19 (OSM supports it, local tiles were limited to 15)
- server geocode returns 'label' key to match what history.js/yaris.js expect

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:34:49 -04:00
Mathieu MoranandCopilot 64b9481ce0 Phase 24: add password change page
- GET/POST /account/password with CSRF token and bcrypt re-hash
- 'Password' link in sidebar next to Logout
- change_password.html template

Co-authored-by: Copilot <[email protected]>
2026-08-10 04:22:28 -04:00
Mathieu MoranandCopilot c4dfcbaf25 Phase 24: remote trip + dashcam portal
- Add Flask-Login browser session auth (separate from device X-Api-Key auth)
  - modules/user_auth.py: User model, require_login decorator, bcrypt helpers
  - /login with CSRF token, /logout
  - scripts/create_user.py to provision admin user

- Add server-side trip computation from tracking_points
  - db.compute_trips_for_device(): gap > 5 min = new trip, haversine distance,
    upserts into trips table, auto-triggered in bg thread after each upload batch
  - db.list_trips(), db.get_trip_route(): same JSON shape as Pi API
  - db.get_overview_stats(): aggregated totals for overview page
  - db.list_dashcam_files(), db.get_dashcam_file(): browse/stream helpers

- Add web portal to server/app.py
  - Overview page (/): stat cards + recent trips + recent clips
  - Trip history (/history): reuses Pi history.js + data-list.js unchanged
    via /api/trips + /api/trip/<id> compatibility aliases
  - Dashcam archive (/dashcam): file list + inline video player
  - /api/v1/portal/dashcam/stream/<id>: Range-request streaming, path traversal guard
  - /api/geocode: same Nominatim→reverse_geocoder offline fallback as Pi

- Add server templates (server/templates/)
  - base.html: shared shell with 'Remote server' badge in sidebar + mobile topbar
  - login.html, index.html, history.html, dashcam.html, components.html

- DB schema: users + trips tables added to init.sql (fresh deploys) +
  migrate_phase24.sql (existing deployments)

- Infrastructure: Dockerfile uses repo-root build context to copy shared
  static/ assets; docker-compose updated; SECRET_KEY + DEVICE_NAME in .env;
  requirements: Flask-Login, bcrypt, reverse_geocoder

Co-authored-by: Copilot <[email protected]>
2026-08-10 03:58:45 -04:00