v1.0.6: fix CSP wildcard *.geo.admin.ch, fix SW tile caching, dropdown layer selector, reduce swisstopo maxzoom
This commit is contained in:
@@ -49,9 +49,9 @@ const nextConfig = {
|
|||||||
"default-src 'self'",
|
"default-src 'self'",
|
||||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:",
|
"script-src 'self' 'unsafe-inline' 'unsafe-eval' blob:",
|
||||||
"style-src 'self' 'unsafe-inline'",
|
"style-src 'self' 'unsafe-inline'",
|
||||||
"img-src 'self' data: blob: https://*.tile.openstreetmap.org https://api.maptiler.com https://server.arcgisonline.com https://wmts.geo.admin.ch https://wmts0.geo.admin.ch https://wmts1.geo.admin.ch https://wmts2.geo.admin.ch https://wmts3.geo.admin.ch https://wmts4.geo.admin.ch http://localhost:9000 http://minio:9000",
|
"img-src 'self' data: blob: https://*.tile.openstreetmap.org https://api.maptiler.com https://server.arcgisonline.com https://*.geo.admin.ch http://localhost:9000 http://minio:9000",
|
||||||
"font-src 'self' data:",
|
"font-src 'self' data:",
|
||||||
"connect-src 'self' ws: wss: https://api.maptiler.com https://*.tile.openstreetmap.org https://api.open-meteo.com https://server.arcgisonline.com https://wmts.geo.admin.ch https://wmts0.geo.admin.ch https://wmts1.geo.admin.ch https://wmts2.geo.admin.ch https://wmts3.geo.admin.ch https://wmts4.geo.admin.ch",
|
"connect-src 'self' ws: wss: https://api.maptiler.com https://*.tile.openstreetmap.org https://api.open-meteo.com https://server.arcgisonline.com https://*.geo.admin.ch",
|
||||||
"frame-ancestors 'self'",
|
"frame-ancestors 'self'",
|
||||||
"base-uri 'self'",
|
"base-uri 'self'",
|
||||||
"form-action 'self'",
|
"form-action 'self'",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lageplan",
|
"name": "lageplan",
|
||||||
"version": "1.0.5",
|
"version": "1.0.6",
|
||||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -87,8 +87,8 @@ self.addEventListener('fetch', (event) => {
|
|||||||
// Other API requests: network only
|
// Other API requests: network only
|
||||||
if (pathname.startsWith('/api/')) return
|
if (pathname.startsWith('/api/')) return
|
||||||
|
|
||||||
// Cache map tiles from OpenStreetMap / MapTiler (Cache First — tiles don't change)
|
// Cache map tiles from OSM / MapTiler / ArcGIS / Swisstopo (Cache First — tiles don't change)
|
||||||
if (url.includes('tile.openstreetmap.org') || url.includes('api.maptiler.com')) {
|
if (url.includes('tile.openstreetmap.org') || url.includes('api.maptiler.com') || url.includes('server.arcgisonline.com') || url.includes('geo.admin.ch')) {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
caches.open(TILE_CACHE).then((cache) =>
|
caches.open(TILE_CACHE).then((cache) =>
|
||||||
cache.match(event.request).then((cached) => {
|
cache.match(event.request).then((cached) => {
|
||||||
|
|||||||
@@ -696,7 +696,7 @@ export function MapView({
|
|||||||
],
|
],
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
attribution: '© swisstopo',
|
attribution: '© swisstopo',
|
||||||
maxzoom: 18,
|
maxzoom: 17,
|
||||||
},
|
},
|
||||||
'swissimage': {
|
'swissimage': {
|
||||||
type: 'raster',
|
type: 'raster',
|
||||||
@@ -705,7 +705,7 @@ export function MapView({
|
|||||||
],
|
],
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
attribution: '© swisstopo SWISSIMAGE',
|
attribution: '© swisstopo SWISSIMAGE',
|
||||||
maxzoom: 20,
|
maxzoom: 18,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
layers: [
|
layers: [
|
||||||
@@ -2154,39 +2154,34 @@ export function MapView({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Layer toggle: cycle through base maps */}
|
{/* Layer selector dropdown */}
|
||||||
<button
|
<select
|
||||||
onClick={() => {
|
value={activeBaseLayer}
|
||||||
|
onChange={(e) => {
|
||||||
if (!map.current) return
|
if (!map.current) return
|
||||||
const layers: Array<'osm' | 'satellite' | 'swisstopo' | 'swissimage'> = ['osm', 'satellite', 'swisstopo', 'swissimage']
|
const newLayer = e.target.value as 'osm' | 'satellite' | 'swisstopo' | 'swissimage'
|
||||||
const currentIdx = layers.indexOf(activeBaseLayer)
|
const allLayers: Array<'osm' | 'satellite' | 'swisstopo' | 'swissimage'> = ['osm', 'satellite', 'swisstopo', 'swissimage']
|
||||||
const nextLayer = layers[(currentIdx + 1) % layers.length]
|
for (const l of allLayers) {
|
||||||
for (const l of layers) {
|
map.current.setLayoutProperty(l, 'visibility', l === newLayer ? 'visible' : 'none')
|
||||||
map.current.setLayoutProperty(l, 'visibility', l === nextLayer ? 'visible' : 'none')
|
|
||||||
}
|
}
|
||||||
setActiveBaseLayer(nextLayer)
|
setActiveBaseLayer(newLayer)
|
||||||
}}
|
}}
|
||||||
className="absolute top-3 right-3 z-10 flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs font-semibold shadow-lg border transition-colors"
|
className="absolute top-3 right-3 z-10 px-2.5 py-1.5 rounded-lg text-xs font-semibold shadow-lg border transition-colors cursor-pointer appearance-none pr-7"
|
||||||
style={{
|
style={{
|
||||||
background: activeBaseLayer !== 'osm' ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.95)',
|
background: activeBaseLayer !== 'osm' ? 'rgba(0,0,0,0.75)' : 'rgba(255,255,255,0.95)',
|
||||||
color: activeBaseLayer !== 'osm' ? '#fff' : '#333',
|
color: activeBaseLayer !== 'osm' ? '#fff' : '#333',
|
||||||
borderColor: activeBaseLayer !== 'osm' ? 'rgba(255,255,255,0.3)' : 'rgba(0,0,0,0.15)',
|
borderColor: activeBaseLayer !== 'osm' ? 'rgba(255,255,255,0.3)' : 'rgba(0,0,0,0.15)',
|
||||||
|
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='${activeBaseLayer !== 'osm' ? 'white' : '%23333'}' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E")`,
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundPosition: 'right 6px center',
|
||||||
}}
|
}}
|
||||||
title="Kartenstil wechseln"
|
title="Kartenstil wählen"
|
||||||
>
|
>
|
||||||
{activeBaseLayer === 'osm' && (
|
<option value="osm">🗺️ OpenStreetMap</option>
|
||||||
<><svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>Satellit</>
|
<option value="satellite">🛰️ Satellit (Esri)</option>
|
||||||
)}
|
<option value="swisstopo">🇨🇭 Swisstopo Karte</option>
|
||||||
{activeBaseLayer === 'satellite' && (
|
<option value="swissimage">🇨🇭 Swisstopo Luftbild</option>
|
||||||
<><svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 7l6-3 6 3 6-3v13l-6 3-6-3-6 3z"/><path d="M9 4v13"/><path d="M15 7v13"/></svg>Swisstopo</>
|
</select>
|
||||||
)}
|
|
||||||
{activeBaseLayer === 'swisstopo' && (
|
|
||||||
<><svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/></svg>Luftbild CH</>
|
|
||||||
)}
|
|
||||||
{activeBaseLayer === 'swissimage' && (
|
|
||||||
<><svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M3 7l6-3 6 3 6-3v13l-6 3-6-3-6 3z"/><path d="M9 4v13"/><path d="M15 7v13"/></svg>OSM</>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* Zeichnung abschliessen Button (Linie/Polygon/Pfeil) */}
|
{/* Zeichnung abschliessen Button (Linie/Polygon/Pfeil) */}
|
||||||
{(drawMode === 'linestring' || drawMode === 'polygon' || drawMode === 'arrow' || drawMode === 'dangerzone') && drawingPointCount >= 2 && (
|
{(drawMode === 'linestring' || drawMode === 'polygon' || drawMode === 'arrow' || drawMode === 'dangerzone') && drawingPointCount >= 2 && (
|
||||||
|
|||||||
Reference in New Issue
Block a user