Stage 1 of the GIS Analytical Tools concept — client-side spatial analysis:
- src/analysis/overlay.js: vector overlays (intersect / clip / difference /
union-dissolve) on Turf.js, reprojecting to WGS84 and merging attributes
(intersect keeps both layers', clip keeps only A's).
- src/analysis/zonal.js: vector-in-vector zonal statistics — count / sum /
mean / min / max / total area per zone, with centroid-in-zone (default) or
any-overlap membership.
- Bounding-box pre-filtering in both: only genuinely overlapping pairs reach
the expensive geometry test. 43 zones x 25,004 parcels now completes in
~106 ms; previously it was refused as too large.
- src/analysis-modal.js + markup: Analysis panel with "Apply to" scoping —
whole layer, current map view, selected features, or the catch of a drawn
Circle/Area. Reached from a new "Analyse" dock button.
- MapView.addCOGLayer() for Cloud-Optimized GeoTIFF display (WebGLTile +
GeoTIFF source, imported lazily); listVectorLayers(); getSelectedFeatures().
- Circle/Area analysis popup: one "Export" button (PDF folded into the export
modal as a fourth format, field-rename table hidden for it) plus an
"Analyse" button that opens the panel pre-scoped to the intersecting
features.
- vite.config.js: code-split turf, geotiff and pako so the eager bundle is
unchanged (~283 kB). Giving pako its own chunk also fixes a circular chunk
between jspdf and geotiff, which share it via fast-png.
Drawing-tool fixes carried in the same working tree:
- Delete/Backspace key deletes the selection via the EditBar's Delete
interaction (same undoable block as the button).
- Multi-select: shift-click toggles, Ctrl/Cmd-drag box-selects; helper layers
(vertex overlay, GPS) excluded.
- Undo: split/merge/divide wrapped in undo blocks so one press reverses the
whole operation; vertex-overlay churn no longer pollutes the undo stack;
sources are re-scanned and the stack cleared when edit mode is entered, so
deletes on sub-grouped layers are undoable. NOTE: the undo behaviour is not
yet confirmed on-device.
- ol-ext TouchCursor gated to touch-only devices, so hybrid touchscreen
laptops keep the normal cursor.
Service worker v12 -> v13.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
UPN-grid layer:
- src/database.js — new upn_grid SQLocal table (id, districtid, upn_prefix,
geometry_wkt) + saveUpnGrid / getLocalUpnGrid; cache-once-per-district.
- src/remotedb.js — getUpnGrid → get_upn_grid_per_district.php.
- main.js loadUpnGrid + upnGridToGeoJSON in the Administration group, with
a zoom-aware style: white casing under a bolder violet dashed stroke
(visible against parcels) and upn_prefix labels rendered only when
resolution ≤ 7 m/px (≈ scale ≤ 1:25,000).
- main.js click handler: single click on a UPN-grid cell opens an info
popup showing the upn_prefix.
External-dataset import → staging → upload (client-side complete):
- src/database.js — external_imports + external_import_features tables,
plus createExternalImport / addExternalImportFeatures /
updateExternalImport / getExternalImport / getExternalImportFeatures /
listExternalImports / remapImportedFeatureProperties /
deleteExternalImport. Status enum: imported/mapped/other/uploading/
submitted/migrated/failed (aligned with the database team's staged-
upload model — lu_parcels_upload_tmp + supervisor review).
- src/import-detect.js — pure helpers: detectTargetType(),
autoMapFields(), applyFieldMapping(), listSourceFields() + TARGET_TYPES
/ TARGET_FIELDS registries.
- src/import-modal.js — Bootstrap mapping modal: target dropdown,
field-rename table, three actions (Cancel / Save / Save + Upload now).
- main.js — stageImport hooked into addImportedGeoJSON (the single
convergence point for shp/GeoJSON/KML drops); handleImportModalResult
applies the mapping in one transaction; runUpload builds the real
payload (district_id + api_token from remotePost, user_id_upload from
SSO session, per-feature client_uuid/geom/props) and currently logs +
toasts — the upload_<target>.php endpoints are not yet live.
- index.html — #importMappingModal markup.
- MapView._decorateLayerListItem — import-state chip (Upload N /
spinner / ✓ submitted / ✓ live / N errors) dispatching
lupmis:import-chip-click; src/styles/layerswitcher.css — chip variants.
GIS export from Area / Circle Analysis popups:
- MapView._showAnalysisPopup now accepts an exportContext (clipGeometry +
parcelFeatures + zoneFeatures + otherByLayer) and renders an "Export
GIS" button next to "Export PDF". Click dispatches lupmis:export-gis.
- index.html — #exportGisModal markup.
- src/export-gis-modal.js — Bootstrap modal: format toggle (GeoJSON
default / Shapefile / KML), filename, field-rename table with SHP
10-char DBF warning.
- src/gis-export.js — writers: GeoJSON via Blob, KML via OL KMLFormat,
Shapefile via shp-write (with DBF-safe name sanitiser).
- Adds shp-write@0.3.2 dependency.
MapView style options:
- addGeoJSONLayer now accepts strokeDash for line-dash patterns (used by
the UPN-grid layer and available for any future contextual overlay).
Service Worker v9 → v10 to evict the stale shell/module caches on the
next deploy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>