Robust saving strategy and vertex editing improvement
Deploy TrassenPlaner / deploy (push) Waiting to run Details

This commit is contained in:
Johannes Baumeister 2026-04-20 09:56:54 +02:00
parent bf6183ce80
commit 6e5ef89733
2 changed files with 53 additions and 14 deletions

View File

@ -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); }

View File

@ -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' });