docs: Add comprehensive update and fix plan for map system layers
This commit is contained in:
788
docs/MAP_SYSTEM_UPDATE_PLAN.md
Normal file
788
docs/MAP_SYSTEM_UPDATE_PLAN.md
Normal file
@@ -0,0 +1,788 @@
|
|||||||
|
# Map System - Comprehensive Update & Fix Plan
|
||||||
|
|
||||||
|
Based on layer testing results from LAYER_NOTES.md
|
||||||
|
Date: January 16, 2026
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Executive Summary
|
||||||
|
|
||||||
|
**Current Status:**
|
||||||
|
- ✅ **6/7 base layers working** (1 broken: Polish Orthophoto High Resolution)
|
||||||
|
- ⚠️ **2/9 overlay layers working** (2 very slow, 5 not tested, 2 broken)
|
||||||
|
- 🎯 **Priority:** Fix broken layers, optimize slow WMS services, remove LP-Portal layers
|
||||||
|
|
||||||
|
**Key Issues Identified:**
|
||||||
|
1. Polish Orthophoto High Resolution completely broken
|
||||||
|
2. Polish Cadastral Data servers extremely slow (both servers)
|
||||||
|
3. Polish Spatial Planning layer not working
|
||||||
|
4. LP-Portal layers not tested/documented - likely region-specific
|
||||||
|
5. No caching or performance optimization for WMS layers
|
||||||
|
6. Missing zoom level restrictions causing tile request failures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1: Critical Fixes (Week 1)
|
||||||
|
|
||||||
|
### 1.1 Fix Polish Orthophoto High Resolution
|
||||||
|
**Issue:** Doesn't load at all
|
||||||
|
**Root Cause:** Likely incorrect WMTS parameters or service endpoint change
|
||||||
|
|
||||||
|
**Action Plan:**
|
||||||
|
1. Test GetCapabilities response:
|
||||||
|
```bash
|
||||||
|
curl "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/HighResolution?Service=WMTS&Request=GetCapabilities"
|
||||||
|
```
|
||||||
|
2. Compare with Standard Resolution working configuration
|
||||||
|
3. Check for:
|
||||||
|
- Different tile matrix sets
|
||||||
|
- Different available zoom levels
|
||||||
|
- Format differences (jpeg vs png)
|
||||||
|
- Authentication requirements
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Test if service requires different parameters
|
||||||
|
{
|
||||||
|
name: "🇵🇱 Polish Orthophoto (High Resolution)",
|
||||||
|
url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/HighResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=EPSG:3857&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image/jpeg",
|
||||||
|
maxZoom: 19, // May need adjustment based on GetCapabilities
|
||||||
|
minZoom: 15, // High-res often only available at higher zoom
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Layer loads tiles without errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1.2 Fix Polish Spatial Planning Layer
|
||||||
|
**Issue:** Doesn't work or extremely slow
|
||||||
|
**Service:** `https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego`
|
||||||
|
|
||||||
|
**Action Plan:**
|
||||||
|
1. Verify service is still active via GetCapabilities
|
||||||
|
2. Test with simplified layer list (may be requesting too many layers)
|
||||||
|
3. Check if service moved to new endpoint
|
||||||
|
4. Test with different WMS versions (1.1.1 vs 1.3.0)
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Simplified layer request
|
||||||
|
{
|
||||||
|
name: "🏗️ Polish Spatial Planning",
|
||||||
|
type: "wms",
|
||||||
|
url: "https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego",
|
||||||
|
params: {
|
||||||
|
layers: "raster", // Start with just raster
|
||||||
|
format: "image/png",
|
||||||
|
transparent: true,
|
||||||
|
version: "1.3.0",
|
||||||
|
},
|
||||||
|
maxZoom: 18, // Limit to prevent overload
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Layer loads or is removed if permanently unavailable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 1.3 Optimize Polish Cadastral Data Performance
|
||||||
|
**Issue:** Both servers very slow, currently only work up to zoom 18
|
||||||
|
**Impact:** Core functionality for land surveying projects
|
||||||
|
|
||||||
|
**Action Plan:**
|
||||||
|
1. Implement tile loading indicators
|
||||||
|
2. Add request debouncing
|
||||||
|
3. Consider caching strategy
|
||||||
|
4. Test alternate GUGiK services
|
||||||
|
5. (Future) Enable zoom 19-20 with proper optimization
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Update both cadastral servers with performance optimizations
|
||||||
|
{
|
||||||
|
name: "📋 Polish Cadastral Data (Działki) - Server 2",
|
||||||
|
type: "wms",
|
||||||
|
url: "https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow",
|
||||||
|
params: {
|
||||||
|
layers: "dzialki,numery_dzialek,budynki", // Simplified - remove slow layers
|
||||||
|
format: "image/png",
|
||||||
|
transparent: true,
|
||||||
|
version: "1.3.0",
|
||||||
|
},
|
||||||
|
maxZoom: 18, // Current working limit (TODO: extend to 20 with optimization)
|
||||||
|
minZoom: 13, // Don't load at far zoom levels
|
||||||
|
opacity: 0.8,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Additional Optimizations:**
|
||||||
|
- Add WMS tiled parameter: `tiled: true`
|
||||||
|
- Reduce requested layers to essential only
|
||||||
|
- Implement progressive loading (load parcels first, then details)
|
||||||
|
|
||||||
|
**Success Criteria:** Acceptable load times (<3s) at zoom 15-18, prepare for zoom 20 support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2: Layer Management (Week 2)
|
||||||
|
|
||||||
|
### 2.1 Remove/Document LP-Portal Layers
|
||||||
|
**Issue:** 4 LP-Portal layers never tested, likely region-specific (Nowy Sącz)
|
||||||
|
|
||||||
|
**Action Plan:**
|
||||||
|
1. Test if LP-Portal layers work outside Nowy Sącz region
|
||||||
|
2. If region-specific: Move to separate optional configuration
|
||||||
|
3. Document geographic limitations
|
||||||
|
4. Consider conditional loading based on map center coordinates
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
|
||||||
|
**Option A - Remove Entirely:**
|
||||||
|
```javascript
|
||||||
|
// Remove from mapLayers.overlays array:
|
||||||
|
// - LP-Portal Roads
|
||||||
|
// - LP-Portal Street Names
|
||||||
|
// - LP-Portal Parcels
|
||||||
|
// - LP-Portal Survey Markers
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B - Conditional Loading:**
|
||||||
|
```javascript
|
||||||
|
// Only show LP-Portal layers when in Nowy Sącz region
|
||||||
|
const isInNowySecz = (lat, lng) => {
|
||||||
|
return lat >= 49.5 && lat <= 49.7 && lng >= 20.5 && lng <= 20.8;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter overlays based on location
|
||||||
|
const availableOverlays = mapLayers.overlays.filter(layer => {
|
||||||
|
if (layer.name.includes('LP-Portal')) {
|
||||||
|
return isInNowySecz(mapCenter[0], mapCenter[1]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Recommendation:** Option B - Keep but make conditional
|
||||||
|
|
||||||
|
**Success Criteria:** Only relevant layers shown to users
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2.2 Reorganize Layer Categories
|
||||||
|
**Current:** Mixed organization, no clear hierarchy
|
||||||
|
**Proposed:** Clear categorization with user-friendly names
|
||||||
|
|
||||||
|
**New Structure:**
|
||||||
|
```javascript
|
||||||
|
export const mapLayers = {
|
||||||
|
base: [
|
||||||
|
// International Base Maps
|
||||||
|
{ name: "OpenStreetMap", ... },
|
||||||
|
{ name: "🌍 Google Satellite", ... },
|
||||||
|
{ name: "🌍 Google Hybrid", ... },
|
||||||
|
{ name: "🗺️ Esri Satellite", ... },
|
||||||
|
{ name: "🗺️ Topographic (CARTO)", ... },
|
||||||
|
|
||||||
|
// Polish Aerial Imagery
|
||||||
|
{ name: "🇵🇱 Orthophoto (Standard)", ... },
|
||||||
|
{ name: "🇵🇱 Orthophoto (High-Res)", ... }, // After fix
|
||||||
|
],
|
||||||
|
|
||||||
|
overlays: {
|
||||||
|
government: [
|
||||||
|
{ name: "📋 Cadastral Data (Official)", ... },
|
||||||
|
{ name: "🏗️ Spatial Planning", ... },
|
||||||
|
],
|
||||||
|
utility: [
|
||||||
|
{ name: "🛣️ Google Roads", ... },
|
||||||
|
],
|
||||||
|
regional: [ // Only shown in specific regions
|
||||||
|
{ name: "🏘️ LP-Portal Roads", region: "nowysacz", ... },
|
||||||
|
{ name: "🏘️ LP-Portal Street Names", region: "nowysacz", ... },
|
||||||
|
{ name: "🏘️ LP-Portal Parcels", region: "nowysacz", ... },
|
||||||
|
{ name: "🏘️ LP-Portal Survey Markers", region: "nowysacz", ... },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Clearer user experience, better organization
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Performance Optimization (Week 3)
|
||||||
|
|
||||||
|
### 3.1 Implement Tile Caching
|
||||||
|
**Goal:** Reduce redundant WMS requests
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Add to WMSLayer component
|
||||||
|
const WMSLayer = ({ url, params, opacity, attribution }) => {
|
||||||
|
const map = useMap();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const wmsOptions = {
|
||||||
|
// ... existing options ...
|
||||||
|
// Add caching headers
|
||||||
|
crossOrigin: true,
|
||||||
|
updateWhenIdle: true,
|
||||||
|
updateWhenZooming: false,
|
||||||
|
keepBuffer: 2, // Keep tiles loaded from 2 screens away
|
||||||
|
};
|
||||||
|
|
||||||
|
const wmsLayer = L.tileLayer.wms(url, wmsOptions);
|
||||||
|
wmsLayer.addTo(map);
|
||||||
|
|
||||||
|
return () => map.removeLayer(wmsLayer);
|
||||||
|
}, [map, url, params, opacity, attribution]);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** 30% reduction in WMS requests on pan/zoom
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 Add Loading States
|
||||||
|
**Goal:** User feedback during slow WMS loads
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// New LoadingOverlay component
|
||||||
|
function MapLoadingOverlay({ isLoading }) {
|
||||||
|
if (!isLoading) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="absolute top-16 right-4 bg-white dark:bg-gray-800 rounded-lg shadow-lg px-4 py-2 z-[1000]">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className="animate-spin rounded-full h-4 w-4 border-2 border-blue-500 border-t-transparent"></div>
|
||||||
|
<span className="text-sm text-gray-700 dark:text-gray-300">Loading map layers...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track loading state in LeafletMap
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
map.on('layeradd', () => setIsLoading(true));
|
||||||
|
map.on('load', () => setIsLoading(false));
|
||||||
|
}, [map]);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Visual feedback for all layer loads
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 Implement Progressive Layer Loading
|
||||||
|
**Goal:** Load essential layers first, details later
|
||||||
|
|
||||||
|
**Strategy:**
|
||||||
|
1. **Zoom 1-12:** Base map only
|
||||||
|
2. **Zoom 13-15:** + Basic cadastral boundaries
|
||||||
|
3. **Zoom 16-18:** + Parcel numbers, buildings
|
||||||
|
4. **Zoom 19-20:** + Survey markers, detailed overlays
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Auto-enable/disable overlays based on zoom
|
||||||
|
function ZoomBasedOverlayManager() {
|
||||||
|
const map = useMap();
|
||||||
|
const [currentZoom, setCurrentZoom] = useState(map.getZoom());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
map.on('zoomend', () => {
|
||||||
|
const zoom = map.getZoom();
|
||||||
|
setCurrentZoom(zoom);
|
||||||
|
|
||||||
|
// Auto-manage overlay visibility
|
||||||
|
if (zoom < 13) {
|
||||||
|
// Disable all overlays at far zoom
|
||||||
|
disableAllOverlays();
|
||||||
|
} else if (zoom >= 16) {
|
||||||
|
// Enable cadastral at close zoom
|
||||||
|
enableCadastralLayer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [map]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Smooth performance at all zoom levels
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Enhanced Features (Week 4)
|
||||||
|
|
||||||
|
### 4.1 Dynamic Opacity Controls
|
||||||
|
**Goal:** User-adjustable layer transparency
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// LayerOpacityControl component
|
||||||
|
function LayerOpacityControl({ layerName, currentOpacity, onOpacityChange }) {
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-2 px-2 py-1">
|
||||||
|
<label className="text-xs text-gray-600 dark:text-gray-400 w-24 truncate">
|
||||||
|
{layerName}
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="range"
|
||||||
|
min="0"
|
||||||
|
max="100"
|
||||||
|
value={currentOpacity * 100}
|
||||||
|
onChange={(e) => onOpacityChange(e.target.value / 100)}
|
||||||
|
className="flex-1 h-1"
|
||||||
|
/>
|
||||||
|
<span className="text-xs text-gray-500 w-8 text-right">
|
||||||
|
{Math.round(currentOpacity * 100)}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to layer control
|
||||||
|
<LayersControl position="topright">
|
||||||
|
<Overlay name="Cadastral Data">
|
||||||
|
<WMSLayer {...layer} opacity={cadastralOpacity} />
|
||||||
|
</Overlay>
|
||||||
|
<LayerOpacityControl
|
||||||
|
layerName="Cadastral"
|
||||||
|
currentOpacity={cadastralOpacity}
|
||||||
|
onOpacityChange={setCadastralOpacity}
|
||||||
|
/>
|
||||||
|
</LayersControl>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** User can adjust opacity for all overlay layers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.2 Layer Information Panels
|
||||||
|
**Goal:** Show layer metadata, legends, data source info
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// Layer metadata structure
|
||||||
|
const layerMetadata = {
|
||||||
|
"Polish Cadastral Data": {
|
||||||
|
title: "Polish Cadastral Data (Działki)",
|
||||||
|
description: "Official land parcel boundaries and property information from GUGiK",
|
||||||
|
dataSource: "Główny Urząd Geodezji i Kartografii",
|
||||||
|
updateFrequency: "Daily",
|
||||||
|
coverage: "Poland nationwide",
|
||||||
|
legend: "/images/legends/cadastral.png",
|
||||||
|
moreInfo: "https://www.gugik.gov.pl/",
|
||||||
|
usageNotes: "Best viewed at zoom levels 15-18. Performance may vary.",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// InfoButton component next to layer name
|
||||||
|
<LayersControl>
|
||||||
|
<Overlay name={
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
📋 Cadastral Data
|
||||||
|
<button onClick={() => showLayerInfo('Polish Cadastral Data')} className="...">
|
||||||
|
ℹ️
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}>
|
||||||
|
...
|
||||||
|
</Overlay>
|
||||||
|
</LayersControl>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Users understand what each layer shows
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4.3 Error Handling & Fallbacks
|
||||||
|
**Goal:** Graceful degradation when layers fail
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// WMSLayer with error handling
|
||||||
|
function WMSLayer({ url, params, opacity, attribution, fallbackLayer }) {
|
||||||
|
const map = useMap();
|
||||||
|
const [hasError, setHasError] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const wmsLayer = L.tileLayer.wms(url, wmsOptions);
|
||||||
|
|
||||||
|
// Track tile errors
|
||||||
|
wmsLayer.on('tileerror', (error) => {
|
||||||
|
console.error(`WMS tile error for ${params.layers}:`, error);
|
||||||
|
setHasError(true);
|
||||||
|
|
||||||
|
// Show user notification
|
||||||
|
showNotification({
|
||||||
|
type: 'warning',
|
||||||
|
message: `Layer "${params.layers}" is experiencing issues`,
|
||||||
|
duration: 5000
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
wmsLayer.addTo(map);
|
||||||
|
|
||||||
|
// If too many errors, switch to fallback
|
||||||
|
if (hasError && fallbackLayer) {
|
||||||
|
setTimeout(() => {
|
||||||
|
map.removeLayer(wmsLayer);
|
||||||
|
fallbackLayer.addTo(map);
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => map.removeLayer(wmsLayer);
|
||||||
|
}, [map, url, params, hasError]);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** No silent failures, users informed of issues
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5: Code Quality (Week 5)
|
||||||
|
|
||||||
|
### 5.1 Consolidate Map Components
|
||||||
|
**Current Issue:** Multiple similar map components (ComprehensivePolishMap, ImprovedPolishOrthophotoMap, etc.)
|
||||||
|
|
||||||
|
**Action Plan:**
|
||||||
|
1. Audit all map components:
|
||||||
|
- LeafletMap.js (main)
|
||||||
|
- ProjectMap.js (wrapper)
|
||||||
|
- ComprehensivePolishMap.js
|
||||||
|
- ImprovedPolishOrthophotoMap.js
|
||||||
|
- PolishOrthophotoMap.js
|
||||||
|
- AdvancedPolishOrthophotoMap.js
|
||||||
|
- TransparencyDemoMap.js
|
||||||
|
- CustomWMTSMap.js
|
||||||
|
- EnhancedLeafletMap.js
|
||||||
|
|
||||||
|
2. Determine which are:
|
||||||
|
- Production (keep)
|
||||||
|
- Deprecated (remove)
|
||||||
|
- Experimental (move to /docs/examples)
|
||||||
|
|
||||||
|
**Recommendation:**
|
||||||
|
```
|
||||||
|
KEEP:
|
||||||
|
- LeafletMap.js (main production component)
|
||||||
|
- ProjectMap.js (SSR wrapper)
|
||||||
|
|
||||||
|
MOVE TO /docs/examples:
|
||||||
|
- TransparencyDemoMap.js (example of opacity controls)
|
||||||
|
- CustomWMTSMap.js (example of custom WMTS)
|
||||||
|
|
||||||
|
DEPRECATE/REMOVE:
|
||||||
|
- ComprehensivePolishMap.js (superseded by LeafletMap)
|
||||||
|
- ImprovedPolishOrthophotoMap.js (experimental)
|
||||||
|
- PolishOrthophotoMap.js (old version)
|
||||||
|
- AdvancedPolishOrthophotoMap.js (experimental)
|
||||||
|
- EnhancedLeafletMap.js (duplicate?)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Single source of truth for map rendering
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.2 Improve WMTS Capabilities Parsing
|
||||||
|
**Current Issue:** wmtsCapabilities.js has placeholder code
|
||||||
|
|
||||||
|
**Options:**
|
||||||
|
|
||||||
|
**Option A - Complete XML Parsing:**
|
||||||
|
```javascript
|
||||||
|
export async function parseWMTSCapabilities(url) {
|
||||||
|
const response = await fetch(`${url}?Service=WMTS&Request=GetCapabilities`);
|
||||||
|
const xmlText = await response.text();
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const xml = parser.parseFromString(xmlText, 'text/xml');
|
||||||
|
|
||||||
|
const layers = Array.from(xml.querySelectorAll('Layer')).map(layer => ({
|
||||||
|
id: layer.querySelector('Identifier')?.textContent,
|
||||||
|
title: layer.querySelector('Title')?.textContent,
|
||||||
|
formats: Array.from(layer.querySelectorAll('Format')).map(f => f.textContent),
|
||||||
|
tileMatrixSets: Array.from(layer.querySelectorAll('TileMatrixSet')).map(t => t.textContent),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return { layers };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B - Remove and Document:**
|
||||||
|
- Remove wmtsCapabilities.js
|
||||||
|
- Document WMTS configuration in MAP_LAYERS.md
|
||||||
|
- Use manual configuration (current working approach)
|
||||||
|
|
||||||
|
**Recommendation:** Option B - Keep it simple, current approach works
|
||||||
|
|
||||||
|
**Success Criteria:** No dead code, clear documentation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5.3 Add TypeScript/JSDoc Types
|
||||||
|
**Goal:** Better IDE support and type safety
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
/**
|
||||||
|
* @typedef {Object} LayerConfig
|
||||||
|
* @property {string} name - Display name for the layer
|
||||||
|
* @property {'tile'|'wms'} type - Layer type
|
||||||
|
* @property {string} url - Service URL
|
||||||
|
* @property {string} attribution - Attribution HTML
|
||||||
|
* @property {number} [maxZoom=20] - Maximum zoom level
|
||||||
|
* @property {number} [minZoom=0] - Minimum zoom level
|
||||||
|
* @property {number} [opacity=1.0] - Layer opacity (0-1)
|
||||||
|
* @property {boolean} [checked=false] - Default enabled state
|
||||||
|
* @property {Object} [params] - WMS parameters (for WMS layers)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} MapLayersConfig
|
||||||
|
* @property {LayerConfig[]} base - Base layer options
|
||||||
|
* @property {LayerConfig[]} overlays - Overlay layer options
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {MapLayersConfig} */
|
||||||
|
export const mapLayers = {
|
||||||
|
base: [...],
|
||||||
|
overlays: [...]
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Better autocomplete and error detection
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6: Testing & Documentation (Week 6)
|
||||||
|
|
||||||
|
### 6.1 Create Layer Test Suite
|
||||||
|
**Goal:** Automated testing of layer availability
|
||||||
|
|
||||||
|
**Implementation:**
|
||||||
|
```javascript
|
||||||
|
// __tests__/map-layers.test.js
|
||||||
|
describe('Map Layers', () => {
|
||||||
|
describe('Base Layers', () => {
|
||||||
|
test('OSM tiles are accessible', async () => {
|
||||||
|
const response = await fetch('https://a.tile.openstreetmap.org/15/17560/11326.png');
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Polish Orthophoto Standard is accessible', async () => {
|
||||||
|
const url = 'https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?Service=WMTS&Request=GetCapabilities';
|
||||||
|
const response = await fetch(url);
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('WMS Overlays', () => {
|
||||||
|
test('Cadastral WMS GetCapabilities works', async () => {
|
||||||
|
const url = 'https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow?Service=WMS&Request=GetCapabilities';
|
||||||
|
const response = await fetch(url);
|
||||||
|
expect(response.status).toBe(200);
|
||||||
|
expect(response.headers.get('content-type')).toContain('xml');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** All layers validated before deployment
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 6.2 Update Documentation
|
||||||
|
**Files to Update:**
|
||||||
|
1. MAP_LAYERS.md - Add troubleshooting section
|
||||||
|
2. LAYER_NOTES.md - Keep updated with testing
|
||||||
|
3. README.md - Add maps usage section
|
||||||
|
|
||||||
|
**New Documentation:**
|
||||||
|
```markdown
|
||||||
|
## Troubleshooting Map Layers
|
||||||
|
|
||||||
|
### Slow Loading Cadastral Data
|
||||||
|
- **Cause:** GUGiK WMS servers are resource-limited
|
||||||
|
- **Solution:** Only enable at zoom 15+, limit to essential layers
|
||||||
|
- **Alternative:** Pre-cache frequently used areas
|
||||||
|
|
||||||
|
### Polish Orthophoto Not Loading
|
||||||
|
- **Check:** Zoom level (works up to 19, not 20)
|
||||||
|
- **Check:** Network connectivity to geoportal.gov.pl
|
||||||
|
- **Alternative:** Use Google Satellite or Esri
|
||||||
|
|
||||||
|
### Layer Control Not Showing
|
||||||
|
- **Cause:** Map container too small
|
||||||
|
- **Solution:** Minimum map height of 400px recommended
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Criteria:** Users can self-service common issues
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Priority Matrix
|
||||||
|
|
||||||
|
| Priority | Phase | Task | Impact | Effort | Status |
|
||||||
|
|----------|-------|------|--------|--------|--------|
|
||||||
|
| 🔴 P0 | 1 | Fix Polish Orthophoto High-Res | High | Low | Not Started |
|
||||||
|
| 🔴 P0 | 1 | Add zoom restrictions to Cadastral | High | Low | Not Started |
|
||||||
|
| 🟡 P1 | 1 | Fix/Remove Spatial Planning | Medium | Medium | Not Started |
|
||||||
|
| 🟡 P1 | 2 | Document LP-Portal region limits | Medium | Low | Not Started |
|
||||||
|
| 🟡 P1 | 3 | Add loading indicators | Medium | Low | Not Started |
|
||||||
|
| 🟢 P2 | 2 | Reorganize layer categories | Low | Medium | Not Started |
|
||||||
|
| 🟢 P2 | 4 | Add opacity controls | Low | Medium | Not Started |
|
||||||
|
| 🟢 P2 | 4 | Add layer info panels | Low | High | Not Started |
|
||||||
|
| 🟢 P3 | 5 | Consolidate map components | Low | High | Not Started |
|
||||||
|
| 🟢 P3 | 6 | Add automated tests | Low | Medium | Not Started |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Wins (Do First)
|
||||||
|
|
||||||
|
These can be implemented in 1-2 hours with immediate impact:
|
||||||
|
|
||||||
|
1. **Add minZoom to performance-heavy layers**
|
||||||
|
- Prevent loading at far zoom levels (minZoom: 13 for Cadastral)
|
||||||
|
- Reduce unnecessary requests at distant zoom
|
||||||
|
|
||||||
|
2. **Optimize Cadastral layer requests**
|
||||||
|
- Reduce number of requested WMS layers
|
||||||
|
- Add tiled parameter for better performance
|
||||||
|
|
||||||
|
3. **Remove broken Spatial Planning layer**
|
||||||
|
- If GetCapabilities fails, just remove it
|
||||||
|
- Better than showing broken functionality
|
||||||
|
|
||||||
|
4. **Update layer names for clarity**
|
||||||
|
- "Polish Orthophoto Standard" → "🇵🇱 Aerial Imagery (Standard)"
|
||||||
|
- Better user understanding
|
||||||
|
|
||||||
|
5. **Add loading spinner to ProjectMap**
|
||||||
|
- Copy LoadingOverlay component
|
||||||
|
- Better UX during slow loads
|
||||||
|
|
||||||
|
6. **Verify current zoom limits**
|
||||||
|
- Document actual working zoom ranges per layer
|
||||||
|
- Note: Goal is zoom 20 for all layers (future optimization)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- [ ] All base layers load in <2 seconds
|
||||||
|
- [ ] Cadastral overlays load in <5 seconds at zoom 15-18
|
||||||
|
- [ ] No console errors for working layers
|
||||||
|
- [ ] 90%+ tile success rate
|
||||||
|
|
||||||
|
### User Experience
|
||||||
|
- [ ] Layer control accessible on all screen sizes
|
||||||
|
- [ ] Clear feedback during loading
|
||||||
|
- [ ] No broken/blank layers in production
|
||||||
|
- [ ] Layer purposes clear from names/descriptions
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
- [ ] Single production map component
|
||||||
|
- [ ] All map files under 500 lines
|
||||||
|
- [ ] JSDoc types for all exports
|
||||||
|
- [ ] 80%+ test coverage for layer configs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollout Plan
|
||||||
|
|
||||||
|
### Week 1: Emergency Fixes
|
||||||
|
- Fix critical broken layers
|
||||||
|
- Add zoom restrictions
|
||||||
|
- Remove non-working layers
|
||||||
|
|
||||||
|
### Week 2: Optimization
|
||||||
|
- Implement caching
|
||||||
|
- Add loading states
|
||||||
|
- Progressive loading
|
||||||
|
|
||||||
|
### Week 3: Features
|
||||||
|
- Opacity controls
|
||||||
|
- Layer info panels
|
||||||
|
- Error handling
|
||||||
|
|
||||||
|
### Week 4: Cleanup
|
||||||
|
- Consolidate components
|
||||||
|
- Remove experimental code
|
||||||
|
- Update documentation
|
||||||
|
|
||||||
|
### Week 5: Testing
|
||||||
|
- Automated tests
|
||||||
|
- User acceptance testing
|
||||||
|
- Performance benchmarking
|
||||||
|
|
||||||
|
### Week 6: Release
|
||||||
|
- Deploy to production
|
||||||
|
- Monitor performance
|
||||||
|
- Gather user feedback
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Rollback Strategy
|
||||||
|
|
||||||
|
If issues occur:
|
||||||
|
1. **Keep old mapLayers.js** as `mapLayers.backup.js`
|
||||||
|
2. **Feature flags** for new functionality
|
||||||
|
3. **Incremental rollout** - enable for admin users first
|
||||||
|
4. **Quick disable** - config flag to revert to old layers
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Considerations
|
||||||
|
|
||||||
|
### Potential New Features
|
||||||
|
- [ ] **Universal zoom 20 support for all layers**
|
||||||
|
- Optimize WMS services to handle zoom 19-20
|
||||||
|
- Implement tile prefetching and caching
|
||||||
|
- Add progressive detail loading at high zoom
|
||||||
|
- [ ] Save user layer preferences
|
||||||
|
- [ ] Share map view URLs (with layers/zoom)
|
||||||
|
- [ ] Export map as image/PDF
|
||||||
|
- [ ] Offline tile caching
|
||||||
|
- [ ] Custom layer upload (GeoJSON, KML)
|
||||||
|
|
||||||
|
### Alternative Services to Explore
|
||||||
|
- [ ] Planet imagery (if budget allows)
|
||||||
|
- [ ] Bing Maps aerial imagery
|
||||||
|
- [ ] Additional Polish regional services
|
||||||
|
- [ ] CORS proxies for restricted services
|
||||||
|
|
||||||
|
### Advanced Optimizations
|
||||||
|
- [ ] Service worker for tile caching
|
||||||
|
- [ ] WebGL rendering for better performance
|
||||||
|
- [ ] Vector tiles instead of raster
|
||||||
|
- [ ] CDN for frequently accessed tiles
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- LP-Portal layers appear to be **Nowy Sącz specific** - need regional filtering
|
||||||
|
- Polish government servers are **consistently slow** - can't fix, only mitigate
|
||||||
|
- Google services are **unofficial** - may break without notice
|
||||||
|
- WMTS is more performant than WMS - prefer when available
|
||||||
|
- **Zoom 20 support:** Long-term goal for all layers; currently some layers work only to zoom 18-19
|
||||||
|
- Requires server-side optimization or caching strategy
|
||||||
|
- May need to implement client-side tile scaling/interpolation
|
||||||
|
- Keep LAYER_NOTES.md updated as testing continues
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Approval & Sign-off
|
||||||
|
|
||||||
|
- [ ] Technical review completed
|
||||||
|
- [ ] Performance benchmarks met
|
||||||
|
- [ ] Documentation updated
|
||||||
|
- [ ] Stakeholder approval
|
||||||
|
- [ ] Ready for production deployment
|
||||||
|
|
||||||
|
**Last Updated:** January 16, 2026
|
||||||
|
**Next Review:** After Phase 1 completion
|
||||||
Reference in New Issue
Block a user