2 bugs:
1. After Magic/base download completes, progress bar stayed stuck at
77% because exportProgress was never updated to 'done' client-side.
Fix: set progress to 'Finalizat' + 100% after successful blob download.
2. syncLayer overwrote the export route's weighted percentages (0-100)
with raw feature counts (50/200), causing progress bar to jump.
Fix: when isSubStep=true, sync writes phase/note/phaseCurrent/phaseTotal
but preserves the parent route's downloaded/total weighted values.
3 bugs fixed:
- syncLayer was called without jobId -> user saw no progress duringSync
- syncLayer set status:'done' prematurely -> client stopped polling before GPKG phase
- syncLayer errors were silently ignored -> confusing 'no features in DB' error
Added isSubStep option to syncLayer: when true, keeps status as 'running'
and doesn't schedule clearProgress. Export routes now pass jobId + isSubStep
so the real sync progress (Descărcare features 50/200) is visible in the UI.
- Rewrite export-bundle to sync-first: check freshness -> sync layers -> enrich (magic) -> build GPKG/CSV from local DB
- Rewrite export-layer-gpkg to sync-first: sync if stale -> export from DB
- Create enrich-service.ts: extracted magic enrichment logic (CF, owners, addresses) with DB storage
- Add enrichment + enrichedAt columns to GisFeature schema
- Update PostGIS views to include enrichment data
- UI: update button labels for sync-first semantics, refresh sync status after exports
- Smart caching: skip sync if data is fresh (168h / 1 week default)
- resolveWorkspace: use listLayer() instead of listLayerByWhere() with
hardcoded field names. Auto-discovers admin field (ADMIN_UNIT_ID/SIRUTA)
from ArcGIS layer metadata via buildWhere().
- resolveWorkspace: persist WORKSPACE_ID to DB on first resolution for
fast subsequent lookups.
- UATs POST: seed from uat.json (correct SIRUTA codes) instead of eTerra
nomenclature API (nomenPk != SIRUTA, county nomenPk != WORKSPACE_ID).
- Remove eTerra nomenclature dependency from UATs endpoint.
- Fix activeJobs Set iteration error on container restart.
- Remove unused enrichedUatsFetched ref.
- Add fetchNomenByPk() to EterraClient single nomen entry lookup
- resolveWorkspace() now tries fast path first: direct nomen lookup for
SIRUTA walk parentNomenPk chain to find COUNTY (1-3 calls vs 42+)
- Falls back to full county scan only if direct lookup fails
- Search route: DB lookup as middle fallback between workspacePk and resolve
- Debug logging to trace workspace resolution on production
- Fix: try all possible UAT identifier fields (nomenPk, siruta, code, pk)
- New /api/eterra/uats endpoint fetches all counties + UATs from eTerra,
caches server-side for 1 hour, returns enriched data with county name
and workspacePk for each UAT
- When eTerra is connected, auto-fetches enriched UAT list (replaces
static uat.json fallback) shows 'FELEACU (57582), CLUJ' format
- UAT autocomplete now searches both UAT name and county name
- Selected UAT stores workspacePk in state, passes it directly to
/api/eterra/search eliminates slow per-search county resolution
- Search route accepts optional workspacePk, falls back to resolveWorkspace()
- Dropdown shows UAT name, SIRUTA code, and county prominently
- Increased autocomplete results from 8 to 12 items
Search tab now uses eTerra application API (same as the web UI):
- POST /api/eterra/search queries /api/immovable/list with exact
identifierDetails filter + /api/documentation/data for full details
- Returns: nr cad, nr CF, CF vechi, nr topo, suprafata, intravilan,
categorii folosinta, adresa, proprietari, solicitant
- Automatic workspace (county) resolution from SIRUTA with cache
- Support for multiple cadastral numbers (comma separated)
UI changes:
- Detail cards instead of flat ArcGIS feature table
- Copy details to clipboard button per parcel
- Add parcels to list + CSV export
- Search list with summary table + CSV download
- No more layer filter or pagination (not needed for app API)
New EterraClient methods:
- searchImmovableByIdentifier (exact cadaster lookup)
- fetchCounties / fetchAdminUnitsByCounty (workspace resolution)
- Add session-store.ts: global singleton for shared eTerra session state
with job tracking (registerJob/unregisterJob/getRunningJobs)
- Add GET/POST /api/eterra/session: connect/disconnect with job-running guard
- Export routes: credential fallback chain (body > session > env vars),
register/unregister active jobs for disconnect protection
- Login route: also creates server-side session
- ConnectionPill: session-aware display with job count, no credential form
- Auto-connect: triggers on first UAT keystroke via autoConnectAttempted ref
- Session polling: all clients poll GET /api/eterra/session every 30s
- Multi-client: any browser sees shared connection state