Merge pull request 'feature/start-end-line-marker' (#1) from feature/start-end-line-marker into develop
Reviewed-on: http://10.10.0.12:3000/ISA/nodeMap/pulls/1
This commit is contained in:
3
.babelrc
Normal file
3
.babelrc
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"presets": ["@babel/preset-env", "@babel/preset-react"]
|
||||||
|
}
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,3 +26,4 @@ trace
|
|||||||
|
|
||||||
# Ignore specific Next.js build files
|
# Ignore specific Next.js build files
|
||||||
pages-manifest.json
|
pages-manifest.json
|
||||||
|
nodeMap für 13 am 16.07.2024.zip
|
||||||
|
|||||||
32
Jenkinsfile
vendored
Normal file
32
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
pipeline {
|
||||||
|
agent any
|
||||||
|
|
||||||
|
stages {
|
||||||
|
stage('Install Dependencies') {
|
||||||
|
steps {
|
||||||
|
// Installiere npm Abhängigkeiten
|
||||||
|
sh 'npm install'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stage('Run Tests') {
|
||||||
|
steps {
|
||||||
|
// Führt Ihre Tests aus
|
||||||
|
sh 'npm test'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
// Archivieren Sie die Testberichte, wenn verfügbar
|
||||||
|
junit '**/test-results.xml'
|
||||||
|
}
|
||||||
|
success {
|
||||||
|
echo 'Die Tests wurden erfolgreich abgeschlossen!'
|
||||||
|
}
|
||||||
|
failure {
|
||||||
|
echo 'Einige Tests sind fehlgeschlagen.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
__mocks__/leaflet.js
Normal file
12
__mocks__/leaflet.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
module.exports = {
|
||||||
|
map: () => ({
|
||||||
|
setView: jest.fn(),
|
||||||
|
addLayer: jest.fn(),
|
||||||
|
}),
|
||||||
|
tileLayer: () => ({
|
||||||
|
addTo: jest.fn(),
|
||||||
|
}),
|
||||||
|
marker: () => ({
|
||||||
|
addTo: jest.fn(),
|
||||||
|
}),
|
||||||
|
};
|
||||||
89
__tests__/MapComponent.test.js
Normal file
89
__tests__/MapComponent.test.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// __tests__/MapComponent.test.js
|
||||||
|
|
||||||
|
// Ein einfacher Testfall, der sicherstellt, dass die Addition korrekt ist
|
||||||
|
test("simple addition", () => {
|
||||||
|
const a = 1;
|
||||||
|
const b = 2;
|
||||||
|
const c = a + b;
|
||||||
|
expect(c).toBe(3); // Überprüft, ob c gleich 3 ist
|
||||||
|
});
|
||||||
|
|
||||||
|
//import L from "leaflet";
|
||||||
|
//import { checkOverlappingMarkers } from "../utils/mapUtils"; // Passe den Pfad entsprechend an
|
||||||
|
|
||||||
|
/* describe("checkOverlappingMarkers", () => {
|
||||||
|
let map;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// Erstelle eine neue Leaflet-Karte für jeden Test
|
||||||
|
map = L.map(document.createElement("div"));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should group markers by coordinates and add plus icons for overlapping markers", () => {
|
||||||
|
// Erstelle einige Beispielmarker
|
||||||
|
const markers = [
|
||||||
|
L.marker([51.505, -0.09]),
|
||||||
|
L.marker([51.505, -0.09]),
|
||||||
|
L.marker([51.51, -0.1]),
|
||||||
|
];
|
||||||
|
|
||||||
|
const plusIcon = L.divIcon({ className: "plus-icon" });
|
||||||
|
|
||||||
|
// Rufe die Funktion auf
|
||||||
|
checkOverlappingMarkers(map, markers, plusIcon);
|
||||||
|
|
||||||
|
// Überprüfe, dass die Marker zu Gruppen hinzugefügt wurden
|
||||||
|
const overlappingGroups = map._layers;
|
||||||
|
expect(Object.keys(overlappingGroups).length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Überprüfe, dass die Plus-Marker hinzugefügt wurden
|
||||||
|
const plusMarkers = Object.values(overlappingGroups).filter(
|
||||||
|
(layer) =>
|
||||||
|
layer.options.icon &&
|
||||||
|
layer.options.icon.options.className === "plus-icon"
|
||||||
|
);
|
||||||
|
expect(plusMarkers.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should handle non-array markers argument gracefully", () => {
|
||||||
|
const plusIcon = L.divIcon({ className: "plus-icon" });
|
||||||
|
|
||||||
|
// Rufe die Funktion mit einem ungültigen Argument auf
|
||||||
|
checkOverlappingMarkers(map, null, plusIcon);
|
||||||
|
|
||||||
|
// Stelle sicher, dass keine Marker hinzugefügt wurden
|
||||||
|
const layers = map._layers;
|
||||||
|
expect(Object.keys(layers).length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not add plus markers if there are no overlaps", () => {
|
||||||
|
// Erstelle einige Beispielmarker
|
||||||
|
const markers = [
|
||||||
|
L.marker([51.505, -0.09]),
|
||||||
|
L.marker([51.51, -0.1]),
|
||||||
|
L.marker([51.52, -0.12]),
|
||||||
|
];
|
||||||
|
|
||||||
|
const plusIcon = L.divIcon({ className: "plus-icon" });
|
||||||
|
|
||||||
|
// Rufe die Funktion auf
|
||||||
|
checkOverlappingMarkers(map, markers, plusIcon);
|
||||||
|
|
||||||
|
// Überprüfe, dass keine Plus-Marker hinzugefügt wurden
|
||||||
|
const plusMarkers = Object.values(map._layers).filter(
|
||||||
|
(layer) =>
|
||||||
|
layer.options.icon &&
|
||||||
|
layer.options.icon.options.className === "plus-icon"
|
||||||
|
);
|
||||||
|
expect(plusMarkers.length).toBe(0);
|
||||||
|
});
|
||||||
|
}); */
|
||||||
|
/*
|
||||||
|
In diesem Test:
|
||||||
|
|
||||||
|
Wird eine neue Leaflet-Karte vor jedem Test erstellt.
|
||||||
|
checkOverlappingMarkers wird aufgerufen, um zu überprüfen, ob die Funktion die Marker richtig gruppiert und Plus-Icons für überlappende Marker hinzufügt.
|
||||||
|
Der Test überprüft auch, ob die Funktion ungültige Argumente (wie null für Marker) korrekt behandelt.
|
||||||
|
Es wird sichergestellt, dass keine Plus-Marker hinzugefügt werden, wenn keine Überlappungen vorliegen.
|
||||||
|
Stelle sicher, dass du die Pfade und Importe entsprechend deiner Projektstruktur anpasst.
|
||||||
|
*/
|
||||||
3
babel.config.js
Normal file
3
babel.config.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: ["@babel/preset-env", "@babel/preset-react"],
|
||||||
|
};
|
||||||
13
components/CircleIcon.js
Normal file
13
components/CircleIcon.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// /components/CircleIcon.js
|
||||||
|
// Custom circle icon for draggable markers
|
||||||
|
import L from "leaflet";
|
||||||
|
import "leaflet/dist/leaflet.css";
|
||||||
|
|
||||||
|
const circleIcon = L.divIcon({
|
||||||
|
className: "custom-div-icon",
|
||||||
|
html: "<div style='background-color:gray;border-radius:50%;width:10px;height:10px;border: solid black 1px;'></div>",
|
||||||
|
iconSize: [25, 25],
|
||||||
|
iconAnchor: [5, 5],
|
||||||
|
});
|
||||||
|
|
||||||
|
export default circleIcon;
|
||||||
10
components/EndIcon.js
Normal file
10
components/EndIcon.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Custom circle icon for draggable markers
|
||||||
|
import L from "leaflet";
|
||||||
|
const endIcon = L.divIcon({
|
||||||
|
className: "custom-end-icon",
|
||||||
|
html: "<div style='background-color: gray; width: 14px; height: 14px; border: solid black 2px;'></div>", // Graues Viereck
|
||||||
|
iconSize: [14, 14],
|
||||||
|
iconAnchor: [7, 7], // Mittelpunkt des Vierecks als Anker
|
||||||
|
});
|
||||||
|
|
||||||
|
export default endIcon;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
// pages/api/poiUpdateModal.js
|
// pages/api/poiUpdateModal.js
|
||||||
//
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useRecoilValue } from "recoil";
|
import { useRecoilValue } from "recoil";
|
||||||
import { selectedPoiState } from "../store/atoms/poiState";
|
import { selectedPoiState } from "../store/atoms/poiState";
|
||||||
@@ -15,52 +15,24 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
const [locationDeviceData, setLocationDeviceData] = useState([]);
|
const [locationDeviceData, setLocationDeviceData] = useState([]);
|
||||||
const [deviceName, setDeviceName] = useState("");
|
const [deviceName, setDeviceName] = useState("");
|
||||||
const [idLD, setIdLD] = useState(poiData ? poiData.idLD : "");
|
const [idLD, setIdLD] = useState(poiData ? poiData.idLD : "");
|
||||||
const [idLocationDevice, setIdLocationDevice] = useState("");
|
|
||||||
|
|
||||||
const [description, setDescription] = useState(
|
const [description, setDescription] = useState(
|
||||||
poiData ? poiData.description : ""
|
poiData ? poiData.description : ""
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log the initial POI data
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (poiData) {
|
if (poiData) {
|
||||||
|
console.log("Initial poiData:", poiData);
|
||||||
setPoiId(poiData.idPoi);
|
setPoiId(poiData.idPoi);
|
||||||
setName(poiData.name);
|
setName(poiData.name);
|
||||||
setPoiTypeId(poiData.idPoiTyp);
|
setPoiTypeId(poiData.idPoiTyp);
|
||||||
setIdLD(poiData.idLD);
|
setIdLD(poiData.idLD);
|
||||||
|
|
||||||
setDescription(poiData.description);
|
setDescription(poiData.description);
|
||||||
setDeviceName(poiData.idLD);
|
setDeviceName(poiData.idLD);
|
||||||
console.log("Loaded POI Data for editing:", poiData);
|
console.log("Loaded POI Data for editing:", poiData);
|
||||||
console.log("POI ID:", poiData.idPoi);
|
|
||||||
console.log("POI Name:", poiData.name);
|
|
||||||
console.log("POI Typ ID:", poiData.idPoiTyp);
|
|
||||||
console.log("POI Beschreibung:", poiData.description);
|
|
||||||
console.log("POI Geräte-ID:", poiData.idLD);
|
|
||||||
}
|
}
|
||||||
}, [poiData]);
|
}, [poiData]);
|
||||||
|
|
||||||
/* const fetchDeviceNameById = async (idLD) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/getDeviceNameById?idLD=${idLD}`);
|
|
||||||
const data = await response.json();
|
|
||||||
setDeviceName(data.deviceName);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching device name:", error);
|
|
||||||
}
|
|
||||||
}; */
|
|
||||||
|
|
||||||
/* const fetchDeviceNameById = async (idLD) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/api/talas_v5_DB/locationDevice/locationDeviceNameById?idLD=${idLD}`);
|
|
||||||
const data = await response.json();
|
|
||||||
setDeviceName(data.deviceName);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching device name:", error);
|
|
||||||
}
|
|
||||||
}; */
|
|
||||||
|
|
||||||
// Beim Öffnen des Modals die Geräte-ID basierend auf dem Gerätenamen abrufen, wenn vorhanden
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchDeviceId = async () => {
|
const fetchDeviceId = async () => {
|
||||||
if (poiData && poiData.idLD) {
|
if (poiData && poiData.idLD) {
|
||||||
@@ -82,7 +54,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
fetchDeviceId();
|
fetchDeviceId();
|
||||||
}, [poiData]);
|
}, [poiData]);
|
||||||
|
|
||||||
// Function to handle deleting a POI
|
|
||||||
const handleDeletePoi = async () => {
|
const handleDeletePoi = async () => {
|
||||||
if (confirm("Sind Sie sicher, dass Sie diesen POI löschen möchten?")) {
|
if (confirm("Sind Sie sicher, dass Sie diesen POI löschen möchten?")) {
|
||||||
try {
|
try {
|
||||||
@@ -94,8 +65,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
);
|
);
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
alert("POI wurde erfolgreich gelöscht.");
|
alert("POI wurde erfolgreich gelöscht.");
|
||||||
onClose(); // Close the modal
|
onClose();
|
||||||
//Browser neu laden, um die aktualisierte Liste anzuzeigen
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Fehler beim Löschen des POI.");
|
throw new Error("Fehler beim Löschen des POI.");
|
||||||
@@ -107,7 +77,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fetch POI types
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchPoiTypData = async () => {
|
const fetchPoiTypData = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -127,22 +96,20 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
fetchPoiTypData();
|
fetchPoiTypData();
|
||||||
}, [selectedPoi]);
|
}, [selectedPoi]);
|
||||||
|
|
||||||
// Fetch device data um den Gerät Namen in den dropdown menu anzuzeigen also erstmal die Liste der Geräte abrufen
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/talas_v5/location_device");
|
// const response = await fetch("/api/talas_v5/location_device"); //"/api/talas_v5_DB/locationDevice/location_device"
|
||||||
|
const response = await fetch(
|
||||||
|
"/api/talas_v5_DB/locationDevice/locationDevices"
|
||||||
|
);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
//console.log("Standort- und Gerätedaten:", data);
|
|
||||||
setLocationDeviceData(data);
|
setLocationDeviceData(data);
|
||||||
console.log("Standort- und Gerätedaten poiData:", poiData);
|
|
||||||
if (poiData && poiData.idLD) {
|
if (poiData && poiData.idLD) {
|
||||||
const selectedDevice = data.find(
|
const selectedDevice = data.find(
|
||||||
(device) => device.id === poiData.idLD
|
(device) => device.id === poiData.idLD
|
||||||
);
|
);
|
||||||
setDeviceName(selectedDevice ? selectedDevice.id : data[0].id); // Hier wird die ID als initialer Zustand gesetzt
|
setDeviceName(selectedDevice ? selectedDevice.id : data[0].id);
|
||||||
console.log("Selected Device:", selectedDevice);
|
|
||||||
console.log("Selected devciceName:", deviceName);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(
|
console.error(
|
||||||
@@ -153,18 +120,12 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
};
|
};
|
||||||
fetchData();
|
fetchData();
|
||||||
}, []);
|
}, []);
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
// Fetch device name basierend auf der Geräte-ID
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("currentPoi von PoiUpdateModal.js : ", currentPoi.idLD);
|
|
||||||
fetch("/api/talas_v5_DB/locationDevice/locationDevices")
|
fetch("/api/talas_v5_DB/locationDevice/locationDevices")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setLocationDeviceData(data);
|
setLocationDeviceData(data);
|
||||||
console.log("Standort- und Gerätedaten 3:", data);
|
|
||||||
console.log("Standort- und Gerätedaten 3 poiData:", poiData);
|
|
||||||
// Findet das Gerät, das der aktuellen IDLD entspricht
|
|
||||||
const currentDevice = data.find(
|
const currentDevice = data.find(
|
||||||
(device) => device.idLD === currentPoi.idLD
|
(device) => device.idLD === currentPoi.idLD
|
||||||
);
|
);
|
||||||
@@ -178,10 +139,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
});
|
});
|
||||||
}, [poiData?.idLD, currentPoi]);
|
}, [poiData?.idLD, currentPoi]);
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
// Angenommen, deviceName enthält die Geräte-ID
|
|
||||||
//const idLD = deviceName; // Stellen Sie sicher, dass dies eine ID ist und kein Name
|
|
||||||
|
|
||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const idLDResponse = await fetch(
|
const idLDResponse = await fetch(
|
||||||
@@ -201,7 +158,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
description: description,
|
description: description,
|
||||||
idPoiTyp: poiTypeId,
|
idPoiTyp: poiTypeId,
|
||||||
idLD: idLD,
|
idLD: idLD,
|
||||||
//idLD: parseInt(deviceName, 10), // Konvertieren in eine Ganzzahl
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -220,19 +176,6 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//ausgewählte poi Informationen in Console anzeigen
|
|
||||||
console.log("Selected POI:", selectedPoi);
|
|
||||||
console.log("Selected POI Gerät id in poiUpdateModal.js:", selectedPoi.id);
|
|
||||||
console.log("Selected POI Typ name in poiUpdateModal.js:", selectedPoi.typ); //als Typ in dropdown menu
|
|
||||||
console.log(
|
|
||||||
"Selected POI Beschreibung in poiUpdateModal.js:",
|
|
||||||
selectedPoi.description
|
|
||||||
);
|
|
||||||
console.log(
|
|
||||||
"Selected POI Gerät deviceId in poiUpdateModal.js:",
|
|
||||||
selectedPoi.deviceId
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit} className="m-0 p-2 w-full">
|
<form onSubmit={handleSubmit} className="m-0 p-2 w-full">
|
||||||
<div className="flex items-center mb-4">
|
<div className="flex items-center mb-4">
|
||||||
@@ -261,16 +204,11 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
onChange={(e) => setDeviceName(e.target.value)}
|
onChange={(e) => setDeviceName(e.target.value)}
|
||||||
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm"
|
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm"
|
||||||
>
|
>
|
||||||
{locationDeviceData.map(
|
{locationDeviceData.map((device, index) => (
|
||||||
(device, index) => (
|
<option key={index} value={device.id}>
|
||||||
console.log("device.id und name:", device),
|
{device.name}
|
||||||
(
|
</option>
|
||||||
<option key={index} value={device.id}>
|
))}
|
||||||
{device.name}
|
|
||||||
</option>
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -294,7 +232,7 @@ const PoiUpdateModal = ({ onClose, poiData }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button" // Use button type to prevent form submission
|
type="button"
|
||||||
onClick={handleDeletePoi}
|
onClick={handleDeletePoi}
|
||||||
className="bg-red-400 hover:bg-red-600 text-white font-bold py-2 px-4 rounded w-full mb-4"
|
className="bg-red-400 hover:bg-red-600 text-white font-bold py-2 px-4 rounded w-full mb-4"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -109,6 +109,9 @@ const ShowAddStationPopup = ({ onClose, map, latlng }) => {
|
|||||||
onClose();
|
onClose();
|
||||||
return newTrigger;
|
return newTrigger;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Browser aktualisieren
|
||||||
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
console.error("Fehler beim Hinzufügen des POI");
|
console.error("Fehler beim Hinzufügen des POI");
|
||||||
}
|
}
|
||||||
@@ -117,6 +120,7 @@ const ShowAddStationPopup = ({ onClose, map, latlng }) => {
|
|||||||
map.closePopup();
|
map.closePopup();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------handleSubmit-------------------
|
//-----------------handleSubmit-------------------
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
16
components/StartIcon.js
Normal file
16
components/StartIcon.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Custom triangle icon for draggable markers
|
||||||
|
import L from "leaflet";
|
||||||
|
|
||||||
|
const startIcon = L.divIcon({
|
||||||
|
className: "custom-start-icon",
|
||||||
|
html: `
|
||||||
|
<svg width="18" height="18" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<polygon points="10,2 18,18 2,18" fill="black" />
|
||||||
|
<polygon points="10,5 16,16 4,16" fill="gray" />
|
||||||
|
</svg>
|
||||||
|
`, // Schwarzes Dreieck innerhalb eines grauen Dreiecks
|
||||||
|
iconSize: [18, 18],
|
||||||
|
iconAnchor: [9, 18],
|
||||||
|
});
|
||||||
|
|
||||||
|
export default startIcon;
|
||||||
22
components/useMapContextMenu.js
Normal file
22
components/useMapContextMenu.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { useState, useCallback } from "react";
|
||||||
|
|
||||||
|
const useMapContextMenu = (map, hasRights, addStationCallback) => {
|
||||||
|
const [menuItemAdded, setMenuItemAdded] = useState(false);
|
||||||
|
|
||||||
|
const addItemsToMapContextMenu = useCallback(() => {
|
||||||
|
if (map && !menuItemAdded) {
|
||||||
|
map.contextmenu.addItem({
|
||||||
|
text: "POI hinzufügen",
|
||||||
|
icon: "img/add_station.png",
|
||||||
|
className: "background-red",
|
||||||
|
callback: (event) => addStationCallback(event, hasRights),
|
||||||
|
});
|
||||||
|
|
||||||
|
setMenuItemAdded(true); // Menüpunkt wurde hinzugefült, Zustand aktualisieren
|
||||||
|
}
|
||||||
|
}, [map, menuItemAdded, hasRights, addStationCallback]);
|
||||||
|
|
||||||
|
return { addItemsToMapContextMenu };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useMapContextMenu;
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte
|
// /config/config.js
|
||||||
|
|
||||||
|
// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte
|
||||||
const mapVersion = "0.5.3"; // Die Version der verwendeten Karte
|
const mapVersion = "0.5.3"; // Die Version der verwendeten Karte
|
||||||
const standardSideMenu = true; // Einstellung, ob ein standardmäßiges Seitenmenü verwendet wird
|
const standardSideMenu = true; // Einstellung, ob ein standardmäßiges Seitenmenü verwendet wird
|
||||||
const fullSideMenu = false; // Einstellung, ob ein vollständiges Seitenmenü verwendet wird
|
const fullSideMenu = false; // Einstellung, ob ein vollständiges Seitenmenü verwendet wird
|
||||||
const serverURL = "/api"; // Die Basis-URL des Servers, von dem Daten bezogen werden
|
//const serverURL = "/api"; // Die Basis-URL des Servers, von dem Daten bezogen werden
|
||||||
|
const serverURL = "http://10.10.0.13";
|
||||||
|
console.log("serverURL in config:", serverURL);
|
||||||
// Initialisieren von Variablen, die später im Browserkontext gesetzt werden
|
// Initialisieren von Variablen, die später im Browserkontext gesetzt werden
|
||||||
let windowHeight, url_string, url, c, user;
|
let windowHeight, url_string, url, idMap, idUser;
|
||||||
//Online Daten
|
//Online Daten
|
||||||
let mapGisStationsStaticDistrictUrl,
|
let mapGisStationsStaticDistrictUrl,
|
||||||
mapGisStationsStatusDistrictUrl,
|
mapGisStationsStatusDistrictUrl,
|
||||||
@@ -20,28 +23,30 @@ if (typeof window !== "undefined") {
|
|||||||
windowHeight = window.innerHeight; // Die Höhe des Browserfensters
|
windowHeight = window.innerHeight; // Die Höhe des Browserfensters
|
||||||
url_string = window.location.href; // Die vollständige URL als String
|
url_string = window.location.href; // Die vollständige URL als String
|
||||||
url = new URL(url_string); // Die URL als URL-Objekt, um Teile der URL einfacher zu handhaben
|
url = new URL(url_string); // Die URL als URL-Objekt, um Teile der URL einfacher zu handhaben
|
||||||
c = url.searchParams.get("m"); // Ein Parameter aus der URL, Standardwert ist '10'
|
console.log("URL in config:", url);
|
||||||
user = url.searchParams.get("u"); // Ein weiterer Parameter aus der URL, Standardwert ist '484 admin zu testen von Stationen ausblenden und einblenden in der Card'
|
console.log("URL origin in config:", url.origin); //http://localhost:3000
|
||||||
|
idMap = url.searchParams.get("m"); // Ein Parameter aus der URL, Standardwert ist '10'
|
||||||
|
idUser = url.searchParams.get("u"); // Ein weiterer Parameter aus der URL, Standardwert ist '484 admin zu testen von Stationen ausblenden und einblenden in der Card'
|
||||||
|
|
||||||
console.log(`Parameter 'idMap' : ${c}`);
|
console.log(`Parameter 'idMap' : ${idMap}`);
|
||||||
console.log(`Parameter 'idUser': ${user}`);
|
console.log(`Parameter 'idUser': ${idUser}`);
|
||||||
|
|
||||||
console.log(`Parameter 'idMap' : ${c}`);
|
|
||||||
console.log(`Parameter 'idUser': ${user}`);
|
|
||||||
|
|
||||||
// Konstruktion von URLs, die auf spezifische Ressourcen auf dem Server zeigen
|
// Konstruktion von URLs, die auf spezifische Ressourcen auf dem Server zeigen
|
||||||
//http://localhost:3000/?m=10&u=485
|
//http://localhost:3000/?m=10&u=485
|
||||||
|
|
||||||
//-----------------Von WebService------------------------------------------------
|
//-----------------Von WebService------------------------------------------------
|
||||||
mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict?idMap=${c}&idUser=${user}`; //idMap: 10, idUser: 484
|
mapGisStationsStaticDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict?idMap=${idMap}&idUser=${idUser}`; //idMap: 10, idUser: 484
|
||||||
mapGisStationsStatusDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStatusDistrict?idMap=${c}&idUser=${user}`;
|
mapGisStationsStatusDistrictUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStatusDistrict?idMap=${idMap}&idUser=${idUser}`;
|
||||||
mapGisStationsMeasurementsUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsMeasurements?idMap=${c}`;
|
mapGisStationsMeasurementsUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisStationsMeasurements?idMap=${idMap}`;
|
||||||
mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${c}&idUser=${user}`;
|
mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${idMap}&idUser=${idUser}`;
|
||||||
mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`;
|
mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`;
|
||||||
|
|
||||||
//webserviceGisLinesStatusUrl = `http://10.10.0.13/talas5/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=${c}`;
|
//webserviceGisLinesStatusUrl = `http://10.10.0.13/talas5/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=${idMap}`;
|
||||||
|
//webserviceGisLinesStatusUrl = `http://localhost:3000/api/linesColorApi`;
|
||||||
|
//webserviceGisLinesStatusUrl = `http://localhost:3000/api/linesColorApi`;
|
||||||
|
//webserviceGisLinesStatusUrl = `${"serverURL"}:3000/api/linesColorApi`;
|
||||||
webserviceGisLinesStatusUrl = `http://localhost:3000/api/linesColorApi`;
|
webserviceGisLinesStatusUrl = `http://localhost:3000/api/linesColorApi`;
|
||||||
//webserviceGisLinesStatusUrl = `http://192.168.10.14/talas5/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=${c}`;
|
//webserviceGisLinesStatusUrl = `http://192.168.10.14/talas5/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=${idMap}`;
|
||||||
|
|
||||||
//http://10.10.0.13/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=12&idUser=484
|
//http://10.10.0.13/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=12&idUser=484
|
||||||
|
|
||||||
@@ -51,11 +56,11 @@ if (typeof window !== "undefined") {
|
|||||||
mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic`;
|
mapGisSystemStaticUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic`;
|
||||||
mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; */
|
mapDataIconUrl = `${serverURL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`; */
|
||||||
|
|
||||||
/* mapGisStationsStaticDistrictUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsStaticDistrict?idMap=${c}&idUser=${user}`;
|
/* mapGisStationsStaticDistrictUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsStaticDistrict?idMap=${idMap}&idUser=${idUser}`;
|
||||||
mapGisStationsStatusDistrictUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsStatusDistrict?idMap=${c}&idUser=${user}`;
|
mapGisStationsStatusDistrictUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsStatusDistrict?idMap=${idMap}&idUser=${idUser}`;
|
||||||
mapGisStationsMeasurementsUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsMeasurements?idMap=${c}`;
|
mapGisStationsMeasurementsUrl = `${serverURL}/api/talas5/webserviceMap/GisStationsMeasurements?idMap=${idMap}`;
|
||||||
mapGisStationsMeasurementsUrl = `${serverURL}/api/talas5/webserviceMap/gisStationsMeasurementsSQL?idMap=${c}`;
|
mapGisStationsMeasurementsUrl = `${serverURL}/api/talas5/webserviceMap/gisStationsMeasurementsSQL?idMap=${idMap}`;
|
||||||
mapGisSystemStaticUrl = `${serverURL}/api/talas5/webserviceMap/GisSystemStatic?idMap=${c}&idUser=${user}`;
|
mapGisSystemStaticUrl = `${serverURL}/api/talas5/webserviceMap/GisSystemStatic?idMap=${idMap}&idUser=${idUser}`;
|
||||||
mapDataIconUrl = `${serverURL}/api/talas5/webserviceMap/GetIconsStatic`; */
|
mapDataIconUrl = `${serverURL}/api/talas5/webserviceMap/GetIconsStatic`; */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,8 +73,8 @@ export {
|
|||||||
windowHeight,
|
windowHeight,
|
||||||
url_string,
|
url_string,
|
||||||
url,
|
url,
|
||||||
c,
|
idMap,
|
||||||
user,
|
idUser,
|
||||||
mapGisStationsStaticDistrictUrl,
|
mapGisStationsStaticDistrictUrl,
|
||||||
mapGisStationsStatusDistrictUrl,
|
mapGisStationsStatusDistrictUrl,
|
||||||
mapGisStationsMeasurementsUrl,
|
mapGisStationsMeasurementsUrl,
|
||||||
@@ -77,3 +82,9 @@ export {
|
|||||||
mapDataIconUrl,
|
mapDataIconUrl,
|
||||||
webserviceGisLinesStatusUrl,
|
webserviceGisLinesStatusUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Access to fetch at 'http://localhost:3000/api/linesColorApi' from origin 'http://10.10.0.13:3000' has been blocked by CORS policy:
|
||||||
|
No 'Access-Control-Allow-Origin' header is present on the requested resource.
|
||||||
|
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
|
||||||
|
*/
|
||||||
|
|||||||
17
config/layers.js
Normal file
17
config/layers.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import L from "leaflet";
|
||||||
|
|
||||||
|
export const MAP_LAYERS = {
|
||||||
|
TALAS: new L.layerGroup(),
|
||||||
|
ECI: new L.layerGroup(),
|
||||||
|
ULAF: new L.layerGroup(),
|
||||||
|
GSMModem: new L.layerGroup(),
|
||||||
|
CiscoRouter: new L.layerGroup(),
|
||||||
|
WAGO: new L.layerGroup(),
|
||||||
|
Siemens: new L.layerGroup(),
|
||||||
|
OTDR: new L.layerGroup(),
|
||||||
|
WDM: new L.layerGroup(),
|
||||||
|
GMA: new L.layerGroup(),
|
||||||
|
Sonstige: new L.layerGroup(),
|
||||||
|
TALASICL: new L.layerGroup(),
|
||||||
|
lineLayer: new L.LayerGroup(),
|
||||||
|
};
|
||||||
5
config/settings.js
Normal file
5
config/settings.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// /config/settings.js
|
||||||
|
// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte
|
||||||
|
export const MAP_VERSION = "1.0.0";
|
||||||
|
//export const STANDARD_SIDE_MENU = true;
|
||||||
|
//export const FULL_SIDE_MENU = false;
|
||||||
36
config/urls.js
Normal file
36
config/urls.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
// /sonstige/urls.js
|
||||||
|
|
||||||
|
// BASE_URL für Station öffnen in neuer tab und gleicher tab, im localhost gab es keine Probleme mit der Frame
|
||||||
|
//export const BASE_URL = "http://10.10.0.13/talas5/devices/";
|
||||||
|
//const baseUrl = "http://localhost:3000/talas5/devices/";
|
||||||
|
//const baseUrl = "http://192.168.10.14/talas5/devices/";
|
||||||
|
//----
|
||||||
|
//Talas_v5 Server
|
||||||
|
//export const OFFLINE_TILE_LAYER = "/mapTiles/{z}/{x}/{y}.png"; // wenn im von localhost also selben Server die Karte angezeigt wird
|
||||||
|
//export const OFFLINE_TILE_LAYER = "/mapTiles/{z}/{x}/{y}.png";
|
||||||
|
export const BASE_URL = "http://10.10.0.13/talas5/devices/";
|
||||||
|
export const OFFLINE_TILE_LAYER = "/mapTiles/{z}/{x}/{y}.png";
|
||||||
|
export const ONLINE_TILE_LAYER =
|
||||||
|
"http://10.10.0.13:3000/mapTiles/{z}/{x}/{y}.png"; //Talas_v5 Server */
|
||||||
|
//-----------------------------------
|
||||||
|
// weil ich keine API habe, ansonsten serverURL ist localhost(IP-Adresse) für GisSystemStatic für die Benutzerrechte
|
||||||
|
//const serverURL = `${protocol}//${hostname}`;
|
||||||
|
//const serverURL = `${protocol}//${hostname}${port ? `:${port}` : ""}`;
|
||||||
|
//const serverURL = "http://localhost:3000";
|
||||||
|
export const SERVER_URL = "http://10.10.0.13";
|
||||||
|
|
||||||
|
// Online Daten URLs
|
||||||
|
/* export const MAP_GIS_STATIONS_STATIC_DISTRICT_URL = `${SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStaticDistrict?idMap=${c}&idUser=${user}`; //idMap: 10, idUser: 484
|
||||||
|
export const MAP_GIS_STATIONS_STATUS_DISTRICT_URL = `${SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GisStationsStatusDistrict?idMap=${c}&idUser=${user}`;
|
||||||
|
export const MAP_GIS_STATIONS_MEASUREMENTS_URL = `${SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GisStationsMeasurements?idMap=${c}`;
|
||||||
|
export const MAP_GIS_SYSTEM_STATIC_URL = `${SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${c}&idUser=${user}`;
|
||||||
|
export const MAP_DATA_ICON_URL = `${SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GetIconsStatic`;
|
||||||
|
export const WEBSERVICE_GIS_LINES_STATUS_URL =
|
||||||
|
"http://localhost:3000/api/linesColorApi";
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Access to fetch at 'http://localhost:3000/api/linesColorApi' from origin 'http://10.10.0.13:3000' has been blocked by CORS policy:
|
||||||
|
No 'Access-Control-Allow-Origin' header is present on the requested resource.
|
||||||
|
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
|
||||||
|
*/
|
||||||
13
jest.config.js
Normal file
13
jest.config.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
setupFilesAfterEnv: ["<rootDir>/setupTests.js"],
|
||||||
|
transform: {
|
||||||
|
"^.+\\.(js|jsx)$": "babel-jest",
|
||||||
|
},
|
||||||
|
transformIgnorePatterns: [
|
||||||
|
"/node_modules/(?!(@react-leaflet|react-leaflet|leaflet)/)",
|
||||||
|
],
|
||||||
|
testEnvironment: "jsdom",
|
||||||
|
moduleNameMapper: {
|
||||||
|
"\\.(css|less|scss|sass)$": "identity-obj-proxy",
|
||||||
|
},
|
||||||
|
};
|
||||||
1
jest.setup.js
Normal file
1
jest.setup.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import "@testing-library/jest-dom";
|
||||||
Binary file not shown.
7834
package-lock.json
generated
7834
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@@ -10,8 +10,9 @@
|
|||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"mysql2": "^3.10.1",
|
"mysql2": "^3.10.1",
|
||||||
"next": "^14.2.3",
|
"next": "^14.2.3",
|
||||||
|
"nextjs-cors": "^2.2.0",
|
||||||
"overlapping-marker-spiderfier-leaflet": "^0.2.7",
|
"overlapping-marker-spiderfier-leaflet": "^0.2.7",
|
||||||
"react": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-leaflet": "^4.2.1",
|
"react-leaflet": "^4.2.1",
|
||||||
"react-toastify": "^10.0.5",
|
"react-toastify": "^10.0.5",
|
||||||
@@ -21,15 +22,26 @@
|
|||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"export": "next export"
|
"export": "next export",
|
||||||
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.24.7",
|
||||||
|
"@babel/preset-env": "^7.24.7",
|
||||||
|
"@babel/preset-react": "^7.24.7",
|
||||||
|
"@testing-library/jest-dom": "^6.4.6",
|
||||||
|
"@testing-library/react": "^16.0.0",
|
||||||
"@types/leaflet": "^1.9.12",
|
"@types/leaflet": "^1.9.12",
|
||||||
"@types/leaflet-contextmenu": "^1.4.3",
|
"@types/leaflet-contextmenu": "^1.4.3",
|
||||||
"@types/react": "^18.3.1",
|
"@types/react": "^18.3.1",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^18.3.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"postcss": "^8.4.38",
|
"babel-jest": "^29.7.0",
|
||||||
|
"identity-obj-proxy": "^3.0.0",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"jest-css-modules-transform": "^4.4.2",
|
||||||
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
|
"postcss": "^8.4.39",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"tailwindcss": "^3.4.3"
|
"tailwindcss": "^3.4.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Pfad: pages/_app.js
|
// Pfad: pages/_app.js
|
||||||
import { RecoilRoot } from 'recoil';
|
import React from "react";
|
||||||
|
import { RecoilRoot } from "recoil";
|
||||||
import "../styles/global.css";
|
import "../styles/global.css";
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
|
|||||||
@@ -2,7 +2,18 @@
|
|||||||
// http://10.10.0.13/talas5/ClientData/WebServiceMap.asmx/GisStationsStatusDistrict
|
// http://10.10.0.13/talas5/ClientData/WebServiceMap.asmx/GisStationsStatusDistrict
|
||||||
//In DB gis_lines idLD und idModul anpassen entsprechend
|
//In DB gis_lines idLD und idModul anpassen entsprechend
|
||||||
|
|
||||||
export default function handler(req, res) {
|
// /pages/api/linesColorApi.js
|
||||||
|
import NextCors from "nextjs-cors";
|
||||||
|
|
||||||
|
export default async function handler(req, res) {
|
||||||
|
// Run the cors middleware
|
||||||
|
await NextCors(req, res, {
|
||||||
|
// Options
|
||||||
|
methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
|
||||||
|
origin: "*", // Erlauben Sie alle Ursprünge, oder geben Sie spezifische Ursprünge an
|
||||||
|
optionsSuccessStatus: 200, // Legacy-Browser-Unterstützung für 204
|
||||||
|
});
|
||||||
|
|
||||||
const response = {
|
const response = {
|
||||||
Name: "Liste aller Statis der Linien",
|
Name: "Liste aller Statis der Linien",
|
||||||
Zeitstempel: new Date().toISOString(), // Aktuellen Zeitstempel hinzufügen
|
Zeitstempel: new Date().toISOString(), // Aktuellen Zeitstempel hinzufügen
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// pages/index.js
|
import React, { useEffect, useState } from "react";
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useRecoilState, useRecoilValue } from "recoil";
|
import { useRecoilState, useRecoilValue } from "recoil";
|
||||||
import { readPoiMarkersStore } from "../store/selectors/readPoiMarkersStore"; // Aktualisiert mit atom
|
import { readPoiMarkersStore } from "../store/selectors/readPoiMarkersStore";
|
||||||
import { poiReadFromDbTriggerAtom } from "../store/atoms/poiReadFromDbTriggerAtom";
|
import { poiReadFromDbTriggerAtom } from "../store/atoms/poiReadFromDbTriggerAtom";
|
||||||
|
|
||||||
const MapComponentWithNoSSR = dynamic(
|
const MapComponentWithNoSSR = dynamic(
|
||||||
@@ -24,14 +23,12 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
setLocations(data);
|
setLocations(data);
|
||||||
//console.log("Geladene Daten in Home.js:", data);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// URL-Parameter abfragen
|
|
||||||
function getURLParameter(name) {
|
function getURLParameter(name) {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
return params.get(name);
|
return params.get(name);
|
||||||
@@ -39,10 +36,7 @@ export default function Home() {
|
|||||||
setMParam(getURLParameter("m"));
|
setMParam(getURLParameter("m"));
|
||||||
setUParam(getURLParameter("u"));
|
setUParam(getURLParameter("u"));
|
||||||
|
|
||||||
// Daten beim Laden der Seite holen
|
|
||||||
loadData();
|
loadData();
|
||||||
|
|
||||||
//console.log("poiReadTrigger in Home.js:", poiReadTrigger);
|
|
||||||
}, [poiReadTrigger]);
|
}, [poiReadTrigger]);
|
||||||
|
|
||||||
const handleAddLocation = async (name, type, lat, lng) => {
|
const handleAddLocation = async (name, type, lat, lng) => {
|
||||||
@@ -56,8 +50,7 @@ export default function Home() {
|
|||||||
throw new Error("Fehler beim Hinzufügen des Standorts");
|
throw new Error("Fehler beim Hinzufügen des Standorts");
|
||||||
}
|
}
|
||||||
console.log("Standort erfolgreich hinzugefügt");
|
console.log("Standort erfolgreich hinzugefügt");
|
||||||
loadData(); // Aktualisiere die Daten nach dem Hinzufügen
|
loadData();
|
||||||
console.log("poiReadTrigger in Home.js:", poiReadTrigger);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error.message);
|
console.error(error.message);
|
||||||
}
|
}
|
||||||
@@ -72,13 +65,11 @@ export default function Home() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
//------------------------------------
|
|
||||||
// Daten beim Laden der Seite holen
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadData();
|
loadData();
|
||||||
//console.log("poiReadTrigger in Home.js:", poiReadTrigger);
|
|
||||||
}, [poiReadTrigger]);
|
}, [poiReadTrigger]);
|
||||||
//------------------------------------
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<MapComponentWithNoSSR
|
<MapComponentWithNoSSR
|
||||||
|
|||||||
142
services/apiService.js
Normal file
142
services/apiService.js
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
// services/apiService.js
|
||||||
|
import * as config from "../config/config";
|
||||||
|
import { setPriorityConfig } from "../utils/utils";
|
||||||
|
import * as urls from "../config/urls";
|
||||||
|
|
||||||
|
export const fetchGisStatusStations = async (idMap, idUser) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/talas5/webserviceMap/GisStationsStatusDistrict?idMap=${idMap}&idUser=${idUser}`
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Error: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("GisStatusStations:", data);
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Abrufen der Daten:", error);
|
||||||
|
throw error; // Fehler weiter werfen, um ihn in der Komponente behandeln zu können
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
export const fetchPriorityConfig = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/talas_v5_DB/priorityConfig");
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Prioritätskonfiguration:", data);
|
||||||
|
setPriorityConfig(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Laden der Prioritätskonfiguration:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
export const fetchPoiData = async (idPoi) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/talas_v5_DB/pois/getPoiById?idPoi=${idPoi}`
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Fehler beim Abrufen der POI-Daten");
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
return {
|
||||||
|
idPoi,
|
||||||
|
name: data.name,
|
||||||
|
description: data.description,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Abrufen der POI-Daten", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// ----------------------------------------------
|
||||||
|
// Funktion zum Aktualisieren der Position in der Datenbank
|
||||||
|
export const updateLocationInDatabase = async (
|
||||||
|
id,
|
||||||
|
newLatitude,
|
||||||
|
newLongitude
|
||||||
|
) => {
|
||||||
|
const response = await fetch("/api/talas_v5_DB/pois/updateLocation", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
id,
|
||||||
|
latitude: newLatitude,
|
||||||
|
longitude: newLongitude,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
//schreib die neue Kooridnaten in die Console
|
||||||
|
//akuellisiere die Position in der Datenbank mit den neuen Koordinaten mit updateLocation mit SQL Anweisung UPDATE
|
||||||
|
} else {
|
||||||
|
console.error("Fehler beim Aktualisieren der Position");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
// Funktionen zur Überwachung der Internetverbindung
|
||||||
|
export const checkInternet = () => {
|
||||||
|
fetch("https://tile.openstreetmap.org/1/1/1.png", { method: "HEAD" })
|
||||||
|
.then((response) => setOnline(response.ok))
|
||||||
|
.catch(() => setOnline(false));
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
export const fetchDeviceNameById = async (idLD) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/talas_v5_DB/locationDevice/locationDeviceNameById?idLD=${idLD}`
|
||||||
|
);
|
||||||
|
const data = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
return data.name;
|
||||||
|
} else {
|
||||||
|
throw new Error(data.error || "Gerät nicht gefunden");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
/* console.error(
|
||||||
|
"Fehler beim Abrufen des Gerätenamens in MapComponent.js:",
|
||||||
|
error
|
||||||
|
); */
|
||||||
|
return "Unbekannt";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------
|
||||||
|
// services/apiService.js
|
||||||
|
export const fetchUserRights = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${urls.SERVER_URL}/talas5/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${config.idMap}&idUser=${config.idUser}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
// console.log("Benutzerrechte in fetchRights:", data);
|
||||||
|
|
||||||
|
// Überprüfen der Struktur der Antwort
|
||||||
|
if (!data || !data.Rights || !Array.isArray(data.Rights)) {
|
||||||
|
throw new Error("Invalid response structure");
|
||||||
|
}
|
||||||
|
|
||||||
|
const rightsArray = data.Rights; // Nehmen an, dass 'Rights' das Array von Rechten ist
|
||||||
|
//console.log("rightsArray in apiService:", rightsArray);
|
||||||
|
|
||||||
|
// Speichert die IDs der Rechte in einem Array
|
||||||
|
const userRightsIds = rightsArray.map((right) => right.IdRight);
|
||||||
|
|
||||||
|
// Wenn alles gut geht, logge die erfolgreichen Abschluss
|
||||||
|
// console.log("Benutzerrechte erfolgreich abgerufen:", userRightsIds);
|
||||||
|
return userRightsIds;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Abrufen der Benutzerrechte", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
2
setupTests.js
Normal file
2
setupTests.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
// setupTests.js
|
||||||
|
import "@testing-library/jest-dom";
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
purge: ["./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}"],
|
content: [
|
||||||
content: [],
|
"./pages/**/*.{js,ts,jsx,tsx}",
|
||||||
|
"./components/**/*.{js,ts,jsx,tsx}",
|
||||||
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
zIndex: {
|
zIndex: {
|
||||||
|
|||||||
33
utils/contextMenuUtils.js
Normal file
33
utils/contextMenuUtils.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// contextMenuUtils.js
|
||||||
|
import { BASE_URL } from "../config/urls";
|
||||||
|
export function addContextMenuToMarker(marker) {
|
||||||
|
marker.unbindContextMenu(); // Entferne das Kontextmenü, um Duplikate zu vermeiden
|
||||||
|
|
||||||
|
marker.bindContextMenu({
|
||||||
|
contextmenu: true,
|
||||||
|
contextmenuWidth: 140,
|
||||||
|
contextmenuItems: [
|
||||||
|
/* {
|
||||||
|
text: "Station öffnen (Tab)",
|
||||||
|
icon: "/img/screen_new.png",
|
||||||
|
callback: (e) => openInNewTab(e, marker),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Station öffnen",
|
||||||
|
icon: "/img/screen_same.png",
|
||||||
|
callback: (e) => openInSameWindow(e, marker),
|
||||||
|
}, */
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Funktion zum Öffnen in einem neuen Tab
|
||||||
|
export function openInNewTab(e, marker) {
|
||||||
|
const baseUrl = BASE_URL;
|
||||||
|
console.log("baseUrl:", baseUrl);
|
||||||
|
if (marker && marker.options && marker.options.link) {
|
||||||
|
//console.log("Marker data:", baseUrl + marker.options.link);
|
||||||
|
window.open(baseUrl + marker.options.link, "_blank");
|
||||||
|
} else {
|
||||||
|
console.error("Fehler: Marker hat keine gültige 'link' Eigenschaft");
|
||||||
|
}
|
||||||
|
}
|
||||||
21
utils/geometryUtils.js
Normal file
21
utils/geometryUtils.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
export const parsePoint = (position) => {
|
||||||
|
const [longitude, latitude] = position.slice(6, -1).split(" ");
|
||||||
|
return { latitude: parseFloat(latitude), longitude: parseFloat(longitude) };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const findClosestPoints = (coordinates, newPoint, map) => {
|
||||||
|
let minDist = Infinity;
|
||||||
|
let closestPair = [];
|
||||||
|
for (let i = 1; i < coordinates.length; i++) {
|
||||||
|
const dist = L.LineUtil.pointToSegmentDistance(
|
||||||
|
map.latLngToLayerPoint(newPoint),
|
||||||
|
map.latLngToLayerPoint(coordinates[i - 1]),
|
||||||
|
map.latLngToLayerPoint(coordinates[i])
|
||||||
|
);
|
||||||
|
if (dist < minDist) {
|
||||||
|
minDist = dist;
|
||||||
|
closestPair = [coordinates[i - 1], coordinates[i], i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return closestPair;
|
||||||
|
};
|
||||||
111
utils/mapUtils.js
Normal file
111
utils/mapUtils.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
// /utils/mapUtils.js
|
||||||
|
import L from "leaflet";
|
||||||
|
|
||||||
|
export const redrawPolyline = (lineData, lineColors, tooltipContents, map) => {
|
||||||
|
if (!lineData || !lineColors || !tooltipContents || !map) {
|
||||||
|
console.error("Invalid parameters for redrawPolyline");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineData.coordinates || !Array.isArray(lineData.coordinates)) {
|
||||||
|
console.error("Invalid coordinates in lineData");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const color = lineColors[lineData.idModul] || "#000000";
|
||||||
|
const tooltipContent =
|
||||||
|
tooltipContents[lineData.idModul] || "Standard-Tooltip-Inhalt";
|
||||||
|
|
||||||
|
if (lineData.polyline) map.removeLayer(lineData.polyline);
|
||||||
|
|
||||||
|
lineData.polyline = L.polyline(lineData.coordinates, {
|
||||||
|
color: color,
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
lineData.polyline.bindTooltip(tooltipContent, {
|
||||||
|
permanent: false,
|
||||||
|
direction: "auto",
|
||||||
|
});
|
||||||
|
|
||||||
|
lineData.polyline.on("mouseover", () => {
|
||||||
|
lineData.polyline.setStyle({ weight: 10 });
|
||||||
|
lineData.polyline.bringToFront();
|
||||||
|
});
|
||||||
|
|
||||||
|
lineData.polyline.on("mouseout", () => {
|
||||||
|
lineData.polyline.setStyle({ weight: 5 });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const saveLineData = (lineData) => {
|
||||||
|
fetch("/api/talas_v5_DB/gisLines/updateLineCoordinates", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
idModul: lineData.idModul,
|
||||||
|
idLD: lineData.idLD,
|
||||||
|
newCoordinates: lineData.coordinates,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Fehler beim Speichern der Linienänderungen");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
console.log("Linienänderungen gespeichert:", data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Fehler beim Speichern der Linienänderungen:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Call this function on page load to restore zoom and center
|
||||||
|
export const restoreMapSettings = (map) => {
|
||||||
|
const savedZoom = localStorage.getItem("mapZoom");
|
||||||
|
const savedCenter = localStorage.getItem("mapCenter");
|
||||||
|
|
||||||
|
if (savedZoom && savedCenter) {
|
||||||
|
try {
|
||||||
|
const centerCoords = JSON.parse(savedCenter);
|
||||||
|
map.setView(centerCoords, parseInt(savedZoom));
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error parsing stored map center:", e);
|
||||||
|
map.setView([53.111111, 8.4625], 12); // Standardkoordinaten und -zoom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Now update checkOverlappingMarkers to check if oms is initialized
|
||||||
|
export const checkOverlappingMarkers = (map, markers, plusIcon) => {
|
||||||
|
// Ensure markers is always an array
|
||||||
|
if (!Array.isArray(markers)) {
|
||||||
|
//console.error("The `markers` argument is not an array:", markers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const overlappingGroups = {};
|
||||||
|
|
||||||
|
// Group markers by coordinates as strings
|
||||||
|
markers.forEach((marker) => {
|
||||||
|
const latlngStr = marker.getLatLng().toString();
|
||||||
|
if (overlappingGroups[latlngStr]) {
|
||||||
|
overlappingGroups[latlngStr].push(marker);
|
||||||
|
} else {
|
||||||
|
overlappingGroups[latlngStr] = [marker];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add plus markers at coordinates where overlaps occur
|
||||||
|
for (const coords in overlappingGroups) {
|
||||||
|
if (overlappingGroups[coords].length > 1) {
|
||||||
|
const latLng = L.latLng(coords.match(/[-.\d]+/g).map(Number));
|
||||||
|
const plusMarker = L.marker(latLng, { icon: plusIcon });
|
||||||
|
plusMarker.addTo(map);
|
||||||
|
|
||||||
|
//console.log("Adding plus icon marker at", latLng);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
117
utils/markerUtils.js
Normal file
117
utils/markerUtils.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
// /utils/markerUtils.js
|
||||||
|
import circleIcon from "../components/CircleIcon";
|
||||||
|
import { saveLineData, redrawPolyline } from "./mapUtils";
|
||||||
|
import L from "leaflet";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
export const insertNewMarker = (closestPoints, newPoint, lineData, map) => {
|
||||||
|
const newMarker = L.marker(newPoint, {
|
||||||
|
icon: circleIcon,
|
||||||
|
draggable: true,
|
||||||
|
}).addTo(map);
|
||||||
|
lineData.coordinates.splice(closestPoints[2], 0, [
|
||||||
|
newPoint.lat,
|
||||||
|
newPoint.lng,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Hier direkt speichern nach Einfügen
|
||||||
|
saveLineData(lineData);
|
||||||
|
|
||||||
|
redrawPolyline(lineData);
|
||||||
|
|
||||||
|
// Event-Listener für das Verschieben des Markers hinzufügen
|
||||||
|
newMarker.on("dragend", () => {
|
||||||
|
const newCoords = newMarker.getLatLng();
|
||||||
|
setNewCoords(newCoords);
|
||||||
|
const newCoordinates = [...lineData.coordinates];
|
||||||
|
newCoordinates[closestPoints[2]] = [newCoords.lat, newCoords.lng];
|
||||||
|
lineData.coordinates = newCoordinates;
|
||||||
|
redrawPolyline(lineData);
|
||||||
|
|
||||||
|
updateMarkerPosition(newMarker.getLatLng(), lineData, newMarker);
|
||||||
|
saveLineData(lineData); // Speichern der neuen Koordinaten nach dem Verschieben
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const removeMarker = (marker, lineData, currentZoom, currentCenter) => {
|
||||||
|
// Save zoom and center to localStorage
|
||||||
|
//localStorage.setItem("mapZoom", currentZoom);
|
||||||
|
//localStorage.setItem("mapCenter", JSON.stringify(currentCenter));
|
||||||
|
|
||||||
|
// Find the index of the coordinate that matches the marker's position
|
||||||
|
const index = lineData.coordinates.findIndex((coord) =>
|
||||||
|
L.latLng(coord[0], coord[1]).equals(marker.getLatLng())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
// Remove the coordinate from the line data
|
||||||
|
lineData.coordinates.splice(index, 1);
|
||||||
|
|
||||||
|
// Redraw the polyline with the updated coordinates
|
||||||
|
redrawPolyline(lineData);
|
||||||
|
|
||||||
|
// Remove the marker from the map
|
||||||
|
marker.remove();
|
||||||
|
|
||||||
|
// Save the updated line data
|
||||||
|
saveLineData(lineData);
|
||||||
|
|
||||||
|
// Refresh the browser
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const handleEditPoi = (
|
||||||
|
marker,
|
||||||
|
userRights,
|
||||||
|
setCurrentPoiData,
|
||||||
|
setShowPoiUpdateModal,
|
||||||
|
fetchPoiData,
|
||||||
|
toast // Hier toast als Parameter erhalten
|
||||||
|
) => {
|
||||||
|
console.log("Selected Marker ID (idPoi):", marker.options.id);
|
||||||
|
console.log("Selected Marker Description:", marker.options.description);
|
||||||
|
console.log("User Rights:", userRights);
|
||||||
|
|
||||||
|
// Sicherstellen, dass userRights ein Array ist
|
||||||
|
if (!Array.isArray(userRights)) {
|
||||||
|
console.error("User Rights is not an array:", userRights);
|
||||||
|
toast.error("Benutzerrechte sind ungültig.", {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 5000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("User Rights includes 56:", userRights.includes(56));
|
||||||
|
|
||||||
|
// Prüfung, ob der Benutzer die notwendigen Rechte hat
|
||||||
|
if (!userRights.includes(56)) {
|
||||||
|
toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 5000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
});
|
||||||
|
console.log("Benutzer hat keine Berechtigung zum Bearbeiten.");
|
||||||
|
return; // Beendet die Funktion frühzeitig, wenn keine Berechtigung vorliegt
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentPoiData({
|
||||||
|
idPoi: marker.options.id,
|
||||||
|
name: marker.options.name,
|
||||||
|
description: marker.options.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchPoiData(marker.options.id);
|
||||||
|
|
||||||
|
setShowPoiUpdateModal(true);
|
||||||
|
};
|
||||||
10
utils/openInSameWindow.js
Normal file
10
utils/openInSameWindow.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// utils/openInSameWindow.js
|
||||||
|
|
||||||
|
export function openInSameWindow(e, marker, baseUrl) {
|
||||||
|
if (marker && marker.options && marker.options.link) {
|
||||||
|
//console.log("Marker data:", baseUrl + marker.options.link);
|
||||||
|
window.location.href = baseUrl + marker.options.link;
|
||||||
|
} else {
|
||||||
|
console.error("Fehler: Marker hat keine gültige 'link' Eigenschaft");
|
||||||
|
}
|
||||||
|
}
|
||||||
265
utils/utils.js
Normal file
265
utils/utils.js
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
// /utils/utils.js
|
||||||
|
import { useState } from "react";
|
||||||
|
import circleIcon from "../components/CircleIcon";
|
||||||
|
|
||||||
|
export const parsePoint = (position) => {
|
||||||
|
const [longitude, latitude] = position.slice(6, -1).split(" ");
|
||||||
|
return { latitude: parseFloat(latitude), longitude: parseFloat(longitude) };
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
|
||||||
|
export const determinePriority = (iconPath) => {
|
||||||
|
const [priorityConfig, setPriorityConfig] = useState([]);
|
||||||
|
for (let priority of priorityConfig) {
|
||||||
|
if (iconPath.includes(priority.name.toLowerCase())) {
|
||||||
|
return priority.level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 5; // Default priority (lowest)
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
export const createAndSetMarkers = async (systemId, setMarkersFunction) => {
|
||||||
|
try {
|
||||||
|
const response1 = await fetch(config.mapGisStationsStaticDistrictUrl);
|
||||||
|
const jsonResponse = await response1.json();
|
||||||
|
const response2 = await fetch(config.mapGisStationsStatusDistrictUrl);
|
||||||
|
const statusResponse = await response2.json();
|
||||||
|
|
||||||
|
const getIdSystemAndAllowValueMap = new Map(
|
||||||
|
GisSystemStatic.map((system) => [system.IdSystem, system.Allow])
|
||||||
|
);
|
||||||
|
//console.log("getIdSystemAndAllowValueMap:", getIdSystemAndAllowValueMap);
|
||||||
|
|
||||||
|
if (jsonResponse.Points && statusResponse.Statis) {
|
||||||
|
const statisMap = new Map(statusResponse.Statis.map((s) => [s.IdLD, s]));
|
||||||
|
let markersData = jsonResponse.Points.filter(
|
||||||
|
(station) =>
|
||||||
|
station.System === systemId &&
|
||||||
|
getIdSystemAndAllowValueMap.get(station.System) === 1
|
||||||
|
).map((station) => {
|
||||||
|
const statis = statisMap.get(station.IdLD);
|
||||||
|
const iconPath = statis
|
||||||
|
? `img/icons/${statis.Na}-marker-icon-${station.Icon}.png`
|
||||||
|
: `img/icons/marker-icon-${station.Icon}.png`;
|
||||||
|
|
||||||
|
const priority = determinePriority(iconPath);
|
||||||
|
const zIndexOffset = 100 * (5 - priority); // Adjusted for simplicity and positive values
|
||||||
|
|
||||||
|
const marker = L.marker([station.X, station.Y], {
|
||||||
|
icon: L.icon({
|
||||||
|
iconUrl: iconPath,
|
||||||
|
iconSize: [25, 41],
|
||||||
|
iconAnchor: [12, 41],
|
||||||
|
popupAnchor: [1, -34],
|
||||||
|
}),
|
||||||
|
areaName: station.Area_Name, // Stelle sicher, dass dieser Bereich gesetzt wird
|
||||||
|
link: station.Link,
|
||||||
|
zIndexOffset: zIndexOffset,
|
||||||
|
bounceOnAdd: !!statis,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (statis) {
|
||||||
|
marker.on("add", () => marker.bounce(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusInfo = statusResponse.Statis.filter(
|
||||||
|
(status) => status.IdLD === station.IdLD
|
||||||
|
)
|
||||||
|
.reverse()
|
||||||
|
.map(
|
||||||
|
(status) => `
|
||||||
|
<div class="flex items-center my-1">
|
||||||
|
<div class="w-2 h-2 mr-2 inline-block rounded-full" style="background-color: ${status.Co};"></div>
|
||||||
|
${status.Me} <span style="color: ${status.Co};">(${status.Na})</span>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
.join("");
|
||||||
|
|
||||||
|
marker.bindPopup(`
|
||||||
|
<div class=" bg-white rounded-lg ">
|
||||||
|
<span class="text-lg font-semibold text-gray-900">${station.LD_Name}</span>
|
||||||
|
<span class="text-md font-bold text-gray-800"> ${station.Device}</span><br>
|
||||||
|
<span class="text-gray-800"><strong> ${station.Area_Short} </strong>(${station.Area_Name})</span><br>
|
||||||
|
<span class="text-gray-800"><strong>${station.Location_Short} </strong> (${station.Location_Name})</span>
|
||||||
|
<div class="mt-2">${statusInfo}</div>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
return marker;
|
||||||
|
});
|
||||||
|
|
||||||
|
setMarkersFunction(markersData);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data: ", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
export const fetchPriorityConfig = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/talas_v5_DB/priorityConfig");
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Prioritätskonfiguration:", data);
|
||||||
|
setPriorityConfig(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Laden der Prioritätskonfiguration:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
export const fetchGisStatusStations = async (idMap, idUser) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/talas5/webserviceMap/GisStationsStatusDistrict?idMap=${idMap}&idUser=${idUser}`
|
||||||
|
);
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Error: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("GisStatusStations:", data);
|
||||||
|
return data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Fehler beim Abrufen der Daten:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
export const handleEditPoi = (marker) => {
|
||||||
|
// Prüfung, ob der Benutzer die notwendigen Rechte hat
|
||||||
|
if (!userRights || !userRights.includes(56)) {
|
||||||
|
toast.error("Benutzer hat keine Berechtigung zum Bearbeiten.", {
|
||||||
|
position: "top-center",
|
||||||
|
autoClose: 5000,
|
||||||
|
hideProgressBar: false,
|
||||||
|
closeOnClick: true,
|
||||||
|
pauseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
progress: undefined,
|
||||||
|
});
|
||||||
|
console.log("Benutzer hat keine Berechtigung zum Bearbeiten.");
|
||||||
|
return; // Beendet die Funktion frühzeitig, wenn keine Berechtigung vorliegt
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log("Selected Marker ID (idPoi):", marker.options.idPoi);
|
||||||
|
//console.log("Selected Marker Description:", marker.options.description);
|
||||||
|
|
||||||
|
setCurrentPoiData({
|
||||||
|
idPoi: marker.options.id,
|
||||||
|
name: marker.options.name,
|
||||||
|
description: marker.options.description,
|
||||||
|
});
|
||||||
|
//console.log("POI-Daten1:", currentPoiData);
|
||||||
|
|
||||||
|
fetchPoiData(marker.options.id);
|
||||||
|
|
||||||
|
setShowPoiUpdateModal(true);
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
export const insertNewMarker = (closestPoints, newPoint, lineData, map) => {
|
||||||
|
const newMarker = L.marker(newPoint, {
|
||||||
|
icon: circleIcon,
|
||||||
|
draggable: true,
|
||||||
|
}).addTo(map);
|
||||||
|
lineData.coordinates.splice(closestPoints[2], 0, [
|
||||||
|
newPoint.lat,
|
||||||
|
newPoint.lng,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Hier direkt speichern nach Einfügen
|
||||||
|
saveLineData(lineData);
|
||||||
|
|
||||||
|
redrawPolyline(lineData);
|
||||||
|
|
||||||
|
// Event-Listener für das Verschieben des Markers hinzufügen
|
||||||
|
newMarker.on("dragend", () => {
|
||||||
|
const newCoords = newMarker.getLatLng();
|
||||||
|
setNewCoords(newCoords);
|
||||||
|
const newCoordinates = [...lineData.coordinates];
|
||||||
|
newCoordinates[closestPoints[2]] = [newCoords.lat, newCoords.lng];
|
||||||
|
lineData.coordinates = newCoordinates;
|
||||||
|
redrawPolyline(lineData);
|
||||||
|
|
||||||
|
updateMarkerPosition(newMarker.getLatLng(), lineData, newMarker);
|
||||||
|
saveLineData(lineData); // Speichern der neuen Koordinaten nach dem Verschieben
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
/* export const addItemsToMapContextMenu = () => {
|
||||||
|
const [menuItemAdded, setMenuItemAdded] = useState(false);
|
||||||
|
if (!menuItemAdded) {
|
||||||
|
//console.log("contextMenuItems hasRights:", hasRights);
|
||||||
|
|
||||||
|
map.contextmenu.addItem({
|
||||||
|
text: "POI hinzufügen",
|
||||||
|
icon: "img/add_station.png",
|
||||||
|
className: "background-red",
|
||||||
|
callback: (event) => addStationCallback(event, hasRights),
|
||||||
|
});
|
||||||
|
|
||||||
|
setMenuItemAdded(true); // Menüpunkt wurde hinzugefült, Zustand aktualisieren
|
||||||
|
}
|
||||||
|
}; */
|
||||||
|
//----------------------------------------------
|
||||||
|
export const saveLineData = (lineData) => {
|
||||||
|
fetch("/api/talas_v5_DB/gisLines/updateLineCoordinates", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
idModul: lineData.idModul,
|
||||||
|
idLD: lineData.idLD,
|
||||||
|
newCoordinates: lineData.coordinates,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Fehler beim Speichern der Linienänderungen");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
console.log("Linienänderungen gespeichert:", data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Fehler beim Speichern der Linienänderungen:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//----------------------------------------------
|
||||||
|
/* export const redrawPolyline = (lineData) => {
|
||||||
|
const [lineColors, setLineColors] = useState({}); */
|
||||||
|
import L from "leaflet";
|
||||||
|
|
||||||
|
export const redrawPolyline = (lineData, lineColors, tooltipContents, map) => {
|
||||||
|
if (!lineData || !lineColors || !tooltipContents || !map) {
|
||||||
|
console.error("Invalid parameters for redrawPolyline");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lineData.coordinates || !Array.isArray(lineData.coordinates)) {
|
||||||
|
console.error("Invalid coordinates in lineData");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const color = lineColors[lineData.idModul] || "#000000";
|
||||||
|
const tooltipContent =
|
||||||
|
tooltipContents[lineData.idModul] || "Standard-Tooltip-Inhalt";
|
||||||
|
|
||||||
|
if (lineData.polyline) map.removeLayer(lineData.polyline);
|
||||||
|
|
||||||
|
lineData.polyline = L.polyline(lineData.coordinates, {
|
||||||
|
color: color,
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
lineData.polyline.bindTooltip(tooltipContent, {
|
||||||
|
permanent: false,
|
||||||
|
direction: "auto",
|
||||||
|
});
|
||||||
|
|
||||||
|
lineData.polyline.on("mouseover", () => {
|
||||||
|
lineData.polyline.setStyle({ weight: 10 });
|
||||||
|
lineData.polyline.bringToFront();
|
||||||
|
});
|
||||||
|
|
||||||
|
lineData.polyline.on("mouseout", () => {
|
||||||
|
lineData.polyline.setStyle({ weight: 5 });
|
||||||
|
});
|
||||||
|
};
|
||||||
45
utils/zoomAndCenterUtils.js
Normal file
45
utils/zoomAndCenterUtils.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// utils/zoomAndCenterUtils.js
|
||||||
|
/* export const zoomIn = (e, map) => {
|
||||||
|
if (!map) {
|
||||||
|
console.error("map is not defined in zoomIn");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map.flyTo(e.latlng, map.getZoom() + 1);
|
||||||
|
localStorage.setItem("mapZoom", map.getZoom());
|
||||||
|
localStorage.setItem("mapCenter", JSON.stringify(map.getCenter()));
|
||||||
|
}; */
|
||||||
|
|
||||||
|
export const zoomIn = (e, map) => {
|
||||||
|
if (!map) {
|
||||||
|
console.error("map is not defined in zoomIn");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map.flyTo(e.latlng, 12);
|
||||||
|
localStorage.setItem("mapZoom", map.getZoom());
|
||||||
|
localStorage.setItem("mapCenter", JSON.stringify(map.getCenter()));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const zoomOut = (map) => {
|
||||||
|
if (!map) {
|
||||||
|
console.error("map is not defined in zoomOut");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const x = 51.41321407879154;
|
||||||
|
const y = 7.739617925303934;
|
||||||
|
const zoom = 7;
|
||||||
|
console.log("map");
|
||||||
|
console.log(map);
|
||||||
|
map.flyTo([x, y], zoom);
|
||||||
|
localStorage.setItem("mapZoom", map.getZoom());
|
||||||
|
localStorage.setItem("mapCenter", JSON.stringify(map.getCenter()));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const centerHere = (e, map) => {
|
||||||
|
if (!map) {
|
||||||
|
console.error("map is not defined in centerHere");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map.panTo(e.latlng);
|
||||||
|
localStorage.setItem("mapZoom", map.getZoom());
|
||||||
|
localStorage.setItem("mapCenter", JSON.stringify(map.getCenter()));
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user