- GET /api/geoportal/setup-views checks if zoom views exist
- POST creates them (idempotent)
- SetupBanner component: auto-checks on mount, shows amber banner if
views missing, button to create them, success message with docker
restart reminder, auto-hides when everything is ready
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Feature panel: simplified (NR_CAD/NR_CF/SIRUTA/Suprafata/Proprietari),
aligned top-right under basemap switcher, click empty space to close
- Basemap switch: preserves zoom+center via viewStateRef + moveend listener
- DXF export: use -s_srs + -t_srs (not -a_srs + -t_srs which ogr2ogr rejects)
- Intravilan: double line (black outer + orange inner), z13+, no fill
- Parcel labels: cadastral_ref shown at z16+
- UAT z12: original geometry (no simplification)
- Removed MapLibre popup (only side panel)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Views already select only needed columns, so Martin auto-discovery
serves the same result without needing a config file.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Martin v0.15.0 serves tiles at /{source}/{z}/{x}/{y} without .pbf
extension. Requests with .pbf returned 404.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Basemap switching now recreates the map (basemap in useEffect deps)
instead of buggy remove/re-add that swallowed errors
- OpenTopoMap maxzoom set to 17 (was requesting z19 → 400 errors)
- Basemap maxzoom applied to both source and map maxZoom
Note: Martin vector tiles return 404 — PostGIS views or Martin container
need to be checked on the server.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MapLibre sets position:relative on its container element, which overrides
our absolute inset-0 and causes height to collapse to 0. Using w-full h-full
instead works because the parent (absolute inset-0) has a definite computed
height from positioning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
h-full (height:100%) doesn't propagate through absolutely positioned
parents. The MapLibre container had width=1065 but height=0. Using
absolute inset-0 on the wrapper fills the parent directly via positioning
instead of percentage height.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
height: 100% doesn't work when the parent gets its height from flex-1
(flexbox-computed, not explicit height). Fixed by adding position:relative
to main in fullscreen mode and using absolute inset-0 on the geoportal
container.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add /geoportal to FULLSCREEN_ROUTES (overflow-hidden, no padding)
- Copy maplibre-gl.css to public/ and load from same origin (avoids CDN/CSP)
- Simplify layout: fill parent via h-full w-full (no negative margin hack)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Static CSS import doesn't work with next/dynamic + standalone output.
Now injects a <link> tag to unpkg CDN at module load time (bulletproof).
- Geoportal is now fullscreen: map fills entire viewport below the header,
no duplicate title/description, negative margins bleed to edges.
- Removed page-level CSS imports (no longer needed).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CSS imports inside dynamically loaded components (ssr: false) don't get
included in the production bundle. Importing maplibre-gl CSS at the page
level ensures it's always available. Applied to both geoportal and
parcel-sync pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major geoportal enhancements:
- Basemap switcher (OSM/Satellite/Terrain) with ESRI + OpenTopoMap tiles
- Search bar with debounced lookup (UATs by name, parcels by cadastral ref, owners by name)
- Feature info panel showing enrichment data from ParcelSync (cadastru, proprietari, suprafata, folosinta)
- Parcel selection mode with amber highlight + export (GeoJSON/DXF/GPKG via ogr2ogr)
- Next.js /tiles rewrite proxying to Martin (fixes dev + avoids mixed content)
- Fixed MapLibre web worker relative URL resolution (window.location.origin)
API routes: /api/geoportal/search, /api/geoportal/feature, /api/geoportal/export
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Feature count groupBy query is expensive but data changes rarely.
First request waits for query, subsequent ones return cached instantly.
After 5min, stale cache is returned immediately while background
refresh runs. Badge "N local" is back on UAT dropdown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The groupBy query scanning the entire GisFeature table (~30k+ rows)
was blocking the UAT list API for 25+ seconds on every page load.
Feature counts are now opt-in via ?features=true query param.
Default response is instant (just GisUat table, no joins).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
React's useDeferredValue lets the input update immediately while
deferring the expensive filter (3186 items) to a lower priority.
Removes the setTimeout debounce in favor of React's built-in
concurrent rendering scheduler. Input stays responsive.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Checkbox on each row (ordered selection → numbered files in ZIP)
- "Descarcă selecție (N)" button appears when items selected
- Tooltip shows position in ZIP: "#1 in ZIP", "#2 in ZIP"
- Select-all checkbox in header
- Tooltips on Descarcă tot + Descarcă selecție buttons
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The nested JSON in ePay HTML breaks [^}]* regex. New approach:
find all CF.stringValues independently, find all solutii independently,
then zip them by position (they appear in same order in HTML).
This correctly maps CF number → document for batch orders.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Re-download: all 7 orders re-downloaded using documentsByCadastral
for correct CF→document matching. No more hardcoded order→parcel map.
Tooltips on all CF extract UI elements:
- No extract: "Comandă extras CF (1 credit)"
- Valid: "Valid până la DD.MM.YYYY" + "Descarcă extras CF"
- Expired: "Expirat pe DD.MM.YYYY" + "Comandă extras CF nou (1 credit)"
- Processing: "Comanda în curs de procesare"
Animations: Loader2 spinner while ordering, transition to green check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical fix: batch order documents are now matched by CF number
from parsed metadateCereri (documentsByCadastral), not by index.
Prevents PDF content mismatch when ePay returns docs in different order.
UAT search: name matches shown first, county-only matches after.
Typing "cluj" now shows CLUJ-NAPOCA before county "Cluj" matches.
Cleaned MinIO + DB of incorrectly mapped old test data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major rewrite:
- Queue now processes batches: addToCart×N → saveMetadata×N → ONE
submitOrder → poll → download ALL documents → store in MinIO
- Removed unique constraint on orderId (shared across batch items)
- Added step=download to test endpoint: downloads PDFs from 5
existing orders (9685480-9685484) and stores in MinIO
- step=order now uses enqueueBatch for 2 test parcels (61904, 309952)
as ONE ePay order instead of separate orders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
EditCartSubmit returns 200 (not redirect) — Angular does client-side
redirect to CheckoutConfirmationSubmit.action. Added this step to
actually confirm the order before looking for the orderId.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
submitOrder now captures the previous orderId BEFORE submitting, then
searches for a NEW orderId that isn't in the knownOrderIds set. Queue
passes knownOrderIds between sequential items to prevent duplicate
orderId assignment (unique constraint violation).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Angular uses doPostAsFormMultipart — the save endpoint requires
multipart/form-data, not application/x-www-form-urlencoded.
Install form-data package and restore multipart upload.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
form-data package not installed — crashes at runtime. Use
URLSearchParams instead (the Angular source uses doPostAsForm
which is form-urlencoded, so this should work too).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>