Compare commits

...

10 Commits

Author SHA1 Message Date
ISA
3a9b436352 feat: Icons 2025-09-12 15:59:44 +02:00
ISA
7b881e80c2 link Ebenen 2025-09-12 15:18:55 +02:00
ISA
cc19a0a466 feat: hamburger menu und info Icons 2025-09-12 14:55:19 +02:00
ISA
f200d0bb20 chore(husky): remove deprecated v9 bootstrap lines from pre-commit 2025-09-12 13:58:44 +02:00
ISA
75a0ab000f chore(Websocket): Websocket dump refresh 2025-09-12 13:58:13 +02:00
ISA
4d2a94ffea chore(mocks): sync all mock JSON with WebService (10.10.0.13) 2025-09-12 13:23:26 +02:00
ISA
239ad82e46 fix(dev): add missing Map flags in GisSystemStatic to match production
Add/restore Map: 1 attributes in GisSystemStatic (dev)
Ensures mapLayers initialization creates visibility keys
Fixes missing area markers and layer control state in dev
Behavior now consistent with production
2025-09-12 13:09:21 +02:00
ISA
a2d3338624 fix: kein DB Verbindung von der Anwendung
Der Fehler war, dass im Code die Funktion getDebugLog() verwendet wurde, die nicht definiert war.
Dadurch ist beim Erstellen des Datenbank-Pools ein Fehler aufgetreten, bevor überhaupt eine Verbindung zur Datenbank aufgebaut werden konnte.

Erst nachdem die Debug-Logik entfernt wurde, konnte die Verbindung erfolgreich hergestellt werden.
Das Problem lag also nicht an der Datenbank oder an den Zugangsdaten, sondern an einem fehlenden bzw. nicht importierten Hilfsfunktion im Pool-Code.
2025-09-12 12:19:51 +02:00
ISA
598acb8441 doc: TODO Icons 2025-09-12 09:33:58 +02:00
ISA
f8512c485e doc: TODO 2025-09-12 09:26:59 +02:00
15 changed files with 2837 additions and 260 deletions

View File

@@ -23,4 +23,4 @@ NEXT_PUBLIC_USE_MOCKS=true
# z.B. http://10.10.0.13/xyz/index.aspx -> basePath in config.json auf /xyz setzen
# basePath wird jetzt in public/config.json gepflegt
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.1.350
NEXT_PUBLIC_APP_VERSION=1.1.361

View File

@@ -24,4 +24,4 @@ NEXT_PUBLIC_USE_MOCKS=false
# basePath wird jetzt in public/config.json gepflegt
# App-Versionsnummer
NEXT_PUBLIC_APP_VERSION=1.1.350
NEXT_PUBLIC_APP_VERSION=1.1.361

View File

@@ -1,6 +1,3 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo "🔄 Version wird automatisch erhöht (bumpVersion.js)..."
# Version automatisch erhöhen

View File

@@ -6,7 +6,7 @@ import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
import "leaflet-contextmenu";
import "leaflet.smooth_marker_bouncing";
import "react-toastify/dist/ReactToastify.css";
import { InformationCircleIcon } from "@heroicons/react/20/solid";
import { Icon } from "@iconify/react";
import PoiUpdateModal from "@/components/pois/poiUpdateModal/PoiUpdateModal.js";
import { ToastContainer, toast } from "react-toastify";
import plusRoundIcon from "../icons/devices/overlapping/PlusRoundIcon.js";
@@ -24,6 +24,7 @@ import { useMapComponentState } from "@/components/hooks/useMapComponentState.js
import CoordinatePopup from "@/components/contextmenu/CoordinatePopup.js";
//----------Ui Widgets----------------
import MapLayersControlPanel from "@/components/uiWidgets/mapLayersControlPanel/MapLayersControlPanel.js";
import BaseMapPanel from "@/components/uiWidgets/baseMapPanel/BaseMapPanel.js";
import CoordinateInput from "@/components/uiWidgets/CoordinateInput.js";
import VersionInfoModal from "@/components/uiWidgets/VersionInfoModal.js";
//----------Daten aus API--------------------
@@ -39,6 +40,8 @@ import { setSelectedPoi } from "@/redux/slices/database/pois/selectedPoiSlice.js
import { setDisabled } from "@/redux/slices/database/polylines/polylineEventsDisabledSlice.js";
import { setMapId, setUserId } from "@/redux/slices/urlParameterSlice";
import { selectMapLayersState, setLayerVisibility } from "@/redux/slices/mapLayersSlice";
import { setSelectedArea } from "@/redux/slices/selectedAreaSlice";
import { incrementZoomTrigger } from "@/redux/slices/zoomTriggerSlice";
import { setCurrentPoi } from "@/redux/slices/database/pois/currentPoiSlice.js";
import { selectGisLines } from "@/redux/slices/database/polylines/gisLinesSlice";
import { selectGisLinesStatus } from "@/redux/slices/webservice/gisLinesStatusSlice";
@@ -151,6 +154,42 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
const [map, setMap] = useState(null); // Zustand der Karteninstanz
const [oms, setOms] = useState(null); // State für OMS-Instanz
// Sichtbarkeit der App-Info-Karte (unten links)
const [showAppInfoCard, setShowAppInfoCard] = useState(() => {
try {
const v = localStorage.getItem("showAppInfoCard");
return v === null ? true : v === "true";
} catch (_) {
return true;
}
});
// Sichtbarkeit des Layer-Kontrollpanels (oben rechts)
const [showLayersPanel, setShowLayersPanel] = useState(() => {
try {
const v = localStorage.getItem("showLayersPanel");
return v === null ? true : v === "true";
} catch (_) {
return true;
}
});
// Sichtbarkeit des Base-Map Panels (oben rechts, unter Toolbar)
const [showBaseMapPanel, setShowBaseMapPanel] = useState(() => {
try {
const v = localStorage.getItem("showBaseMapPanel");
return v === null ? false : v === "true";
} catch (_) {
return false;
}
});
// Sichtbarkeit der Koordinaten-Suche (Lupe)
const [showCoordinateInput, setShowCoordinateInput] = useState(() => {
try {
const v = localStorage.getItem("showCoordinateInput");
return v === null ? false : v === "true";
} catch (_) {
return false;
}
});
// Flag, ob Nutzer die Polyline-Checkbox manuell betätigt hat
// Nutzer-Flag global auf window, damit auch Redux darauf zugreifen kann
@@ -188,6 +227,14 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const [popupCoordinates, setPopupCoordinates] = useState(null);
const [popupVisible, setPopupVisible] = useState(false);
const [poiData, setPoiData] = useState([]);
// Edit mode state mirrors MapLayersControlPanel's behavior
const [editMode, setEditMode] = useState(() => {
try {
return localStorage.getItem("editMode") === "true";
} catch (_) {
return false;
}
});
const openVersionInfoModal = () => {
setShowVersionInfoModal(true);
@@ -209,6 +256,31 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}
});
// Persistiere Sichtbarkeit der App-Info-Karte
useEffect(() => {
try {
localStorage.setItem("showAppInfoCard", String(showAppInfoCard));
} catch (_) {}
}, [showAppInfoCard]);
// Persistiere Sichtbarkeit des Layer-Panels
useEffect(() => {
try {
localStorage.setItem("showLayersPanel", String(showLayersPanel));
} catch (_) {}
}, [showLayersPanel]);
// Persistiere Sichtbarkeit des Base-Map Panels
useEffect(() => {
try {
localStorage.setItem("showBaseMapPanel", String(showBaseMapPanel));
} catch (_) {}
}, [showBaseMapPanel]);
// Persistiere Sichtbarkeit der Koordinaten-Suche
useEffect(() => {
try {
localStorage.setItem("showCoordinateInput", String(showCoordinateInput));
} catch (_) {}
}, [showCoordinateInput]);
//--------------------------------------------
const handleCoordinatesSubmit = coords => {
@@ -981,6 +1053,29 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}, [GisSystemStatic, mapLayersVisibility, dispatch]);
//---------------------------------------------
//--------------------------------------------
// Expand handler (same behavior as MapLayersControlPanel expand icon)
const handleExpandClick = () => {
dispatch(setSelectedArea("Station wählen"));
dispatch(incrementZoomTrigger());
};
// Toggle edit mode (same logic as EditModeToggle component)
const hasEditRight = Array.isArray(userRights)
? userRights.includes?.(56) || userRights.some?.(r => r?.IdRight === 56)
: false;
const toggleEditMode = () => {
if (!hasEditRight) return;
const next = !editMode;
setEditMode(next);
try {
localStorage.setItem("editMode", String(next));
} catch (_) {}
if (typeof window !== "undefined") {
window.location.reload();
}
};
//--------------------------------------------
return (
<>
@@ -1035,17 +1130,117 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
)}
</div>
{GisStationsStaticDistrict && GisStationsStaticDistrict.Points?.length > 0 && (
{GisStationsStaticDistrict &&
GisStationsStaticDistrict.Points?.length > 0 &&
showLayersPanel && (
<MapLayersControlPanel
className="z-50"
handlePolylineCheckboxChange={handlePolylineCheckboxChange}
/>
)}
<CoordinateInput onCoordinatesSubmit={handleCoordinatesSubmit} />
{showCoordinateInput && <CoordinateInput onCoordinatesSubmit={handleCoordinatesSubmit} />}
<div id="map" ref={mapRef} className="z-0" style={{ height: "100vh", width: "100vw" }}></div>
{/* Top-right controls: layers, info, expand, edit, and base map stack */}
<div className="absolute top-3 right-3 z-50 pointer-events-auto flex items-center gap-2">
<button
onClick={toggleEditMode}
aria-label={editMode ? "Bearbeitungsmodus deaktivieren" : "Bearbeitungsmodus aktivieren"}
className={`rounded-full shadow p-1 ${
hasEditRight
? "bg-white/90 hover:bg-white"
: "bg-white/60 cursor-not-allowed opacity-50"
}`}
title={
hasEditRight
? editMode
? "Bearbeitungsmodus deaktivieren"
: "Bearbeitungsmodus aktivieren"
: "Keine Bearbeitungsrechte"
}
disabled={!hasEditRight}
>
<Icon
icon={editMode ? "material-symbols:edit-off-rounded" : "material-symbols:edit-rounded"}
className="h-8 w-8 text-blue-900"
/>
</button>
<button
onClick={handleExpandClick}
aria-label="Karte auf Standardansicht"
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title="Karte auf Standardansicht"
>
<img src="/img/expand-icon.svg" alt="Expand" className="h-8 w-8" />
</button>
<button
onClick={() => setShowBaseMapPanel(v => !v)}
aria-label={
showBaseMapPanel ? "Kartenhintergrund ausblenden" : "Kartenhintergrund wählen"
}
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title={showBaseMapPanel ? "Kartenhintergrund ausblenden" : "Kartenhintergrund wählen"}
>
<Icon icon="material-symbols:layers-rounded" className="h-8 w-8 text-blue-900" />
</button>
<button
onClick={() => setShowLayersPanel(v => !v)}
aria-label={showLayersPanel ? "Layer-Panel ausblenden" : "Layer-Panel einblenden"}
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title={showLayersPanel ? "Layer-Panel ausblenden" : "Layer-Panel einblenden"}
>
<Icon icon="material-symbols:menu-rounded" className="h-8 w-8 text-blue-900" />
</button>
{/* Lupe: Koordinaten-Suche ein-/ausblenden */}
<button
onClick={() => setShowCoordinateInput(v => !v)}
aria-label={
showCoordinateInput ? "Koordinatensuche ausblenden" : "Koordinatensuche einblenden"
}
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title={
showCoordinateInput ? "Koordinatensuche ausblenden" : "Koordinatensuche einblenden"
}
>
<Icon icon="material-symbols:search-rounded" className="h-8 w-8 text-blue-900" />
</button>
{/* Marker-Icon (line-md) */}
<button
onClick={() => {}}
aria-label="Marker"
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title="Marker"
>
<Icon icon="line-md:map-marker-filled" className="h-8 w-8 text-blue-900" />
</button>
{/* Alarm-Icon (mdi) */}
<button
onClick={() => {}}
aria-label="Alarm"
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title="Alarm"
>
<Icon icon="mdi:alarm-light-outline" className="h-8 w-8 text-blue-900" />
</button>
<button
onClick={() => setShowAppInfoCard(v => !v)}
aria-label={showAppInfoCard ? "Info ausblenden" : "Info einblenden"}
className="rounded-full bg-white/90 hover:bg-white shadow p-1"
title={showAppInfoCard ? "Info ausblenden" : "Info einblenden"}
>
<Icon
icon="material-symbols:info-rounded"
className="text-blue-900 h-8 w-8 pr-1"
title={showAppInfoCard ? "Info ausblenden" : "Info einblenden"}
/>
</button>
</div>
{showBaseMapPanel && map && (
<BaseMapPanel map={map} onClose={() => setShowBaseMapPanel(false)} />
)}
<CoordinatePopup isOpen={isPopupOpen} coordinates={currentCoordinates} onClose={closePopup} />
{showAppInfoCard && (
<div className="absolute bottom-3 left-3 w-72 p-4 bg-white rounded-lg shadow-md z-50">
<div className="flex justify-between items-center">
<div>
@@ -1055,11 +1250,16 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
</div>
<div>
<button onClick={openVersionInfoModal}>
<InformationCircleIcon className="text-blue-900 h-8 w-8 pr-1" title="Weitere Infos" />
<Icon
icon="material-symbols:info-rounded"
className="text-blue-900 h-8 w-8 pr-1"
title="Weitere Infos"
/>
</button>
</div>
</div>
</div>
)}
<VersionInfoModal
showVersionInfoModal={showVersionInfoModal}
closeVersionInfoModal={closeVersionInfoModal}

View File

@@ -0,0 +1,163 @@
// components/uiWidgets/baseMapPanel/BaseMapPanel.js
import React, { useEffect, useMemo, useRef, useState } from "react";
import L from "leaflet";
import { Icon } from "@iconify/react";
// Minimal, safe defaults (no API key required). You can extend via config later.
const DEFAULT_BASE_LAYERS = [
{
id: "osm-standard",
name: "Standard",
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
attribution: "&copy; OpenStreetMap contributors",
minZoom: 0,
maxZoom: 19,
},
{
id: "osm-humanitarian",
name: "Humanitarian",
url: "https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
attribution: "&copy; OpenStreetMap contributors, Humanitarian OpenStreetMap Team",
minZoom: 0,
maxZoom: 19,
},
{
id: "cyclosm",
name: "CyclOSM",
url: "https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png",
attribution: "&copy; OpenStreetMap contributors, CyclOSM",
minZoom: 0,
maxZoom: 20,
},
{
id: "carto-light",
name: "Carto Light",
url: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
attribution: "&copy; OpenStreetMap contributors, &copy; CARTO",
subdomains: "abcd",
minZoom: 0,
maxZoom: 20,
},
];
function getCurrentTileLayer(map) {
let found = null;
if (!map) return null;
map.eachLayer(layer => {
if (!found && layer instanceof L.TileLayer) {
found = layer;
}
});
return found;
}
export default function BaseMapPanel({ map, onSelect, onClose, initialId }) {
const [activeId, setActiveId] = useState(initialId || null);
const layerCacheRef = useRef({});
const bases = useMemo(() => {
try {
if (typeof window !== "undefined") {
const cfg = window.__leafletConfig;
if (cfg && cfg.tileSources) {
return Object.entries(cfg.tileSources).map(([key, ts]) => ({
id: key,
name: ts.name || key,
url: ts.url,
attribution: ts.attribution || "&copy; OpenStreetMap contributors",
minZoom: ts.minZoom ?? cfg.minZoom ?? 0,
maxZoom: ts.maxZoom ?? cfg.maxZoom ?? 19,
subdomains: ts.subdomains,
}));
}
}
} catch (_) {}
return DEFAULT_BASE_LAYERS;
}, []);
const applyBase = id => {
if (!map) return;
const base = bases.find(b => b.id === id) || bases[0];
if (!base) return;
// Remove current tile layer
const current = getCurrentTileLayer(map);
if (current) {
try {
map.removeLayer(current);
} catch (_) {}
}
// Get or create the new layer
let nextLayer = layerCacheRef.current[id];
if (!nextLayer) {
nextLayer = L.tileLayer(base.url, {
attribution: base.attribution,
subdomains: base.subdomains || "abc",
tileSize: 256,
minZoom: base.minZoom ?? 0,
maxZoom: base.maxZoom ?? 19,
noWrap: true,
// Ensure base tiles stay behind overlays
zIndex: 1,
});
layerCacheRef.current[id] = nextLayer;
}
nextLayer.addTo(map);
try {
if (typeof map.setMinZoom === "function") map.setMinZoom(base.minZoom ?? 0);
if (typeof map.setMaxZoom === "function") map.setMaxZoom(base.maxZoom ?? 19);
if (typeof window !== "undefined") {
window.__tileSourceMinZoom = base.minZoom ?? 0;
window.__tileSourceMaxZoom = base.maxZoom ?? 19;
}
} catch (_) {}
setActiveId(id);
try {
localStorage.setItem("baseMapId", id);
} catch (_) {}
onSelect && onSelect(id);
};
useEffect(() => {
const saved = (() => {
try {
return localStorage.getItem("baseMapId");
} catch (_) {
return null;
}
})();
const targetId = initialId || saved || bases[0]?.id;
if (targetId) {
applyBase(targetId);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [map]);
return (
<div className="absolute top-16 right-3 z-50 w-64 bg-white rounded-lg shadow-lg p-3">
<div className="flex items-center justify-between mb-2">
<h3 className="text-sm font-semibold">Map Layers</h3>
<button onClick={onClose} aria-label="Schließen" title="Schließen">
<Icon icon="material-symbols:close-rounded" className="h-5 w-5 text-gray-700" />
</button>
</div>
<div className="flex flex-col gap-2">
{bases.map(b => (
<button
key={b.id}
onClick={() => applyBase(b.id)}
className={`text-left rounded-md border p-2 hover:bg-gray-50 ${
activeId === b.id ? "ring-2 ring-blue-500" : ""
}`}
title={b.name}
>
<div className="font-medium text-sm">{b.name}</div>
<div className="text-[10px] text-gray-500 truncate">{b.url}</div>
</button>
))}
</div>
</div>
);
}

View File

@@ -275,6 +275,7 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
</option>
))}
</select>
{/*
<div className="flex items-center space-x-2">
<EditModeToggle />
<img
@@ -284,6 +285,7 @@ function MapLayersControlPanel({ handlePolylineCheckboxChange }) {
onClick={handleIconClick}
/>
</div>
*/}
</div>
{/* Checkboxen mit Untermenüs */}

View File

@@ -74,3 +74,32 @@ die Daten von DB auch mit WebSocket gelöst werden
28.07.2025 IdSystem 11 GMA Glätemeldeanlagen, werden neu neu laden das Browser nich mehr geladen in
DB maps idsystem ändern und testen
# 12.09.2025
Die aktuelle Ansicht ist bei kleineren Auflösungen unübersichtlich bzw. es wird zuviel von der
eigentlichen Karte verdeckt. Unquittierter Alarm, critical
Zu Marker zoomen
Station suchen
- [ ] TODO: Unquittierter Alarm, critical 🚨 Alarm
- [ ] TODO: Zu Marker zoomen: Dropdown-Menu Station auswählen und hinein zoomen bis zu ausgewählte
in einem betimmten Zoom-Stufe der Leaflet (OSM) Station mit flyto in Leaflet 📍 POI
- [ ] TODO: Station suchen: CoordinateInput.js Modal soll über einem Icon 'Suche / Lupe' oben rechts
eingeblendet und ausgeblendet um mehr von der Karte zu sehen 🔍 Suche
- [ ] TODO: Editiermodus: EditMode Stift Icon aktivieren und deaktivieren um POI Position ändern zu
können wenn der User Berechtigung hat ✏️ Edit
- [ ] TODO: Vergrössern: Maximieren Icon Button um rauszoomen zu einem bestimmten Bereich, z.B.
Deutschland Karte im Fenster sichtbar ⬜ Fenster maximieren
- [ ] TODO: Ebenen (Openstreetmap): Stack/Stapel/Ebenen Icon um den Ansicht der Karten zu ändern 🗂️
Stapel
- [ ] TODO: Menü öffenen mit Kiste der Systeme: MapLayerControlPanel.js Modal soll über einem Icon
'Hamburger menu' oben rechts eingeblendet und ausgeblendet um mehr von der Karte zu sehen ☰
Hamburger-Menü
- [ ] TODO: Info Karte: VersionInfoModal.js Modal soll über einem Icon 'Info' oben rechts
eingeblendet und ausgeblendet um mehr von der Karte zu sehen Info
https://www.openstreetmap.org/#map=13/51.80097/9.33495&layers=P

26
package-lock.json generated
View File

@@ -1,16 +1,17 @@
{
"name": "nodemap",
"version": "1.1.350",
"version": "1.1.361",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nodemap",
"version": "1.1.350",
"version": "1.1.361",
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@heroicons/react": "^2.1.5",
"@iconify/react": "^6.0.1",
"@mui/icons-material": "^6.0.2",
"@reduxjs/toolkit": "^2.5.1",
"autoprefixer": "^10.4.19",
@@ -357,6 +358,27 @@
"react": ">= 16 || ^19.0.0-rc"
}
},
"node_modules/@iconify/react": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@iconify/react/-/react-6.0.1.tgz",
"integrity": "sha512-fCocnAfiGXjrA0u7KkS3W/OQHNp9LRFICudvOtxmS3Mf7U92aDhP50wyzRbobZli51zYt9ksZ9g0J7H586XvOQ==",
"license": "MIT",
"dependencies": {
"@iconify/types": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/cyberalien"
},
"peerDependencies": {
"react": ">=16"
}
},
"node_modules/@iconify/types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
"integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
"license": "MIT"
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",

View File

@@ -1,10 +1,11 @@
{
"name": "nodemap",
"version": "1.1.350",
"version": "1.1.361",
"dependencies": {
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@heroicons/react": "^2.1.5",
"@iconify/react": "^6.0.1",
"@mui/icons-material": "^6.0.2",
"@reduxjs/toolkit": "^2.5.1",
"autoprefixer": "^10.4.19",

View File

@@ -0,0 +1,18 @@
// pages/api/testDbConnection.js
import getPool from "../../utils/mysqlPool";
export default async function handler(req, res) {
const pool = getPool();
let connection;
try {
connection = await pool.getConnection();
const [rows] = await connection.query("SELECT 1 AS test");
console.log("DB-Verbindung erfolgreich! Ergebnis:", rows);
res.status(200).json({ success: true, result: rows });
} catch (error) {
console.error("DB-Verbindungsfehler:", error);
res.status(500).json({ success: false, error: error.message });
} finally {
if (connection) connection.release();
}
}

View File

@@ -1,9 +1,7 @@
import mysql from "mysql2/promise";
// Variablen für den Singleton-Pool
let cachedPool;
let connectionCount = 0; // Zähler für die aktiven Verbindungen
let connectionCount = 0;
// Funktion zum Abrufen des Pools
function getPool() {
if (!cachedPool) {
cachedPool = mysql.createPool({
@@ -12,12 +10,11 @@ function getPool() {
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
port: process.env.DB_PORT,
connectionLimit: 20, // Setze ein Limit für gleichzeitige Verbindungen
connectionLimit: 20,
waitForConnections: true,
queueLimit: 10, // Warteschlangenlimit für Verbindungen
connectTimeout: 5000, // Timeout für Verbindungsversuche (5 Sekunden)
//acquireTimeout: 10000, // Timeout für Verbindungsanforderungen aus dem Pool (10 Sekunden)
idleTimeout: 60000, // 1 Minute
queueLimit: 10,
connectTimeout: 5000,
idleTimeout: 60000,
});
// Ereignisse für das Protokollieren der Verbindungsstatistiken
@@ -25,46 +22,27 @@ function getPool() {
cachedPool.on("acquire", () => {
connectionCount++;
if (process.env.NODE_ENV === "development") {
if (getDebugLog()) {
console.log("\x1b[36m%s\x1b[0m", ` Connection acquired (${connectionCount} total)`);
}
// Debug-Logging entfernt
if (connectionCount > maxUsed) {
maxUsed = connectionCount;
if (getDebugLog()) {
console.log(`📈 Neue Höchstzahl aktiver gleichzeitiger Verbindungen: ${maxUsed}`);
}
}
}
});
cachedPool.on("release", () => {
connectionCount--;
if (process.env.NODE_ENV === "development") {
if (getDebugLog()) {
console.log("\x1b[32m%s\x1b[0m", ` Connection released (${connectionCount} total)`);
}
}
});
cachedPool.on("enqueue", () => {
if (process.env.NODE_ENV === "development") {
if (getDebugLog()) {
console.warn("\x1b[33m%s\x1b[0m", "⏳ Pool voll Anfrage in Warteschlange");
}
}
// Debug-Logging entfernt
});
}
return cachedPool;
}
// Optionale Funktion zum Schließen aller Verbindungen im Pool (manuell aufzurufen)
export function closePool() {
if (cachedPool) {
cachedPool.end(() => {
console.log("All pool connections closed.");
});
cachedPool = null; // Setze den Pool auf null, um sicherzustellen, dass er neu erstellt wird, falls benötigt.
cachedPool = null;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,153 +1,85 @@
[
{
"LD_Name": "CPL Ismail4",
"IdLD": 50922,
"Device": "CPL V3.5 mit 24 Kü",
"Link": "cpl.aspx?ver=35&kue=24&id=50922",
"LD_Name": "CPL Kai Schmidt",
"IdLD": 50977,
"Device": "CPL V3.5 mit 24 Kü",
"Link": "cpl.aspx?ver=35&kue=24&id=50977",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Name": "Rastede 2",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"X": 53.245957,
"Y": 8.164172,
"Icon": 20,
"System": 1,
"Active": 1
},
{
"LD_Name": "LR 77 ISA",
"IdLD": 50935,
"Device": "LTE Modem LR77",
"Link": "lr77.aspx?ver=1&id=50935",
"LD_Name": "GMA-isa-test",
"IdLD": 50981,
"Device": "Glättemeldeanlage",
"Link": "gma.aspx?ver=1&id=50981",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Name": "Rastede 2",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Icon": 12,
"System": 5,
"Active": 1
},
{
"LD_Name": "Cisco Router 1841",
"IdLD": 50936,
"Device": "Cisco 1841",
"Link": "cisco1841.aspx?ver=1&id=50936",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Icon": 21,
"System": 6,
"Active": 1
},
{
"LD_Name": "GMA Testgerät ISA",
"IdLD": 50937,
"Device": "Glättemeldeanlage",
"Link": "gma.aspx?ver=1&id=50937",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"X": 53.245957,
"Y": 8.164172,
"Icon": 1,
"System": 11,
"Active": 1
},
{
"LD_Name": "SMS-Funkmodem",
"IdLD": 50938,
"Device": "SMS Funkmodem",
"Link": "sms_modem.aspx?ver=1&id=50938",
"LD_Name": "Cisco-isa",
"IdLD": 50982,
"Device": "Cisco 1841",
"Link": "cisco1841.aspx?ver=1&id=50982",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Name": "Rastede 2",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Icon": 12,
"System": 111,
"X": 53.245957,
"Y": 8.164172,
"Icon": 21,
"System": 6,
"Active": 1
},
{
"LD_Name": "TALAS Meldestationen ISA",
"IdLD": 50939,
"Device": "CPL V3.5 mit 16 Kü",
"Link": "cpl.aspx?ver=35&kue=16&id=50939",
"LD_Name": "CPL Ganz neu",
"IdLD": 50984,
"Device": "CPL V3.5 mit 24 Kü",
"Link": "cpl.aspx?ver=35&kue=24&id=50984",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Name": "Rastede 2",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"X": 53.245957,
"Y": 8.164172,
"Icon": 20,
"System": 1,
"Active": 1
},
{
"LD_Name": "WAGO Klemmen ISA",
"IdLD": 50941,
"Device": "WAGO 16 DE",
"Link": "wago.aspx?ver=1&DE=16&id=50941",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Icon": 9,
"System": 7,
"Active": 1
},
{
"LD_Name": "Cisco 1921",
"IdLD": 50942,
"Device": "Cisco 1921",
"Link": "cisco1921.aspx?ver=1&id=50942",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Area_Name": "Rastede",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Icon": 21,
"System": 6,
"Active": 1
},
{
"LD_Name": "Cisco 8200",
"IdLD": 50943,
"LD_Name": "Entwicklung KAS Cisco 8200 für LVZ 2025",
"IdLD": 50986,
"Device": "Cisco 8200",
"Link": "cisco8200.aspx?ver=1&id=50943",
"Location_Name": "Littwin",
"Location_Short": "LTW",
"IdLocation": 24101,
"Link": "cisco8200.aspx?ver=1&id=50986",
"Location_Name": "SW-Entwicklung 1.01",
"Location_Short": "SW101",
"IdLocation": 24102,
"Area_Name": "Rastede",
"Area_Short": "",
"IdArea": 20998,
"X": 53.242157,
"Y": 8.160353,
"Area_Short": "RAST-007",
"IdArea": 18192,
"X": 53.24615,
"Y": 8.16237,
"Icon": 21,
"System": 6,
"Active": 1

View File

@@ -4,25 +4,7 @@
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 01 kommend test2",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 05 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 17 kommend",
"Me": "Eingang DE 01 kommend",
"Feld": 4,
"Icon": 0
},
@@ -40,10 +22,127 @@
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 17 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 05 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 20 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 32 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 01 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Station offline",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 01 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Station offline",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50066,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "CPL offline",
"Feld": 5,
"Icon": 0
},
{
"IdLD": 50011,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "CPL offline",
"Feld": 16,
"Icon": 0
},
{
"IdLD": 50011,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Wasserdruck aus",
"Feld": 16,
"Icon": 0
},
{
"IdLD": 50011,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Ein",
"Feld": 16,
"Icon": 0
},
{
"IdLD": 50011,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Digitaleingang 1 ON",
"Feld": 16,
"Icon": 0
},
{
"IdLD": 50000,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Ein",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "system",
@@ -53,6 +152,51 @@
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "system",
"Le": 4,
"Co": "#FF00FF",
"Me": "Eingang DE 32 kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "minor",
"Le": 3,
"Co": "#FFFF00",
"Me": "KÜG 07: Überspannung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "minor",
"Le": 3,
"Co": "#FFFF00",
"Me": "KÜG 08: Überspannung gehend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "minor",
"Le": 3,
"Co": "#FFFF00",
"Me": "KÜG 08: Überspannung gehend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "minor",
"Le": 3,
"Co": "#FFFF00",
"Me": "KÜG 08: Überspannung gehend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "minor",
@@ -76,7 +220,16 @@
"Na": "major",
"Le": 2,
"Co": "#FF9900",
"Me": "Eingang DE 03 kommend",
"Me": "Eingang DE 03 Test Karte kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50922,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 01: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
@@ -97,5 +250,167 @@
"Me": "KÜG 03: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50000,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "über 8V kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 05: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 02: Isolationsminderung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50984,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 06: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 01: Isolationsminderung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 06: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50977,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 05: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50976,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "CPL offline",
"Feld": 3,
"Icon": 0
},
{
"IdLD": 50976,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 03: Isolationsminderung kommend",
"Feld": 3,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 04: Isolationsminderung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 02: Isolationsminderung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 01: Isolationsminderung kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50001,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "Sammelstörung kommend",
"Feld": 5,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 06: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50975,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "KÜG 05: Aderbruch kommend",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50963,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "CPL offline",
"Feld": 3,
"Icon": 0
},
{
"IdLD": 50063,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "Digitaleingang 1 EIN",
"Feld": 4,
"Icon": 0
},
{
"IdLD": 50000,
"Na": "critical",
"Le": 1,
"Co": "#FF0000",
"Me": "über 10V kommend",
"Feld": 4,
"Icon": 0
}
]

View File

@@ -4,111 +4,303 @@
"Name": "TALAS",
"Longname": "Talas Meldestationen",
"Allow": 1,
"Icon": 1
"Icon": 20,
"Map": 1
},
{
"IdSystem": 1,
"Name": "TALAS",
"Longname": "Talas Meldestationen",
"Allow": 0,
"Icon": 20,
"Map": 1
},
{
"IdSystem": 2,
"Name": "ECI",
"Longname": "ECI Geräte",
"Allow": 1,
"Icon": 2
"Allow": 0,
"Icon": 17,
"Map": 1
},
{
"IdSystem": 3,
"Name": "ULAF",
"Longname": "ULAF Geräte",
"Allow": 1,
"Icon": 3
"Icon": 14,
"Map": 1
},
{
"IdSystem": 3,
"Name": "ULAF",
"Longname": "ULAF Geräte",
"Allow": 0,
"Icon": 14,
"Map": 1
},
{
"IdSystem": 5,
"Name": "GSM Modem",
"Longname": "LR77 GSM Modems",
"Allow": 1,
"Icon": 5
"Icon": 12,
"Map": 1
},
{
"IdSystem": 5,
"Name": "GSM Modem",
"Longname": "LR77 GSM Modems",
"Allow": 0,
"Icon": 12,
"Map": 1
},
{
"IdSystem": 6,
"Name": "Cisco Router",
"Longname": "Cisco Router",
"Allow": 0,
"Icon": 21,
"Map": 1
},
{
"IdSystem": 6,
"Name": "Cisco Router",
"Longname": "Cisco Router",
"Allow": 1,
"Icon": 6
"Icon": 21,
"Map": 1
},
{
"IdSystem": 6,
"Name": "Cisco Router",
"Longname": "Cisco Router",
"Allow": 0,
"Icon": 21,
"Map": 1
},
{
"IdSystem": 7,
"Name": "WAGO",
"Longname": "WAGO I/O Systeme",
"Allow": 1,
"Icon": 9,
"Map": 1
},
{
"IdSystem": 7,
"Name": "WAGO",
"Longname": "WAGO I/O Systeme",
"Allow": 0,
"Icon": 7
"Icon": 9,
"Map": 1
},
{
"IdSystem": 7,
"Name": "WAGO",
"Longname": "WAGO I/O Systeme",
"Allow": 0,
"Icon": 9,
"Map": 1
},
{
"IdSystem": 7,
"Name": "WAGO",
"Longname": "WAGO I/O Systeme",
"Allow": 0,
"Icon": 9,
"Map": 1
},
{
"IdSystem": 8,
"Name": "Siemens",
"Longname": "Siemens Notrufsysteme",
"Allow": 1,
"Icon": 19,
"Map": 1
},
{
"IdSystem": 8,
"Name": "Siemens",
"Longname": "Siemens Notrufsysteme",
"Allow": 0,
"Icon": 8
"Icon": 19,
"Map": 1
},
{
"IdSystem": 9,
"Name": "OTDR",
"Longname": "Glasfaserüberwachung OTU",
"Allow": 1,
"Icon": 24,
"Map": 1
},
{
"IdSystem": 9,
"Name": "OTDR",
"Longname": "Glasfaserüberwachung OTU",
"Allow": 0,
"Icon": 9
"Icon": 24,
"Map": 1
},
{
"IdSystem": 9,
"Name": "OTDR",
"Longname": "Glasfaserüberwachung OTU",
"Allow": 0,
"Icon": 24,
"Map": 1
},
{
"IdSystem": 9,
"Name": "OTDR",
"Longname": "Glasfaserüberwachung OTU",
"Allow": 0,
"Icon": 24,
"Map": 1
},
{
"IdSystem": 10,
"Name": "WDM",
"Longname": " Wavelength Division Multiplexing",
"Allow": 1,
"Icon": 24,
"Map": 1
},
{
"IdSystem": 10,
"Name": "WDM",
"Longname": " Wavelength Division Multiplexing",
"Allow": 0,
"Icon": 10
"Icon": 24,
"Map": 1
},
{
"IdSystem": 10,
"Name": "WDM",
"Longname": " Wavelength Division Multiplexing",
"Allow": 0,
"Icon": 24,
"Map": 1
},
{
"IdSystem": 11,
"Name": "GMA",
"Longname": "Glättemeldeanlagen",
"Allow": 1,
"Icon": 11
"Icon": 1,
"Map": 1
},
{
"IdSystem": 11,
"Name": "GMA",
"Longname": "Glättemeldeanlagen",
"Allow": 0,
"Icon": 1,
"Map": 1
},
{
"IdSystem": 11,
"Name": "GMA",
"Longname": "Glättemeldeanlagen",
"Allow": 0,
"Icon": 1,
"Map": 1
},
{
"IdSystem": 13,
"Name": "Messstellen",
"Longname": "Messstellen",
"Allow": 0,
"Icon": 13
"Icon": 23,
"Map": 1
},
{
"IdSystem": 30,
"Name": "TK-Komponenten",
"Longname": "TK-Komponenten",
"Allow": 1,
"Icon": 14,
"Map": 1
},
{
"IdSystem": 30,
"Name": "TK-Komponenten",
"Longname": "TK-Komponenten",
"Allow": 0,
"Icon": 30
"Icon": 14,
"Map": 1
},
{
"IdSystem": 100,
"Name": "TALAS ICL",
"Longname": "Talas ICL Unterstationen",
"Allow": 1,
"Icon": 23,
"Map": 1
},
{
"IdSystem": 100,
"Name": "TALAS ICL",
"Longname": "Talas ICL Unterstationen",
"Allow": 0,
"Icon": 100
"Icon": 23,
"Map": 1
},
{
"IdSystem": 110,
"Name": "DAUZ",
"Longname": "Dauerzählstellen",
"Allow": 0,
"Icon": 110
"Icon": 14,
"Map": 1
},
{
"IdSystem": 110,
"Name": "DAUZ",
"Longname": "Dauerzählstellen",
"Allow": 1,
"Icon": 14,
"Map": 1
},
{
"IdSystem": 110,
"Name": "DAUZ",
"Longname": "Dauerzählstellen",
"Allow": 0,
"Icon": 14,
"Map": 1
},
{
"IdSystem": 111,
"Name": "SMS Modem",
"Longname": "SMS Modem",
"Allow": 1,
"Icon": 12,
"Map": 1
},
{
"IdSystem": 111,
"Name": "SMS Modem",
"Longname": "SMS Modem",
"Allow": 0,
"Icon": 111
"Icon": 12,
"Map": 1
},
{
"IdSystem": 200,
"Name": "Sonstige",
"Longname": "Sonstige",
"Allow": 1,
"Icon": 31,
"Map": 1
},
{
"IdSystem": 200,
"Name": "Sonstige",
"Longname": "Sonstige",
"Allow": 0,
"Icon": 200
"Icon": 31,
"Map": 1
}
]