feat: link project to postgres database (geodaten.wea_standorte) and add save button
This commit is contained in:
parent
5682c076c1
commit
4107a62167
|
|
@ -0,0 +1,12 @@
|
|||
node_modules/
|
||||
.env
|
||||
backend/node_modules/
|
||||
backend/check_db.py
|
||||
backend/check_db.js
|
||||
backend/check_db2.js
|
||||
backend/check_db_admin.js
|
||||
backend/list_tables.js
|
||||
backend/check_columns.js
|
||||
backend/setup_db.py
|
||||
.vscode/
|
||||
*.log
|
||||
38
app.js
38
app.js
|
|
@ -1414,9 +1414,45 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
a.download = `WindPlan_Projekt_${new Date().toLocaleDateString()}.json`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
document.getElementById('statusInfo').innerText = "Projekt exportiert.";
|
||||
document.getElementById('statusInfo').innerText = "Projekt lokal exportiert.";
|
||||
});
|
||||
|
||||
const btnSaveDB = document.getElementById('btnSaveDB');
|
||||
if (btnSaveDB) {
|
||||
btnSaveDB.addEventListener('click', async () => {
|
||||
const statusEl = document.getElementById('statusInfo');
|
||||
statusEl.innerText = "Speichere in Datenbank...";
|
||||
|
||||
const project_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('http://localhost:3000/api/wea', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ projekt_id, turbines: turbineData })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
statusEl.innerHTML = `<span style="color: #2ecc71;">${result.message}</span>`;
|
||||
} else {
|
||||
throw new Error("Fehler beim Speichern in DB");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
statusEl.innerHTML = `<span style="color: #ff4444;">Fehler beim DB-Sync: ${err.message}</span>`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
btnLoad.addEventListener('click', () => projectInput.click());
|
||||
|
||||
projectInput.addEventListener('change', (e) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
require('dotenv').config();
|
||||
const express = require('express');
|
||||
const { Pool } = require('pg');
|
||||
const bodyParser = require('body-parser');
|
||||
const cors = require('cors');
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
app.use(cors());
|
||||
app.use(bodyParser.json());
|
||||
|
||||
const pool = new Pool({
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT,
|
||||
database: process.env.DB_NAME,
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD
|
||||
});
|
||||
|
||||
// Test DB Connection
|
||||
pool.connect()
|
||||
.then(() => console.log('Connected to PostgreSQL (enwelo_db) successfully'))
|
||||
.catch(err => console.error('Connection error', err.stack));
|
||||
|
||||
// API to save turbines
|
||||
app.post('/api/wea', async (req, res) => {
|
||||
const { projekt_id, turbines } = req.body;
|
||||
const client = await pool.connect();
|
||||
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
|
||||
// Delete existing turbines for this project before saving new state
|
||||
// (This ensures we always have the latest state on 'Save')
|
||||
await client.query('DELETE FROM geodaten.wea_standorte WHERE projekt_id = $1', [projekt_id]);
|
||||
|
||||
for(let t of turbines) {
|
||||
// Mapping frontend data to geodaten.wea_standorte columns:
|
||||
// wea_nummer, hersteller, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, projekt_id, geom
|
||||
|
||||
await client.query(
|
||||
`INSERT INTO geodaten.wea_standorte (
|
||||
wea_nummer, hersteller, anlagentyp, nabenhoehe, rotordurchmesser, ksf_drehung, projekt_id, geom
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, ST_SetSRID(ST_MakePoint($8, $9), 4326))`,
|
||||
[
|
||||
t.nr,
|
||||
t.hersteller || '',
|
||||
t.type,
|
||||
parseInt(t.hh),
|
||||
parseInt(t.rd),
|
||||
parseInt(t.ksfAngle || 0),
|
||||
projekt_id,
|
||||
t.latlng.lng,
|
||||
t.latlng.lat
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
await client.query('COMMIT');
|
||||
res.status(200).json({ message: 'Windenergieanlagen erfolgreich in Datenbank gespeichert' });
|
||||
} catch (e) {
|
||||
await client.query('ROLLBACK');
|
||||
console.error('Error saving turbines', e);
|
||||
res.status(500).json({ error: e.message });
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
});
|
||||
|
||||
// API to load turbines
|
||||
app.get('/api/wea/:projekt_id', async (req, res) => {
|
||||
const { projekt_id } = req.params;
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`SELECT wea_nummer as nr, anlagentyp as type, nabenhoehe as hh, rotordurchmesser as rd, ksf_drehung as ksfAngle,
|
||||
ST_X(geom) as lng, ST_Y(geom) as lat
|
||||
FROM geodaten.wea_standorte WHERE projekt_id = $1`,
|
||||
[projekt_id]
|
||||
);
|
||||
res.status(200).json(result.rows);
|
||||
} catch (e) {
|
||||
console.error('Error loading turbines', e);
|
||||
res.status(500).json({ error: e.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Backend server listening at http://localhost:${port}`);
|
||||
});
|
||||
|
|
@ -120,8 +120,9 @@
|
|||
|
||||
<div class="section">
|
||||
<h2>Projektverwaltung</h2>
|
||||
<button class="btn-secondary" id="btnSaveProject">Projekt speichern</button>
|
||||
<button class="btn-secondary" id="btnLoadProject">Projekt laden</button>
|
||||
<button class="btn-secondary" id="btnSaveProject">Projekt speichern (Lokal)</button>
|
||||
<button class="btn-primary" id="btnSaveDB">In Datenbank speichern</button>
|
||||
<button class="btn-secondary" id="btnLoadProject">Projekt laden (Lokal)</button>
|
||||
<input type="file" id="projectInput" style="display: none;" accept=".json">
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue