Refactor LeafletMap to implement custom WMSLayer component and remove WMSTileLayer usage; update mapLayers configuration for improved readability and maintainability; delete obsolete page_backup.js file.

This commit is contained in:
Chop
2025-06-24 22:46:53 +02:00
parent af133c1d5f
commit 74550be679
4 changed files with 395 additions and 340 deletions

View File

@@ -29,7 +29,8 @@ export default function ProjectsMapPage() {
in_progress_design: true, in_progress_design: true,
in_progress_construction: true, in_progress_construction: true,
fulfilled: true, fulfilled: true,
}); const [activeBaseLayer, setActiveBaseLayer] = useState("Polish Geoportal Orthophoto"); });
const [activeBaseLayer, setActiveBaseLayer] = useState("OpenStreetMap");
const [activeOverlays, setActiveOverlays] = useState([]); const [activeOverlays, setActiveOverlays] = useState([]);
const [showLayerPanel, setShowLayerPanel] = useState(true); const [showLayerPanel, setShowLayerPanel] = useState(true);
const [currentTool, setCurrentTool] = useState("move"); // Current map tool const [currentTool, setCurrentTool] = useState("move"); // Current map tool
@@ -103,9 +104,9 @@ export default function ProjectsMapPage() {
// Update URL with current map state (debounced to avoid too many updates) // Update URL with current map state (debounced to avoid too many updates)
const updateURL = (center, zoom) => { const updateURL = (center, zoom) => {
const params = new URLSearchParams(); const params = new URLSearchParams();
params.set('lat', center[0].toFixed(6)); params.set("lat", center[0].toFixed(6));
params.set('lng', center[1].toFixed(6)); params.set("lng", center[1].toFixed(6));
params.set('zoom', zoom.toString()); params.set("zoom", zoom.toString());
// Use replace to avoid cluttering browser history // Use replace to avoid cluttering browser history
router.replace(`/projects/map?${params.toString()}`, { scroll: false }); router.replace(`/projects/map?${params.toString()}`, { scroll: false });
@@ -126,9 +127,9 @@ export default function ProjectsMapPage() {
// Hide navigation and ensure full-screen layout // Hide navigation and ensure full-screen layout
useEffect(() => { useEffect(() => {
// Check for URL parameters for coordinates and zoom // Check for URL parameters for coordinates and zoom
const lat = searchParams.get('lat'); const lat = searchParams.get("lat");
const lng = searchParams.get('lng'); const lng = searchParams.get("lng");
const zoom = searchParams.get('zoom'); const zoom = searchParams.get("zoom");
if (lat && lng) { if (lat && lng) {
const latitude = parseFloat(lat); const latitude = parseFloat(lat);
@@ -177,8 +178,8 @@ export default function ProjectsMapPage() {
setProjects(data); setProjects(data);
// Only calculate center based on projects if no URL parameters are provided // Only calculate center based on projects if no URL parameters are provided
const lat = searchParams.get('lat'); const lat = searchParams.get("lat");
const lng = searchParams.get('lng'); const lng = searchParams.get("lng");
if (!lat || !lng) { if (!lat || !lng) {
// Calculate center based on projects with coordinates // Calculate center based on projects with coordinates
@@ -348,9 +349,7 @@ export default function ProjectsMapPage() {
); );
} }
return ( return (
<div <div className="fixed inset-0 bg-gray-50 overflow-hidden">
className="fixed inset-0 bg-gray-50 overflow-hidden"
>
{/* Floating Header - Left Side */} {/* Floating Header - Left Side */}
<div className="absolute top-4 left-4 z-[1000]"> <div className="absolute top-4 left-4 z-[1000]">
{/* Title Box */} {/* Title Box */}
@@ -362,9 +361,9 @@ export default function ProjectsMapPage() {
<div className="text-sm text-gray-600"> <div className="text-sm text-gray-600">
{markers.length} of {projects.length} projects with coordinates {markers.length} of {projects.length} projects with coordinates
</div> </div>
</div> </div> </div>{" "}
</div>
</div> </div>
{/* Zoom Controls - Below Title */} {/* Zoom Controls - Below Title */}
<div className="absolute top-20 left-4 z-[1000]"> <div className="absolute top-20 left-4 z-[1000]">
<div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 flex flex-col"> <div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 flex flex-col">
@@ -372,7 +371,7 @@ export default function ProjectsMapPage() {
className="px-3 py-2 hover:bg-gray-50 transition-colors duration-200 border-b border-gray-200 text-gray-700 font-medium text-lg" className="px-3 py-2 hover:bg-gray-50 transition-colors duration-200 border-b border-gray-200 text-gray-700 font-medium text-lg"
onClick={() => { onClick={() => {
// This will be handled by the map component // This will be handled by the map component
const event = new CustomEvent('mapZoomIn'); const event = new CustomEvent("mapZoomIn");
window.dispatchEvent(event); window.dispatchEvent(event);
}} }}
title="Zoom In" title="Zoom In"
@@ -383,15 +382,21 @@ export default function ProjectsMapPage() {
className="px-3 py-2 hover:bg-gray-50 transition-colors duration-200 text-gray-700 font-medium text-lg" className="px-3 py-2 hover:bg-gray-50 transition-colors duration-200 text-gray-700 font-medium text-lg"
onClick={() => { onClick={() => {
// This will be handled by the map component // This will be handled by the map component
const event = new CustomEvent('mapZoomOut'); const event = new CustomEvent("mapZoomOut");
window.dispatchEvent(event); window.dispatchEvent(event);
}} }}
title="Zoom Out" title="Zoom Out"
> >
</button> </div> </button>{" "}
</div> {/* Tool Panel - Below Zoom Controls */} </div>
<div className="absolute top-48 left-4 z-[1000]"> <div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 flex flex-col"> {/* Move Tool */} </div>{" "}
{/* Tool Panel - Below Zoom Controls */}
<div className="absolute top-48 left-4 z-[1000]">
{" "}
<div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg border border-gray-200 flex flex-col">
{" "}
{/* Move Tool */}
<button <button
className={`p-3 transition-colors duration-200 border-b border-gray-200 ${ className={`p-3 transition-colors duration-200 border-b border-gray-200 ${
currentTool === "move" currentTool === "move"
@@ -401,15 +406,10 @@ export default function ProjectsMapPage() {
onClick={() => setCurrentTool("move")} onClick={() => setCurrentTool("move")}
title="Move Tool (Pan Map)" title="Move Tool (Pan Map)"
> >
<svg <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 512 512">
className="w-5 h-5" <path d="M256 0c-25.3 0-47.2 14.7-57.6 36c-7-2.6-14.5-4-22.4-4c-35.3 0-64 28.7-64 64l0 165.5-2.7-2.7c-25-25-65.5-25-90.5 0s-25 65.5 0 90.5L106.5 437c48 48 113.1 75 181 75l8.5 0 8 0c1.5 0 3-.1 4.5-.4c91.7-6.2 165-79.4 171.1-171.1c.3-1.5 .4-3 .4-4.5l0-176c0-35.3-28.7-64-64-64c-5.5 0-10.9 .7-16 2l0-2c0-35.3-28.7-64-64-64c-7.9 0-15.4 1.4-22.4 4C303.2 14.7 281.3 0 256 0zM240 96.1l0-.1 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 31.9 0 .1 0 136c0 13.3 10.7 24 24 24s24-10.7 24-24l0-136c0 0 0 0 0-.1c0-8.8 7.2-16 16-16s16 7.2 16 16l0 55.9c0 0 0 .1 0 .1l0 80c0 13.3 10.7 24 24 24s24-10.7 24-24l0-71.9c0 0 0-.1 0-.1c0-8.8 7.2-16 16-16s16 7.2 16 16l0 172.9c-.1 .6-.1 1.3-.2 1.9c-3.4 69.7-59.3 125.6-129 129c-.6 0-1.3 .1-1.9 .2l-4.9 0-8.5 0c-55.2 0-108.1-21.9-147.1-60.9L52.7 315.3c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0L119 336.4c6.9 6.9 17.2 8.9 26.2 5.2s14.8-12.5 14.8-22.2L160 96c0-8.8 7.2-16 16-16c8.8 0 16 7.1 16 15.9L192 232c0 13.3 10.7 24 24 24s24-10.7 24-24l0-135.9z" />
fill="currentColor"
viewBox="0 0 512 512"
>
<path d="M256 0c-25.3 0-47.2 14.7-57.6 36c-7-2.6-14.5-4-22.4-4c-35.3 0-64 28.7-64 64l0 165.5-2.7-2.7c-25-25-65.5-25-90.5 0s-25 65.5 0 90.5L106.5 437c48 48 113.1 75 181 75l8.5 0 8 0c1.5 0 3-.1 4.5-.4c91.7-6.2 165-79.4 171.1-171.1c.3-1.5 .4-3 .4-4.5l0-176c0-35.3-28.7-64-64-64c-5.5 0-10.9 .7-16 2l0-2c0-35.3-28.7-64-64-64c-7.9 0-15.4 1.4-22.4 4C303.2 14.7 281.3 0 256 0zM240 96.1l0-.1 0-32c0-8.8 7.2-16 16-16s16 7.2 16 16l0 31.9 0 .1 0 136c0 13.3 10.7 24 24 24s24-10.7 24-24l0-136c0 0 0 0 0-.1c0-8.8 7.2-16 16-16s16 7.2 16 16l0 55.9c0 0 0 .1 0 .1l0 80c0 13.3 10.7 24 24 24s24-10.7 24-24l0-71.9c0 0 0-.1 0-.1c0-8.8 7.2-16 16-16s16 7.2 16 16l0 172.9c-.1 .6-.1 1.3-.2 1.9c-3.4 69.7-59.3 125.6-129 129c-.6 0-1.3 .1-1.9 .2l-4.9 0-8.5 0c-55.2 0-108.1-21.9-147.1-60.9L52.7 315.3c-6.2-6.2-6.2-16.4 0-22.6s16.4-6.2 22.6 0L119 336.4c6.9 6.9 17.2 8.9 26.2 5.2s14.8-12.5 14.8-22.2L160 96c0-8.8 7.2-16 16-16c8.8 0 16 7.1 16 15.9L192 232c0 13.3 10.7 24 24 24s24-10.7 24-24l0-135.9z"/>
</svg> </svg>
</button> </button>
{/* Select Tool */} {/* Select Tool */}
<button <button
className={`p-3 transition-colors duration-200 border-b border-gray-200 ${ className={`p-3 transition-colors duration-200 border-b border-gray-200 ${
@@ -434,7 +434,6 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
</button> </button>
{/* Measure Tool */} {/* Measure Tool */}
<button <button
className={`p-3 transition-colors duration-200 border-b border-gray-200 ${ className={`p-3 transition-colors duration-200 border-b border-gray-200 ${
@@ -459,7 +458,6 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
</button> </button>
{/* Draw Tool */} {/* Draw Tool */}
<button <button
className={`p-3 transition-colors duration-200 border-b border-gray-200 ${ className={`p-3 transition-colors duration-200 border-b border-gray-200 ${
@@ -484,7 +482,6 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
</button> </button>
{/* Pin/Marker Tool */} {/* Pin/Marker Tool */}
<button <button
className={`p-3 transition-colors duration-200 border-b border-gray-200 ${ className={`p-3 transition-colors duration-200 border-b border-gray-200 ${
@@ -515,7 +512,6 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
</button> </button>
{/* Area Tool */} {/* Area Tool */}
<button <button
className={`p-3 transition-colors duration-200 ${ className={`p-3 transition-colors duration-200 ${
@@ -542,7 +538,6 @@ export default function ProjectsMapPage() {
</button> </button>
</div> </div>
</div> </div>
{/* Layer Control Panel - Right Side */} {/* Layer Control Panel - Right Side */}
<div className="absolute top-4 right-4 z-[1000] flex flex-col gap-3"> <div className="absolute top-4 right-4 z-[1000] flex flex-col gap-3">
{/* Action Buttons */} {/* Action Buttons */}
@@ -635,10 +630,15 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
</button> </button>
</div> {/* Layer Control Content */} </div>{" "}
<div className={`transition-all duration-300 ease-in-out ${ {/* Layer Control Content */}
showLayerPanel ? "max-h-[70vh] opacity-100 overflow-visible" : "max-h-0 opacity-0 overflow-hidden" <div
}`}> className={`transition-all duration-300 ease-in-out ${
showLayerPanel
? "max-h-[70vh] opacity-100 overflow-visible"
: "max-h-0 opacity-0 overflow-hidden"
}`}
>
<div className="p-4 min-w-80 max-w-96 max-h-[60vh] overflow-y-auto"> <div className="p-4 min-w-80 max-w-96 max-h-[60vh] overflow-y-auto">
{/* Base Layers Section */} {/* Base Layers Section */}
<div className="mb-4"> <div className="mb-4">
@@ -697,7 +697,8 @@ export default function ProjectsMapPage() {
/> />
</svg> </svg>
Overlay Layers Overlay Layers
</h3> <div className="space-y-2"> </h3>{" "}
<div className="space-y-2">
{mapLayers.overlays.map((layer, index) => ( {mapLayers.overlays.map((layer, index) => (
<label <label
key={index} key={index}
@@ -718,9 +719,9 @@ export default function ProjectsMapPage() {
</div> </div>
)} )}
</div> </div>
</div> </div> </div>{" "}
</div>
</div> </div>
{/* Status Filter Panel - Bottom Left */} {/* Status Filter Panel - Bottom Left */}
<div className="absolute bottom-4 left-4 z-[1000]"> <div className="absolute bottom-4 left-4 z-[1000]">
<div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg px-4 py-3 border border-gray-200"> <div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg px-4 py-3 border border-gray-200">
@@ -728,7 +729,6 @@ export default function ProjectsMapPage() {
<span className="text-sm font-medium text-gray-700 mr-2"> <span className="text-sm font-medium text-gray-700 mr-2">
Filters: Filters:
</span> </span>
{/* Toggle All Button */} {/* Toggle All Button */}
<button <button
onClick={toggleAllFilters} onClick={toggleAllFilters}
@@ -754,7 +754,6 @@ export default function ProjectsMapPage() {
: "Show All"} : "Show All"}
</span> </span>
</button> </button>
{/* Individual Status Filters */} {/* Individual Status Filters */}
{Object.entries(statusConfig).map(([status, config]) => { {Object.entries(statusConfig).map(([status, config]) => {
const isActive = statusFilters[status]; const isActive = statusFilters[status];
@@ -795,10 +794,13 @@ export default function ProjectsMapPage() {
</span> </span>
</button> </button>
); );
})} </div> })}{" "}
</div> </div>
</div> {/* Status Panel - Bottom Left */} </div>
{markers.length > 0 && ( <div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg px-4 py-3 border border-gray-200"> </div>{" "}
{/* Status Panel - Bottom Left */}
{markers.length > 0 && (
<div className="bg-white/95 backdrop-blur-sm rounded-lg shadow-lg px-4 py-3 border border-gray-200">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-sm font-medium text-gray-700 mr-2"> <span className="text-sm font-medium text-gray-700 mr-2">
Filters: Filters:
@@ -873,7 +875,8 @@ export default function ProjectsMapPage() {
})} })}
</div> </div>
</div> </div>
)} {/* Full Screen Map */} )}{" "}
{/* Full Screen Map */}
{markers.length === 0 ? ( {markers.length === 0 ? (
<div className="h-full w-full flex items-center justify-center bg-gray-100"> <div className="h-full w-full flex items-center justify-center bg-gray-100">
<div className="text-center max-w-md mx-auto p-8 bg-white rounded-lg shadow-lg"> <div className="text-center max-w-md mx-auto p-8 bg-white rounded-lg shadow-lg">
@@ -919,6 +922,7 @@ export default function ProjectsMapPage() {
onViewChange={handleMapViewChange} onViewChange={handleMapViewChange}
/> />
</div> </div>
)} </div> )}{" "}
</div>
); );
} }

View File

@@ -3,7 +3,6 @@
import { import {
MapContainer, MapContainer,
TileLayer, TileLayer,
WMSTileLayer,
Marker, Marker,
Popup, Popup,
LayersControl, LayersControl,
@@ -15,6 +14,45 @@ import "leaflet/dist/leaflet.css";
import { useEffect } from "react"; import { useEffect } from "react";
import { mapLayers } from "./mapLayers"; import { mapLayers } from "./mapLayers";
// Custom WMS Layer component using Leaflet's native WMS support
function WMSLayer({ url, params, opacity = 1, attribution }) {
const map = useMap();
useEffect(() => {
if (!map || !url) return;
// Clean up params for L.tileLayer.wms
const wmsOptions = {
layers: params.layers,
styles: params.styles || '',
format: params.format || 'image/png',
transparent: params.transparent !== false,
version: params.version || '1.1.1',
attribution: attribution,
opacity: opacity
};
// Add CRS/SRS parameter based on version
const version = parseFloat(params.version || '1.1.1');
if (version >= 1.3) {
wmsOptions.crs = L.CRS.EPSG3857;
} else {
wmsOptions.srs = 'EPSG:3857';
}
// Create WMS layer using Leaflet's native support
const wmsLayer = L.tileLayer.wms(url, wmsOptions);
wmsLayer.addTo(map);
return () => {
map.removeLayer(wmsLayer);
};
}, [map, url, params, opacity, attribution]);
return null;
}
// Fix for default markers in react-leaflet // Fix for default markers in react-leaflet
const fixLeafletIcons = () => { const fixLeafletIcons = () => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
@@ -148,12 +186,10 @@ export default function EnhancedLeafletMap({
name={layer.name} name={layer.name}
> >
{layer.type === "wms" ? ( {layer.type === "wms" ? (
<WMSTileLayer <WMSLayer
attribution={layer.attribution} attribution={layer.attribution}
url={layer.url} url={layer.url}
params={layer.params} params={layer.params}
format={layer.params.format}
transparent={layer.params.transparent}
opacity={layer.opacity} opacity={layer.opacity}
/> />
) : ( ) : (
@@ -188,13 +224,11 @@ export default function EnhancedLeafletMap({
.map((layer, index) => { .map((layer, index) => {
if (layer.type === "wms") { if (layer.type === "wms") {
return ( return (
<WMSTileLayer <WMSLayer
key={`custom-overlay-${index}`} key={`custom-overlay-${index}`}
attribution={layer.attribution} attribution={layer.attribution}
url={layer.url} url={layer.url}
params={layer.params} params={layer.params}
format={layer.params.format}
transparent={layer.params.transparent}
opacity={layer.opacity} opacity={layer.opacity}
/> />
); );

View File

@@ -1,124 +1,136 @@
// Map layer configurations // Map layer configurations
import { generateLayerConfig } from './wmtsCapabilities'; import { generateLayerConfig } from "./wmtsCapabilities";
// Generate layer configurations from WMTS capabilities // Generate layer configurations from WMTS capabilities
const polishOrthophoto = generateLayerConfig('orthophoto'); const polishOrthophoto = generateLayerConfig("orthophoto");
export const mapLayers = { export const mapLayers = {
base: [ base: [
{ {
name: "OpenStreetMap", name: "OpenStreetMap",
checked: true, checked: true,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors', attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
maxZoom: 20 maxZoom: 20,
}, },
{ {
name: "🇵🇱 Polish Orthophoto (Standard)", name: "🇵🇱 Polish Orthophoto (Standard)",
attribution: '&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>', attribution:
'&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ORTO&STYLE=default&TILEMATRIXSET=EPSG:3857&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=image/jpeg", url: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?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: 20, maxZoom: 20,
checked: false checked: false,
}, },
{ {
name: "🇵🇱 Polish Orthophoto (High Resolution)", name: "🇵🇱 Polish Orthophoto (High Resolution)",
attribution: '&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>', attribution:
'&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
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", 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: 20, maxZoom: 20,
checked: false checked: false,
}, },
{ {
name: "🌍 Google Satellite", name: "🌍 Google Satellite",
attribution: '&copy; Google', attribution: "&copy; Google",
url: "http://mt1.google.com/vt/lyrs=s&hl=pl&x={x}&y={y}&z={z}", url: "http://mt1.google.com/vt/lyrs=s&hl=pl&x={x}&y={y}&z={z}",
maxZoom: 20, maxZoom: 20,
checked: false checked: false,
}, { },
{
name: "🌍 Google Hybrid", name: "🌍 Google Hybrid",
attribution: '&copy; Google', attribution: "&copy; Google",
url: "http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}", url: "http://mt1.google.com/vt/lyrs=y&hl=pl&x={x}&y={y}&z={z}",
maxZoom: 20, maxZoom: 20,
checked: false checked: false,
}, },
{ {
name: "Satellite (Esri)", name: "Satellite (Esri)",
attribution: '&copy; <a href="https://www.esri.com/">Esri</a> &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community', attribution:
'&copy; <a href="https://www.esri.com/">Esri</a> &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community',
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
maxZoom: 20 maxZoom: 20,
}, },
{ {
name: "Topographic", name: "Topographic",
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/attributions">CARTO</a>', attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/attributions">CARTO</a>',
url: "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png", url: "https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",
maxZoom: 20 maxZoom: 20,
} },
].filter(Boolean), // Remove any null entries ].filter(Boolean), // Remove any null entries
overlays: [ overlays: [
{ {
name: "🌍 Google Roads", name: "🌍 Google Roads",
type: "tile", type: "tile",
attribution: '&copy; Google', attribution: "&copy; Google",
url: "http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}", url: "http://mt1.google.com/vt/lyrs=h&hl=pl&x={x}&y={y}&z={z}",
maxZoom: 20, maxZoom: 20,
opacity: 1.0, opacity: 1.0,
checked: false checked: false,
}, { },
{
name: "📋 Polish Cadastral Data (Działki) - Server 1", name: "📋 Polish Cadastral Data (Działki) - Server 1",
type: "wms", type: "wms",
attribution: '&copy; <a href="https://www.gugik.gov.pl/">GUGiK</a> - Krajowa Integracja Ewidencji Gruntów', attribution:
'&copy; <a href="https://www.gugik.gov.pl/">GUGiK</a> - Krajowa Integracja Ewidencji Gruntów',
url: "https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow", url: "https://integracja01.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: 'powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki', layers:
styles: ',,,,,,,', "powiaty,powiaty_obreby,zsin,obreby,dzialki,geoportal,numery_dzialek,budynki",
format: 'image/png', styles: ",,,,,,,",
format: "image/png",
transparent: true, transparent: true,
version: '1.3.0', version: "1.3.0",
srs: 'EPSG:3857', srs: "EPSG:3857",
exceptions: 'xml', exceptions: "xml",
tiled: true tiled: true,
}, },
opacity: 0.8, opacity: 0.8,
checked: false checked: false,
}, },
{ {
name: "📋 Polish Cadastral Data (Działki) - Server 2", name: "📋 Polish Cadastral Data (Działki) - Server 2",
type: "wms", type: "wms",
attribution: '&copy; <a href="https://www.gugik.gov.pl/">GUGiK</a> - Krajowa Integracja Ewidencji Gruntów', attribution:
'&copy; <a href="https://www.gugik.gov.pl/">GUGiK</a> - Krajowa Integracja Ewidencji Gruntów',
url: "https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow", url: "https://integracja.gugik.gov.pl/cgi-bin/KrajowaIntegracjaEwidencjiGruntow",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: 'dzialki,obreby,numery_dzialek,budynki,kontury,uzytki', layers: "dzialki,obreby,numery_dzialek,budynki,kontury,uzytki",
styles: ',,,,,,', styles: ",,,,,,",
format: 'image/png', format: "image/png",
transparent: true, transparent: true,
version: '1.3.0', version: "1.3.0",
srs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 0.8, opacity: 0.8,
checked: false checked: false,
}, },
{ {
name: "🏗️ Polish Spatial Planning", name: "🏗️ Polish Spatial Planning",
type: "wms", type: "wms",
attribution: '&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>', attribution:
'&copy; <a href="https://www.geoportal.gov.pl/">Geoportal</a>',
url: "https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego", url: "https://mapy.geoportal.gov.pl/wss/ext/KrajowaIntegracjaMiejscowychPlanowZagospodarowaniaPrzestrzennego",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: 'raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice', layers:
styles: ',,,,,,', "raster,wektor-str,wektor-lzb,wektor-pow,wektor-lin,wektor-pkt,granice",
format: 'image/png', styles: ",,,,,,",
format: "image/png",
transparent: true, transparent: true,
version: '1.3.0', version: "1.3.0",
srs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 0.7, opacity: 0.7,
checked: false checked: false,
}, },
{ {
name: "🛣️ LP-Portal Roads", name: "🛣️ LP-Portal Roads",
@@ -126,18 +138,18 @@ export const mapLayers = {
attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>', attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>',
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms", url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: '00_6_mapainteraktywna_drogi', layers: "00_6_mapainteraktywna_drogi",
styles: '', styles: "",
format: 'image/png8', format: "image/png8",
transparent: true, transparent: true,
version: '1.3.0', version: "1.3.0",
srs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 0.9, opacity: 0.9,
checked: false checked: false,
}, },
{ {
name: "🏷️ LP-Portal Street Names", name: "🏷️ LP-Portal Street Names",
@@ -145,18 +157,19 @@ export const mapLayers = {
attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>', attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>',
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms", url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: '00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic', layers:
styles: '', "00_5_mapainteraktywna_opisy_drog,00_3_mapainteraktywna_nazwy_ulic",
format: 'image/png8', styles: "",
format: "image/png8",
transparent: true, transparent: true,
version: '1.1.1', version: "1.1.1",
srs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 1.0, opacity: 1.0,
checked: false checked: false,
}, },
{ {
name: "📐 LP-Portal Parcels", name: "📐 LP-Portal Parcels",
@@ -164,18 +177,18 @@ export const mapLayers = {
attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>', attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>',
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms", url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: 'dzialki', layers: "dzialki",
styles: '', styles: "",
format: 'image/png', format: "image/png",
transparent: true, transparent: true,
version: '1.1.1', version: "1.1.1",
srs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 0.6, opacity: 0.6,
checked: false checked: false,
}, },
{ {
name: "📍 LP-Portal Survey Markers", name: "📍 LP-Portal Survey Markers",
@@ -183,31 +196,32 @@ export const mapLayers = {
attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>', attribution: '&copy; <a href="https://lp-portal.pl/">LP-Portal</a>',
url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms", url: "https://geoserver.lp-portal.pl/geoserver/pzdnowysacz/wms",
params: { params: {
service: 'WMS', service: "WMS",
request: 'GetMap', request: "GetMap",
layers: '00_2_view_geop_odcinek_pikietaz_glob_multi', layers: "00_2_view_geop_odcinek_pikietaz_glob_multi",
styles: '', styles: "",
format: 'image/png8', format: "image/png8",
transparent: true, transparent: true,
version: '1.1.1', version: "1.1.1",
crs: 'EPSG:3857', srs: "EPSG:3857",
tiled: true tiled: true,
}, },
opacity: 0.8, opacity: 0.8,
checked: false checked: false,
} },
] ],
}; };
// WMTS services configuration with GetCapabilities URLs // WMTS services configuration with GetCapabilities URLs
export const wmtsServices = { export const wmtsServices = {
polishOrthophoto: { polishOrthophoto: {
capabilitiesUrl: "https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?Service=WMTS&Request=GetCapabilities", capabilitiesUrl:
"https://mapy.geoportal.gov.pl/wss/service/PZGIK/ORTO/WMTS/StandardResolution?Service=WMTS&Request=GetCapabilities",
layer: "ORTO", layer: "ORTO",
style: "default", style: "default",
tilematrixSet: "EPSG:2180", tilematrixSet: "EPSG:2180",
format: "image/jpeg" format: "image/jpeg",
} },
}; };
// Helper function to check WMTS capabilities // Helper function to check WMTS capabilities
@@ -221,7 +235,10 @@ export async function checkWMTSCapabilities(serviceKey) {
console.log(`WMTS Capabilities for ${serviceKey}:`, xml); console.log(`WMTS Capabilities for ${serviceKey}:`, xml);
return xml; return xml;
} catch (error) { } catch (error) {
console.error(`Failed to fetch WMTS capabilities for ${serviceKey}:`, error); console.error(
`Failed to fetch WMTS capabilities for ${serviceKey}:`,
error
);
return null; return null;
} }
} }