fix: korrigiere fetchGisLinesStatusService für WebService-Antwort 'Statis'

- ersetzt Zugriff auf json.Lines durch json.Statis
- behebt leeren Redux-State bei Linienstatus
- Daten aus Webservice fließen jetzt korrekt in gisLinesStatusSlice
This commit is contained in:
ISA
2025-05-22 11:30:03 +02:00
parent 04e6d19e19
commit 97ee76c5b5
15 changed files with 196 additions and 44 deletions

View File

@@ -4,6 +4,26 @@ Alle bedeutenden Änderungen an diesem Projekt werden in dieser Datei dokumentie
---
## [1.1.144] 2025-05-22
### Fixed
- ✅ Fehlerhafte Webservice-Antwortstruktur in `fetchGisLinesStatusService.js` korrigiert
- Erwartet wurde `json.Lines`, geliefert wurde aber `json.Statis`
- Daten landen jetzt korrekt im Redux Slice `gisLinesStatus`
### Architecture
- 🔁 Vollständige Redux-Anbindung von Linienstatus über `fetchGisLinesStatusThunk`
- 🧠 Daten aus WebService `GisLinesStatus` werden zentral über Redux verwaltet
- 💡 Fehlerbehandlung und JSON-Parsing robuster gestaltet
### Version
- 📦 Version erhöht auf **1.1.144**
---
## [1.1.139] 2025-05-22
### Changed

View File

@@ -2,7 +2,7 @@
import React, { useState, useEffect, use } from "react";
import ReactDOM from "react-dom";
import { setPoiMarkers } from "../redux/slices/readPoiMarkersStoreSlice";
import { selectGisStationsStaticDistrict } from "../redux/slices/webService/gisStationsStaticDistrictSlice";
import { selectGisStationsStaticDistrict } from "../redux/slices/webservice/gisStationsStaticDistrictSlice";
import { useDispatch, useSelector } from "react-redux";
import { fetchPoiTypes } from "../redux/slices/database/poiTypesSlice";
import { incrementTrigger } from "../redux/slices/poiReadFromDbTriggerSlice";

View File

@@ -4,8 +4,8 @@ import { setSelectedArea } from "../redux/slices/selectedAreaSlice";
import EditModeToggle from "./EditModeToggle";
import { useSelector, useDispatch } from "react-redux";
import { selectPolylineVisible, setPolylineVisible } from "../redux/slices/polylineLayerVisibleSlice";
import { selectGisSystemStatic } from "../redux/slices/webService/gisSystemStaticSlice";
import { selectGisStationsStaticDistrict } from "../redux/slices/webService/gisStationsStaticDistrictSlice";
import { selectGisSystemStatic } from "../redux/slices/webservice/gisSystemStaticSlice";
import { selectGisStationsStaticDistrict } from "../redux/slices/webservice/gisStationsStaticDistrictSlice";
import { selectMapLayersState, setLayerVisibility } from "../redux/slices/mapLayersSlice";
import { setVisible } from "../redux/slices/poiLayerVisibleSlice";
import { incrementZoomTrigger } from "../redux/slices/zoomTriggerSlice";

View File

@@ -38,8 +38,8 @@ import CoordinatePopup from "../CoordinatePopup.js";
//------------------------Daten aus API--------------------
import { fetchPoiDataService } from "../../services/database/fetchPoiDataService.js";
import { selectPolylineVisible, setPolylineVisible } from "../../redux/slices/polylineLayerVisibleSlice.js";
import { selectGisStationsStaticDistrict } from "../../redux/slices/webService/gisStationsStaticDistrictSlice";
import { selectGisSystemStatic, setGisSystemStatic } from "../../redux/slices/webService/gisSystemStaticSlice";
import { selectGisStationsStaticDistrict } from "../../redux/slices/webservice/gisStationsStaticDistrictSlice.js";
import { selectGisSystemStatic, setGisSystemStatic } from "../../redux/slices/webservice/gisSystemStaticSlice.js";
import ShowAddStationPopup from "../AddPOIModal.js";
import AddPOIOnPolyline from "../AddPOIOnPolyline";
import { enablePolylineEvents, disablePolylineEvents } from "../../utils/polylines/eventHandlers";
@@ -62,7 +62,10 @@ import { fetchLocationDevicesThunk } from "../../redux/thunks/database/fetchLoca
import { fetchPriorityConfigThunk } from "../../redux/thunks/database/fetchPriorityConfigThunk";
import { selectPriorityConfig } from "../../redux/slices/database/priorityConfigSlice";
import { fetchGisLinesThunk } from "../../redux/thunks/database/fetchGisLinesThunk";
import { fetchGisLinesStatusThunk } from "../../redux/thunks/webservice/fetchGisLinesStatusThunk";
import { fetchUserRightsThunk } from "../../redux/thunks/webservice/fetchUserRightsThunk";
import { selectGisLines } from "../../redux/slices/database/gisLinesSlice";
import { selectGisLinesStatus } from "../../redux/slices/webservice/gisLinesStatusSlice";
const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
//-------------------------------
@@ -90,6 +93,11 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
const linesData = useSelector((state) => state.gisLines.data);
const gisLinesStatus = useSelector((state) => state.gisLines.status);
const { data: gisLinesStatusData, status: statusGisLinesStatus } = useSelector(selectGisLinesStatus);
useEffect(() => {
console.log("✅ Redux: gisLinesStatusData:", gisLinesStatusData);
}, [gisLinesStatusData]);
//-------------------------------
const { deviceName, setDeviceName } = useMapComponentState();
const [locationDeviceData, setLocationDeviceData] = useState([]);
@@ -228,6 +236,14 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => {
}
}, [gisLinesStatus, dispatch]);
//--------------------------------------------------------
useEffect(() => {
dispatch(fetchGisLinesStatusThunk());
}, [dispatch]);
//---------------------------------------------------------
useEffect(() => {
dispatch(fetchUserRightsThunk());
}, [dispatch]);
//----------------------------------------------------
useEffect(() => {
if (linesData && Array.isArray(linesData)) {

View File

@@ -1,2 +1,2 @@
// /config/appVersion
export const APP_VERSION = "1.1.143";
export const APP_VERSION = "1.1.145";

View File

@@ -1,30 +1,32 @@
// Datei: /config/config.js
import { BASE_URL } from "../config/paths";
// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte
const standardSideMenu = true;
const fullSideMenu = false;
// Server-URL aus Umgebungsvariable holen (nur bei echter API benötigt)
const mode = process.env.NEXT_PUBLIC_API_PORT_MODE;
const serverURL = mode === "dev" ? `${window.location.protocol}//${window.location.hostname}:80` : `${window.location.origin}`;
if (!serverURL && !isMockMode()) {
throw new Error("Die Umgebungsvariable ist nicht gesetzt!");
}
console.log("%c 1- serverURL in config:", "color: #006400;", serverURL);
// Initialisieren von Variablen, die später im Browserkontext gesetzt werden
let windowHeight, url_string, url, idMap, idUser;
let mapGisSystemStaticUrl, mapDataIconUrl, webserviceGisLinesStatusUrl;
// Prüfen, ob Mock-Modus aktiv ist
function isMockMode() {
return process.env.NEXT_PUBLIC_USE_MOCK_API === "true";
}
// Definieren der grundlegenden Umgebungseinstellungen und Konfigurationen der Karte
const mode = process.env.NEXT_PUBLIC_API_PORT_MODE;
let serverURL = "";
if (typeof window !== "undefined") {
serverURL = mode === "dev" ? `${window.location.protocol}//${window.location.hostname}:80` : `${window.location.origin}`;
}
if (typeof window !== "undefined" && !serverURL && !isMockMode()) {
throw new Error("Die Umgebungsvariable ist nicht gesetzt!");
}
if (typeof window !== "undefined") {
console.log("%c 1- serverURL in config:", "color: #006400;", serverURL);
}
// Initialisieren von Variablen, die später im Browserkontext gesetzt werden
let windowHeight, url_string, url, idMap, idUser;
let webserviceGisLinesStatusUrl;
// URL-Setup - dynamisch abhängig von Mock oder Echtbetrieb
if (typeof window !== "undefined") {
windowHeight = window.innerHeight;
@@ -39,23 +41,14 @@ if (typeof window !== "undefined") {
if (isMockMode()) {
// Mock-Daten jetzt über API-Endpunkte aus pages/api/mockData/webService/
mapGisSystemStaticUrl = "/api/mockData/webService/GisSystemStaticMock";
mapDataIconUrl = "/api/mockData/webService/GetIconsStaticMock";
webserviceGisLinesStatusUrl = "/api/mockData/webService/GisLinesStatusMock";
console.log("📡 Mock-Mode aktiv: Daten werden aus /api/mockData/webService geladen.");
} else {
// Echte URLs zur Webservice-API
mapGisSystemStaticUrl = `${serverURL}${BASE_URL}/ClientData/WebserviceMap.asmx/GisSystemStatic?idMap=${idMap}&idUser=${idUser}`;
mapDataIconUrl = `${serverURL}${BASE_URL}/ClientData/WebserviceMap.asmx/GetIconsStatic`;
webserviceGisLinesStatusUrl = `${serverURL}${BASE_URL}/ClientData/WebServiceMap.asmx/GisLinesStatus?idMap=${idMap}`;
console.log("🌐 Echt-Mode aktiv: Daten werden von der API geholt.");
}
}
// Export der Variablen und URLs
export { standardSideMenu, fullSideMenu, serverURL, windowHeight, url_string, url, idMap, idUser, mapGisSystemStaticUrl, mapDataIconUrl, webserviceGisLinesStatusUrl, isMockMode };
export { serverURL, windowHeight, url_string, url, idMap, idUser, webserviceGisLinesStatusUrl, isMockMode };

View File

@@ -1,3 +1,4 @@
// /redux/slices/database/gisLinesSlice.js
import { createSlice } from "@reduxjs/toolkit";
import { fetchGisLinesThunk } from "../../thunks/database/fetchGisLinesThunk";

View File

@@ -0,0 +1,33 @@
// /redux/slices/webservice/gisLinesStatusSlice.js
import { createSlice } from "@reduxjs/toolkit";
import { fetchGisLinesStatusThunk } from "../../thunks/webservice/fetchGisLinesStatusThunk";
const initialState = {
data: [],
status: "idle",
error: null,
};
export const gisLinesStatusSlice = createSlice({
name: "gisLinesStatus",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchGisLinesStatusThunk.pending, (state) => {
state.status = "loading";
})
.addCase(fetchGisLinesStatusThunk.fulfilled, (state, action) => {
state.status = "succeeded";
state.data = action.payload;
})
.addCase(fetchGisLinesStatusThunk.rejected, (state, action) => {
state.status = "failed";
state.error = action.payload;
});
},
});
export default gisLinesStatusSlice.reducer;
export const selectGisLinesStatus = (state) => state.gisLinesStatus;

View File

@@ -0,0 +1,34 @@
// /redux/slices/webservice/userRightsSlice.js
import { createSlice } from "@reduxjs/toolkit";
import { fetchUserRightsThunk } from "../../thunks/webservice/fetchUserRightsThunk";
const initialState = {
rights: [],
status: "idle",
error: null,
};
export const userRightsSlice = createSlice({
name: "userRights",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUserRightsThunk.pending, (state) => {
state.status = "loading";
})
.addCase(fetchUserRightsThunk.fulfilled, (state, action) => {
state.status = "succeeded";
state.rights = action.payload;
})
.addCase(fetchUserRightsThunk.rejected, (state, action) => {
state.status = "failed";
state.error = action.payload;
});
},
});
export default userRightsSlice.reducer;
export const selectUserRights = (state) => state.userRights.rights;
export const selectUserRightsStatus = (state) => state.userRights.status;

View File

@@ -3,13 +3,6 @@ import { configureStore } from "@reduxjs/toolkit";
import lineVisibilityReducer from "./slices/lineVisibilitySlice";
import currentPoiReducer from "./slices/currentPoiSlice";
import polylineLayerVisibleReducer from "./slices/polylineLayerVisibleSlice";
import locationDevicesFromDBReducer from "./slices/database/locationDevicesFromDBSlice";
import gisStationsStaticDistrictReducer from "./slices/webService/gisStationsStaticDistrictSlice";
import gisStationsStatusDistrictReducer from "./slices/webService/gisStationsStatusDistrictSlice";
import gisStationsMeasurementsReducer from "./slices/webService/gisStationsMeasurementsSlice";
import gisSystemStaticReducer from "./slices/webService/gisSystemStaticSlice";
import poiTypesReducer from "./slices/database/poiTypesSlice";
import addPoiOnPolylineReducer from "./slices/addPoiOnPolylineSlice";
import polylineContextMenuReducer from "./slices/polylineContextMenuSlice";
import selectedPoiReducer from "./slices/selectedPoiSlice";
@@ -22,8 +15,18 @@ import readPoiMarkersStoreReducer from "./slices/readPoiMarkersStoreSlice";
import selectedAreaReducer from "./slices/selectedAreaSlice";
import zoomTriggerReducer from "./slices/zoomTriggerSlice";
import urlParameterReducer from "./slices/urlParameterSlice";
//-----database------------
import priorityConfigReducer from "./slices/database/priorityConfigSlice";
import gisLinesReducer from "./slices/database/gisLinesSlice";
import poiTypesReducer from "./slices/database/poiTypesSlice";
import locationDevicesFromDBReducer from "./slices/database/locationDevicesFromDBSlice";
//----webservice------------
import gisStationsStaticDistrictReducer from "./slices/webservice/gisStationsStaticDistrictSlice";
import gisStationsStatusDistrictReducer from "./slices/webservice/gisStationsStatusDistrictSlice";
import gisStationsMeasurementsReducer from "./slices/webservice/gisStationsMeasurementsSlice";
import gisSystemStaticReducer from "./slices/webservice/gisSystemStaticSlice";
import gisLinesStatusReducer from "./slices/webservice/gisLinesStatusSlice";
import userRightsReducer from "./slices/webservice/userRightsSlice";
export const store = configureStore({
reducer: {
@@ -50,5 +53,7 @@ export const store = configureStore({
urlParameter: urlParameterReducer,
priorityConfig: priorityConfigReducer,
gisLines: gisLinesReducer,
gisLinesStatus: gisLinesStatusReducer,
userRights: userRightsReducer,
},
});

View File

@@ -1,3 +1,4 @@
// /redux/thunks/database/fetchGisLinesThunk.js
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchGisLinesService } from "../../../services/database/fetchGisLinesService";

View File

@@ -0,0 +1,11 @@
// /redux/thunks/webservice/fetchGisLinesStatusThunk.js
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchGisLinesStatusService } from "../../../services/webservice/fetchGisLinesStatusService";
export const fetchGisLinesStatusThunk = createAsyncThunk("gisLinesStatus/fetch", async (_, thunkAPI) => {
try {
return await fetchGisLinesStatusService();
} catch (error) {
return thunkAPI.rejectWithValue(error.message);
}
});

View File

@@ -0,0 +1,11 @@
// /redux/thunks/webservice/fetchUserRightsThunk.js
import { createAsyncThunk } from "@reduxjs/toolkit";
import { fetchUserRightsService } from "../../../services/webservice/fetchUserRightsService";
export const fetchUserRightsThunk = createAsyncThunk("userRights/fetch", async (_, thunkAPI) => {
try {
return await fetchUserRightsService();
} catch (error) {
return thunkAPI.rejectWithValue(error.message);
}
});

View File

@@ -0,0 +1,27 @@
// /services/webservice/fetchGisLinesStatusService.js
export const fetchGisLinesStatusService = async () => {
const mode = process.env.NEXT_PUBLIC_API_PORT_MODE;
const baseUrl = mode === "dev" ? `${window.location.protocol}//${window.location.hostname}:80/talas5/ClientData/WebServiceMap.asmx` : `${window.location.origin}/talas5/ClientData/WebServiceMap.asmx`;
const params = new URLSearchParams(window.location.search);
const idMap = params.get("m");
const url = `${baseUrl}/GisLinesStatus?idMap=${idMap}`;
console.log("📡 fetchGisLinesStatusService URL:", url);
const response = await fetch(url);
if (!response.ok) throw new Error("Fehler beim Laden der Linienstatusdaten");
const text = await response.text();
let json;
try {
json = JSON.parse(text);
} catch (e) {
console.error("❌ Fehler beim JSON-Parsing der Antwort:", text);
throw new Error("Antwort ist kein gültiges JSON");
}
if (!Array.isArray(json.Statis)) throw new Error("Ungültige Antwortstruktur: Statis fehlt");
return json.Statis;
};

View File

@@ -7,8 +7,8 @@ import { store } from "../../redux/store.js";
import { updateLineStatus } from "../../redux/slices/lineVisibilitySlice.js";
import { setSelectedDevice, clearSelectedDevice } from "../../redux/slices/selectedDeviceSlice.js";
import { addContextMenuToMarker } from "../contextMenuUtils.js";
import { selectGisStationsStaticDistrict } from "../../redux/slices/webService/gisStationsStaticDistrictSlice.js";
import { selectGisStationsStatusDistrict } from "../../redux/slices/webService/gisStationsStatusDistrictSlice.js";
import { selectGisStationsStaticDistrict } from "../../redux/slices/webservice/gisStationsStaticDistrictSlice.js";
import { selectGisStationsStatusDistrict } from "../../redux/slices/webservice/gisStationsStatusDistrictSlice.js";
const determinePriority = (iconPath, priorityConfig) => {
for (let priority of priorityConfig) {