4 Commits

Author SHA1 Message Date
c335a8987e Logout: perform full SSO logout via /user-logout
The /?logout=1 endpoint destroyed only the PWA's own PHP session and then
redirected to the bare landing page — which has no session and immediately
blocks access, so the user was never actually logged out of SSO.

- public/index.php: after session_destroy(), redirect to
  https://lupmis4luspa.org/user-logout (the portal's full SSO logout) instead
  of the landing page. Crucially, no longer clear sso_auth_token here —
  /user-logout needs that cookie to identify which SSO session to terminate
  (and it clears the cookie itself). The production access-guard bounce to the
  landing page is unchanged.
- main.js: drop the now-redundant best-effort client call to /sso/logout; the
  server redirect chain (/?logout=1 → /user-logout) owns the SSO logout. Offline
  guard and district-cache wipe unchanged.
- sw.js: update the v12 changelog note (still v12; not yet deployed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 12:29:45 +00:00
d8ddbbc910 Fix stale district + offline-safe logout; GPS UTM format; touch-cursor gating; SW v12
Session / district correctness
- public/index.php: add a /?logout=1 endpoint that destroys the PWA's own PHP
  session (session_destroy + expire PHPSESSID + clear sso_auth_token, then
  redirect to the SSO portal). Logout previously cleared only the SSO cookie,
  leaving the PHPSESSID session — and its frozen district_id — intact, which is
  why a reassigned user kept loading the old district across logout/login.
- SSO token is validated once per session, at login (unchanged first-login
  logic). A district transfer is now picked up on the next logout→login, which
  is correct precisely because logout finally tears the session down. No
  periodic SSO polling.
- main.js: the menu Logout button routes through /?logout=1 and wipes
  district-scoped local caches first. Logout is blocked while offline — a
  session can only be created online, so an offline logout would strand the
  user with no way back in (and would not actually reach the server).
- main.js: enforceDistrictConsistency() clears district-scoped caches when the
  session district changes between loads; the district boundary is cached under
  a per-district key (district_boundary_<id>) so one district's geometry can
  never be served for another.

GPS coordinate format
- New "GPS Coordinate Format" setting (Lat/Lon · UTM · Both) in the Settings
  panel; the navbar read-out renders the chosen format and repaints the current
  fix immediately on change. Self-contained WGS84→UTM converter in
  geo-utils.js, verified against an independent Redfearn-series implementation.

ol-ext touch cursor
- MapView gates the TouchCursor to genuine touch-only devices via matchMedia
  (any-pointer: fine / any-hover: hover); hybrid touchscreen laptops keep the
  normal cursor. Reactive to pointer-capability changes.

- Service worker v11 → v12 (new shell). docs/SSO_Session_Refresh_Proposal.md
  documents the implemented approach.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 11:58:36 +00:00
933bfcf4c0 Permit-map iframe embed, lu_parcels schema, security guards, LayerSwitcher fix
Iframe embed for the Permitting app (LUPMIS2_Reusable_Mapping_Concept §3.2):
- public/embed.php — SSO + production gate + frame-ancestors CSP +
  whitelisted URL params (mode, lon/lat/zoom, upn, basemap,
  application_code); injects window.LUPMIS_SESSION + window.LUPMIS_EMBED.
- public/.htaccess — clean /embed URL (rewrite before the SPA fallback).
- src/embed-bridge.js — postMessage protocol: out ready / parcel:select /
  parcel:cleared / error; in set:view / set:selected / clear:selected /
  set:basemap. Visual highlight via a dedicated VectorLayer; pending-UPN
  queue resolved as parcels stream in.
- main.js — reads window.LUPMIS_EMBED, gates the normal click/dblclick
  handlers in permit mode, exposes parcelsLayer to module scope, makes
  it visible and hands it to the bridge after loadParcels().
- index.html — CSS for body.embed-mode-permit hides navbar/dock/offcanvas
  and lets the map fill the iframe.
- LUPMIS2_Permit_Map_Integration.docx — integration instructions for the
  Permitting team (contract, show.blade.php changes, phasing).

Local lu_parcels structural refactor:
- src/database.js — parcels table now mirrors spatial.lu_parcels with
  explicit columns (upn, style, landuse, zone_code/name, sector, block,
  parcel_no, prop_no, st_name, prop_add, fac_name, min/max_height,
  eff_date, lp_name, locality, mmda, last_update, remarks, geom→geometry_wkt,
  created_at, updated_at, districtid) plus local-only status/fetched_at.
  Drop-and-recreate migration off `upn` presence. saveParcels wraps the
  ~25k inserts in a transaction; numeric coercion via numOrNull.
  updateParcel/insertNewParcel write individual columns.
- main.js parcelsToGeoJSON — handles GeoJSON `geom` object (API) and
  `geometry_wkt` string (local cache); skips housekeeping fields.

Production access guard + no-district overlay:
- public/index.php — on *.lupmis4luspa.org, redirect to the SSO portal
  if no session.
- src/remotedb.js resolveDistrictId — no silent fallback to '1' for an
  authenticated user; dev mode (no session at all) keeps the fallback.
- main.js — blocking overlay if the session lacks district_id; init
  aborts so no API call is made with the wrong scope.

LayerSwitcher ordering fix:
- MapView.initEditBar + MapTools — find the Overlays group by reference
  / title instead of assuming it's the last layer (the GPS layers
  add-layered on top in the constructor broke that assumption).

Service Worker v8 → v9 to evict stale shell/module caches on deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-01 16:20:15 +02:00
cfaceb3487 GPS trail recording, SSO auth, account menu, and mobile/UI refinements
Major:
- GPS trail recording: reusable, dependency-free engine in src/geotracker/
  (GeoTracker + geo-utils) with pluggable storage/sync adapters; LUPMIS
  wiring in src/geotracker-lupmis.js. Expandable My Location control
  (Locate Me + Record Trail), live navbar GPS readout, on-map trail/position
  rendering, gps_trails/gps_trail_points SQLocal tables, and store-and-forward
  sync via pushGpsTrail() -> save_gps_trail.php (server side documented, not
  yet built).
- SSO authentication: public/index.php entry point validates the LUSPA SSO
  cookie and injects window.LUPMIS_SESSION; remotedb district_id is now a
  session-resolved getter. Adds public/.htaccess (DirectoryIndex).
- Account menu offcanvas (navbar burger) with sign-in/out states.

UI / fixes:
- LayerSwitcher modernisation; base-map "None" option in picker + settings.
- Mobile drawing toolbar wraps to two rows below 576px and shows only in
  Draw mode; second row right-aligned and clears the Select option bar.
- Safari bottom-dock clipping fixed (app-container 100dvh -> 100svh).
- Rename public/icons -> app-icons to dodge Apache's default /icons/ alias.
- Service Worker bumped to v8 (network-first HTML, per-provider tile clear).

Docs: reusable-mapping and OSM-3D-buildings concept notes; ignore Office
lock files (~$*). Rebuilt dist/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 16:08:37 +02:00