feat: Import WEA types from Excel and implement dynamic dropdown UI
Deploy Standortplaner / deploy (push) Successful in 19s
Details
Deploy Standortplaner / deploy (push) Successful in 19s
Details
This commit is contained in:
parent
242cdaa400
commit
a844d8a872
Binary file not shown.
97
app.js
97
app.js
|
|
@ -110,8 +110,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const btnDeleteWEA = document.getElementById('btnDeleteWEA');
|
const btnDeleteWEA = document.getElementById('btnDeleteWEA');
|
||||||
|
|
||||||
const editNr = document.getElementById('edit-wea-nr');
|
const editNr = document.getElementById('edit-wea-nr');
|
||||||
const editManufacturer = document.getElementById('edit-wea-manufacturer');
|
const editWeaSelector = document.getElementById('edit-wea-selector');
|
||||||
const editType = document.getElementById('edit-wea-type');
|
|
||||||
const editRd = document.getElementById('edit-wea-rd');
|
const editRd = document.getElementById('edit-wea-rd');
|
||||||
const editNh = document.getElementById('edit-wea-nh');
|
const editNh = document.getElementById('edit-wea-nh');
|
||||||
const editFr = document.getElementById('edit-wea-fr');
|
const editFr = document.getElementById('edit-wea-fr');
|
||||||
|
|
@ -127,8 +126,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const inputRotor = document.getElementById('rotorDiameter');
|
const inputRotor = document.getElementById('rotorDiameter');
|
||||||
const inputHub = document.getElementById('hubHeight');
|
const inputHub = document.getElementById('hubHeight');
|
||||||
const inputFoundation = document.getElementById('foundationRadius');
|
const inputFoundation = document.getElementById('foundationRadius');
|
||||||
const inputManufacturer = document.getElementById('turbineManufacturer');
|
const weaTypeSelector = document.getElementById('weaTypeSelector');
|
||||||
const inputType = document.getElementById('turbineType');
|
|
||||||
|
|
||||||
let placementMode = false;
|
let placementMode = false;
|
||||||
let measureMode = null; // 'dist' or 'area'
|
let measureMode = null; // 'dist' or 'area'
|
||||||
|
|
@ -291,8 +289,20 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
activeTurbine = turbine;
|
activeTurbine = turbine;
|
||||||
editNr.value = turbine.nr;
|
editNr.value = turbine.nr;
|
||||||
editManufacturer.value = turbine.hersteller || 'Enercon';
|
let matched = false;
|
||||||
editType.value = turbine.type;
|
for (const opt of editWeaSelector.options) {
|
||||||
|
if (opt.value) {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(opt.value);
|
||||||
|
if (data.hersteller === turbine.hersteller && data.anlagentyp === turbine.type && data.nabenhoehe === turbine.hh) {
|
||||||
|
editWeaSelector.value = opt.value;
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!matched) editWeaSelector.value = "";
|
||||||
editRd.value = turbine.rd;
|
editRd.value = turbine.rd;
|
||||||
editNh.value = turbine.hh;
|
editNh.value = turbine.hh;
|
||||||
editFr.value = turbine.fr || 15;
|
editFr.value = turbine.fr || 15;
|
||||||
|
|
@ -374,8 +384,15 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const rd = overrideData?.rd || Number.parseFloat(inputRotor?.value) || 160;
|
const rd = overrideData?.rd || Number.parseFloat(inputRotor?.value) || 160;
|
||||||
const hh = overrideData?.hh || Number.parseFloat(inputHub?.value) || 165;
|
const hh = overrideData?.hh || Number.parseFloat(inputHub?.value) || 165;
|
||||||
const fr = overrideData?.fr || Number.parseFloat(inputFoundation?.value) || 15;
|
const fr = overrideData?.fr || Number.parseFloat(inputFoundation?.value) || 15;
|
||||||
const type = overrideData?.type || inputType?.value || "Standard Typ";
|
let type = overrideData?.type || "Standard Typ";
|
||||||
const hersteller = overrideData?.hersteller || inputManufacturer?.value || "Enercon";
|
let hersteller = overrideData?.hersteller || "Unbekannt";
|
||||||
|
if (!overrideData && weaTypeSelector && weaTypeSelector.value) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(weaTypeSelector.value);
|
||||||
|
type = parsed.anlagentyp;
|
||||||
|
hersteller = parsed.hersteller;
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
const weaNr = overrideData?.nr || loadedNr || (state.turbines.length + 1).toString();
|
const weaNr = overrideData?.nr || loadedNr || (state.turbines.length + 1).toString();
|
||||||
const ksfAngle = overrideData?.ksfAngle || 0;
|
const ksfAngle = overrideData?.ksfAngle || 0;
|
||||||
const ksfMirrored = overrideData?.ksfMirrored || false;
|
const ksfMirrored = overrideData?.ksfMirrored || false;
|
||||||
|
|
@ -536,8 +553,15 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
btnSaveEdit.onclick = () => {
|
btnSaveEdit.onclick = () => {
|
||||||
if (!activeTurbine) return;
|
if (!activeTurbine) return;
|
||||||
const newNr = editNr.value;
|
const newNr = editNr.value;
|
||||||
const newManufacturer = editManufacturer.value;
|
let newManufacturer = activeTurbine.hersteller;
|
||||||
const newType = editType.value;
|
let newType = activeTurbine.type;
|
||||||
|
if (editWeaSelector && editWeaSelector.value) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(editWeaSelector.value);
|
||||||
|
newManufacturer = parsed.hersteller;
|
||||||
|
newType = parsed.anlagentyp;
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
const newRd = Number.parseFloat(editRd.value);
|
const newRd = Number.parseFloat(editRd.value);
|
||||||
const newNh = Number.parseFloat(editNh.value);
|
const newNh = Number.parseFloat(editNh.value);
|
||||||
const newFr = Number.parseFloat(editFr.value) || 15;
|
const newFr = Number.parseFloat(editFr.value) || 15;
|
||||||
|
|
@ -2164,6 +2188,58 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize allowed projects and project selector
|
// Initialize allowed projects and project selector
|
||||||
|
window.availableWeaTypes = [];
|
||||||
|
|
||||||
|
async function loadWeaTypes() {
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/wea-types');
|
||||||
|
if (!res.ok) throw new Error('Network response was not ok');
|
||||||
|
window.availableWeaTypes = await res.json();
|
||||||
|
|
||||||
|
// Build grouped options
|
||||||
|
const groups = {};
|
||||||
|
window.availableWeaTypes.forEach(wea => {
|
||||||
|
if (!groups[wea.hersteller]) groups[wea.hersteller] = [];
|
||||||
|
groups[wea.hersteller].push(wea);
|
||||||
|
});
|
||||||
|
|
||||||
|
let html = '<option value="">Bitte Anlage wählen...</option>';
|
||||||
|
for (const h in groups) {
|
||||||
|
html += `<optgroup label="${h}">`;
|
||||||
|
groups[h].forEach(wea => {
|
||||||
|
const jsonStr = JSON.stringify(wea).replace(/"/g, '"');
|
||||||
|
html += `<option value="${jsonStr}">${wea.anlagentyp} (NH: ${wea.nabenhoehe}m, RD: ${wea.rotordurchmesser}m, Nennleistung: ${wea.nennleistung}MW)</option>`;
|
||||||
|
});
|
||||||
|
html += `</optgroup>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weaTypeSelector) {
|
||||||
|
weaTypeSelector.innerHTML = html;
|
||||||
|
weaTypeSelector.addEventListener('change', (e) => {
|
||||||
|
if (!e.target.value) return;
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(e.target.value.replace(/"/g, '"'));
|
||||||
|
inputRotor.value = data.rotordurchmesser;
|
||||||
|
inputHub.value = data.nabenhoehe;
|
||||||
|
} catch(err) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (editWeaSelector) {
|
||||||
|
editWeaSelector.innerHTML = html;
|
||||||
|
editWeaSelector.addEventListener('change', (e) => {
|
||||||
|
if (!e.target.value) return;
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(e.target.value.replace(/"/g, '"'));
|
||||||
|
editRd.value = data.rotordurchmesser;
|
||||||
|
editNh.value = data.nabenhoehe;
|
||||||
|
} catch(err) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Fehler beim Laden der Anlagentypen:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function initializeProjects() {
|
async function initializeProjects() {
|
||||||
const statusEl = document.getElementById('statusInfo');
|
const statusEl = document.getElementById('statusInfo');
|
||||||
try {
|
try {
|
||||||
|
|
@ -2258,6 +2334,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start loading process
|
// Start loading process
|
||||||
|
await loadWeaTypes();
|
||||||
initializeProjects();
|
initializeProjects();
|
||||||
|
|
||||||
// Project Persistence
|
// Project Persistence
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const js = `
|
||||||
|
// --- PDF Export Logic ---
|
||||||
|
const btnExportPDF = document.getElementById('btnExportPDF');
|
||||||
|
if (btnExportPDF) {
|
||||||
|
btnExportPDF.addEventListener('click', async () => {
|
||||||
|
const originalText = btnExportPDF.innerText;
|
||||||
|
btnExportPDF.innerText = 'Exportiere...';
|
||||||
|
btnExportPDF.disabled = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (typeof html2canvas === 'undefined' || typeof jspdf === 'undefined') {
|
||||||
|
throw new Error('PDF Bibliotheken (html2canvas, jspdf) sind noch nicht geladen.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapContainer = document.getElementById('map');
|
||||||
|
|
||||||
|
// Add Overlay
|
||||||
|
const exportOverlay = document.createElement('div');
|
||||||
|
exportOverlay.style.position = 'absolute';
|
||||||
|
exportOverlay.style.bottom = '30px';
|
||||||
|
exportOverlay.style.left = '30px';
|
||||||
|
exportOverlay.style.zIndex = '9999';
|
||||||
|
exportOverlay.style.background = 'rgba(255, 255, 255, 0.95)';
|
||||||
|
exportOverlay.style.padding = '15px';
|
||||||
|
exportOverlay.style.border = '2px solid #333';
|
||||||
|
exportOverlay.style.borderRadius = '5px';
|
||||||
|
exportOverlay.style.color = '#333';
|
||||||
|
exportOverlay.style.fontFamily = 'Arial, sans-serif';
|
||||||
|
exportOverlay.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)';
|
||||||
|
|
||||||
|
const projName = document.getElementById('projectSelector')?.options[document.getElementById('projectSelector')?.selectedIndex]?.text || 'Unbekannt';
|
||||||
|
|
||||||
|
exportOverlay.innerHTML = \`
|
||||||
|
<div style="font-weight: bold; font-size: 1.4rem; margin-bottom: 8px; color: #004a99;">ENWELO Standortplanung</div>
|
||||||
|
<div style="font-size: 1rem; margin-bottom: 12px; font-weight: bold;">Projekt: \${projName}</div>
|
||||||
|
<div style="display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem;">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00c8ff; border: 1px dashed #00c8ff; opacity: 0.5;"></div> Rotorüberstreichfläche</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; background: #00aaff; border: 1px dashed #00aaff; opacity: 0.5;"></div> Gebietsumring</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 3px; background: #ff0000;"></div> Abstandslinien</div>
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;"><div style="width: 16px; height: 16px; border-radius: 50%; background: #00c8ff;"></div> WEA Standort</div>
|
||||||
|
</div>
|
||||||
|
\`;
|
||||||
|
mapContainer.appendChild(exportOverlay);
|
||||||
|
|
||||||
|
// Wait a tiny bit for DOM to render overlay
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
|
const canvas = await html2canvas(mapContainer, {
|
||||||
|
useCORS: true,
|
||||||
|
allowTaint: true,
|
||||||
|
ignoreElements: (element) => {
|
||||||
|
return element.classList.contains('leaflet-control-zoom');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
mapContainer.removeChild(exportOverlay);
|
||||||
|
|
||||||
|
const imgData = canvas.toDataURL('image/png');
|
||||||
|
const pdf = new jspdf.jsPDF({
|
||||||
|
orientation: 'landscape',
|
||||||
|
unit: 'mm',
|
||||||
|
format: 'a3'
|
||||||
|
});
|
||||||
|
|
||||||
|
const pdfWidth = pdf.internal.pageSize.getWidth();
|
||||||
|
const pdfHeight = pdf.internal.pageSize.getHeight();
|
||||||
|
|
||||||
|
const imgProps = pdf.getImageProperties(imgData);
|
||||||
|
const ratio = imgProps.width / imgProps.height;
|
||||||
|
|
||||||
|
let renderWidth = pdfWidth;
|
||||||
|
let renderHeight = pdfWidth / ratio;
|
||||||
|
|
||||||
|
if (renderHeight > pdfHeight) {
|
||||||
|
renderHeight = pdfHeight;
|
||||||
|
renderWidth = pdfHeight * ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Center image in PDF
|
||||||
|
const xOffset = (pdfWidth - renderWidth) / 2;
|
||||||
|
const yOffset = (pdfHeight - renderHeight) / 2;
|
||||||
|
|
||||||
|
pdf.addImage(imgData, 'PNG', xOffset, yOffset, renderWidth, renderHeight);
|
||||||
|
pdf.save('Karte_Enwelo.pdf');
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Fehler beim PDF Export:', err);
|
||||||
|
alert('Fehler beim PDF Export: ' + err.message);
|
||||||
|
} finally {
|
||||||
|
btnExportPDF.innerText = originalText;
|
||||||
|
btnExportPDF.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
fs.appendFileSync('app.js', js);
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
await pool.query('ALTER TABLE geodaten."potentialflächen_wind" ADD COLUMN IF NOT EXISTS projekt_id VARCHAR(255);');
|
||||||
|
console.log('Column projekt_id added successfully.');
|
||||||
|
// Set for samern-ohne as default since they want to see it!
|
||||||
|
// But wait, what if there's only one row?
|
||||||
|
const res = await pool.query('SELECT id FROM geodaten."potentialflächen_wind"');
|
||||||
|
console.log('Found rows:', res.rowCount);
|
||||||
|
if (res.rowCount === 1) {
|
||||||
|
await pool.query("UPDATE geodaten.\"potentialflächen_wind\" SET projekt_id = 'projekt_bw_samern-ohne'");
|
||||||
|
console.log('Updated the single row to projekt_bw_samern-ohne');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Fehler:', e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
await pool.query('ALTER TABLE geodaten."potentialflächen_wind" ADD COLUMN IF NOT EXISTS planungsstand VARCHAR(255);');
|
||||||
|
console.log('Column planungsstand added successfully.');
|
||||||
|
|
||||||
|
const res = await pool.query("UPDATE geodaten.\"potentialflächen_wind\" SET planungsstand = 'rechtsverbindlich'");
|
||||||
|
console.log(`Updated ${res.rowCount} rows to rechtsverbindlich`);
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Fehler:', e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const res = await pool.query("SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'geodaten' AND table_name = 'potentialflächen_wind';");
|
||||||
|
console.log('Columns:', res.rows);
|
||||||
|
|
||||||
|
// Check if projekt_id exists in columns
|
||||||
|
const hasProjektId = res.rows.some(r => r.column_name === 'projekt_id');
|
||||||
|
if (hasProjektId) {
|
||||||
|
const dataRes = await pool.query('SELECT DISTINCT projekt_id FROM geodaten."potentialflächen_wind";');
|
||||||
|
console.log('Projects:', dataRes.rows);
|
||||||
|
} else {
|
||||||
|
console.log('No projekt_id column found.');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Fehler:', e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const client = await pool.connect();
|
||||||
|
await client.query('BEGIN');
|
||||||
|
|
||||||
|
// Update artennachweise
|
||||||
|
let res = await client.query("UPDATE geodaten.artennachweise SET projekt_id = 'trasse_bw_scheddebrock' WHERE projekt_id = 'BW Scheddebrock'");
|
||||||
|
console.log('Artennachweise (trasse_bw_scheddebrock):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.artennachweise SET projekt_id = 'projekt_bw_samern-ohne' WHERE projekt_id = 'bw_samern-ohne'");
|
||||||
|
console.log('Artennachweise (projekt_bw_samern-ohne):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.artennachweise SET projekt_id = 'projekt_bw_test' WHERE projekt_id = 'test'");
|
||||||
|
console.log('Artennachweise (projekt_bw_test):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.artennachweise SET projekt_id = 'projekt_bw_an_der_landwehr' WHERE projekt_id ILIKE '%landwehr%'");
|
||||||
|
console.log('Artennachweise (projekt_bw_an_der_landwehr):', res.rowCount);
|
||||||
|
|
||||||
|
await client.query('COMMIT');
|
||||||
|
console.log('--- ERFOLGREICH GESPEICHERT ---');
|
||||||
|
client.release();
|
||||||
|
} catch(e) {
|
||||||
|
await pool.query('ROLLBACK');
|
||||||
|
console.error('Fehler:', e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const client = await pool.connect();
|
||||||
|
|
||||||
|
await client.query('BEGIN');
|
||||||
|
|
||||||
|
// 1. Projekte
|
||||||
|
let res = await client.query("UPDATE geodaten.projekte SET name = 'trasse_bw_scheddebrock' WHERE name = 'BW Scheddebrock'");
|
||||||
|
console.log('Projekte (trasse_bw_scheddebrock):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.projekte SET name = 'projekt_bw_samern-ohne' WHERE name = 'bw_samern-ohne'");
|
||||||
|
console.log('Projekte (projekt_bw_samern-ohne):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.projekte SET name = 'projekt_bw_test' WHERE name = 'test'");
|
||||||
|
console.log('Projekte (projekt_bw_test):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.projekte SET name = 'projekt_bw_an_der_landwehr' WHERE name ILIKE '%landwehr%'");
|
||||||
|
console.log('Projekte (projekt_bw_an_der_landwehr):', res.rowCount);
|
||||||
|
|
||||||
|
// 2. WEA Standorte
|
||||||
|
res = await client.query("UPDATE geodaten.wea_standorte SET projekt_id = 'trasse_bw_scheddebrock' WHERE projekt_id = 'BW Scheddebrock'");
|
||||||
|
console.log('WEA (trasse_bw_scheddebrock):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_samern-ohne' WHERE projekt_id = 'bw_samern-ohne'");
|
||||||
|
console.log('WEA (projekt_bw_samern-ohne):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_test' WHERE projekt_id = 'test'");
|
||||||
|
console.log('WEA (projekt_bw_test):', res.rowCount);
|
||||||
|
|
||||||
|
res = await client.query("UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_an_der_landwehr' WHERE projekt_id ILIKE '%landwehr%'");
|
||||||
|
console.log('WEA (projekt_bw_an_der_landwehr):', res.rowCount);
|
||||||
|
|
||||||
|
await client.query('COMMIT');
|
||||||
|
console.log('--- ERFOLGREICH GESPEICHERT ---');
|
||||||
|
client.release();
|
||||||
|
} catch(e) {
|
||||||
|
await pool.query('ROLLBACK');
|
||||||
|
console.error('Fehler:', e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- 1. Aktualisieren der Haupttabelle "projekte"
|
||||||
|
UPDATE geodaten.projekte SET name = 'trasse_bw_scheddebrock' WHERE name = 'BW Scheddebrock';
|
||||||
|
UPDATE geodaten.projekte SET name = 'projekt_bw_samern-ohne' WHERE name = 'bw_samern-ohne';
|
||||||
|
UPDATE geodaten.projekte SET name = 'projekt_bw_test' WHERE name = 'test';
|
||||||
|
UPDATE geodaten.projekte SET name = 'projekt_bw_an_der_landwehr' WHERE name ILIKE '%landwehr%';
|
||||||
|
|
||||||
|
-- 2. Aktualisieren der Verknüpfungen in den Standorten (WEA)
|
||||||
|
UPDATE geodaten.wea_standorte SET projekt_id = 'trasse_bw_scheddebrock' WHERE projekt_id = 'BW Scheddebrock';
|
||||||
|
UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_samern-ohne' WHERE projekt_id = 'bw_samern-ohne';
|
||||||
|
UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_test' WHERE projekt_id = 'test';
|
||||||
|
UPDATE geodaten.wea_standorte SET projekt_id = 'projekt_bw_an_der_landwehr' WHERE projekt_id ILIKE '%landwehr%';
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
const shapefile = require('shapefile');
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'enwelo_admin',
|
||||||
|
host: '87.106.21.21',
|
||||||
|
database: 'enwelo',
|
||||||
|
password: 'WX1t1cgP1qK09',
|
||||||
|
port: 5432,
|
||||||
|
ssl: false
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
console.log("Reading shapefile...");
|
||||||
|
const geojson = await shapefile.read("Shapefile/Windeignungsgebiet.shp", "Shapefile/Windeignungsgebiet.dbf");
|
||||||
|
console.log(`Loaded ${geojson.features.length} features.`);
|
||||||
|
|
||||||
|
if (geojson.features.length === 0) {
|
||||||
|
console.log("No features found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = await pool.connect();
|
||||||
|
try {
|
||||||
|
await client.query('BEGIN');
|
||||||
|
|
||||||
|
// wir wollen die Shapefile-Geometrie für samern-ohne in die DB pushen
|
||||||
|
const projektId = 'projekt_bw_samern-ohne';
|
||||||
|
|
||||||
|
// Zuerst bestehende löschen?
|
||||||
|
await client.query('DELETE FROM geodaten."potentialflächen_wind" WHERE projekt_id = $1', [projektId]);
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
for (const feature of geojson.features) {
|
||||||
|
const geomJson = JSON.stringify(feature.geometry);
|
||||||
|
|
||||||
|
await client.query(
|
||||||
|
`INSERT INTO geodaten."potentialflächen_wind" (projekt_id, geom)
|
||||||
|
VALUES ($1, ST_SetSRID(ST_GeomFromGeoJSON($2), 25832))`,
|
||||||
|
[projektId, geomJson]
|
||||||
|
);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.query('COMMIT');
|
||||||
|
console.log(`Erfolgreich ${count} Potentialflächen für ${projektId} importiert!`);
|
||||||
|
} catch (e) {
|
||||||
|
await client.query('ROLLBACK');
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error("Fehler:", e);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
require('dotenv').config({ override: true });
|
||||||
|
const { Pool } = require('pg');
|
||||||
|
const xlsx = require('xlsx');
|
||||||
|
|
||||||
|
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
|
||||||
|
});
|
||||||
|
|
||||||
|
async function importWea() {
|
||||||
|
const wb = xlsx.readFile('./Anlagentypen/Anlagentypen.xlsx');
|
||||||
|
const sheet = wb.Sheets[wb.SheetNames[0]];
|
||||||
|
const data = xlsx.utils.sheet_to_json(sheet);
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('Connecting to DB...');
|
||||||
|
await pool.query('BEGIN');
|
||||||
|
|
||||||
|
console.log('Dropping and creating table geodaten.anlagendaten_wea...');
|
||||||
|
await pool.query(`
|
||||||
|
DROP TABLE IF EXISTS geodaten.anlagendaten_wea;
|
||||||
|
CREATE TABLE geodaten.anlagendaten_wea (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
hersteller VARCHAR(255),
|
||||||
|
anlagentyp VARCHAR(255),
|
||||||
|
nennleistung FLOAT,
|
||||||
|
nabenhoehe FLOAT,
|
||||||
|
rotordurchmesser FLOAT,
|
||||||
|
gesamthoehe FLOAT
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log(`Importing ${data.length} rows...`);
|
||||||
|
for (const row of data) {
|
||||||
|
// Keys from Excel
|
||||||
|
// "Hersteller", "Anlagentyp", "Nennleistung (MW)", "Nabenhöhe (m)", "Rotordurchmesser (m)", "Gesamthöhe (m)"
|
||||||
|
const hersteller = row['Hersteller'] || '';
|
||||||
|
const anlagentyp = row['Anlagentyp'] || '';
|
||||||
|
const nennleistung = parseFloat(row['Nennleistung (MW)'] || 0);
|
||||||
|
const nabenhoehe = parseFloat(row['Nabenhöhe (m)'] || 0);
|
||||||
|
const rotordurchmesser = parseFloat(row['Rotordurchmesser (m)'] || 0);
|
||||||
|
const gesamthoehe = parseFloat(row['Gesamthöhe (m)'] || 0);
|
||||||
|
|
||||||
|
await pool.query(`
|
||||||
|
INSERT INTO geodaten.anlagendaten_wea
|
||||||
|
(hersteller, anlagentyp, nennleistung, nabenhoehe, rotordurchmesser, gesamthoehe)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6)
|
||||||
|
`, [hersteller, anlagentyp, nennleistung, nabenhoehe, rotordurchmesser, gesamthoehe]);
|
||||||
|
}
|
||||||
|
|
||||||
|
await pool.query('COMMIT');
|
||||||
|
console.log('Import finished successfully.');
|
||||||
|
} catch (err) {
|
||||||
|
await pool.query('ROLLBACK');
|
||||||
|
console.error('Error importing:', err);
|
||||||
|
} finally {
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
importWea();
|
||||||
46
index.html
46
index.html
|
|
@ -74,28 +74,19 @@
|
||||||
WEA Konfiguration <span style="margin-left: auto;">+</span>
|
WEA Konfiguration <span style="margin-left: auto;">+</span>
|
||||||
</summary>
|
</summary>
|
||||||
<div style="margin-top: 12px; cursor: default;">
|
<div style="margin-top: 12px; cursor: default;">
|
||||||
<div style="display: flex; gap: 8px; margin-bottom: 6px;">
|
<div style="margin-bottom: 8px;">
|
||||||
<div style="flex: 1;">
|
<label for="weaTypeSelector" class="label-small">Anlagentyp (aus Datenbank)</label>
|
||||||
<label for="turbineManufacturer" class="label-small">Hersteller</label>
|
<select id="weaTypeSelector" class="input-styled input-small" style="width: 100%;">
|
||||||
<select id="turbineManufacturer" class="input-styled input-small">
|
<option value="">Lade Anlagentypen...</option>
|
||||||
<option value="Enercon">Enercon</option>
|
</select>
|
||||||
<option value="Nordex">Nordex</option>
|
|
||||||
<option value="Vestas">Vestas</option>
|
|
||||||
<option value="GE">GE</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div style="flex: 1;">
|
|
||||||
<label for="turbineType" class="label-small">Anlagentyp</label>
|
|
||||||
<input type="text" id="turbineType" class="input-styled input-small" placeholder="z.B. V162">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
||||||
<label for="rotorDiameter" class="label-small" style="flex: 1; margin: 0;">Rotordurchmesser (m)</label>
|
<label for="rotorDiameter" class="label-small" style="flex: 1; margin: 0; color: var(--text-dim);">Rotordurchmesser (m)</label>
|
||||||
<input type="number" id="rotorDiameter" class="input-styled input-small" value="160" style="width: 60px;">
|
<input type="number" id="rotorDiameter" class="input-styled input-small" value="" style="width: 60px; background: rgba(255,255,255,0.05);" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
||||||
<label for="hubHeight" class="label-small" style="flex: 1; margin: 0;">Nabenhöhe (m)</label>
|
<label for="hubHeight" class="label-small" style="flex: 1; margin: 0; color: var(--text-dim);">Nabenhöhe (m)</label>
|
||||||
<input type="number" id="hubHeight" class="input-styled input-small" value="165" style="width: 60px;">
|
<input type="number" id="hubHeight" class="input-styled input-small" value="" style="width: 60px; background: rgba(255,255,255,0.05);" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
<div style="display: flex; gap: 8px; align-items: center; margin-bottom: 6px;">
|
||||||
<label for="foundationRadius" class="label-small" style="flex: 1; margin: 0;">Fundament Radius (m)</label>
|
<label for="foundationRadius" class="label-small" style="flex: 1; margin: 0;">Fundament Radius (m)</label>
|
||||||
|
|
@ -180,26 +171,19 @@
|
||||||
<label for="edit-wea-nr">Nr:</label>
|
<label for="edit-wea-nr">Nr:</label>
|
||||||
<input type="text" id="edit-wea-nr" class="edit-input">
|
<input type="text" id="edit-wea-nr" class="edit-input">
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-row separator">
|
<div class="edit-row separator" style="flex-direction: column; align-items: flex-start; gap: 4px;">
|
||||||
<label for="edit-wea-manufacturer">Hersteller:</label>
|
<label for="edit-wea-selector">Anlagentyp:</label>
|
||||||
<select id="edit-wea-manufacturer" class="edit-input">
|
<select id="edit-wea-selector" class="edit-input" style="width: 100%;">
|
||||||
<option value="Enercon">Enercon</option>
|
<option value="">Lade Anlagentypen...</option>
|
||||||
<option value="Nordex">Nordex</option>
|
|
||||||
<option value="Vestas">Vestas</option>
|
|
||||||
<option value="GE">GE</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-row separator">
|
|
||||||
<label for="edit-wea-type">Typ:</label>
|
|
||||||
<input type="text" id="edit-wea-type" class="edit-input">
|
|
||||||
</div>
|
|
||||||
<div class="edit-row">
|
<div class="edit-row">
|
||||||
<label for="edit-wea-rd">RD (m):</label>
|
<label for="edit-wea-rd">RD (m):</label>
|
||||||
<input type="number" id="edit-wea-rd" class="edit-input">
|
<input type="number" id="edit-wea-rd" class="edit-input" style="background: rgba(255,255,255,0.05);" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-row separator">
|
<div class="edit-row separator">
|
||||||
<label for="edit-wea-nh">NH (m):</label>
|
<label for="edit-wea-nh">NH (m):</label>
|
||||||
<input type="number" id="edit-wea-nh" class="edit-input">
|
<input type="number" id="edit-wea-nh" class="edit-input" style="background: rgba(255,255,255,0.05);" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-row">
|
<div class="edit-row">
|
||||||
<label for="edit-wea-fr">Fund (m):</label>
|
<label for="edit-wea-fr">Fund (m):</label>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,8 @@
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"pg": "^8.11.5",
|
"pg": "^8.11.5",
|
||||||
"shapefile": "^0.6.6"
|
"shapefile": "^0.6.6",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/accepts": {
|
"node_modules/accepts": {
|
||||||
|
|
@ -29,6 +30,15 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/adler-32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/array-flatten": {
|
"node_modules/array-flatten": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||||
|
|
@ -103,6 +113,28 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cfb": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"crc-32": "~1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/codepage": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "2.20.3",
|
"version": "2.20.3",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
|
|
@ -162,6 +194,18 @@
|
||||||
"url": "https://opencollective.com/express"
|
"url": "https://opencollective.com/express"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crc-32": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bin": {
|
||||||
|
"crc32": "bin/crc32.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
|
|
@ -358,6 +402,15 @@
|
||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/frac": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
|
|
@ -1001,6 +1054,18 @@
|
||||||
"node": ">= 10.x"
|
"node": ">= 10.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ssf": {
|
||||||
|
"version": "0.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||||
|
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"frac": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/statuses": {
|
"node_modules/statuses": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
|
||||||
|
|
@ -1072,6 +1137,45 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wmf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/word": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xlsx": {
|
||||||
|
"version": "0.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||||
|
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"cfb": "~1.2.1",
|
||||||
|
"codepage": "~1.15.0",
|
||||||
|
"crc-32": "~1.2.1",
|
||||||
|
"ssf": "~0.11.2",
|
||||||
|
"wmf": "~1.0.1",
|
||||||
|
"word": "~0.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xlsx": "bin/xlsx.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xtend": {
|
"node_modules/xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"express": "^4.19.2",
|
"express": "^4.19.2",
|
||||||
"pg": "^8.11.5",
|
"pg": "^8.11.5",
|
||||||
"shapefile": "^0.6.6"
|
"shapefile": "^0.6.6",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
const xlsx = require('xlsx');
|
||||||
|
const wb = xlsx.readFile('./Anlagentypen/Anlagentypen.xlsx');
|
||||||
|
const sheetName = wb.SheetNames[0];
|
||||||
|
const sheet = wb.Sheets[sheetName];
|
||||||
|
const data = xlsx.utils.sheet_to_json(sheet);
|
||||||
|
console.log('Columns:', Object.keys(data[0] || {}));
|
||||||
|
console.log('Sample Data:', data.slice(0, 3));
|
||||||
14
server.js
14
server.js
|
|
@ -215,6 +215,20 @@ app.get('/api/logs', (req, res) => {
|
||||||
res.type('text/plain').send(serverLogs.join('\n'));
|
res.type('text/plain').send(serverLogs.join('\n'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// API to load available WEA types
|
||||||
|
app.get('/api/wea-types', async (req, res) => {
|
||||||
|
const client = await pool.connect();
|
||||||
|
try {
|
||||||
|
const result = await client.query('SELECT * FROM geodaten.anlagendaten_wea ORDER BY hersteller, anlagentyp, nabenhoehe');
|
||||||
|
res.status(200).json(result.rows);
|
||||||
|
} catch (e) {
|
||||||
|
log(`FEHLER beim Laden der Anlagentypen: ${e.message}`);
|
||||||
|
res.status(500).json({ error: e.message });
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// API to save turbines
|
// API to save turbines
|
||||||
app.post('/api/wea', async (req, res) => {
|
app.post('/api/wea', async (req, res) => {
|
||||||
const { projekt_id, turbines } = req.body;
|
const { projekt_id, turbines } = req.body;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue