Choosing Shapefile in the Export GIS modal produced no file. shp-write@0.3.2
cannot run in this build, in three separate ways: its dbf dependency assigns an
undeclared variable, which was fine in the browserify bundle it was written for
but is a ReferenceError under the strict mode ES modules always use; its zip.js
branches on process.browser, which does not exist in a browser; and its
download.js delivers the archive by navigating to a data:application/zip URL,
which Chromium blocks in the top frame.
- src/shapefile-write.js writes .shp/.shx/.dbf/.prj/.cpg itself: geometries
split by type into up to three layers, polygon rings re-wound clockwise as
the format requires, DBF column types inferred per column, names sanitised
to DBF's 10 characters and de-duplicated, UTF-8 declared via .cpg.
- src/zip-store.js holds the STORED-ZIP writer that was inside analysis/xlsx.js,
so both writers share it. Pure-ASCII archives are byte-for-byte as before.
- shp-write, and with it dbf and JSZip 2.5.0, leave the dependency tree; the
build no longer warns that node's "assert" was externalised.
- Service Worker v26 for the new bundle.
Verified in a browser: the Export GIS modal, driven through its own controls
with Web Mercator features, produced area_analysis.zip holding both layers with
WGS84 coordinates, file code 9994 and the right shape types. The archive reads
back through the application's own shpjs importer with geometries, numeric,
text and boolean attributes intact. The zonal-statistics .xlsx export, which now
shares the zip writer, still opens and reads correctly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>