diff --git a/.env.development b/.env.development
index aa0975f..fda0d08 100644
--- a/.env.development
+++ b/.env.development
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
NEXT_PUBLIC_EXPORT_STATIC=false
NEXT_PUBLIC_USE_CGI=false
# App-Versionsnummer
-NEXT_PUBLIC_APP_VERSION=1.6.667
+NEXT_PUBLIC_APP_VERSION=1.6.668
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
diff --git a/.env.production b/.env.production
index ec51c37..5a6b536 100644
--- a/.env.production
+++ b/.env.production
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
NEXT_PUBLIC_EXPORT_STATIC=true
NEXT_PUBLIC_USE_CGI=true
# App-Versionsnummer
-NEXT_PUBLIC_APP_VERSION=1.6.667
+NEXT_PUBLIC_APP_VERSION=1.6.668
NEXT_PUBLIC_CPL_MODE=production
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e23aa4b..c5ff2e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+## [1.6.668] – 2025-07-31
+
+- feat: implement chart modal with report functionality for cable monitoring
+
+- Add chartTitle state management to kabelueberwachungChartSlice with "Messkurve"/"Meldungen" options
+- Update IsoChartActionBar dropdown to show current chartTitle value with proper binding
+- Implement conditional rendering in IsoChartView between IsoMeasurementChart and Report components
+- Create Report.tsx component using same data structure as MeldungenView (Meldung type)
+- Add slot-based message filtering for specific cable monitoring units (KÜ)
+- Integrate getMessagesThunk for consistent data loading across components
+- Style Report component with consistent table layout, German date formatting, and Littwin branding
+- Enable seamless switching between measurement chart and filtered messages in modal
+
+---
## [1.6.667] – 2025-07-31
- feat: TDR --> Messkurven TDR anzeigen und dort Schalter Messung aktivieren
diff --git a/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx b/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx
index def321a..74f9e63 100644
--- a/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx
+++ b/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartActionBar.tsx
@@ -88,6 +88,87 @@ export const useIsoChartLoader = () => {
return { loadIsoChartData };
};
+//-----------------------------------------------------------------------------------useIsoDataLoader Hook
+export const useIsoDataLoader = () => {
+ const dispatch = useDispatch();
+ const { vonDatum, bisDatum, selectedMode, slotNumber } = useSelector(
+ (state: RootState) => state.kabelueberwachungChartSlice
+ );
+
+ const formatDate = (dateString: string) => {
+ const [year, month, day] = dateString.split("-");
+ return `${year};${month};${day}`;
+ };
+
+ const getApiUrl = (mode: "DIA0" | "DIA1" | "DIA2", slotNumber: number) => {
+ const type = 3; // Fest auf Isolationswiderstand gesetzt
+ const typeFolder = "isolationswiderstand";
+
+ const baseUrl =
+ process.env.NODE_ENV === "development"
+ ? `/api/cpl/slotDataAPIHandler?slot=${slotNumber}&messart=${typeFolder}&dia=${mode}&vonDatum=${vonDatum}&bisDatum=${bisDatum}`
+ : `${window.location.origin}/CPL?seite.ACP&${mode}=${formatDate(
+ vonDatum
+ )};${formatDate(bisDatum)};${slotNumber};${type};`;
+
+ return baseUrl;
+ };
+
+ const loadData = async () => {
+ if (slotNumber === null) {
+ console.log("⚠️ Kein Slot ausgewählt - automatisches Laden übersprungen");
+ return;
+ }
+
+ const apiUrl = getApiUrl(selectedMode, slotNumber);
+ if (!apiUrl) return;
+
+ dispatch(setLoading(true));
+ dispatch(setChartOpen(false));
+ dispatch(setIsoMeasurementCurveChartData([]));
+
+ const MIN_LOADING_TIME_MS = 1000;
+ const startTime = Date.now();
+
+ try {
+ const response = await fetch(apiUrl, {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ });
+
+ if (!response.ok) throw new Error(`Fehler: ${response.status}`);
+
+ const jsonData = await response.json();
+ const elapsedTime = Date.now() - startTime;
+ const waitTime = Math.max(0, MIN_LOADING_TIME_MS - elapsedTime);
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
+
+ console.log("▶️ Automatisches Laden - Isolationswiderstand-Daten für:");
+ console.log(" Slot:", slotNumber);
+ console.log(" Modus:", selectedMode);
+ console.log(" Von:", vonDatum);
+ console.log(" Bis:", bisDatum);
+
+ if (Array.isArray(jsonData) && jsonData.length > 0) {
+ dispatch(setIsoMeasurementCurveChartData(jsonData));
+ dispatch(setChartOpen(true));
+ } else {
+ console.log(
+ "⚠️ Keine Messdaten im gewählten Zeitraum gefunden (automatisches Laden)"
+ );
+ dispatch(setIsoMeasurementCurveChartData([]));
+ dispatch(setChartOpen(false));
+ }
+ } catch (err) {
+ console.error("❌ Fehler beim automatischen Laden der Daten:", err);
+ } finally {
+ dispatch(setLoading(false));
+ }
+ };
+
+ return { loadData };
+};
+
//-----------------------------------------------------------------------------------IsoChartActionBar
const IsoChartActionBar: React.FC = () => {
const dispatch = useDispatch();
@@ -183,67 +264,71 @@ const IsoChartActionBar: React.FC = () => {
-
+ {/* DateRangePicker - nur bei Messkurve anzeigen */}
+ {chartTitle === "Messkurve" &&
}
-
{
- dispatch(setSelectedMode(value));
- dispatch(setBrushRange({ startIndex: 0, endIndex: 0 }));
- }}
- >
-
-
-
- {
- {
- DIA0: "Alle Messwerte",
- DIA1: "Stündliche Werte",
- DIA2: "Tägliche Werte",
- }[selectedMode]
- }
-
-
-
-
- {["DIA0", "DIA1", "DIA2"].map((mode) => (
-
- `px-4 py-1 cursor-pointer ${
- selected
- ? "bg-littwin-blue text-white"
- : active
- ? "bg-gray-200"
- : ""
- }`
- }
- >
+ {/* DIA0-DIA2 Dropdown - nur bei Messkurve anzeigen */}
+ {chartTitle === "Messkurve" && (
+ {
+ dispatch(setSelectedMode(value));
+ dispatch(setBrushRange({ startIndex: 0, endIndex: 0 }));
+ }}
+ >
+
+
+
{
{
DIA0: "Alle Messwerte",
DIA1: "Stündliche Werte",
DIA2: "Tägliche Werte",
- }[mode]
+ }[selectedMode]
}
-
- ))}
-
-
-
+
+
+
+
+ {["DIA0", "DIA1", "DIA2"].map((mode) => (
+
+ `px-4 py-1 cursor-pointer ${
+ selected
+ ? "bg-littwin-blue text-white"
+ : active
+ ? "bg-gray-200"
+ : ""
+ }`
+ }
+ >
+ {
+ {
+ DIA0: "Alle Messwerte",
+ DIA1: "Stündliche Werte",
+ DIA2: "Tägliche Werte",
+ }[mode]
+ }
+
+ ))}
+
+
+
+ )}
- {/* Dropdown für Auswahl zwischen "Messkurve" und "Meldungen" */}
+ {/* Dropdown für Auswahl zwischen "Messkurve" und "Meldungen" - immer anzeigen */}
dispatch(setChartTitle(value))}
@@ -285,14 +370,18 @@ const IsoChartActionBar: React.FC = () => {
-
+ {/* Daten laden Button - nur bei Messkurve anzeigen */}
+ {chartTitle === "Messkurve" && (
+
+ )}
- {isLoading && (
+ {/* Loading Indicator - nur bei Messkurve anzeigen */}
+ {chartTitle === "Messkurve" && isLoading && (
Lade Daten...
diff --git a/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartView.tsx b/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartView.tsx
index f4a781a..c6453a0 100644
--- a/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartView.tsx
+++ b/components/main/kabelueberwachung/kue705FO/Charts/IsoMeasurementChart/IsoChartView.tsx
@@ -3,7 +3,7 @@
import React, { useEffect } from "react";
import ReactModal from "react-modal";
import IsoMeasurementChart from "./IsoMeasurementChart";
-import IsoChartActionBar from "./IsoChartActionBar";
+import IsoChartActionBar, { useIsoDataLoader } from "./IsoChartActionBar";
import Report from "./Report";
import { useSelector, useDispatch } from "react-redux";
import { AppDispatch } from "@/redux/store";
@@ -36,6 +36,7 @@ const IsoChartView: React.FC
= ({
slotIndex,
}) => {
const dispatch = useDispatch();
+ const { loadData } = useIsoDataLoader();
const { isFullScreen, chartTitle } = useSelector(
(state: RootState) => state.kabelueberwachungChartSlice
@@ -92,8 +93,18 @@ const IsoChartView: React.FC = ({
// Set default to Messkurve
dispatch(setChartTitle("Messkurve"));
+
+ // Automatisch Daten laden nach kurzer Verzögerung
+ // um sicherzustellen, dass alle Redux-States gesetzt sind
+ const timer = setTimeout(() => {
+ loadData();
+ }, 100);
+
+ // Cleanup timer
+ return () => clearTimeout(timer);
}
- }, [isOpen, slotIndex, dispatch]);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isOpen, slotIndex, dispatch]); // loadData bewusst ausgelassen um Endlosschleife zu vermeiden
return (
{
(allMessages: Meldung[], slot: number) => {
if (slot === null) return [];
- // Filter basierend auf der Quelle (i-Feld)
- return allMessages.filter((msg: Meldung) => {
- // Verschiedene mögliche Slot-Identifikationen
- const slotIdentifiers = [
- `CableLine${slot + 1}`,
+ // Primärer Filter: Exakte CableLineX Übereinstimmung (X = slot + 1)
+ const primaryIdentifier = `CableLine${slot + 1}`;
+
+ console.log(
+ `🔍 Filtere Nachrichten für Slot ${slot} (${primaryIdentifier}):`
+ );
+ console.log(`📥 Gesamt Nachrichten: ${allMessages.length}`);
+
+ // Debug: Zeige alle verfügbaren Quellen
+ const allSources = [...new Set(allMessages.map((msg) => msg.i))];
+ console.log(`📋 Alle verfügbaren Quellen:`, allSources);
+
+ // Filter basierend auf der Quelle (i-Feld) - EXAKTE Übereinstimmung
+ const filtered = allMessages.filter((msg: Meldung) => {
+ // Exakte Übereinstimmung: msg.i sollte genau "CableLineX" sein
+ const isExactMatch = msg.i === primaryIdentifier;
+
+ // Fallback: Falls die Quelle mehr Informationen enthält (z.B. "CableLine1_Sensor")
+ const isPartialMatch =
+ msg.i.startsWith(primaryIdentifier) &&
+ (msg.i === primaryIdentifier ||
+ msg.i.charAt(primaryIdentifier.length).match(/[^0-9]/));
+
+ const isMatch = isExactMatch || isPartialMatch;
+
+ if (isMatch) {
+ console.log(`✅ Gefunden: "${msg.i}" -> ${msg.m}`);
+ }
+ return isMatch;
+ });
+
+ console.log(
+ `📤 Gefilterte Nachrichten für ${primaryIdentifier}: ${filtered.length}`
+ );
+
+ // Falls keine Nachrichten mit CableLineX gefunden, versuche alternative Identifikatoren
+ if (filtered.length === 0) {
+ console.log(
+ `⚠️ Keine Nachrichten für ${primaryIdentifier} gefunden. Versuche alternative Identifikatoren...`
+ );
+
+ const alternativeIdentifiers = [
`Slot${slot + 1}`,
`KÜ${slot + 1}`,
`Kue${slot + 1}`,
@@ -45,8 +82,29 @@ const Report: React.FC = () => {
`Line${slot + 1}`,
];
- return slotIdentifiers.some((identifier) => msg.i.includes(identifier));
- });
+ const alternativeFiltered = allMessages.filter((msg: Meldung) => {
+ return alternativeIdentifiers.some((identifier) => {
+ const isExactMatch = msg.i === identifier;
+ const isPartialMatch =
+ msg.i.startsWith(identifier) &&
+ (msg.i === identifier ||
+ msg.i.charAt(identifier.length).match(/[^0-9]/));
+ const isMatch = isExactMatch || isPartialMatch;
+
+ if (isMatch) {
+ console.log(`🔄 Alternative gefunden: "${msg.i}" -> ${msg.m}`);
+ }
+ return isMatch;
+ });
+ });
+
+ console.log(
+ `📤 Alternative gefilterte Nachrichten: ${alternativeFiltered.length}`
+ );
+ return alternativeFiltered;
+ }
+
+ return filtered;
},
[]
);
@@ -107,25 +165,15 @@ const Report: React.FC = () => {
}
return (
-
-
-
- Meldungen für KÜ {slotNumber !== null ? slotNumber + 1 : "-"}
-
-
-
-
+
{filteredMessages.length === 0 ? (
-
- Keine Meldungen im gewählten Zeitraum gefunden.
+
+ Keine Meldungen für CableLine
+ {slotNumber !== null ? slotNumber + 1 : "-"} im gewählten Zeitraum
+ gefunden.
) : (
-
+
@@ -165,7 +213,7 @@ const Report: React.FC = () => {
)}
-
+
{filteredMessages.length} Meldung(en) gefunden
diff --git a/package-lock.json b/package-lock.json
index 93c3988..30c3523 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "cpl-v4",
- "version": "1.6.667",
+ "version": "1.6.668",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cpl-v4",
- "version": "1.6.667",
+ "version": "1.6.668",
"dependencies": {
"@fontsource/roboto": "^5.1.0",
"@headlessui/react": "^2.2.4",
diff --git a/package.json b/package.json
index 461f853..0243490 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cpl-v4",
- "version": "1.6.667",
+ "version": "1.6.668",
"private": true,
"scripts": {
"dev": "next dev",