No locations yet.
Click the map or fill the form above!
@@ -822,15 +826,15 @@ This only affects the current session — built-in layers cannot be removed.`))r
`}).join(""),n.classList.remove("d-none"),e.querySelectorAll(".table-name-link").forEach(o=>{o.addEventListener("click",a=>{a.preventDefault(),al(o.dataset.table)})}),e.querySelectorAll(".table-clear-btn").forEach(o=>{o.addEventListener("click",async a=>{a.preventDefault();const i=o.dataset.table;if(confirm(`Clear local cache for "${i}"?
-The data will be re-downloaded from the server on the next app start.`))try{const s=await rr(i);ge(`Cleared ${s} row${s===1?"":"s"} from "${i}". It will re-download on next start.`),await $t()}catch(s){console.error("[App] Per-table clear failed:",s),F(`Could not clear "${i}": ${s.message}`)}})})}catch(r){console.error("[App] Failed to load table stats:",r),e.innerHTML='
Failed to load ',n.classList.remove("d-none")}t&&!t._wired&&(t._wired=!0,t.addEventListener("click",rl))}}async function rl(){if(confirm(`Delete all cached map layers from this device?
+The data will be re-downloaded from the server on the next app start.`))try{const s=await rr(i);ge(`Cleared ${s} row${s===1?"":"s"} from "${i}". It will re-download on next start.`),await $t()}catch(s){console.error("[App] Per-table clear failed:",s),O(`Could not clear "${i}": ${s.message}`)}})})}catch(r){console.error("[App] Failed to load table stats:",r),e.innerHTML='
Failed to load ',n.classList.remove("d-none")}t&&!t._wired&&(t._wired=!0,t.addEventListener("click",rl))}}async function rl(){if(confirm(`Delete all cached map layers from this device?
-The next time the app starts (or after a reload), every layer will be re-downloaded from the server. Your locally drawn data is not affected.`))try{const n=await Io(),e=n.reduce((t,r)=>t+r.count,0);ge(`Cleared ${e} row${e===1?"":"s"} across ${n.length} table${n.length===1?"":"s"}.`),await $t(),confirm("Reload the app now to re-download the layers fresh from the server?")&&window.location.reload()}catch(n){console.error("[App] Clear-all failed:",n),F("Failed to clear cached layers: "+n.message)}}async function al(n){const e=document.getElementById("tableContentModalLabel"),t=document.getElementById("table-content-body"),r=document.getElementById("table-content-info");e.textContent=`Table: ${n}`,t.innerHTML=`
+The next time the app starts (or after a reload), every layer will be re-downloaded from the server. Your locally drawn data is not affected.`))try{const n=await Io(),e=n.reduce((t,r)=>t+r.count,0);ge(`Cleared ${e} row${e===1?"":"s"} across ${n.length} table${n.length===1?"":"s"}.`),await $t(),confirm("Reload the app now to re-download the layers fresh from the server?")&&window.location.reload()}catch(n){console.error("[App] Clear-all failed:",n),O("Failed to clear cached layers: "+n.message)}}async function al(n){const e=document.getElementById("tableContentModalLabel"),t=document.getElementById("table-content-body"),r=document.getElementById("table-content-info");e.textContent=`Table: ${n}`,t.innerHTML=`
- `,r.textContent="",new ht(document.getElementById("tableContentModal")).show();try{const{columns:a,rows:i}=await za(n);if(i.length===0){t.innerHTML='
Table is empty
',r.textContent="0 rows";return}const s=a.map(c=>`
${U(c)} `).join(""),l=i.map(c=>`
${a.map(u=>{let f=c[u];if(f==null)return'NULL ';f=String(f);const p=f.length>120?f.substring(0,120)+"...":f;return`${U(p)} `}).join("")} `).join("");t.innerHTML=`
+ `,r.textContent="",new ht(document.getElementById("tableContentModal")).show();try{const{columns:a,rows:i}=await qa(n);if(i.length===0){t.innerHTML='
Table is empty
',r.textContent="0 rows";return}const s=a.map(c=>`
${U(c)} `).join(""),l=i.map(c=>`
${a.map(u=>{let p=c[u];if(p==null)return'NULL ';p=String(p);const f=p.length>120?p.substring(0,120)+"...":p;return`${U(f)} `}).join("")} `).join("");t.innerHTML=`
@@ -839,7 +843,7 @@ The next time the app starts (or after a reload), every layer will be re-downloa
${l}
- `,r.textContent=`${i.length}${i.length>=200?"+":""} row(s), ${a.length} column(s)`}catch(a){console.error("[App] Failed to load table content:",a),t.innerHTML=`
Failed to load: ${U(a.message)}
`}}async function il(){try{await Ga("lupmis-backup.sqlite3"),ge("Database exported successfully")}catch(n){console.error("[App] Export failed:",n),F("Export failed: "+n.message)}}async function sl(){try{const n=await ja(),e=new Blob([JSON.stringify(n,null,2)],{type:"application/json"}),t=URL.createObjectURL(e),r=document.createElement("a");r.href=t,r.download="locations.geojson",r.click(),URL.revokeObjectURL(t),ge(`Exported ${n.features.length} location(s)`)}catch(n){console.error("[App] GeoJSON Export failed:",n),F("GeoJSON Export failed: "+n.message)}}async function ll(){try{const n=await ko(),e=document.getElementById("status-content");e&&(e.innerHTML=`
+ `,r.textContent=`${i.length}${i.length>=200?"+":""} row(s), ${a.length} column(s)`}catch(a){console.error("[App] Failed to load table content:",a),t.innerHTML=`
Failed to load: ${U(a.message)}
`}}async function il(){try{await Ga("lupmis-backup.sqlite3"),ge("Database exported successfully")}catch(n){console.error("[App] Export failed:",n),O("Export failed: "+n.message)}}async function sl(){try{const n=await ja(),e=new Blob([JSON.stringify(n,null,2)],{type:"application/json"}),t=URL.createObjectURL(e),r=document.createElement("a");r.href=t,r.download="locations.geojson",r.click(),URL.revokeObjectURL(t),ge(`Exported ${n.features.length} location(s)`)}catch(n){console.error("[App] GeoJSON Export failed:",n),O("GeoJSON Export failed: "+n.message)}}async function ll(){try{const n=await ko(),e=document.getElementById("status-content");e&&(e.innerHTML=`
@@ -864,7 +868,7 @@ The next time the app starts (or after a reload), every layer will be re-downloa
- `),new ht(document.getElementById("statusModal")).show()}catch(n){console.error("[App] Failed to get status:",n),F("Failed to get status")}}function Pr(n){return n.replace(/^\(+/,"").replace(/\)+$/,"").split(",").map(e=>{const[t,r]=e.trim().split(/\s+/).map(Number);return[t,r]})}function cl(n){return{type:"Polygon",coordinates:n.trim().replace(/^POLYGON\s*\(\s*/i,"").replace(/\s*\)$/,"").split("),(").map(Pr)}}function dl(n){return{type:"MultiPolygon",coordinates:n.trim().replace(/^MULTIPOLYGON\s*\(\s*/i,"").replace(/\s*\)$/,"").split(")),((").map(o=>o.replace(/^\(+/,"").replace(/\)+$/,"").split("),(").map(Pr))}}function gt(n){if(!n)return null;const e=n.trim().toUpperCase();return e.startsWith("MULTIPOLYGON")?dl(n):e.startsWith("POLYGON")?cl(n):(console.warn("[App] Unsupported WKT type:",e.substring(0,30)),null)}function ul(n){if(!n?.success||!n?.data?.boundary)return console.warn("[App] API response missing success or boundary data"),null;const{boundary:e,districtid:t,district_name:r}=n.data,o=gt(e);return{type:"FeatureCollection",features:[{type:"Feature",properties:{districtid:t,district_name:r},geometry:o}]}}function Fn(n){if(!Array.isArray(n)||n.length===0)return null;const e=[];for(const t of n){const r=t.polygon||t.boundary,o=gt(r);if(!o)continue;const a={_layerType:"collector_zone"};for(const[i,s]of Object.entries(t))i==="polygon"||i==="boundary"||(a[i]=s);e.push({type:"Feature",properties:a,geometry:o})}return e.length===0?null:{type:"FeatureCollection",features:e}}const vo="lupmis-last-district";function pl(n){return n==null||String(n).length===0?"district_boundary":`district_boundary_${n}`}async function fl(){const e=Ke()?.district_id;if(e==null||String(e).length===0)return;const t=String(e);let r=null;try{r=localStorage.getItem(vo)}catch{}if(r!==null&&r!==t){console.warn(`[App] District changed ${r} → ${t}; clearing cached layers.`);try{await Io(),Do("Your district was updated — refreshing map data.")}catch(o){console.error("[App] Failed to clear caches on district change:",o)}}try{localStorage.setItem(vo,t)}catch{}}async function hl(){const n=Ke()?.district_id??null,e=pl(n),t=1,r={strokeColor:"#e11d48",strokeWidth:2.5,fillColor:"rgba(225,29,72,0.08)",typeDescription:"Vector / Polygon"},o=E?.getLayerGroup(t)||null;function a(s){if(!s)return;const l=s.getLayers(),c=[];l.forEach(d=>{d.get("title")==="District Boundary"&&c.push(d)}),c.forEach(d=>l.remove(d))}function i(s){if(!s||!E)return;const l=s.getSource().getExtent();l&&l[0]!==1/0&&E.getMap().getView().fit(l,{padding:[40,40,40,40],duration:600})}try{const s=V()&&Te(),l=await er(e);if(l){console.log("[App] District boundary loaded from local cache");const c=E?.addGeoJSONLayer(l,"District Boundary",r,o);s||i(c)}if(s){console.log("[App] Fetching district boundary from API...");const c=await ts(),d=ul(c);if(!d){console.warn("[App] Could not convert API response to GeoJSON");return}console.log("[App] District boundary:",d.features[0]?.properties?.district_name,"→",d.features[0]?.geometry?.coordinates?.length,"polygon(s)"),await Qn(e,d),l&&a(o||E?.getOverlayGroup());const u=E?.addGeoJSONLayer(d,"District Boundary",r,o);i(u),console.log("[App] District boundary loaded from API")}else l||console.log("[App] District boundary not available — offline and no local cache")}catch(s){console.error("[App] Failed to load district boundary:",s)}}function On(n){if(!Array.isArray(n)||n.length===0)return null;const e=[];for(const t of n){const r=t.polygon||t.geometry_wkt||t.geom,o=gt(r);o&&e.push({type:"Feature",properties:{_layerType:"upn_grid",upn_prefix:t.upn_prefix??null},geometry:o})}return e.length===0?null:{type:"FeatureCollection",features:e}}async function gl(){const e={strokeColor:"#5b21b6",strokeWidth:1.5,fillColor:"rgba(124,58,237,0.04)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(1)||null,r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"UPN Grid",e,t);if(!o){console.warn("[App] Could not create UPN Grid layer");return}o.setVisible(!1);const a=7;o.setStyle((s,l)=>{const c=[new M({stroke:new I({color:"rgba(255,255,255,0.95)",width:3.5})}),new M({stroke:new I({color:"#5b21b6",width:1.5,lineDash:[7,4]}),fill:new A({color:"rgba(124,58,237,0.04)"})})];if(l<=a){const d=s.get("upn_prefix");d!=null&&String(d).length>0&&c.push(new M({text:new pt({text:String(d),font:"600 12px Arial, sans-serif",fill:new A({color:"#3b0764"}),stroke:new I({color:"rgba(255,255,255,0.95)",width:3}),overflow:!0})}))}return c}),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&F("No UPN grid available locally. Connect to the internet to download it.")});function i(s){const l=new le().readFeatures(s,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(l)}try{const l=Ke()?.district_id??null,c=await xa(l);if(c){const p=On(c);p&&i(p),console.log("[App] UPN grid from cache:",c.length,"cells (district",l,")");return}if(!V()||!Te()){console.log("[App] UPN grid not available — offline and no cache for district",l);return}console.log("[App] Fetching UPN grid from API (district",l,")...");const d=await ls();if(!d?.success||!Array.isArray(d?.data)){console.warn("[App] getUpnGrid invalid response:",d);return}const u=d.data;console.log("[App] UPN grid from API:",u.length,"cells"),await Ea(u,l);const f=On(u);f&&i(f),console.log("[App] UPN grid loaded:",f?.features.length??0,"cells rendered")}catch(s){console.error("[App] Failed to load UPN grid:",s)}}async function ml(){const e={strokeColor:"#7c3aed",strokeWidth:1.5,fillColor:"rgba(124,58,237,0.12)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(1)||null;console.log("[App] loadCollectorZones — adminGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"Zones",e,t);if(!o){console.warn("[App] Could not create Zones layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&F("No collector zones available locally. Connect to the internet to download zone data.")});function a(i){const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(s)}try{const i=await va();if(i){const s=Fn(i);s&&(console.log("[App] Collector zones loaded from local cache:",s.features.length,"zones"),a(s))}if(V()&&Te()){console.log("[App] Fetching collector zones from API...");const s=await ns();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getCollectorZones API response invalid:",s);return}const l=s.data;console.log("[App] Collector zones from API:",l.length,"entries"),await _a(l);const c=Fn(l);if(!c){console.warn("[App] Could not convert zones to GeoJSON");return}a(c),console.log("[App] Collector zones updated from API:",c.features.length,"zones")}else i||console.log("[App] Collector zones not available — offline and no local cache")}catch(i){console.error("[App] Failed to load collector zones:",i)}}function Dn(n){if(!Array.isArray(n)||n.length===0)return null;const e=new Set,t=[];for(const r of n){const o=r.id||r.parcelid||r.parcel_id;if(o!=null){if(e.has(o))continue;e.add(o)}let a=null;if(r.geom&&r.geom.type&&r.geom.coordinates)a={type:r.geom.type,coordinates:r.geom.coordinates};else if(r.sp_boundary&&r.sp_boundary.type&&r.sp_boundary.coordinates)a={type:r.sp_boundary.type,coordinates:r.sp_boundary.coordinates};else{const l=r.boundary||r.geometry_wkt||r.polygon||r.wkt;a=gt(l)}if(!a)continue;const i=new Set(["polygon","boundary","geom","geometry_wkt","wkt","textboundary","sp_boundary","fetched_at"]),s={_layerType:"parcel"};for(const[l,c]of Object.entries(r))i.has(l)||(s[l]=c);t.push({type:"Feature",properties:s,geometry:a})}return t.length===0?null:{type:"FeatureCollection",features:t}}async function yl(){const e={strokeColor:"#0ea5e9",strokeWidth:1.5,fillColor:"rgba(14,165,233,0.12)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(4)||null;console.log("[App] loadParcels — landUseGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]};if(se=E?.addGeoJSONLayer(r,"Parcels",e,t),!se){console.warn("[App] Could not create Parcels layer");return}se.setVisible(!1),se.on("change:visible",()=>{se.getVisible()&&se.getSource().getFeatures().length===0&&F("No parcels available locally. Connect to the internet to download parcel data.")});function o(a){const i=new le().readFeatures(a,{featureProjection:"EPSG:3857"});se.getSource().clear(),se.getSource().addFeatures(i)}try{const a=await Ca();if(a){const i=Dn(a);i&&(console.log("[App] Parcels loaded from local cache:",i.features.length,"parcels"),o(i))}if(V()&&Te()){console.log("[App] Fetching parcels from API...");const i=await rs();if(!i?.success||!Array.isArray(i?.data)){console.warn("[App] getDistrictParcels API response invalid:",i);return}const s=i.data;console.log("[App] Parcels from API:",s.length,"entries"),s.length>0&&console.log("[App] First parcel keys:",Object.keys(s[0])),await Aa(s);const l=Dn(s);if(!l){console.warn("[App] Could not convert parcels to GeoJSON");return}o(l),console.log("[App] Parcels updated from API:",l.features.length,"parcels")}else a||console.log("[App] Parcels not available — offline and no local cache")}catch(a){console.error("[App] Failed to load parcels:",a)}}function Rn(n){if(!Array.isArray(n)||n.length===0)return null;const e=["polygon","boundary","geom","wkt","footprint"],t=[];for(const r of n){const o=r.polygon||r.boundary||r.geom||r.wkt||r.footprint;let a;if(typeof o=="object"&&o!==null&&o.type?a=o:a=gt(o),!a)continue;const i={_layerType:"building_footprint"};for(const[s,l]of Object.entries(r))e.includes(s)||typeof l=="object"&&l!==null||(i[s]=l);t.push({type:"Feature",properties:i,geometry:a})}return t.length===0?null:{type:"FeatureCollection",features:t}}async function bl(){const e={strokeColor:"#8b6f47",strokeWidth:1,fillColor:"rgba(139,111,71,0.18)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(5)||null;console.log("[App] loadBuildingFootprints — physInfraGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"Building footprints",e,t);if(!o){console.warn("[App] Could not create Building footprints layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&F("No building footprints available locally. Connect to the internet to download footprint data.")});function a(i){const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(s)}try{const i=await Ra();if(i){const s=Rn(i);s&&(console.log("[App] Building footprints loaded from local cache:",s.features.length,"footprints"),a(s))}if(V()&&Te()){console.log("[App] Fetching building footprints from API...");const s=await as();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getBuildingFootprints API response invalid:",s);return}const l=s.data;console.log("[App] Building footprints from API:",l.length,"entries"),l.length>0&&console.log("[App] First footprint keys:",Object.keys(l[0])),await Da(l);const c=Rn(l);if(!c){console.warn("[App] Could not convert building footprints to GeoJSON");return}a(c),console.log("[App] Building footprints updated from API:",c.features.length,"footprints")}else i||console.log("[App] Building footprints not available — offline and no local cache")}catch(i){console.error("[App] Failed to load building footprints:",i)}}function Mr(n,e){if(!Array.isArray(n)||n.length===0)return null;const t=new So,r=new le,o=["geom","geometry","wkt","polygon","boundary","road","line"],a=[];for(const i of n){const s=i.geom||i.geometry||i.wkt||i.polygon||i.boundary||i.road||i.line;if(!s)continue;let l;try{if(typeof s=="object"&&s!==null&&s.type){a.push({type:"Feature",properties:Nn(i,o,e),geometry:s});continue}l=t.readGeometry(s)}catch(d){console.warn(`[App] Could not parse WKT for ${e}:`,d,s?.toString().slice(0,60));continue}const c=JSON.parse(r.writeGeometry(l));a.push({type:"Feature",properties:Nn(i,o,e),geometry:c})}return a.length===0?null:{type:"FeatureCollection",features:a}}function Nn(n,e,t){const r={_layerType:t};for(const[o,a]of Object.entries(n))e.includes(o)||typeof a=="object"&&a!==null||(r[o]=a);return r}async function wl(){const n={strokeColor:"#78716c",strokeWidth:.8,typeDescription:"Vector / Line",fillColor:"rgba(0,0,0,0)"},e=E?.getLayerGroupByTitle("Biophysical Environment");console.log("[App] loadContoursHillshade — group:",e?e.get("title"):"null");const t={type:"FeatureCollection",features:[]},r=E?.addGeoJSONLayer(t,"Contours hillshade",n,e);if(!r){console.warn("[App] Could not create Contours hillshade layer");return}if(r.setVisible(!1),r.on("change:visible",()=>{r.getVisible()&&r.getSource().getFeatures().length===0&&F("No Contours hillshade data available. Connect to the internet to download it.")}),!V()||!Te()){console.log("[App] Contours hillshade not available — offline or server unreachable");return}try{console.log("[App] Fetching contours_hillshade from API...");const o=await is();if(!o?.success||!Array.isArray(o?.data)){console.warn("[App] getContoursHillshade API response invalid:",o);return}const a=o.data;console.log("[App] Contours hillshade from API:",a.length,"rows"),a.length>0&&console.log("[App] First row keys:",Object.keys(a[0]));const i=Mr(a,"contours_hillshade");if(!i){console.warn("[App] Could not convert contours to GeoJSON");return}const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});r.getSource().clear(),r.getSource().addFeatures(s),console.log("[App] Contours hillshade loaded:",s.length,"features")}catch(o){console.error("[App] Failed to load contours_hillshade:",o)}}async function _l(){const e={strokeColor:"#F0F1F0",strokeWidth:1.5,lineCasingColor:"#000000",lineCasingWidth:3.5,fillColor:"rgba(0,0,0,0)",typeDescription:"Vector / Line"},t=E?.getLayerGroup(5)||null;console.log("[App] loadOSMRoads — group:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"OSM_roads",e,t);if(!o){console.warn("[App] Could not create OSM_roads layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&F("No OSM roads available locally. Connect to the internet to download them.")});function a(i){const s=Mr(i,"osm_road");if(!s)return console.warn("[App] Could not convert OSM roads to GeoJSON"),0;const l=new le().readFeatures(s,{featureProjection:"EPSG:3857"});return o.getSource().clear(),o.getSource().addFeatures(l),l.length}try{const i=await $a();if(i){const s=a(i);console.log("[App] OSM_roads loaded from local cache:",s,"features")}if(V()&&Te()){console.log("[App] Fetching OSM_roads from API...");const s=await ss();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getOSMRoads API response invalid:",s);return}const l=s.data;console.log("[App] OSM_roads from API:",l.length,"rows"),l.length>0&&console.log("[App] First row keys:",Object.keys(l[0])),await Na(l);const c=a(l);console.log("[App] OSM_roads updated from API:",c,"features")}else i||console.log("[App] OSM_roads not available — offline and no local cache")}catch(i){console.error("[App] Failed to load OSM_roads:",i)}}function vl(){E?.addWMSLayer("Biophysical Environment","DEAfrica Coastlines v0.4","https://geoserver.digitalearth.africa/geoserver/wms","coastlines:DEAfrica_Coastlines",{serverType:"geoserver",visible:!1,onlineOnly:!0}),E?.addWMSLayer("Biophysical Environment","DEAfrica Slope (SRTM 30m)","https://ows.digitalearth.africa/wms","srtm_deriv",{serverType:null,style:"style_slope",visible:!1,opacity:.5,zIndex:-50,onlineOnly:!0,attributions:'©
Digital Earth Africa — SRTM-derived Slope',legendUrl:"https://ows.digitalearth.africa/legend/srtm_deriv/style_slope/legend.png"})}async function El(){const n="layer_categories";function e(t){const r=[...t].sort((o,a)=>a.id-o.id);for(const o of r)E?.addLayerGroup(o.id,o.name,o.description||"");console.log("[App] Created",t.length,"layer groups on map")}try{const t=await er(n);if(t&&(console.log("[App] Layer categories loaded from local cache:",t.length,"entries"),e(t)),V()&&Te()){console.log("[App] Fetching layer categories from API...");const r=await os();if(!r?.success||!Array.isArray(r?.data)){console.warn("[App] getLayers API response invalid:",r);return}const o=r.data;if(console.log("[App] Layer categories from API:",o.length,"entries"),await Qn(n,o),t){const a=E?.getOverlayGroup()?.getLayers();if(a){const i=[];a.forEach(s=>{s.get("layerId")!==void 0&&i.push(s)}),i.forEach(s=>a.remove(s))}}e(o),console.log("[App] Layer categories refreshed from API")}else t||console.log("[App] Layer categories not available — offline and no local cache")}catch(t){console.error("[App] Failed to load layer categories:",t)}}async function xl(){if(!V()){console.log("[App] Cannot sync - offline");return}console.log("[App] Sync placeholder - implement based on your backend")}const ue=[],Sl={strokeColor:"#e11d48",strokeWidth:2,fillColor:"rgba(225,29,72,0.12)"};function oe(n){Bt("error",n);const e=document.getElementById("file-import-alert");e&&(e.querySelector(".message-text").textContent=n,e.classList.remove("d-none"),setTimeout(()=>e.classList.add("d-none"),8e3))}function Fo(n,e,t){const r=Array.isArray(n)?n:[n];let o=0;for(const i of r){if(!i||i.type!=="FeatureCollection"||!i.features?.length)continue;const s=i.fileName?i.fileName.replace(/\.[^/.]+$/,""):e,l=E?.addGeoJSONLayer(i,s,Sl);l&&(l.set("removable",!0),l.set("typeTag","GEO"),ue.push(l),o+=i.features.length,kl(i,s,l).catch(c=>console.warn("[FileImport] Staging failed (layer remains view-only):",c)))}if(o===0){de(),oe("No features found in the file.");return}console.log(`[${t}] Added ${o} feature(s) from ${r.length} layer(s)`);const a=ue[ue.length-1];if(a){const i=a.getSource().getExtent();E?.getMap().getView().fit(i,{padding:[50,50,50,50],maxZoom:18})}Oo()}const Ll=new So;function Tl(n){return Ll.writeGeometry(n,{dataProjection:"EPSG:4326",featureProjection:"EPSG:3857"})}async function kl(n,e,t){const r=n?.features?.length??0;if(r===0){de();return}const{id:o}=await Sa({filename:e||"imported dataset",targetType:"other",featureCount:r});t.set("_externalImportId",o);const i=t.getSource().getFeatures().map(s=>{const l=s.getGeometry(),c=Il();return s.set("_externalImportId",o),s.set("_clientUuid",c),{client_uuid:c,geometry_wkt:l?Tl(l):"",properties:Pl(s.getProperties())}});await La(o,i),t.getSource().on("removefeature",async s=>{const l=s.feature,c=l?.get("_clientUuid"),d=l?.get("_externalImportId");if(!(!c||d==null))try{await Ma(c),console.log("[FileImport] Removed feature from staging:",c)}catch(u){console.warn("[FileImport] Failed to remove staging row:",u)}}),de(),As({importId:o,filename:e,fc:n,onResult:async s=>{try{await Ml(o,t,s)}catch(l){console.error("[FileImport] Failed to apply mapping result:",l),F("Could not save the import mapping: "+l.message)}}})}function Il(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{const e=Math.random()*16|0;return(n==="x"?e:e&3|8).toString(16)})}function Pl(n){const e={};for(const[t,r]of Object.entries(n||{}))t!=="geometry"&&(e[t]=r);return e}async function Ml(n,e,t){if(!t||t.action==="cancel"){e?.set("_externalImportStatus","other"),He(e);return}const{action:r,targetType:o,mapping:a}=t;if(!o||o==="other"){await Ft(n,{targetType:"other",mapping:null,status:"other"}),e?.set("_externalImportStatus","other"),He(e);return}await Ia(n,i=>Ts(i,a)),await Ft(n,{targetType:o,mapping:a,status:"mapped"}),e?.set("_externalImportStatus","mapped"),e?.set("_externalImportTargetType",o),He(e),r==="upload"&&await Ar(n,e)}async function Ar(n,e){e?.set("_externalImportStatus","uploading"),He(e);try{await Ft(n,{status:"uploading"});const t=await Ta(n),r=await ka(n),a={user_id_upload:Ke()?.user_id??null,import:{client_import_id:t.client_import_id,filename:t.filename,feature_count:r.length},features:r.map(i=>({client_uuid:i.client_uuid,geom:i.geometry_wkt,props:i.properties}))};console.log("[Upload]",{endpoint:`upload_${t.target_type}.php (not yet available on the server)`,target_type:t.target_type,body:a}),await Ft(n,{status:"mapped",lastUploadedAt:new Date().toISOString()}),e?.set("_externalImportStatus","mapped"),He(e),Do("The server upload endpoint is not yet available. The data stays staged locally — you can upload again later.")}catch(t){console.error("[Upload] Stub failed:",t),e?.set("_externalImportStatus","mapped"),He(e),F("Upload preparation failed: "+t.message)}}window.addEventListener("lupmis:export-gis",n=>{Qs(n.detail||{})});window.addEventListener("lupmis:analyse-features",async n=>{if(!E)return;const e=n.detail||{},t=[...e.parcelFeatures||[],...e.zoneFeatures||[],...Object.values(e.otherByLayer||{}).flat()];try{const{openAnalysisModal:r}=await Le(async()=>{const{openAnalysisModal:o}=await import("./analysis-modal-CYhcFxIW.js");return{openAnalysisModal:o}},__vite__mapDeps([7,8,9,1,2,10,0,3,11,12,6]));r(E,{scopeFeatures:t,scopeLabel:e.title||"drawn area"})}catch(r){console.error("[App] Could not load the Analysis panel:",r),F("Analysis tools could not be loaded — check your connection and try again.")}});window.addEventListener("lupmis:import-chip-click",n=>{const{importId:e,status:t,layer:r}=n.detail||{};t==="mapped"&&Ar(e,r).catch(o=>console.error("[FileImport] runUpload failed:",o))});function He(n){if(!n||!E)return;const e=E.getMap()?.getControls()?.getArray()?.find(t=>t?.constructor?.name==="LayerSwitcher"||t?.element?.classList?.contains("ol-layerswitcher"));e&&typeof e.drawPanel=="function"&&e.drawPanel()}function Oo(){const n=document.getElementById("imported-layers-info");if(!n)return;if(ue.length===0){n.innerHTML="",n.classList.add("d-none");return}n.innerHTML=`
+ `),new ht(document.getElementById("statusModal")).show()}catch(n){console.error("[App] Failed to get status:",n),O("Failed to get status")}}function Pr(n){return n.replace(/^\(+/,"").replace(/\)+$/,"").split(",").map(e=>{const[t,r]=e.trim().split(/\s+/).map(Number);return[t,r]})}function cl(n){return{type:"Polygon",coordinates:n.trim().replace(/^POLYGON\s*\(\s*/i,"").replace(/\s*\)$/,"").split("),(").map(Pr)}}function dl(n){return{type:"MultiPolygon",coordinates:n.trim().replace(/^MULTIPOLYGON\s*\(\s*/i,"").replace(/\s*\)$/,"").split(")),((").map(o=>o.replace(/^\(+/,"").replace(/\)+$/,"").split("),(").map(Pr))}}function gt(n){if(!n)return null;const e=n.trim().toUpperCase();return e.startsWith("MULTIPOLYGON")?dl(n):e.startsWith("POLYGON")?cl(n):(console.warn("[App] Unsupported WKT type:",e.substring(0,30)),null)}function ul(n){if(!n?.success||!n?.data?.boundary)return console.warn("[App] API response missing success or boundary data"),null;const{boundary:e,districtid:t,district_name:r}=n.data,o=gt(e);return{type:"FeatureCollection",features:[{type:"Feature",properties:{districtid:t,district_name:r},geometry:o}]}}function Fn(n){if(!Array.isArray(n)||n.length===0)return null;const e=[];for(const t of n){const r=t.polygon||t.boundary,o=gt(r);if(!o)continue;const a={_layerType:"collector_zone"};for(const[i,s]of Object.entries(t))i==="polygon"||i==="boundary"||(a[i]=s);e.push({type:"Feature",properties:a,geometry:o})}return e.length===0?null:{type:"FeatureCollection",features:e}}const vo="lupmis-last-district";function pl(n){return n==null||String(n).length===0?"district_boundary":`district_boundary_${n}`}async function fl(){const e=Ke()?.district_id;if(e==null||String(e).length===0)return;const t=String(e);let r=null;try{r=localStorage.getItem(vo)}catch{}if(r!==null&&r!==t){console.warn(`[App] District changed ${r} → ${t}; clearing cached layers.`);try{await Io(),Do("Your district was updated — refreshing map data.")}catch(o){console.error("[App] Failed to clear caches on district change:",o)}}try{localStorage.setItem(vo,t)}catch{}}async function hl(){const n=Ke()?.district_id??null,e=pl(n),t=1,r={strokeColor:"#e11d48",strokeWidth:2.5,fillColor:"rgba(225,29,72,0.08)",typeDescription:"Vector / Polygon"},o=E?.getLayerGroup(t)||null;function a(s){if(!s)return;const l=s.getLayers(),c=[];l.forEach(d=>{d.get("title")==="District Boundary"&&c.push(d)}),c.forEach(d=>l.remove(d))}function i(s){if(!s||!E)return;const l=s.getSource().getExtent();l&&l[0]!==1/0&&E.getMap().getView().fit(l,{padding:[40,40,40,40],duration:600})}try{const s=V()&&Te(),l=await er(e);if(l){console.log("[App] District boundary loaded from local cache");const c=E?.addGeoJSONLayer(l,"District Boundary",r,o);s||i(c)}if(s){console.log("[App] Fetching district boundary from API...");const c=await ts(),d=ul(c);if(!d){console.warn("[App] Could not convert API response to GeoJSON");return}console.log("[App] District boundary:",d.features[0]?.properties?.district_name,"→",d.features[0]?.geometry?.coordinates?.length,"polygon(s)"),await Qn(e,d),l&&a(o||E?.getOverlayGroup());const u=E?.addGeoJSONLayer(d,"District Boundary",r,o);i(u),console.log("[App] District boundary loaded from API")}else l||console.log("[App] District boundary not available — offline and no local cache")}catch(s){console.error("[App] Failed to load district boundary:",s)}}function On(n){if(!Array.isArray(n)||n.length===0)return null;const e=[];for(const t of n){const r=t.polygon||t.geometry_wkt||t.geom,o=gt(r);o&&e.push({type:"Feature",properties:{_layerType:"upn_grid",upn_prefix:t.upn_prefix??null},geometry:o})}return e.length===0?null:{type:"FeatureCollection",features:e}}async function gl(){const e={strokeColor:"#5b21b6",strokeWidth:1.5,fillColor:"rgba(124,58,237,0.04)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(1)||null,r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"UPN Grid",e,t);if(!o){console.warn("[App] Could not create UPN Grid layer");return}o.setVisible(!1);const a=7;o.setStyle((s,l)=>{const c=[new M({stroke:new I({color:"rgba(255,255,255,0.95)",width:3.5})}),new M({stroke:new I({color:"#5b21b6",width:1.5,lineDash:[7,4]}),fill:new A({color:"rgba(124,58,237,0.04)"})})];if(l<=a){const d=s.get("upn_prefix");d!=null&&String(d).length>0&&c.push(new M({text:new pt({text:String(d),font:"600 12px Arial, sans-serif",fill:new A({color:"#3b0764"}),stroke:new I({color:"rgba(255,255,255,0.95)",width:3}),overflow:!0})}))}return c}),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&O("No UPN grid available locally. Connect to the internet to download it.")});function i(s){const l=new le().readFeatures(s,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(l)}try{const l=Ke()?.district_id??null,c=await xa(l);if(c){const f=On(c);f&&i(f),console.log("[App] UPN grid from cache:",c.length,"cells (district",l,")");return}if(!V()||!Te()){console.log("[App] UPN grid not available — offline and no cache for district",l);return}console.log("[App] Fetching UPN grid from API (district",l,")...");const d=await ls();if(!d?.success||!Array.isArray(d?.data)){console.warn("[App] getUpnGrid invalid response:",d);return}const u=d.data;console.log("[App] UPN grid from API:",u.length,"cells"),await Ea(u,l);const p=On(u);p&&i(p),console.log("[App] UPN grid loaded:",p?.features.length??0,"cells rendered")}catch(s){console.error("[App] Failed to load UPN grid:",s)}}async function ml(){const e={strokeColor:"#7c3aed",strokeWidth:1.5,fillColor:"rgba(124,58,237,0.12)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(1)||null;console.log("[App] loadCollectorZones — adminGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"Zones",e,t);if(!o){console.warn("[App] Could not create Zones layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&O("No collector zones available locally. Connect to the internet to download zone data.")});function a(i){const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(s)}try{const i=await va();if(i){const s=Fn(i);s&&(console.log("[App] Collector zones loaded from local cache:",s.features.length,"zones"),a(s))}if(V()&&Te()){console.log("[App] Fetching collector zones from API...");const s=await ns();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getCollectorZones API response invalid:",s);return}const l=s.data;console.log("[App] Collector zones from API:",l.length,"entries"),await _a(l);const c=Fn(l);if(!c){console.warn("[App] Could not convert zones to GeoJSON");return}a(c),console.log("[App] Collector zones updated from API:",c.features.length,"zones")}else i||console.log("[App] Collector zones not available — offline and no local cache")}catch(i){console.error("[App] Failed to load collector zones:",i)}}function Dn(n){if(!Array.isArray(n)||n.length===0)return null;const e=new Set,t=[];for(const r of n){const o=r.id||r.parcelid||r.parcel_id;if(o!=null){if(e.has(o))continue;e.add(o)}let a=null;if(r.geom&&r.geom.type&&r.geom.coordinates)a={type:r.geom.type,coordinates:r.geom.coordinates};else if(r.sp_boundary&&r.sp_boundary.type&&r.sp_boundary.coordinates)a={type:r.sp_boundary.type,coordinates:r.sp_boundary.coordinates};else{const l=r.boundary||r.geometry_wkt||r.polygon||r.wkt;a=gt(l)}if(!a)continue;const i=new Set(["polygon","boundary","geom","geometry_wkt","wkt","textboundary","sp_boundary","fetched_at"]),s={_layerType:"parcel"};for(const[l,c]of Object.entries(r))i.has(l)||(s[l]=c);t.push({type:"Feature",properties:s,geometry:a})}return t.length===0?null:{type:"FeatureCollection",features:t}}async function yl(){const e={strokeColor:"#0ea5e9",strokeWidth:1.5,fillColor:"rgba(14,165,233,0.12)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(4)||null;console.log("[App] loadParcels — landUseGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]};if(se=E?.addGeoJSONLayer(r,"Parcels",e,t),!se){console.warn("[App] Could not create Parcels layer");return}se.setVisible(!1),se.on("change:visible",()=>{se.getVisible()&&se.getSource().getFeatures().length===0&&O("No parcels available locally. Connect to the internet to download parcel data.")});function o(a){const i=new le().readFeatures(a,{featureProjection:"EPSG:3857"});se.getSource().clear(),se.getSource().addFeatures(i)}try{const a=await Ca();if(a){const i=Dn(a);i&&(console.log("[App] Parcels loaded from local cache:",i.features.length,"parcels"),o(i))}if(V()&&Te()){console.log("[App] Fetching parcels from API...");const i=await rs();if(!i?.success||!Array.isArray(i?.data)){console.warn("[App] getDistrictParcels API response invalid:",i);return}const s=i.data;console.log("[App] Parcels from API:",s.length,"entries"),s.length>0&&console.log("[App] First parcel keys:",Object.keys(s[0])),await Aa(s);const l=Dn(s);if(!l){console.warn("[App] Could not convert parcels to GeoJSON");return}o(l),console.log("[App] Parcels updated from API:",l.features.length,"parcels")}else a||console.log("[App] Parcels not available — offline and no local cache")}catch(a){console.error("[App] Failed to load parcels:",a)}}function Rn(n){if(!Array.isArray(n)||n.length===0)return null;const e=["polygon","boundary","geom","wkt","footprint"],t=[];for(const r of n){const o=r.polygon||r.boundary||r.geom||r.wkt||r.footprint;let a;if(typeof o=="object"&&o!==null&&o.type?a=o:a=gt(o),!a)continue;const i={_layerType:"building_footprint"};for(const[s,l]of Object.entries(r))e.includes(s)||typeof l=="object"&&l!==null||(i[s]=l);t.push({type:"Feature",properties:i,geometry:a})}return t.length===0?null:{type:"FeatureCollection",features:t}}async function bl(){const e={strokeColor:"#8b6f47",strokeWidth:1,fillColor:"rgba(139,111,71,0.18)",typeDescription:"Vector / Polygon"},t=E?.getLayerGroup(5)||null;console.log("[App] loadBuildingFootprints — physInfraGroup:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"Building footprints",e,t);if(!o){console.warn("[App] Could not create Building footprints layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&O("No building footprints available locally. Connect to the internet to download footprint data.")});function a(i){const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});o.getSource().clear(),o.getSource().addFeatures(s)}try{const i=await Ra();if(i){const s=Rn(i);s&&(console.log("[App] Building footprints loaded from local cache:",s.features.length,"footprints"),a(s))}if(V()&&Te()){console.log("[App] Fetching building footprints from API...");const s=await as();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getBuildingFootprints API response invalid:",s);return}const l=s.data;console.log("[App] Building footprints from API:",l.length,"entries"),l.length>0&&console.log("[App] First footprint keys:",Object.keys(l[0])),await Da(l);const c=Rn(l);if(!c){console.warn("[App] Could not convert building footprints to GeoJSON");return}a(c),console.log("[App] Building footprints updated from API:",c.features.length,"footprints")}else i||console.log("[App] Building footprints not available — offline and no local cache")}catch(i){console.error("[App] Failed to load building footprints:",i)}}function Mr(n,e){if(!Array.isArray(n)||n.length===0)return null;const t=new So,r=new le,o=["geom","geometry","wkt","polygon","boundary","road","line"],a=[];for(const i of n){const s=i.geom||i.geometry||i.wkt||i.polygon||i.boundary||i.road||i.line;if(!s)continue;let l;try{if(typeof s=="object"&&s!==null&&s.type){a.push({type:"Feature",properties:Nn(i,o,e),geometry:s});continue}l=t.readGeometry(s)}catch(d){console.warn(`[App] Could not parse WKT for ${e}:`,d,s?.toString().slice(0,60));continue}const c=JSON.parse(r.writeGeometry(l));a.push({type:"Feature",properties:Nn(i,o,e),geometry:c})}return a.length===0?null:{type:"FeatureCollection",features:a}}function Nn(n,e,t){const r={_layerType:t};for(const[o,a]of Object.entries(n))e.includes(o)||typeof a=="object"&&a!==null||(r[o]=a);return r}async function wl(){const n={strokeColor:"#78716c",strokeWidth:.8,typeDescription:"Vector / Line",fillColor:"rgba(0,0,0,0)"},e=E?.getLayerGroupByTitle("Biophysical Environment");console.log("[App] loadContoursHillshade — group:",e?e.get("title"):"null");const t={type:"FeatureCollection",features:[]},r=E?.addGeoJSONLayer(t,"Contours hillshade",n,e);if(!r){console.warn("[App] Could not create Contours hillshade layer");return}if(r.setVisible(!1),r.on("change:visible",()=>{r.getVisible()&&r.getSource().getFeatures().length===0&&O("No Contours hillshade data available. Connect to the internet to download it.")}),!V()||!Te()){console.log("[App] Contours hillshade not available — offline or server unreachable");return}try{console.log("[App] Fetching contours_hillshade from API...");const o=await is();if(!o?.success||!Array.isArray(o?.data)){console.warn("[App] getContoursHillshade API response invalid:",o);return}const a=o.data;console.log("[App] Contours hillshade from API:",a.length,"rows"),a.length>0&&console.log("[App] First row keys:",Object.keys(a[0]));const i=Mr(a,"contours_hillshade");if(!i){console.warn("[App] Could not convert contours to GeoJSON");return}const s=new le().readFeatures(i,{featureProjection:"EPSG:3857"});r.getSource().clear(),r.getSource().addFeatures(s),console.log("[App] Contours hillshade loaded:",s.length,"features")}catch(o){console.error("[App] Failed to load contours_hillshade:",o)}}async function _l(){const e={strokeColor:"#F0F1F0",strokeWidth:1.5,lineCasingColor:"#000000",lineCasingWidth:3.5,fillColor:"rgba(0,0,0,0)",typeDescription:"Vector / Line"},t=E?.getLayerGroup(5)||null;console.log("[App] loadOSMRoads — group:",t?t.get("title"):"null");const r={type:"FeatureCollection",features:[]},o=E?.addGeoJSONLayer(r,"OSM_roads",e,t);if(!o){console.warn("[App] Could not create OSM_roads layer");return}o.setVisible(!1),o.on("change:visible",()=>{o.getVisible()&&o.getSource().getFeatures().length===0&&O("No OSM roads available locally. Connect to the internet to download them.")});function a(i){const s=Mr(i,"osm_road");if(!s)return console.warn("[App] Could not convert OSM roads to GeoJSON"),0;const l=new le().readFeatures(s,{featureProjection:"EPSG:3857"});return o.getSource().clear(),o.getSource().addFeatures(l),l.length}try{const i=await $a();if(i){const s=a(i);console.log("[App] OSM_roads loaded from local cache:",s,"features")}if(V()&&Te()){console.log("[App] Fetching OSM_roads from API...");const s=await ss();if(!s?.success||!Array.isArray(s?.data)){console.warn("[App] getOSMRoads API response invalid:",s);return}const l=s.data;console.log("[App] OSM_roads from API:",l.length,"rows"),l.length>0&&console.log("[App] First row keys:",Object.keys(l[0])),await Na(l);const c=a(l);console.log("[App] OSM_roads updated from API:",c,"features")}else i||console.log("[App] OSM_roads not available — offline and no local cache")}catch(i){console.error("[App] Failed to load OSM_roads:",i)}}function vl(){E?.addWMSLayer("Biophysical Environment","DEAfrica Coastlines v0.4","https://geoserver.digitalearth.africa/geoserver/wms","coastlines:DEAfrica_Coastlines",{serverType:"geoserver",visible:!1,onlineOnly:!0}),E?.addWMSLayer("Biophysical Environment","DEAfrica Slope (SRTM 30m)","https://ows.digitalearth.africa/wms","srtm_deriv",{serverType:null,style:"style_slope",visible:!1,opacity:.5,zIndex:-50,onlineOnly:!0,attributions:'©
Digital Earth Africa — SRTM-derived Slope',legendUrl:"https://ows.digitalearth.africa/legend/srtm_deriv/style_slope/legend.png"})}async function El(){const n="layer_categories";function e(t){const r=[...t].sort((o,a)=>a.id-o.id);for(const o of r)E?.addLayerGroup(o.id,o.name,o.description||"");console.log("[App] Created",t.length,"layer groups on map")}try{const t=await er(n);if(t&&(console.log("[App] Layer categories loaded from local cache:",t.length,"entries"),e(t)),V()&&Te()){console.log("[App] Fetching layer categories from API...");const r=await os();if(!r?.success||!Array.isArray(r?.data)){console.warn("[App] getLayers API response invalid:",r);return}const o=r.data;if(console.log("[App] Layer categories from API:",o.length,"entries"),await Qn(n,o),t){const a=E?.getOverlayGroup()?.getLayers();if(a){const i=[];a.forEach(s=>{s.get("layerId")!==void 0&&i.push(s)}),i.forEach(s=>a.remove(s))}}e(o),console.log("[App] Layer categories refreshed from API")}else t||console.log("[App] Layer categories not available — offline and no local cache")}catch(t){console.error("[App] Failed to load layer categories:",t)}}async function xl(){if(!V()){console.log("[App] Cannot sync - offline");return}console.log("[App] Sync placeholder - implement based on your backend")}const ue=[],Sl={strokeColor:"#e11d48",strokeWidth:2,fillColor:"rgba(225,29,72,0.12)"};function oe(n){Bt("error",n);const e=document.getElementById("file-import-alert");e&&(e.querySelector(".message-text").textContent=n,e.classList.remove("d-none"),setTimeout(()=>e.classList.add("d-none"),8e3))}function Fo(n,e,t){const r=Array.isArray(n)?n:[n];let o=0;for(const i of r){if(!i||i.type!=="FeatureCollection"||!i.features?.length)continue;const s=i.fileName?i.fileName.replace(/\.[^/.]+$/,""):e,l=E?.addGeoJSONLayer(i,s,Sl);l&&(l.set("removable",!0),l.set("typeTag","GEO"),ue.push(l),o+=i.features.length,kl(i,s,l).catch(c=>console.warn("[FileImport] Staging failed (layer remains view-only):",c)))}if(o===0){de(),oe("No features found in the file.");return}console.log(`[${t}] Added ${o} feature(s) from ${r.length} layer(s)`);const a=ue[ue.length-1];if(a){const i=a.getSource().getExtent();E?.getMap().getView().fit(i,{padding:[50,50,50,50],maxZoom:18})}Oo()}const Ll=new So;function Tl(n){return Ll.writeGeometry(n,{dataProjection:"EPSG:4326",featureProjection:"EPSG:3857"})}async function kl(n,e,t){const r=n?.features?.length??0;if(r===0){de();return}const{id:o}=await Sa({filename:e||"imported dataset",targetType:"other",featureCount:r});t.set("_externalImportId",o);const i=t.getSource().getFeatures().map(s=>{const l=s.getGeometry(),c=Il();return s.set("_externalImportId",o),s.set("_clientUuid",c),{client_uuid:c,geometry_wkt:l?Tl(l):"",properties:Pl(s.getProperties())}});await La(o,i),t.getSource().on("removefeature",async s=>{const l=s.feature,c=l?.get("_clientUuid"),d=l?.get("_externalImportId");if(!(!c||d==null))try{await Ma(c),console.log("[FileImport] Removed feature from staging:",c)}catch(u){console.warn("[FileImport] Failed to remove staging row:",u)}}),de(),As({importId:o,filename:e,fc:n,onResult:async s=>{try{await Ml(o,t,s)}catch(l){console.error("[FileImport] Failed to apply mapping result:",l),O("Could not save the import mapping: "+l.message)}}})}function Il(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{const e=Math.random()*16|0;return(n==="x"?e:e&3|8).toString(16)})}function Pl(n){const e={};for(const[t,r]of Object.entries(n||{}))t!=="geometry"&&(e[t]=r);return e}async function Ml(n,e,t){if(!t||t.action==="cancel"){e?.set("_externalImportStatus","other"),He(e);return}const{action:r,targetType:o,mapping:a}=t;if(!o||o==="other"){await Ft(n,{targetType:"other",mapping:null,status:"other"}),e?.set("_externalImportStatus","other"),He(e);return}await Ia(n,i=>Ts(i,a)),await Ft(n,{targetType:o,mapping:a,status:"mapped"}),e?.set("_externalImportStatus","mapped"),e?.set("_externalImportTargetType",o),He(e),r==="upload"&&await Ar(n,e)}async function Ar(n,e){e?.set("_externalImportStatus","uploading"),He(e);try{await Ft(n,{status:"uploading"});const t=await Ta(n),r=await ka(n),a={user_id_upload:Ke()?.user_id??null,import:{client_import_id:t.client_import_id,filename:t.filename,feature_count:r.length},features:r.map(i=>({client_uuid:i.client_uuid,geom:i.geometry_wkt,props:i.properties}))};console.log("[Upload]",{endpoint:`upload_${t.target_type}.php (not yet available on the server)`,target_type:t.target_type,body:a}),await Ft(n,{status:"mapped",lastUploadedAt:new Date().toISOString()}),e?.set("_externalImportStatus","mapped"),He(e),Do("The server upload endpoint is not yet available. The data stays staged locally — you can upload again later.")}catch(t){console.error("[Upload] Stub failed:",t),e?.set("_externalImportStatus","mapped"),He(e),O("Upload preparation failed: "+t.message)}}window.addEventListener("lupmis:export-gis",n=>{Qs(n.detail||{})});window.addEventListener("lupmis:analyse-features",async n=>{if(!E)return;const e=n.detail||{},t=[...e.parcelFeatures||[],...e.zoneFeatures||[],...Object.values(e.otherByLayer||{}).flat()];try{const{openAnalysisModal:r}=await Le(async()=>{const{openAnalysisModal:o}=await import("./analysis-modal-05Uf_OF7.js");return{openAnalysisModal:o}},__vite__mapDeps([7,0,1,2,3,8,9,10,11,12,6]));r(E,{scopeFeatures:t,scopeLabel:e.title||"drawn area"})}catch(r){console.error("[App] Could not load the Analysis panel:",r),O("Analysis tools could not be loaded — check your connection and try again.")}});window.addEventListener("lupmis:import-chip-click",n=>{const{importId:e,status:t,layer:r}=n.detail||{};t==="mapped"&&Ar(e,r).catch(o=>console.error("[FileImport] runUpload failed:",o))});function He(n){if(!n||!E)return;const e=E.getMap()?.getControls()?.getArray()?.find(t=>t?.constructor?.name==="LayerSwitcher"||t?.element?.classList?.contains("ol-layerswitcher"));e&&typeof e.drawPanel=="function"&&e.drawPanel()}function Oo(){const n=document.getElementById("imported-layers-info");if(!n)return;if(ue.length===0){n.innerHTML="",n.classList.add("d-none");return}n.innerHTML=`
`;return}const l=s.totals,c=s.byProvider.filter(p=>p.count>0).map(p=>`
- ${U(f.label)}
- ${f.count.toLocaleString()} / ${f.limit.toLocaleString()}
- ${r(f.estBytes)}
+ ${U(p.label)}
+ ${p.count.toLocaleString()} / ${p.limit.toLocaleString()}
+ ${r(p.estBytes)}
+ data-cache="${U(p.key)}" data-label="${U(p.label)}"
+ title="Clear ${U(p.label)} tiles only">
- `).join("");let d="";const u=await Gi();if(u&&u.quota>0){const f=(u.usage/u.quota*100).toFixed(1);d=`
+ `).join("");let d="";const u=await Gi();if(u&&u.quota>0){const p=(u.usage/u.quota*100).toFixed(1);d=`
- Total app storage: ${r(u.usage)} of ${r(u.quota)} available (${f}%)
+ Total app storage: ${r(u.usage)} of ${r(u.quota)} available (${p}%)
`}if(l.count===0){n.innerHTML=`
No tiles cached yet. Pan and zoom the map to start caching tiles automatically.
@@ -913,11 +917,11 @@ UTM: ${a}`)}function Rl(){const n=document.getElementById("gps-readout"),e=docum
${c}
- ${d}`,e.disabled=!1,n.querySelectorAll(".provider-clear-btn").forEach(f=>{f.addEventListener("click",async p=>{p.preventDefault();const h=f.dataset.cache,m=f.dataset.label||h;if(!confirm(`Clear cached "${m}" tiles?
+ ${d}`,e.disabled=!1,n.querySelectorAll(".provider-clear-btn").forEach(p=>{p.addEventListener("click",async f=>{f.preventDefault();const h=p.dataset.cache,m=p.dataset.label||h;if(!confirm(`Clear cached "${m}" tiles?
-Other providers are not affected. The tiles will re-download as you browse online.`))return;f.disabled=!0,await Bi(h)?console.log(`[Settings] Cleared tile cache for ${m}`):console.warn(`[Settings] Could not clear tile cache for ${m}`),await a()})})}finally{o=null}})(),o}e.addEventListener("click",async()=>{if(!confirm("Clear all cached map tiles from this device? You will need to be online to view them again."))return;e.disabled=!0,await $i()?console.log("[Settings] Tile caches cleared"):console.warn("[Settings] Tile-cache clear failed"),await a()}),t.addEventListener("show.bs.offcanvas",a),Ri(()=>{console.log("[Settings] SW controller changed → refreshing tile-cache stats"),a()}),a()}function zl(){const n=document.getElementById("download-tiles-btn"),e=document.getElementById("offline-download-modal");if(!n||!e)return;const t=ht.getOrCreateInstance(e),r=document.getElementById("offline-download-form-view"),o=document.getElementById("offline-download-progress-view"),a=document.getElementById("offline-download-done-view"),i=document.getElementById("offline-download-cancel-btn"),s=document.getElementById("offline-download-start-btn"),l=document.getElementById("offline-download-close-done-btn"),c=document.getElementById("offline-download-close-btn"),d=document.getElementById("offline-basemap-select"),u=document.getElementById("offline-min-zoom"),f=document.getElementById("offline-max-zoom"),p=document.getElementById("offline-ack-check"),h=document.getElementById("offline-estimate-detail"),m=document.getElementById("offline-estimate"),g=document.getElementById("offline-area-view"),y=document.getElementById("offline-area-district"),w=document.getElementById("offline-area-ghana"),_=document.getElementById("offline-area-view-info"),x=document.getElementById("offline-area-district-info"),L=document.getElementById("offline-progress-bar"),v=document.getElementById("offline-progress-percent"),S=document.getElementById("offline-progress-counts"),P=document.getElementById("offline-progress-ok"),k=document.getElementById("offline-progress-failed"),z=document.getElementById("offline-progress-eta"),q=document.getElementById("offline-done-title"),Z=document.getElementById("offline-done-detail");let B=null;function ce(G){return G?G<1024*1024?(G/1024).toFixed(0)+" KB":G<1024*1024*1024?(G/(1024*1024)).toFixed(1)+" MB":(G/(1024*1024*1024)).toFixed(2)+" GB":"0 KB"}function Q(G){if(!G||G<1e3)return"< 1 s";const J=Math.round(G/1e3);if(J<60)return J+" s";const K=Math.floor(J/60),ne=J%60;return K<60?`${K} min ${ne} s`:`${Math.floor(K/60)} h ${K%60} min`}function ye(){return g.checked?E?.getCurrentViewExtent()||null:y.checked?E?.getDistrictBoundaryExtent()?.extent||null:w.checked?Ki:null}function H(){const G=d.value,J=parseInt(u.value,10),K=parseInt(f.value,10);if(Number.isNaN(J)||Number.isNaN(K)||J>K){h.textContent="Invalid zoom range",m.classList.replace("alert-info","alert-warning"),s.disabled=!0;return}const ne=ye();if(!ne){h.textContent="Selected area is not available.",m.classList.replace("alert-info","alert-warning"),s.disabled=!0;return}const R=pr[G]?.maxZoom??19,W=Math.min(K,R),re=zi(ne,J,W),Gt=Vi(re);let we="";W
Zoom ${K} is above this provider's max (${R}); will clamp to ${R}. `),re>8e3&&(we+='More than 8 000 tiles — exceeds the per-provider cache limit. Earlier tiles will be evicted as new ones arrive. '),h.innerHTML=`${re.toLocaleString()} tiles · ~${ce(Gt)}`+we,m.classList.toggle("alert-warning",!!we),m.classList.toggle("alert-info",!we),s.disabled=!p.checked||re===0}function be(){E?.getCurrentViewExtent()?_.textContent=" · ready":_.textContent="",E?.getDistrictBoundaryExtent()?(x.textContent="",y.disabled=!1):(x.textContent=" (not loaded — connect online to fetch)",y.disabled=!0,y.checked&&(g.checked=!0))}function Ve(){r.classList.remove("d-none"),o.classList.add("d-none"),a.classList.add("d-none"),s.classList.remove("d-none"),i.classList.remove("d-none"),i.textContent="Cancel",l.classList.add("d-none"),c.disabled=!1,p.checked=!1,s.disabled=!0,B=null}n.addEventListener("click",()=>{Ve(),be(),H(),t.show()}),d.addEventListener("change",H),u.addEventListener("input",H),f.addEventListener("input",H),g.addEventListener("change",H),y.addEventListener("change",H),w.addEventListener("change",H),p.addEventListener("change",H),s.addEventListener("click",async()=>{const G=d.value,J=parseInt(u.value,10),K=parseInt(f.value,10),ne=ye();if(!ne)return;r.classList.add("d-none"),o.classList.remove("d-none"),s.classList.add("d-none"),i.textContent="Cancel download",c.disabled=!0,L.style.width="0%",L.setAttribute("aria-valuenow","0"),v.textContent="0%",S.textContent="0 of 0 tiles",P.textContent="0",k.textContent="0",z.textContent="—",B=new Wi({baseMap:G,extent3857:ne,minZoom:J,maxZoom:K,onProgress:W=>{if(W.total>0){const re=Math.min(100,Math.round(W.done/W.total*100));L.style.width=re+"%",L.setAttribute("aria-valuenow",String(re)),v.textContent=re+"%",S.textContent=`${W.done.toLocaleString()} of ${W.total.toLocaleString()} tiles`}P.textContent=W.ok.toLocaleString(),k.textContent=W.failed.toLocaleString(),z.textContent=W.etaMs!=null?Q(W.etaMs):"—"}});let R;try{R=await B.start()}catch(W){console.error("[OfflineDownload] failed:",W),R={phase:"error",done:0,total:0,ok:0,failed:0}}o.classList.add("d-none"),a.classList.remove("d-none"),i.classList.add("d-none"),l.classList.remove("d-none"),c.disabled=!1,R.phase==="cancelled"?(q.textContent="Download cancelled",Z.innerHTML=`Stopped after ${R.done.toLocaleString()} of ${R.total.toLocaleString()} tiles. ${R.ok.toLocaleString()} fetched · ${R.failed.toLocaleString()} failed.`):R.phase==="error"?(q.textContent="Download failed",Z.textContent="See console for details."):(q.textContent="Download complete",Z.innerHTML=`${R.ok.toLocaleString()} tiles cached`+(R.failed>0?`, ${R.failed.toLocaleString()} failed`:"")+`. Took ${Q(R.elapsedMs)}.`)}),i.addEventListener("click",()=>{B&&B.cancel()}),e.addEventListener("hidden.bs.modal",()=>{B&&B.cancel(),Ve()})}function ql(){const n=Ke(),e=document.getElementById("menu-btn"),t=document.getElementById("menu-user-avatar"),r=document.getElementById("menu-user-name"),o=document.getElementById("menu-user-email"),a=document.getElementById("menu-user-detail"),i=document.getElementById("menu-signout-btn"),s=document.getElementById("menu-landing-link"),l=document.getElementById("menu-signin-link"),c=document.getElementById("menu-no-session-note");if(!e||!t||!r||!o||!a||!i){console.warn("[AccountMenu] One or more elements missing — shell may be stale. Hard-refresh.");return}if(!!n&&!!n.user_id){const u=[n.title,n.full_name].filter(Boolean).join(" ").trim()||n.username||"Authenticated user",f=(n.full_name||n.username||"?").trim().charAt(0).toUpperCase();t.textContent=f,t.style.background="var(--brand-navy, #1e1a4b)",r.textContent=u,o.textContent=n.email||"";const p=[];n.district_id!=null&&p.push(`District ${U(String(n.district_id))}`),n.region_id!=null&&p.push(`Region ${U(String(n.region_id))}`),n.ua_position&&p.push(U(n.ua_position)),a.innerHTML=p.join(" · ")||"No district info",i.classList.remove("d-none"),i.addEventListener("click",()=>Hl(n),{once:!1}),s?.classList.remove("d-none"),l?.classList.add("d-none"),c?.classList.add("d-none"),e.removeAttribute("data-state"),e.setAttribute("title",`Menu — ${u}`)}else typeof window.LUPMIS_SESSION>"u"?(t.innerHTML=' ',t.style.background="var(--brand-orange-warm, #ff9e1b)",r.textContent="No session injected",o.textContent="",a.textContent="",i.classList.add("d-none"),s?.classList.add("d-none"),l?.classList.add("d-none"),c?.classList.remove("d-none"),e.dataset.state="no-session",e.setAttribute("title","Menu (no session — dev mode)")):(t.innerHTML=' ',t.style.background="var(--brand-gray-medium, #7a7a7a)",r.textContent="Not signed in",o.textContent="",a.textContent="",i.classList.add("d-none"),s?.classList.add("d-none"),l?.classList.remove("d-none"),c?.classList.add("d-none"),e.dataset.state="unauthenticated",e.setAttribute("title","Menu (not signed in)"))}async function Hl(n){if(!V()){alert(`You appear to be offline.
+Other providers are not affected. The tiles will re-download as you browse online.`))return;p.disabled=!0,await Bi(h)?console.log(`[Settings] Cleared tile cache for ${m}`):console.warn(`[Settings] Could not clear tile cache for ${m}`),await a()})})}finally{o=null}})(),o}e.addEventListener("click",async()=>{if(!confirm("Clear all cached map tiles from this device? You will need to be online to view them again."))return;e.disabled=!0,await $i()?console.log("[Settings] Tile caches cleared"):console.warn("[Settings] Tile-cache clear failed"),await a()}),t.addEventListener("show.bs.offcanvas",a),Ri(()=>{console.log("[Settings] SW controller changed → refreshing tile-cache stats"),a()}),a()}function ql(){const n=document.getElementById("download-tiles-btn"),e=document.getElementById("offline-download-modal");if(!n||!e)return;const t=ht.getOrCreateInstance(e),r=document.getElementById("offline-download-form-view"),o=document.getElementById("offline-download-progress-view"),a=document.getElementById("offline-download-done-view"),i=document.getElementById("offline-download-cancel-btn"),s=document.getElementById("offline-download-start-btn"),l=document.getElementById("offline-download-close-done-btn"),c=document.getElementById("offline-download-close-btn"),d=document.getElementById("offline-basemap-select"),u=document.getElementById("offline-min-zoom"),p=document.getElementById("offline-max-zoom"),f=document.getElementById("offline-ack-check"),h=document.getElementById("offline-estimate-detail"),m=document.getElementById("offline-estimate"),g=document.getElementById("offline-area-view"),y=document.getElementById("offline-area-district"),w=document.getElementById("offline-area-ghana"),_=document.getElementById("offline-area-view-info"),x=document.getElementById("offline-area-district-info"),L=document.getElementById("offline-progress-bar"),v=document.getElementById("offline-progress-percent"),S=document.getElementById("offline-progress-counts"),P=document.getElementById("offline-progress-ok"),k=document.getElementById("offline-progress-failed"),q=document.getElementById("offline-progress-eta"),z=document.getElementById("offline-done-title"),Z=document.getElementById("offline-done-detail");let B=null;function ce(G){return G?G<1024*1024?(G/1024).toFixed(0)+" KB":G<1024*1024*1024?(G/(1024*1024)).toFixed(1)+" MB":(G/(1024*1024*1024)).toFixed(2)+" GB":"0 KB"}function Q(G){if(!G||G<1e3)return"< 1 s";const J=Math.round(G/1e3);if(J<60)return J+" s";const K=Math.floor(J/60),ne=J%60;return K<60?`${K} min ${ne} s`:`${Math.floor(K/60)} h ${K%60} min`}function ye(){return g.checked?E?.getCurrentViewExtent()||null:y.checked?E?.getDistrictBoundaryExtent()?.extent||null:w.checked?Ki:null}function H(){const G=d.value,J=parseInt(u.value,10),K=parseInt(p.value,10);if(Number.isNaN(J)||Number.isNaN(K)||J>K){h.textContent="Invalid zoom range",m.classList.replace("alert-info","alert-warning"),s.disabled=!0;return}const ne=ye();if(!ne){h.textContent="Selected area is not available.",m.classList.replace("alert-info","alert-warning"),s.disabled=!0;return}const R=pr[G]?.maxZoom??19,W=Math.min(K,R),re=qi(ne,J,W),Gt=Vi(re);let we="";WZoom ${K} is above this provider's max (${R}); will clamp to ${R}. `),re>8e3&&(we+='More than 8 000 tiles — exceeds the per-provider cache limit. Earlier tiles will be evicted as new ones arrive. '),h.innerHTML=`${re.toLocaleString()} tiles · ~${ce(Gt)}`+we,m.classList.toggle("alert-warning",!!we),m.classList.toggle("alert-info",!we),s.disabled=!f.checked||re===0}function be(){E?.getCurrentViewExtent()?_.textContent=" · ready":_.textContent="",E?.getDistrictBoundaryExtent()?(x.textContent="",y.disabled=!1):(x.textContent=" (not loaded — connect online to fetch)",y.disabled=!0,y.checked&&(g.checked=!0))}function Ve(){r.classList.remove("d-none"),o.classList.add("d-none"),a.classList.add("d-none"),s.classList.remove("d-none"),i.classList.remove("d-none"),i.textContent="Cancel",l.classList.add("d-none"),c.disabled=!1,f.checked=!1,s.disabled=!0,B=null}n.addEventListener("click",()=>{Ve(),be(),H(),t.show()}),d.addEventListener("change",H),u.addEventListener("input",H),p.addEventListener("input",H),g.addEventListener("change",H),y.addEventListener("change",H),w.addEventListener("change",H),f.addEventListener("change",H),s.addEventListener("click",async()=>{const G=d.value,J=parseInt(u.value,10),K=parseInt(p.value,10),ne=ye();if(!ne)return;r.classList.add("d-none"),o.classList.remove("d-none"),s.classList.add("d-none"),i.textContent="Cancel download",c.disabled=!0,L.style.width="0%",L.setAttribute("aria-valuenow","0"),v.textContent="0%",S.textContent="0 of 0 tiles",P.textContent="0",k.textContent="0",q.textContent="—",B=new Wi({baseMap:G,extent3857:ne,minZoom:J,maxZoom:K,onProgress:W=>{if(W.total>0){const re=Math.min(100,Math.round(W.done/W.total*100));L.style.width=re+"%",L.setAttribute("aria-valuenow",String(re)),v.textContent=re+"%",S.textContent=`${W.done.toLocaleString()} of ${W.total.toLocaleString()} tiles`}P.textContent=W.ok.toLocaleString(),k.textContent=W.failed.toLocaleString(),q.textContent=W.etaMs!=null?Q(W.etaMs):"—"}});let R;try{R=await B.start()}catch(W){console.error("[OfflineDownload] failed:",W),R={phase:"error",done:0,total:0,ok:0,failed:0}}o.classList.add("d-none"),a.classList.remove("d-none"),i.classList.add("d-none"),l.classList.remove("d-none"),c.disabled=!1,R.phase==="cancelled"?(z.textContent="Download cancelled",Z.innerHTML=`Stopped after ${R.done.toLocaleString()} of ${R.total.toLocaleString()} tiles. ${R.ok.toLocaleString()} fetched · ${R.failed.toLocaleString()} failed.`):R.phase==="error"?(z.textContent="Download failed",Z.textContent="See console for details."):(z.textContent="Download complete",Z.innerHTML=`${R.ok.toLocaleString()} tiles cached`+(R.failed>0?`, ${R.failed.toLocaleString()} failed`:"")+`. Took ${Q(R.elapsedMs)}.`)}),i.addEventListener("click",()=>{B&&B.cancel()}),e.addEventListener("hidden.bs.modal",()=>{B&&B.cancel(),Ve()})}function zl(){const n=Ke(),e=document.getElementById("menu-btn"),t=document.getElementById("menu-user-avatar"),r=document.getElementById("menu-user-name"),o=document.getElementById("menu-user-email"),a=document.getElementById("menu-user-detail"),i=document.getElementById("menu-signout-btn"),s=document.getElementById("menu-landing-link"),l=document.getElementById("menu-signin-link"),c=document.getElementById("menu-no-session-note");if(!e||!t||!r||!o||!a||!i){console.warn("[AccountMenu] One or more elements missing — shell may be stale. Hard-refresh.");return}if(!!n&&!!n.user_id){const u=[n.title,n.full_name].filter(Boolean).join(" ").trim()||n.username||"Authenticated user",p=(n.full_name||n.username||"?").trim().charAt(0).toUpperCase();t.textContent=p,t.style.background="var(--brand-navy, #1e1a4b)",r.textContent=u,o.textContent=n.email||"";const f=[];n.district_id!=null&&f.push(`District ${U(String(n.district_id))}`),n.region_id!=null&&f.push(`Region ${U(String(n.region_id))}`),n.ua_position&&f.push(U(n.ua_position)),a.innerHTML=f.join(" · ")||"No district info",i.classList.remove("d-none"),i.addEventListener("click",()=>Hl(n),{once:!1}),s?.classList.remove("d-none"),l?.classList.add("d-none"),c?.classList.add("d-none"),e.removeAttribute("data-state"),e.setAttribute("title",`Menu — ${u}`)}else typeof window.LUPMIS_SESSION>"u"?(t.innerHTML=' ',t.style.background="var(--brand-orange-warm, #ff9e1b)",r.textContent="No session injected",o.textContent="",a.textContent="",i.classList.add("d-none"),s?.classList.add("d-none"),l?.classList.add("d-none"),c?.classList.remove("d-none"),e.dataset.state="no-session",e.setAttribute("title","Menu (no session — dev mode)")):(t.innerHTML=' ',t.style.background="var(--brand-gray-medium, #7a7a7a)",r.textContent="Not signed in",o.textContent="",a.textContent="",i.classList.add("d-none"),s?.classList.add("d-none"),l?.classList.remove("d-none"),c?.classList.add("d-none"),e.dataset.state="unauthenticated",e.setAttribute("title","Menu (not signed in)"))}async function Hl(n){if(!V()){alert(`You appear to be offline.
Logging out needs a connection to the sign-in server, and you would not be able to sign back in until you are online again.
-Please try again once you have a connection. You can keep working — the app stays signed in while offline.`);return}if(confirm(`Log out, ${n?.full_name||n?.username||"user"}?`)){try{await Io(),localStorage.removeItem(vo)}catch(e){console.warn("[Logout] Cache clear failed (continuing):",e)}window.location.href="/?logout=1"}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Cn):Cn();export{D as s};
-//# sourceMappingURL=index-BYEiD6vv.js.map
+Please try again once you have a connection. You can keep working — the app stays signed in while offline.`);return}if(confirm(`Log out, ${n?.full_name||n?.username||"user"}?`)){try{await Io(),localStorage.removeItem(vo)}catch(e){console.warn("[Logout] Cache clear failed (continuing):",e)}window.location.href="/?logout=1"}}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",Cn):Cn();export{F as s};
+//# sourceMappingURL=index-Cyeghdft.js.map
diff --git a/dist/assets/index-Cyeghdft.js.map b/dist/assets/index-Cyeghdft.js.map
new file mode 100644
index 0000000..0afc815
--- /dev/null
+++ b/dist/assets/index-Cyeghdft.js.map
@@ -0,0 +1 @@
+{"version":3,"mappings":"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","names":["FUNCTION","CHANNEL","GET","HAS","SET","isArray","SharedArrayBuffer","window","notify","wait","waitAsync","postPatched","buffer","onmessage","w","ids","resolvers","postMessage","listener","event","details","id","sb","data","rest","resolve","buff","i","as","Int32Array","Map","Uint16Array","I32_BYTES","UI16_BYTES","waitInterrupt","delay","handler","buffers","context","syncResult","fn","uid","coincident","self","parse","stringify","transform","interrupt","sendMessage","post","transfer","args","decoder","waitFor","isAsync","seppuku","_","action","deadlock","length","bytes","actions","callback","type","results","error","result","serialized","ui16a","createMutex","promise","res","normalizeDatabaseFile","dbFile","convertStreamTo","bufferOrStream","reader","chunks","streamDone","chunk","arrayLength","offset","SQLiteMemoryDriver","sqlite3InitModule","config","databasePath","flags","__vitePreload","statement","statements","tx","prepared","stmt","newStmt","columns","rows","size","database","dataPointer","resultCode","pointer","readOnly","verbose","db","statementData","opMap","_ctx","opId","_db","table","rowid","cb","debounce","func","options","lastArgs","lastThis","maxWait","timerId","lastCallTime","lastInvokeTime","leading","maxing","trailing","invokeFunc","time","thisArg","leadingEdge","timerExpired","remainingWait","timeSinceLastCall","timeSinceLastInvoke","timeWaiting","shouldInvoke","trailingEdge","cancel","flush","debounced","isInvoking","getQueryKey","getDatabaseKey","clientKey","sessionKey","SQLocalProcessor","driver","reason","dbKey","message","change","_transfer","response","partOfTransaction","sql","name","queryKey","errored","proxy","sqlTag","queryTemplate","params","isArrayOfArrays","row","convertRowsToObjects","checkedRows","rowObj","column","columnIndex","isDrizzleStatement","isStatement","normalizeStatement","drizzleStatement","exec","normalizeSql","maybeQueryTemplate","mutationLock","mode","bypass","mutation","SQLiteKvvfsDriver","storageType","memdb","_a","_b","SQLocal","queries","reject","userCallback","method","transactionKey","resultIndex","passStatements","query","passStatement","transaction","err","value","gotFirstValue","isListening","updateCount","watchedTables","subObservers","errObservers","runStatement","updateOrder","usedTables","readTables","writtenTables","observer","onEffect","onData","onError","funcName","key","attachFunction","databaseFile","beforeUnlock","clientConfig","onInit","onConnect","processor","commonConfig","DATABASE_PATH","BROADCAST_CHANNEL","channel","isReady","readyResolve","readyReject","dbReady","changeListeners","onDatabaseChange","payload","e","broadcastChange","initSchema","testResult","tablesAfterLocations","cols","c","allTables","t","addLocation","longitude","latitude","description","category","tableCheck","newId","verifyResult","getLocations","limit","getLocationCount","saveRemoteData","json","getRemoteData","parsed","saveCollectorZones","zones","z","props","getLocalCollectorZones","r","saveUpnGrid","districtId","saved","wkt","numOrNull","getLocalUpnGrid","uuidv4","createExternalImport","opts","filename","targetType","featureCount","clientImportId","addExternalImportFeatures","importId","features","inserted","f","propsJson","cuuid","updateExternalImport","patch","cur","mappingJson","status","errorCount","lastUploadedAt","getExternalImport","getExternalImportFeatures","remapImportedFeatureProperties","remap","n","before","after","updateExternalImportFeatureGeometry","clientUuid","geometryWkt","properties","deleteExternalImportFeature","v","saveParcels","parcels","p","getLocalParcels","updateParcel","parcelId","insertNewParcel","saveBuildingFootprints","footprints","first","types","k","rawWkt","rawId","getLocalBuildingFootprints","saveOSMRoads","roads","getLocalOSMRoads","exportDatabase","downloadDatabase","blob","url","a","exportToGeoJSON","loc","getDatabaseStatus","tables","locationCount","CACHED_LAYER_TABLES","isCachedLayerTable","tableName","clearTable","count","clearAllCachedLayers","existing","existingNames","total","s","getTableStats","getTableContent","testDatabase","version","createGpsTrail","meta","uuid","startedAt","addGpsTrailPoint","trailId","point","seq","lon","lat","altitude","accuracy","altitudeAccuracy","heading","speed","satellites","timestamp","recordedAt","finishGpsTrail","summary","endedAt","pointCount","distanceM","getUnsyncedGpsTrails","getGpsTrailPoints","markGpsTrailSynced","remoteId","M_TO_FT","M_TO_MI","SQM_TO_SQFT","SQM_TO_ACRE","SQM_TO_SQMI","getSystem","formatLength","metres","ft","formatLengthFull","mi","formatArea","sqMetres","acres","formatAreaFull","sqft","sqmi","formatCircleExtent","radiusMetres","segmentIntersection","p1","p2","p3","p4","eps","dx1","dy1","dx2","dy2","denom","dx3","dy3","u","signedArea","ring","area","pointInRing","pt","inside","j","xi","yi","xj","yj","dist2","b","findIntersections","line","hits","li","ri","ix","isDup","h","insertPointsIntoRing","sorted","expanded","indices","insertIdx","snapDist","ringSlice","i0","i1","start","end","idx","cuttingLineSlice","hit0","hit1","startSeg","endSeg","ensureWinding","ccw","closeRing","coords","last","extendLineOutsideRing","minX","minY","maxX","maxY","diag","p0","dx","dy","len","scale","pN","pN1","splitPolygonByLine","polygonCoords","lineCoords","exteriorRing","holes","extendedLine","expandedRing","idx0","idx1","iA","iB","cutForward","cutReverse","sliceAB","ringA","sliceBA","ringB","originalCCW","finalA","finalB","polyA","polyB","hole","centroid","holeCentroid","cx","cy","THEMES","container","ensureContainer","showToast","duration","parent","theme","el","dismiss","SPLIT_COLORS","HIGHLIGHT_STYLE","Style","Stroke","Fill","SKETCH_STYLE","CircleStyle","PolygonSplitInteraction","ol_interaction_Interaction","VectorSource","VectorLayer","map","active","sources","collect","layers","layer","hit","clone","best","bestDist","source","feat","geom","closest","distPx","LineString","ol_interaction_Draw","evt","cuttingLine","cuttingLineCoords","feature","coordsA","coordsB","featureA","PolygonGeom","featureB","splitFeatures","splitMap","distToSegmentSq","segA","segB","lenSq","projX","projY","findClosestEdge","clickCoord","bestIdx","d","coordsEqual","tolSq","isVertexNearRing","findSharedBoundary","seedIdxA","seedIdxB","tolerance","nA","nB","a0","a1","b0","b1","a0NearB","a1NearB","b0NearA","b1NearA","reversed","startA","endA","startB","endB","safety","nextA","nextB","prevA","prevB","walkRing","fromIdx","toIdx","mergePolygons","polygonCoordsA","polygonCoordsB","clickCoordA","clickCoordB","holesA","holesB","seedA","seedB","shared","partA","partB","merged","mergedRing","areaA","areaB","areaMerged","expectedArea","finalRing","validHoles","HIGHLIGHT_A","HIGHLIGHT_B","LABEL_A","Text","LABEL_B","EDGE_STYLE","MERGE_STYLE","PolygonMergeInteraction","skipFeature","style","edge","edgeFeat","Feature","resolution","bestSeg","sourceA","sourceB","geomA","geomB","mergedFeature","evtData","mergeMap","afterEvt","isParcelA","isParcelB","toRemove","cloneA","cloneB","polygonArea","longestEdge","bestLen","bestI","along","perp","makeCuttingLine","origin","extent","centroidT","sx","sy","dividePolygon","edgeCoords","nVerts","perpMin","perpMax","pieces","remaining","remainingCount","remainingArea","targetArea","remRing","remN","rMin","rMax","lo","hi","bestPiece","bestRemaining","bestError","iter","mid","nudge","lineA","resultA","halfA","halfB","tA","tB","nearPiece","farPiece","nearArea","lineB","resultB","pieceColors","colors","hue","PolygonDivideInteraction","ext","center","newFeatures","divideMap","MapView","targetId","cat","emoji","label","fontSize","baseLayers","LayerGroup","View","fromLonLat","layerSwitcher","LayerSwitcher","btn","baseUrl","_lsChromeScheduled","ScaleLine","searchNominatim","SearchNominatim","searchResult","lonLat","coordinate","Circle","mapLayers","overlayIdx","Select","clickCondition","shiftKeyOnly","DragBox","platformModifierKeyOnly","selected","ModifyFeature","UndoRedo","EditBar","extraBar","Bar","Button","Split","idFields","field","splitLineToggle","Toggle","splitPolyToggle","splitDivideToggle","splitSubBar","splitParentToggle","mergeToggle","editbarEl","breakEl","SnapGuides","VectorImageLayer","drawToolNames","interaction","snapToggleBtn","visible","TouchCursor","tag","del","l","listeners","wasActive","hasFinePointer","canHover","wantCursor","q","onChange","mq","ur","prev","feats","Point","out","isCoord","visitRing","isPolygonRing","poly","walk","sub","system","Overlay","currentFeature","html","catColor","title","color","geometry","geomType","skipKeys","areaSqm","getArea","areaFormatted","lengthM","getLength","lengthFormatted","toLonLat","parcelFeatures","zoneFeatures","otherByLayer","dataRows","names","tableRows","labelColor","border","exportContext","pdfRows","analyseBtn","totalFeatures","arr","gisBtn","circleFeature","circleGeom","circlePoly","fromCircle","circleExtent","radius","intersectsCircle","fExtent","scanGroup","group","groupTitle","layerTitle","candidates","fType","radiusFormatted","polygonFeature","polyGeom","polyExtent","perimeterM","perimeterFormatted","intersectsPoly","typeB","flatB","stride","flatA","strideA","fieldsHtml","displayVal","escapedKey","escapedVal","form","formData","updatedProps","propsA","propsB","getLabel","labelA","labelB","close","chosenProps","labels","radios","updateHighlight","lbl","radio","input","keys","attributeKeys","clickedFeature","text","div","coordsEl","defaultBasemap","topoLayer","TileLayer","XYZ","cartoLightLayer","cartoDarkLayer","osmCycleLayer","OSM","satelliteLayer","googleLayer","osmLayer","baseGroup","matched","on","OPTIONS","target","panel","opt","syncSelection","open","resAtLat","halo","dot","radiusMeters","segments","zoom","toggle","next","customStyle","styles","locations","featureOrId","padding","hasOverlayFeature","hasParcelFeature","markerFeature","index","hoveredFeature","geojson","styleOptions","targetGroup","strokeColor","strokeWidth","strokeDash","fillColor","lineCasingColor","lineCasingWidth","pointRadius","pointFillColor","pointStrokeColor","pointStrokeWidth","GeoJSON","fillStyle","pointStyle","mainStroke","layerStyle","casingW","describeFromGeom","initial","once","ev","desc","wmsSource","TileWMS","wmsLayer","xyzSource","xyzLayer","problem","WebGLTileLayer","GeoTIFFSource","cogLayer","sourceOpts","visibleOnly","nonEmptyOnly","card","nameRow","nameHint","urlInput","typeHint","layerName","dlg","typeHintEl","inp","wmsSrc","wfsUrl","wfsSource","labelSpan","chip","btnBar","chevronEl","content","ensureSubtitle","removeBtn","chipSpec","fresh","addBtn","visit","removed","child","panelContainer","ul","badge","footer","counts","totalOverlays","activeOverlays","HIDDEN_INTERNAL","refresh","hookLayer","added","legendUrl","wrapper","update","children","str","found","view","src","ex","MapTools","drawCircle","Draw","output","radiusLine","unByKey","drawLine","drawPolygon","drawPoint","mainBar","measureBar","circleBtn","lineBtn","areaBtn","clearBtn","swRegistration","registerServiceWorker","newWorker","showUpdateNotification","deferredPrompt","installButton","initInstallPrompt","buttonSelector","showManualInstallInstructions","outcome","isIOS","isSafari","offlineIndicator","offlineListeners","initOfflineDetection","indicatorSelector","updateOfflineUI","notifyOfflineListeners","isOffline","onOfflineChange","isOnline","applyUpdate","getActiveServiceWorker","timeoutMs","ready","timeout","registration","sw","onServiceWorkerControllerChange","requestFromServiceWorker","requestType","responseType","extra","readyTimeoutMs","timer","getTileCacheStats","clearTileCaches","clearTileCacheForProvider","cacheName","getStorageEstimate","usage","quota","initPWA","autoRegisterSW","BASEMAP_TEMPLATES","AVG_TILE_BYTES","ORIGIN_SHIFT","metersToLonLat","x","y","lonLatToTile","latRad","tileRangeForExtent","extent3857","minLon","minLat","maxLon","maxLat","tl","br","minTileX","maxTileX","minTileY","maxTileY","countTiles","minZ","maxZ","enumerateTiles","formatTileUrl","template","OfflineTileDownloader","baseMap","minZoom","maxZoom","concurrency","interBatchDelayMs","onProgress","tpl","tiles","done","ok","failed","cached","emit","phase","elapsedMs","etaMs","batch","GHANA_EXTENT_3857","lonLatToMeters","ne","estimatedSizeBytes","tileCount","API_BASE","FALLBACK_DISTRICT_ID","API_TOKEN","resolveDistrictId","session","API_CREDENTIALS","getSession","raw","REQUEST_TIMEOUT","PING_TIMEOUT","_serverReachable","checkServerReachable","force","controller","isServerReachable","withTimeout","ms","remotePost","endpoint","body","getDistrictBoundary","getLayers","getCollectorZones","getDistrictParcels","getBuildingFootprints","getContoursHillshade","getOSMRoads","getUpnGrid","pushGpsTrail","trail","points","EARTH_RADIUS_M","DEG2RAD","haversineMeters","lon1","lat1","lon2","lat2","dLat","dLon","formatCoord","decimals","UTM_A","UTM_F","UTM_K0","UTM_E2","UTM_EP2","latLonToUTM","lonNorm","zone","lon0","phi","lambda","lambda0","sinPhi","cosPhi","tanPhi","N","T","C","A","M","easting","northing","hemisphere","formatUTM","formatDistance","meters","formatAccuracy","accuracyQuality","DEFAULTS","GeoTracker","set","pos","fix","trailMeta","synced","pushed","trails","trailRow","minIntervalMs","minDistanceM","heartbeatMs","maxAccuracyM","now","keep","stepM","elapsed","num","ch","sqlocalStorage","remote","remoteSync","geoTracker","KNOWN_COMMANDS","createEmbedBridge","mapView","embedConfig","highlightSource","highlightLayer","parcelsLayer","pendingSelectUpn","readyEmitted","send","emitError","code","emitReady","parcelPayload","outLon","outLat","getCenter","highlightFeature","_markerFeature","parcelFeature","msg","selectByUpn","upn","attachParcelsLayer","drain","scheduled","TARGET_TYPES","TARGET_FIELDS","dominantGeometryFamily","fc","polys","lines","max","attributeFingerprint","sampleSize","has","fp","detectTargetType","family","FIELD_CANDIDATES","normaliseKey","autoMapFields","sourceByNorm","mapping","col","cand","applyFieldMapping","sourceProps","targetCol","sourceKey","listSourceFields","seen","sampleSourceValues","maxLen","samples","els","modal","state","cacheEls","onTargetChange","finish","renderFieldsTable","sampleSuffix","escapeHtml","optionsHtml","escapeAttr","toBoldUnicode","current","select","sel","newType","onResult","openImportMappingModal","Modal","cp","fieldsize","lib","char","fieldLength","fieldSize","require$$0","fields","multi","bytesPer","obj","inherit","isDef","o","memo","require$$1","require$$2","structure","field_meta","fieldDescLength","bytesPerRecord","headerLength","val","dbf","prj","coordinates","shpView","shxView","contentLength","fileLength","shpI","shxI","geometries","TYPE","shxOffset","writePolyLine","flattened","justCoords","noParts","parts","featureExtent","onlyParts","no","rings","require$$3","require$$4","pointWriter","require$$6","polyWriter","require$$7","writers","write_1","write","geometry_type","writer","shpLength","shxLength","shpBuffer","shxBuffer","writeHeader","writeExtent","dbfBuf","justType","gj","oftype","isType","justProps","JSZip","zip","files","fileName","generateOptions","download","shpWrite","PROJ_MAP","PROJ_WGS84","exportFeaturesToGis","rename","format","filenameBase","buildRenamedGeoJSON","downloadBlob","writeKml","writeShp","fmt","GeoJSONFormat","geomGeoJson","stripGeometryFromProps","outProps","clones","labelKey","KMLFormat","sanitised","sanitiseShpFieldNames","shpwrite.download","allKeys","used","base","candidate","suffix","newProps","onFormatChange","onExportClick","collectFeatures","ctx","tagWithSource","sourceLabel","unionAttributeKeys","skip","currentFormat","warn","isPdf","exportAnalysisPDF","openExportGisModal","def","_shpModule","getShp","mod","showImportSpinner","overlay","nameEl","hideImportSpinner","mapTools","embedBridge","EMBED_CONFIG","IS_EMBED_PERMIT","currentMode","showNoDistrictBlockerIfNeeded","initApp","savedBasemap","initGpsTracking","upnGridFeature","showLocationDetails","layerType","loadLocations","showSuccess","showError","wktFormat","WKT","wktString","enforceDistrictConsistency","showWarning","loadLayers","loadDistrictBoundary","loadUpnGrid","loadCollectorZones","loadParcels","loadBuildingFootprints","loadContoursHillshade","loadOSMRoads","loadExternalWMSLayers","initUI","statsContainer","refreshLocalDataStats","offline","syncData","initFieldworkMode","initMeasurementSystem","initCoordinateFormat","initDarkMode","initDefaultBasemap","initOfflineTileCache","initOfflineDownloadDialog","initAccountCard","initMessageLog","exportBtn","handleExport","localDataBtn","importShpBtn","shpFileInput","handleShapefileImport","importGeoJSONBtn","geojsonFileInput","handleGeoJSONImport","importKMLBtn","kmlFileInput","handleKMLImport","initMapDropZone","exportGeoJSONBtn","handleExportGeoJSON","statusBtn","handleShowStatus","fitBtn","addLocationBtn","measureCircleBtn","measureLineBtn","measureAreaBtn","drawBtn","analysisBtn","openAnalysisModal","modeButtons","setMode","activeBtn","renderLocations","countEl","mobileCount","categoryEmojis","item","tbody","clearAllBtn","stats","link","showTableContent","handleClearAllCachedLayers","modalTitle","modalBody","modalInfo","headerCells","bodyRows","display","statusContent","parseCoordRing","ringStr","pair","parseWKTPolygon","parseWKTMultiPolygon","polyStr","parseWKT","trimmed","apiResponseToGeoJSON","apiResponse","boundary","districtid","district_name","zonesToGeoJSON","LAST_DISTRICT_KEY","districtBoundaryCacheKey","currentStr","previous","CACHE_KEY","ADMIN_GROUP_ID","boundaryStyle","adminGroup","removeBoundaryLayer","zoomToBoundary","willFetchFresh","upnGridToGeoJSON","upnGridStyle","emptyGeoJSON","upnGridLayer","UPN_LABEL_MAX_RESOLUTION","prefix","OlText","setFeatures","zoneStyle","zonesLayer","setZoneFeatures","parcelsToGeoJSON","parcel","parcelStyle","landUseGroup","setParcelFeatures","footprintsToGeoJSON","geomKeys","footprintStyle","physInfraGroup","footprintsLayer","setFootprintFeatures","wktRowsToGeoJSON","geojsonFormat","olGeom","flattenProps","contoursStyle","biophysGroup","contoursLayer","roadsStyle","roadsLayer","setRoadFeatures","createLayerGroupsOnMap","overlayLayers","importedFileLayers","IMPORT_STYLE","showFileImportError","logMessage","addImportedGeoJSON","geojsonInput","fallbackName","collections","stageImport","lastLayer","refreshImportedLayersCard","wktFormat4326","geometryToWkt4326","displayName","stagedRows","newClientUuid","impId","handleImportModalResult","refreshLayerSwitcherChip","runUpload","imp","scopeFeatures","switcher","infoEl","listEl","removeImportedLayer","removeImportedLayers","overlayGroup","indexFilesByExtension","MAX_FILE_SIZE","totalSize","sizeMB","byExt","file","missing","shpObj","KML","dragCounter","exts","fakeEvt","MESSAGE_LOG_MAX","MSG_CONFIG","cfg","log","placeholder","entry","_lastGpsFix","getCoordFormat","renderGpsCoords","utmEl","latlon","utm","readout","accEl","satsEl","trySync","applyDark","updateLabel","statsEl","offcanvas","fmtBytes","refreshInFlight","swActive","storageNote","est","pct","triggerBtn","modalEl","formView","progressView","doneView","cancelBtn","startBtn","closeDoneBtn","headerCloseBtn","basemapSelect","minZoomInput","maxZoomInput","ackCheck","estimateEl","estimateBox","areaViewRadio","areaDistrictRadio","areaGhanaRadio","areaViewInfo","areaDistrictInfo","progressBar","progressPercent","progressCounts","progressOk","progressFailed","progressEta","doneTitle","doneDetail","currentDownloader","fmtDuration","m","getSelectedExtent","updateEstimate","tplMaxZoom","effMaxZ","warningHTML","updateAreaInfos","resetModal","menuBtn","avatarEl","emailEl","detailEl","signoutBtn","landingLink","signinLink","noSessNote","bits","handleSignOut"],"ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54],"sources":["../../node_modules/proxy-target/esm/types.js","../../node_modules/coincident/esm/channel.js","../../node_modules/proxy-target/esm/traps.js","../../node_modules/coincident/esm/bridge.js","../../node_modules/coincident/esm/index.js","../../node_modules/sqlocal/dist/lib/create-mutex.js","../../node_modules/sqlocal/dist/lib/normalize-database-file.js","../../node_modules/sqlocal/dist/drivers/sqlite-memory-driver.js","../../node_modules/sqlocal/dist/lib/debounce.js","../../node_modules/sqlocal/dist/lib/get-query-key.js","../../node_modules/sqlocal/dist/lib/get-database-key.js","../../node_modules/sqlocal/dist/processor.js","../../node_modules/sqlocal/dist/lib/sql-tag.js","../../node_modules/sqlocal/dist/lib/convert-rows-to-objects.js","../../node_modules/sqlocal/dist/lib/normalize-statement.js","../../node_modules/sqlocal/dist/lib/normalize-sql.js","../../node_modules/sqlocal/dist/lib/mutation-lock.js","../../node_modules/sqlocal/dist/drivers/sqlite-kvvfs-driver.js","../../node_modules/sqlocal/dist/client.js","../../src/database.js","../../src/units.js","../../src/geom/polygonSplit.js","../../src/toast.js","../../src/interactions/PolygonSplitInteraction.js","../../src/geom/polygonMerge.js","../../src/interactions/PolygonMergeInteraction.js","../../src/geom/polygonDivide.js","../../src/interactions/PolygonDivideInteraction.js","../../src/components/MapView.js","../../src/components/MapTools.js","../../src/pwa.js","../../src/offlineTiles.js","../../src/remotedb.js","../../src/geotracker/geo-utils.js","../../src/geotracker/GeoTracker.js","../../src/geotracker-lupmis.js","../../src/embed-bridge.js","../../src/import-detect.js","../../src/import-modal.js","../../node_modules/shp-write/src/types.js","../../node_modules/dbf/src/fieldsize.js","../../node_modules/dbf/src/lib.js","../../node_modules/dbf/src/fields.js","../../node_modules/dbf/src/structure.js","../../node_modules/dbf/index.js","../../node_modules/shp-write/src/prj.js","../../node_modules/shp-write/src/extent.js","../../node_modules/shp-write/src/fields.js","../../node_modules/shp-write/src/points.js","../../node_modules/shp-write/src/poly.js","../../node_modules/shp-write/src/write.js","../../node_modules/shp-write/src/geojson.js","../../node_modules/shp-write/src/zip.js","../../node_modules/shp-write/src/download.js","../../node_modules/shp-write/index.js","../../src/gis-export.js","../../src/export-gis-modal.js","../../main.js"],"sourcesContent":["export const ARRAY = 'array';\nexport const BIGINT = 'bigint';\nexport const BOOLEAN = 'boolean';\nexport const FUNCTION = 'function';\nexport const NULL = 'null';\nexport const NUMBER = 'number';\nexport const OBJECT = 'object';\nexport const STRING = 'string';\nexport const SYMBOL = 'symbol';\nexport const UNDEFINED = 'undefined';\n","// ⚠️ AUTOMATICALLY GENERATED - DO NOT CHANGE\nexport const CHANNEL = '64e10b34-2bf7-4616-9668-f99de5aa046e';\n\nexport const MAIN = 'M' + CHANNEL;\nexport const THREAD = 'T' + CHANNEL;\n","export const APPLY = 'apply';\nexport const CONSTRUCT = 'construct';\nexport const DEFINE_PROPERTY = 'defineProperty';\nexport const DELETE_PROPERTY = 'deleteProperty';\nexport const GET = 'get';\nexport const GET_OWN_PROPERTY_DESCRIPTOR = 'getOwnPropertyDescriptor';\nexport const GET_PROTOTYPE_OF = 'getPrototypeOf';\nexport const HAS = 'has';\nexport const IS_EXTENSIBLE = 'isExtensible';\nexport const OWN_KEYS = 'ownKeys';\nexport const PREVENT_EXTENSION = 'preventExtensions';\nexport const SET = 'set';\nexport const SET_PROTOTYPE_OF = 'setPrototypeOf';\n","// The goal of this file is to normalize SAB\n// at least in main -> worker() use cases.\n// This still cannot possibly solve the sync\n// worker -> main() use case if SharedArrayBuffer\n// is not available or usable.\n\nimport {CHANNEL} from './channel.js';\n\nconst {isArray} = Array;\n\nlet {SharedArrayBuffer, window} = globalThis;\nlet {notify, wait, waitAsync} = Atomics;\nlet postPatched = null;\n\n// This is needed for some version of Firefox\nif (!waitAsync) {\n waitAsync = buffer => ({\n value: new Promise(onmessage => {\n // encodeURIComponent('onmessage=({data:b})=>(Atomics.wait(b,0),postMessage(0))')\n let w = new Worker('data:application/javascript,onmessage%3D(%7Bdata%3Ab%7D)%3D%3E(Atomics.wait(b%2C0)%2CpostMessage(0))');\n w.onmessage = onmessage;\n w.postMessage(buffer);\n })\n });\n}\n\n// Monkey-patch SharedArrayBuffer if needed\ntry {\n new SharedArrayBuffer(4);\n}\ncatch (_) {\n SharedArrayBuffer = ArrayBuffer;\n\n const ids = new WeakMap;\n // patch only main -> worker():async use case\n if (window) {\n const resolvers = new Map;\n const {prototype: {postMessage}} = Worker;\n\n const listener = event => {\n const details = event.data?.[CHANNEL];\n if (!isArray(details)) {\n event.stopImmediatePropagation();\n const { id, sb } = details;\n resolvers.get(id)(sb);\n }\n };\n\n postPatched = function (data, ...rest) {\n const details = data?.[CHANNEL];\n if (isArray(details)) {\n const [id, sb] = details;\n ids.set(sb, id);\n this.addEventListener('message', listener);\n }\n return postMessage.call(this, data, ...rest);\n };\n\n waitAsync = sb => ({\n value: new Promise(resolve => {\n resolvers.set(ids.get(sb), resolve);\n }).then(buff => {\n resolvers.delete(ids.get(sb));\n ids.delete(sb);\n for (let i = 0; i < buff.length; i++) sb[i] = buff[i];\n return 'ok';\n })\n });\n }\n else {\n const as = (id, sb) => ({[CHANNEL]: { id, sb }});\n\n notify = sb => {\n postMessage(as(ids.get(sb), sb));\n };\n\n addEventListener('message', event => {\n const details = event.data?.[CHANNEL];\n if (isArray(details)) {\n const [id, sb] = details;\n ids.set(sb, id);\n }\n });\n }\n}\n\nexport {SharedArrayBuffer, isArray, notify, postPatched, wait, waitAsync};\n","/*! (c) Andrea Giammarchi - ISC */\n\nimport {FUNCTION} from 'proxy-target/types';\n\nimport {CHANNEL} from './channel.js';\nimport {GET, HAS, SET} from './shared/traps.js';\n\nimport {SharedArrayBuffer, isArray, notify, postPatched, wait, waitAsync} from './bridge.js';\n\n// just minifier friendly for Blob Workers' cases\nconst {Int32Array, Map, Uint16Array} = globalThis;\n\n// common constants / utilities for repeated operations\nconst {BYTES_PER_ELEMENT: I32_BYTES} = Int32Array;\nconst {BYTES_PER_ELEMENT: UI16_BYTES} = Uint16Array;\n\nconst waitInterrupt = (sb, delay, handler) => {\n while (wait(sb, 0, 0, delay) === 'timed-out')\n handler();\n};\n\n// retain buffers to transfer\nconst buffers = new WeakSet;\n\n// retain either main threads or workers global context\nconst context = new WeakMap;\n\nconst syncResult = {value: {then: fn => fn()}};\n\n// used to generate a unique `id` per each worker `postMessage` \"transaction\"\nlet uid = 0;\n\n/**\n * @typedef {Object} Interrupt used to sanity-check interrupts while waiting synchronously.\n * @prop {function} [handler] a callback invoked every `delay` milliseconds.\n * @prop {number} [delay=42] define `handler` invokes in terms of milliseconds.\n */\n\n/**\n * Create once a `Proxy` able to orchestrate synchronous `postMessage` out of the box.\n * @param {globalThis | Worker} self the context in which code should run\n * @param {{parse: (serialized: string) => any, stringify: (serializable: any) => string, transform?: (value:any) => any, interrupt?: () => void | Interrupt}} [JSON] an optional `JSON` like interface to `parse` or `stringify` content with extra `transform` ability.\n * @returns {ProxyHandler | ProxyHandler}\n */\nconst coincident = (self, {parse = JSON.parse, stringify = JSON.stringify, transform, interrupt} = JSON) => {\n // create a Proxy once for the given context (globalThis or Worker instance)\n if (!context.has(self)) {\n // ensure no SAB gets a chance to pass through this call\n const sendMessage = postPatched || self.postMessage;\n // ensure the CHANNEL and data are posted correctly\n const post = (transfer, ...args) => sendMessage.call(self, {[CHANNEL]: args}, {transfer});\n\n const handler = typeof interrupt === FUNCTION ? interrupt : interrupt?.handler;\n const delay = interrupt?.delay || 42;\n const decoder = new TextDecoder('utf-16');\n\n // automatically uses sync wait (worker -> main)\n // or fallback to async wait (main -> worker)\n const waitFor = (isAsync, sb) => isAsync ?\n waitAsync(sb, 0) :\n ((handler ? waitInterrupt(sb, delay, handler) : wait(sb, 0)), syncResult);\n\n // prevent Harakiri https://github.com/WebReflection/coincident/issues/18\n let seppuku = false;\n\n context.set(self, new Proxy(new Map, {\n // there is very little point in checking prop in proxy for this very specific case\n // and I don't want to orchestrate a whole roundtrip neither, as stuff would fail\n // regardless if from Worker we access non existent Main callback, and vice-versa.\n // This is here mostly to guarantee that if such check is performed, at least the\n // get trap goes through and then it's up to developers guarantee they are accessing\n // stuff that actually exists elsewhere.\n [HAS]: (_, action) => typeof action === 'string' && !action.startsWith('_'),\n\n // worker related: get any utility that should be available on the main thread\n [GET]: (_, action) => action === 'then' ? null : ((...args) => {\n // transaction id\n const id = uid++;\n\n // first contact: just ask for how big the buffer should be\n // the value would be stored at index [1] while [0] is just control\n let sb = new Int32Array(new SharedArrayBuffer(I32_BYTES * 2));\n\n // if a transfer list has been passed, drop it from args\n let transfer = [];\n if (buffers.has(args.at(-1) || transfer))\n buffers.delete(transfer = args.pop());\n\n // ask for invoke with arguments and wait for it\n post(transfer, id, sb, action, transform ? args.map(transform) : args);\n\n // helps deciding how to wait for results\n const isAsync = self !== globalThis;\n\n // warn users about possible deadlock still allowing them\n // to explicitly `proxy.invoke().then(...)` without blocking\n let deadlock = 0;\n if (seppuku && isAsync)\n deadlock = setTimeout(console.warn, 1000, `💀🔒 - Possible deadlock if proxy.${action}(...args) is awaited`);\n\n return waitFor(isAsync, sb).value.then(() => {\n clearTimeout(deadlock);\n\n // commit transaction using the returned / needed buffer length\n const length = sb[1];\n\n // filter undefined results\n if (!length) return;\n\n // calculate the needed ui16 bytes length to store the result string\n const bytes = UI16_BYTES * length;\n\n // round up to the next amount of bytes divided by 4 to allow i32 operations\n sb = new Int32Array(new SharedArrayBuffer(bytes + (bytes % I32_BYTES)));\n\n // ask for results and wait for it\n post([], id, sb);\n return waitFor(isAsync, sb).value.then(() => parse(\n decoder.decode(new Uint16Array(sb.buffer).slice(0, length)))\n );\n });\n }),\n\n // main thread related: react to any utility a worker is asking for\n [SET](actions, action, callback) {\n const type = typeof callback;\n if (type !== FUNCTION)\n throw new Error(`Unable to assign ${action} as ${type}`);\n // lazy event listener and logic handling, triggered once by setters actions\n if (!actions.size) {\n // maps results by `id` as they are asked for\n const results = new Map;\n // add the event listener once (first defined setter, all others work the same)\n self.addEventListener('message', async (event) => {\n // grub the very same library CHANNEL; ignore otherwise\n const details = event.data?.[CHANNEL];\n if (isArray(details)) {\n // if early enough, avoid leaking data to other listeners\n event.stopImmediatePropagation();\n const [id, sb, ...rest] = details;\n let error;\n // action available: it must be defined/known on the main thread\n if (rest.length) {\n const [action, args] = rest;\n if (actions.has(action)) {\n seppuku = true;\n try {\n // await for result either sync or async and serialize it\n const result = await actions.get(action)(...args);\n if (result !== void 0) {\n const serialized = stringify(transform ? transform(result) : result);\n // store the result for \"the very next\" event listener call\n results.set(id, serialized);\n // communicate the required SharedArrayBuffer length out of the\n // resulting serialized string\n sb[1] = serialized.length;\n }\n }\n catch (_) {\n error = _;\n }\n finally {\n seppuku = false;\n }\n }\n // unknown action should be notified as missing on the main thread\n else {\n error = new Error(`Unsupported action: ${action}`);\n }\n // unlock the wait lock later on\n sb[0] = 1;\n }\n // no action means: get results out of the well known `id`\n // wait lock automatically unlocked here as no `0` value would\n // possibly ever land at index `0`\n else {\n const result = results.get(id);\n results.delete(id);\n // populate the SharedArrayBuffer with utf-16 chars code\n for (let ui16a = new Uint16Array(sb.buffer), i = 0; i < result.length; i++)\n ui16a[i] = result.charCodeAt(i);\n }\n // release te worker waiting either the length or the result\n notify(sb, 0);\n if (error) throw error;\n }\n });\n }\n // store this action callback allowing the setter in the process\n return !!actions.set(action, callback);\n }\n }));\n }\n return context.get(self);\n};\n\ncoincident.transfer = (...args) => (buffers.add(args), args);\n\nexport default coincident;\n","export function createMutex() {\n let promise;\n let resolve;\n const lock = async () => {\n while (promise) {\n await promise;\n }\n promise = new Promise((res) => {\n resolve = res;\n });\n };\n const unlock = async () => {\n const res = resolve;\n promise = undefined;\n resolve = undefined;\n res?.();\n };\n return { lock, unlock };\n}\n//# sourceMappingURL=create-mutex.js.map","export async function normalizeDatabaseFile(dbFile, convertStreamTo) {\n let bufferOrStream;\n if (dbFile instanceof Blob) {\n bufferOrStream = dbFile.stream();\n }\n else {\n bufferOrStream = dbFile;\n }\n if (bufferOrStream instanceof ReadableStream && convertStreamTo) {\n const stream = bufferOrStream;\n const reader = stream.getReader();\n switch (convertStreamTo) {\n case 'callback':\n return async () => {\n const chunk = await reader.read();\n return chunk.value;\n };\n case 'buffer':\n const chunks = [];\n let streamDone = false;\n while (!streamDone) {\n const chunk = await reader.read();\n if (chunk.value)\n chunks.push(chunk.value);\n streamDone = chunk.done;\n }\n const arrayLength = chunks.reduce((length, chunk) => {\n return length + chunk.length;\n }, 0);\n const buffer = new Uint8Array(arrayLength);\n let offset = 0;\n chunks.forEach((chunk) => {\n buffer.set(chunk, offset);\n offset += chunk.length;\n });\n return buffer.buffer;\n }\n }\n else {\n return bufferOrStream;\n }\n}\n//# sourceMappingURL=normalize-database-file.js.map","import { normalizeDatabaseFile } from '../lib/normalize-database-file.js';\nexport class SQLiteMemoryDriver {\n constructor(sqlite3InitModule) {\n Object.defineProperty(this, \"sqlite3InitModule\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: sqlite3InitModule\n });\n Object.defineProperty(this, \"sqlite3\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"db\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"config\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"pointers\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: []\n });\n Object.defineProperty(this, \"writeCallbacks\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: new Set()\n });\n Object.defineProperty(this, \"storageType\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: 'memory'\n });\n }\n async init(config) {\n const { databasePath } = config;\n const flags = this.getFlags(config);\n if (!this.sqlite3InitModule) {\n const { default: sqlite3InitModule } = await import('@sqlite.org/sqlite-wasm');\n this.sqlite3InitModule = sqlite3InitModule;\n }\n if (!this.sqlite3) {\n this.sqlite3 = await this.sqlite3InitModule();\n }\n if (this.db) {\n await this.destroy();\n }\n this.db = new this.sqlite3.oo1.DB(databasePath, flags);\n this.config = config;\n this.initWriteHook();\n }\n onWrite(callback) {\n this.writeCallbacks.add(callback);\n return () => {\n this.writeCallbacks.delete(callback);\n };\n }\n async exec(statement) {\n if (!this.db)\n throw new Error('Driver not initialized');\n return this.execOnDb(this.db, statement);\n }\n async execBatch(statements) {\n if (!this.db)\n throw new Error('Driver not initialized');\n const results = [];\n this.db.transaction((tx) => {\n const prepared = new Map();\n try {\n for (let statement of statements) {\n let stmt = prepared.get(statement.sql);\n if (!stmt) {\n const newStmt = tx.prepare(statement.sql);\n prepared.set(statement.sql, newStmt);\n stmt = newStmt;\n }\n if (statement.params?.length) {\n stmt.bind(statement.params);\n }\n let columns = [];\n let rows = [];\n while (stmt.step()) {\n columns = stmt.getColumnNames([]);\n rows.push(stmt.get([]));\n }\n results.push({ columns, rows });\n stmt.reset();\n }\n }\n finally {\n prepared.forEach((stmt) => {\n stmt.finalize();\n });\n }\n });\n return results;\n }\n async isDatabasePersisted() {\n return false;\n }\n async getDatabaseSizeBytes() {\n const sizeResult = await this.exec({\n sql: `SELECT page_count * page_size AS size \n\t\t\t\tFROM pragma_page_count(), pragma_page_size()`,\n method: 'get',\n });\n const size = sizeResult?.rows?.[0];\n if (typeof size !== 'number') {\n throw new Error('Failed to query database size');\n }\n return size;\n }\n async createFunction(fn) {\n if (!this.db)\n throw new Error('Driver not initialized');\n switch (fn.type) {\n case 'callback':\n case 'scalar':\n this.db.createFunction({\n name: fn.name,\n xFunc: (_, ...args) => fn.func(...args),\n arity: -1,\n });\n break;\n case 'aggregate':\n this.db.createFunction({\n name: fn.name,\n xStep: (_, ...args) => fn.func.step(...args),\n xFinal: (_, ...args) => fn.func.final(...args),\n arity: -1,\n });\n break;\n }\n }\n async import(database) {\n if (!this.sqlite3 || !this.db || !this.config) {\n throw new Error('Driver not initialized');\n }\n const data = await normalizeDatabaseFile(database, 'buffer');\n const dataPointer = this.sqlite3.wasm.allocFromTypedArray(data);\n this.pointers.push(dataPointer);\n const resultCode = this.sqlite3.capi.sqlite3_deserialize(this.db, 'main', dataPointer, data.byteLength, data.byteLength, this.config.readOnly\n ? this.sqlite3.capi.SQLITE_DESERIALIZE_READONLY\n : this.sqlite3.capi.SQLITE_DESERIALIZE_RESIZEABLE);\n this.db.checkRc(resultCode);\n }\n async export() {\n if (!this.sqlite3 || !this.db) {\n throw new Error('Driver not initialized');\n }\n return {\n name: 'database.sqlite3',\n data: this.sqlite3.capi.sqlite3_js_db_export(this.db),\n };\n }\n async clear() { }\n async destroy() {\n this.closeDb();\n this.pointers.forEach((pointer) => this.sqlite3?.wasm.dealloc(pointer));\n this.pointers = [];\n this.writeCallbacks.clear();\n }\n getFlags(config) {\n const { readOnly, verbose } = config;\n const parts = [readOnly === true ? 'r' : 'cw', verbose === true ? 't' : ''];\n return parts.join('');\n }\n execOnDb(db, statement) {\n const statementData = {\n rows: [],\n columns: [],\n };\n const rows = db.exec({\n sql: statement.sql,\n bind: statement.params,\n returnValue: 'resultRows',\n rowMode: 'array',\n columnNames: statementData.columns,\n });\n switch (statement.method) {\n case 'run':\n break;\n case 'get':\n statementData.rows = rows[0] ?? [];\n break;\n case 'all':\n default:\n statementData.rows = rows;\n break;\n }\n return statementData;\n }\n initWriteHook() {\n if (!this.config?.reactive)\n return;\n if (!this.sqlite3 || !this.db) {\n throw new Error('Driver not initialized');\n }\n const opMap = {\n [this.sqlite3.capi.SQLITE_INSERT]: 'insert',\n [this.sqlite3.capi.SQLITE_UPDATE]: 'update',\n [this.sqlite3.capi.SQLITE_DELETE]: 'delete',\n };\n this.sqlite3.capi.sqlite3_update_hook(this.db, (_ctx, opId, _db, table, rowid) => {\n this.writeCallbacks.forEach((cb) => {\n cb({ table, rowid, operation: opMap[opId] });\n });\n }, 0);\n }\n closeDb() {\n if (this.db) {\n this.db.close();\n this.db = undefined;\n }\n }\n}\n//# sourceMappingURL=sqlite-memory-driver.js.map","/**\n * Lodash (Custom Build) \n * Build: `lodash modularize exports=\"es\" include=\"debounce\" -p -o ./`\n * Copyright JS Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\nexport function debounce(func, wait, options) {\n let lastArgs;\n let lastThis;\n let maxWait;\n let result;\n let timerId;\n let lastCallTime;\n let lastInvokeTime = 0;\n let leading = false;\n let maxing = false;\n let trailing = true;\n if (typeof func !== 'function') {\n throw new TypeError('Expected a function');\n }\n wait = Number(wait) || 0;\n if (typeof options === 'object' && options !== null) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? Math.max(Number(options.maxWait) || 0, wait) : 0;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n function invokeFunc(time) {\n const args = lastArgs;\n const thisArg = lastThis;\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n function leadingEdge(time) {\n lastInvokeTime = time;\n timerId = setTimeout(timerExpired, wait);\n return leading ? invokeFunc(time) : result;\n }\n function remainingWait(time) {\n const timeSinceLastCall = time - (lastCallTime ?? 0);\n const timeSinceLastInvoke = time - lastInvokeTime;\n const timeWaiting = wait - timeSinceLastCall;\n return maxing\n ? Math.min(timeWaiting, maxWait - timeSinceLastInvoke)\n : timeWaiting;\n }\n function shouldInvoke(time) {\n const timeSinceLastCall = time - (lastCallTime ?? 0);\n const timeSinceLastInvoke = time - lastInvokeTime;\n return (lastCallTime === undefined ||\n timeSinceLastCall >= wait ||\n timeSinceLastCall < 0 ||\n (maxing && timeSinceLastInvoke >= maxWait));\n }\n function timerExpired() {\n const time = Date.now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n function trailingEdge(time) {\n timerId = undefined;\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n function flush() {\n return timerId === undefined ? result : trailingEdge(Date.now());\n }\n function debounced() {\n const time = Date.now();\n const isInvoking = shouldInvoke(time);\n // @ts-ignore\n lastArgs = arguments;\n // @ts-ignore\n lastThis = this;\n lastCallTime = time;\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n//# sourceMappingURL=debounce.js.map","export function getQueryKey() {\n return crypto.randomUUID();\n}\n//# sourceMappingURL=get-query-key.js.map","import { getQueryKey } from './get-query-key.js';\nexport function getDatabaseKey(databasePath, clientKey) {\n switch (databasePath) {\n case 'session':\n case ':sessionStorage:':\n // The sessionStorage DB can be shared between clients in the same tab\n let sessionKey = sessionStorage._sqlocal_session_key;\n if (!sessionKey) {\n sessionKey = getQueryKey();\n sessionStorage._sqlocal_session_key = sessionKey;\n }\n return `session:${sessionKey}`;\n case 'local':\n case ':localStorage:':\n // There's only one localStorage DB per origin\n return 'local';\n case ':memory:':\n // Each memory DB is unique to a client\n return `memory:${clientKey}`;\n default:\n // OPFS DBs are shared by path across same-origin tabs\n return `path:${databasePath}`;\n }\n}\n//# sourceMappingURL=get-database-key.js.map","import coincident from 'coincident';\nimport { createMutex } from './lib/create-mutex.js';\nimport { SQLiteMemoryDriver } from './drivers/sqlite-memory-driver.js';\nimport { debounce } from './lib/debounce.js';\nimport { getDatabaseKey } from './lib/get-database-key.js';\nexport class SQLocalProcessor {\n constructor(driver) {\n Object.defineProperty(this, \"driver\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"config\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: {}\n });\n Object.defineProperty(this, \"userFunctions\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: new Map()\n });\n Object.defineProperty(this, \"initMutex\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: createMutex()\n });\n Object.defineProperty(this, \"transactionMutex\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: createMutex()\n });\n Object.defineProperty(this, \"transactionKey\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: null\n });\n Object.defineProperty(this, \"proxy\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"dirtyTables\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: new Set()\n });\n Object.defineProperty(this, \"effectsChannel\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"reinitChannel\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"onmessage\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"init\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (reason) => {\n if (!this.config.databasePath || !this.config.clientKey)\n return;\n await this.initMutex.lock();\n try {\n try {\n await this.driver.init(this.config);\n }\n catch {\n console.warn(`Persistence failed, so ${this.config.databasePath} will not be saved. For origin private file system persistence, make sure your web server is configured to use the correct HTTP response headers (See https://sqlocal.dev/guide/setup#cross-origin-isolation).`);\n this.config.databasePath = ':memory:';\n this.driver = new SQLiteMemoryDriver();\n await this.driver.init(this.config);\n }\n const dbKey = getDatabaseKey(this.config.databasePath, this.config.clientKey);\n this.reinitChannel = new BroadcastChannel(`_sqlocal_reinit_(${dbKey})`);\n this.reinitChannel.onmessage = (event) => {\n const message = event.data;\n if (this.config.clientKey === message.clientKey)\n return;\n switch (message.type) {\n case 'reinit':\n this.init(message.reason);\n break;\n case 'close':\n this.driver.destroy();\n break;\n }\n };\n if (this.config.reactive) {\n this.effectsChannel = new BroadcastChannel(`_sqlocal_effects_(${dbKey})`);\n this.driver.onWrite(async (change) => {\n this.dirtyTables.add(change.table);\n await this.transactionMutex.lock();\n this.emitEffectsDebounced();\n await this.transactionMutex.unlock();\n });\n }\n await Promise.all(Array.from(this.userFunctions.values()).map((fn) => {\n return this.initUserFunction(fn);\n }));\n await this.execInitStatements();\n this.emitMessage({ type: 'event', event: 'connect', reason });\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey: null,\n });\n await this.destroy();\n }\n finally {\n await this.initMutex.unlock();\n }\n }\n });\n Object.defineProperty(this, \"postMessage\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (event, _transfer) => {\n const message = event instanceof MessageEvent ? event.data : event;\n await this.initMutex.lock();\n switch (message.type) {\n case 'config':\n this.editConfig(message);\n break;\n case 'query':\n case 'batch':\n case 'transaction':\n this.exec(message);\n break;\n case 'function':\n this.createUserFunction(message);\n break;\n case 'getinfo':\n this.getDatabaseInfo(message);\n break;\n case 'import':\n this.importDb(message);\n break;\n case 'export':\n this.exportDb(message);\n break;\n case 'delete':\n this.deleteDb(message);\n break;\n case 'destroy':\n this.destroy(message);\n break;\n }\n await this.initMutex.unlock();\n }\n });\n Object.defineProperty(this, \"emitMessage\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: (message, transfer = []) => {\n if (this.onmessage) {\n this.onmessage(message, transfer);\n }\n }\n });\n Object.defineProperty(this, \"emitEffects\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: () => {\n if (!this.effectsChannel || this.dirtyTables.size === 0)\n return;\n this.effectsChannel.postMessage({\n type: 'effects',\n tables: [...this.dirtyTables],\n });\n this.dirtyTables.clear();\n }\n });\n Object.defineProperty(this, \"emitEffectsDebounced\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: debounce(() => this.emitEffects(), 32, {\n maxWait: 180,\n })\n });\n Object.defineProperty(this, \"editConfig\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: (message) => {\n this.config = message.config;\n this.init('initial');\n }\n });\n Object.defineProperty(this, \"exec\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n try {\n const response = {\n type: 'data',\n queryKey: message.queryKey,\n data: [],\n };\n switch (message.type) {\n case 'query':\n const partOfTransaction = this.transactionKey !== null &&\n this.transactionKey === message.transactionKey;\n try {\n if (!partOfTransaction) {\n await this.transactionMutex.lock();\n }\n const statementData = await this.driver.exec(message);\n response.data.push(statementData);\n }\n finally {\n if (!partOfTransaction) {\n await this.transactionMutex.unlock();\n }\n }\n break;\n case 'batch':\n try {\n await this.transactionMutex.lock();\n const results = await this.driver.execBatch(message.statements);\n response.data.push(...results);\n }\n finally {\n await this.transactionMutex.unlock();\n }\n break;\n case 'transaction':\n if (message.action === 'begin') {\n await this.transactionMutex.lock();\n this.transactionKey = message.transactionKey;\n await this.driver.exec({ sql: 'BEGIN' });\n }\n if ((message.action === 'commit' || message.action === 'rollback') &&\n this.transactionKey !== null &&\n this.transactionKey === message.transactionKey) {\n const sql = message.action === 'commit' ? 'COMMIT' : 'ROLLBACK';\n await this.driver.exec({ sql });\n this.transactionKey = null;\n await this.transactionMutex.unlock();\n }\n break;\n }\n this.emitMessage(response);\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey: message.queryKey,\n });\n }\n }\n });\n Object.defineProperty(this, \"execInitStatements\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n if (this.config.onInitStatements) {\n for (let statement of this.config.onInitStatements) {\n await this.driver.exec(statement);\n }\n }\n }\n });\n Object.defineProperty(this, \"getDatabaseInfo\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n try {\n this.emitMessage({\n type: 'info',\n queryKey: message.queryKey,\n info: {\n databasePath: this.config.databasePath,\n storageType: this.driver.storageType,\n databaseSizeBytes: await this.driver.getDatabaseSizeBytes(),\n persisted: await this.driver.isDatabasePersisted(),\n },\n });\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n queryKey: message.queryKey,\n error,\n });\n }\n }\n });\n Object.defineProperty(this, \"createUserFunction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n const { functionName: name, functionType: type, queryKey } = message;\n let fn;\n if (this.userFunctions.has(name)) {\n this.emitMessage({\n type: 'error',\n error: new Error(`A user-defined function with the name \"${name}\" has already been created for this SQLocal instance.`),\n queryKey,\n });\n return;\n }\n switch (type) {\n case 'callback':\n fn = {\n type,\n name,\n func: (...args) => {\n this.emitMessage({ type: 'callback', name, args });\n },\n };\n break;\n case 'scalar':\n fn = {\n type,\n name,\n func: this.proxy[`_sqlocal_func_${name}`],\n };\n break;\n case 'aggregate':\n fn = {\n type,\n name,\n func: {\n step: this.proxy[`_sqlocal_func_${name}_step`],\n final: this.proxy[`_sqlocal_func_${name}_final`],\n },\n };\n break;\n }\n try {\n await this.initUserFunction(fn);\n this.emitMessage({\n type: 'success',\n queryKey,\n });\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey,\n });\n }\n }\n });\n Object.defineProperty(this, \"initUserFunction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (fn) => {\n await this.driver.createFunction(fn);\n this.userFunctions.set(fn.name, fn);\n }\n });\n Object.defineProperty(this, \"importDb\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n const { queryKey, database } = message;\n let errored = false;\n try {\n await this.driver.import(database);\n if (this.driver.storageType === 'memory') {\n await this.execInitStatements();\n }\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey,\n });\n errored = true;\n }\n finally {\n if (this.driver.storageType !== 'memory') {\n await this.init('overwrite');\n }\n }\n if (!errored) {\n this.emitMessage({\n type: 'success',\n queryKey,\n });\n }\n }\n });\n Object.defineProperty(this, \"exportDb\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n const { queryKey } = message;\n try {\n const { name, data } = await this.driver.export();\n this.emitMessage({\n type: 'buffer',\n queryKey,\n bufferName: name,\n buffer: data,\n }, [data]);\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey,\n });\n }\n }\n });\n Object.defineProperty(this, \"deleteDb\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n const { queryKey } = message;\n let errored = false;\n try {\n await this.driver.clear();\n }\n catch (error) {\n this.emitMessage({\n type: 'error',\n error,\n queryKey,\n });\n errored = true;\n }\n finally {\n await this.init('delete');\n }\n if (!errored) {\n this.emitMessage({\n type: 'success',\n queryKey,\n });\n }\n }\n });\n Object.defineProperty(this, \"destroy\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n await this.driver.exec({ sql: 'PRAGMA optimize' });\n await this.driver.destroy();\n if (this.effectsChannel) {\n this.emitEffectsDebounced.flush();\n this.effectsChannel.close();\n this.effectsChannel = undefined;\n }\n if (this.reinitChannel) {\n this.reinitChannel.close();\n this.reinitChannel = undefined;\n }\n if (message) {\n this.emitMessage({\n type: 'success',\n queryKey: message.queryKey,\n });\n }\n }\n });\n const isInWorker = typeof WorkerGlobalScope !== 'undefined' &&\n globalThis instanceof WorkerGlobalScope;\n const proxy = isInWorker ? coincident(globalThis) : globalThis;\n this.proxy = proxy;\n this.driver = driver;\n }\n}\n//# sourceMappingURL=processor.js.map","export function sqlTag(queryTemplate, ...params) {\n return {\n sql: queryTemplate.join('?'),\n params,\n };\n}\n//# sourceMappingURL=sql-tag.js.map","function isArrayOfArrays(rows) {\n return !rows.some((row) => !Array.isArray(row));\n}\nexport function convertRowsToObjects(rows, columns) {\n let checkedRows;\n if (isArrayOfArrays(rows)) {\n checkedRows = rows;\n }\n else {\n checkedRows = [rows];\n }\n return checkedRows.map((row) => {\n const rowObj = {};\n columns.forEach((column, columnIndex) => {\n rowObj[column] = row[columnIndex];\n });\n return rowObj;\n });\n}\n//# sourceMappingURL=convert-rows-to-objects.js.map","import { sqlTag } from './sql-tag.js';\nfunction isDrizzleStatement(statement) {\n return (typeof statement === 'object' &&\n statement !== null &&\n 'getSQL' in statement &&\n typeof statement.getSQL === 'function');\n}\nfunction isStatement(statement) {\n return (typeof statement === 'object' &&\n statement !== null &&\n 'sql' in statement === true &&\n typeof statement.sql === 'string' &&\n 'params' in statement === true);\n}\nexport function normalizeStatement(statement) {\n if (typeof statement === 'function') {\n statement = statement(sqlTag);\n }\n if (isDrizzleStatement(statement)) {\n try {\n if (!('toSQL' in statement && typeof statement.toSQL === 'function')) {\n throw 1;\n }\n const drizzleStatement = statement.toSQL();\n if (!isStatement(drizzleStatement)) {\n throw 2;\n }\n const exec = 'all' in statement && typeof statement.all === 'function'\n ? statement.all\n : undefined;\n return {\n ...drizzleStatement,\n exec: exec ? () => exec() : undefined,\n };\n }\n catch {\n throw new Error('The passed statement could not be parsed.');\n }\n }\n const sql = statement.sql;\n let params = [];\n if ('params' in statement) {\n params = statement.params;\n }\n else if ('parameters' in statement) {\n params = statement.parameters;\n }\n return { sql, params };\n}\n//# sourceMappingURL=normalize-statement.js.map","import { sqlTag } from './sql-tag.js';\nexport function normalizeSql(maybeQueryTemplate, params) {\n let statement;\n if (typeof maybeQueryTemplate === 'string') {\n statement = { sql: maybeQueryTemplate, params };\n }\n else {\n statement = sqlTag(maybeQueryTemplate, ...params);\n }\n return statement;\n}\n//# sourceMappingURL=normalize-sql.js.map","export async function mutationLock(mode, bypass, config, mutation) {\n if (!bypass && 'locks' in navigator) {\n return navigator.locks.request(`_sqlocal_mutation_(${config.databasePath})`, { mode }, mutation);\n }\n else {\n return mutation();\n }\n}\n//# sourceMappingURL=mutation-lock.js.map","import { SQLiteMemoryDriver } from './sqlite-memory-driver.js';\nexport class SQLiteKvvfsDriver extends SQLiteMemoryDriver {\n constructor(storageType, sqlite3InitModule) {\n super(sqlite3InitModule);\n Object.defineProperty(this, \"storageType\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: storageType\n });\n }\n async init(config) {\n const flags = this.getFlags(config);\n if (config.readOnly) {\n throw new Error(`SQLite storage type \"${this.storageType}\" does not support read-only mode.`);\n }\n if (!this.sqlite3InitModule) {\n const { default: sqlite3InitModule } = await import('@sqlite.org/sqlite-wasm');\n this.sqlite3InitModule = sqlite3InitModule;\n }\n if (!this.sqlite3) {\n this.sqlite3 = await this.sqlite3InitModule();\n }\n if (this.db) {\n await this.destroy();\n }\n this.db = new this.sqlite3.oo1.JsStorageDb({\n filename: this.storageType,\n flags,\n });\n this.config = config;\n this.initWriteHook();\n }\n async isDatabasePersisted() {\n return navigator.storage?.persisted();\n }\n async getDatabaseSizeBytes() {\n if (!this.db)\n throw new Error('Driver not initialized');\n return this.db.storageSize();\n }\n async import(database) {\n const memdb = new SQLiteMemoryDriver();\n await memdb.init({});\n await memdb.import(database);\n await this.clear();\n await memdb.exec({\n sql: `VACUUM INTO 'file:${this.storageType}?vfs=kvvfs'`,\n });\n await memdb.destroy();\n }\n async clear() {\n if (!this.db)\n throw new Error('Driver not initialized');\n this.db.clearStorage();\n }\n async destroy() {\n this.closeDb();\n this.writeCallbacks.clear();\n }\n}\n//# sourceMappingURL=sqlite-kvvfs-driver.js.map","var _a, _b;\nimport coincident from 'coincident';\nimport { SQLocalProcessor } from './processor.js';\nimport { sqlTag } from './lib/sql-tag.js';\nimport { convertRowsToObjects } from './lib/convert-rows-to-objects.js';\nimport { normalizeStatement } from './lib/normalize-statement.js';\nimport { getQueryKey } from './lib/get-query-key.js';\nimport { normalizeSql } from './lib/normalize-sql.js';\nimport { mutationLock } from './lib/mutation-lock.js';\nimport { normalizeDatabaseFile } from './lib/normalize-database-file.js';\nimport { SQLiteMemoryDriver } from './drivers/sqlite-memory-driver.js';\nimport { SQLiteKvvfsDriver } from './drivers/sqlite-kvvfs-driver.js';\nimport { getDatabaseKey } from './lib/get-database-key.js';\nexport class SQLocal {\n constructor(config) {\n Object.defineProperty(this, \"config\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"clientKey\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"processor\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"isDestroyed\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: false\n });\n Object.defineProperty(this, \"bypassMutationLock\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: false\n });\n Object.defineProperty(this, \"transactionQueryKeyQueue\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: []\n });\n Object.defineProperty(this, \"userCallbacks\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: new Map()\n });\n Object.defineProperty(this, \"queriesInProgress\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: new Map()\n });\n Object.defineProperty(this, \"proxy\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"reinitChannel\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"effectsChannel\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: void 0\n });\n Object.defineProperty(this, \"processMessageEvent\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: (event) => {\n const message = event instanceof MessageEvent ? event.data : event;\n const queries = this.queriesInProgress;\n switch (message.type) {\n case 'success':\n case 'data':\n case 'buffer':\n case 'info':\n case 'error':\n if (message.queryKey && queries.has(message.queryKey)) {\n const [resolve, reject] = queries.get(message.queryKey);\n if (message.type === 'error') {\n reject(message.error);\n }\n else {\n resolve(message);\n }\n queries.delete(message.queryKey);\n }\n else if (message.type === 'error') {\n throw message.error;\n }\n break;\n case 'callback':\n const userCallback = this.userCallbacks.get(message.name);\n if (userCallback) {\n userCallback(...(message.args ?? []));\n }\n break;\n case 'event':\n this.config.onConnect?.(message.reason);\n break;\n }\n }\n });\n Object.defineProperty(this, \"createQuery\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (message) => {\n return mutationLock('shared', this.bypassMutationLock ||\n message.type === 'import' ||\n message.type === 'delete', this.config, async () => {\n if (this.isDestroyed === true) {\n throw new Error('This SQLocal client has been destroyed. You will need to initialize a new client in order to make further queries.');\n }\n const queryKey = getQueryKey();\n switch (message.type) {\n case 'import':\n this.processor.postMessage({\n ...message,\n queryKey,\n }, [message.database]);\n break;\n default:\n this.processor.postMessage({\n ...message,\n queryKey,\n });\n break;\n }\n return new Promise((resolve, reject) => {\n this.queriesInProgress.set(queryKey, [resolve, reject]);\n });\n });\n }\n });\n Object.defineProperty(this, \"broadcast\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: (message) => {\n this.reinitChannel.postMessage(message);\n }\n });\n Object.defineProperty(this, \"exec\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (sql, params, method = 'all', transactionKey) => {\n const message = await this.createQuery({\n type: 'query',\n transactionKey,\n sql,\n params,\n method,\n });\n const data = {\n rows: [],\n columns: [],\n };\n if (message.type === 'data') {\n data.rows = message.data[0]?.rows ?? [];\n data.columns = message.data[0]?.columns ?? [];\n }\n return data;\n }\n });\n Object.defineProperty(this, \"execBatch\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (statements) => {\n const message = await this.createQuery({\n type: 'batch',\n statements,\n });\n const data = new Array(statements.length).fill({\n rows: [],\n columns: [],\n });\n if (message.type === 'data') {\n message.data.forEach((result, resultIndex) => {\n data[resultIndex] = result;\n });\n }\n return data;\n }\n });\n Object.defineProperty(this, \"sql\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (queryTemplate, ...params) => {\n const statement = normalizeSql(queryTemplate, params);\n const { rows, columns } = await this.exec(statement.sql, statement.params, 'all');\n const resultRecords = convertRowsToObjects(rows, columns);\n return resultRecords;\n }\n });\n Object.defineProperty(this, \"batch\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (passStatements) => {\n const statements = passStatements(sqlTag);\n const data = await this.execBatch(statements);\n return data.map(({ rows, columns }) => {\n const resultRecords = convertRowsToObjects(rows, columns);\n return resultRecords;\n });\n }\n });\n Object.defineProperty(this, \"beginTransaction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n const transactionKey = getQueryKey();\n await this.createQuery({\n type: 'transaction',\n transactionKey,\n action: 'begin',\n });\n const query = async (passStatement) => {\n const statement = normalizeStatement(passStatement);\n if (statement.exec) {\n this.transactionQueryKeyQueue.push(transactionKey);\n return statement.exec();\n }\n const { rows, columns } = await this.exec(statement.sql, statement.params, 'all', transactionKey);\n const resultRecords = convertRowsToObjects(rows, columns);\n return resultRecords;\n };\n const sql = async (queryTemplate, ...params) => {\n const statement = normalizeSql(queryTemplate, params);\n const resultRecords = await query(statement);\n return resultRecords;\n };\n const commit = async () => {\n await this.createQuery({\n type: 'transaction',\n transactionKey,\n action: 'commit',\n });\n };\n const rollback = async () => {\n await this.createQuery({\n type: 'transaction',\n transactionKey,\n action: 'rollback',\n });\n };\n return {\n query,\n sql,\n commit,\n rollback,\n };\n }\n });\n Object.defineProperty(this, \"transaction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (transaction) => {\n return mutationLock('exclusive', false, this.config, async () => {\n let tx;\n this.bypassMutationLock = true;\n try {\n tx = await this.beginTransaction();\n const result = await transaction({\n sql: tx.sql,\n query: tx.query,\n });\n await tx.commit();\n return result;\n }\n catch (err) {\n await tx?.rollback();\n throw err;\n }\n finally {\n this.bypassMutationLock = false;\n }\n });\n }\n });\n Object.defineProperty(this, \"reactiveQuery\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: (passStatement) => {\n let value = [];\n let gotFirstValue = false;\n let isListening = false;\n let updateCount = 0;\n const statement = normalizeStatement(passStatement);\n const watchedTables = new Set();\n const subObservers = new Set();\n const errObservers = new Set();\n const runStatement = async () => {\n try {\n const updateOrder = ++updateCount;\n if (watchedTables.size === 0) {\n const usedTables = await this.sql(\"SELECT name, wr FROM tables_used(?) WHERE type = 'table'\", statement.sql);\n const readTables = new Set();\n const writtenTables = new Set();\n usedTables.forEach((table) => {\n if (typeof table.name !== 'string')\n return;\n table.wr\n ? writtenTables.add(table.name)\n : readTables.add(table.name);\n });\n if (readTables.size === 0) {\n throw new Error('The passed SQL does not read any tables.');\n }\n if (Array.from(writtenTables).some((table) => readTables.has(table))) {\n throw new Error('The passed SQL would mutate one or more of the tables that it reads. Doing this in a reactive query would create an infinite loop.');\n }\n readTables.forEach((name) => watchedTables.add(name));\n }\n const results = statement.exec\n ? await statement.exec()\n : await this.sql(statement.sql, ...statement.params);\n if (updateOrder === updateCount) {\n value = results;\n gotFirstValue = true;\n subObservers.forEach((observer) => observer(value));\n }\n }\n catch (err) {\n errObservers.forEach((observer) => {\n observer(err instanceof Error ? err : new Error(String(err)));\n });\n }\n };\n const onEffect = (message) => {\n if (message.data.tables.some((table) => watchedTables.has(table))) {\n runStatement();\n }\n };\n return {\n get value() {\n return value;\n },\n subscribe: (onData, onError) => {\n if (!this.effectsChannel) {\n throw new Error('This SQLocal instance is not configured for reactive queries. Set the \"reactive\" option to enable them.');\n }\n if (!onError) {\n onError = (err) => {\n throw err;\n };\n }\n subObservers.add(onData);\n errObservers.add(onError);\n if (!isListening) {\n this.effectsChannel.addEventListener('message', onEffect);\n isListening = true;\n runStatement();\n }\n else if (gotFirstValue) {\n onData(value);\n }\n return {\n unsubscribe: () => {\n subObservers.delete(onData);\n errObservers.delete(onError);\n if (subObservers.size !== 0)\n return;\n this.effectsChannel?.removeEventListener('message', onEffect);\n isListening = false;\n },\n };\n },\n };\n }\n });\n Object.defineProperty(this, \"createCallbackFunction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (funcName, func) => {\n await this.createQuery({\n type: 'function',\n functionName: funcName,\n functionType: 'callback',\n });\n this.userCallbacks.set(funcName, func);\n }\n });\n Object.defineProperty(this, \"createScalarFunction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (funcName, func) => {\n const key = `_sqlocal_func_${funcName}`;\n const attachFunction = () => {\n this.proxy[key] = func;\n };\n if (this.proxy === globalThis) {\n attachFunction();\n }\n await this.createQuery({\n type: 'function',\n functionName: funcName,\n functionType: 'scalar',\n });\n if (this.proxy !== globalThis) {\n attachFunction();\n }\n }\n });\n Object.defineProperty(this, \"createAggregateFunction\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (funcName, func) => {\n const key = `_sqlocal_func_${funcName}`;\n const attachFunction = () => {\n this.proxy[`${key}_step`] = func.step;\n this.proxy[`${key}_final`] = func.final;\n };\n if (this.proxy === globalThis) {\n attachFunction();\n }\n await this.createQuery({\n type: 'function',\n functionName: funcName,\n functionType: 'aggregate',\n });\n if (this.proxy !== globalThis) {\n attachFunction();\n }\n }\n });\n Object.defineProperty(this, \"getDatabaseInfo\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n const message = await this.createQuery({ type: 'getinfo' });\n if (message.type === 'info') {\n return message.info;\n }\n else {\n throw new Error('The database failed to return valid information.');\n }\n }\n });\n Object.defineProperty(this, \"getDatabaseFile\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n const message = await this.createQuery({ type: 'export' });\n if (message.type === 'buffer') {\n return new File([message.buffer], message.bufferName, {\n type: 'application/x-sqlite3',\n });\n }\n else {\n throw new Error('The database failed to export.');\n }\n }\n });\n Object.defineProperty(this, \"overwriteDatabaseFile\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (databaseFile, beforeUnlock) => {\n await mutationLock('exclusive', false, this.config, async () => {\n try {\n this.broadcast({\n type: 'close',\n clientKey: this.clientKey,\n });\n const database = await normalizeDatabaseFile(databaseFile, 'buffer');\n await this.createQuery({\n type: 'import',\n database,\n });\n if (typeof beforeUnlock === 'function') {\n this.bypassMutationLock = true;\n await beforeUnlock();\n }\n this.broadcast({\n type: 'reinit',\n clientKey: this.clientKey,\n reason: 'overwrite',\n });\n }\n finally {\n this.bypassMutationLock = false;\n }\n });\n }\n });\n Object.defineProperty(this, \"deleteDatabaseFile\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async (beforeUnlock) => {\n await mutationLock('exclusive', false, this.config, async () => {\n try {\n this.broadcast({\n type: 'close',\n clientKey: this.clientKey,\n });\n await this.createQuery({\n type: 'delete',\n });\n if (typeof beforeUnlock === 'function') {\n this.bypassMutationLock = true;\n await beforeUnlock();\n }\n this.broadcast({\n type: 'reinit',\n clientKey: this.clientKey,\n reason: 'delete',\n });\n }\n finally {\n this.bypassMutationLock = false;\n }\n });\n }\n });\n Object.defineProperty(this, \"destroy\", {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n await this.createQuery({ type: 'destroy' });\n if (typeof globalThis.Worker !== 'undefined' &&\n this.processor instanceof Worker) {\n this.processor.removeEventListener('message', this.processMessageEvent);\n this.processor.terminate();\n }\n this.queriesInProgress.clear();\n this.userCallbacks.clear();\n this.reinitChannel.close();\n this.effectsChannel?.close();\n this.isDestroyed = true;\n }\n });\n Object.defineProperty(this, _a, {\n enumerable: true,\n configurable: true,\n writable: true,\n value: () => {\n this.destroy();\n }\n });\n Object.defineProperty(this, _b, {\n enumerable: true,\n configurable: true,\n writable: true,\n value: async () => {\n await this.destroy();\n }\n });\n const clientConfig = typeof config === 'string' ? { databasePath: config } : config;\n const { onInit, onConnect, processor, ...commonConfig } = clientConfig;\n const { databasePath } = commonConfig;\n this.config = clientConfig;\n this.clientKey = getQueryKey();\n const dbKey = getDatabaseKey(databasePath, this.clientKey);\n this.reinitChannel = new BroadcastChannel(`_sqlocal_reinit_(${dbKey})`);\n if (commonConfig.reactive) {\n this.effectsChannel = new BroadcastChannel(`_sqlocal_effects_(${dbKey})`);\n }\n if (typeof processor !== 'undefined') {\n this.processor = processor;\n }\n else if (databasePath === 'local' || databasePath === ':localStorage:') {\n const driver = new SQLiteKvvfsDriver('local');\n this.processor = new SQLocalProcessor(driver);\n }\n else if (databasePath === 'session' ||\n databasePath === ':sessionStorage:') {\n const driver = new SQLiteKvvfsDriver('session');\n this.processor = new SQLocalProcessor(driver);\n }\n else if (typeof globalThis.Worker !== 'undefined' &&\n databasePath !== ':memory:') {\n this.processor = new Worker(new URL('./worker', import.meta.url), {\n type: 'module',\n });\n }\n else {\n const driver = new SQLiteMemoryDriver();\n this.processor = new SQLocalProcessor(driver);\n }\n if (this.processor instanceof SQLocalProcessor) {\n this.processor.onmessage = (message) => this.processMessageEvent(message);\n this.proxy = globalThis;\n }\n else {\n this.processor.addEventListener('message', this.processMessageEvent);\n this.proxy = coincident(this.processor);\n }\n this.processor.postMessage({\n type: 'config',\n config: {\n ...commonConfig,\n clientKey: this.clientKey,\n onInitStatements: onInit?.(sqlTag) ?? [],\n },\n });\n }\n}\n_a = Symbol.dispose, _b = Symbol.asyncDispose;\n//# sourceMappingURL=client.js.map","/**\n * Database Module\n *\n * Uses SQLocal directly with BroadcastChannel for cross-tab coordination.\n *\n * Why this approach instead of SharedWorker?\n * - SQLocal already uses its own internal worker for OPFS access\n * - Wrapping it in another SharedWorker adds complexity and causes issues\n * - BroadcastChannel provides simple cross-tab communication\n * - Each tab has its own SQLocal instance but they share the same OPFS database file\n *\n * Usage:\n * import { sql, dbReady, addLocation, getLocations } from './database.js';\n *\n * await dbReady;\n * await addLocation('Point A', -1.5, 7.5);\n * const locations = await getLocations();\n */\n\nimport { SQLocal } from 'sqlocal';\n\n// Database configuration\nconst DATABASE_PATH = 'lupmis2.db';\nconst BROADCAST_CHANNEL = 'lupmis-db-sync';\n\n// Create SQLocal instance\nconst db = new SQLocal(DATABASE_PATH);\n\n// Get the sql tagged template function\nconst { sql } = db;\n\nconsole.log('[Database] SQLocal instance created for:', DATABASE_PATH);\n\n// Export sql for direct queries\nexport { sql };\n\n// Create broadcast channel for cross-tab coordination\nconst channel = new BroadcastChannel(BROADCAST_CHANNEL);\n\n// Track if database is ready\nlet isReady = false;\nlet readyResolve;\nlet readyReject;\n\nexport const dbReady = new Promise((resolve, reject) => {\n readyResolve = resolve;\n readyReject = reject;\n});\n\n// Database change listeners\nconst changeListeners = new Set();\n\n/**\n * Subscribe to database changes (from any tab)\n * @param {Function} listener - Called with { table, action, id }\n * @returns {Function} Unsubscribe function\n */\nexport function onDatabaseChange(listener) {\n changeListeners.add(listener);\n return () => changeListeners.delete(listener);\n}\n\n// Handle messages from other tabs\nchannel.onmessage = (event) => {\n const { type, payload } = event.data;\n if (type === 'DB_CHANGE') {\n // Notify local listeners about changes from other tabs\n for (const listener of changeListeners) {\n try {\n listener(payload);\n } catch (e) {\n console.error('[Database] Change listener error:', e);\n }\n }\n }\n};\n\n/**\n * Broadcast a database change to other tabs\n */\nfunction broadcastChange(table, action, id = null) {\n channel.postMessage({\n type: 'DB_CHANGE',\n payload: { table, action, id, timestamp: Date.now() }\n });\n\n // Also notify local listeners\n for (const listener of changeListeners) {\n try {\n listener({ table, action, id, timestamp: Date.now(), local: true });\n } catch (e) {\n console.error('[Database] Change listener error:', e);\n }\n }\n}\n\n// ============================================================================\n// Database Initialization\n// ============================================================================\n\n/**\n * Initialize the database schema\n */\nexport async function initSchema() {\n try {\n console.log('[Database] Initializing schema...');\n\n // Test connection\n const testResult = await sql`SELECT sqlite_version() as version`;\n console.log('[Database] SQLite version:', testResult[0]?.version);\n\n // Create locations table\n console.log('[Database] Creating locations table...');\n await sql`\n CREATE TABLE IF NOT EXISTS locations (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n name TEXT NOT NULL,\n longitude REAL NOT NULL,\n latitude REAL NOT NULL,\n description TEXT,\n category TEXT DEFAULT 'default',\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n updated_at TEXT DEFAULT CURRENT_TIMESTAMP,\n synced INTEGER DEFAULT 0\n )\n `;\n\n // Verify table exists\n const tablesAfterLocations = await sql`SELECT name FROM sqlite_master WHERE type='table' AND name='locations'`;\n console.log('[Database] Locations table exists:', tablesAfterLocations.length > 0);\n\n // Create sync_log table\n console.log('[Database] Creating sync_log table...');\n await sql`\n CREATE TABLE IF NOT EXISTS sync_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n table_name TEXT NOT NULL,\n record_id INTEGER NOT NULL,\n action TEXT NOT NULL,\n timestamp TEXT DEFAULT CURRENT_TIMESTAMP,\n synced INTEGER DEFAULT 0\n )\n `;\n\n // Create remote_data cache table\n console.log('[Database] Creating remote_data table...');\n await sql`\n CREATE TABLE IF NOT EXISTS remote_data (\n key TEXT PRIMARY KEY,\n data TEXT NOT NULL,\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // Create collector_zones table for caching zone data\n console.log('[Database] Creating collector_zones table...');\n await sql`\n CREATE TABLE IF NOT EXISTS collector_zones (\n id INTEGER PRIMARY KEY,\n zone_name TEXT,\n geometry_wkt TEXT,\n properties TEXT,\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // Create parcels table — mirrors the server's spatial.lu_parcels structure\n // (land-use parcels). Attribute columns match the server 1:1 so the local\n // data viewer shows real fields rather than a JSON blob.\n // status — local-only flag: 'verified' = downloaded from the API,\n // 'new' = drawn locally and pending server verification.\n // fetched_at — local-only cache timestamp.\n // Migrate older databases that used the previous JSON-blob schema\n // (id, geometry_wkt, properties, status, fetched_at): if the new `upn`\n // column is missing, drop the cached table so it is recreated with the\n // lu_parcels columns. Cached server parcels re-download on next load.\n console.log('[Database] Creating parcels table...');\n try {\n const cols = await sql`PRAGMA table_info(parcels)`;\n if (cols.length > 0 && !cols.some((c) => c.name === 'upn')) {\n console.log('[Database] Migrating parcels table to lu_parcels structure (dropping old cache)...');\n await sql`DROP TABLE parcels`;\n }\n } catch (e) {\n console.warn('[Database] parcels migration check failed:', e);\n }\n await sql`\n CREATE TABLE IF NOT EXISTS parcels (\n id INTEGER PRIMARY KEY,\n upn TEXT,\n style INTEGER,\n landuse TEXT,\n zone_code TEXT,\n zone_name TEXT,\n sector TEXT,\n block TEXT,\n parcel_no TEXT,\n prop_no TEXT,\n st_name TEXT,\n prop_add TEXT,\n fac_name TEXT,\n min_height INTEGER,\n max_height INTEGER,\n eff_date TEXT,\n lp_name TEXT,\n locality TEXT,\n mmda TEXT,\n last_update TEXT,\n remarks TEXT,\n geometry_wkt TEXT,\n created_at TEXT,\n updated_at TEXT,\n districtid INTEGER,\n status TEXT DEFAULT 'verified',\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // Create building_footprints table for caching footprint data\n console.log('[Database] Creating building_footprints table...');\n await sql`\n CREATE TABLE IF NOT EXISTS building_footprints (\n id INTEGER PRIMARY KEY,\n geometry_wkt TEXT,\n properties TEXT,\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // Create osm_roads table for caching the OSM road network\n console.log('[Database] Creating osm_roads table...');\n await sql`\n CREATE TABLE IF NOT EXISTS osm_roads (\n osm_id INTEGER PRIMARY KEY,\n geometry_wkt TEXT,\n properties TEXT,\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // UPN-grid table — district sub-division grid (one cell per UPN prefix).\n // The grid is static per district, so the cache is populated once and only\n // refreshed when the user is associated with a different district. The\n // districtid column lets getLocalUpnGrid() detect that mismatch.\n console.log('[Database] Creating upn_grid table...');\n await sql`\n CREATE TABLE IF NOT EXISTS upn_grid (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n districtid INTEGER,\n upn_prefix TEXT,\n geometry_wkt TEXT,\n fetched_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n // ── GPS trails ──────────────────────────────────────────────────────\n // Recorded field-movement tracks. These are the local store for the\n // reusable GeoTracker module (src/geotracker/). `client_uuid` lets the\n // server de-duplicate re-synced trails; `satellites` is nullable because\n // the web Geolocation API does not expose it (only native builds do).\n console.log('[Database] Creating gps_trails table...');\n await sql`\n CREATE TABLE IF NOT EXISTS gps_trails (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n client_uuid TEXT UNIQUE,\n name TEXT,\n district_id TEXT,\n started_at TEXT NOT NULL,\n ended_at TEXT,\n status TEXT NOT NULL DEFAULT 'recording',\n point_count INTEGER NOT NULL DEFAULT 0,\n distance_m REAL NOT NULL DEFAULT 0,\n synced INTEGER NOT NULL DEFAULT 0,\n remote_id TEXT,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP\n )\n `;\n\n console.log('[Database] Creating gps_trail_points table...');\n await sql`\n CREATE TABLE IF NOT EXISTS gps_trail_points (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n trail_id INTEGER NOT NULL,\n seq INTEGER NOT NULL,\n longitude REAL NOT NULL,\n latitude REAL NOT NULL,\n altitude REAL,\n accuracy REAL,\n altitude_accuracy REAL,\n heading REAL,\n speed REAL,\n satellites INTEGER,\n recorded_at TEXT NOT NULL\n )\n `;\n\n // ── External imports ────────────────────────────────────────────────\n // Staging for shapefile / GeoJSON / KML imports before they are uploaded\n // to the server. See LUPMIS2_Import_Upload_Design.docx §4.\n // external_imports — one row per imported file (the dataset)\n // external_import_features — staged features (rows pending upload)\n //\n // Status state machine (aligns with the database team's staged-upload\n // model — uploads land in spatial.lu_parcels_upload_tmp first, then a\n // supervisor promotes them to the live spatial.lu_parcels via the\n // migrated flag):\n //\n // 'imported' → 'mapped' → 'uploading' → 'submitted' → 'migrated'\n // ↘ 'failed'\n //\n // 'other' is a terminal display-only state (user chose \"Other / view only\").\n // 'submitted' = row exists in upload_tmp, awaiting supervisor review.\n // 'migrated' = supervisor approved & promoted to the live table.\n console.log('[Database] Creating external_imports table...');\n await sql`\n CREATE TABLE IF NOT EXISTS external_imports (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n filename TEXT NOT NULL,\n target_type TEXT NOT NULL DEFAULT 'other',\n mapping_json TEXT,\n status TEXT NOT NULL DEFAULT 'imported',\n feature_count INTEGER NOT NULL DEFAULT 0,\n error_count INTEGER NOT NULL DEFAULT 0,\n client_import_id TEXT UNIQUE,\n created_at TEXT DEFAULT CURRENT_TIMESTAMP,\n last_uploaded_at TEXT\n )\n `;\n\n console.log('[Database] Creating external_import_features table...');\n await sql`\n CREATE TABLE IF NOT EXISTS external_import_features (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n import_id INTEGER NOT NULL REFERENCES external_imports(id) ON DELETE CASCADE,\n client_uuid TEXT UNIQUE,\n geometry_wkt TEXT NOT NULL,\n properties_json TEXT,\n upload_status TEXT NOT NULL DEFAULT 'pending',\n server_id INTEGER,\n error_message TEXT\n )\n `;\n\n // Create indexes\n await sql`CREATE INDEX IF NOT EXISTS idx_locations_category ON locations(category)`;\n await sql`CREATE INDEX IF NOT EXISTS idx_locations_synced ON locations(synced)`;\n await sql`CREATE INDEX IF NOT EXISTS idx_gps_trails_synced ON gps_trails(synced, status)`;\n await sql`CREATE INDEX IF NOT EXISTS idx_gps_trail_points_trail ON gps_trail_points(trail_id, seq)`;\n await sql`CREATE INDEX IF NOT EXISTS idx_external_imports_status ON external_imports(status)`;\n await sql`CREATE INDEX IF NOT EXISTS idx_external_import_features_import ON external_import_features(import_id, upload_status)`;\n\n // Final verification\n const allTables = await sql`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`;\n console.log('[Database] All tables:', allTables.map(t => t.name));\n\n isReady = true;\n readyResolve(true);\n console.log('[Database] ✓ Schema initialized');\n\n } catch (error) {\n console.error('[Database] ✗ Schema init failed:', error);\n readyReject(error);\n throw error;\n }\n}\n\n// ============================================================================\n// Location Operations\n// ============================================================================\n\n/**\n * Add a new location\n */\nexport async function addLocation(name, longitude, latitude, options = {}) {\n const { description = null, category = 'default' } = options;\n\n console.log('[Database] Adding location:', name, longitude, latitude, category);\n\n try {\n // Check table exists first\n const tableCheck = await sql`SELECT name FROM sqlite_master WHERE type='table' AND name='locations'`;\n console.log('[Database] Table check before insert:', tableCheck);\n\n if (tableCheck.length === 0) {\n console.error('[Database] ✗ locations table does not exist!');\n throw new Error('locations table does not exist');\n }\n\n // Insert - using explicit values\n console.log('[Database] Executing INSERT...');\n await sql`\n INSERT INTO locations (name, longitude, latitude, description, category)\n VALUES (${name}, ${longitude}, ${latitude}, ${description}, ${category})\n `;\n console.log('[Database] INSERT completed');\n\n // Get the ID\n const idResult = await sql`SELECT last_insert_rowid() as id`;\n const newId = idResult[0]?.id;\n console.log('[Database] New ID:', newId);\n\n // Verify it was actually inserted\n const verifyResult = await sql`SELECT * FROM locations WHERE id = ${newId}`;\n console.log('[Database] Verify insert:', verifyResult);\n\n if (verifyResult.length === 0) {\n console.error('[Database] ✗ Insert verification failed - row not found!');\n throw new Error('Insert verification failed');\n }\n\n // Log for sync\n await sql`\n INSERT INTO sync_log (table_name, record_id, action)\n VALUES ('locations', ${newId}, 'INSERT')\n `;\n\n // Broadcast to other tabs\n broadcastChange('locations', 'INSERT', newId);\n\n console.log('[Database] ✓ Location added:', newId);\n return { id: newId };\n\n } catch (error) {\n console.error('[Database] ✗ Failed to add location:', error);\n throw error;\n}\n}\n\n/**\n * Get all locations\n */\nexport async function getLocations(options = {}) {\n const { category = null, limit = 1000 } = options;\n\n try {\n // First check if table exists\n const tableCheck = await sql`SELECT name FROM sqlite_master WHERE type='table' AND name='locations'`;\n console.log('[Database] getLocations - table exists:', tableCheck.length > 0);\n\n if (tableCheck.length === 0) {\n console.warn('[Database] locations table does not exist yet');\n return [];\n }\n\n let results;\n if (category) {\n results = await sql`\n SELECT * FROM locations\n WHERE category = ${category}\n ORDER BY created_at DESC\n LIMIT ${limit}\n `;\n } else {\n results = await sql`\n SELECT * FROM locations\n ORDER BY created_at DESC\n LIMIT ${limit}\n `;\n}\n\n console.log('[Database] getLocations returned', results.length, 'rows');\n return results;\n\n } catch (error) {\n console.error('[Database] getLocations error:', error);\n return [];\n }\n}\n\nexport async function getLocation(id) {\n try {\n const results = await sql`SELECT * FROM locations WHERE id = ${id}`;\n return results[0] || null;\n } catch (error) {\n console.error('[Database] getLocation error:', error);\n return null;\n}\n}\n\n/**\n * Update a location\n */\nexport async function updateLocation(id, updates) {\n const { name, longitude, latitude, description, category } = updates;\n\n try {\n const location = await getLocation(id);\n if (!location) {\n throw new Error(`Location ${id} not found`);\n }\n\n await sql`\n UPDATE locations\n SET\n name = ${name ?? location.name},\n longitude = ${longitude ?? location.longitude},\n latitude = ${latitude ?? location.latitude},\n description = ${description ?? location.description},\n category = ${category ?? location.category},\n updated_at = CURRENT_TIMESTAMP,\n synced = 0\n WHERE id = ${id}\n `;\n\n // Log for sync\n await sql`\n INSERT INTO sync_log (table_name, record_id, action)\n VALUES ('locations', ${id}, 'UPDATE')\n `;\n\n // Broadcast to other tabs\n broadcastChange('locations', 'UPDATE', id);\n console.log('[Database] ✓ Location updated:', id);\n\n } catch (error) {\n console.error('[Database] ✗ updateLocation error:', error);\n throw error;\n}\n}\n\n/**\n * Delete a location\n */\nexport async function deleteLocation(id) {\n try {\n await sql`\n INSERT INTO sync_log (table_name, record_id, action)\n VALUES ('locations', ${id}, 'DELETE')\n `;\n\n await sql`DELETE FROM locations WHERE id = ${id}`;\n\n // Broadcast to other tabs\n broadcastChange('locations', 'DELETE', id);\n console.log('[Database] ✓ Location deleted:', id);\n\n } catch (error) {\n console.error('[Database] ✗ deleteLocation error:', error);\n throw error;\n}\n}\n\n/**\n * Get location count\n */\nexport async function getLocationCount() {\n try {\n const result = await sql`SELECT COUNT(*) as count FROM locations`;\n return result[0]?.count ?? 0;\n } catch (error) {\n console.error('[Database] getLocationCount error:', error);\n return 0;\n}\n}\n\n// ============================================================================\n// Sync Operations\n// ============================================================================\n\n/**\n * Get unsynced changes\n */\nexport async function getUnsyncedChanges() {\n return sql`SELECT * FROM sync_log WHERE synced = 0 ORDER BY timestamp ASC`;\n}\n\n/**\n * Mark changes as synced\n */\nexport async function markSynced(syncLogIds) {\n if (!syncLogIds.length) return;\n for (const id of syncLogIds) {\n await sql`UPDATE sync_log SET synced = 1 WHERE id = ${id}`;\n}\n}\n\n/**\n * Get locations that need syncing\n */\nexport async function getUnsyncedLocations() {\n return sql`SELECT * FROM locations WHERE synced = 0`;\n}\n\n/**\n * Mark locations as synced\n */\nexport async function markLocationsSynced(ids) {\n if (!ids.length) return;\n for (const id of ids) {\n await sql`UPDATE locations SET synced = 1 WHERE id = ${id}`;\n}\n}\n\n// ============================================================================\n// Remote Data Cache\n// ============================================================================\n\n/**\n * Save remote API data to the local cache.\n * Uses INSERT OR REPLACE so the same key is always overwritten.\n *\n * @param {string} key - Unique identifier (e.g. 'district_boundary')\n * @param {Object|Array} data - JSON-serialisable data to cache\n */\nexport async function saveRemoteData(key, data) {\n try {\n const json = JSON.stringify(data);\n await sql`\n INSERT OR REPLACE INTO remote_data (key, data, fetched_at)\n VALUES (${key}, ${json}, CURRENT_TIMESTAMP)\n `;\n console.log('[Database] ✓ Remote data cached:', key);\n } catch (error) {\n console.error('[Database] ✗ Failed to cache remote data:', key, error);\n throw error;\n }\n}\n\n/**\n * Retrieve cached remote data by key.\n *\n * @param {string} key - Unique identifier (e.g. 'district_boundary')\n * @returns {Promise} Parsed data, or null if not cached\n */\nexport async function getRemoteData(key) {\n try {\n const rows = await sql`SELECT data, fetched_at FROM remote_data WHERE key = ${key}`;\n if (rows.length === 0) return null;\n const parsed = JSON.parse(rows[0].data);\n console.log('[Database] ✓ Remote data loaded from cache:', key, '(fetched', rows[0].fetched_at + ')');\n return parsed;\n } catch (error) {\n console.error('[Database] ✗ Failed to read cached remote data:', key, error);\n return null;\n }\n}\n\n// ============================================================================\n// Collector Zones\n// ============================================================================\n\n/**\n * Save collector zones to the local table.\n * Replaces all existing rows.\n *\n * @param {Array} zones - Array of zone objects from the API\n */\nexport async function saveCollectorZones(zones) {\n try {\n await sql`DELETE FROM collector_zones`;\n for (const z of zones) {\n const props = JSON.stringify(z);\n await sql`\n INSERT INTO collector_zones (id, zone_name, geometry_wkt, properties, fetched_at)\n VALUES (${z.colzonenr || z.id}, ${z.colzonename || z.zone_name || ''}, ${z.polygon || z.boundary || ''}, ${props}, CURRENT_TIMESTAMP)\n `;\n }\n console.log('[Database] ✓ Saved', zones.length, 'collector zones');\n } catch (error) {\n console.error('[Database] ✗ Failed to save collector zones:', error);\n throw error;\n }\n}\n\n/**\n * Load all cached collector zones from the local table.\n * @returns {Promise} Array of zone objects, or null if empty\n */\nexport async function getLocalCollectorZones() {\n try {\n const rows = await sql`SELECT properties FROM collector_zones ORDER BY id`;\n if (rows.length === 0) return null;\n return rows.map(r => JSON.parse(r.properties));\n } catch (error) {\n console.error('[Database] ✗ Failed to read local collector zones:', error);\n return null;\n }\n}\n\n// ============================================================================\n// UPN Grid\n// ============================================================================\n\n/**\n * Save the UPN-grid for one district to the local table. Replaces any\n * previously cached grid (even if it was for a different district) — the\n * grid is static per district, so we only ever keep the current district's\n * cells locally.\n *\n * @param {Array} rows - Grid rows from the API\n * (each: { polygon, districtid, upn_prefix })\n * @param {number|string} districtId - The current district id\n */\nexport async function saveUpnGrid(rows, districtId) {\n try {\n await sql`BEGIN`;\n await sql`DELETE FROM upn_grid`;\n let saved = 0;\n for (const r of rows) {\n const wkt = r.polygon || r.geometry_wkt || r.geom || '';\n await sql`\n INSERT INTO upn_grid (districtid, upn_prefix, geometry_wkt, fetched_at)\n VALUES (${numOrNull(districtId)}, ${r.upn_prefix ?? null}, ${wkt}, CURRENT_TIMESTAMP)\n `;\n saved++;\n }\n await sql`COMMIT`;\n console.log('[Database] ✓ Saved', saved, 'UPN-grid cells (district', districtId, ')');\n } catch (error) {\n try { await sql`ROLLBACK`; } catch { /* no active txn */ }\n console.error('[Database] ✗ Failed to save UPN grid:', error);\n throw error;\n }\n}\n\n/**\n * Load the UPN-grid rows that belong to the given district. Returns null\n * if no cells are cached for that district — the caller should then fetch\n * from the API and call saveUpnGrid().\n *\n * @param {number|string} districtId\n * @returns {Promise}\n */\nexport async function getLocalUpnGrid(districtId) {\n try {\n const rows = await sql`\n SELECT id, districtid, upn_prefix, geometry_wkt\n FROM upn_grid\n WHERE districtid = ${numOrNull(districtId)}\n ORDER BY id\n `;\n if (rows.length === 0) return null;\n return rows;\n } catch (error) {\n console.error('[Database] ✗ Failed to read UPN grid:', error);\n return null;\n }\n}\n\n// ============================================================================\n// External imports (staging for shapefile / GeoJSON / KML uploads)\n// See LUPMIS2_Import_Upload_Design.docx §3 & §4.\n// ============================================================================\n\n/** Tiny RFC-4122-ish UUIDv4 (uses crypto.randomUUID when available). */\nfunction uuidv4() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);\n });\n}\n\n/**\n * Create a new staging row for an imported dataset. Returns the import_id.\n *\n * @param {Object} opts\n * @param {string} opts.filename — original filename\n * @param {string} [opts.targetType] — initial target ('other' by default)\n * @param {number} [opts.featureCount] — number of features being staged\n * @returns {Promise<{ id: number, client_import_id: string }>}\n */\nexport async function createExternalImport(opts) {\n const { filename, targetType = 'other', featureCount = 0 } = opts;\n const clientImportId = uuidv4();\n try {\n await sql`\n INSERT INTO external_imports\n (filename, target_type, status, feature_count, client_import_id)\n VALUES\n (${filename}, ${targetType},\n ${targetType === 'other' ? 'other' : 'imported'},\n ${featureCount}, ${clientImportId})\n `;\n const idRow = await sql`SELECT last_insert_rowid() AS id`;\n const id = idRow[0]?.id;\n broadcastChange('external_imports', 'INSERT', id);\n return { id, client_import_id: clientImportId };\n } catch (error) {\n console.error('[Database] ✗ Failed to create external import:', error);\n throw error;\n }\n}\n\n/**\n * Bulk-insert staging features for an import. Wraps the inserts in a single\n * transaction (the upload payload is typically dozens to thousands of rows).\n *\n * @param {number} importId\n * @param {Array<{ geometry_wkt: string, properties: Object }>} features\n */\nexport async function addExternalImportFeatures(importId, features) {\n if (!Array.isArray(features) || features.length === 0) return 0;\n try {\n await sql`BEGIN`;\n let inserted = 0;\n for (const f of features) {\n const wkt = f.geometry_wkt || '';\n if (!wkt) continue;\n const propsJson = JSON.stringify(f.properties ?? {});\n const cuuid = f.client_uuid || uuidv4();\n await sql`\n INSERT INTO external_import_features\n (import_id, client_uuid, geometry_wkt, properties_json, upload_status)\n VALUES\n (${importId}, ${cuuid}, ${wkt}, ${propsJson}, 'pending')\n `;\n inserted++;\n }\n await sql`COMMIT`;\n broadcastChange('external_import_features', 'INSERT', importId);\n return inserted;\n } catch (error) {\n try { await sql`ROLLBACK`; } catch { /* no active txn */ }\n console.error('[Database] ✗ Failed to add import features:', error);\n throw error;\n }\n}\n\n/**\n * Update target type + mapping + status for a staged import. Pass any\n * subset of fields. Useful targets:\n * updateExternalImport(id, { targetType: 'parcels', mapping: {...},\n * status: 'mapped' })\n */\nexport async function updateExternalImport(importId, patch = {}) {\n try {\n const cur = await sql`SELECT * FROM external_imports WHERE id = ${importId}`;\n if (cur.length === 0) throw new Error(`Import ${importId} not found`);\n const row = cur[0];\n\n const targetType = patch.targetType ?? row.target_type;\n const mappingJson = patch.mapping !== undefined\n ? (patch.mapping ? JSON.stringify(patch.mapping) : null)\n : row.mapping_json;\n const status = patch.status ?? row.status;\n const errorCount = patch.errorCount ?? row.error_count;\n const lastUploadedAt = patch.lastUploadedAt ?? row.last_uploaded_at;\n\n await sql`\n UPDATE external_imports SET\n target_type = ${targetType},\n mapping_json = ${mappingJson},\n status = ${status},\n error_count = ${errorCount},\n last_uploaded_at = ${lastUploadedAt}\n WHERE id = ${importId}\n `;\n broadcastChange('external_imports', 'UPDATE', importId);\n } catch (error) {\n console.error('[Database] ✗ Failed to update external import:', error);\n throw error;\n }\n}\n\n/** Get an external_imports row by id (parsed mapping_json). */\nexport async function getExternalImport(importId) {\n try {\n const rows = await sql`SELECT * FROM external_imports WHERE id = ${importId}`;\n if (rows.length === 0) return null;\n const row = rows[0];\n return { ...row, mapping: row.mapping_json ? JSON.parse(row.mapping_json) : null };\n } catch (error) {\n console.error('[Database] ✗ Failed to read external import:', error);\n return null;\n }\n}\n\n/** List every external import, newest first. */\nexport async function listExternalImports() {\n try {\n return await sql`SELECT * FROM external_imports ORDER BY id DESC`;\n } catch (error) {\n console.error('[Database] ✗ Failed to list external imports:', error);\n return [];\n }\n}\n\n/** Get the staging features for an import (parsed properties_json). */\nexport async function getExternalImportFeatures(importId) {\n try {\n const rows = await sql`\n SELECT id, client_uuid, geometry_wkt, properties_json,\n upload_status, server_id, error_message\n FROM external_import_features\n WHERE import_id = ${importId}\n ORDER BY id\n `;\n return rows.map((r) => ({\n ...r,\n properties: r.properties_json ? JSON.parse(r.properties_json) : {},\n }));\n } catch (error) {\n console.error('[Database] ✗ Failed to read import features:', error);\n return [];\n }\n}\n\n/**\n * Bulk-rewrite the properties_json of every staged feature for an import.\n * Used after the user confirms a field-mapping: the caller passes a function\n * that receives each row's parsed properties and returns the remapped ones.\n * All updates run in a single transaction.\n *\n * @param {number} importId\n * @param {(props: Object) => Object} remap\n */\nexport async function remapImportedFeatureProperties(importId, remap) {\n try {\n const rows = await sql`\n SELECT id, properties_json\n FROM external_import_features\n WHERE import_id = ${importId}\n `;\n if (rows.length === 0) return 0;\n\n await sql`BEGIN`;\n let n = 0;\n for (const r of rows) {\n const before = r.properties_json ? JSON.parse(r.properties_json) : {};\n const after = remap(before) ?? {};\n await sql`\n UPDATE external_import_features\n SET properties_json = ${JSON.stringify(after)}\n WHERE id = ${r.id}\n `;\n n++;\n }\n await sql`COMMIT`;\n broadcastChange('external_import_features', 'UPDATE', importId);\n return n;\n } catch (error) {\n try { await sql`ROLLBACK`; } catch { /* */ }\n console.error('[Database] ✗ Failed to remap import features:', error);\n throw error;\n }\n}\n\n/**\n * Update a single staged feature's geometry (and properties, optionally).\n * Used when the user modifies an imported feature on the map (the EditBar\n * Modify interaction fires `modifyend`) — we write the new WKT back so the\n * next upload re-sends the corrected geometry.\n *\n * @param {string} clientUuid - the per-feature idempotency key on the OL feature\n * @param {string} geometryWkt - new geometry in EPSG:4326 WKT\n * @param {Object} [properties] - optional new properties (if omitted, leave as-is)\n */\nexport async function updateExternalImportFeatureGeometry(clientUuid, geometryWkt, properties) {\n try {\n if (properties !== undefined) {\n const propsJson = JSON.stringify(properties);\n await sql`\n UPDATE external_import_features\n SET geometry_wkt = ${geometryWkt}, properties_json = ${propsJson}\n WHERE client_uuid = ${clientUuid}\n `;\n } else {\n await sql`\n UPDATE external_import_features\n SET geometry_wkt = ${geometryWkt}\n WHERE client_uuid = ${clientUuid}\n `;\n }\n broadcastChange('external_import_features', 'UPDATE', clientUuid);\n } catch (error) {\n console.error('[Database] ✗ Failed to update import feature geometry:', error);\n throw error;\n }\n}\n\n/**\n * Delete a single staged feature by client_uuid, and decrement the parent\n * import's feature_count. Used when the user deletes an imported feature on\n * the map (EditBar Delete).\n *\n * @param {string} clientUuid\n */\nexport async function deleteExternalImportFeature(clientUuid) {\n try {\n // Look up parent import_id first so we can decrement its count atomically.\n const row = await sql`\n SELECT import_id FROM external_import_features WHERE client_uuid = ${clientUuid}\n `;\n if (row.length === 0) return; // already gone\n const importId = row[0].import_id;\n\n await sql`BEGIN`;\n try {\n await sql`DELETE FROM external_import_features WHERE client_uuid = ${clientUuid}`;\n await sql`\n UPDATE external_imports\n SET feature_count = MAX(0, feature_count - 1)\n WHERE id = ${importId}\n `;\n await sql`COMMIT`;\n } catch (e) {\n try { await sql`ROLLBACK`; } catch { /* */ }\n throw e;\n }\n broadcastChange('external_import_features', 'DELETE', clientUuid);\n broadcastChange('external_imports', 'UPDATE', importId);\n } catch (error) {\n console.error('[Database] ✗ Failed to delete import feature:', error);\n throw error;\n }\n}\n\n/** Delete a staged import (and its features via CASCADE). */\nexport async function deleteExternalImport(importId) {\n try {\n await sql`DELETE FROM external_imports WHERE id = ${importId}`;\n broadcastChange('external_imports', 'DELETE', importId);\n } catch (error) {\n console.error('[Database] ✗ Failed to delete external import:', error);\n throw error;\n }\n}\n\n// ============================================================================\n// Parcels\n// ============================================================================\n\n/** Coerce a value for an INTEGER column; '' / null / undefined / NaN → null. */\nfunction numOrNull(v) {\n if (v === '' || v === null || v === undefined) return null;\n const n = Number(v);\n return Number.isNaN(n) ? null : n;\n}\n\n/**\n * Save parcels to the local table (mirrors spatial.lu_parcels).\n * Replaces all server-cached rows. Each API field maps to its own column.\n * Geometry is taken from the server `geom` field (WKT, EPSG:4326).\n *\n * @param {Array} parcels - Array of parcel objects from the API\n */\nexport async function saveParcels(parcels) {\n try {\n // Wrap the bulk load in a single transaction — with ~25k parcels, per-row\n // auto-commits on OPFS would be prohibitively slow.\n await sql`BEGIN`;\n await sql`DELETE FROM parcels`;\n let saved = 0;\n for (const p of parcels) {\n const id = p.id ?? p.parcelid ?? p.parcel_id ?? null;\n if (id == null) continue; // skip rows without a usable ID\n // Geometry must be a WKT *string* for the geometry_wkt TEXT column.\n // The API sends WKT in `boundary` and a GeoJSON *object* in `geom`, so\n // prefer the string fields and only accept `geom` when it is a string.\n const wkt = p.boundary || p.geometry_wkt || p.polygon || p.wkt\n || (typeof p.geom === 'string' ? p.geom : '');\n await sql`\n INSERT OR REPLACE INTO parcels (\n id, upn, style, landuse, zone_code, zone_name, sector, block, parcel_no,\n prop_no, st_name, prop_add, fac_name, min_height, max_height, eff_date,\n lp_name, locality, mmda, last_update, remarks, geometry_wkt,\n created_at, updated_at, districtid, status, fetched_at\n ) VALUES (\n ${id}, ${p.upn ?? null}, ${numOrNull(p.style)}, ${p.landuse ?? null},\n ${p.zone_code ?? null}, ${p.zone_name ?? null}, ${p.sector ?? null},\n ${p.block ?? null}, ${p.parcel_no ?? null}, ${p.prop_no ?? null},\n ${p.st_name ?? null}, ${p.prop_add ?? null}, ${p.fac_name ?? null},\n ${numOrNull(p.min_height)}, ${numOrNull(p.max_height)}, ${p.eff_date ?? null},\n ${p.lp_name ?? null}, ${p.locality ?? null}, ${p.mmda ?? null},\n ${p.last_update ?? null}, ${p.remarks ?? null}, ${wkt},\n ${p.created_at ?? null}, ${p.updated_at ?? null}, ${numOrNull(p.districtid)},\n 'verified', CURRENT_TIMESTAMP\n )\n `;\n saved++;\n }\n await sql`COMMIT`;\n console.log('[Database] ✓ Saved', saved, 'parcels (from', parcels.length, 'rows,', parcels.length - saved, 'skipped/replaced)');\n } catch (error) {\n try { await sql`ROLLBACK`; } catch { /* no active txn */ }\n console.error('[Database] ✗ Failed to save parcels:', error);\n throw error;\n }\n}\n\n/**\n * Load all cached parcels from the local table.\n * Each row is a plain object keyed by column name (incl. geometry_wkt).\n * @returns {Promise} Array of parcel rows, or null if empty\n */\nexport async function getLocalParcels() {\n try {\n const rows = await sql`SELECT * FROM parcels ORDER BY id`;\n if (rows.length === 0) return null;\n return rows;\n } catch (error) {\n console.error('[Database] ✗ Failed to read local parcels:', error);\n return null;\n }\n}\n\n/**\n * Update a single parcel's attribute columns in the local table.\n * Geometry, id, created_at and status are left unchanged; updated_at is bumped.\n *\n * @param {number|string} parcelId - The parcel id\n * @param {Object} p - Updated attribute values (keys = lu_parcels columns)\n */\nexport async function updateParcel(parcelId, p) {\n try {\n await sql`\n UPDATE parcels SET\n upn = ${p.upn ?? null},\n style = ${numOrNull(p.style)},\n landuse = ${p.landuse ?? null},\n zone_code = ${p.zone_code ?? null},\n zone_name = ${p.zone_name ?? null},\n sector = ${p.sector ?? null},\n block = ${p.block ?? null},\n parcel_no = ${p.parcel_no ?? null},\n prop_no = ${p.prop_no ?? null},\n st_name = ${p.st_name ?? null},\n prop_add = ${p.prop_add ?? null},\n fac_name = ${p.fac_name ?? null},\n min_height = ${numOrNull(p.min_height)},\n max_height = ${numOrNull(p.max_height)},\n eff_date = ${p.eff_date ?? null},\n lp_name = ${p.lp_name ?? null},\n locality = ${p.locality ?? null},\n mmda = ${p.mmda ?? null},\n last_update = ${p.last_update ?? null},\n remarks = ${p.remarks ?? null},\n districtid = ${numOrNull(p.districtid)},\n updated_at = CURRENT_TIMESTAMP\n WHERE id = ${parcelId}\n `;\n console.log('[Database] ✓ Parcel updated:', parcelId);\n broadcastChange('parcels', 'UPDATE', parcelId);\n } catch (error) {\n console.error('[Database] ✗ Failed to update parcel:', parcelId, error);\n throw error;\n }\n}\n\n/**\n * Insert a newly drawn parcel into the local table.\n * The parcel is tagged with status='new' to indicate it needs verification.\n *\n * @param {string} geometryWkt - WKT geometry string (EPSG:4326)\n * @param {Object} p - Attribute values from the form (keys = lu_parcels columns)\n * @returns {Promise<{id: number}>} The new row id\n */\nexport async function insertNewParcel(geometryWkt, p = {}) {\n try {\n await sql`\n INSERT INTO parcels (\n id, upn, style, landuse, zone_code, zone_name, sector, block, parcel_no,\n prop_no, st_name, prop_add, fac_name, min_height, max_height, eff_date,\n lp_name, locality, mmda, last_update, remarks, geometry_wkt,\n created_at, updated_at, districtid, status, fetched_at\n ) VALUES (\n NULL, ${p.upn ?? null}, ${numOrNull(p.style)}, ${p.landuse ?? null},\n ${p.zone_code ?? null}, ${p.zone_name ?? null}, ${p.sector ?? null},\n ${p.block ?? null}, ${p.parcel_no ?? null}, ${p.prop_no ?? null},\n ${p.st_name ?? null}, ${p.prop_add ?? null}, ${p.fac_name ?? null},\n ${numOrNull(p.min_height)}, ${numOrNull(p.max_height)}, ${p.eff_date ?? null},\n ${p.lp_name ?? null}, ${p.locality ?? null}, ${p.mmda ?? null},\n ${p.last_update ?? null}, ${p.remarks ?? null}, ${geometryWkt},\n CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, ${numOrNull(p.districtid)},\n 'new', CURRENT_TIMESTAMP\n )\n `;\n const idResult = await sql`SELECT last_insert_rowid() as id`;\n const newId = idResult[0]?.id;\n console.log('[Database] ✓ New parcel inserted:', newId, '(status: new)');\n broadcastChange('parcels', 'INSERT', newId);\n return { id: newId };\n } catch (error) {\n console.error('[Database] ✗ Failed to insert new parcel:', error);\n throw error;\n }\n}\n\n// ============================================================================\n// Building Footprints\n// ============================================================================\n\n/**\n * Save building footprints to the local table.\n * Replaces all existing rows.\n *\n * @param {Array} footprints - Array of footprint objects from the API\n */\nexport async function saveBuildingFootprints(footprints) {\n try {\n // Log first entry's keys and value types to help debug field names\n if (footprints.length > 0) {\n const first = footprints[0];\n const types = {};\n for (const [k, v] of Object.entries(first)) {\n types[k] = v === null ? 'null' : typeof v;\n }\n console.log('[Database] First footprint field types:', types);\n }\n\n await sql`DELETE FROM building_footprints`;\n for (const f of footprints) {\n const props = JSON.stringify(f);\n\n // Geometry may arrive as a string (WKT) or an object (GeoJSON) —\n // coerce to a string so SQLocal can bind it.\n let rawWkt = f.polygon || f.boundary || f.geom || f.wkt || f.footprint || '';\n const wkt = typeof rawWkt === 'object' ? JSON.stringify(rawWkt) : String(rawWkt);\n\n // ID must be a primitive (number or null)\n let rawId = f.id || f.footprint_id || f.building_id || null;\n const id = (rawId !== null && typeof rawId === 'object') ? null : rawId;\n\n await sql`\n INSERT INTO building_footprints (id, geometry_wkt, properties, fetched_at)\n VALUES (${id}, ${wkt}, ${props}, CURRENT_TIMESTAMP)\n `;\n }\n console.log('[Database] ✓ Saved', footprints.length, 'building footprints');\n } catch (error) {\n console.error('[Database] ✗ Failed to save building footprints:', error);\n throw error;\n }\n}\n\n/**\n * Load all cached building footprints from the local table.\n * @returns {Promise} Array of footprint objects, or null if empty\n */\nexport async function getLocalBuildingFootprints() {\n try {\n const rows = await sql`SELECT properties FROM building_footprints ORDER BY id`;\n if (rows.length === 0) return null;\n return rows.map(r => JSON.parse(r.properties));\n } catch (error) {\n console.error('[Database] ✗ Failed to read local building footprints:', error);\n return null;\n }\n}\n\n/**\n * Save OSM roads to the local SQLite table.\n * Replaces all existing rows.\n *\n * @param {Array} roads - Array of road objects from the API\n */\nexport async function saveOSMRoads(roads) {\n try {\n if (roads.length > 0) {\n const first = roads[0];\n const types = {};\n for (const [k, v] of Object.entries(first)) {\n types[k] = v === null ? 'null' : typeof v;\n }\n console.log('[Database] First road field types:', types);\n }\n\n await sql`DELETE FROM osm_roads`;\n for (const r of roads) {\n const props = JSON.stringify(r);\n\n // Geometry — may arrive as WKT string or GeoJSON object\n let rawWkt = r.geom || r.geometry || r.wkt || r.road || r.line || '';\n const wkt = typeof rawWkt === 'object' ? JSON.stringify(rawWkt) : String(rawWkt);\n\n // osm_id must be a primitive — fall back to null if missing or malformed\n let rawId = r.osm_id ?? r.osmid ?? r.id ?? null;\n const osmId = (rawId !== null && typeof rawId === 'object') ? null : rawId;\n\n await sql`\n INSERT OR REPLACE INTO osm_roads (osm_id, geometry_wkt, properties, fetched_at)\n VALUES (${osmId}, ${wkt}, ${props}, CURRENT_TIMESTAMP)\n `;\n }\n console.log('[Database] ✓ Saved', roads.length, 'OSM roads');\n } catch (error) {\n console.error('[Database] ✗ Failed to save OSM roads:', error);\n throw error;\n }\n}\n\n/**\n * Load all cached OSM roads from the local table.\n * @returns {Promise} Array of road objects, or null if empty\n */\nexport async function getLocalOSMRoads() {\n try {\n const rows = await sql`SELECT properties FROM osm_roads ORDER BY osm_id`;\n if (rows.length === 0) return null;\n return rows.map(r => JSON.parse(r.properties));\n } catch (error) {\n console.error('[Database] ✗ Failed to read local OSM roads:', error);\n return null;\n }\n}\n\n// ============================================================================\n// Export / Import\n// ============================================================================\n\n/**\n * Export database for backup\n */\nexport async function exportDatabase() {\n return db.getDatabaseFile();\n}\n\n/**\n * Import database from backup\n */\nexport async function importDatabase(data) {\n await db.overwriteDatabaseFile(data);\n broadcastChange('*', 'IMPORT', null);\n}\n\n/**\n * Download database as file\n */\nexport async function downloadDatabase(filename = 'lupmis-backup.sqlite3') {\n const data = await exportDatabase();\n const blob = new Blob([data], { type: 'application/x-sqlite3' });\n const url = URL.createObjectURL(blob);\n\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.click();\n\n URL.revokeObjectURL(url);\n}\n\n// Export to GeoJSON\nexport async function exportToGeoJSON() {\n const locations = await getLocations();\n\n return {\n type: 'FeatureCollection',\n features: locations.map((loc) => ({\n type: 'Feature',\n properties: {\n id: loc.id,\n name: loc.name,\n category: loc.category,\n notes: loc.notes,\n created_at: loc.created_at,\n },\n geometry: {\n type: 'Point',\n coordinates: [loc.lon, loc.lat],\n },\n })),\n };\n}\n\n// ============================================================================\n// Utility & Debug\n// ============================================================================\n\n/**\n * Get database status\n */\nexport async function getDatabaseStatus() {\n try {\n const tables = await sql`\n SELECT name FROM sqlite_master\n WHERE type='table' AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `;\n\n const locationCount = await getLocationCount();\n\n return {\n ready: isReady,\n databasePath: DATABASE_PATH,\n tables: tables.map(t => t.name),\n locationCount\n };\n } catch (error) {\n return {\n ready: false,\n error: error.message\n };\n}\n}\n\n// ============================================================================\n// Cached-Layer Management\n// ============================================================================\n\n/**\n * Tables that hold data fetched from the server.\n *\n * Clearing these is safe — the corresponding loaders (loadParcels,\n * loadBuildingFootprints, loadOSMRoads, loadCollectorZones, …) will re-fetch\n * the data from the API on the next app start.\n *\n * NOT included: user-created tables (`locations`, `pending_changes`) — those\n * hold local work that must not be auto-deleted.\n */\nexport const CACHED_LAYER_TABLES = Object.freeze([\n 'parcels',\n 'building_footprints',\n 'osm_roads',\n 'collector_zones',\n 'upn_grid',\n 'remote_data',\n]);\n\n/**\n * Check whether a table name is in the cleared-layer allow-list.\n * @param {string} tableName\n * @returns {boolean}\n */\nexport function isCachedLayerTable(tableName) {\n return CACHED_LAYER_TABLES.includes(tableName);\n}\n\n/**\n * Delete all rows from a single cached-layer table.\n * Rejects unknown table names so this can't be abused to drop user data.\n *\n * @param {string} tableName - One of CACHED_LAYER_TABLES\n * @returns {Promise} Number of rows that were in the table before deletion\n */\nexport async function clearTable(tableName) {\n if (!isCachedLayerTable(tableName)) {\n throw new Error(`Refusing to clear \"${tableName}\" — not a known cached-layer table`);\n }\n\n const before = await sql(`SELECT COUNT(*) AS n FROM \"${tableName}\"`);\n const count = before[0]?.n ?? 0;\n\n await sql(`DELETE FROM \"${tableName}\"`);\n console.log(`[Database] ✓ Cleared \"${tableName}\" (${count} rows)`);\n broadcastChange(tableName, 'CLEAR', null);\n return count;\n}\n\n/**\n * Clear every cached-layer table (whatever exists in this database).\n * Tables that don't exist yet are skipped silently.\n *\n * @returns {Promise<{ table: string, count: number }[]>} per-table report\n */\nexport async function clearAllCachedLayers() {\n const existing = await sql`\n SELECT name FROM sqlite_master\n WHERE type='table' AND name IN (\n 'parcels', 'building_footprints', 'osm_roads', 'collector_zones', 'upn_grid', 'remote_data'\n )\n `;\n const existingNames = new Set(existing.map((r) => r.name));\n\n const results = [];\n for (const tableName of CACHED_LAYER_TABLES) {\n if (!existingNames.has(tableName)) continue;\n try {\n const count = await clearTable(tableName);\n results.push({ table: tableName, count });\n } catch (err) {\n console.error(`[Database] Failed to clear ${tableName}:`, err);\n results.push({ table: tableName, count: 0, error: err.message });\n }\n }\n\n const total = results.reduce((s, r) => s + r.count, 0);\n console.log(`[Database] ✓ Cleared all cached layers: ${total} rows across ${results.length} tables`);\n return results;\n}\n\n/**\n * Get a list of all tables with their row counts.\n * @returns {Promise>}\n */\nexport async function getTableStats() {\n const tables = await sql`\n SELECT name FROM sqlite_master\n WHERE type='table' AND name NOT LIKE 'sqlite_%'\n ORDER BY name\n `;\n\n if (tables.length === 0) return [];\n\n // Build a UNION ALL query — table names come from sqlite_master so safe to embed.\n // sql() accepts a plain string as first argument (not only tagged template).\n const query = tables\n .map(t => `SELECT '${t.name}' AS name, COUNT(*) AS count FROM \"${t.name}\"`)\n .join(' UNION ALL ');\n\n return sql(query);\n}\n\n/**\n * Get all rows from a given table (max 200 rows for safety).\n * Table name is validated against sqlite_master before querying.\n * @param {string} tableName - Name of the table to read\n * @param {number} [limit=200] - Max rows to return\n * @returns {Promise<{columns: string[], rows: Object[]}>}\n */\nexport async function getTableContent(tableName, limit = 200) {\n // Validate that the table actually exists (prevent injection)\n const valid = await sql`\n SELECT name FROM sqlite_master\n WHERE type='table' AND name = ${tableName}\n `;\n if (valid.length === 0) {\n throw new Error(`Table \"${tableName}\" does not exist`);\n }\n\n const rows = await sql(`SELECT * FROM \"${tableName}\" LIMIT ${limit}`);\n\n // Extract column names from the first row (or return empty)\n const columns = rows.length > 0 ? Object.keys(rows[0]) : [];\n\n return { columns, rows };\n}\n\n// Debug function - call from console to test\nexport async function testDatabase() {\n console.log('=== DATABASE TEST ===');\n\n try {\n // 1. Check connection\n const version = await sql`SELECT sqlite_version() as v`;\n console.log('1. SQLite version:', version[0].v);\n\n // 2. Check tables\n const tables = await sql`SELECT name FROM sqlite_master WHERE type='table'`;\n console.log('2. Tables:', tables.map(t => t.name));\n\n // 3. Try to insert a test row\n console.log('3. Inserting test row...');\n await sql`INSERT INTO locations (name, longitude, latitude, category) VALUES ('TEST', -1.0, 7.0, 'test')`;\n\n // 4. Read it back\n const rows = await sql`SELECT * FROM locations WHERE name = 'TEST'`;\n console.log('4. Test row:', rows);\n\n // 5. Count all rows\n const count = await sql`SELECT COUNT(*) as c FROM locations`;\n console.log('5. Total rows:', count[0].c);\n\n // 6. Delete test row\n await sql`DELETE FROM locations WHERE name = 'TEST'`;\n console.log('6. Test row deleted');\n\n console.log('=== TEST PASSED ===');\n return true;\n } catch (error) {\n console.error('=== TEST FAILED ===', error);\n return false;\n}\n}\n\n// Expose to window for debugging\nif (typeof window !== 'undefined') {\n window.testDatabase = testDatabase;\n window.dbStatus = getDatabaseStatus;\n}\n\nexport async function closeDatabase() {\n channel.close();\n if (db.destroy) {\n await db.destroy();\n}\n}\n\n// ============================================================================\n// GPS Trails (storage adapter for the reusable GeoTracker module)\n// ============================================================================\n//\n// These functions implement the GeoTracker \"storage adapter\" contract using\n// SQLocal. They are intentionally generic (no map / UI coupling) so the same\n// schema + helpers can be lifted into another app alongside src/geotracker/.\n\n/**\n * Create a new trail row (status='recording') and return its local id.\n * @param {object} meta { uuid, name, startedAt, districtId }\n * @returns {Promise} local trail id\n */\nexport async function createGpsTrail(meta) {\n const { uuid, name = null, startedAt, districtId = null } = meta;\n await sql`\n INSERT INTO gps_trails (client_uuid, name, district_id, started_at, status)\n VALUES (${uuid}, ${name}, ${districtId}, ${startedAt}, 'recording')\n `;\n const idResult = await sql`SELECT last_insert_rowid() as id`;\n const id = idResult[0]?.id;\n broadcastChange('gps_trails', 'insert', id);\n return id;\n}\n\n/**\n * Append one recorded point to a trail.\n * @param {number} trailId\n * @param {object} point normalized fix + { seq }\n */\nexport async function addGpsTrailPoint(trailId, point) {\n const {\n seq, lon, lat,\n altitude = null, accuracy = null, altitudeAccuracy = null,\n heading = null, speed = null, satellites = null, timestamp,\n } = point;\n const recordedAt = typeof timestamp === 'number' ? new Date(timestamp).toISOString() : (timestamp || new Date().toISOString());\n await sql`\n INSERT INTO gps_trail_points\n (trail_id, seq, longitude, latitude, altitude, accuracy, altitude_accuracy, heading, speed, satellites, recorded_at)\n VALUES\n (${trailId}, ${seq}, ${lon}, ${lat}, ${altitude}, ${accuracy}, ${altitudeAccuracy}, ${heading}, ${speed}, ${satellites}, ${recordedAt})\n `;\n}\n\n/**\n * Finalise a trail: mark completed and store the summary.\n * @param {number} trailId\n * @param {object} summary { endedAt, pointCount, distanceM }\n */\nexport async function finishGpsTrail(trailId, summary) {\n const { endedAt, pointCount = 0, distanceM = 0 } = summary;\n await sql`\n UPDATE gps_trails\n SET ended_at = ${endedAt}, point_count = ${pointCount}, distance_m = ${distanceM}, status = 'completed'\n WHERE id = ${trailId}\n `;\n broadcastChange('gps_trails', 'update', trailId);\n}\n\n/**\n * Trails that are completed but not yet pushed to the server.\n * @returns {Promise}\n */\nexport async function getUnsyncedGpsTrails() {\n return sql`SELECT * FROM gps_trails WHERE synced = 0 AND status = 'completed' ORDER BY started_at ASC`;\n}\n\n/**\n * All points of a trail, in recorded order.\n * @param {number} trailId\n * @returns {Promise}\n */\nexport async function getGpsTrailPoints(trailId) {\n return sql`SELECT * FROM gps_trail_points WHERE trail_id = ${trailId} ORDER BY seq ASC`;\n}\n\n/**\n * Mark a trail as synced and record the server-assigned id.\n * @param {number} trailId\n * @param {string|number|null} remoteId\n */\nexport async function markGpsTrailSynced(trailId, remoteId = null) {\n await sql`UPDATE gps_trails SET synced = 1, remote_id = ${remoteId} WHERE id = ${trailId}`;\n broadcastChange('gps_trails', 'update', trailId);\n}\n\n/**\n * List trails (most recent first) for a history/list UI.\n * @returns {Promise}\n */\nexport async function getGpsTrails() {\n return sql`SELECT * FROM gps_trails ORDER BY started_at DESC`;\n}\n\n/**\n * Delete a trail and all its points.\n * @param {number} trailId\n */\nexport async function deleteGpsTrail(trailId) {\n await sql`DELETE FROM gps_trail_points WHERE trail_id = ${trailId}`;\n await sql`DELETE FROM gps_trails WHERE id = ${trailId}`;\n broadcastChange('gps_trails', 'delete', trailId);\n}\n\nexport default {\n sql,\n dbReady,\n initSchema,\n addLocation,\n getLocations,\n getLocation,\n updateLocation,\n deleteLocation,\n getLocationCount,\n getUnsyncedChanges,\n getUnsyncedLocations,\n markSynced,\n markLocationsSynced,\n saveRemoteData,\n getRemoteData,\n saveCollectorZones,\n getLocalCollectorZones,\n saveUpnGrid,\n getLocalUpnGrid,\n createExternalImport,\n addExternalImportFeatures,\n updateExternalImport,\n getExternalImport,\n listExternalImports,\n getExternalImportFeatures,\n remapImportedFeatureProperties,\n updateExternalImportFeatureGeometry,\n deleteExternalImportFeature,\n deleteExternalImport,\n saveParcels,\n getLocalParcels,\n updateParcel,\n insertNewParcel,\n saveBuildingFootprints,\n getLocalBuildingFootprints,\n saveOSMRoads,\n getLocalOSMRoads,\n createGpsTrail,\n addGpsTrailPoint,\n finishGpsTrail,\n getUnsyncedGpsTrails,\n getGpsTrailPoints,\n markGpsTrailSynced,\n getGpsTrails,\n deleteGpsTrail,\n CACHED_LAYER_TABLES,\n isCachedLayerTable,\n clearTable,\n clearAllCachedLayers,\n exportDatabase,\n exportToGeoJSON,\n importDatabase,\n downloadDatabase,\n getDatabaseStatus,\n getTableStats,\n getTableContent,\n testDatabase,\n onDatabaseChange,\n closeDatabase\n};\n","/**\n * Measurement unit formatting — Metric / Imperial.\n *\n * The active system is persisted in localStorage('measurement-system').\n * Every formatter reads the current setting so the UI updates immediately\n * after the user flips the toggle.\n *\n * All input values are in metres (length) or square metres (area).\n */\n\n// ── Conversion constants ────────────────────────────────────────────────────\nconst M_TO_FT = 3.28084;\nconst M_TO_MI = 0.000621371;\nconst SQM_TO_SQFT = 10.7639;\nconst SQM_TO_ACRE = 0.000247105;\nconst SQM_TO_SQMI = 3.861e-7;\n\n// ── System accessor ─────────────────────────────────────────────────────────\n\n/** @returns {'metric'|'imperial'} */\nexport function getSystem() {\n return localStorage.getItem('measurement-system') || 'metric';\n}\n\n// ── Length / distance ───────────────────────────────────────────────────────\n\n/**\n * Format a length value (in metres) for display.\n * Metric: m / km\n * Imperial: ft / mi\n */\nexport function formatLength(metres) {\n if (getSystem() === 'imperial') {\n const ft = metres * M_TO_FT;\n if (ft >= 5280) {\n return (Math.round(metres * M_TO_MI * 100) / 100) + ' mi';\n }\n return Math.round(ft) + ' ft';\n }\n // metric\n if (metres > 1000) {\n return (Math.round(metres / 1000 * 100) / 100) + ' km';\n }\n return (Math.round(metres * 100) / 100) + ' m';\n}\n\n/**\n * Format a length with both large and small units (for info popups).\n * Metric: \"1.23 km (1,230 m)\" or \"456 m\"\n * Imperial: \"1.23 mi (6,494 ft)\" or \"456 ft\"\n */\nexport function formatLengthFull(metres) {\n if (getSystem() === 'imperial') {\n const ft = metres * M_TO_FT;\n const mi = metres * M_TO_MI;\n if (ft >= 5280) {\n return `${mi.toFixed(2)} mi (${ft.toLocaleString('en', { maximumFractionDigits: 0 })} ft)`;\n }\n return `${ft.toLocaleString('en', { maximumFractionDigits: 1 })} ft`;\n }\n if (metres >= 1000) {\n return `${(metres / 1000).toFixed(2)} km (${metres.toLocaleString('en', { maximumFractionDigits: 0 })} m)`;\n }\n return `${metres.toLocaleString('en', { maximumFractionDigits: 1 })} m`;\n}\n\n// ── Area ────────────────────────────────────────────────────────────────────\n\n/**\n * Format an area value (in square metres) for display.\n * Metric: m² / km²\n * Imperial: ft² / acres / mi²\n */\nexport function formatArea(sqMetres) {\n if (getSystem() === 'imperial') {\n const acres = sqMetres * SQM_TO_ACRE;\n if (acres >= 640) {\n return (Math.round(sqMetres * SQM_TO_SQMI * 100) / 100) + ' mi²';\n }\n if (acres >= 1) {\n return (Math.round(acres * 100) / 100) + ' acres';\n }\n return Math.round(sqMetres * SQM_TO_SQFT).toLocaleString('en') + ' ft²';\n }\n // metric\n if (sqMetres > 1000000) {\n return (Math.round(sqMetres / 1000000 * 100) / 100) + ' km²';\n }\n return (Math.round(sqMetres * 100) / 100) + ' m²';\n}\n\n/**\n * Format an area with both large and small units (for info popups).\n * Metric: \"1.23 km² (1,230,000 m²)\" or \"456 m²\"\n * Imperial: \"1.23 mi² (787 acres)\" or \"2.5 acres\" or \"456 ft²\"\n */\nexport function formatAreaFull(sqMetres) {\n if (getSystem() === 'imperial') {\n const sqft = sqMetres * SQM_TO_SQFT;\n const acres = sqMetres * SQM_TO_ACRE;\n const sqmi = sqMetres * SQM_TO_SQMI;\n if (acres >= 640) {\n return `${sqmi.toFixed(2)} mi² (${acres.toLocaleString('en', { maximumFractionDigits: 0 })} acres)`;\n }\n if (acres >= 1) {\n return `${acres.toLocaleString('en', { maximumFractionDigits: 1 })} acres (${sqft.toLocaleString('en', { maximumFractionDigits: 0 })} ft²)`;\n }\n return `${sqft.toLocaleString('en', { maximumFractionDigits: 0 })} ft²`;\n }\n if (sqMetres > 1000000) {\n return `${(sqMetres / 1000000).toFixed(2)} km² (${sqMetres.toLocaleString('en', { maximumFractionDigits: 0 })} m²)`;\n }\n return `${sqMetres.toLocaleString('en', { maximumFractionDigits: 0 })} m²`;\n}\n\n// ── Circle helper ───────────────────────────────────────────────────────────\n\n/**\n * Format the area of a circle given its radius (in metres).\n */\nexport function formatCircleExtent(radiusMetres) {\n return formatArea(Math.PI * radiusMetres * radiusMetres);\n}\n","/**\n * Pure geometry functions for splitting a polygon by a line.\n *\n * No OpenLayers dependency — operates on raw coordinate arrays.\n */\n\n/**\n * Compute the intersection point of two 2D line segments.\n * Segment A: p1→p2, Segment B: p3→p4.\n *\n * @param {number[]} p1\n * @param {number[]} p2\n * @param {number[]} p3\n * @param {number[]} p4\n * @param {number} [eps=1e-10] tolerance for parallel check\n * @returns {{ point: number[], t: number, u: number } | null}\n * t = parametric position on segment A (0–1),\n * u = parametric position on segment B (0–1)\n */\nfunction segmentIntersection(p1, p2, p3, p4, eps = 1e-10) {\n const dx1 = p2[0] - p1[0];\n const dy1 = p2[1] - p1[1];\n const dx2 = p4[0] - p3[0];\n const dy2 = p4[1] - p3[1];\n\n const denom = dx1 * dy2 - dy1 * dx2;\n if (Math.abs(denom) < eps) return null; // parallel / collinear\n\n const dx3 = p3[0] - p1[0];\n const dy3 = p3[1] - p1[1];\n\n const t = (dx3 * dy2 - dy3 * dx2) / denom;\n const u = (dx3 * dy1 - dy3 * dx1) / denom;\n\n if (t < -eps || t > 1 + eps || u < -eps || u > 1 + eps) return null;\n\n return {\n point: [p1[0] + t * dx1, p1[1] + t * dy1],\n t: Math.max(0, Math.min(1, t)),\n u: Math.max(0, Math.min(1, u)),\n };\n}\n\n/**\n * Signed area of a ring (shoelace formula).\n * Positive = counter-clockwise, negative = clockwise.\n */\nfunction signedArea(ring) {\n let area = 0;\n for (let i = 0, n = ring.length; i < n - 1; i++) {\n area += (ring[i][0] * ring[i + 1][1]) - (ring[i + 1][0] * ring[i][1]);\n }\n return area / 2;\n}\n\n/**\n * Test whether a point is inside a ring (ray-casting algorithm).\n */\nfunction pointInRing(pt, ring) {\n let inside = false;\n for (let i = 0, j = ring.length - 2; i < ring.length - 1; j = i++) {\n const xi = ring[i][0], yi = ring[i][1];\n const xj = ring[j][0], yj = ring[j][1];\n if (((yi > pt[1]) !== (yj > pt[1])) &&\n (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi)) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * Squared distance between two points.\n */\nfunction dist2(a, b) {\n return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2;\n}\n\n/**\n * Find all intersection points between a cutting line and a polygon ring.\n *\n * @param {number[][]} ring Closed ring coordinates (first === last)\n * @param {number[][]} line LineString coordinates (2+ points)\n * @returns {Array<{ point: number[], ringSegIdx: number, ringT: number, lineSegIdx: number, lineT: number }>}\n */\nfunction findIntersections(ring, line) {\n const hits = [];\n const eps = 1e-10;\n\n for (let li = 0; li < line.length - 1; li++) {\n for (let ri = 0; ri < ring.length - 1; ri++) {\n const ix = segmentIntersection(ring[ri], ring[ri + 1], line[li], line[li + 1], eps);\n if (!ix) continue;\n\n // Skip if intersection is at the very start of the ring segment\n // but was already caught as the end of the previous segment\n const pt = ix.point;\n\n // Avoid duplicate hits at shared vertices\n let isDup = false;\n for (const h of hits) {\n if (dist2(h.point, pt) < 1e-6) {\n isDup = true;\n break;\n }\n }\n if (isDup) continue;\n\n hits.push({\n point: pt,\n ringSegIdx: ri,\n ringT: ix.t,\n lineSegIdx: li,\n lineT: ix.u,\n });\n }\n }\n\n // Sort by position along the cutting line\n hits.sort((a, b) => {\n if (a.lineSegIdx !== b.lineSegIdx) return a.lineSegIdx - b.lineSegIdx;\n return a.lineT - b.lineT;\n });\n\n return hits;\n}\n\n/**\n * Insert intersection points into a ring, returning the expanded ring\n * and the new indices of the inserted points.\n *\n * @param {number[][]} ring Closed ring (first === last)\n * @param {Array<{ point: number[], ringSegIdx: number, ringT: number }>} hits\n * Sorted by ringSegIdx then ringT.\n * @returns {{ ring: number[][], indices: number[] }}\n */\nfunction insertPointsIntoRing(ring, hits) {\n // Sort hits by ring position (segment index, then parametric t) so\n // we can insert from back to front without shifting earlier indices.\n const sorted = hits.map((h, i) => ({ ...h, origOrder: i }));\n sorted.sort((a, b) => {\n if (a.ringSegIdx !== b.ringSegIdx) return a.ringSegIdx - b.ringSegIdx;\n return a.ringT - b.ringT;\n });\n\n const expanded = ring.slice(); // copy\n const indices = new Array(sorted.length);\n\n // Insert from the end so that earlier insertions don't shift later indices.\n for (let k = sorted.length - 1; k >= 0; k--) {\n const h = sorted[k];\n const insertIdx = h.ringSegIdx + 1;\n\n // Check if this point is essentially identical to an existing vertex\n const snapDist = 1e-6;\n if (dist2(h.point, expanded[h.ringSegIdx]) < snapDist) {\n indices[h.origOrder] = h.ringSegIdx;\n continue;\n }\n if (dist2(h.point, expanded[h.ringSegIdx + 1]) < snapDist) {\n indices[h.origOrder] = h.ringSegIdx + 1;\n continue;\n }\n\n // Insert the new point\n expanded.splice(insertIdx, 0, h.point);\n indices[h.origOrder] = insertIdx;\n\n // Adjust indices for all previously recorded insertions\n // that reference a position >= insertIdx\n for (let j = k + 1; j < sorted.length; j++) {\n if (indices[sorted[j].origOrder] >= insertIdx) {\n indices[sorted[j].origOrder]++;\n }\n }\n }\n\n return { ring: expanded, indices };\n}\n\n/**\n * Extract a slice of a ring from index i0 to i1 (going forward, wrapping).\n * Both endpoints are included.\n *\n * @param {number[][]} ring Closed ring (first === last); length includes closing vertex\n * @param {number} i0 Start index (inclusive)\n * @param {number} i1 End index (inclusive)\n * @returns {number[][]}\n */\nfunction ringSlice(ring, i0, i1) {\n const n = ring.length - 1; // number of unique vertices (ring is closed)\n // Normalise indices into the [0, n-1] range\n const start = ((i0 % n) + n) % n;\n const end = ((i1 % n) + n) % n;\n const result = [];\n let idx = start;\n while (true) {\n result.push(ring[idx]);\n if (idx === end) break;\n idx = (idx + 1) % n;\n }\n return result;\n}\n\n/**\n * Extract the cutting line segment between two intersection points.\n *\n * @param {number[][]} line Full cutting line coordinates\n * @param {{ point: number[], lineSegIdx: number, lineT: number }} hit0\n * @param {{ point: number[], lineSegIdx: number, lineT: number }} hit1\n * @returns {number[][]} Coordinates from hit0.point to hit1.point along the line\n */\nfunction cuttingLineSlice(line, hit0, hit1) {\n const result = [hit0.point];\n\n // Include all intermediate line vertices between the two hit segments\n const startSeg = hit0.lineSegIdx;\n const endSeg = hit1.lineSegIdx;\n\n for (let i = startSeg + 1; i <= endSeg; i++) {\n result.push(line[i]);\n }\n\n // Add the end intersection point if it's not the same as the last vertex\n if (dist2(result[result.length - 1], hit1.point) > 1e-10) {\n result.push(hit1.point);\n }\n\n return result;\n}\n\n/**\n * Ensure a ring has the desired winding order.\n * @param {number[][]} ring Closed ring\n * @param {boolean} ccw true for counter-clockwise\n * @returns {number[][]}\n */\nfunction ensureWinding(ring, ccw) {\n const area = signedArea(ring);\n if ((ccw && area < 0) || (!ccw && area > 0)) {\n return ring.slice().reverse();\n }\n return ring;\n}\n\n/**\n * Close a ring (ensure first === last).\n */\nfunction closeRing(coords) {\n if (coords.length < 2) return coords;\n const first = coords[0];\n const last = coords[coords.length - 1];\n if (dist2(first, last) > 1e-10) {\n return [...coords, first.slice()];\n }\n return coords;\n}\n\n/**\n * Extend a cutting line so that both endpoints lie outside the polygon ring.\n * If an endpoint is inside, we extend the first/last segment outward past the\n * bounding box diagonal so it definitely exits.\n *\n * @param {number[][]} line Cutting line coordinates\n * @param {number[][]} ring Closed polygon ring\n * @returns {number[][]} Extended line (may be the original if already outside)\n */\nfunction extendLineOutsideRing(line, ring) {\n // Compute bounding-box diagonal for a generous extension distance\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const pt of ring) {\n if (pt[0] < minX) minX = pt[0];\n if (pt[1] < minY) minY = pt[1];\n if (pt[0] > maxX) maxX = pt[0];\n if (pt[1] > maxY) maxY = pt[1];\n }\n const diag = Math.sqrt((maxX - minX) ** 2 + (maxY - minY) ** 2) || 1;\n\n const result = line.slice();\n\n // Extend start if inside\n if (pointInRing(result[0], ring)) {\n const p0 = result[0];\n const p1 = result[1];\n const dx = p0[0] - p1[0];\n const dy = p0[1] - p1[1];\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n const scale = diag * 2 / len;\n result[0] = [p0[0] + dx * scale, p0[1] + dy * scale];\n }\n\n // Extend end if inside\n const last = result.length - 1;\n if (pointInRing(result[last], ring)) {\n const pN = result[last];\n const pN1 = result[last - 1];\n const dx = pN[0] - pN1[0];\n const dy = pN[1] - pN1[1];\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n const scale = diag * 2 / len;\n result[last] = [pN[0] + dx * scale, pN[1] + dy * scale];\n }\n\n return result;\n}\n\n/**\n * Split a polygon by a cutting line.\n *\n * The cutting line can start or end inside the polygon — the algorithm will\n * automatically extend it outward so it crosses the boundary at exactly 2\n * points. Multi-vertex cutting lines (with corners or approximated arcs)\n * are fully supported.\n *\n * @param {number[][][]} polygonCoords Polygon coordinates:\n * [exteriorRing, ...holeRings] where each ring is closed (first === last)\n * @param {number[][]} lineCoords Cutting line coordinates (2+ points)\n * @returns {number[][][][] | null} Two polygon coordinate arrays, or null if split failed\n */\nexport function splitPolygonByLine(polygonCoords, lineCoords) {\n const exteriorRing = polygonCoords[0];\n const holes = polygonCoords.slice(1);\n\n // Extend the cutting line if its endpoints are inside the polygon\n const extendedLine = extendLineOutsideRing(lineCoords, exteriorRing);\n\n // 1. Find intersections between cutting line and exterior ring\n const hits = findIntersections(exteriorRing, extendedLine);\n\n // We need exactly 2 intersection points for a simple split\n if (hits.length !== 2) {\n console.warn(`[polygonSplit] Expected 2 intersections, got ${hits.length}`);\n return null;\n }\n\n const [hit0, hit1] = hits;\n\n // 2. Insert intersection points into the ring\n const { ring: expandedRing, indices } = insertPointsIntoRing(exteriorRing, hits);\n const idx0 = indices[0];\n const idx1 = indices[1];\n\n // Ensure idx0 < idx1 for consistent traversal\n const [iA, iB] = idx0 < idx1 ? [idx0, idx1] : [idx1, idx0];\n const [hitA, hitB] = idx0 < idx1 ? [hit0, hit1] : [hit1, hit0];\n\n // 3. Get the cutting line segment between the two intersection points\n const cutForward = idx0 < idx1\n ? cuttingLineSlice(extendedLine, hit0, hit1)\n : cuttingLineSlice(extendedLine, hit1, hit0);\n const cutReverse = cutForward.slice().reverse();\n\n // 4. Build two polygon rings\n // Ring A: walk ring from iA to iB (forward), then cutting line reversed back to iA\n const sliceAB = ringSlice(expandedRing, iA, iB);\n const ringA = closeRing([...sliceAB, ...cutReverse.slice(1)]);\n\n // Ring B: walk ring from iB to iA (wrapping), then cutting line forward back to iB\n const sliceBA = ringSlice(expandedRing, iB, iA);\n const ringB = closeRing([...sliceBA, ...cutForward.slice(1)]);\n\n // 5. Match winding order to original\n const originalCCW = signedArea(exteriorRing) > 0;\n const finalA = ensureWinding(ringA, originalCCW);\n const finalB = ensureWinding(ringB, originalCCW);\n\n // 6. Build polygon coordinate arrays, assigning holes to the correct piece\n const polyA = [finalA];\n const polyB = [finalB];\n\n for (const hole of holes) {\n // Use the centroid of the hole to determine containment\n const centroid = holeCentroid(hole);\n if (pointInRing(centroid, finalA)) {\n polyA.push(hole);\n } else {\n polyB.push(hole);\n }\n }\n\n return [polyA, polyB];\n}\n\n/**\n * Compute the centroid of a closed ring.\n */\nfunction holeCentroid(ring) {\n let cx = 0, cy = 0;\n const n = ring.length - 1; // exclude closing vertex\n for (let i = 0; i < n; i++) {\n cx += ring[i][0];\n cy += ring[i][1];\n }\n return [cx / n, cy / n];\n}\n","/**\n * Lightweight toast notification system.\n *\n * Usage:\n * import { showToast } from '../toast.js';\n *\n * showToast('Something went wrong', 'error');\n * showToast('Merge successful!', 'success');\n * showToast('Select two adjacent polygons', 'info');\n */\n\n// ── Palette ──────────────────────────────────────────────────────────────────\n\nconst THEMES = {\n success: { bg: '#10b981', icon: '\\u2705' }, // green\n error: { bg: '#ef4444', icon: '\\u274c' }, // red\n warning: { bg: '#f59e0b', icon: '\\u26a0\\ufe0f' }, // amber\n info: { bg: '#0ea5e9', icon: '\\u2139\\ufe0f' }, // cyan\n};\n\n// ── Container (created once, appended to ) ────────────────────────────\n\nlet container = null;\n\nfunction ensureContainer() {\n if (container) return container;\n container = document.createElement('div');\n container.style.cssText = `\n position: fixed;\n top: 16px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 10000;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n pointer-events: none;\n `;\n document.body.appendChild(container);\n return container;\n}\n\n// ── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Display a toast notification.\n *\n * @param {string} message Plain-text message to show.\n * @param {'success'|'error'|'warning'|'info'} [type='info']\n * @param {number} [duration=4000] Auto-dismiss time in ms.\n */\nexport function showToast(message, type = 'info', duration = 4000) {\n const parent = ensureContainer();\n const theme = THEMES[type] || THEMES.info;\n\n const el = document.createElement('div');\n el.style.cssText = `\n background: ${theme.bg};\n color: #fff;\n padding: 10px 18px;\n border-radius: 8px;\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n font-weight: 600;\n box-shadow: 0 4px 12px rgba(0,0,0,0.25);\n pointer-events: auto;\n cursor: pointer;\n opacity: 0;\n transition: opacity 0.25s ease, transform 0.25s ease;\n transform: translateY(-8px);\n max-width: 420px;\n text-align: center;\n line-height: 1.4;\n `;\n el.textContent = `${theme.icon} ${message}`;\n\n parent.appendChild(el);\n\n // Animate in\n requestAnimationFrame(() => {\n el.style.opacity = '1';\n el.style.transform = 'translateY(0)';\n });\n\n // Dismiss helper\n const dismiss = () => {\n el.style.opacity = '0';\n el.style.transform = 'translateY(-8px)';\n setTimeout(() => el.remove(), 300);\n };\n\n // Click to dismiss early\n el.addEventListener('click', dismiss);\n\n // Auto-dismiss\n setTimeout(dismiss, duration);\n}\n","/**\n * PolygonSplitInteraction\n *\n * A two-phase OpenLayers interaction for splitting polygons:\n * Phase 1 – SELECT: hover to highlight, click to select a polygon\n * Phase 2 – DRAW: draw a cutting line, double-click to finish\n *\n * After a successful split the original feature is removed and two new\n * coloured features are added. The interaction fires `beforesplit` and\n * `aftersplit` events compatible with ol-ext's UndoRedo.\n */\n\nimport ol_interaction_Interaction from 'ol/interaction/Interaction';\nimport ol_interaction_Draw from 'ol/interaction/Draw';\nimport VectorSource from 'ol/source/Vector';\nimport VectorLayer from 'ol/layer/Vector';\nimport Feature from 'ol/Feature';\nimport { Style, Stroke, Fill, Circle as CircleStyle } from 'ol/style';\nimport { LineString } from 'ol/geom';\nimport { Polygon as PolygonGeom } from 'ol/geom';\nimport { splitPolygonByLine } from '../geom/polygonSplit.js';\nimport { showToast } from '../toast.js';\n\n// Marker colours for the two split pieces\nconst SPLIT_COLORS = [\n { stroke: '#ef4444', fill: 'rgba(239,68,68,0.25)' }, // red\n { stroke: '#3b82f6', fill: 'rgba(59,130,246,0.25)' }, // blue\n];\n\n// Highlight style for the selected polygon (phase 1)\nconst HIGHLIGHT_STYLE = new Style({\n stroke: new Stroke({ color: '#0ea5e9', width: 3 }),\n fill: new Fill({ color: 'rgba(14,165,233,0.15)' }),\n});\n\n// Style for the cutting-line sketch (phase 2)\nconst SKETCH_STYLE = new Style({\n stroke: new Stroke({ color: '#f43f5e', width: 2, lineDash: [8, 6] }),\n image: new CircleStyle({\n radius: 5,\n fill: new Fill({ color: '#f43f5e' }),\n stroke: new Stroke({ color: '#fff', width: 1.5 }),\n }),\n});\n\nexport class PolygonSplitInteraction extends ol_interaction_Interaction {\n /**\n * @param {Object} options\n * @param {VectorSource|VectorSource[]} [options.sources] Sources containing\n * polygons to split. If omitted the interaction searches all visible\n * vector layers on the map.\n * @param {number} [options.snapDistance=25] Pixel distance for hover highlight.\n */\n constructor(options = {}) {\n super({\n handleEvent: (e) => this._handleEvent(e),\n });\n\n this.snapDistance_ = options.snapDistance || 25;\n this._sources = options.sources\n ? (Array.isArray(options.sources) ? options.sources : [options.sources])\n : null;\n\n // Phase: 'select' | 'draw' | 'pick'\n this._phase = 'select';\n this._selectedFeature = null;\n this._selectedSource = null;\n this._drawInteraction = null;\n this._splitFeatures = null; // the two pieces (for pick phase)\n\n // Overlay layer for highlighting the polygon under the cursor / selected\n this._overlaySource = new VectorSource({ useSpatialIndex: false });\n this._overlayLayer = new VectorLayer({\n source: this._overlaySource,\n displayInLayerSwitcher: false,\n style: HIGHLIGHT_STYLE,\n });\n }\n\n /* ------------------------------------------------------------------ */\n /* Map lifecycle */\n /* ------------------------------------------------------------------ */\n\n setMap(map) {\n if (this.getMap()) {\n this.getMap().removeLayer(this._overlayLayer);\n this._removeDrawInteraction();\n }\n super.setMap(map);\n if (map) {\n this._overlayLayer.setMap(map);\n }\n }\n\n setActive(active) {\n super.setActive(active);\n if (!active) {\n this._reset();\n }\n }\n\n /* ------------------------------------------------------------------ */\n /* Source helpers */\n /* ------------------------------------------------------------------ */\n\n _getSources() {\n if (this._sources) return this._sources;\n if (!this.getMap()) return [];\n const sources = [];\n const collect = (layers) => {\n layers.forEach((layer) => {\n if (layer.getVisible()) {\n if (layer.getSource && layer.getSource() instanceof VectorSource) {\n sources.push(layer.getSource());\n } else if (layer.getLayers) {\n collect(layer.getLayers());\n }\n }\n });\n };\n collect(this.getMap().getLayers());\n return sources;\n }\n\n /* ------------------------------------------------------------------ */\n /* Event router */\n /* ------------------------------------------------------------------ */\n\n _handleEvent(e) {\n if (!this.getActive()) return true;\n\n if (this._phase === 'select') {\n if (e.type === 'pointermove') return this._onSelectMove(e);\n if (e.type === 'singleclick') return this._onSelectClick(e);\n }\n // In 'draw' phase the Draw interaction handles events directly;\n // we only intercept Escape to cancel.\n if (this._phase === 'draw') {\n if (e.type === 'keydown' && e.originalEvent?.key === 'Escape') {\n this._cancelDraw();\n return false;\n }\n }\n\n // In 'pick' phase the user selects which split piece keeps the UPN\n if (this._phase === 'pick') {\n if (e.type === 'pointermove') return this._onPickMove(e);\n if (e.type === 'singleclick') return this._onPickClick(e);\n if (e.type === 'keydown' && e.originalEvent?.key === 'Escape') {\n this._reset();\n return false;\n }\n }\n\n return true;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 1: SELECT */\n /* ------------------------------------------------------------------ */\n\n _onSelectMove(e) {\n const map = this.getMap();\n if (!map) return true;\n\n this._overlaySource.clear();\n\n const hit = this._closestPolygon(e);\n if (hit) {\n // Show highlight copy\n const clone = hit.feature.clone();\n this._overlaySource.addFeature(clone);\n map.getTargetElement().style.cursor = 'pointer';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onSelectClick(e) {\n const hit = this._closestPolygon(e);\n if (!hit) return true;\n\n this._selectedFeature = hit.feature;\n this._selectedSource = hit.source;\n\n // Keep highlight visible during draw phase\n this._overlaySource.clear();\n const clone = hit.feature.clone();\n this._overlaySource.addFeature(clone);\n\n this._startDrawPhase();\n return false; // consume the click\n }\n\n /**\n * Find the closest polygon feature within snap distance.\n */\n _closestPolygon(e) {\n let best = null;\n let bestDist = this.snapDistance_ + 1;\n\n for (const source of this._getSources()) {\n const feat = source.getClosestFeatureToCoordinate(e.coordinate);\n if (!feat) continue;\n const geom = feat.getGeometry();\n if (!geom) continue;\n const type = geom.getType();\n if (type !== 'Polygon' && type !== 'MultiPolygon') continue;\n\n const closest = geom.getClosestPoint(e.coordinate);\n const line = new LineString([e.coordinate, closest]);\n const distPx = line.getLength() / e.frameState.viewState.resolution;\n\n if (distPx < bestDist) {\n bestDist = distPx;\n best = { feature: feat, source, coord: closest };\n }\n }\n return best;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 2: DRAW cutting line */\n /* ------------------------------------------------------------------ */\n\n _startDrawPhase() {\n this._phase = 'draw';\n const map = this.getMap();\n if (!map) return;\n\n map.getTargetElement().style.cursor = 'crosshair';\n\n this._drawInteraction = new ol_interaction_Draw({\n type: 'LineString',\n style: SKETCH_STYLE,\n });\n\n this._drawInteraction.on('drawend', (evt) => {\n const cuttingLine = evt.feature.getGeometry().getCoordinates();\n this._performSplit(cuttingLine);\n });\n\n map.addInteraction(this._drawInteraction);\n }\n\n _removeDrawInteraction() {\n if (this._drawInteraction && this.getMap()) {\n this.getMap().removeInteraction(this._drawInteraction);\n }\n this._drawInteraction = null;\n }\n\n _cancelDraw() {\n this._removeDrawInteraction();\n this._reset();\n }\n\n /* ------------------------------------------------------------------ */\n /* Split logic */\n /* ------------------------------------------------------------------ */\n\n _performSplit(cuttingLineCoords) {\n const feature = this._selectedFeature;\n const source = this._selectedSource;\n const geom = feature.getGeometry();\n\n let polygonCoords;\n if (geom.getType() === 'Polygon') {\n polygonCoords = geom.getCoordinates();\n } else if (geom.getType() === 'MultiPolygon') {\n // For MultiPolygon, try to split each sub-polygon and use the\n // first one that produces a valid result.\n // For now, use the first polygon ring.\n polygonCoords = geom.getCoordinates()[0];\n }\n\n const result = splitPolygonByLine(polygonCoords, cuttingLineCoords);\n\n if (!result) {\n console.warn('[PolygonSplit] Split failed — line must cross the polygon boundary at exactly 2 points.');\n // Stay in draw phase so user can retry\n this._removeDrawInteraction();\n this._startDrawPhase();\n return;\n }\n\n const [coordsA, coordsB] = result;\n\n // Create two new features from the split result\n const featureA = feature.clone();\n featureA.setGeometry(new PolygonGeom(coordsA));\n featureA.setStyle(new Style({\n stroke: new Stroke({ color: SPLIT_COLORS[0].stroke, width: 2.5 }),\n fill: new Fill({ color: SPLIT_COLORS[0].fill }),\n }));\n\n const featureB = feature.clone();\n featureB.setGeometry(new PolygonGeom(coordsB));\n featureB.setStyle(new Style({\n stroke: new Stroke({ color: SPLIT_COLORS[1].stroke, width: 2.5 }),\n fill: new Fill({ color: SPLIT_COLORS[1].fill }),\n }));\n\n // Dispatch beforesplit (compatible with ol-ext UndoRedo)\n const splitFeatures = [featureA, featureB];\n this.dispatchEvent({\n type: 'beforesplit',\n original: feature,\n features: splitFeatures,\n });\n source.dispatchEvent({\n type: 'beforesplit',\n original: feature,\n features: splitFeatures,\n });\n\n // Replace the original feature. Group the remove + two adds into a single\n // UndoRedo block (via the map-level undoblockstart/undoblockend events the\n // ol-ext UndoRedo interaction listens for) so the whole split is reversed\n // by ONE undo press instead of three.\n const splitMap = this.getMap();\n splitMap?.dispatchEvent('undoblockstart');\n source.removeFeature(feature);\n source.addFeature(featureA);\n source.addFeature(featureB);\n splitMap?.dispatchEvent('undoblockend');\n\n // Dispatch aftersplit\n this.dispatchEvent({\n type: 'aftersplit',\n original: feature,\n features: splitFeatures,\n });\n source.dispatchEvent({\n type: 'aftersplit',\n original: feature,\n features: splitFeatures,\n });\n\n // Clean up draw interaction\n this._removeDrawInteraction();\n\n // If the original was a parcel, enter pick phase for UPN assignment\n const isParcel = feature.get('_layerType') === 'parcel';\n if (isParcel) {\n this._splitFeatures = splitFeatures;\n this._phase = 'pick';\n this._overlaySource.clear();\n const map = this.getMap();\n if (map) map.getTargetElement().style.cursor = '';\n showToast('Click the polygon that should keep the original identifier.', 'info', 5000);\n\n this.dispatchEvent({\n type: 'splitparcel',\n features: splitFeatures,\n originalProps: feature.getProperties(),\n source,\n });\n } else {\n this._reset();\n }\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 3: PICK — select which split piece keeps the UPN */\n /* ------------------------------------------------------------------ */\n\n _onPickMove(e) {\n const map = this.getMap();\n if (!map) return true;\n\n this._overlaySource.clear();\n\n const hit = this._closestSplitPiece(e);\n if (hit) {\n const clone = hit.clone();\n this._overlaySource.addFeature(clone);\n map.getTargetElement().style.cursor = 'pointer';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onPickClick(e) {\n const hit = this._closestSplitPiece(e);\n if (!hit) return true;\n\n this.dispatchEvent({\n type: 'splitpick',\n picked: hit,\n features: this._splitFeatures,\n });\n\n this._reset();\n return false;\n }\n\n /**\n * Find the closest split piece to the cursor.\n */\n _closestSplitPiece(e) {\n if (!this._splitFeatures) return null;\n let best = null;\n let bestDist = this.snapDistance_ + 1;\n\n for (const feat of this._splitFeatures) {\n const geom = feat.getGeometry();\n if (!geom) continue;\n const closest = geom.getClosestPoint(e.coordinate);\n const line = new LineString([e.coordinate, closest]);\n const distPx = line.getLength() / e.frameState.viewState.resolution;\n if (distPx < bestDist) {\n bestDist = distPx;\n best = feat;\n }\n }\n return best;\n }\n\n /* ------------------------------------------------------------------ */\n /* Reset */\n /* ------------------------------------------------------------------ */\n\n _reset() {\n this._phase = 'select';\n this._selectedFeature = null;\n this._selectedSource = null;\n this._splitFeatures = null;\n this._overlaySource.clear();\n this._removeDrawInteraction();\n\n const map = this.getMap();\n if (map) {\n map.getTargetElement().style.cursor = '';\n }\n }\n}\n","/**\n * Pure geometry functions for merging two adjacent polygons.\n *\n * No OpenLayers dependency — operates on raw coordinate arrays.\n */\n\n/**\n * Squared distance between two points.\n */\nfunction dist2(a, b) {\n return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2;\n}\n\n/**\n * Signed area of a ring (shoelace formula).\n * Positive = counter-clockwise, negative = clockwise.\n */\nfunction signedArea(ring) {\n let area = 0;\n for (let i = 0, n = ring.length; i < n - 1; i++) {\n area += (ring[i][0] * ring[i + 1][1]) - (ring[i + 1][0] * ring[i][1]);\n }\n return area / 2;\n}\n\n/**\n * Test whether a point is inside a ring (ray-casting algorithm).\n */\nfunction pointInRing(pt, ring) {\n let inside = false;\n for (let i = 0, j = ring.length - 2; i < ring.length - 1; j = i++) {\n const xi = ring[i][0], yi = ring[i][1];\n const xj = ring[j][0], yj = ring[j][1];\n if (((yi > pt[1]) !== (yj > pt[1])) &&\n (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi)) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * Ensure a ring has the desired winding order.\n */\nfunction ensureWinding(ring, ccw) {\n const area = signedArea(ring);\n if ((ccw && area < 0) || (!ccw && area > 0)) {\n return ring.slice().reverse();\n }\n return ring;\n}\n\n/**\n * Close a ring (ensure first === last).\n */\nfunction closeRing(coords) {\n if (coords.length < 2) return coords;\n if (dist2(coords[0], coords[coords.length - 1]) > 1e-10) {\n return [...coords, coords[0].slice()];\n }\n return coords;\n}\n\n/**\n * Perpendicular distance from a point to a segment.\n *\n * @param {number[]} pt\n * @param {number[]} segA Segment start\n * @param {number[]} segB Segment end\n * @returns {number} Squared distance\n */\nfunction distToSegmentSq(pt, segA, segB) {\n const dx = segB[0] - segA[0];\n const dy = segB[1] - segA[1];\n const lenSq = dx * dx + dy * dy;\n\n if (lenSq < 1e-20) return dist2(pt, segA); // degenerate segment\n\n // Parametric position of the projection\n let t = ((pt[0] - segA[0]) * dx + (pt[1] - segA[1]) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n\n const projX = segA[0] + t * dx;\n const projY = segA[1] + t * dy;\n return (pt[0] - projX) ** 2 + (pt[1] - projY) ** 2;\n}\n\n/**\n * Find the ring edge closest to a click coordinate.\n *\n * @param {number[][]} ring Closed ring\n * @param {number[]} clickCoord [x, y]\n * @returns {{ segIdx: number, distSq: number }}\n */\nfunction findClosestEdge(ring, clickCoord) {\n let bestIdx = 0;\n let bestDist = Infinity;\n const n = ring.length - 1; // unique vertices\n\n for (let i = 0; i < n; i++) {\n const d = distToSegmentSq(clickCoord, ring[i], ring[(i + 1) % n === 0 ? n : i + 1]);\n if (d < bestDist) {\n bestDist = d;\n bestIdx = i;\n }\n }\n return { segIdx: bestIdx, distSq: bestDist };\n}\n\n/**\n * Check if two coordinates are equal within tolerance.\n */\nfunction coordsEqual(a, b, tolSq) {\n return dist2(a, b) < tolSq;\n}\n\n/**\n * Test whether a point lies within tolerance of any edge of a ring.\n *\n * Unlike coordsEqual (vertex-to-vertex), this checks whether the point is\n * close to the ring's *boundary* — it projects onto segments, so it works\n * even when the two polygons have different vertex density along the shared\n * edge or when vertices are slightly offset from separate digitisation.\n *\n * @param {number[]} pt Point to test\n * @param {number[][]} ring Closed ring\n * @param {number} tolSq Squared distance tolerance\n * @returns {boolean}\n */\nfunction isVertexNearRing(pt, ring, tolSq) {\n const n = ring.length - 1;\n for (let i = 0; i < n; i++) {\n if (distToSegmentSq(pt, ring[i], ring[i + 1]) < tolSq) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Find the shared boundary between two polygon rings.\n *\n * Adjacent polygons share edges in reverse winding direction:\n * if A walks P→Q along the shared boundary, B walks Q→P.\n *\n * The algorithm has two stages:\n *\n * 1. **Seed validation** — uses `isVertexNearRing` (vertex-to-edge proximity)\n * to confirm the user-clicked edges actually lie on a common boundary.\n * This is the forgiving check that handles offset vertices from separate\n * digitisation.\n *\n * 2. **Lockstep extension** — walks both rings together (A forward, B in\n * the opposite direction) and extends the shared boundary one vertex at\n * a time. Three cases are tried at each step:\n * a) Both rings advance: vertex-to-vertex match (classic case).\n * b) Only A advances: A has an extra vertex that projects onto B's\n * frontier edge (different vertex density).\n * c) Only B advances: vice-versa.\n * Because extension is coupled to the *frontier edge* of the other ring\n * (not the entire ring), it cannot overshoot into non-shared territory,\n * even for small or closely-spaced polygons.\n *\n * @param {number[][]} ringA Closed ring\n * @param {number[][]} ringB Closed ring\n * @param {number} seedIdxA Seed edge index on ring A\n * @param {number} seedIdxB Seed edge index on ring B\n * @param {number} tolerance Distance tolerance (in map units)\n * @returns {{ startA: number, endA: number, startB: number, endB: number, reversed: boolean } | null}\n */\nfunction findSharedBoundary(ringA, ringB, seedIdxA, seedIdxB, tolerance) {\n const nA = ringA.length - 1; // unique vertices\n const nB = ringB.length - 1;\n const tolSq = tolerance * tolerance;\n\n // ── Validate seed edges ─────────────────────────────────────────────\n // Both vertices of the seed edge on A must be near ring B's boundary,\n // or both vertices of the seed edge on B must be near ring A's boundary.\n // This uses vertex-to-edge proximity so it handles offset digitisation.\n const a0 = ringA[seedIdxA];\n const a1 = ringA[(seedIdxA + 1) % nA];\n const b0 = ringB[seedIdxB];\n const b1 = ringB[(seedIdxB + 1) % nB];\n\n const a0NearB = isVertexNearRing(a0, ringB, tolSq);\n const a1NearB = isVertexNearRing(a1, ringB, tolSq);\n const b0NearA = isVertexNearRing(b0, ringA, tolSq);\n const b1NearA = isVertexNearRing(b1, ringA, tolSq);\n\n if (!(a0NearB && a1NearB) && !(b0NearA && b1NearA)) {\n console.warn('[polygonMerge] Seed edges are not on the shared boundary');\n return null;\n }\n\n // ── Determine winding direction ─────────────────────────────────────\n // Reversed (the normal case): A's a0 ≈ B's b1 and A's a1 ≈ B's b0.\n let reversed;\n if (coordsEqual(a0, b1, tolSq) && coordsEqual(a1, b0, tolSq)) {\n reversed = true;\n } else if (coordsEqual(a0, b0, tolSq) && coordsEqual(a1, b1, tolSq)) {\n reversed = false;\n } else {\n // Vertices don't match exactly — use proximity to decide direction\n reversed = dist2(a0, b1) < dist2(a0, b0);\n }\n\n // ── Initialise shared boundary ──────────────────────────────────────\n let startA = seedIdxA;\n let endA = (seedIdxA + 1) % nA;\n let startB, endB;\n\n if (reversed) {\n // A walks startA → endA, B walks startB ← endB (reversed ring order)\n startB = (seedIdxB + 1) % nB;\n endB = seedIdxB;\n } else {\n startB = seedIdxB;\n endB = (seedIdxB + 1) % nB;\n }\n\n // ── Extend forward (endA++, endB-- if reversed) ─────────────────────\n // Walk both rings in lockstep. At each step try three strategies:\n // 1. Both advance — vertices match (vertex-to-vertex).\n // 2. Only A advances — A's next vertex projects onto B's frontier edge.\n // 3. Only B advances — B's next vertex projects onto A's frontier edge.\n let safety = nA + nB;\n while (safety-- > 0) {\n const nextA = (endA + 1) % nA;\n const nextB = reversed ? (endB - 1 + nB) % nB : (endB + 1) % nB;\n if (nextA === startA || nextB === startB) break; // wrapped around\n\n // Case 1: vertex-to-vertex match\n if (coordsEqual(ringA[nextA], ringB[nextB], tolSq)) {\n endA = nextA;\n endB = nextB;\n continue;\n }\n\n // Case 2: A has extra vertex — project onto B's frontier edge\n if (distToSegmentSq(ringA[nextA], ringB[endB], ringB[nextB]) < tolSq) {\n endA = nextA;\n continue;\n }\n\n // Case 3: B has extra vertex — project onto A's frontier edge\n if (distToSegmentSq(ringB[nextB], ringA[endA], ringA[nextA]) < tolSq) {\n endB = nextB;\n continue;\n }\n\n break; // no match — end of shared boundary\n }\n\n // ── Extend backward (startA--, startB++ if reversed) ────────────────\n safety = nA + nB;\n while (safety-- > 0) {\n const prevA = (startA - 1 + nA) % nA;\n const prevB = reversed ? (startB + 1) % nB : (startB - 1 + nB) % nB;\n if (prevA === endA || prevB === endB) break;\n\n // Case 1: vertex-to-vertex match\n if (coordsEqual(ringA[prevA], ringB[prevB], tolSq)) {\n startA = prevA;\n startB = prevB;\n continue;\n }\n\n // Case 2: A has extra vertex — project onto B's frontier edge\n if (distToSegmentSq(ringA[prevA], ringB[startB], ringB[prevB]) < tolSq) {\n startA = prevA;\n continue;\n }\n\n // Case 3: B has extra vertex — project onto A's frontier edge\n if (distToSegmentSq(ringB[prevB], ringA[startA], ringA[prevA]) < tolSq) {\n startB = prevB;\n continue;\n }\n\n break;\n }\n\n return { startA, endA, startB, endB, reversed };\n}\n\n/**\n * Walk a ring from startIdx to endIdx (exclusive), going forward and wrapping.\n * Skips startIdx and stops before reaching endIdx.\n * Returns the vertices of the non-shared portion.\n *\n * @param {number[][]} ring Closed ring\n * @param {number} fromIdx Start walking from this index (inclusive)\n * @param {number} toIdx Stop at this index (inclusive)\n * @returns {number[][]}\n */\nfunction walkRing(ring, fromIdx, toIdx) {\n const n = ring.length - 1;\n const result = [];\n let idx = fromIdx;\n while (true) {\n result.push(ring[idx]);\n if (idx === toIdx) break;\n idx = (idx + 1) % n;\n // Safety: prevent infinite loops\n if (result.length > n + 1) break;\n }\n return result;\n}\n\n/**\n * Merge two adjacent polygons along their shared boundary.\n *\n * @param {number[][][]} polygonCoordsA Polygon A coordinates [exteriorRing, ...holes]\n * @param {number[][][]} polygonCoordsB Polygon B coordinates [exteriorRing, ...holes]\n * @param {number[]} clickCoordA Click coordinate on the shared edge of polygon A\n * @param {number[]} clickCoordB Click coordinate on the shared edge of polygon B\n * @param {number} [tolerance=5] Distance tolerance in map units (default 5 metres in EPSG:3857).\n * A larger tolerance handles polygons that were digitised separately and\n * whose shared vertices don't coincide exactly.\n * @returns {{ coords: number[][][], error?: undefined } | { coords: null, error: string }}\n * On success: `{ coords: [...] }`. On failure: `{ coords: null, error: 'reason' }`.\n */\nexport function mergePolygons(polygonCoordsA, polygonCoordsB, clickCoordA, clickCoordB, tolerance = 5) {\n const ringA = polygonCoordsA[0];\n const ringB = polygonCoordsB[0];\n const holesA = polygonCoordsA.slice(1);\n const holesB = polygonCoordsB.slice(1);\n\n // 1. Find seed edges (closest to user clicks)\n const seedA = findClosestEdge(ringA, clickCoordA);\n const seedB = findClosestEdge(ringB, clickCoordB);\n\n // 2. Find shared boundary\n const shared = findSharedBoundary(ringA, ringB, seedA.segIdx, seedB.segIdx, tolerance);\n if (!shared) {\n console.warn('[polygonMerge] Could not find shared boundary between polygons — seed edges are not near the other ring');\n return { coords: null, error: 'The selected edges are not on a shared boundary. Click edges that lie on the common border between the two polygons.' };\n }\n\n const { startA, endA, startB, endB, reversed } = shared;\n const nA = ringA.length - 1;\n const nB = ringB.length - 1;\n\n // 3. Stitch the non-shared portions together\n // A's shared goes from startA → endA. Non-shared: endA → startA (forward, wrapping).\n // B's shared (reversed case) goes from startB backward to endB.\n // Non-shared: startB → endB (forward).\n // B's shared (same-dir case) goes from startB → endB.\n // Non-shared: endB → startB (forward, wrapping).\n //\n // The last vertex of partA (startA) must coincide with the first vertex\n // of partB for a clean join.\n\n const partA = walkRing(ringA, endA, startA);\n\n let partB;\n if (reversed) {\n // B's non-shared goes from startB forward to endB.\n // startB vertex ≈ startA vertex (they meet at one end of the shared boundary).\n partB = walkRing(ringB, startB, endB);\n } else {\n // B's non-shared goes from endB forward to startB.\n partB = walkRing(ringB, endB, startB);\n }\n\n // partA ends at startA, partB starts at a vertex that should coincide.\n // Skip the first vertex of partB to avoid the duplicate junction point.\n const merged = [...partA, ...partB.slice(1)];\n\n // Snap the closing junction. With non-coincident vertices (separate\n // digitisation) the last vertex of partB may be a few metres from the\n // first vertex of partA (ringA[endA]). Replace it to avoid a tiny\n // sliver edge that closeRing would otherwise create.\n const tolSq = tolerance * tolerance;\n if (merged.length > 2 && dist2(merged[merged.length - 1], merged[0]) < tolSq) {\n merged[merged.length - 1] = merged[0].slice();\n }\n\n const mergedRing = closeRing(merged);\n\n // 4. Validate: the merged ring should have a reasonable area\n const areaA = Math.abs(signedArea(ringA));\n const areaB = Math.abs(signedArea(ringB));\n const areaMerged = Math.abs(signedArea(mergedRing));\n const expectedArea = areaA + areaB;\n\n // Allow 10% tolerance for area mismatch (shared edges can cause slight differences)\n if (areaMerged < expectedArea * 0.5 || areaMerged > expectedArea * 1.5) {\n console.warn(`[polygonMerge] Area mismatch: A=${areaA.toFixed(1)}, B=${areaB.toFixed(1)}, merged=${areaMerged.toFixed(1)}, expected≈${expectedArea.toFixed(1)}`);\n return { coords: null, error: 'Merge produced an invalid polygon (area mismatch). The polygons may not be truly adjacent — try clicking closer to the shared boundary.' };\n }\n\n // 5. Match winding order to original\n const originalCCW = signedArea(ringA) > 0;\n const finalRing = ensureWinding(mergedRing, originalCCW);\n\n // 6. Collect holes from both polygons\n const allHoles = [...holesA, ...holesB];\n // Filter: only include holes that actually fall inside the merged ring\n const validHoles = allHoles.filter(hole => {\n const cx = hole.reduce((s, p) => s + p[0], 0) / (hole.length - 1);\n const cy = hole.reduce((s, p) => s + p[1], 0) / (hole.length - 1);\n return pointInRing([cx, cy], finalRing);\n });\n\n return { coords: [finalRing, ...validHoles] };\n}\n","/**\n * PolygonMergeInteraction\n *\n * A four-phase OpenLayers interaction for merging two adjacent polygons:\n * Phase 1 – SELECT_A: hover to highlight, click to select polygon A\n * Phase 2 – SELECT_B: hover to highlight, click to select polygon B\n * Phase 3 – CLICK_EDGE_A: hover highlights edge, click to pick shared edge on A\n * Phase 4 – CLICK_EDGE_B: hover highlights edge, click to pick shared edge on B → merge\n *\n * After a successful merge the two original features are removed and one\n * merged feature (coloured green) is added. If both originals were parcels,\n * a `mergedparcel` event is fired so external code can present a UPN chooser.\n */\n\nimport ol_interaction_Interaction from 'ol/interaction/Interaction';\nimport VectorSource from 'ol/source/Vector';\nimport VectorLayer from 'ol/layer/Vector';\nimport Feature from 'ol/Feature';\nimport { Style, Stroke, Fill, Text } from 'ol/style';\nimport { LineString, Polygon as PolygonGeom } from 'ol/geom';\nimport { mergePolygons } from '../geom/polygonMerge.js';\nimport { showToast } from '../toast.js';\n\n// ── Styles ───────────────────────────────────────────────────────────────────\n\nconst HIGHLIGHT_A = new Style({\n stroke: new Stroke({ color: '#0ea5e9', width: 3 }),\n fill: new Fill({ color: 'rgba(14,165,233,0.15)' }),\n});\n\nconst HIGHLIGHT_B = new Style({\n stroke: new Stroke({ color: '#f59e0b', width: 3 }),\n fill: new Fill({ color: 'rgba(245,158,11,0.15)' }),\n});\n\n// Labelled versions for permanent highlights (shown after selection)\nconst LABEL_A = new Style({\n stroke: new Stroke({ color: '#0ea5e9', width: 3 }),\n fill: new Fill({ color: 'rgba(14,165,233,0.15)' }),\n text: new Text({\n text: 'A',\n font: 'bold 22px Exo, sans-serif',\n fill: new Fill({ color: '#0ea5e9' }),\n stroke: new Stroke({ color: '#fff', width: 4 }),\n overflow: true,\n }),\n});\n\nconst LABEL_B = new Style({\n stroke: new Stroke({ color: '#f59e0b', width: 3 }),\n fill: new Fill({ color: 'rgba(245,158,11,0.15)' }),\n text: new Text({\n text: 'B',\n font: 'bold 22px Exo, sans-serif',\n fill: new Fill({ color: '#f59e0b' }),\n stroke: new Stroke({ color: '#fff', width: 4 }),\n overflow: true,\n }),\n});\n\nconst EDGE_STYLE = new Style({\n stroke: new Stroke({ color: '#ec4899', width: 4, lineDash: [10, 6] }),\n});\n\nconst MERGE_STYLE = new Style({\n stroke: new Stroke({ color: '#10b981', width: 2.5 }),\n fill: new Fill({ color: 'rgba(16,185,129,0.3)' }),\n});\n\n// ── Interaction ──────────────────────────────────────────────────────────────\n\nexport class PolygonMergeInteraction extends ol_interaction_Interaction {\n /**\n * @param {Object} [options]\n * @param {number} [options.snapDistance=25] Pixel distance for hover detection.\n * @param {number} [options.tolerance=5] Map-unit tolerance for shared-edge matching.\n */\n constructor(options = {}) {\n super({\n handleEvent: (e) => this._handleEvent(e),\n });\n\n this.snapDistance_ = options.snapDistance || 25;\n this.tolerance_ = options.tolerance || 5;\n\n // Phase: 'select_a' | 'select_b' | 'click_edge_a' | 'click_edge_b'\n this._phase = 'select_a';\n\n // Selected features and their sources\n this._featureA = null;\n this._sourceA = null;\n this._featureB = null;\n this._sourceB = null;\n\n // Clicked edge coordinates (map coords)\n this._edgeClickA = null;\n this._edgeClickB = null;\n\n // Overlay for polygon highlights\n this._highlightSource = new VectorSource({ useSpatialIndex: false });\n this._highlightLayer = new VectorLayer({\n source: this._highlightSource,\n displayInLayerSwitcher: false,\n style: (f) => f.get('_highlightStyle') || HIGHLIGHT_A,\n });\n\n // Overlay for edge highlights\n this._edgeSource = new VectorSource({ useSpatialIndex: false });\n this._edgeLayer = new VectorLayer({\n source: this._edgeSource,\n displayInLayerSwitcher: false,\n style: EDGE_STYLE,\n });\n }\n\n /* ------------------------------------------------------------------ */\n /* Map lifecycle */\n /* ------------------------------------------------------------------ */\n\n setMap(map) {\n if (this.getMap()) {\n this.getMap().removeLayer(this._highlightLayer);\n this.getMap().removeLayer(this._edgeLayer);\n }\n super.setMap(map);\n if (map) {\n this._highlightLayer.setMap(map);\n this._edgeLayer.setMap(map);\n }\n }\n\n setActive(active) {\n super.setActive(active);\n if (!active) this._reset();\n }\n\n /* ------------------------------------------------------------------ */\n /* Source helpers */\n /* ------------------------------------------------------------------ */\n\n _getSources() {\n if (!this.getMap()) return [];\n const sources = [];\n const collect = (layers) => {\n layers.forEach((layer) => {\n if (layer.getVisible()) {\n if (layer.getSource && layer.getSource() instanceof VectorSource) {\n sources.push(layer.getSource());\n } else if (layer.getLayers) {\n collect(layer.getLayers());\n }\n }\n });\n };\n collect(this.getMap().getLayers());\n return sources;\n }\n\n /* ------------------------------------------------------------------ */\n /* Event router */\n /* ------------------------------------------------------------------ */\n\n _handleEvent(e) {\n if (!this.getActive()) return true;\n\n // Escape cancels at any phase\n if (e.type === 'keydown' && e.originalEvent?.key === 'Escape') {\n this._reset();\n return false;\n }\n\n switch (this._phase) {\n case 'select_a':\n if (e.type === 'pointermove') return this._onSelectMove(e, null);\n if (e.type === 'singleclick') return this._onSelectAClick(e);\n break;\n case 'select_b':\n if (e.type === 'pointermove') return this._onSelectMove(e, this._featureA);\n if (e.type === 'singleclick') return this._onSelectBClick(e);\n break;\n case 'click_edge_a':\n if (e.type === 'pointermove') return this._onEdgeMove(e, this._featureA);\n if (e.type === 'singleclick') return this._onEdgeAClick(e);\n break;\n case 'click_edge_b':\n if (e.type === 'pointermove') return this._onEdgeMove(e, this._featureB);\n if (e.type === 'singleclick') return this._onEdgeBClick(e);\n break;\n }\n return true;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 1 & 2: SELECT polygons */\n /* ------------------------------------------------------------------ */\n\n _onSelectMove(e, skipFeature) {\n const map = this.getMap();\n if (!map) return true;\n\n // Keep existing highlights for already-selected polygons\n this._highlightSource.clear();\n this._edgeSource.clear();\n this._rebuildHighlights();\n\n const hit = this._closestPolygon(e, skipFeature);\n if (hit) {\n const style = this._phase === 'select_a' ? HIGHLIGHT_A : HIGHLIGHT_B;\n const clone = hit.feature.clone();\n clone.set('_highlightStyle', style);\n this._highlightSource.addFeature(clone);\n map.getTargetElement().style.cursor = 'pointer';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onSelectAClick(e) {\n const hit = this._closestPolygon(e, null);\n if (!hit) return true;\n\n this._featureA = hit.feature;\n this._sourceA = hit.source;\n this._phase = 'select_b';\n\n this._rebuildHighlights();\n return false;\n }\n\n _onSelectBClick(e) {\n const hit = this._closestPolygon(e, this._featureA);\n if (!hit) return true;\n\n this._featureB = hit.feature;\n this._sourceB = hit.source;\n this._phase = 'click_edge_a';\n\n this._rebuildHighlights();\n this.getMap().getTargetElement().style.cursor = 'crosshair';\n return false;\n }\n\n /**\n * Find the closest polygon feature within snap distance.\n * Optionally skip a feature (used in phase 2 to avoid re-selecting A).\n */\n _closestPolygon(e, skipFeature) {\n let best = null;\n let bestDist = this.snapDistance_ + 1;\n\n for (const source of this._getSources()) {\n const feat = source.getClosestFeatureToCoordinate(e.coordinate);\n if (!feat) continue;\n if (skipFeature && feat === skipFeature) continue;\n const geom = feat.getGeometry();\n if (!geom) continue;\n const type = geom.getType();\n if (type !== 'Polygon' && type !== 'MultiPolygon') continue;\n\n const closest = geom.getClosestPoint(e.coordinate);\n const line = new LineString([e.coordinate, closest]);\n const distPx = line.getLength() / e.frameState.viewState.resolution;\n\n if (distPx < bestDist) {\n bestDist = distPx;\n best = { feature: feat, source, coord: closest };\n }\n }\n return best;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 3 & 4: CLICK edges */\n /* ------------------------------------------------------------------ */\n\n _onEdgeMove(e, feature) {\n const map = this.getMap();\n if (!map) return true;\n\n this._edgeSource.clear();\n\n const edge = this._closestEdgeSegment(feature, e);\n if (edge) {\n const edgeFeat = new Feature(new LineString([edge.segStart, edge.segEnd]));\n this._edgeSource.addFeature(edgeFeat);\n map.getTargetElement().style.cursor = 'crosshair';\n }\n return true;\n }\n\n _onEdgeAClick(e) {\n this._edgeClickA = e.coordinate;\n this._phase = 'click_edge_b';\n this._edgeSource.clear();\n return false;\n }\n\n _onEdgeBClick(e) {\n this._edgeClickB = e.coordinate;\n this._performMerge();\n return false;\n }\n\n /**\n * Find the closest edge segment of a polygon feature to the cursor.\n */\n _closestEdgeSegment(feature, e) {\n const geom = feature.getGeometry();\n let ring;\n if (geom.getType() === 'Polygon') {\n ring = geom.getCoordinates()[0];\n } else if (geom.getType() === 'MultiPolygon') {\n ring = geom.getCoordinates()[0][0];\n } else {\n return null;\n }\n\n const resolution = e.frameState.viewState.resolution;\n let bestDist = Infinity;\n let bestSeg = null;\n const n = ring.length - 1;\n\n for (let i = 0; i < n; i++) {\n const a = ring[i];\n const b = ring[i + 1];\n const dx = b[0] - a[0], dy = b[1] - a[1];\n const lenSq = dx * dx + dy * dy;\n if (lenSq < 1e-20) continue;\n\n let t = ((e.coordinate[0] - a[0]) * dx + (e.coordinate[1] - a[1]) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n const projX = a[0] + t * dx, projY = a[1] + t * dy;\n const distPx = Math.sqrt((e.coordinate[0] - projX) ** 2 + (e.coordinate[1] - projY) ** 2) / resolution;\n\n if (distPx < bestDist) {\n bestDist = distPx;\n bestSeg = { segStart: a, segEnd: b };\n }\n }\n return bestDist <= this.snapDistance_ ? bestSeg : null;\n }\n\n /* ------------------------------------------------------------------ */\n /* Merge logic */\n /* ------------------------------------------------------------------ */\n\n _performMerge() {\n const featureA = this._featureA;\n const featureB = this._featureB;\n const sourceA = this._sourceA;\n const sourceB = this._sourceB;\n\n // Extract polygon coordinates\n const geomA = featureA.getGeometry();\n const geomB = featureB.getGeometry();\n const coordsA = geomA.getType() === 'Polygon' ? geomA.getCoordinates() : geomA.getCoordinates()[0];\n const coordsB = geomB.getType() === 'Polygon' ? geomB.getCoordinates() : geomB.getCoordinates()[0];\n\n const result = mergePolygons(coordsA, coordsB, this._edgeClickA, this._edgeClickB, this.tolerance_);\n\n if (!result.coords) {\n showToast(result.error || 'Merge failed — try clicking on the shared boundary.', 'error', 5000);\n // Return to edge click phase for retry\n this._edgeClickA = null;\n this._edgeClickB = null;\n this._phase = 'click_edge_a';\n this._edgeSource.clear();\n return;\n }\n\n // Create merged feature (clone A for default properties)\n const mergedFeature = featureA.clone();\n mergedFeature.setGeometry(new PolygonGeom(result.coords));\n mergedFeature.setStyle(MERGE_STYLE);\n\n // Dispatch beforemerge events\n const evtData = {\n type: 'beforemerge',\n original: [featureA, featureB],\n merged: mergedFeature,\n };\n this.dispatchEvent(evtData);\n sourceA.dispatchEvent({ ...evtData });\n if (sourceB !== sourceA) {\n sourceB.dispatchEvent({ ...evtData });\n }\n\n // Replace originals with merged. Group the two removes + one add into a\n // single UndoRedo block (map-level undoblockstart/undoblockend) so the\n // whole merge — across both source layers — is reversed by ONE undo press.\n const mergeMap = this.getMap();\n mergeMap?.dispatchEvent('undoblockstart');\n sourceA.removeFeature(featureA);\n sourceB.removeFeature(featureB);\n sourceA.addFeature(mergedFeature);\n mergeMap?.dispatchEvent('undoblockend');\n\n // Dispatch aftermerge events\n const afterEvt = {\n type: 'aftermerge',\n original: [featureA, featureB],\n merged: mergedFeature,\n };\n this.dispatchEvent(afterEvt);\n sourceA.dispatchEvent({ ...afterEvt });\n if (sourceB !== sourceA) {\n sourceB.dispatchEvent({ ...afterEvt });\n }\n\n // If both features were parcels, fire mergedparcel so MapView can show the UPN chooser\n const isParcelA = featureA.get('_layerType') === 'parcel';\n const isParcelB = featureB.get('_layerType') === 'parcel';\n if (isParcelA && isParcelB) {\n this.dispatchEvent({\n type: 'mergedparcel',\n merged: mergedFeature,\n propsA: featureA.getProperties(),\n propsB: featureB.getProperties(),\n coordinate: this._edgeClickA,\n });\n showToast('Polygons merged — choose which identifier to keep.', 'success');\n } else {\n showToast('Polygons merged successfully.', 'success');\n }\n\n // Clean up\n this._reset();\n }\n\n /* ------------------------------------------------------------------ */\n /* Highlight management */\n /* ------------------------------------------------------------------ */\n\n /**\n * Rebuild the permanent highlights for already-selected polygons.\n */\n _rebuildHighlights() {\n // Remove previous non-hover highlights\n const toRemove = [];\n this._highlightSource.getFeatures().forEach((f) => {\n if (f.get('_permanent')) toRemove.push(f);\n });\n toRemove.forEach((f) => this._highlightSource.removeFeature(f));\n\n if (this._featureA) {\n const cloneA = this._featureA.clone();\n cloneA.set('_highlightStyle', LABEL_A);\n cloneA.set('_permanent', true);\n this._highlightSource.addFeature(cloneA);\n }\n if (this._featureB) {\n const cloneB = this._featureB.clone();\n cloneB.set('_highlightStyle', LABEL_B);\n cloneB.set('_permanent', true);\n this._highlightSource.addFeature(cloneB);\n }\n }\n\n /* ------------------------------------------------------------------ */\n /* Reset */\n /* ------------------------------------------------------------------ */\n\n _reset() {\n this._phase = 'select_a';\n this._featureA = null;\n this._sourceA = null;\n this._featureB = null;\n this._sourceB = null;\n this._edgeClickA = null;\n this._edgeClickB = null;\n this._highlightSource.clear();\n this._edgeSource.clear();\n\n const map = this.getMap();\n if (map) {\n map.getTargetElement().style.cursor = '';\n }\n }\n}\n","/**\n * Pure geometry functions for dividing a polygon into N equal-area pieces.\n *\n * No OpenLayers dependency — operates on raw coordinate arrays.\n *\n * The algorithm finds the polygon's longest edge, then places N-1 cutting\n * lines perpendicular to that edge. Each cutting-line position is found\n * via binary search so that the piece it cuts off has exactly 1/N of the\n * remaining area. The actual cut is delegated to `splitPolygonByLine()`.\n */\n\nimport { splitPolygonByLine } from './polygonSplit.js';\n\n// ── Utility helpers (self-contained) ─────────────────────────────────────────\n\nfunction dist2(a, b) {\n return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2;\n}\n\n/**\n * Signed area of a ring (shoelace formula).\n */\nfunction signedArea(ring) {\n let area = 0;\n for (let i = 0, n = ring.length; i < n - 1; i++) {\n area += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];\n }\n return area / 2;\n}\n\n/**\n * Absolute polygon area, accounting for holes.\n */\nfunction polygonArea(coords) {\n let area = Math.abs(signedArea(coords[0]));\n for (let i = 1; i < coords.length; i++) {\n area -= Math.abs(signedArea(coords[i]));\n }\n return area;\n}\n\n/**\n * Find the longest edge of a ring and return direction vectors.\n *\n * @param {number[][]} ring Closed ring\n * @returns {{ p0: number[], p1: number[], along: number[], perp: number[] }}\n * `along` = unit vector along the longest edge,\n * `perp` = unit vector perpendicular to `along` (rotated 90° CCW)\n */\nfunction longestEdge(ring) {\n const n = ring.length - 1; // unique vertices\n let bestLen = -1;\n let bestI = 0;\n\n for (let i = 0; i < n; i++) {\n const d = dist2(ring[i], ring[i + 1]);\n if (d > bestLen) {\n bestLen = d;\n bestI = i;\n }\n }\n\n const p0 = ring[bestI];\n const p1 = ring[bestI + 1];\n const len = Math.sqrt(bestLen);\n const along = [(p1[0] - p0[0]) / len, (p1[1] - p0[1]) / len];\n // Perpendicular: rotate 90° CCW\n const perp = [-along[1], along[0]];\n\n return { p0, p1, along, perp };\n}\n\n/**\n * Build a cutting line perpendicular to `along` at parameter `t`.\n *\n * The line passes through `origin + t * along` and extends `extent` units\n * in both `perp` directions — long enough to fully cross the polygon.\n */\nfunction makeCuttingLine(origin, along, perp, t, extent) {\n const cx = origin[0] + t * along[0];\n const cy = origin[1] + t * along[1];\n return [\n [cx - extent * perp[0], cy - extent * perp[1]],\n [cx + extent * perp[0], cy + extent * perp[1]],\n ];\n}\n\n/**\n * Project the centroid of a polygon's exterior ring onto the `along` axis.\n * Returns the scalar parameter `t` relative to `origin`.\n */\nfunction centroidT(coords, origin, along) {\n const ring = coords[0];\n const n = ring.length - 1;\n let sx = 0, sy = 0;\n for (let i = 0; i < n; i++) {\n sx += ring[i][0];\n sy += ring[i][1];\n }\n const cx = sx / n - origin[0];\n const cy = sy / n - origin[1];\n return cx * along[0] + cy * along[1];\n}\n\n// ── Main export ──────────────────────────────────────────────────────────────\n\n/**\n * Divide a polygon into N equal-area pieces by parallel cuts perpendicular\n * to a user-selected edge.\n *\n * @param {number[][][]} polygonCoords Polygon coordinates [ring, ...holes]\n * @param {number} n Number of pieces (must be >= 1)\n * @param {number[][]} edgeCoords The selected edge `[p0, p1]` — cuts will be\n * perpendicular to this edge direction.\n * @returns {{ pieces: number[][][][], error?: undefined } | { pieces: null, error: string }}\n */\nexport function dividePolygon(polygonCoords, n, edgeCoords) {\n if (!Number.isInteger(n) || n < 1) {\n return { pieces: null, error: 'Number of divisions must be a positive integer.' };\n }\n if (n === 1) {\n return { pieces: [polygonCoords] };\n }\n\n const ring = polygonCoords[0];\n const totalArea = polygonArea(polygonCoords);\n\n if (totalArea < 1e-6) {\n return { pieces: null, error: 'Polygon has no measurable area.' };\n }\n\n // 1. Determine cutting direction from the selected edge\n let p0, along, perp;\n if (edgeCoords && edgeCoords.length === 2) {\n p0 = edgeCoords[0];\n const dx = edgeCoords[1][0] - edgeCoords[0][0];\n const dy = edgeCoords[1][1] - edgeCoords[0][1];\n const len = Math.sqrt(dx * dx + dy * dy);\n if (len < 1e-10) {\n return { pieces: null, error: 'Selected edge has zero length.' };\n }\n along = [dx / len, dy / len];\n perp = [-along[1], along[0]];\n } else {\n // Fallback: use longest edge\n const edge = longestEdge(ring);\n p0 = edge.p0;\n along = edge.along;\n perp = edge.perp;\n }\n const origin = p0;\n\n // 2. Project all vertices onto the `along` axis to find extent\n const nVerts = ring.length - 1;\n let tMin = Infinity, tMax = -Infinity;\n for (let i = 0; i < nVerts; i++) {\n const dx = ring[i][0] - origin[0];\n const dy = ring[i][1] - origin[1];\n const t = dx * along[0] + dy * along[1];\n if (t < tMin) tMin = t;\n if (t > tMax) tMax = t;\n }\n\n // Cutting line extent: enough to cross the polygon in the `perp` direction\n let perpMin = Infinity, perpMax = -Infinity;\n for (let i = 0; i < nVerts; i++) {\n const dx = ring[i][0] - origin[0];\n const dy = ring[i][1] - origin[1];\n const p = dx * perp[0] + dy * perp[1];\n if (p < perpMin) perpMin = p;\n if (p > perpMax) perpMax = p;\n }\n const extent = (perpMax - perpMin) * 1.5; // generous overshoot\n\n // 3. Iteratively cut pieces\n const pieces = [];\n let remaining = polygonCoords;\n let remainingCount = n;\n\n for (let i = 0; i < n - 1; i++) {\n const remainingArea = polygonArea(remaining);\n const targetArea = remainingArea / remainingCount;\n\n // Re-project the remaining polygon to get its current t-range\n const remRing = remaining[0];\n const remN = remRing.length - 1;\n let rMin = Infinity, rMax = -Infinity;\n for (let j = 0; j < remN; j++) {\n const dx = remRing[j][0] - origin[0];\n const dy = remRing[j][1] - origin[1];\n const t = dx * along[0] + dy * along[1];\n if (t < rMin) rMin = t;\n if (t > rMax) rMax = t;\n }\n\n // Binary search for the cutting position\n let lo = rMin;\n let hi = rMax;\n let bestT = (lo + hi) / 2;\n let bestPiece = null;\n let bestRemaining = null;\n let bestError = Infinity;\n\n for (let iter = 0; iter < 40; iter++) {\n const mid = (lo + hi) / 2;\n const line = makeCuttingLine(origin, along, perp, mid, extent);\n const result = splitPolygonByLine(remaining, line);\n\n if (!result) {\n // Cutting line didn't produce a valid split — nudge and retry\n // Try slightly shifted positions\n const nudge = (hi - lo) * 0.01;\n const lineA = makeCuttingLine(origin, along, perp, mid + nudge, extent);\n const resultA = splitPolygonByLine(remaining, lineA);\n if (resultA) {\n const [halfA, halfB] = resultA;\n const tA = centroidT(halfA, origin, along);\n const tB = centroidT(halfB, origin, along);\n const nearPiece = tA < tB ? halfA : halfB;\n const farPiece = tA < tB ? halfB : halfA;\n const nearArea = polygonArea(nearPiece);\n const err = Math.abs(nearArea - targetArea);\n if (err < bestError) {\n bestError = err;\n bestT = mid + nudge;\n bestPiece = nearPiece;\n bestRemaining = farPiece;\n }\n }\n // Try the other direction\n const lineB = makeCuttingLine(origin, along, perp, mid - nudge, extent);\n const resultB = splitPolygonByLine(remaining, lineB);\n if (resultB) {\n const [halfA, halfB] = resultB;\n const tA = centroidT(halfA, origin, along);\n const tB = centroidT(halfB, origin, along);\n const nearPiece = tA < tB ? halfA : halfB;\n const farPiece = tA < tB ? halfB : halfA;\n const nearArea = polygonArea(nearPiece);\n const err = Math.abs(nearArea - targetArea);\n if (err < bestError) {\n bestError = err;\n bestT = mid - nudge;\n bestPiece = nearPiece;\n bestRemaining = farPiece;\n }\n }\n // Bisect anyway to keep converging\n lo = mid;\n continue;\n }\n\n const [halfA, halfB] = result;\n const tA = centroidT(halfA, origin, along);\n const tB = centroidT(halfB, origin, along);\n const nearPiece = tA < tB ? halfA : halfB;\n const farPiece = tA < tB ? halfB : halfA;\n const nearArea = polygonArea(nearPiece);\n\n const err = Math.abs(nearArea - targetArea);\n if (err < bestError) {\n bestError = err;\n bestT = mid;\n bestPiece = nearPiece;\n bestRemaining = farPiece;\n }\n\n // Converged?\n if (err / remainingArea < 0.001) break;\n\n // Adjust search range\n if (nearArea < targetArea) {\n lo = mid; // need to cut farther out\n } else {\n hi = mid; // need to cut closer\n }\n }\n\n if (!bestPiece || !bestRemaining) {\n return {\n pieces: null,\n error: `Could not find a valid cut for piece ${i + 1} of ${n}. The polygon shape may be too irregular for equal division.`,\n };\n }\n\n pieces.push(bestPiece);\n remaining = bestRemaining;\n remainingCount--;\n }\n\n // The last remaining piece is the Nth piece\n pieces.push(remaining);\n\n return { pieces };\n}\n","/**\n * PolygonDivideInteraction\n *\n * A three-phase OpenLayers interaction for dividing a polygon into N\n * equal-area pieces:\n * Phase 1 – SELECT: hover to highlight, click to select a polygon\n * Phase 2 – EDGE: hover to highlight edges, click to pick the divide\n * direction (cuts will be perpendicular to this edge)\n * Phase 3 – FORM: wait for the popup form to call performDivide(n)\n *\n * After a successful divide the original feature is removed and N new\n * coloured features are added. The interaction fires `beforedivide` and\n * `afterdivide` events compatible with ol-ext's UndoRedo.\n */\n\nimport ol_interaction_Interaction from 'ol/interaction/Interaction';\nimport VectorSource from 'ol/source/Vector';\nimport VectorLayer from 'ol/layer/Vector';\nimport Feature from 'ol/Feature';\nimport { Style, Stroke, Fill } from 'ol/style';\nimport { LineString, Polygon as PolygonGeom } from 'ol/geom';\nimport { dividePolygon } from '../geom/polygonDivide.js';\nimport { showToast } from '../toast.js';\n\n// Highlight style for the selected polygon (phase 1)\nconst HIGHLIGHT_STYLE = new Style({\n stroke: new Stroke({ color: '#0ea5e9', width: 3 }),\n fill: new Fill({ color: 'rgba(14,165,233,0.15)' }),\n});\n\n// Style for the hovered edge (phase 2)\nconst EDGE_STYLE = new Style({\n stroke: new Stroke({ color: '#8b5cf6', width: 4, lineDash: [10, 6] }),\n});\n\n/**\n * Generate N visually distinct colours using evenly-spaced HSL hues.\n */\nfunction pieceColors(n) {\n const colors = [];\n for (let i = 0; i < n; i++) {\n const hue = Math.round((i * 360) / n);\n colors.push({\n stroke: `hsl(${hue}, 70%, 45%)`,\n fill: `hsla(${hue}, 70%, 55%, 0.25)`,\n });\n }\n return colors;\n}\n\nexport class PolygonDivideInteraction extends ol_interaction_Interaction {\n /**\n * @param {Object} options\n * @param {VectorSource|VectorSource[]} [options.sources] Specific sources\n * to search. If omitted the interaction searches all visible vector layers.\n * @param {number} [options.snapDistance=25] Pixel distance for hover.\n */\n constructor(options = {}) {\n super({\n handleEvent: (e) => this._handleEvent(e),\n });\n\n this.snapDistance_ = options.snapDistance || 25;\n this._sources = options.sources\n ? (Array.isArray(options.sources) ? options.sources : [options.sources])\n : null;\n\n // Phase: 'select' | 'edge' | 'form' | 'pick'\n this._phase = 'select';\n this._selectedFeature = null;\n this._selectedSource = null;\n this._selectedEdge = null; // [p0, p1] — the edge the user clicked\n this._dividedFeatures = null; // features created after divide (for pick phase)\n\n // Overlay layer for polygon highlight\n this._overlaySource = new VectorSource({ useSpatialIndex: false });\n this._overlayLayer = new VectorLayer({\n source: this._overlaySource,\n displayInLayerSwitcher: false,\n style: HIGHLIGHT_STYLE,\n });\n\n // Overlay layer for edge highlight\n this._edgeSource = new VectorSource({ useSpatialIndex: false });\n this._edgeLayer = new VectorLayer({\n source: this._edgeSource,\n displayInLayerSwitcher: false,\n style: EDGE_STYLE,\n });\n }\n\n /* ------------------------------------------------------------------ */\n /* Map lifecycle */\n /* ------------------------------------------------------------------ */\n\n setMap(map) {\n if (this.getMap()) {\n this.getMap().removeLayer(this._overlayLayer);\n this.getMap().removeLayer(this._edgeLayer);\n }\n super.setMap(map);\n if (map) {\n this._overlayLayer.setMap(map);\n this._edgeLayer.setMap(map);\n }\n }\n\n setActive(active) {\n super.setActive(active);\n if (!active) {\n this._reset();\n }\n }\n\n /* ------------------------------------------------------------------ */\n /* Source helpers */\n /* ------------------------------------------------------------------ */\n\n _getSources() {\n if (this._sources) return this._sources;\n if (!this.getMap()) return [];\n const sources = [];\n const collect = (layers) => {\n layers.forEach((layer) => {\n if (layer.getVisible()) {\n if (layer.getSource && layer.getSource() instanceof VectorSource) {\n sources.push(layer.getSource());\n } else if (layer.getLayers) {\n collect(layer.getLayers());\n }\n }\n });\n };\n collect(this.getMap().getLayers());\n return sources;\n }\n\n /* ------------------------------------------------------------------ */\n /* Event router */\n /* ------------------------------------------------------------------ */\n\n _handleEvent(e) {\n if (!this.getActive()) return true;\n\n // Escape cancels at any phase\n if (e.type === 'keydown' && e.originalEvent?.key === 'Escape') {\n if (this._phase === 'form') {\n this.cancelDivide();\n } else {\n this._reset();\n }\n return false;\n }\n\n if (this._phase === 'select') {\n if (e.type === 'pointermove') return this._onSelectMove(e);\n if (e.type === 'singleclick') return this._onSelectClick(e);\n }\n\n if (this._phase === 'edge') {\n if (e.type === 'pointermove') return this._onEdgeMove(e);\n if (e.type === 'singleclick') return this._onEdgeClick(e);\n }\n\n if (this._phase === 'pick') {\n if (e.type === 'pointermove') return this._onPickMove(e);\n if (e.type === 'singleclick') return this._onPickClick(e);\n }\n\n return true;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 1: SELECT polygon */\n /* ------------------------------------------------------------------ */\n\n _onSelectMove(e) {\n const map = this.getMap();\n if (!map) return true;\n\n this._overlaySource.clear();\n\n const hit = this._closestPolygon(e);\n if (hit) {\n const clone = hit.feature.clone();\n this._overlaySource.addFeature(clone);\n map.getTargetElement().style.cursor = 'pointer';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onSelectClick(e) {\n const hit = this._closestPolygon(e);\n if (!hit) return true;\n\n this._selectedFeature = hit.feature;\n this._selectedSource = hit.source;\n\n // Keep polygon highlight visible during edge phase\n this._overlaySource.clear();\n const clone = hit.feature.clone();\n clone.set('_permanent', true);\n this._overlaySource.addFeature(clone);\n\n this._phase = 'edge';\n showToast('Click the edge to divide along.', 'info', 3000);\n return false;\n }\n\n _closestPolygon(e) {\n let best = null;\n let bestDist = this.snapDistance_ + 1;\n\n for (const source of this._getSources()) {\n const feat = source.getClosestFeatureToCoordinate(e.coordinate);\n if (!feat) continue;\n const geom = feat.getGeometry();\n if (!geom) continue;\n const type = geom.getType();\n if (type !== 'Polygon' && type !== 'MultiPolygon') continue;\n\n const closest = geom.getClosestPoint(e.coordinate);\n const line = new LineString([e.coordinate, closest]);\n const distPx = line.getLength() / e.frameState.viewState.resolution;\n\n if (distPx < bestDist) {\n bestDist = distPx;\n best = { feature: feat, source };\n }\n }\n return best;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 2: EDGE selection */\n /* ------------------------------------------------------------------ */\n\n _onEdgeMove(e) {\n const map = this.getMap();\n if (!map) return true;\n\n this._edgeSource.clear();\n\n const edge = this._closestEdgeSegment(this._selectedFeature, e);\n if (edge) {\n const edgeFeat = new Feature(new LineString([edge.segStart, edge.segEnd]));\n this._edgeSource.addFeature(edgeFeat);\n map.getTargetElement().style.cursor = 'crosshair';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onEdgeClick(e) {\n const edge = this._closestEdgeSegment(this._selectedFeature, e);\n if (!edge) return true;\n\n this._selectedEdge = [edge.segStart, edge.segEnd];\n this._edgeSource.clear();\n\n this._phase = 'form';\n\n // Dispatch divideform so MapView can show the popup\n const geom = this._selectedFeature.getGeometry();\n const ext = geom.getExtent();\n const center = [(ext[0] + ext[2]) / 2, (ext[1] + ext[3]) / 2];\n\n this.dispatchEvent({\n type: 'divideform',\n feature: this._selectedFeature,\n source: this._selectedSource,\n coordinate: center,\n });\n\n return false;\n }\n\n /**\n * Find the closest edge segment of a polygon feature to the cursor.\n */\n _closestEdgeSegment(feature, e) {\n const geom = feature.getGeometry();\n let ring;\n if (geom.getType() === 'Polygon') {\n ring = geom.getCoordinates()[0];\n } else if (geom.getType() === 'MultiPolygon') {\n ring = geom.getCoordinates()[0][0];\n } else {\n return null;\n }\n\n const resolution = e.frameState.viewState.resolution;\n let bestDist = Infinity;\n let bestSeg = null;\n const n = ring.length - 1;\n\n for (let i = 0; i < n; i++) {\n const a = ring[i];\n const b = ring[i + 1];\n const dx = b[0] - a[0], dy = b[1] - a[1];\n const lenSq = dx * dx + dy * dy;\n if (lenSq < 1e-20) continue;\n\n let t = ((e.coordinate[0] - a[0]) * dx + (e.coordinate[1] - a[1]) * dy) / lenSq;\n t = Math.max(0, Math.min(1, t));\n const projX = a[0] + t * dx, projY = a[1] + t * dy;\n const distPx = Math.sqrt((e.coordinate[0] - projX) ** 2 + (e.coordinate[1] - projY) ** 2) / resolution;\n\n if (distPx < bestDist) {\n bestDist = distPx;\n bestSeg = { segStart: a, segEnd: b };\n }\n }\n return bestDist <= this.snapDistance_ ? bestSeg : null;\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 3: FORM — called externally by the popup */\n /* ------------------------------------------------------------------ */\n\n /**\n * Divide the selected polygon into `n` equal-area pieces.\n * Called by the MapView popup's Confirm handler.\n *\n * @param {number} n Number of pieces (>= 2)\n */\n performDivide(n) {\n if (this._phase !== 'form' || !this._selectedFeature) return;\n\n const feature = this._selectedFeature;\n const source = this._selectedSource;\n const geom = feature.getGeometry();\n\n let polygonCoords;\n if (geom.getType() === 'Polygon') {\n polygonCoords = geom.getCoordinates();\n } else if (geom.getType() === 'MultiPolygon') {\n polygonCoords = geom.getCoordinates()[0];\n }\n\n const result = dividePolygon(polygonCoords, n, this._selectedEdge);\n\n if (!result.pieces) {\n showToast(result.error || 'Division failed.', 'error', 5000);\n this._reset();\n return;\n }\n\n // Create N new coloured features\n const colors = pieceColors(n);\n const newFeatures = result.pieces.map((coords, i) => {\n const f = feature.clone();\n f.setGeometry(new PolygonGeom(coords));\n f.setStyle(new Style({\n stroke: new Stroke({ color: colors[i].stroke, width: 2.5 }),\n fill: new Fill({ color: colors[i].fill }),\n }));\n return f;\n });\n\n // Dispatch beforedivide (UndoRedo compatible)\n const evtData = {\n type: 'beforedivide',\n original: feature,\n features: newFeatures,\n };\n this.dispatchEvent(evtData);\n source.dispatchEvent({ ...evtData });\n\n // Replace original with pieces. Group the remove + all the adds into a\n // single UndoRedo block (map-level undoblockstart/undoblockend) so the\n // whole divide is reversed by ONE undo press regardless of piece count.\n const divideMap = this.getMap();\n divideMap?.dispatchEvent('undoblockstart');\n source.removeFeature(feature);\n for (const f of newFeatures) {\n source.addFeature(f);\n }\n divideMap?.dispatchEvent('undoblockend');\n\n // Dispatch afterdivide\n const afterEvt = {\n type: 'afterdivide',\n original: feature,\n features: newFeatures,\n };\n this.dispatchEvent(afterEvt);\n source.dispatchEvent({ ...afterEvt });\n\n // If original was a parcel, enter pick phase for UPN assignment\n const isParcel = feature.get('_layerType') === 'parcel';\n if (isParcel) {\n this._dividedFeatures = newFeatures;\n this._phase = 'pick';\n showToast('Click the polygon that should keep the original identifier.', 'info', 5000);\n\n this.dispatchEvent({\n type: 'dividedparcel',\n features: newFeatures,\n originalProps: feature.getProperties(),\n source,\n });\n } else {\n showToast(`Polygon divided into ${n} equal pieces.`, 'success');\n this._reset();\n }\n }\n\n /* ------------------------------------------------------------------ */\n /* Phase 4: PICK — select which piece keeps the UPN */\n /* ------------------------------------------------------------------ */\n\n _onPickMove(e) {\n const map = this.getMap();\n if (!map) return true;\n\n this._overlaySource.clear();\n\n // Highlight whichever divided piece is under the cursor\n const hit = this._closestDividedPiece(e);\n if (hit) {\n const clone = hit.clone();\n this._overlaySource.addFeature(clone);\n map.getTargetElement().style.cursor = 'pointer';\n } else {\n map.getTargetElement().style.cursor = '';\n }\n return true;\n }\n\n _onPickClick(e) {\n const hit = this._closestDividedPiece(e);\n if (!hit) return true;\n\n this.dispatchEvent({\n type: 'dividepick',\n picked: hit,\n features: this._dividedFeatures,\n });\n\n this._reset();\n return false;\n }\n\n /**\n * Find the closest divided piece to the cursor.\n */\n _closestDividedPiece(e) {\n if (!this._dividedFeatures) return null;\n let best = null;\n let bestDist = this.snapDistance_ + 1;\n\n for (const feat of this._dividedFeatures) {\n const geom = feat.getGeometry();\n if (!geom) continue;\n const closest = geom.getClosestPoint(e.coordinate);\n const line = new LineString([e.coordinate, closest]);\n const distPx = line.getLength() / e.frameState.viewState.resolution;\n if (distPx < bestDist) {\n bestDist = distPx;\n best = feat;\n }\n }\n return best;\n }\n\n /**\n * Cancel the divide operation and return to select phase.\n * Called by the MapView popup's Cancel handler.\n */\n cancelDivide() {\n this.dispatchEvent({ type: 'dividecancel' });\n this._reset();\n }\n\n /* ------------------------------------------------------------------ */\n /* Reset */\n /* ------------------------------------------------------------------ */\n\n _reset() {\n this._phase = 'select';\n this._selectedFeature = null;\n this._selectedSource = null;\n this._selectedEdge = null;\n this._dividedFeatures = null;\n this._overlaySource.clear();\n this._edgeSource.clear();\n\n const map = this.getMap();\n if (map) {\n map.getTargetElement().style.cursor = '';\n }\n }\n}\n","/**\n * MapView Component\n *\n * OpenLayers map with ol-ext LayerSwitcher for base map selection.\n *\n * Usage:\n * import { MapView } from './components/MapView.js';\n *\n * const map = new MapView('map', {\n * center: [-1.5, 7.5], // Ghana\n * zoom: 7,\n * basemap: 'osm'\n * });\n *\n * map.onClick((lon, lat) => console.log('Clicked:', lon, lat));\n * map.addMarker(lon, lat, { name: 'Point A' });\n */\n\nimport Map from 'ol/Map';\nimport View from 'ol/View';\nimport Overlay from 'ol/Overlay';\nimport TileLayer from 'ol/layer/Tile';\nimport ImageLayer from 'ol/layer/Image';\nimport LayerGroup from 'ol/layer/Group';\nimport VectorLayer from 'ol/layer/Vector';\nimport VectorImageLayer from 'ol/layer/VectorImage';\nimport VectorSource from 'ol/source/Vector';\nimport ImageWMS from 'ol/source/ImageWMS';\nimport TileWMS from 'ol/source/TileWMS';\n// NOTE: Cloud-Optimized GeoTIFF support (ol/source/GeoTIFF + ol/layer/WebGLTile)\n// is imported lazily inside addCOGLayer(). The underlying geotiff.js library adds\n// ~100 kB to the bundle, which shouldn't be paid by field users who never open a\n// raster on a metered connection.\nimport OSM from 'ol/source/OSM';\nimport XYZ from 'ol/source/XYZ';\nimport { fromLonLat, toLonLat } from 'ol/proj';\nimport { Point, LineString, Polygon as PolygonGeom } from 'ol/geom';\nimport Feature from 'ol/Feature';\nimport { Style, Circle, Fill, Stroke, Text } from 'ol/style';\nimport GeoJSON from 'ol/format/GeoJSON';\nimport { getArea, getLength } from 'ol/sphere';\nimport { fromCircle } from 'ol/geom/Polygon';\nimport ScaleLine from 'ol/control/ScaleLine';\nimport { formatLength, formatLengthFull, formatArea, formatAreaFull } from '../units.js';\n\n// ol-ext LayerSwitcher\nimport LayerSwitcher from 'ol-ext/control/LayerSwitcher';\n\n// ol-ext SearchNominatim\nimport SearchNominatim from 'ol-ext/control/SearchNominatim';\n\n// ol-ext EditBar for drawing/editing features\nimport EditBar from 'ol-ext/control/EditBar';\nimport Bar from 'ol-ext/control/Bar';\nimport Button from 'ol-ext/control/Button';\n\n// ol-ext TouchCursor for touch-enabled devices\nimport TouchCursor from 'ol-ext/interaction/TouchCursor';\n\n// ol-ext ModifyFeature for cross-layer modification\nimport ModifyFeature from 'ol-ext/interaction/ModifyFeature';\n\n// ol-ext UndoRedo interaction\nimport UndoRedo from 'ol-ext/interaction/UndoRedo';\n\n// ol-ext SnapGuides — snaps drawing vertices to alignment guides\nimport SnapGuides from 'ol-ext/interaction/SnapGuides';\n\n// ol Select interaction (for custom multi-layer Select)\nimport Select from 'ol/interaction/Select';\nimport DragBox from 'ol/interaction/DragBox';\nimport { click as clickCondition, platformModifierKeyOnly, shiftKeyOnly } from 'ol/events/condition';\n\n// ol-ext Split interaction (for line splitting) and Toggle control\nimport Split from 'ol-ext/interaction/Split';\nimport Toggle from 'ol-ext/control/Toggle';\nimport TextButton from 'ol-ext/control/TextButton';\n\n// Custom polygon split interaction\nimport { PolygonSplitInteraction } from '../interactions/PolygonSplitInteraction.js';\n\n// Custom polygon merge interaction\nimport { PolygonMergeInteraction } from '../interactions/PolygonMergeInteraction.js';\n\n// Custom polygon divide interaction\nimport { PolygonDivideInteraction } from '../interactions/PolygonDivideInteraction.js';\n\n// Toast notifications\nimport { showToast } from '../toast.js';\n\n// CSS imports\nimport 'ol/ol.css';\nimport 'ol-ext/dist/ol-ext.css';\nimport '../styles/layerswitcher.css';\n\nexport class MapView {\n constructor(targetId, options = {}) {\n this.options = options;\n this.markerSource = new VectorSource();\n this.clickCallbacks = [];\n\n // Category emoji and label mapping\n // Add new categories here - they will automatically appear in the dropdown\n this.categoryEmojis = {\n 'default': { emoji: '📍', label: 'Default' },\n 'water': { emoji: '💧', label: 'Water Point' },\n 'school': { emoji: '🏫', label: 'School' },\n 'health': { emoji: '🏥', label: 'Health Facility' },\n 'market': { emoji: '🏪', label: 'Market' },\n 'other': { emoji: '📌', label: 'Other' }\n };\n\n // Helper to get emoji for a category\n this.getEmoji = (category) => {\n const cat = this.categoryEmojis[category];\n return cat ? cat.emoji : '📍';\n };\n\n // Helper to generate category options HTML for select dropdowns\n this.getCategoryOptionsHtml = () => {\n return Object.entries(this.categoryEmojis)\n .map(([key, { emoji, label }]) =>\n `${emoji} ${label} `\n )\n .join('\\n ');\n };\n\n // Create emoji style helper\n this.createEmojiStyle = (emoji, fontSize = 24) => {\n return new Style({\n text: new Text({\n text: emoji,\n font: `${fontSize}px sans-serif`,\n textBaseline: 'bottom',\n textAlign: 'center',\n offsetY: -5,\n }),\n });\n };\n\n // Default marker style (pin emoji)\n this.defaultStyle = this.createEmojiStyle('📍', 32);\n\n // Selected marker style (larger)\n this.selectedStyle = this.createEmojiStyle('📍', 42);\n\n // Initialize category styles with emojis\n this.categoryStyles = {};\n for (const [category, { emoji }] of Object.entries(this.categoryEmojis)) {\n this.categoryStyles[category] = this.createEmojiStyle(emoji, 32);\n }\n\n // Create base layers group\n const baseLayers = this.createBaseLayers(options.basemap || 'topo');\n\n // Markers layer — hidden at startup; the user enables it from the\n // LayerSwitcher when they want to see location markers / category pins.\n this.markersLayer = new VectorLayer({\n title: 'Markers',\n source: this.markerSource,\n style: (feature) => this.getFeatureStyle(feature),\n visible: false,\n });\n\n // Overlay layers group (for remote data like boundaries)\n this.overlayGroup = new LayerGroup({\n title: 'Overlays',\n });\n\n // Create map\n // Layer order (bottom → top): Base Maps, Markers, Overlays\n // MapTools will insert Measurements and Drawings between Markers and Overlays.\n // initEditBar() will insert its Drawings group above those.\n // Final LayerSwitcher order (top → bottom):\n // Overlays, Drawings, Measurements, Markers, Base Maps\n this.map = new Map({\n target: targetId,\n layers: [\n baseLayers,\n this.markersLayer,\n this.overlayGroup,\n ],\n view: new View({\n center: fromLonLat(options.center || [0, 0]),\n zoom: options.zoom || 2,\n minZoom: options.minZoom || 2,\n maxZoom: options.maxZoom || 19,\n })\n });\n\n // Add LayerSwitcher control\n const layerSwitcher = new LayerSwitcher({\n collapsed: true,\n mouseover: true,\n extent: true,\n trash: false,\n oninfo: null,\n });\n this.map.addControl(layerSwitcher);\n\n // Apply the LUSPA branded icon to the LayerSwitcher's collapse button.\n // Done in JS so the URL respects Vite's BASE_URL — survives deployment\n // under any sub-path.\n // NOTE: folder name is `app-icons`, NOT `icons` — Apache aliases `/icons/`\n // by default to its own directory-listing thumbnails, which would\n // intercept this request server-side.\n queueMicrotask(() => {\n const btn = layerSwitcher.element?.querySelector(':scope > button');\n if (btn) {\n const baseUrl = (import.meta.env?.BASE_URL || '/').replace(/\\/?$/, '/');\n btn.style.backgroundImage = `url('${baseUrl}app-icons/luspa-72x72.png')`;\n }\n });\n\n // ------------------------------------------------------------------\n // Decorate each layer's as it's rendered:\n // • inject a type-tag chip (WMS / XYZ / VEC / …) next to the label\n // • add a green \"+\" button to the \"External Source\" group header\n // After each draw cycle, refresh the panel chrome (active count badge\n // + footer reset button). Schedule once per cycle via a microtask.\n // ------------------------------------------------------------------\n let _lsChromeScheduled = false;\n layerSwitcher.on('drawlist', (evt) => {\n this._decorateLayerListItem(evt.layer, evt.li);\n\n if (!_lsChromeScheduled) {\n _lsChromeScheduled = true;\n queueMicrotask(() => {\n _lsChromeScheduled = false;\n this._refreshLayerSwitcherChrome(layerSwitcher);\n });\n }\n });\n\n // Re-render the chrome whenever any layer's visibility changes (so the\n // active-count badge updates even when the user toggles via the panel).\n this.map.getLayers().on('change', () => {\n this._refreshLayerSwitcherChrome(layerSwitcher);\n });\n // Hook visibility events on every layer (recursive into groups).\n this._wireLayerSwitcherVisibilityHooks(layerSwitcher);\n\n // Create the add-layer dialog (hidden by default)\n this._createAddLayerDialog();\n\n // Create the legend panel (shows legends for visible layers that have one)\n this._createLegendPanel();\n\n // Add ScaleBar control\n this.scaleBar = new ScaleLine({\n bar: true,\n steps: 4,\n text: true,\n minWidth: 140,\n });\n this.map.addControl(this.scaleBar);\n\n // GPS rendering layers (current position + recorded trail) and the\n // expandable \"My Location\" control (Locate Me + Record Trail sub-buttons).\n this._initGpsRendering();\n this._createLocationControl();\n\n // Dedicated base-map picker — sits above the My Location button\n this._createBaseMapPicker();\n\n // Add SearchNominatim control\n const searchNominatim = new SearchNominatim({\n placeholder: 'Search location...',\n typing: 300, // Delay before search (ms)\n minLength: 3, // Minimum characters to start search\n maxItems: 10, // Maximum results to show\n collapsed: true, // Start collapsed\n // Limit search to improve relevance (can be adjusted)\n // countrycodes: 'gh', // Uncomment to limit to Ghana\n });\n this.map.addControl(searchNominatim);\n\n // Handle search result selection\n searchNominatim.on('select', (event) => {\n const searchResult = event.search;\n if (searchResult) {\n // SearchNominatim returns a plain object with lon/lat properties (as strings)\n const lon = parseFloat(searchResult.lon);\n const lat = parseFloat(searchResult.lat);\n const lonLat = [lon, lat];\n const coordinate = fromLonLat(lonLat);\n\n // Navigate to the selected location\n this.navigateTo(lon, lat, 14);\n\n // Trigger search select callbacks\n const result = {\n coordinate: coordinate,\n lonLat: lonLat,\n name: searchResult.display_name || searchResult.name || 'Unknown',\n searchResult: searchResult,\n };\n this.searchSelectCallbacks.forEach(cb => cb(result));\n }\n });\n\n // Store reference for external access\n this.searchNominatim = searchNominatim;\n this.searchSelectCallbacks = [];\n\n // Track selected feature\n this.selectedFeature = null;\n\n // Create popup overlay for hover\n this.createPopup();\n\n // Create info popup for double-click feature details\n this.createInfoPopup();\n\n // Create Add Location popup form\n this.createAddLocationPopup();\n\n // Create editable parcel form popup\n this.createParcelEditPopup();\n\n // Create drawn polygon attribute popup\n this.createDrawnPolygonPopup();\n\n // Create merge identifier (UPN) chooser popup\n this.createMergePopup();\n\n // Create divide polygon popup (number input)\n this.createDividePopup();\n\n // Double-click callbacks\n this.dblClickCallbacks = [];\n\n // EditBar is set up lazily via initEditBar() once the Drawings\n // layer/group is available (called from main.js after loadLayers).\n this.editBar = null;\n this.drawingsSource = null;\n this.drawingsLayer = null;\n this.touchCursor = null;\n this._editBarActive = false;\n }\n\n // ============================================================================\n // EditBar + Drawings Layer + TouchCursor\n // ============================================================================\n\n /**\n * Initialise the EditBar with a dedicated \"Drawings\" LayerGroup.\n *\n * A \"Drawings\" LayerGroup is created at the top of the overlay stack\n * containing a \"sketches\" VectorLayer for storing drawn features.\n * The EditBar, Select and Modify interactions are only active while\n * edit mode is on; in all other cases normal click / double-click\n * behaviour is preserved.\n *\n * Call this once from main.js after the layer groups have been created.\n */\n initEditBar() {\n // 1. Create a \"Drawings\" LayerGroup with a \"sketches\" VectorLayer inside\n this.drawingsSource = new VectorSource();\n this.drawingsLayer = new VectorLayer({\n title: 'sketches',\n source: this.drawingsSource,\n style: new Style({\n stroke: new Stroke({ color: '#f59e0b', width: 2.5 }),\n fill: new Fill({ color: 'rgba(245,158,11,0.15)' }),\n image: new Circle({\n radius: 6,\n fill: new Fill({ color: '#f59e0b' }),\n stroke: new Stroke({ color: '#fff', width: 1.5 }),\n }),\n }),\n });\n\n this._drawingsGroup = new LayerGroup({\n title: 'Drawings',\n layers: [this.drawingsLayer],\n });\n // Insert as a top-level map layer just before the Overlays group so the\n // LayerSwitcher order is: Overlays > Drawings > Measurements > Markers > Base Maps.\n // Find Overlays by reference rather than assuming it is the last layer —\n // other layers (e.g. the GPS trail/position layers added by\n // _initGpsRendering) may sit on top of it.\n const mapLayers = this.map.getLayers();\n const overlayIdx = mapLayers.getArray().indexOf(this.overlayGroup);\n mapLayers.insertAt(overlayIdx >= 0 ? overlayIdx : mapLayers.getLength(), this._drawingsGroup);\n\n // 2. Create a Select interaction that works on ALL vector layers.\n // It starts INACTIVE so it doesn't steal clicks from normal handlers.\n // Multi-select: a plain click selects a single feature (replacing the\n // selection); Shift-click toggles a feature in/out of the selection so\n // the user can build up a set to delete or move together. Shift-click is\n // the ol default toggleCondition, but we set it explicitly for clarity.\n this._selectInteraction = new Select({\n condition: clickCondition,\n toggleCondition: shiftKeyOnly,\n filter: (feature, layer) => !!layer,\n layers: (layer) => layer instanceof VectorLayer,\n });\n this._selectInteraction.setActive(false);\n this.map.addInteraction(this._selectInteraction);\n\n // 2b. Box-select — Ctrl/Cmd + drag draws a rectangle and adds every\n // intersecting feature to the selection. This is the discoverable\n // \"select multiple\" gesture (Shift-click also works, one at a time).\n // Plain drag still pans the map; Shift-drag is left free. The box is\n // only live while the Select tool itself is active (see the\n // change:active wiring below) so it never interferes with drawing.\n this._dragBoxSelect = new DragBox({ condition: platformModifierKeyOnly });\n this._dragBoxSelect.setActive(false);\n this.map.addInteraction(this._dragBoxSelect);\n this._dragBoxSelect.on('boxend', () => {\n const extent = this._dragBoxSelect.getGeometry().getExtent();\n const selected = this._selectInteraction.getFeatures();\n // Walk every visible vector layer the Select interaction would accept\n // and add features whose geometry intersects the box.\n this.map.getLayers().forEach((layer) => this._boxAddFromLayer(layer, extent, selected));\n this._refreshVertexOverlay?.();\n });\n // Keep box-select armed only while the Select sub-tool is active.\n this._selectInteraction.on('change:active', () => {\n this._dragBoxSelect.setActive(this._selectInteraction.getActive());\n });\n\n // 3. Create a ModifyFeature interaction bound to the selection.\n // Also starts inactive.\n this._modifyInteraction = new ModifyFeature({\n features: this._selectInteraction.getFeatures(),\n });\n this._modifyInteraction.setActive(false);\n\n // 3b. Fire onFeatureModified callbacks when a modification completes.\n // Consumers attach via onFeatureModified() and decide for themselves\n // whether to react (e.g. the staged-import code persists geometry\n // changes back to external_import_features).\n this._modifyInteraction.on('modifyend', (evt) => {\n if (!this._featureModifiedCallbacks?.length) return;\n const features = evt.features?.getArray?.() || [];\n for (const f of features) {\n for (const cb of this._featureModifiedCallbacks) {\n try { cb(f); } catch (err) { console.warn('[MapView] onFeatureModified callback failed:', err); }\n }\n }\n });\n\n // 4. UndoRedo interaction — watches the drawings source\n this._undoRedo = new UndoRedo();\n this.map.addInteraction(this._undoRedo);\n\n // 5. Build the EditBar — all interactions enabled.\n this.editBar = new EditBar({\n source: this.drawingsSource,\n interactions: {\n Select: this._selectInteraction,\n ModifySelect: this._modifyInteraction,\n DrawPoint: true,\n DrawLine: true,\n DrawPolygon: true,\n DrawRegular: true,\n DrawHole: true,\n Delete: true,\n Info: true,\n Transform: true,\n Split: false,\n },\n });\n this.map.addControl(this.editBar);\n\n // 5b. Persistent vertex overlay — when edit mode is active and the user\n // selects a polygon (or line) for modification, render a small dot\n // at every vertex so the user can see all editable nodes at a glance.\n // ol-ext's ModifyFeature only renders the closest vertex on hover; this\n // overlay complements that without subclassing the interaction.\n this._setupVertexOverlay();\n\n // 6. Add extra buttons (Undo, Redo, Save) as a sub-bar\n // inside the EditBar so they appear inline.\n const extraBar = new Bar({\n group: true,\n // Stable class so CSS can move this group (undo/redo/save/snap) to a\n // second row on small screens — see `.ol-editbar-actions` media query.\n className: 'ol-editbar-actions',\n controls: [\n new Button({\n html: ' ',\n className: 'ol-undo',\n title: 'Undo',\n handleClick: () => {\n if (this._undoRedo.hasUndo()) this._undoRedo.undo();\n },\n }),\n new Button({\n html: ' ',\n className: 'ol-redo',\n title: 'Redo',\n handleClick: () => {\n if (this._undoRedo.hasRedo()) this._undoRedo.redo();\n },\n }),\n new Button({\n html: ' ',\n className: 'ol-save',\n title: 'Save drawings',\n handleClick: () => {\n this.dispatchEditEvent('save');\n },\n }),\n ],\n });\n this.editBar.addControl(extraBar);\n\n // 6a-split. Custom Split tool with Lines / Polygons sub-categories.\n // The default ol-ext Split only handles LineString. We add a parent\n // Toggle with a sub-bar containing two sub-toggles: \"Lines\" (ol-ext\n // Split) and \"Polygons\" (our PolygonSplitInteraction).\n // No explicit sources → both interactions search ALL visible vector layers,\n // so they work on drawn features, parcels, zones, and any other polygon layer.\n this._lineSplitInteraction = new Split();\n this._polygonSplitInteraction = new PolygonSplitInteraction();\n this.map.addInteraction(this._lineSplitInteraction);\n this.map.addInteraction(this._polygonSplitInteraction);\n this._lineSplitInteraction.setActive(false);\n this._polygonSplitInteraction.setActive(false);\n\n // When a parcel is split, the user picks which piece keeps the UPN.\n this._polygonSplitInteraction.on('splitpick', (evt) => {\n const idFields = ['UPN', 'upn', 'id', 'parcelid', 'parcel_id', 'PARCELID', 'PARCEL_ID', 'ID'];\n for (const feat of evt.features) {\n if (feat === evt.picked) continue;\n for (const field of idFields) {\n if (feat.get(field) !== undefined) {\n feat.set(field, '');\n }\n }\n }\n });\n\n // Polygon Divide interaction (parameter-driven equal-area division)\n this._polygonDivideInteraction = new PolygonDivideInteraction();\n this.map.addInteraction(this._polygonDivideInteraction);\n this._polygonDivideInteraction.setActive(false);\n\n const splitLineToggle = new Toggle({\n html: ' ',\n className: 'ol-split-line',\n title: 'Split Lines',\n name: 'SplitLine',\n interaction: this._lineSplitInteraction,\n autoActivate: true,\n });\n const splitPolyToggle = new Toggle({\n html: ' ',\n className: 'ol-split-polygon',\n title: 'Split Polygons',\n name: 'SplitPolygon',\n interaction: this._polygonSplitInteraction,\n });\n const splitDivideToggle = new Toggle({\n html: ' ',\n className: 'ol-split-divide',\n title: 'Divide Polygon',\n name: 'DividePolygon',\n interaction: this._polygonDivideInteraction,\n });\n\n const splitSubBar = new Bar({\n toggleOne: true,\n autoDeactivate: true,\n controls: [splitLineToggle, splitPolyToggle, splitDivideToggle],\n });\n\n const splitParentToggle = new Toggle({\n className: 'ol-split',\n title: 'Split',\n name: 'Split',\n bar: splitSubBar,\n onToggle: (active) => {\n if (!active) {\n this._lineSplitInteraction.setActive(false);\n this._polygonSplitInteraction.setActive(false);\n this._polygonDivideInteraction.setActive(false);\n }\n },\n });\n this.editBar.addControl(splitParentToggle);\n\n // Listen for divide form request → show divide popup\n this._polygonDivideInteraction.on('divideform', (evt) => {\n this.showDividePopup(evt.feature, evt.source, evt.coordinate);\n });\n this._polygonDivideInteraction.on('dividecancel', () => {\n this.hideDividePopup();\n });\n\n // When a parcel is divided, the user picks which piece keeps the UPN.\n // The picked piece gets the original properties; all others get UPN cleared.\n this._polygonDivideInteraction.on('dividepick', (evt) => {\n const idFields = ['UPN', 'upn', 'id', 'parcelid', 'parcel_id', 'PARCELID', 'PARCEL_ID', 'ID'];\n for (const feat of evt.features) {\n if (feat === evt.picked) continue;\n // Clear identifier fields on the non-picked pieces\n for (const field of idFields) {\n if (feat.get(field) !== undefined) {\n feat.set(field, '');\n }\n }\n }\n });\n\n // 6a-merge. Polygon Merge tool — select two adjacent polygons, click shared\n // edges, and merge them into one. For parcels, a UPN chooser popup appears.\n this._polygonMergeInteraction = new PolygonMergeInteraction();\n this.map.addInteraction(this._polygonMergeInteraction);\n this._polygonMergeInteraction.setActive(false);\n\n const mergeToggle = new Toggle({\n html: ' ',\n className: 'ol-merge',\n title: 'Merge Polygons',\n name: 'Merge',\n interaction: this._polygonMergeInteraction,\n });\n this.editBar.addControl(mergeToggle);\n\n // Listen for merged-parcel event → show UPN chooser\n this._polygonMergeInteraction.on('mergedparcel', (evt) => {\n this.showMergeIdentifierPopup(evt.merged, evt.propsA, evt.propsB, evt.coordinate);\n });\n\n // Small-screen layout: insert a zero-height, full-width flex line-break\n // immediately BEFORE the action group. On phones (see the .ol-editbar\n // media query) this forces the wrap to happen here, so the action group\n // (undo/redo/save/snap) together with the Split and Merge toggles all land\n // on a single second row instead of Split/Merge spilling onto a third row.\n // The break is display:none on wider screens, so desktop layout is unchanged.\n const editbarEl = this.editBar.element;\n if (editbarEl && extraBar.element && extraBar.element.parentNode === editbarEl) {\n const breakEl = document.createElement('div');\n breakEl.className = 'ol-editbar-break';\n editbarEl.insertBefore(breakEl, extraBar.element);\n }\n\n // 6b. SnapGuides — shows alignment guides while drawing.\n // Uses VectorImageLayer for GPU-friendly canvas rendering instead of\n // re-creating individual SVG elements on every guide update.\n this._snapGuidesEnabled = localStorage.getItem('snap-guides-enabled') === '1';\n this._snapGuides = new SnapGuides({\n pixelTolerance: 10,\n vectorClass: VectorImageLayer,\n });\n this.map.addInteraction(this._snapGuides);\n\n // Connect SnapGuides to whichever draw interaction becomes active.\n // setDrawInteraction() only tracks one at a time, so we re-bind\n // whenever a draw tool is activated.\n const drawToolNames = ['DrawPoint', 'DrawLine', 'DrawPolygon', 'DrawHole', 'DrawRegular'];\n for (const name of drawToolNames) {\n const interaction = this.editBar.getInteraction(name);\n if (interaction) {\n interaction.on('change:active', () => {\n if (interaction.getActive()) {\n this._snapGuides.setDrawInteraction(interaction);\n }\n });\n }\n }\n\n // Also connect SnapGuides to the Modify interaction for vertex editing\n if (this._modifyInteraction) {\n this._snapGuides.setModifyInteraction(this._modifyInteraction);\n }\n\n // 6c. Snap-guides toggle button (magnet icon) — persisted in localStorage\n const snapToggleBtn = new Button({\n html: ' ',\n className: 'ol-snap-toggle' + (this._snapGuidesEnabled ? ' ol-active' : ''),\n title: 'Toggle Snap Guides',\n handleClick: () => {\n this._snapGuidesEnabled = !this._snapGuidesEnabled;\n localStorage.setItem('snap-guides-enabled', this._snapGuidesEnabled ? '1' : '0');\n // Update visual state\n snapToggleBtn.element.classList.toggle('ol-active', this._snapGuidesEnabled);\n // Activate or deactivate the interaction\n if (this._snapGuides) {\n this._snapGuides.setActive(this._snapGuidesEnabled && this._editBarActive);\n }\n console.log('[MapView] Snap guides:', this._snapGuidesEnabled ? 'ON' : 'OFF');\n },\n });\n this._snapToggleBtn = snapToggleBtn;\n extraBar.addControl(snapToggleBtn);\n\n // Start hidden — use the full setEditMode(false) so the Select +\n // Modify interactions are deactivated (the EditBar constructor may\n // have re-activated them).\n this.setEditMode(false);\n\n // 7. Link EditBar visibility to the Drawings group's visibility.\n this._drawingsGroup.on('change:visible', () => {\n const visible = this._drawingsGroup.getVisible();\n this.setEditMode(visible);\n });\n\n // 8. Touch-device detection & TouchCursor setup\n //\n // The TouchCursor is only practical on *touch-only* devices (phones,\n // tablets) where the finger is the sole pointing device. On hybrid\n // laptops — a touchscreen plus a touchpad/mouse — the changed cursor\n // gets in the way, because the user is most likely driving the map\n // with the precise pointer, not the screen.\n //\n // The classic `'ontouchstart' in window` / `maxTouchPoints` test can't\n // tell the two apart: it is true for both a tablet and a touchscreen\n // laptop. We additionally consult CSS Media Queries Level 4 pointer\n // features, which DO distinguish them:\n //\n // any-pointer: fine → at least one fine pointer exists\n // (mouse / touchpad / stylus). True on a\n // touch laptop, false on a phone/tablet.\n // any-hover: hover → at least one device can hover. Same split.\n //\n // So we enable the TouchCursor only when the device is touch-capable\n // AND exposes no fine/hovering pointer — i.e. a genuine touch-only\n // device. `_isTouchOnlyDevice()` is also reactive: if the user later\n // plugs in a mouse, `_refreshTouchCursor()` tears the cursor down.\n if (this._isTouchOnlyDevice()) {\n this.touchCursor = new TouchCursor({\n className: 'ol-editbar-cursor',\n });\n this.map.addInteraction(this.touchCursor);\n this.touchCursor.setActive(false);\n console.log('[MapView] Touch-only device detected — TouchCursor added');\n } else {\n console.log('[MapView] Fine pointer available — TouchCursor skipped');\n }\n\n // React to pointer-capability changes (e.g. a Bluetooth mouse paired\n // with a tablet, or a tablet docked to a trackpad keyboard). When a\n // fine pointer appears we drop the TouchCursor; when the last one is\n // removed on a touch device we add it back.\n this._installPointerCapabilityWatcher();\n\n // 9. Listen for polygon features drawn via EditBar's DrawPolygon tool.\n // When a Polygon is added to the drawings source, show the attribute popup.\n this.drawingsSource.on('addfeature', (evt) => {\n const feature = evt.feature;\n const geom = feature.getGeometry();\n if (!geom || geom.getType() !== 'Polygon') return;\n\n const coordinate = geom.getInteriorPoint().getCoordinates();\n this.showDrawnPolygonPopup(feature, coordinate);\n });\n\n // 10. Keyboard Delete — pressing Delete or Backspace while edit mode is\n // active deletes the currently-selected feature(s), mirroring the\n // EditBar's Delete button (same undoable deletestart/deleteend block).\n // Guarded so it never fires while the user is typing in a form field.\n this._editKeyHandler = (e) => {\n if (e.key !== 'Delete' && e.key !== 'Backspace') return;\n if (!this._editBarActive) return;\n const t = e.target;\n const tag = t && t.tagName;\n if (t?.isContentEditable || tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;\n if (this._deleteSelectedFeatures()) {\n e.preventDefault();\n }\n };\n document.addEventListener('keydown', this._editKeyHandler);\n\n console.log('[MapView] EditBar initialised with Drawings group, UndoRedo and SnapGuides (default:', this._snapGuidesEnabled ? 'ON' : 'OFF', ')');\n }\n\n /**\n * Delete the currently-selected feature(s) via the EditBar's Delete\n * interaction, so the removal is recorded as a single undoable block\n * (deletestart/deleteend) exactly like the Delete button. Returns true if\n * anything was deleted.\n * @returns {boolean}\n */\n _deleteSelectedFeatures() {\n if (!this._editBarActive) return false;\n const del = this.editBar?.getInteraction('Delete');\n const features = this._selectInteraction?.getFeatures();\n if (!del || !features || features.getLength() === 0) return false;\n del.delete(features); // removes from all map sources; undoable\n features.clear(); // drop the now-deleted features from selection\n this._refreshVertexOverlay?.();\n return true;\n }\n\n /**\n * Box-select helper: add every feature of a (visible, Select-eligible) vector\n * layer whose geometry intersects `extent` to the `selected` collection,\n * skipping duplicates. Recurses into LayerGroups.\n * @private\n */\n _boxAddFromLayer(layer, extent, selected) {\n if (!layer) return;\n if (typeof layer.getLayers === 'function') {\n layer.getLayers().forEach((l) => this._boxAddFromLayer(l, extent, selected));\n return;\n }\n if (!(layer instanceof VectorLayer)) return;\n if (layer.getVisible && !layer.getVisible()) return;\n // Skip non-selectable helper layers: the vertex-edit overlay, GPS trail /\n // position, and anything explicitly hidden from the layer switcher.\n if (layer === this._vertexOverlayLayer ||\n layer === this._gpsTrailLayer ||\n layer === this._gpsPositionLayer ||\n layer.get('displayInLayerSwitcher') === false) return;\n const source = layer.getSource && layer.getSource();\n if (!source || typeof source.forEachFeatureIntersectingExtent !== 'function') return;\n source.forEachFeatureIntersectingExtent(extent, (feature) => {\n if (!selected.getArray().includes(feature)) selected.push(feature);\n });\n }\n\n /**\n * Dispatch a custom edit event (e.g. 'save').\n * External code can listen via mapView.onEditEvent('save', callback).\n * @param {string} type\n */\n dispatchEditEvent(type) {\n if (!this._editEventListeners) return;\n const listeners = this._editEventListeners[type];\n if (listeners) {\n listeners.forEach((fn) => fn());\n }\n }\n\n /**\n * Listen for custom edit events (e.g. 'save').\n * @param {string} type - Event name\n * @param {Function} callback\n */\n onEditEvent(type, callback) {\n if (!this._editEventListeners) this._editEventListeners = {};\n if (!this._editEventListeners[type]) this._editEventListeners[type] = [];\n this._editEventListeners[type].push(callback);\n }\n\n /**\n * Toggle edit mode on or off.\n *\n * When ON: EditBar is visible, Select + Modify interactions are active.\n * When OFF: EditBar is hidden, Select + Modify are deactivated, any\n * current selection is cleared so normal click / double-click\n * events work without interference.\n *\n * @param {boolean} active\n */\n setEditMode(active) {\n const wasActive = this._editBarActive;\n this._editBarActive = !!active;\n\n // On entering edit mode, (1) re-scan vector sources so UndoRedo watches\n // every layer loaded since the EditBar was built — parcels, zones and\n // imports are pushed into sub-groups AFTER init, and ol-ext's UndoRedo only\n // auto-watches TOP-LEVEL map layer changes, so those sources would\n // otherwise be invisible to undo (a delete records an empty block and undo\n // does nothing); and (2) reset the undo history so it covers only this\n // editing session and can't reach back into data-loading operations.\n if (this._editBarActive && !wasActive && this._undoRedo) {\n try {\n this._undoRedo._watchSources();\n this._undoRedo.clear();\n } catch (err) {\n console.warn('[MapView] UndoRedo re-watch/clear failed:', err);\n }\n }\n\n if (this.editBar) {\n this.editBar.setVisible(this._editBarActive);\n\n if (!this._editBarActive) {\n // Deactivate all EditBar controls (DrawPoint, DrawLine, etc.)\n // so no draw interaction stays active in the background.\n this.editBar.deactivateControls();\n }\n }\n\n // Activate / deactivate Select + Modify\n if (this._selectInteraction) {\n if (!this._editBarActive) {\n // Clear any current selection first\n this._selectInteraction.getFeatures().clear();\n }\n this._selectInteraction.setActive(this._editBarActive);\n }\n if (this._modifyInteraction) {\n this._modifyInteraction.setActive(this._editBarActive);\n }\n\n // Toggle SnapGuides — only active when both edit mode AND the user toggle are on\n if (this._snapGuides) {\n this._snapGuides.setActive(this._snapGuidesEnabled && this._editBarActive);\n }\n\n // Toggle TouchCursor\n if (this.touchCursor) {\n this.touchCursor.setActive(this._editBarActive);\n }\n\n // Clear persistent vertex highlights when leaving edit mode (excluded\n // from the undo stack — see _withoutUndoRecording / _silentClearSource).\n if (!this._editBarActive && this._vertexOverlaySource) {\n this._withoutUndoRecording(() => this._silentClearSource(this._vertexOverlaySource));\n }\n\n console.log('[MapView] Edit mode:', this._editBarActive ? 'ON' : 'OFF');\n }\n\n /**\n * Check whether edit mode (select / modify) is currently active.\n * @returns {boolean}\n */\n isEditMode() {\n return this._editBarActive;\n }\n\n // ============================================================================\n // Pointer-capability detection (touch-only vs. hybrid laptop)\n // ============================================================================\n\n /**\n * Decide whether the ol-ext TouchCursor should be used.\n *\n * Returns true ONLY for genuine touch-only devices (phones, tablets) —\n * i.e. devices that are touch-capable but expose no fine pointer and no\n * hover capability. Hybrid laptops (touchscreen + touchpad/mouse) return\n * false, so they keep the normal cursor.\n *\n * @returns {boolean}\n */\n _isTouchOnlyDevice() {\n const hasTouch = ('ontouchstart' in window) ||\n (navigator.maxTouchPoints > 0) ||\n (navigator.msMaxTouchPoints > 0);\n if (!hasTouch) return false;\n\n // Without matchMedia we can't refine the signal — fall back to the\n // historical behaviour (treat any touch device as touch).\n if (typeof window.matchMedia !== 'function') return true;\n\n // `any-pointer: fine` is true when ANY attached pointing device is\n // fine (mouse / touchpad / stylus); `any-hover: hover` when ANY device\n // can hover. A phone/tablet satisfies neither; a touch laptop both.\n const hasFinePointer = window.matchMedia('(any-pointer: fine)').matches;\n const canHover = window.matchMedia('(any-hover: hover)').matches;\n\n return !hasFinePointer && !canHover;\n }\n\n /**\n * Add or remove the TouchCursor to match the current pointer capability,\n * preserving its active state relative to edit mode. Called both at init\n * and whenever the pointer-capability media queries change.\n */\n _refreshTouchCursor() {\n const wantCursor = this._isTouchOnlyDevice();\n\n if (wantCursor && !this.touchCursor) {\n this.touchCursor = new TouchCursor({ className: 'ol-editbar-cursor' });\n this.map.addInteraction(this.touchCursor);\n this.touchCursor.setActive(this._editBarActive);\n console.log('[MapView] Pointer change → TouchCursor added');\n } else if (!wantCursor && this.touchCursor) {\n this.map.removeInteraction(this.touchCursor);\n this.touchCursor = null;\n console.log('[MapView] Pointer change → TouchCursor removed (fine pointer present)');\n }\n }\n\n /**\n * Watch the pointer-capability media queries and re-evaluate the\n * TouchCursor when they change — e.g. a Bluetooth mouse paired with a\n * tablet, or a 2-in-1 docked to / undocked from a keyboard-trackpad.\n */\n _installPointerCapabilityWatcher() {\n if (typeof window.matchMedia !== 'function') return;\n if (this._pointerMediaQueries) return; // already installed\n\n const queries = ['(any-pointer: fine)', '(any-hover: hover)']\n .map((q) => window.matchMedia(q));\n const onChange = () => this._refreshTouchCursor();\n\n for (const mq of queries) {\n // addEventListener is the modern API; addListener is the legacy\n // fallback for older Safari.\n if (typeof mq.addEventListener === 'function') {\n mq.addEventListener('change', onChange);\n } else if (typeof mq.addListener === 'function') {\n mq.addListener(onChange);\n }\n }\n this._pointerMediaQueries = queries;\n this._pointerMediaListener = onChange;\n }\n\n // ============================================================================\n // Persistent Vertex Highlight Overlay\n // ============================================================================\n\n /**\n * Create a vector layer that renders a small dot at every vertex of any\n * currently-selected feature (polygon, multipolygon, line, multiline).\n * Only active while edit mode is on.\n *\n * Hooks:\n * - `select` event from the Select interaction → rebuild dots for the new selection\n * - `change` event on the selected feature → reposition dots when a vertex is dragged\n */\n _setupVertexOverlay() {\n this._vertexOverlaySource = new VectorSource();\n this._vertexOverlayLayer = new VectorLayer({\n title: '__vertex_highlight__',\n source: this._vertexOverlaySource,\n // Render above all other overlays but below ModifyFeature's hover indicator\n zIndex: 990,\n style: new Style({\n image: new Circle({\n radius: 4,\n fill: new Fill({ color: 'rgba(14,165,233,0.85)' }), // brand blue\n stroke: new Stroke({ color: '#fff', width: 1.2 }),\n }),\n }),\n });\n // Hide from LayerSwitcher — purely visual, not user-toggleable\n this._vertexOverlayLayer.set('displayInLayerSwitcher', false);\n this.map.addLayer(this._vertexOverlayLayer);\n\n // Bound handler so we can attach/detach by reference\n this._onSelectedFeatureGeomChange = () => this._refreshVertexOverlay();\n\n // Track which feature(s) we're listening on, so we can unhook cleanly\n this._vertexTrackedFeatures = new Set();\n\n // When the selection changes, swap which features we listen to and rebuild dots\n this._selectInteraction.on('select', () => this._refreshVertexOverlay());\n }\n\n /**\n * Run `fn` with the UndoRedo interaction's recording temporarily paused, so\n * the vector-source mutations it performs are NOT pushed onto the undo stack.\n *\n * The vertex-overlay layer is a plain VectorLayer, and ol-ext's UndoRedo\n * watches every vector source in the map — so without this, each selection's\n * vertex-dot add/clear would land on the undo stack and undo would reverse\n * those instead of the user's actual edit (the \"first undo does nothing,\n * second shows vertices\" symptom). Our overlay source is a plain ol\n * VectorSource (it never emits ol-ext's clearstart/clearend block events),\n * so gating `_record` is sufficient to fully exclude it.\n * @private\n */\n _withoutUndoRecording(fn) {\n const ur = this._undoRedo;\n if (!ur) return fn();\n const prev = ur._record;\n ur._record = false;\n try { return fn(); }\n finally { ur._record = prev; }\n }\n\n /**\n * Clear a vector source WITHOUT firing the clearstart/clearend events that\n * ol-ext patches onto ol/source/Vector.prototype.clear. Those events drive\n * UndoRedo's blockStart/blockEnd, which are NOT gated by the record flag — so\n * a plain `source.clear()` on a helper layer pushes a stray (empty) block\n * onto the undo stack even inside _withoutUndoRecording. Removing features\n * one by one only fires `removefeature`, which IS gated by the record flag,\n * so wrapped in _withoutUndoRecording this leaves the undo stack untouched.\n * @private\n */\n _silentClearSource(source) {\n if (!source) return;\n const feats = source.getFeatures();\n for (let i = feats.length - 1; i >= 0; i--) {\n source.removeFeature(feats[i]);\n }\n }\n\n /**\n * Rebuild the vertex overlay from the current Select interaction's features.\n * No-ops when not in edit mode.\n */\n _refreshVertexOverlay() {\n if (!this._vertexOverlaySource) return;\n // All overlay-source mutations are excluded from the undo stack.\n this._withoutUndoRecording(() => {\n this._silentClearSource(this._vertexOverlaySource);\n\n // Detach change listeners from previously-tracked features\n if (this._vertexTrackedFeatures) {\n for (const f of this._vertexTrackedFeatures) {\n f.un('change', this._onSelectedFeatureGeomChange);\n }\n this._vertexTrackedFeatures.clear();\n }\n\n if (!this._editBarActive || !this._selectInteraction) return;\n\n const selected = this._selectInteraction.getFeatures().getArray();\n for (const feat of selected) {\n const geom = feat.getGeometry();\n if (!geom) continue;\n const type = geom.getType();\n if (!['Polygon', 'MultiPolygon', 'LineString', 'MultiLineString'].includes(type)) {\n continue;\n }\n const coords = this._collectAllVertices(geom);\n for (const c of coords) {\n this._vertexOverlaySource.addFeature(new Feature(new Point(c)));\n }\n // Listen for vertex moves on this feature\n feat.on('change', this._onSelectedFeatureGeomChange);\n this._vertexTrackedFeatures.add(feat);\n }\n });\n }\n\n /**\n * Walk a (Multi)Polygon or (Multi)LineString geometry and return the flat\n * list of vertex coordinates. Polygon rings have a duplicate closing vertex\n * (last == first) which is dropped here so we don't render two dots on top\n * of each other.\n *\n * @param {Geometry} geom\n * @returns {Array>}\n */\n _collectAllVertices(geom) {\n const out = [];\n const isCoord = (v) => Array.isArray(v) && typeof v[0] === 'number';\n\n const visitRing = (ring, isPolygonRing) => {\n const len = isPolygonRing && ring.length > 1 ? ring.length - 1 : ring.length;\n for (let i = 0; i < len; i++) out.push(ring[i]);\n };\n\n const type = geom.getType();\n const coords = geom.getCoordinates();\n\n switch (type) {\n case 'Polygon':\n // coords = [outerRing, hole1, hole2, …]\n for (const ring of coords) visitRing(ring, true);\n break;\n case 'MultiPolygon':\n // coords = [poly1, poly2, …]; each poly = [outerRing, hole1, …]\n for (const poly of coords) for (const ring of poly) visitRing(ring, true);\n break;\n case 'LineString':\n visitRing(coords, false);\n break;\n case 'MultiLineString':\n for (const line of coords) visitRing(line, false);\n break;\n default:\n // Fallback: deep walk to find arrays of [x, y]\n const walk = (v) => {\n if (isCoord(v)) out.push(v);\n else if (Array.isArray(v)) for (const sub of v) walk(sub);\n };\n walk(coords);\n }\n return out;\n }\n\n /**\n * Get the Drawings layer for external access.\n * @returns {VectorLayer}\n */\n getDrawingsLayer() {\n return this.drawingsLayer;\n }\n\n /**\n * Get the Drawings source for external access.\n * @returns {VectorSource}\n */\n getDrawingsSource() {\n return this.drawingsSource;\n }\n\n /**\n * Get the EditBar control for external access.\n * @returns {EditBar}\n */\n getEditBar() {\n return this.editBar;\n }\n\n /**\n * Update the ScaleBar units ('metric' or 'imperial').\n * @param {'metric'|'imperial'} system\n */\n setScaleBarUnits(system) {\n if (this.scaleBar) {\n this.scaleBar.setUnits(system === 'imperial' ? 'imperial' : 'metric');\n }\n }\n\n /**\n * Create the popup overlay element and add to map\n */\n createPopup() {\n // Create popup container element\n this.popupElement = document.createElement('div');\n this.popupElement.className = 'map-popup';\n this.popupElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n color: var(--card-foreground, #1e1a4b);\n border-radius: 8px;\n padding: 10px 14px;\n box-shadow: 0 2px 8px rgba(0,0,0,0.25);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 150px;\n max-width: 280px;\n pointer-events: none;\n z-index: 1000;\n border: 1px solid var(--border, #1e1a4b1f);\n `;\n\n // Create the overlay\n this.popup = new Overlay({\n element: this.popupElement,\n positioning: 'bottom-center',\n offset: [0, -15],\n stopEvent: false,\n });\n\n this.map.addOverlay(this.popup);\n\n // Set up hover handler\n this.setupHoverPopup();\n }\n\n /**\n * Set up the hover popup behavior\n */\n setupHoverPopup() {\n let currentFeature = null;\n\n this.map.on('pointermove', (evt) => {\n if (evt.dragging) {\n this.hidePopup();\n return;\n }\n\n // Only find features that are location markers (have 'name' property)\n const feature = this.map.forEachFeatureAtPixel(evt.pixel, (f) => {\n // Only return features that have a 'name' property (location markers)\n if (f.get('name')) {\n return f;\n }\n return null;\n });\n\n if (feature && feature !== currentFeature) {\n currentFeature = feature;\n this.showPopup(feature, evt.coordinate);\n } else if (!feature && currentFeature) {\n currentFeature = null;\n this.hidePopup();\n }\n\n // Update cursor - only show pointer for location markers\n this.map.getTargetElement().style.cursor = feature ? 'pointer' : '';\n });\n\n // Hide popup when mouse leaves the map\n this.map.getTargetElement().addEventListener('mouseleave', () => {\n this.hidePopup();\n currentFeature = null;\n });\n }\n\n /**\n * Show popup with feature attributes\n */\n showPopup(feature, coordinate) {\n const name = feature.get('name') || 'Unnamed';\n const category = feature.get('category') || 'default';\n const description = feature.get('description');\n const lon = feature.get('lon');\n const lat = feature.get('lat');\n const emoji = this.getEmoji(category);\n\n // Build popup content\n let html = `\n \n ${emoji} ${this.escapeHtml(name)}\n
\n `;\n\n // Category badge\n const categoryColors = {\n 'water': '#3b82f6',\n 'school': '#f59e0b',\n 'health': '#ef4444',\n 'market': '#8b5cf6',\n 'default': '#2d5016',\n 'other': '#6b7280'\n };\n const catColor = categoryColors[category] || '#6b7280';\n html += `\n \n ${category} \n
\n `;\n\n // Description if available\n if (description) {\n html += `\n \n ${this.escapeHtml(description)}\n
\n `;\n }\n\n // Coordinates\n if (lon !== undefined && lat !== undefined) {\n html += `\n \n ${Number(lon).toFixed(5)}, ${Number(lat).toFixed(5)}\n
\n `;\n }\n\n this.popupElement.innerHTML = html;\n this.popup.setPosition(coordinate);\n }\n\n /**\n * Hide the popup\n */\n hidePopup() {\n this.popup.setPosition(undefined);\n }\n\n /**\n * Create the info popup overlay for double-click feature details\n */\n createInfoPopup() {\n this.infoPopupElement = document.createElement('div');\n this.infoPopupElement.className = 'map-info-popup';\n this.infoPopupElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n color: var(--card-foreground, #1e1a4b);\n border-radius: 10px;\n padding: 0;\n box-shadow: 0 4px 16px rgba(0,0,0,0.3);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 220px;\n max-width: 320px;\n max-height: 70vh;\n display: flex;\n flex-direction: column;\n z-index: 1001;\n border: 1px solid var(--border, #1e1a4b1f);\n overflow: hidden;\n `;\n\n this.infoPopup = new Overlay({\n element: this.infoPopupElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true,\n autoPan: true,\n autoPanAnimation: { duration: 250 },\n });\n\n this.map.addOverlay(this.infoPopup);\n }\n\n /**\n * Show the info popup with feature attributes and area\n * @param {Feature} feature - OpenLayers feature\n * @param {Array} coordinate - Map coordinate [x, y]\n * @param {Object} [options] - Display options\n * @param {string} [options.title='Feature Info'] - Popup header title\n * @param {string} [options.color='#e11d48'] - Header background colour\n */\n showInfoPopup(feature, coordinate, options = {}) {\n const { title = 'Feature Info', color = '#e11d48' } = options;\n const properties = feature.getProperties();\n const geometry = feature.getGeometry();\n const geomType = geometry.getType();\n\n // Build attributes table rows (skip geometry and internal keys)\n const skipKeys = ['geometry', '_layerType'];\n let rows = '';\n for (const [key, value] of Object.entries(properties)) {\n if (skipKeys.includes(key) || value === undefined || value === null) continue;\n rows += `\n \n ${this.escapeHtml(key)} \n ${this.escapeHtml(String(value))} \n \n `;\n }\n\n // Add measurement row based on geometry type\n if (geomType === 'Polygon' || geomType === 'MultiPolygon') {\n // Area for polygons\n const areaSqm = getArea(geometry, { projection: 'EPSG:3857' });\n const areaFormatted = formatAreaFull(areaSqm);\n rows += `\n \n area \n ${areaFormatted} \n \n `;\n } else if (geomType === 'LineString' || geomType === 'MultiLineString') {\n // Length for lines\n const lengthM = getLength(geometry, { projection: 'EPSG:3857' });\n const lengthFormatted = formatLengthFull(lengthM);\n rows += `\n \n length \n ${lengthFormatted} \n \n `;\n } else if (geomType === 'Point') {\n // Coordinates for points\n const coords = toLonLat(geometry.getCoordinates());\n const lon = coords[0].toFixed(6);\n const lat = coords[1].toFixed(6);\n rows += `\n \n longitude \n ${lon} \n \n \n latitude \n ${lat} \n \n `;\n }\n\n const html = `\n \n ${this.escapeHtml(title)} \n \n
\n \n `;\n\n this.infoPopupElement.innerHTML = html;\n this.infoPopup.setPosition(coordinate);\n\n // Close button handler\n this.infoPopupElement.querySelector('#info-popup-close').addEventListener('click', () => {\n this.hideInfoPopup();\n });\n }\n\n /**\n * Hide the info popup\n */\n hideInfoPopup() {\n this.infoPopup.setPosition(undefined);\n }\n\n // ============================================================================\n // Circle Intersection Analysis\n // ============================================================================\n\n /**\n * Analyse which features from overlay layers intersect a measurement circle\n * and show the results in the info popup.\n *\n * @param {Feature} circleFeature - The measurement circle feature (Circle geometry)\n * @param {Array} coordinate - Map coordinate for popup placement [x, y]\n */\n /**\n * Collect intersection results (parcels, zones, other) into a\n * structured { label, value } array for both HTML and PDF rendering.\n */\n _collectIntersectionRows(parcelFeatures, zoneFeatures, otherByLayer) {\n const dataRows = [];\n\n if (parcelFeatures.length > 0) {\n dataRows.push({ label: 'Parcels', value: String(parcelFeatures.length), color: '#0ea5e9' });\n }\n\n if (zoneFeatures.length > 0) {\n const names = zoneFeatures.map(f =>\n f.get('colzonename') || f.get('zone_name') || f.get('name') || 'unnamed'\n );\n dataRows.push({ label: 'Zones', value: String(zoneFeatures.length), color: '#7c3aed' });\n dataRows.push({ label: 'Zone Names', value: names.map(n => this.escapeHtml(n)).join(', '), color: '#7c3aed' });\n }\n\n for (const [title, features] of Object.entries(otherByLayer)) {\n dataRows.push({ label: this.escapeHtml(title), value: `${features.length} feature(s)` });\n }\n\n if (dataRows.length === 0) {\n dataRows.push({ label: '', value: 'No intersecting features found', empty: true });\n }\n\n return dataRows;\n }\n\n /**\n * Build the full popup HTML for an analysis popup (circle or area).\n *\n * @param {string} emoji - Header emoji\n * @param {string} title - e.g. \"Circle Analysis\"\n * @param {Array<{label:string, value:string, color?:string, empty?:boolean}>} dataRows\n * @returns {string} HTML\n */\n _buildAnalysisPopupHtml(emoji, title, dataRows) {\n let tableRows = '';\n for (const row of dataRows) {\n if (row.empty) {\n tableRows += `\n \n ${row.value} \n `;\n continue;\n }\n const labelColor = row.color || 'var(--muted-foreground, #7a7a7a)';\n const border = row._first ? '' : 'border-top:1px solid var(--border, #1e1a4b1f);';\n tableRows += `\n \n ${row.label} \n ${row.value} \n `;\n }\n\n return `\n \n ${emoji} ${title} \n \n
\n \n \n \n \n
`;\n }\n\n /**\n * Show the analysis popup, attach close + PDF / GIS export handlers.\n *\n * @param {string} emoji\n * @param {string} title - e.g. \"Area Analysis\" / \"Circle Analysis\"\n * @param {Array} dataRows - summary rows (PDF uses these)\n * @param {number[]} coordinate - popup anchor\n * @param {Object} [exportContext] - features + clip geometry for GIS export.\n * When omitted, the Export GIS button is\n * disabled (no features to export).\n * { kind: 'area' | 'circle',\n * clipGeometry,\n * parcelFeatures, zoneFeatures, otherByLayer }\n */\n _showAnalysisPopup(emoji, title, dataRows, coordinate, exportContext = null) {\n this.infoPopupElement.innerHTML = this._buildAnalysisPopupHtml(emoji, title, dataRows);\n this.infoPopup.setPosition(coordinate);\n\n this.infoPopupElement.querySelector('#info-popup-close').addEventListener('click', () => {\n this.hideInfoPopup();\n });\n\n // Summary rows, cleaned for the PDF report (HTML stripped, spacers removed).\n // These travel with the export event so the export modal can offer PDF\n // alongside the GIS formats — one \"Export\" entry point instead of two.\n const pdfRows = dataRows\n .filter((r) => !r.empty)\n .map((r) => ({ label: r.label, value: String(r.value).replace(/<[^>]*>/g, '') }));\n\n // Analyse — hand the intersecting features to the Analysis panel so the\n // user can run overlays / zonal statistics on just what the circle or\n // area caught. main.js owns the panel import.\n const analyseBtn = this.infoPopupElement.querySelector('#info-popup-analyse');\n if (analyseBtn) {\n const totalFeatures = exportContext\n ? exportContext.parcelFeatures.length\n + exportContext.zoneFeatures.length\n + Object.values(exportContext.otherByLayer).reduce((s, arr) => s + arr.length, 0)\n : 0;\n if (!exportContext || totalFeatures === 0) {\n analyseBtn.disabled = true;\n analyseBtn.style.opacity = '0.5';\n analyseBtn.style.cursor = 'not-allowed';\n analyseBtn.title = 'No intersecting features to analyse';\n } else {\n analyseBtn.addEventListener('click', () => {\n window.dispatchEvent(new CustomEvent('lupmis:analyse-features', {\n detail: { title, ...exportContext },\n }));\n });\n }\n }\n\n // GIS export — dispatches a window-level CustomEvent so main.js can open\n // the format/field-rename modal without MapView pulling in the writers.\n const gisBtn = this.infoPopupElement.querySelector('#info-popup-export-gis');\n if (gisBtn) {\n const total = exportContext\n ? exportContext.parcelFeatures.length\n + exportContext.zoneFeatures.length\n + Object.values(exportContext.otherByLayer).reduce((s, arr) => s + arr.length, 0)\n : 0;\n if (!exportContext || total === 0) {\n gisBtn.disabled = true;\n gisBtn.style.opacity = '0.5';\n gisBtn.style.cursor = 'not-allowed';\n gisBtn.title = 'No intersecting features to export';\n } else {\n gisBtn.addEventListener('click', () => {\n window.dispatchEvent(new CustomEvent('lupmis:export-gis', {\n detail: { title, pdfRows, ...exportContext },\n }));\n });\n }\n }\n }\n\n showCircleIntersectionPopup(circleFeature, coordinate) {\n const circleGeom = circleFeature.getGeometry();\n if (!circleGeom || typeof circleGeom.getCenter !== 'function') return;\n\n // Convert the OL Circle to a polygon (64 sides) for intersection testing\n const circlePoly = fromCircle(circleGeom, 64);\n const circleExtent = circlePoly.getExtent();\n\n const radius = circleFeature.get('_radius') || circleGeom.getRadius();\n\n // Collect intersecting features grouped by layer type\n const parcelFeatures = [];\n const zoneFeatures = [];\n const otherByLayer = {};\n\n const intersectsCircle = (feature) => {\n const geom = feature.getGeometry();\n if (!geom) return false;\n const fExtent = geom.getExtent();\n if (\n fExtent[2] < circleExtent[0] ||\n fExtent[0] > circleExtent[2] ||\n fExtent[3] < circleExtent[1] ||\n fExtent[1] > circleExtent[3]\n ) {\n return false;\n }\n return circlePoly.intersectsExtent(fExtent) && this._geometriesIntersect(circlePoly, geom);\n };\n\n const scanGroup = (group, groupTitle) => {\n group.getLayers().forEach((layer) => {\n if (layer instanceof LayerGroup) {\n scanGroup(layer, layer.get('title') || groupTitle);\n } else if (layer instanceof VectorLayer && layer.getVisible()) {\n const layerTitle = layer.get('title') || groupTitle || 'Unknown';\n const source = layer.getSource();\n if (!source) return;\n\n const candidates = source.getFeaturesInExtent(circleExtent);\n for (const f of candidates) {\n const fType = f.get('_layerType');\n if (fType === 'measure_circle' || fType === 'measure_circle_radius') continue;\n\n if (!intersectsCircle(f)) continue;\n\n if (fType === 'parcel') {\n parcelFeatures.push(f);\n } else if (fType === 'collector_zone') {\n zoneFeatures.push(f);\n } else {\n if (!otherByLayer[layerTitle]) otherByLayer[layerTitle] = [];\n otherByLayer[layerTitle].push(f);\n }\n }\n }\n });\n };\n\n scanGroup(this.overlayGroup, 'Overlays');\n\n // Build structured data rows\n const radiusFormatted = formatLength(radius);\n const areaSqm = Math.PI * radius * radius;\n const areaFormatted = formatArea(areaSqm);\n\n const dataRows = [\n { label: 'Radius', value: radiusFormatted, _first: true },\n { label: 'Area', value: areaFormatted },\n ...this._collectIntersectionRows(parcelFeatures, zoneFeatures, otherByLayer),\n ];\n\n this._showAnalysisPopup('⭕', 'Circle Analysis', dataRows, coordinate, {\n kind: 'circle',\n clipGeometry: circlePoly,\n parcelFeatures,\n zoneFeatures,\n otherByLayer,\n });\n }\n\n /**\n * Show an intersection-analysis popup for a measured area polygon.\n * Same logic as showCircleIntersectionPopup but works with an\n * arbitrary Polygon geometry instead of a circle.\n *\n * @param {Feature} polygonFeature - The measure_area feature\n * @param {number[]} coordinate - Map coordinate for the popup anchor\n */\n showAreaIntersectionPopup(polygonFeature, coordinate) {\n const polyGeom = polygonFeature.getGeometry();\n if (!polyGeom) return;\n\n const polyExtent = polyGeom.getExtent();\n\n // Compute area via ol/sphere for geodesic accuracy\n const areaSqm = getArea(polyGeom, { projection: 'EPSG:3857' });\n const areaFormatted = formatArea(areaSqm);\n\n // Compute perimeter\n const perimeterM = getLength(polyGeom, { projection: 'EPSG:3857' });\n const perimeterFormatted = formatLength(perimeterM);\n\n // Collect intersecting features grouped by layer type\n const parcelFeatures = [];\n const zoneFeatures = [];\n const otherByLayer = {};\n\n const intersectsPoly = (feature) => {\n const geom = feature.getGeometry();\n if (!geom) return false;\n const fExtent = geom.getExtent();\n if (\n fExtent[2] < polyExtent[0] ||\n fExtent[0] > polyExtent[2] ||\n fExtent[3] < polyExtent[1] ||\n fExtent[1] > polyExtent[3]\n ) {\n return false;\n }\n return polyGeom.intersectsExtent(fExtent) && this._geometriesIntersect(polyGeom, geom);\n };\n\n const scanGroup = (group, groupTitle) => {\n group.getLayers().forEach((layer) => {\n if (layer instanceof LayerGroup) {\n scanGroup(layer, layer.get('title') || groupTitle);\n } else if (layer instanceof VectorLayer && layer.getVisible()) {\n const layerTitle = layer.get('title') || groupTitle || 'Unknown';\n const source = layer.getSource();\n if (!source) return;\n\n const candidates = source.getFeaturesInExtent(polyExtent);\n for (const f of candidates) {\n const fType = f.get('_layerType');\n if (fType === 'measure_area' || fType === 'measure_circle' || fType === 'measure_circle_radius') continue;\n\n if (!intersectsPoly(f)) continue;\n\n if (fType === 'parcel') {\n parcelFeatures.push(f);\n } else if (fType === 'collector_zone') {\n zoneFeatures.push(f);\n } else {\n if (!otherByLayer[layerTitle]) otherByLayer[layerTitle] = [];\n otherByLayer[layerTitle].push(f);\n }\n }\n }\n });\n };\n\n scanGroup(this.overlayGroup, 'Overlays');\n\n // Build structured data rows\n const dataRows = [\n { label: 'Area', value: areaFormatted, _first: true },\n { label: 'Perimeter', value: perimeterFormatted },\n ...this._collectIntersectionRows(parcelFeatures, zoneFeatures, otherByLayer),\n ];\n\n this._showAnalysisPopup('📐', 'Area Analysis', dataRows, coordinate, {\n kind: 'area',\n clipGeometry: polyGeom,\n parcelFeatures,\n zoneFeatures,\n otherByLayer,\n });\n }\n\n /**\n * Test whether two geometries truly intersect (beyond just extent overlap).\n * Works for Polygon/MultiPolygon against any geometry type.\n *\n * @param {Geometry} geomA - First geometry (usually the circle polygon)\n * @param {Geometry} geomB - Second geometry\n * @returns {boolean}\n * @private\n */\n _geometriesIntersect(geomA, geomB) {\n const typeB = geomB.getType();\n\n // For polygons / multi-polygons: check if any coordinate of B is inside A,\n // or if any coordinate of A is inside B (covers overlap & containment).\n if (typeB === 'Polygon' || typeB === 'MultiPolygon') {\n // Check if any vertex of B lies inside A (use flatCoordinates for efficiency)\n const flatB = geomB.getFlatCoordinates();\n const stride = geomB.getStride();\n for (let i = 0; i < flatB.length; i += stride) {\n if (geomA.intersectsCoordinate([flatB[i], flatB[i + 1]])) return true;\n }\n // Check if any vertex of A lies inside B\n const flatA = geomA.getFlatCoordinates();\n const strideA = geomA.getStride();\n for (let i = 0; i < flatA.length; i += strideA) {\n if (geomB.intersectsCoordinate([flatA[i], flatA[i + 1]])) return true;\n }\n return false;\n }\n\n if (typeB === 'Point') {\n return geomA.intersectsCoordinate(geomB.getCoordinates());\n }\n\n if (typeB === 'LineString' || typeB === 'MultiLineString') {\n const flatB = geomB.getFlatCoordinates();\n const stride = geomB.getStride();\n for (let i = 0; i < flatB.length; i += stride) {\n if (geomA.intersectsCoordinate([flatB[i], flatB[i + 1]])) return true;\n }\n return false;\n }\n\n // Fallback: extent overlap is good enough\n return true;\n }\n\n // ============================================================================\n // Parcel Edit Popup (single-click editable form)\n // ============================================================================\n\n /**\n * Create the parcel edit popup overlay with a dynamic form.\n */\n createParcelEditPopup() {\n this.parcelEditElement = document.createElement('div');\n this.parcelEditElement.className = 'map-parcel-edit-popup';\n this.parcelEditElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n color: var(--card-foreground, #1e1a4b);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.3);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 280px;\n max-width: 360px;\n max-height: 420px;\n z-index: 1002;\n border: 2px solid var(--primary, #005eb8);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n `;\n\n this.parcelEditPopup = new Overlay({\n element: this.parcelEditElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true,\n autoPan: true,\n autoPanAnimation: { duration: 250 },\n });\n\n this.map.addOverlay(this.parcelEditPopup);\n\n // Callbacks for save events\n this._parcelEditCallbacks = [];\n // Track the current feature being edited\n this._parcelEditFeature = null;\n }\n\n /**\n * Show the parcel edit popup with an editable form for all feature attributes.\n * Internal keys (_layerType, geometry) are excluded from the form.\n *\n * @param {Feature} feature - The OL feature to edit\n * @param {Array} coordinate - Map coordinate [x, y]\n */\n showParcelEditPopup(feature, coordinate) {\n this._parcelEditFeature = feature;\n const properties = feature.getProperties();\n\n // Keys to skip in the form\n const skipKeys = ['geometry', '_layerType'];\n\n // Build form fields from feature properties\n let fieldsHtml = '';\n for (const [key, value] of Object.entries(properties)) {\n if (skipKeys.includes(key)) continue;\n const displayVal = (value === null || value === undefined) ? '' : String(value);\n const escapedKey = this.escapeHtml(key);\n const escapedVal = this.escapeHtml(displayVal);\n fieldsHtml += `\n \n ${escapedKey} \n \n
\n `;\n }\n\n const html = `\n \n ✏️ Edit Parcel \n × \n
\n \n `;\n\n this.parcelEditElement.innerHTML = html;\n this.parcelEditPopup.setPosition(coordinate);\n\n // Close / Cancel handlers\n this.parcelEditElement.querySelector('.parcel-edit-close').addEventListener('click', () => {\n this.hideParcelEditPopup();\n });\n this.parcelEditElement.querySelector('.parcel-edit-cancel').addEventListener('click', () => {\n this.hideParcelEditPopup();\n });\n\n // Form submit handler\n const form = this.parcelEditElement.querySelector('.parcel-edit-form');\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n\n // Collect all edited values\n const formData = new FormData(form);\n const updatedProps = {};\n for (const [key, value] of formData.entries()) {\n updatedProps[key] = value;\n }\n\n // Restore internal properties that were excluded from the form\n updatedProps._layerType = 'parcel';\n\n // Update the feature's properties in-place\n for (const [key, value] of Object.entries(updatedProps)) {\n this._parcelEditFeature.set(key, value);\n }\n\n // Notify external listeners\n for (const cb of this._parcelEditCallbacks) {\n cb(this._parcelEditFeature, updatedProps);\n }\n\n this.hideParcelEditPopup();\n });\n }\n\n /**\n * Hide the parcel edit popup.\n */\n hideParcelEditPopup() {\n this.parcelEditPopup.setPosition(undefined);\n this._parcelEditFeature = null;\n }\n\n /**\n * Register a callback for when a parcel edit is saved.\n * Callback receives (feature, updatedProperties).\n *\n * @param {Function} callback\n */\n onParcelEdit(callback) {\n this._parcelEditCallbacks.push(callback);\n }\n\n // ============================================================================\n // Merge Identifier (UPN) Chooser Popup\n // ============================================================================\n\n /**\n * Create the merge identifier popup overlay.\n * Shown after two parcels are merged so the user can choose which UPN to keep.\n */\n createMergePopup() {\n this.mergePopupElement = document.createElement('div');\n this.mergePopupElement.className = 'map-merge-popup';\n this.mergePopupElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n color: var(--card-foreground, #1e1a4b);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.3);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 280px;\n max-width: 360px;\n z-index: 1002;\n border: 2px solid #10b981;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n `;\n\n this.mergePopup = new Overlay({\n element: this.mergePopupElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true,\n autoPan: true,\n autoPanAnimation: { duration: 250 },\n });\n\n this.map.addOverlay(this.mergePopup);\n }\n\n /**\n * Show the merge identifier popup so the user can pick which parcel's\n * attributes (including UPN) the merged polygon should inherit.\n *\n * @param {Feature} mergedFeature The newly created merged feature\n * @param {Object} propsA Properties from original parcel A\n * @param {Object} propsB Properties from original parcel B\n * @param {Array} coordinate Map coordinate [x, y] for popup placement\n */\n showMergeIdentifierPopup(mergedFeature, propsA, propsB, coordinate) {\n // Extract identifiers — try common parcel ID field names\n const idFields = ['UPN', 'upn', 'id', 'parcelid', 'parcel_id', 'PARCELID', 'PARCEL_ID', 'ID'];\n const getLabel = (props) => {\n for (const field of idFields) {\n if (props[field] !== undefined && props[field] !== null && String(props[field]).trim()) {\n return { field, value: String(props[field]) };\n }\n }\n return { field: 'id', value: 'Unknown' };\n };\n\n const labelA = getLabel(propsA);\n const labelB = getLabel(propsB);\n\n const html = `\n \n 🔗 Merged Parcel — Choose Identifier \n \n
\n \n
\n Select which parcel's attributes the merged polygon should keep:\n
\n
\n \n \n
Parcel A
\n
${this.escapeHtml(labelA.field)}: ${this.escapeHtml(labelA.value)}
\n
\n \n
\n \n \n
Parcel B
\n
${this.escapeHtml(labelB.field)}: ${this.escapeHtml(labelB.value)}
\n
\n \n
\n \n \n
\n
\n `;\n\n this.mergePopupElement.innerHTML = html;\n this.mergePopup.setPosition(coordinate);\n\n // Close / Cancel — keep parcel A properties (the default from clone)\n const close = () => {\n this.mergePopup.setPosition(undefined);\n };\n this.mergePopupElement.querySelector('.merge-popup-close').addEventListener('click', close);\n this.mergePopupElement.querySelector('.merge-popup-cancel').addEventListener('click', close);\n\n // Confirm — apply chosen parcel's properties\n this.mergePopupElement.querySelector('.merge-popup-confirm').addEventListener('click', () => {\n const choice = this.mergePopupElement.querySelector('input[name=\"merge-choice\"]:checked').value;\n const chosenProps = choice === 'A' ? propsA : propsB;\n\n // Copy all properties (except geometry) onto the merged feature\n const skipKeys = ['geometry'];\n for (const [key, value] of Object.entries(chosenProps)) {\n if (skipKeys.includes(key)) continue;\n mergedFeature.set(key, value);\n }\n // Ensure _layerType is preserved\n mergedFeature.set('_layerType', 'parcel');\n\n // Notify parcel edit callbacks\n for (const cb of this._parcelEditCallbacks) {\n cb(mergedFeature, chosenProps);\n }\n\n close();\n });\n\n // Highlight radio labels on selection\n const labels = this.mergePopupElement.querySelectorAll('label');\n const radios = this.mergePopupElement.querySelectorAll('input[name=\"merge-choice\"]');\n const updateHighlight = () => {\n labels.forEach((lbl) => {\n const radio = lbl.querySelector('input');\n lbl.style.borderColor = radio.checked ? (radio.value === 'A' ? '#0ea5e9' : '#f59e0b') : 'var(--border, #1e1a4b1f)';\n });\n };\n radios.forEach((r) => r.addEventListener('change', updateHighlight));\n updateHighlight();\n }\n\n // ============================================================================\n // Divide Polygon Popup (number input)\n // ============================================================================\n\n /**\n * Create the divide polygon popup overlay.\n * Shown after the user selects a polygon with the Divide tool, so they\n * can enter the number of equal pieces.\n */\n createDividePopup() {\n this.dividePopupElement = document.createElement('div');\n this.dividePopupElement.className = 'map-divide-popup';\n this.dividePopupElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n color: var(--card-foreground, #1e1a4b);\n border-radius: 10px;\n box-shadow: 0 4px 20px rgba(0,0,0,0.3);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 260px;\n max-width: 320px;\n z-index: 1002;\n border: 2px solid #8b5cf6;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n `;\n\n this.dividePopup = new Overlay({\n element: this.dividePopupElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true,\n autoPan: true,\n autoPanAnimation: { duration: 250 },\n });\n\n this.map.addOverlay(this.dividePopup);\n }\n\n /**\n * Show the divide popup so the user can enter the number of divisions.\n *\n * @param {Feature} feature The selected polygon feature\n * @param {VectorSource} source The source containing the feature\n * @param {Array} coordinate Map coordinate [x, y] for popup placement\n */\n showDividePopup(feature, source, coordinate) {\n const html = `\n \n Divide Polygon \n \n
\n \n
\n Enter the number of equal pieces:\n
\n
\n
\n \n \n
\n
\n `;\n\n this.dividePopupElement.innerHTML = html;\n this.dividePopup.setPosition(coordinate);\n\n const input = this.dividePopupElement.querySelector('.divide-input');\n input.focus();\n input.select();\n\n // Close / Cancel\n const cancel = () => {\n this.hideDividePopup();\n this._polygonDivideInteraction.cancelDivide();\n };\n this.dividePopupElement.querySelector('.divide-popup-close').addEventListener('click', cancel);\n this.dividePopupElement.querySelector('.divide-popup-cancel').addEventListener('click', cancel);\n\n // Confirm\n this.dividePopupElement.querySelector('.divide-popup-confirm').addEventListener('click', () => {\n const n = parseInt(input.value, 10);\n if (!n || n < 2) {\n input.style.borderColor = '#ef4444';\n return;\n }\n this.hideDividePopup();\n this._polygonDivideInteraction.performDivide(n);\n });\n\n // Allow Enter key to confirm\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n this.dividePopupElement.querySelector('.divide-popup-confirm').click();\n }\n });\n }\n\n /**\n * Hide the divide popup.\n */\n hideDividePopup() {\n this.dividePopup.setPosition(undefined);\n }\n\n // ============================================================================\n // Drawn Polygon Attribute Popup\n // ============================================================================\n\n /**\n * Create the drawn polygon attribute popup overlay.\n * Shown after the area measurement polygon is completed so the user can\n * attach parcel-like attributes to the drawn polygon.\n */\n createDrawnPolygonPopup() {\n this.drawnPolygonElement = document.createElement('div');\n this.drawnPolygonElement.className = 'map-drawn-polygon-popup';\n this.drawnPolygonElement.style.cssText = `\n position: absolute;\n background: var(--card, #fff);\n border-radius: var(--radius-xl, 0.75rem);\n box-shadow: 0 4px 20px rgba(0,0,0,0.2);\n font-family: var(--font-body, 'Exo', sans-serif);\n font-size: 13px;\n min-width: 280px;\n max-width: 360px;\n max-height: 420px;\n z-index: 1002;\n border: 2px solid var(--success, #006b3f);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n `;\n\n this.drawnPolygonPopup = new Overlay({\n element: this.drawnPolygonElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true,\n autoPan: true,\n autoPanAnimation: { duration: 250 },\n });\n\n this.map.addOverlay(this.drawnPolygonPopup);\n this._drawnPolygonCallbacks = [];\n this._drawnPolygonFeature = null;\n }\n\n /**\n * Get attribute keys from existing parcel features on the map.\n * Scans the overlay group for the first feature with _layerType='parcel'\n * and returns its property key names (excluding internal keys).\n *\n * @returns {string[]} Array of attribute key names\n */\n getParcelAttributeKeys() {\n const skipKeys = ['geometry', '_layerType'];\n const keys = [];\n\n const scanGroup = (group) => {\n if (keys.length > 0) return;\n group.getLayers().forEach((layer) => {\n if (keys.length > 0) return;\n if (layer instanceof LayerGroup) {\n scanGroup(layer);\n } else if (layer instanceof VectorLayer) {\n const source = layer.getSource();\n if (!source) return;\n for (const f of source.getFeatures()) {\n if (f.get('_layerType') !== 'parcel') continue;\n const props = f.getProperties();\n for (const key of Object.keys(props)) {\n if (!skipKeys.includes(key)) keys.push(key);\n }\n return; // one parcel is enough for the schema\n }\n }\n });\n };\n\n scanGroup(this.overlayGroup);\n return keys;\n }\n\n /**\n * Show the drawn polygon attribute popup.\n * Discovers attribute keys from existing parcel features and creates\n * a blank form with those fields.\n *\n * @param {Feature} feature - The drawn polygon feature\n * @param {Array} coordinate - Map coordinate [x, y] for popup placement\n */\n showDrawnPolygonPopup(feature, coordinate) {\n this._drawnPolygonFeature = feature;\n\n // Discover attribute keys from existing parcels\n const attributeKeys = this.getParcelAttributeKeys();\n\n if (attributeKeys.length === 0) {\n console.warn('[MapView] No parcel attributes found — cannot build form');\n return;\n }\n\n // Build form fields (all blank)\n let fieldsHtml = '';\n for (const key of attributeKeys) {\n const escapedKey = this.escapeHtml(key);\n fieldsHtml += `\n \n ${escapedKey} \n \n
\n `;\n }\n\n // Area display\n const geom = feature.getGeometry();\n const areaSqm = getArea(geom, { projection: 'EPSG:3857' });\n const areaFormatted = formatArea(areaSqm);\n\n const html = `\n \n 📐 Polygon Attributes \n × \n
\n \n Area: ${areaFormatted} \n
\n \n `;\n\n this.drawnPolygonElement.innerHTML = html;\n this.drawnPolygonPopup.setPosition(coordinate);\n\n // Close / Cancel handlers\n this.drawnPolygonElement.querySelector('.drawn-polygon-close').addEventListener('click', () => {\n this.hideDrawnPolygonPopup();\n });\n this.drawnPolygonElement.querySelector('.drawn-polygon-cancel').addEventListener('click', () => {\n this.hideDrawnPolygonPopup();\n });\n\n // Form submit handler\n const form = this.drawnPolygonElement.querySelector('.drawn-polygon-form');\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n\n const formData = new FormData(form);\n const props = {};\n for (const [key, value] of formData.entries()) {\n props[key] = value;\n }\n\n // Set properties on the feature\n for (const [key, value] of Object.entries(props)) {\n this._drawnPolygonFeature.set(key, value);\n }\n\n // Tag as parcel so it integrates with existing parcel tools\n this._drawnPolygonFeature.set('_layerType', 'parcel');\n\n // Notify listeners\n for (const cb of this._drawnPolygonCallbacks) {\n cb(this._drawnPolygonFeature, props);\n }\n\n this.hideDrawnPolygonPopup();\n });\n }\n\n /**\n * Hide the drawn polygon attribute popup.\n */\n hideDrawnPolygonPopup() {\n this.drawnPolygonPopup.setPosition(undefined);\n this._drawnPolygonFeature = null;\n }\n\n /**\n * Register a callback for when drawn polygon attributes are saved.\n * Callback receives (feature, properties).\n *\n * @param {Function} callback\n */\n onDrawnPolygonSave(callback) {\n this._drawnPolygonCallbacks.push(callback);\n }\n\n /**\n * Register a callback fired after the user finishes modifying a feature\n * with the EditBar Modify interaction. Callback receives the OL feature\n * whose geometry just changed. Consumers (e.g. the import-staging code in\n * main.js) inspect the feature's tags (_externalImportId / _clientUuid)\n * to decide whether to react. Multiple callbacks are supported.\n *\n * @param {Function} callback - (feature) => void | Promise\n */\n onFeatureModified(callback) {\n if (!this._featureModifiedCallbacks) this._featureModifiedCallbacks = [];\n this._featureModifiedCallbacks.push(callback);\n }\n\n /**\n * Register a double-click callback.\n * Callback receives (lon, lat, feature, event).\n * Feature is the first feature found at the click pixel across all overlay layers,\n * or null if no feature was hit.\n * When a feature is hit, the default double-click-zoom is suppressed.\n */\n onDblClick(callback) {\n this.dblClickCallbacks.push(callback);\n\n // Set up the listener once\n if (this.dblClickCallbacks.length === 1) {\n this.map.on('dblclick', (evt) => {\n const [lon, lat] = toLonLat(evt.coordinate);\n\n // Find any feature at the clicked pixel (overlay layers, not just markers)\n let clickedFeature = null;\n this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {\n clickedFeature = feature;\n return true; // stop at first hit\n });\n\n // If a feature was hit, prevent the default double-click zoom\n if (clickedFeature) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Call all registered callbacks\n for (const cb of this.dblClickCallbacks) {\n cb(lon, lat, clickedFeature, evt);\n }\n\n // Return false to suppress DoubleClickZoom interaction when on a feature\n if (clickedFeature) return false;\n });\n }\n\n return () => {\n const idx = this.dblClickCallbacks.indexOf(callback);\n if (idx > -1) this.dblClickCallbacks.splice(idx, 1);\n };\n }\n\n /**\n * Escape HTML to prevent XSS\n */\n escapeHtml(text) {\n if (!text) return '';\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n /**\n * Create the Add Location popup form overlay\n */\n createAddLocationPopup() {\n // Create popup container element\n this.addLocationPopupElement = document.createElement('div');\n this.addLocationPopupElement.className = 'map-add-location-popup';\n this.addLocationPopupElement.innerHTML = `\n \n \n `;\n\n // Create the overlay\n this.addLocationPopup = new Overlay({\n element: this.addLocationPopupElement,\n positioning: 'bottom-center',\n offset: [0, -10],\n stopEvent: true, // Prevent click from propagating\n autoPan: true,\n autoPanAnimation: {\n duration: 250,\n },\n });\n\n this.map.addOverlay(this.addLocationPopup);\n\n // Store clicked coordinates\n this.addLocationCoords = null;\n\n // Set up close button handler\n const closeBtn = this.addLocationPopupElement.querySelector('.add-location-popup-close');\n closeBtn.addEventListener('click', () => {\n this.hideAddLocationPopup();\n });\n\n // Store form submit callbacks\n this.addLocationCallbacks = [];\n }\n\n /**\n * Show the Add Location popup at the specified coordinate\n */\n showAddLocationPopup(coordinate) {\n const [lon, lat] = toLonLat(coordinate);\n this.addLocationCoords = { lon, lat };\n\n // Update coordinates display\n const coordsEl = this.addLocationPopupElement.querySelector('#map-location-coords');\n coordsEl.textContent = `${lon.toFixed(6)}, ${lat.toFixed(6)}`;\n\n // Reset form\n const form = this.addLocationPopupElement.querySelector('#map-add-location-form');\n form.reset();\n\n // Position and show popup\n this.addLocationPopup.setPosition(coordinate);\n }\n\n /**\n * Hide the Add Location popup\n */\n hideAddLocationPopup() {\n this.addLocationPopup.setPosition(undefined);\n this.addLocationCoords = null;\n }\n\n /**\n * Register a callback for when a location is submitted via the map popup\n * Callback receives: { name, category, description, lon, lat }\n */\n onAddLocation(callback) {\n this.addLocationCallbacks.push(callback);\n\n // Set up form submit handler (only once)\n if (this.addLocationCallbacks.length === 1) {\n const form = this.addLocationPopupElement.querySelector('#map-add-location-form');\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n\n if (!this.addLocationCoords) return;\n\n const formData = new FormData(form);\n const data = {\n name: formData.get('name'),\n category: formData.get('category'),\n description: formData.get('description'),\n lon: this.addLocationCoords.lon,\n lat: this.addLocationCoords.lat,\n };\n\n // Call all registered callbacks\n this.addLocationCallbacks.forEach(cb => cb(data));\n\n // Hide popup after submission\n this.hideAddLocationPopup();\n });\n }\n }\n\n /**\n * Create base layers group for LayerSwitcher\n */\n createBaseLayers(defaultBasemap) {\n\n\n const topoLayer = new TileLayer({\n title: 'Topographic',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'topo',\n source: new XYZ({\n url: 'https://{a-c}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attributions: 'Map data: © OpenTopoMap',\n maxZoom: 17,\n crossOrigin: 'anonymous',\n }),\n });\n topoLayer.set('basemapKey', 'topo');\n\n const cartoLightLayer = new TileLayer({\n title: 'Carto Light',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'carto-light',\n source: new XYZ({\n url: 'https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',\n attributions: '© CARTO',\n maxZoom: 19,\n crossOrigin: 'anonymous',\n }),\n });\n cartoLightLayer.set('basemapKey', 'carto-light');\n\n const cartoDarkLayer = new TileLayer({\n title: 'Carto Dark',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'carto-dark',\n source: new XYZ({\n url: 'https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',\n attributions: '© CARTO',\n maxZoom: 19,\n crossOrigin: 'anonymous',\n }),\n });\n cartoDarkLayer.set('basemapKey', 'carto-dark');\n\n const osmCycleLayer = new TileLayer({\n title: 'OSM Cycle map',\n type: 'base',\n zIndex: -100,\n visible: false, //defaultBasemap === 'osm',\n source: new OSM({\n \t\t\t\t\t\"url\" : \"https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=ae1339c46dd3446b9c491e7336d38760\"\n\t\t\t\t\t\t}),\n });\n\n osmCycleLayer.set('basemapKey', 'cycle');\n\n const satelliteLayer = new TileLayer({\n title: 'Satellite',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'satellite',\n source: new XYZ({\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attributions: 'Tiles © Esri',\n maxZoom: 19,\n crossOrigin: 'anonymous',\n }),\n });\n satelliteLayer.set('basemapKey', 'satellite');\n const googleLayer = new TileLayer({\n title: 'Google Sat',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'googlesat',\n source: new XYZ({\n// url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n url: 'http://mt0.google.com/vt/lyrs=y&hl=en&x={x}&y={y}&z={z}&s=Ga',\n attributions: 'Tiles © Google',\n maxZoom: 19,\n crossOrigin: 'anonymous',\n }),\n });\n googleLayer.set('basemapKey', 'googlesat');\n\n const osmLayer = new TileLayer({\n title: 'OpenStreetMap',\n type: 'base',\n zIndex: -100,\n visible: defaultBasemap === 'osm',\n source: new OSM(),\n });\n osmLayer.set('basemapKey', 'osm');\n\n // Remember the base-map layers so setBaseMap() can toggle visibility later\n this._baseMapLayers = [\n cartoLightLayer, cartoDarkLayer, osmCycleLayer,\n satelliteLayer, googleLayer, osmLayer, topoLayer,\n ];\n\n\n // Return LayerGroup. Hidden from the main LayerSwitcher — base maps are\n // managed by the dedicated base-map picker (see _createBaseMapPicker)\n // accessed via the layers-stack icon above the My Location button.\n const baseGroup = new LayerGroup({\n title: 'Base Maps',\n layers: [\n cartoLightLayer,\n cartoDarkLayer,\n satelliteLayer,\n osmCycleLayer,\n googleLayer,\n osmLayer,\n topoLayer,\n ],\n });\n baseGroup.set('displayInLayerSwitcher', false);\n return baseGroup;\n }\n\n /**\n * Switch the active base map by key.\n * Sets exactly one base layer visible; hides all others.\n *\n * @param {string} key Basemap key: 'none' | 'topo' | 'osm' | 'satellite' | 'googlesat' | 'carto-light' | 'carto-dark' | 'cycle'\n * @returns {boolean} true if the key matched a known base layer (or 'none')\n */\n setBaseMap(key) {\n if (!this._baseMapLayers) return false;\n // 'none' switches the base map off entirely — hide every base layer so the\n // map renders on a blank background (useful over imagery overlays / when a\n // full-coverage overlay should stand alone).\n if (key === 'none') {\n for (const layer of this._baseMapLayers) layer.setVisible(false);\n console.log('[MapView] Base map switched off (none)');\n this.map.dispatchEvent({ type: 'basemapchange', key: 'none' });\n return true;\n }\n let matched = false;\n for (const layer of this._baseMapLayers) {\n const on = layer.get('basemapKey') === key;\n layer.setVisible(on);\n if (on) matched = true;\n }\n if (matched) {\n console.log('[MapView] Base map switched to:', key);\n // Notify external UIs (Settings dropdown, base-map picker, …) so they\n // can keep their visible state in sync.\n this.map.dispatchEvent({ type: 'basemapchange', key });\n }\n return matched;\n }\n\n /**\n * Build the floating \"Base Map\" picker — a small icon button stacked\n * directly above the My Location control, plus a slide-out card with\n * thumbnail chips for every selectable base map.\n *\n * Hidden in tandem with the main LayerSwitcher: clicking outside the\n * picker (or making a selection) closes it.\n *\n * Two-way sync with the existing Settings dropdown is via the\n * `basemapchange` event fired from setBaseMap().\n */\n _createBaseMapPicker() {\n // Configuration — must match the basemapKey set in createBaseLayers.\n // The colour gradients hint at each base map's character so the chip is\n // recognisable without rendering an actual tile preview.\n const OPTIONS = [\n { key: 'topo', label: 'Topographic', grad: 'linear-gradient(135deg,#e8d5b7,#a67c52)' },\n { key: 'osm', label: 'OpenStreetMap',grad: 'linear-gradient(135deg,#d4e6f1,#85c1e9)' },\n { key: 'satellite', label: 'Satellite', grad: 'linear-gradient(135deg,#1b4332,#40916c)' },\n { key: 'googlesat', label: 'Google Sat', grad: 'linear-gradient(135deg,#2a5d3d,#4a8c5a)' },\n { key: 'carto-light', label: 'Carto Light', grad: 'linear-gradient(135deg,#f5f5f5,#d4d4d4)' },\n { key: 'carto-dark', label: 'Carto Dark', grad: 'linear-gradient(135deg,#1a1a2e,#0f3460)' },\n // \"None\" turns the base map off — checkerboard hints at a blank/transparent background.\n { key: 'none', label: 'None', grad: 'repeating-conic-gradient(#e5e7eb 0 25%, #fff 0 50%) 50% / 12px 12px' },\n ];\n\n const target = this.map.getTargetElement();\n if (!target) return;\n\n // ---------- Toggle button ----------\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'ls-basemap-toggle';\n btn.title = 'Switch base map';\n btn.setAttribute('aria-label', 'Switch base map');\n btn.innerHTML =\n '' +\n '' +\n '' +\n '' +\n ' ';\n target.appendChild(btn);\n\n // ---------- Picker panel ----------\n const panel = document.createElement('div');\n panel.className = 'ls-basemap-panel';\n panel.innerHTML =\n '' +\n '';\n target.appendChild(panel);\n\n this._basemapPanel = panel;\n this._basemapToggle = btn;\n\n /** Mark the radio matching the currently-visible base layer. */\n const syncSelection = (key) => {\n const k = key || this._baseMapLayers?.find((l) => l.getVisible())?.get('basemapKey');\n panel.querySelectorAll('input[name=\"lupmis-basemap\"]').forEach((r) => {\n r.checked = (r.value === k);\n });\n };\n syncSelection();\n\n // ---------- Events ----------\n\n // Toggle button → open / close the panel\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n const open = !panel.classList.contains('open');\n panel.classList.toggle('open', open);\n btn.classList.toggle('active', open);\n if (open) syncSelection();\n });\n\n // Click outside → close\n document.addEventListener('click', (e) => {\n if (!panel.classList.contains('open')) return;\n if (panel.contains(e.target) || btn.contains(e.target)) return;\n panel.classList.remove('open');\n btn.classList.remove('active');\n });\n\n // Selection → apply, persist, close\n panel.addEventListener('change', (e) => {\n const radio = e.target.closest('input[type=radio][name=\"lupmis-basemap\"]');\n if (!radio) return;\n const key = radio.value;\n this.setBaseMap(key);\n try { localStorage.setItem('default-basemap', key); } catch {}\n panel.classList.remove('open');\n btn.classList.remove('active');\n });\n\n // Keep the radio state synced when other UIs (Settings dropdown) change it\n this.map.on('basemapchange', (evt) => syncSelection(evt.key));\n }\n\n // ============================================================================\n // GPS: current-position + trail rendering, and the expandable Location control\n //\n // NOTE: MapView deliberately knows nothing about the GeoTracker engine,\n // SQLocal, or sync. It only (a) renders what it's told and (b) emits UI\n // intents via callbacks. main.js wires those intents to the GeoTracker so the\n // map stays reusable/decoupled.\n // ============================================================================\n\n /** Create the vector layers used to draw the live position and the trail. */\n _initGpsRendering() {\n this._gpsPositionSource = new VectorSource();\n this._gpsTrailSource = new VectorSource();\n this._gpsTrailCoords = []; // [ [x,y], ... ] in map projection\n\n // Trail line (drawn under the position marker)\n this._gpsTrailLayer = new VectorLayer({\n source: this._gpsTrailSource,\n zIndex: 940,\n style: new Style({\n stroke: new Stroke({ color: '#ff6d00', width: 4, lineCap: 'round', lineJoin: 'round' }),\n }),\n properties: { title: 'GPS Trail', displayInLayerSwitcher: false },\n });\n\n // Current position: accuracy halo + solid dot\n this._gpsPositionLayer = new VectorLayer({\n source: this._gpsPositionSource,\n zIndex: 950,\n style: (feature) => {\n if (feature.get('_kind') === 'accuracy') {\n return new Style({\n fill: new Fill({ color: 'rgba(0,94,184,0.12)' }),\n stroke: new Stroke({ color: 'rgba(0,94,184,0.35)', width: 1 }),\n });\n }\n return new Style({\n image: new Circle({\n radius: 7,\n fill: new Fill({ color: '#005eb8' }),\n stroke: new Stroke({ color: '#ffffff', width: 2.5 }),\n }),\n });\n },\n properties: { title: 'GPS Position', displayInLayerSwitcher: false },\n });\n\n this.map.addLayer(this._gpsTrailLayer);\n this.map.addLayer(this._gpsPositionLayer);\n\n this._gpsCallbacks = { locate: [], record: [] };\n this._gpsRecording = false;\n }\n\n /** Register a callback fired when the user taps \"Locate Me\". */\n onLocateMe(cb) { this._gpsCallbacks.locate.push(cb); }\n /** Register a callback fired when the user toggles trail recording. Receives the desired state (true=start). */\n onToggleRecording(cb) { this._gpsCallbacks.record.push(cb); }\n\n /**\n * Draw / move the current-position marker and accuracy halo.\n * @param {number} lon\n * @param {number} lat\n * @param {number|null} [accuracy] horizontal accuracy in metres\n */\n showCurrentPosition(lon, lat, accuracy = null) {\n if (lon == null || lat == null) return;\n const center = fromLonLat([lon, lat]);\n this._gpsPositionSource.clear();\n\n if (accuracy && accuracy > 0) {\n // Approximate the accuracy circle in projected units. Good enough for a\n // visual halo at typical zoom levels.\n const resAtLat = accuracy / Math.cos((lat * Math.PI) / 180);\n const halo = new Feature({ geometry: new PolygonGeom([this._circleRing(center, resAtLat)]) });\n halo.set('_kind', 'accuracy');\n this._gpsPositionSource.addFeature(halo);\n }\n const dot = new Feature({ geometry: new Point(center) });\n dot.set('_kind', 'dot');\n this._gpsPositionSource.addFeature(dot);\n }\n\n /** @private build a ring of coordinates approximating a circle (metres → projected). */\n _circleRing(center, radiusMeters, segments = 48) {\n // Convert metres to projected units (Web Mercator) roughly via the\n // resolution at the centre latitude.\n const ring = [];\n const metersPerUnit = 1; // EPSG:3857 units are metres (approx near equator/locally)\n const r = radiusMeters / metersPerUnit;\n for (let i = 0; i <= segments; i++) {\n const a = (i / segments) * 2 * Math.PI;\n ring.push([center[0] + r * Math.cos(a), center[1] + r * Math.sin(a)]);\n }\n return ring;\n }\n\n /** Smoothly center the view on a coordinate. */\n centerOn(lon, lat, zoom = 16) {\n const view = this.map.getView();\n view.animate({ center: fromLonLat([lon, lat]), zoom, duration: 500 });\n }\n\n /** Reset the trail line (call when a new recording starts). */\n startTrailRender() {\n this._gpsTrailCoords = [];\n this._gpsTrailSource.clear();\n }\n\n /** Append a coordinate to the growing trail line. */\n appendTrailPoint(lon, lat) {\n if (lon == null || lat == null) return;\n this._gpsTrailCoords.push(fromLonLat([lon, lat]));\n this._gpsTrailSource.clear();\n if (this._gpsTrailCoords.length >= 2) {\n this._gpsTrailSource.addFeature(new Feature({ geometry: new LineString(this._gpsTrailCoords) }));\n }\n }\n\n /** Remove the rendered trail (does not affect stored data). */\n clearTrailRender() {\n this._gpsTrailCoords = [];\n this._gpsTrailSource.clear();\n }\n\n /** Reflect recording state on the control button. */\n setRecordingState(active) {\n this._gpsRecording = !!active;\n if (this._recordBtn) {\n this._recordBtn.classList.toggle('recording', this._gpsRecording);\n this._recordBtn.title = this._gpsRecording ? 'Stop trail recording' : 'Record GPS trail';\n this._recordBtn.innerHTML = this._gpsRecording\n ? ' '\n : ' ';\n }\n if (this._locateToggle) this._locateToggle.classList.toggle('recording', this._gpsRecording);\n }\n\n /**\n * Build the expandable \"My Location\" control: a main button that reveals two\n * sub-buttons (Locate Me, Record Trail). Anchored at the same spot the old\n * ol-ext GeolocationButton occupied (bottom-right), so the base-map picker\n * still lines up above it.\n */\n _createLocationControl() {\n const target = this.map.getTargetElement();\n if (!target) return;\n\n // Main toggle\n const toggle = document.createElement('button');\n toggle.type = 'button';\n toggle.className = 'ls-locate-toggle';\n toggle.title = 'My Location';\n toggle.setAttribute('aria-label', 'My Location');\n toggle.innerHTML = ' ';\n target.appendChild(toggle);\n\n // Sub-button cluster (hidden until the main button is tapped)\n const actions = document.createElement('div');\n actions.className = 'ls-locate-actions';\n actions.innerHTML =\n '' +\n ' ' +\n '' +\n ' ';\n target.appendChild(actions);\n\n this._locateToggle = toggle;\n this._locateActions = actions;\n this._locateMeBtn = actions.querySelector('.ls-locate-me');\n this._recordBtn = actions.querySelector('.ls-locate-record');\n\n const close = () => { actions.classList.remove('open'); toggle.classList.remove('active'); };\n const open = () => { actions.classList.add('open'); toggle.classList.add('active'); };\n\n toggle.addEventListener('click', (e) => {\n e.stopPropagation();\n actions.classList.contains('open') ? close() : open();\n });\n\n // Tap outside closes the cluster (but never while recording, so the stop\n // button stays reachable).\n document.addEventListener('click', (e) => {\n if (!actions.classList.contains('open')) return;\n if (actions.contains(e.target) || toggle.contains(e.target)) return;\n if (this._gpsRecording) return;\n close();\n });\n\n this._locateMeBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n for (const cb of this._gpsCallbacks.locate) { try { cb(); } catch (err) { console.error(err); } }\n if (!this._gpsRecording) close();\n });\n\n this._recordBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n const next = !this._gpsRecording;\n for (const cb of this._gpsCallbacks.record) { try { cb(next); } catch (err) { console.error(err); } }\n });\n }\n\n /**\n * Get style for a feature (handles selection state)\n */\n getFeatureStyle(feature) {\n const category = feature.get('category') || 'default';\n const emoji = this.getEmoji(category);\n\n if (feature === this.selectedFeature) {\n // Return selected style with the correct emoji and highlight\n return [\n // Background highlight circle\n new Style({\n image: new Circle({\n radius: 22,\n fill: new Fill({ color: 'rgba(220, 38, 38, 0.25)' }),\n stroke: new Stroke({ color: '#dc2626', width: 3 }),\n }),\n }),\n // Emoji on top, larger\n new Style({\n text: new Text({\n text: emoji,\n font: '40px sans-serif',\n textBaseline: 'bottom',\n textAlign: 'center',\n offsetY: -5,\n }),\n }),\n ];\n }\n\n // Check for custom style\n const customStyle = feature.get('style');\n if (customStyle) {\n return customStyle;\n }\n\n // Return category-based emoji style\n if (this.categoryStyles[category]) {\n return this.categoryStyles[category];\n }\n\n return this.defaultStyle;\n }\n\n /**\n * Set category-based styles with emojis\n * @param {Object} styles - Map of category to config { emoji, label, fontSize }\n */\n setCategoryStyles(styles) {\n for (const [category, config] of Object.entries(styles)) {\n // Update category mapping if provided\n if (config.emoji) {\n if (!this.categoryEmojis[category]) {\n this.categoryEmojis[category] = { emoji: config.emoji, label: config.label || category };\n } else {\n this.categoryEmojis[category].emoji = config.emoji;\n if (config.label) {\n this.categoryEmojis[category].label = config.label;\n }\n }\n }\n\n // Create/update style\n const emoji = this.getEmoji(category);\n const fontSize = config.fontSize || 28;\n\n this.categoryStyles[category] = this.createEmojiStyle(emoji, fontSize);\n }\n\n // Refresh markers\n this.markerSource.changed();\n }\n\n /**\n * Add a single marker\n */\n addMarker(lon, lat, properties = {}) {\n console.log('[MapView] Adding marker at', lon, lat, 'with properties:', properties);\n\n const feature = new Feature({\n geometry: new Point(fromLonLat([lon, lat])),\n ...properties,\n });\n\n // Store original coordinates for easy access\n feature.set('lon', lon);\n feature.set('lat', lat);\n\n this.markerSource.addFeature(feature);\n console.log('[MapView] Marker added, total features:', this.markerSource.getFeatures().length);\n return feature;\n }\n\n /**\n * Add multiple markers from an array of location objects\n */\n addMarkers(locations) {\n console.log('[MapView] Adding', locations.length, 'markers');\n\n const features = locations.map((loc) => {\n const feature = new Feature({\n geometry: new Point(fromLonLat([loc.longitude, loc.latitude])),\n id: loc.id,\n name: loc.name,\n description: loc.description,\n category: loc.category,\n lon: loc.longitude,\n lat: loc.latitude,\n });\n return feature;\n });\n\n this.markerSource.addFeatures(features);\n console.log('[MapView] Markers added, total features:', this.markerSource.getFeatures().length);\n return features;\n }\n\n /**\n * Clear all markers\n */\n clearMarkers() {\n this.markerSource.clear();\n this.selectedFeature = null;\n }\n\n /**\n * Remove a specific marker by feature or ID\n */\n removeMarker(featureOrId) {\n if (typeof featureOrId === 'object') {\n this.markerSource.removeFeature(featureOrId);\n } else {\n const feature = this.markerSource.getFeatures().find(\n f => f.get('id') === featureOrId\n );\n if (feature) {\n this.markerSource.removeFeature(feature);\n }\n }\n }\n\n /**\n * Get all markers\n */\n getMarkers() {\n return this.markerSource.getFeatures();\n }\n\n /**\n * Find marker by ID\n */\n findMarker(id) {\n return this.markerSource.getFeatures().find(f => f.get('id') === id);\n }\n\n /**\n * Select a marker (highlights it)\n */\n selectMarker(featureOrId) {\n if (typeof featureOrId === 'object') {\n this.selectedFeature = featureOrId;\n } else {\n this.selectedFeature = this.findMarker(featureOrId);\n }\n this.markerSource.changed();\n return this.selectedFeature;\n }\n\n /**\n * Clear selection\n */\n clearSelection() {\n this.selectedFeature = null;\n this.markerSource.changed();\n }\n\n /**\n * Zoom to a specific location\n */\n zoomTo(lon, lat, zoom = 15) {\n this.map.getView().animate({\n center: fromLonLat([lon, lat]),\n zoom: zoom,\n duration: 500,\n });\n }\n\n /**\n * Fit view to show all markers\n */\n fitToMarkers(padding = 50) {\n const extent = this.markerSource.getExtent();\n if (extent && extent[0] !== Infinity) {\n this.map.getView().fit(extent, {\n padding: [padding, padding, padding, padding],\n duration: 500,\n maxZoom: 16,\n });\n }\n }\n\n /**\n * Get current map center in lon/lat\n */\n getCenter() {\n const center = this.map.getView().getCenter();\n return toLonLat(center);\n }\n\n /**\n * Get current zoom level\n */\n getZoom() {\n return this.map.getView().getZoom();\n }\n\n /**\n * Set map center\n */\n setCenter(lon, lat) {\n this.map.getView().setCenter(fromLonLat([lon, lat]));\n }\n\n /**\n * Set zoom level\n */\n setZoom(zoom) {\n this.map.getView().setZoom(zoom);\n }\n\n /**\n * Register click callback\n * Callback receives (lon, lat, feature, event)\n *\n * Single-click is delayed by 300 ms so that a double-click can cancel it.\n * If the click lands on an overlay feature (e.g. district boundary) the\n * single-click is suppressed entirely — only double-click will fire.\n */\n onClick(callback) {\n this.clickCallbacks.push(callback);\n\n // Set up click handler if this is the first callback\n if (this.clickCallbacks.length === 1) {\n this._clickTimer = null;\n\n // Double-click cancels any pending single-click\n this.map.on('dblclick', () => {\n if (this._clickTimer) {\n clearTimeout(this._clickTimer);\n this._clickTimer = null;\n }\n });\n\n this.map.on('click', (evt) => {\n // Cancel any previous pending click\n if (this._clickTimer) {\n clearTimeout(this._clickTimer);\n this._clickTimer = null;\n }\n\n // When NOT in edit / draw mode, immediately clear any feature\n // the Select interaction may have grabbed on this click so the\n // user never sees a selection flash.\n if (!this._editBarActive && this._selectInteraction) {\n this._selectInteraction.getFeatures().clear();\n }\n\n // Check what features sit under the click pixel\n let hasOverlayFeature = false;\n let hasParcelFeature = false;\n let markerFeature = null;\n this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {\n if (feature.get('_layerType') === 'parcel') {\n hasParcelFeature = true;\n }\n if (feature.get('name')) {\n markerFeature = feature;\n }\n hasOverlayFeature = true;\n });\n\n // If an overlay feature was hit, suppress single-click\n // UNLESS it's a parcel or a location marker\n if (hasOverlayFeature && !hasParcelFeature && !markerFeature) {\n return;\n }\n\n // Delay the single-click to allow double-click to cancel it\n const [lon, lat] = toLonLat(evt.coordinate);\n this._clickTimer = setTimeout(() => {\n this._clickTimer = null;\n\n // Find location marker at pixel\n let clickedFeature = null;\n this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {\n if (feature.get('name')) {\n clickedFeature = feature;\n return true;\n }\n });\n\n for (const cb of this.clickCallbacks) {\n cb(lon, lat, clickedFeature, evt);\n }\n }, 300);\n });\n }\n\n // Return unsubscribe function\n return () => {\n const index = this.clickCallbacks.indexOf(callback);\n if (index > -1) {\n this.clickCallbacks.splice(index, 1);\n }\n };\n }\n\n /**\n * Register pointer move callback (for hover effects)\n */\n onPointerMove(callback) {\n this.map.on('pointermove', (evt) => {\n if (evt.dragging) return;\n\n const [lon, lat] = toLonLat(evt.coordinate);\n\n // Only find location markers (features with 'name' property)\n let hoveredFeature = null;\n this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {\n if (feature.get('name')) {\n hoveredFeature = feature;\n return true;\n }\n });\n\n // Change cursor\n this.map.getTargetElement().style.cursor = hoveredFeature ? 'pointer' : '';\n\n callback(lon, lat, hoveredFeature, evt);\n });\n }\n\n /**\n * Enable cursor change on marker hover\n * Note: This is now handled automatically by the popup system\n */\n enableHoverCursor() {\n // Cursor changes are now handled by setupHoverPopup()\n // This method is kept for backwards compatibility\n }\n\n /**\n * Add a GeoJSON layer (visible in LayerSwitcher).\n * By default the layer is added to the root overlay group.\n * Pass a targetGroup (LayerGroup) to nest it inside a specific group.\n *\n * @param {Object} geojson - GeoJSON FeatureCollection or Feature\n * @param {string} title - Layer title for the LayerSwitcher\n * @param {Object} [styleOptions] - Optional style configuration\n * @param {string} [styleOptions.strokeColor='#3b82f6'] - Stroke color\n * @param {number} [styleOptions.strokeWidth=2] - Stroke width\n * @param {string} [styleOptions.fillColor='rgba(59,130,246,0.1)'] - Fill color\n * @param {number[]} [styleOptions.strokeDash] - Dash pattern for the stroke\n * (passed straight to ol/style/Stroke#lineDash, e.g. [4,4]). Useful for\n * contextual overlays (grids, draft outlines) so they read differently\n * from solid property boundaries.\n * @param {LayerGroup} [targetGroup] - Optional group to add the layer to\n * @returns {VectorLayer} The created layer\n */\n addGeoJSONLayer(geojson, title, styleOptions = {}, targetGroup = null) {\n const {\n strokeColor = '#3b82f6',\n strokeWidth = 2,\n strokeDash = null,\n fillColor = 'rgba(59,130,246,0.1)',\n // Optional line \"casing\": a thicker darker stroke drawn UNDERNEATH the\n // main stroke. Used for road-like layers to make light-colored lines\n // visible on any base map. Set lineCasingColor to enable; the casing\n // width defaults to strokeWidth + 2.\n lineCasingColor = null,\n lineCasingWidth = null,\n pointRadius = 5,\n pointFillColor = null, // defaults to strokeColor\n pointStrokeColor = '#ffffff',\n pointStrokeWidth = 1.5,\n } = styleOptions;\n\n const source = new VectorSource({\n features: new GeoJSON().readFeatures(geojson, {\n featureProjection: 'EPSG:3857',\n }),\n });\n\n // Build per-geometry styles. OpenLayers picks `image` for Point /\n // MultiPoint, `stroke`+`fill` for Polygon / MultiPolygon, and `stroke`\n // alone for LineString / MultiLineString. Putting all three on a single\n // Style is enough — but a Style with only stroke+fill leaves Points\n // invisible, which is what was happening on shapefile import.\n const fillStyle = new Fill({ color: fillColor });\n const pointStyle = new Circle({\n radius: pointRadius,\n fill: new Fill({ color: pointFillColor || strokeColor }),\n stroke: new Stroke({ color: pointStrokeColor, width: pointStrokeWidth }),\n });\n\n // If a line casing is requested, return an array of two Styles per\n // feature: the casing renders first (underneath), then the inner stroke.\n // For polygons the casing also outlines them; for points the casing has\n // no effect (Point geometries only render `image`).\n const mainStroke = new Stroke({\n color: strokeColor,\n width: strokeWidth,\n ...(strokeDash ? { lineDash: strokeDash } : {}),\n });\n\n let layerStyle;\n if (lineCasingColor) {\n const casingW = lineCasingWidth != null ? lineCasingWidth : strokeWidth + 2;\n layerStyle = [\n new Style({\n stroke: new Stroke({ color: lineCasingColor, width: casingW }),\n }),\n new Style({\n stroke: mainStroke,\n fill: fillStyle,\n image: pointStyle,\n }),\n ];\n } else {\n layerStyle = new Style({\n stroke: mainStroke,\n fill: fillStyle,\n image: pointStyle,\n });\n }\n\n const layer = new VectorLayer({\n title: title,\n source: source,\n style: layerStyle,\n });\n layer.set('typeTag', styleOptions.typeTag || 'VEC');\n\n // Derive a friendly \"Vector / Polygon\" / \"Vector / Line\" / \"Vector / Point\"\n // subtitle from the first feature's geometry type, unless the caller\n // already supplied one in styleOptions.\n //\n // Layers created EMPTY (parcels, OSM_roads, …, populated later from the\n // API) leave the subtitle absent until the first feature arrives —\n // see the `addfeature` listener below.\n const describeFromGeom = (geomType) => {\n if (!geomType) return null;\n if (geomType.includes('Polygon')) return 'Vector / Polygon';\n if (geomType.includes('LineString')) return 'Vector / Line';\n if (geomType.includes('Point')) return 'Vector / Point';\n return 'Vector';\n };\n\n if (styleOptions.typeDescription) {\n layer.set('typeDescription', styleOptions.typeDescription);\n } else {\n const feats = source.getFeatures();\n const initial = describeFromGeom(feats[0]?.getGeometry?.()?.getType?.());\n if (initial) {\n layer.set('typeDescription', initial);\n } else {\n // Source is empty — wait for the first feature and set then.\n const once = (ev) => {\n const desc = describeFromGeom(ev.feature.getGeometry?.()?.getType?.());\n if (desc) layer.set('typeDescription', desc);\n source.un('addfeature', once);\n };\n source.on('addfeature', once);\n }\n }\n\n const group = targetGroup || this.overlayGroup;\n group.getLayers().push(layer);\n\n console.log('[MapView] GeoJSON layer added:', title, '→', source.getFeatures().length, 'features',\n targetGroup ? `(in group \"${targetGroup.get('title')}\")` : '');\n return layer;\n }\n\n /**\n * Add a LayerGroup to the overlay group.\n * Used to create layer categories from the remote catalogue;\n * individual vector layers will be added into these groups later.\n *\n * @param {number|string} id - Unique layer group id (from the API)\n * @param {string} title - Group title for the LayerSwitcher\n * @param {string} [description=''] - Group description (stored as property)\n * @returns {LayerGroup} The created (empty) layer group\n */\n addLayerGroup(id, title, description = '') {\n const group = new LayerGroup({\n title: title.trim(),\n });\n\n // Store metadata for later use\n group.set('layerId', id);\n group.set('description', description);\n\n this.overlayGroup.getLayers().push(group);\n\n console.log('[MapView] Layer group added:', title.trim(), '(id:', id + ')');\n return group;\n }\n\n /**\n * Add a WMS layer to a layer group.\n *\n * @param {string} groupTitle Title of the target LayerGroup (e.g. 'Biophysical Environment')\n * @param {string} title Display title for the layer\n * @param {string} url WMS server URL\n * @param {string} layers WMS LAYERS parameter\n * @param {Object} [options] Extra options\n * @param {string} [options.serverType='geoserver'] Server type hint ('geoserver'|'mapserver'|'qgis'|null)\n * @param {string} [options.style] WMS STYLES parameter (e.g. 'colours' for DEAfrica DEM)\n * @param {boolean} [options.visible=true] Initial visibility\n * @param {string} [options.attributions] Attribution HTML\n * @param {number} [options.opacity=1] Layer opacity (0–1). Use ~0.5 for background-style layers.\n * @param {number} [options.zIndex] Render z-index. Use negative values (e.g. -10) to force the\n * layer behind all default-z-index layers regardless of group order.\n * @param {string} [options.legendUrl] URL of a legend image to display while the layer is visible.\n * @param {boolean} [options.onlineOnly=false] If true, show a toast when the user toggles the layer on\n * while offline, explaining that the layer requires connectivity.\n * @returns {TileLayer|null} The created layer, or null if group not found\n */\n addWMSLayer(groupTitle, title, url, layers, options = {}) {\n const group = this.getLayerGroupByTitle(groupTitle);\n if (!group) {\n console.warn(`[MapView] Layer group \"${groupTitle}\" not found — cannot add WMS layer \"${title}\"`);\n return null;\n }\n\n const params = { LAYERS: layers, TILED: true, WIDTH: 256, HEIGHT: 256 };\n if (options.style !== undefined) params.STYLES = options.style;\n\n const wmsSource = new TileWMS({\n url,\n params,\n serverType: options.serverType !== undefined ? options.serverType : 'geoserver',\n crossOrigin: 'anonymous',\n hidpi: false,\n attributions: options.attributions,\n });\n\n const wmsLayer = new TileLayer({\n title,\n visible: options.visible !== undefined ? options.visible : true,\n source: wmsSource,\n opacity: options.opacity !== undefined ? options.opacity : 1,\n zIndex: options.zIndex,\n });\n wmsLayer.set('typeTag', 'WMS');\n wmsLayer.set('typeDescription', 'WMS / Raster');\n\n // Show toast on tile load errors (e.g. server rejects request)\n wmsSource.on('tileloaderror', () => {\n showToast(`WMS layer \"${title}\" — tile load error. Check the URL and layer name.`, 'warning', 5000);\n });\n\n group.getLayers().push(wmsLayer);\n\n // Register legend AFTER push so that a failure here doesn't block the LayerSwitcher\n if (options.legendUrl) {\n try {\n this._registerLegend(wmsLayer, title, options.legendUrl);\n } catch (err) {\n console.warn(`[MapView] Could not register legend for \"${title}\":`, err);\n }\n }\n\n // Online-only warning: when the user toggles the layer on while offline,\n // surface a toast explaining why nothing will render.\n if (options.onlineOnly) {\n this._attachOnlineOnlyHandler(wmsLayer, title);\n }\n\n console.log(`[MapView] WMS layer added: \"${title}\" → group \"${groupTitle}\"`);\n return wmsLayer;\n }\n\n /**\n * Add an XYZ tile layer to a layer group.\n *\n * @param {string} groupTitle Title of the target LayerGroup\n * @param {string} title Display title for the layer\n * @param {string} url XYZ tile URL template (with {z}/{x}/{y} placeholders)\n * @param {Object} [options] Extra options\n * @param {boolean} [options.visible=true] Initial visibility\n * @param {string} [options.attributions] Attribution HTML\n * @param {number} [options.maxZoom=19] Maximum zoom level\n * @param {number} [options.opacity=1] Layer opacity (0–1). Use ~0.5 for background-style layers.\n * @param {number} [options.zIndex] Render z-index. Use negative values to force behind other layers.\n * @param {string} [options.legendUrl] URL of a legend image to display while the layer is visible.\n * @param {boolean} [options.onlineOnly=false] If true, show a toast when the user toggles the layer on\n * while offline, explaining that the layer requires connectivity.\n * @returns {TileLayer|null} The created layer, or null if group not found\n */\n addXYZLayer(groupTitle, title, url, options = {}) {\n const group = this.getLayerGroupByTitle(groupTitle);\n if (!group) {\n console.warn(`[MapView] Layer group \"${groupTitle}\" not found — cannot add XYZ layer \"${title}\"`);\n return null;\n }\n\n const xyzSource = new XYZ({\n url,\n crossOrigin: 'anonymous',\n maxZoom: options.maxZoom !== undefined ? options.maxZoom : 19,\n attributions: options.attributions,\n });\n\n const xyzLayer = new TileLayer({\n title,\n visible: options.visible !== undefined ? options.visible : true,\n source: xyzSource,\n opacity: options.opacity !== undefined ? options.opacity : 1,\n zIndex: options.zIndex,\n });\n xyzLayer.set('typeTag', 'XYZ');\n xyzLayer.set('typeDescription', 'XYZ / Tile');\n\n // Show toast on tile load errors\n xyzSource.on('tileloaderror', () => {\n showToast(`XYZ layer \"${title}\" — tile load error. Check the URL.`, 'warning', 5000);\n });\n\n group.getLayers().push(xyzLayer);\n\n // Register legend AFTER push so that a failure here doesn't block the LayerSwitcher\n if (options.legendUrl) {\n try {\n this._registerLegend(xyzLayer, title, options.legendUrl);\n } catch (err) {\n console.warn(`[MapView] Could not register legend for \"${title}\":`, err);\n }\n }\n\n // Online-only warning: when the user toggles the layer on while offline,\n // surface a toast explaining why nothing will render.\n if (options.onlineOnly) {\n this._attachOnlineOnlyHandler(xyzLayer, title);\n }\n\n console.log(`[MapView] XYZ layer added: \"${title}\" → group \"${groupTitle}\"`);\n return xyzLayer;\n }\n\n /**\n * Add a Cloud-Optimized GeoTIFF (COG) raster layer.\n *\n * COGs are streamed by range-request and rendered on the GPU via\n * WebGLTile, so a large DEM or satellite scene can be displayed without\n * downloading the whole file. This is the display half of Stage 1's raster\n * support (analysis on rasters runs server-side — see the concept note).\n *\n * @param {string} groupTitle Title of the target LayerGroup\n * @param {string} title Display title for the layer\n * @param {string} url URL of the .tif (must be a valid COG, CORS-enabled)\n * @param {Object} [options]\n * @param {boolean} [options.visible=true]\n * @param {number} [options.opacity=1]\n * @param {number} [options.zIndex]\n * @param {boolean} [options.normalize=true] Auto-stretch values to 0–1 for display\n * @param {number} [options.min] Explicit min for contrast stretch\n * @param {number} [options.max] Explicit max for contrast stretch\n * @param {Object} [options.style] OpenLayers WebGLTile style (e.g. a colour ramp)\n * @param {string} [options.attributions]\n * @returns {Promise} the created layer (async: the COG libraries\n * are code-split and fetched on first use)\n */\n async addCOGLayer(groupTitle, title, url, options = {}) {\n const group = this.getLayerGroupByTitle(groupTitle);\n if (!group) {\n console.warn(`[MapView] Layer group \"${groupTitle}\" not found — cannot add COG layer \"${title}\"`);\n return null;\n }\n\n // Pre-flight the URL before handing it to geotiff.js. Without this, a bad\n // URL (a web page, a 404, a CORS block) surfaces only as an unhandled\n // AggregateError from the library's internal range-request machinery,\n // which tells the user nothing. A one-byte range request is cheap and\n // distinguishes the common failures precisely.\n const problem = await this._probeCOGUrl(url);\n if (problem) {\n console.warn(`[MapView] COG pre-flight failed for \"${title}\":`, problem);\n showToast(problem, 'error', 8000);\n return null;\n }\n\n // Lazy-load the GeoTIFF stack only when a raster is actually opened.\n let WebGLTileLayer, GeoTIFFSource;\n try {\n [{ default: WebGLTileLayer }, { default: GeoTIFFSource }] = await Promise.all([\n import('ol/layer/WebGLTile'),\n import('ol/source/GeoTIFF'),\n ]);\n } catch (err) {\n console.error('[MapView] Could not load COG support:', err);\n showToast('Raster (COG) support could not be loaded — check your connection.', 'error', 6000);\n return null;\n }\n\n let cogLayer = null;\n try {\n const sourceOpts = {\n sources: [{\n url,\n ...(options.min !== undefined ? { min: options.min } : {}),\n ...(options.max !== undefined ? { max: options.max } : {}),\n }],\n // normalize=true stretches band values into 0–1 so single-band rasters\n // (DEMs, indices) render without an explicit style.\n normalize: options.normalize !== undefined ? options.normalize : true,\n attributions: options.attributions,\n };\n const source = new GeoTIFFSource(sourceOpts);\n\n cogLayer = new WebGLTileLayer({\n title,\n source,\n visible: options.visible !== undefined ? options.visible : true,\n opacity: options.opacity !== undefined ? options.opacity : 1,\n zIndex: options.zIndex,\n ...(options.style ? { style: options.style } : {}),\n });\n cogLayer.set('typeTag', 'COG');\n cogLayer.set('typeDescription', 'Cloud-Optimized GeoTIFF');\n\n // Surface load failures — a non-COG or a CORS-blocked file is the usual cause.\n source.on('error', (evt) => {\n console.warn(`[MapView] COG \"${title}\" source error:`, evt);\n showToast(`Raster \"${title}\" could not be loaded. Check that the file is a valid COG and is CORS-enabled.`,\n 'warning', 6000);\n });\n\n group.getLayers().push(cogLayer);\n } catch (err) {\n console.error(`[MapView] Failed to add COG layer \"${title}\":`, err);\n showToast(`Could not add raster \"${title}\": ${err.message}`, 'error', 6000);\n return null;\n }\n\n if (options.onlineOnly) this._attachOnlineOnlyHandler(cogLayer, title);\n\n console.log(`[MapView] COG layer added: \"${title}\" → group \"${groupTitle}\"`);\n return cogLayer;\n }\n\n /**\n * Check that a URL can plausibly serve a Cloud-Optimized GeoTIFF.\n *\n * Issues a 1-byte range request and inspects the response. Returns a\n * human-readable problem description, or null when the URL looks usable.\n * This exists because geotiff.js reports these failures as an opaque\n * \"AggregateError: Request failed\" from deep inside its block reader.\n *\n * @param {string} url\n * @returns {Promise}\n * @private\n */\n async _probeCOGUrl(url) {\n let res;\n try {\n res = await fetch(url, { headers: { Range: 'bytes=0-0' } });\n } catch (err) {\n // Thrown for CORS rejections and network failures alike — the browser\n // deliberately doesn't tell us which, so say so rather than guess.\n return 'Could not reach that file. It may be offline, or the server may not ' +\n 'allow cross-origin (CORS) requests from this app.';\n }\n\n if (res.status === 404) return 'No file at that URL (404). Check the address.';\n if (!res.ok && res.status !== 206) {\n return `The server refused the request (HTTP ${res.status}).`;\n }\n\n const type = (res.headers.get('content-type') || '').toLowerCase();\n if (type.includes('text/html')) {\n return 'That URL is a web page, not a GeoTIFF. Paste the direct link to the ' +\n '.tif file itself — a documentation or viewer page will not work.';\n }\n if (type.startsWith('text/') || type.includes('json')) {\n return `That URL returns ${type.split(';')[0]}rather than image data. ` +\n 'Paste the direct link to the .tif file.';\n }\n // 200 instead of 206 means range requests are ignored: the file still\n // loads, but the whole thing is downloaded. Worth warning about, not fatal.\n if (res.status === 200) {\n showToast('This server does not support byte-range requests, so the whole raster ' +\n 'will be downloaded. It may be slow for a large file.', 'warning', 7000);\n }\n return null;\n }\n\n /**\n * The features currently selected with the Select tool (shift-click or\n * Ctrl/Cmd box-select). Used by the Analysis panel to restrict an analysis\n * to a hand-picked subset.\n * @returns {Array}\n */\n getSelectedFeatures() {\n if (!this._selectInteraction) return [];\n return this._selectInteraction.getFeatures().getArray().slice();\n }\n\n /**\n * List the vector layers a user can pick as analysis inputs.\n *\n * Walks the layer tree (recursing into groups) and returns the real,\n * feature-bearing layers — excluding helper overlays (vertex handles, GPS\n * trail/position, snap guides) which are never meaningful analysis inputs.\n *\n * @param {Object} [opts]\n * @param {boolean} [opts.visibleOnly=false] only include currently-visible layers\n * @param {boolean} [opts.nonEmptyOnly=true] skip layers with no features loaded\n * @returns {Array<{layer: VectorLayer, title: string, count: number}>}\n */\n listVectorLayers(opts = {}) {\n const { visibleOnly = false, nonEmptyOnly = true } = opts;\n const out = [];\n\n const walk = (layer) => {\n if (!layer) return;\n if (typeof layer.getLayers === 'function') {\n layer.getLayers().forEach(walk);\n return;\n }\n if (!(layer instanceof VectorLayer)) return;\n if (layer === this._vertexOverlayLayer ||\n layer === this._gpsTrailLayer ||\n layer === this._gpsPositionLayer ||\n layer.get('displayInLayerSwitcher') === false) return;\n if (visibleOnly && layer.getVisible && !layer.getVisible()) return;\n\n const source = layer.getSource && layer.getSource();\n if (!source || typeof source.getFeatures !== 'function') return;\n const count = source.getFeatures().length;\n if (nonEmptyOnly && count === 0) return;\n\n out.push({ layer, title: layer.get('title') || '(untitled layer)', count });\n };\n\n this.map.getLayers().forEach(walk);\n return out;\n }\n\n // ============================================================================\n // Add External Layer Dialog\n // ============================================================================\n\n /**\n * Create the add-layer dialog overlay (hidden by default).\n * Appended to the map target element so it stays within the map viewport.\n */\n _createAddLayerDialog() {\n this._addLayerDialog = document.createElement('div');\n this._addLayerDialog.className = 'map-add-layer-dialog';\n this._addLayerDialog.style.cssText = `\n display:none;position:absolute;top:0;left:0;right:0;bottom:0;\n z-index:1100;background:rgba(0,0,0,0.4);\n align-items:center;justify-content:center;\n `;\n\n const card = document.createElement('div');\n card.style.cssText = `\n background:var(--card, #fff);color:var(--card-foreground, #1e1a4b);\n border-radius:12px;box-shadow:0 8px 30px rgba(0,0,0,0.35);\n font-family:var(--font-body, 'Exo', sans-serif);font-size:13px;\n width:340px;max-width:90vw;border:2px solid #10b981;overflow:hidden;\n `;\n\n card.innerHTML = `\n \n Add External Layer \n × \n
\n \n
\n
\n Server URL \n \n
\n
\n
Layer Name \n
\n
\n WMS LAYERS parameter (e.g. workspace:layer)\n
\n
\n
\n Display Title \n \n
\n
\n \n Add Layer\n \n \n Cancel\n \n
\n
\n `;\n\n this._addLayerDialog.appendChild(card);\n this.map.getTargetElement().appendChild(this._addLayerDialog);\n\n // Type radio change — toggle layer name row visibility\n const nameRow = card.querySelector('.add-layer-name-row');\n const nameHint = card.querySelector('.add-layer-name-hint');\n const urlInput = card.querySelector('.add-layer-url');\n const typeHint = card.querySelector('.add-layer-type-hint');\n card.querySelectorAll('input[name=\"add-layer-type\"]').forEach((radio) => {\n radio.addEventListener('change', () => {\n const type = radio.value;\n typeHint.textContent = type === 'cog'\n ? 'Cloud-Optimized GeoTIFF — the server must allow CORS and byte-range requests.'\n : '';\n if (type === 'cog') {\n // A COG is a single file, so there is no layer/typename to pick.\n nameRow.style.display = 'none';\n urlInput.placeholder = 'https://example.com/data/elevation_cog.tif';\n } else if (type === 'xyz') {\n nameRow.style.display = 'none';\n urlInput.placeholder = 'https://example.com/tiles/{z}/{x}/{y}.png';\n } else {\n nameRow.style.display = '';\n urlInput.placeholder = type === 'wms'\n ? 'https://example.com/wms'\n : 'https://example.com/wfs';\n nameHint.textContent = type === 'wms'\n ? 'WMS LAYERS parameter (e.g. workspace:layer)'\n : 'WFS typename (e.g. workspace:layer)';\n }\n });\n });\n\n // Close / Cancel\n const close = () => this._hideAddLayerDialog();\n card.querySelector('.add-layer-close').addEventListener('click', close);\n card.querySelector('.add-layer-cancel').addEventListener('click', close);\n this._addLayerDialog.addEventListener('click', (e) => {\n if (e.target === this._addLayerDialog) close();\n });\n\n // Confirm\n card.querySelector('.add-layer-confirm').addEventListener('click', () => {\n const type = card.querySelector('input[name=\"add-layer-type\"]:checked').value;\n const url = card.querySelector('.add-layer-url').value.trim();\n const layerName = card.querySelector('.add-layer-name').value.trim();\n const title = card.querySelector('.add-layer-title').value.trim();\n\n if (!url) {\n card.querySelector('.add-layer-url').style.borderColor = '#ef4444';\n return;\n }\n if ((type === 'wms' || type === 'wfs') && !layerName) {\n card.querySelector('.add-layer-name').style.borderColor = '#ef4444';\n return;\n }\n if (!title) {\n card.querySelector('.add-layer-title').style.borderColor = '#ef4444';\n return;\n }\n\n this._addExternalLayer(type, url, layerName, title);\n this._hideAddLayerDialog();\n });\n\n // Enter key to confirm\n card.addEventListener('keydown', (e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n card.querySelector('.add-layer-confirm').click();\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n close();\n }\n });\n }\n\n /**\n * Show the add-layer dialog.\n */\n showAddLayerDialog() {\n const dlg = this._addLayerDialog;\n // Reset form\n dlg.querySelector('.add-layer-url').value = '';\n dlg.querySelector('.add-layer-name').value = '';\n dlg.querySelector('.add-layer-title').value = '';\n dlg.querySelectorAll('input[name=\"add-layer-type\"]')[0].checked = true;\n dlg.querySelector('.add-layer-name-row').style.display = '';\n dlg.querySelector('.add-layer-url').placeholder = 'https://example.com/wms';\n dlg.querySelector('.add-layer-name-hint').textContent = 'WMS LAYERS parameter (e.g. workspace:layer)';\n const typeHintEl = dlg.querySelector('.add-layer-type-hint');\n if (typeHintEl) typeHintEl.textContent = '';\n\n // Reset border colours\n dlg.querySelectorAll('input[type=\"text\"]').forEach((inp) => {\n inp.style.borderColor = 'var(--border, #1e1a4b1f)';\n });\n\n dlg.style.display = 'flex';\n dlg.querySelector('.add-layer-url').focus();\n }\n\n /**\n * Hide the add-layer dialog.\n */\n _hideAddLayerDialog() {\n this._addLayerDialog.style.display = 'none';\n }\n\n /**\n * Add an external layer to the \"External Source\" group.\n *\n * @param {string} type 'wms' | 'wfs' | 'xyz'\n * @param {string} url Server URL\n * @param {string} layerName WMS LAYERS / WFS typename (ignored for XYZ)\n * @param {string} title Display title in layer switcher\n */\n _addExternalLayer(type, url, layerName, title) {\n const group = this._externalSourceGroup;\n if (!group) {\n showToast('Layer group \"External Source\" not found.', 'error', 4000);\n return;\n }\n\n let layer;\n\n switch (type) {\n case 'wms': {\n const wmsSrc = new TileWMS({\n url,\n params: { LAYERS: layerName, TILED: true, WIDTH: 256, HEIGHT: 256 },\n serverType: 'geoserver',\n crossOrigin: 'anonymous',\n hidpi: false,\n });\n layer = new TileLayer({\n title,\n visible: true,\n source: wmsSrc,\n });\n wmsSrc.on('tileloaderror', () => {\n showToast(`WMS \"${title}\" — tile load error. Check URL and layer name.`, 'warning', 5000);\n });\n break;\n }\n\n case 'wfs': {\n const wfsUrl = `${url}${url.includes('?') ? '&' : '?'}` +\n `service=WFS&version=1.1.0&request=GetFeature` +\n `&typename=${encodeURIComponent(layerName)}` +\n `&outputFormat=application/json&srsname=EPSG:3857`;\n\n const wfsSource = new VectorSource({\n url: wfsUrl,\n format: new GeoJSON(),\n });\n wfsSource.on('featuresloaderror', () => {\n showToast(`WFS \"${title}\" — load error. Check URL and layer name.`, 'warning', 5000);\n });\n\n layer = new VectorLayer({\n title,\n visible: true,\n source: wfsSource,\n style: new Style({\n stroke: new Stroke({ color: '#e11d48', width: 2 }),\n fill: new Fill({ color: 'rgba(225,29,72,0.15)' }),\n }),\n });\n break;\n }\n\n case 'xyz':\n layer = new TileLayer({\n title,\n visible: true,\n source: new XYZ({\n url,\n crossOrigin: 'anonymous',\n }),\n });\n layer.getSource().on('tileloaderror', () => {\n showToast(`XYZ \"${title}\" — tile load error. Check the URL template.`, 'warning', 5000);\n });\n break;\n\n case 'cog': {\n // A Cloud-Optimized GeoTIFF is a single file streamed by byte-range\n // request. addCOGLayer() lazy-loads the GeoTIFF stack, pushes the layer\n // into the group itself and reports its own failures, so we return\n // early rather than falling through to the shared push below.\n const groupTitle = group.get('title') || 'External Source';\n this.addCOGLayer(groupTitle, title, url).then((cogLayer) => {\n if (!cogLayer) return;\n cogLayer.set('removable', true);\n showToast(`Layer \"${title}\" added to External Source.`, 'success', 3000);\n console.log(`[MapView] External COG layer added: \"${title}\"`);\n });\n return;\n }\n\n default:\n showToast(`Unknown layer type: ${type}`, 'error', 4000);\n return;\n }\n\n // Tag for the LayerSwitcher chip\n layer.set('typeTag', type.toUpperCase()); // 'WMS' | 'WFS' | 'XYZ'\n layer.set('typeDescription', {\n wms: 'WMS / Raster',\n wfs: 'WFS / Vector',\n xyz: 'XYZ / Tile',\n }[type] || type.toUpperCase());\n\n // User-added external layers ARE removable — they're not part of the\n // app's built-in data model.\n layer.set('removable', true);\n\n group.getLayers().push(layer);\n showToast(`Layer \"${title}\" added to External Source.`, 'success', 3000);\n console.log(`[MapView] External ${type.toUpperCase()} layer added: \"${title}\"`);\n }\n\n // ============================================================================\n // LayerSwitcher decoration (Option A — visual refresh)\n // ============================================================================\n\n /**\n * Decorate a layer's after ol-ext renders it:\n * • inject a type-tag chip next to the layer label\n * • inject the green \"+\" button on the External Source group header\n *\n * Idempotent — safe to call repeatedly; each injected element checks\n * whether it already exists in the row.\n */\n _decorateLayerListItem(layer, li) {\n // 1. Type-tag chip (e.g. WMS / XYZ / VEC) next to the layer name.\n // Inserted INSIDE the label's so it doesn't collide with the\n // label's left padding (where ol-ext draws the checkbox via ::before).\n const tag = layer.get('typeTag'); // 'WMS' | 'WFS' | 'XYZ' | 'VEC' | 'GEO' | 'BASE'\n if (tag) {\n const labelSpan = li.querySelector(':scope > .li-content > label > span');\n if (labelSpan && !labelSpan.querySelector(':scope > .ls-type-tag')) {\n const chip = document.createElement('span');\n chip.className = `ls-type-tag ls-type-tag-${String(tag).toLowerCase()}`;\n chip.textContent = String(tag);\n chip.title = `${tag} layer`;\n labelSpan.appendChild(chip);\n }\n }\n\n // 2. Replace ol-ext's bar-drawn +/- chevron with the GeoView chevron SVG.\n // The SVG uses stroke=\"currentColor\", so CSS `color` (set in\n // layerswitcher.css) tints it. Rotation handles the open/closed state.\n const btnBar = li.querySelector(':scope > .ol-layerswitcher-buttons');\n if (btnBar) {\n const chevronEl = btnBar.querySelector(':scope > .expend-layers, :scope > .collapse-layers');\n if (chevronEl && !chevronEl.querySelector(':scope > svg.ls-chevron-svg')) {\n chevronEl.innerHTML =\n '' +\n ' ' +\n ' ';\n }\n }\n\n // 3. Layer-type subtitle (\"Vector / Polygon\", \"WMS / Raster\", …) below\n // the layer name. Only rendered when layer.get('typeDescription') is\n // set. For layers that start empty and gain features later (the API\n // loaders), we listen for `change:typeDescription` and update or\n // insert the subtitle then.\n const content = li.querySelector(':scope > .li-content');\n const ensureSubtitle = () => {\n if (!content) return;\n const text = layer.get('typeDescription');\n let sub = content.querySelector(':scope > .ls-layer-subtitle');\n if (!text) {\n if (sub) sub.remove();\n return;\n }\n if (!sub) {\n sub = document.createElement('div');\n sub.className = 'ls-layer-subtitle';\n const label = content.querySelector(':scope > label');\n if (label && label.nextSibling) {\n content.insertBefore(sub, label.nextSibling);\n } else {\n content.appendChild(sub);\n }\n }\n sub.textContent = text;\n };\n ensureSubtitle();\n if (!layer._lsSubtitleHooked) {\n layer._lsSubtitleHooked = true;\n layer.on('change:typeDescription', () => {\n // The may not exist any more (panel re-rendered between events)\n // — guard with a fresh lookup via the LayerSwitcher next time it draws.\n // For now we just call ensureSubtitle bound to the original li.\n ensureSubtitle();\n });\n }\n\n // 4. Per-layer Remove button — only for layers explicitly marked\n // `removable: true` (external sources, imported files, …). Built-in\n // layers (Parcels, OSM_roads, district boundary, …) are NOT removable\n // so the user can't accidentally delete them.\n if (layer.get('removable') === true && btnBar && !btnBar.querySelector(':scope > .ls-remove-btn')) {\n const removeBtn = document.createElement('button');\n removeBtn.type = 'button';\n removeBtn.className = 'ls-remove-btn';\n removeBtn.title = 'Remove this layer';\n removeBtn.setAttribute('aria-label', 'Remove layer');\n removeBtn.innerHTML =\n '' +\n ' ' +\n ' ';\n removeBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this._removeLayer(layer);\n });\n btnBar.appendChild(removeBtn);\n }\n\n // 5b. Import-state chip on layers staged via the external-dataset import\n // flow (LUPMIS2_Import_Upload_Design.docx §3.2). The chip's text and\n // behaviour depend on `_externalImportStatus`:\n // 'mapped' → \"Upload N\" (click → upload)\n // 'uploading' → spinner (disabled)\n // 'submitted' → \"✓ submitted\" (in upload_tmp, awaiting review)\n // 'migrated' → \"✓ live\" (supervisor promoted to lu_parcels)\n // 'failed' → \"N errors — fix?\"\n // 'other'/null→ no chip\n // Clicks dispatch a window-level CustomEvent so main.js can react\n // without MapView knowing anything about staging.\n const importId = layer.get('_externalImportId');\n if (importId != null) {\n const labelSpan = li.querySelector(':scope > .li-content > label > span');\n let chip = labelSpan ? labelSpan.querySelector(':scope > .ls-import-chip') : null;\n const status = layer.get('_externalImportStatus') || 'mapped';\n const featureCount = layer.getSource()?.getFeatures().length ?? 0;\n const errorCount = layer.get('_externalImportErrorCount') ?? 0;\n\n // Decide chip appearance.\n const chipSpec = (() => {\n switch (status) {\n case 'mapped':\n return { text: `Upload ${featureCount}`, cls: 'ls-import-chip-mapped',\n title: 'Upload this dataset to the database', clickable: true };\n case 'uploading':\n return { text: '…', cls: 'ls-import-chip-uploading',\n title: 'Uploading…', clickable: false };\n case 'submitted':\n return { text: '✓ submitted', cls: 'ls-import-chip-submitted',\n title: 'Uploaded — awaiting supervisor review', clickable: false };\n case 'migrated':\n return { text: '✓ live', cls: 'ls-import-chip-migrated',\n title: 'Approved by supervisor and live on the server', clickable: false };\n case 'failed':\n return { text: `${errorCount} errors — fix?`, cls: 'ls-import-chip-failed',\n title: 'Some rows failed; click to review', clickable: true };\n case 'other':\n case null:\n case undefined:\n default:\n return null;\n }\n })();\n\n if (!chipSpec) {\n if (chip) chip.remove();\n } else if (labelSpan) {\n if (!chip) {\n chip = document.createElement('span');\n chip.className = 'ls-import-chip';\n labelSpan.appendChild(chip);\n }\n chip.className = `ls-import-chip ${chipSpec.cls}`;\n chip.textContent = chipSpec.text;\n chip.title = chipSpec.title;\n chip.style.cursor = chipSpec.clickable ? 'pointer' : 'default';\n chip.style.opacity = chipSpec.clickable ? '1' : '0.85';\n\n // Replace any prior listener by cloning the node.\n const fresh = chip.cloneNode(true);\n chip.replaceWith(fresh);\n chip = fresh;\n\n if (chipSpec.clickable) {\n chip.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n window.dispatchEvent(new CustomEvent('lupmis:import-chip-click', {\n detail: { importId, status, layer },\n }));\n });\n }\n }\n }\n\n // 5. \"+\" button on the External Source group\n const groupTitle = (layer.get('title') || '').toLowerCase();\n if (groupTitle.includes('external')) {\n this._externalSourceGroup = layer;\n // btnBar already resolved above (same .ol-layerswitcher-buttons element)\n if (btnBar && !btnBar.querySelector('.ol-add-layer')) {\n const addBtn = document.createElement('span');\n addBtn.className = 'ol-add-layer';\n addBtn.title = 'Add external layer';\n addBtn.textContent = '+';\n addBtn.style.cssText = `\n display:inline-flex !important;align-items:center;justify-content:center;\n width:22px !important;height:22px !important;border-radius:50%;\n background:#41b6a6 !important;color:#fff !important;\n font-size:15px !important;font-weight:700;\n cursor:pointer;line-height:1 !important;\n margin:0 4px 0 0;vertical-align:middle;\n transition:background 0.2s;box-sizing:border-box;border:none;\n `;\n addBtn.addEventListener('mouseenter', () => { addBtn.style.background = '#329686'; });\n addBtn.addEventListener('mouseleave', () => { addBtn.style.background = '#41b6a6'; });\n addBtn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.showAddLayerDialog();\n });\n btnBar.prepend(addBtn);\n }\n }\n }\n\n /**\n * Remove a layer from its parent group, after confirmation. Only called\n * from the per-layer × button injected by `_decorateLayerListItem` — and\n * that button is only injected for layers marked `removable: true`, so\n * built-in layers (Parcels, OSM_roads, …) can never reach this path.\n *\n * @param {Layer} layer\n */\n _removeLayer(layer) {\n const title = layer.get('title') || 'this layer';\n if (!confirm(`Remove \"${title}\" from the map?\\n\\nThis only affects the current session — built-in layers cannot be removed.`)) {\n return;\n }\n\n // Find the parent group that owns this layer and call .remove() on its\n // collection. Walk recursively from the overlay group.\n const visit = (group) => {\n const layers = group.getLayers();\n if (layers.getArray().includes(layer)) {\n layers.remove(layer);\n return true;\n }\n let removed = false;\n layers.forEach((child) => {\n if (!removed && child.getLayers) {\n removed = visit(child);\n }\n });\n return removed;\n };\n\n const ok = visit(this.overlayGroup);\n if (ok) {\n console.log(`[MapView] Removed layer \"${title}\"`);\n showToast(`Removed \"${title}\" from the map.`, 'info', 3000);\n } else {\n console.warn(`[MapView] Could not find layer \"${title}\" in any group`);\n }\n }\n\n /**\n * Inject (or refresh) the panel chrome — an \"active count\" badge at the top\n * and a footer row with \"Reset overlays\" button at the bottom.\n *\n * The chrome lives in `.panel-container` (the wrapping ), not inside\n * the `
` — that way the badge and footer are siblings of\n * the layer list rather than malformed children of a ``.\n *\n * Called from drawlist via queueMicrotask, so it runs once per redraw cycle\n * regardless of how many layers are in the panel.\n */\n _refreshLayerSwitcherChrome(layerSwitcher) {\n const panelContainer = layerSwitcher.element?.querySelector('.panel-container');\n const ul = layerSwitcher.element?.querySelector('ul.panel');\n if (!panelContainer || !ul) return;\n\n // --- Active-count badge (top of panel-container, before the