diff --git a/app.js b/app.js index 0fec8df..784d97d 100644 --- a/app.js +++ b/app.js @@ -396,6 +396,7 @@ document.addEventListener('DOMContentLoaded', async () => { updateLabel(turbine, newGeoms); updateProximityLines(); updateLegend(); // Show symbols in legend + triggerAutoSave(); if (activeTurbine && activeTurbine.id === turbine.id) { // Keep fields updated editNr.value = turbine.nr; @@ -429,9 +430,12 @@ document.addEventListener('DOMContentLoaded', async () => { turbine.layers.mf.clearLayers().addData(newGeoms.mf); updateRotationHandlePos(turbine); }); + + turbine.layers.rotationHandle.on('dragend', triggerAutoSave); state.turbines.push(turbine); updateProximityLines(); + triggerAutoSave(); if (!loadedNr) openEditPanel(turbine); } @@ -471,6 +475,7 @@ document.addEventListener('DOMContentLoaded', async () => { activeTurbine.layers.mf.clearLayers().addData(geoms.mf); updateLabel(activeTurbine, geoms); updateProximityLines(); + triggerAutoSave(); document.getElementById('statusInfo').innerText = `WEA ${newNr} gespeichert.`; }; @@ -481,6 +486,7 @@ document.addEventListener('DOMContentLoaded', async () => { Object.values(activeTurbine.layers).forEach(l => variantLayers[activeTurbine.variant].removeLayer(l)); state.turbines = state.turbines.filter(t => t.id !== activeTurbine.id); updateProximityLines(); + triggerAutoSave(); closeEditPanel(); } }; @@ -1417,40 +1423,52 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('statusInfo').innerText = "Projekt lokal exportiert."; }); + // DB Persistence + let autoSaveTimeout = null; + function triggerAutoSave() { + if (autoSaveTimeout) clearTimeout(autoSaveTimeout); + autoSaveTimeout = setTimeout(() => { + saveTurbinesToDB(); + }, 1500); // 1.5 Seconds debounce + } + + async function saveTurbinesToDB() { + const statusEl = document.getElementById('statusInfo'); + if (statusEl) statusEl.innerText = "Automatische Speicherung..."; + + const projekt_id = "BWSamern-Ohne"; + const turbineData = state.turbines.map(t => ({ + nr: t.nr, + variant: t.variant, + type: t.type, + rd: t.rd, + hh: t.hh, + ksfAngle: t.ksfAngle, + latlng: t.layers.marker.getLatLng() + })); + + try { + const response = await fetch('/api/wea', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ projekt_id, turbines: turbineData }) + }); + + const result = await response.json(); + if (response.ok) { + if (statusEl) statusEl.innerHTML = `${result.message}`; + } else { + throw new Error(result.error || "Fehler beim Speichern in DB"); + } + } catch (err) { + console.error(err); + if (statusEl) statusEl.innerHTML = `Auto-Save Fehler: ${err.message}`; + } + } + const btnSaveDB = document.getElementById('btnSaveDB'); if (btnSaveDB) { - btnSaveDB.addEventListener('click', async () => { - const statusEl = document.getElementById('statusInfo'); - statusEl.innerText = "Speichere in Datenbank..."; - - const projekt_id = "BWSamern-Ohne"; // Could be dynamic from config - const turbineData = state.turbines.map(t => ({ - nr: t.nr, - variant: t.variant, - type: t.type, - rd: t.rd, - hh: t.hh, - latlng: t.layers.marker.getLatLng() - })); - - try { - const response = await fetch('/api/wea', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ projekt_id, turbines: turbineData }) - }); - - const result = await response.json(); - if (response.ok) { - statusEl.innerHTML = `${result.message}`; - } else { - throw new Error(result.error || "Fehler beim Speichern in DB"); - } - } catch (err) { - console.error(err); - statusEl.innerHTML = `Fehler beim DB-Sync: ${err.message}`; - } - }); + btnSaveDB.addEventListener('click', saveTurbinesToDB); } async function loadTurbinesFromDB() { @@ -1475,7 +1493,8 @@ document.addEventListener('DOMContentLoaded', async () => { nr: t.nr, type: t.type, rd: t.rd, - hh: t.hh + hh: t.hh, + ksfAngle: t.ksfangle || t.ksfAngle }); }); statusEl.innerText = `${dbTurbines.length} WEAs aus Datenbank geladen.`; @@ -1536,6 +1555,7 @@ document.addEventListener('DOMContentLoaded', async () => { updateProximityLines(); updateLegend(); + triggerAutoSave(); document.getElementById('statusInfo').innerText = "Projekt geladen."; } catch (err) { diff --git a/server.js b/server.js index 3dc65d0..e1e6faa 100644 --- a/server.js +++ b/server.js @@ -75,9 +75,9 @@ app.post('/api/wea', async (req, res) => { log(`Füge WEA ein: Nr=${t.nr}, Typ=${t.type}, Pos=${t.latlng?.lat},${t.latlng?.lng}`); await client.query( `INSERT INTO ${schema}.wea_standorte - (projekt_id, wea_nummer, anlagentyp, nabenhoehe, rotordurchmesser, geom) - VALUES ($1, $2, $3, $4, $5, ST_Transform(ST_SetSRID(ST_MakePoint($6, $7), 4326), 25832))`, - [targetProject, t.nr, t.type, t.hh, t.rd, t.latlng.lng, t.latlng.lat] + (projekt_id, wea_nummer, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, geom) + VALUES ($1, $2, $3, $4, $5, $6, ST_Transform(ST_SetSRID(ST_MakePoint($7, $8), 4326), 25832))`, + [targetProject, t.nr, t.type, t.hh, t.rd, t.ksfAngle, t.latlng.lng, t.latlng.lat] ); } }