diff --git a/index.html b/index.html index 474310c..ea68c6f 100644 --- a/index.html +++ b/index.html @@ -1720,8 +1720,8 @@ middleMarkers: true, pane: 'trassenPane', lineOptions: { color: '#cca300', weight: 6 }, - vertexOptions: { color: '#cca300', radius: 5 }, - middleMarkerOptions: { color: '#cca300', opacity: 0.5, radius: 3 } + vertexOptions: { color: '#cca300', radius: 6 }, + middleMarkerOptions: { color: '#cca300', opacity: 0.6, radius: 4 } }); drillingLayers[v.id] = L.featureGroup({ interactive: false, pane: 'drillingPane' }); labelLayers[v.id] = L.featureGroup({ interactive: false, pane: 'labelPane' }); @@ -1732,8 +1732,29 @@ labelLayers[v.id].addTo(map); } - // Allow vertex insertion by clicking the polyline itself - routeLayers[v.id].on('click', handleVertexInsertion); + // Allow vertex insertion by clicking anywhere on the polyline + routeLayers[v.id].on('click', (e) => { + if (!v.active) return; + if (!map.editTools) return; + + // Prevent the default map click from bubbling + L.DomEvent.stopPropagation(e); + + const layer = routeLayers[v.id]; + // Find the closest segment and insert a point + const point = map.mouseEventToLatLng(e.originalEvent); + const vertexIndex = findClosestSegmentIndex(layer.getLatLngs(), point); + + if (vertexIndex !== -1) { + const latlngs = layer.getLatLngs(); + latlngs.splice(vertexIndex + 1, 0, point); + layer.setLatLngs(latlngs); + layer.editor.refresh(); // Tell the Leaflet.Editable editor to update markers + + // Trigger all the sync events manually + map.fire('editable:vertex:inserted', { layer: layer }); + } + }); } const layer = routeLayers[v.id]; @@ -1892,13 +1913,27 @@ calculateStats(activeV); updateVariantStatsUI(activeV); updateVariantStatsUI(activeV); - if (e.type.includes('end') || e.type === 'editable:created' || e.type.includes('dragend')) { + if (e.type.includes('end') || e.type === 'editable:created' || e.type.includes('dragend') || e.type === 'editable:vertex:inserted') { renderVariants(); const _activeV = state.variants.find(v => v.active); if (_activeV) saveVariantToDB(_activeV); } }); + // Helper to find the best spot to insert a new vertex + function findClosestSegmentIndex(latlngs, point) { + let minDistance = Infinity; + let index = -1; + for (let i = 0; i < latlngs.length - 1; i++) { + const distance = L.LineUtil.closestPointOnSegment(map.latLngToLayerPoint(point), map.latLngToLayerPoint(latlngs[i]), map.latLngToLayerPoint(latlngs[i+1])).distanceTo(map.latLngToLayerPoint(point)); + if (distance < minDistance) { + minDistance = distance; + index = i; + } + } + return index; + } + function getFlattenedCoords(raw) { if (!raw) return []; // If it's a flat array of LatLngs already @@ -2787,7 +2822,11 @@ if (slot && f.geometry && f.geometry.coordinates) { slot.id = f.id || p.id || slot.id; slot.routes = f.geometry.coordinates.map(c => ({ lat: c[1], lng: c[0] })); - console.log(`[V3-Sync] ${slot.name} erfolgreich gemappt.`); + + // Re-sync the polyline layer if it exists + if (routeLayers[slot.id]) { + routeLayers[slot.id].setLatLngs(slot.routes); + } } }); @@ -2825,6 +2864,7 @@ if (Math.abs(firstCoord) > 1000) gj = transformGeoJSON(gj, "EPSG:25832", "EPSG:4326"); } state.usage = gj; + cachedObstacles = null; // IMPORTANT: Reset cache to trigger new calculation updateUsageLayer(); } } catch (e) { console.error("[V3-Sync] Usage Error:", e); } diff --git a/server.js b/server.js index 9aa76df..4e7dc84 100644 --- a/server.js +++ b/server.js @@ -187,7 +187,7 @@ app.get('/api/variants', async (req, res) => { await setSchema(client); const query = ` SELECT - id, name, "Variante", + COALESCE(id, fid) AS id, name, "Variante", ST_AsGeoJSON(ST_Transform(geom, 4326)) as geometry FROM kabeltrasse ORDER BY id DESC @@ -227,22 +227,21 @@ app.post('/api/variants', async (req, res) => { const varianteValue = properties.Variante || (properties.name ? properties.name.replace('Variante ', '') : 'A'); const geoJsonStr = JSON.stringify(geometry); - const upsertQuery = ` + // Delete existing variant if it exists (Manual UPSERT to bypass missing index permissions) + await client.query('DELETE FROM kabeltrasse WHERE "Variante" = $1 OR name = $2', [varianteValue, routeName]); + + const insertQuery = ` INSERT INTO kabeltrasse (geom, name, "Variante") VALUES ( ST_MakeValid(ST_Transform(ST_GeomFromGeoJSON($1), 25832)), $2, $3 ) - ON CONFLICT ("Variante") - DO UPDATE SET - geom = EXCLUDED.geom, - name = EXCLUDED.name RETURNING id `; - const upsertRes = await client.query(upsertQuery, [geoJsonStr, routeName, varianteValue]); - res.json({ success: true, id: upsertRes.rows[0].id }); + const insertRes = await client.query(insertQuery, [geoJsonStr, routeName, varianteValue]); + res.json({ success: true, id: insertRes.rows[0].id }); } catch (err) { console.error("SQL-FEHLER (SAVE):", err.message); res.status(500).json({ error: 'Failed to save variant' });