feat: Verbesserung der Slot-Auswahl und Chart-Steuerung
- `selectedSlot` in `kueChartModeSlice.ts` hinzugefügt, um den aktiven Slot zu speichern. - `handleButtonClick.ts` aktualisiert, damit `selectedSlot` in Redux gesetzt wird. - `handleOpenChartModal.ts` angepasst, sodass `selectedSlot` beim Öffnen des Modals gesetzt wird. - `Kue705FO.tsx` nutzt jetzt Redux für die Slot- und Modus-Steuerung (`selectedSlot`, `activeMode`). - Redux-Logik optimiert: `selectedSlot` wird nun konsistent zwischen `TDRChart.tsx` und `ChartSwitcher.tsx` genutzt. - Verbesserung der Benutzererfahrung: Nur `onClick` verwendet, `onMouseOver` wegen Performance-Problemen vermieden. ✅ Jetzt wird der richtige Slot in Redux gespeichert, wenn ein Button oder das Chart-Modal geöffnet wird. ✅ `TDRChart.tsx` zeigt nur das gewählte Modul an, kein unnötiges Neuladen von Daten. ✅ Stabile und optimierte Chart-Steuerung ohne ungewollte Änderungen durch Mausbewegungen.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"use client"; // /components/modules/kue705FO/charts/ChartSwitcher.tsx
|
||||
|
||||
import React, { useState } from "react";
|
||||
import ReactModal from "react-modal";
|
||||
import LoopChartActionBar from "./LoopMeasurementChart/LoopChartActionBar";
|
||||
@@ -11,15 +12,26 @@ import {
|
||||
setChartOpen,
|
||||
setFullScreen,
|
||||
} from "../../../../../redux/slices/kabelueberwachungChartSlice";
|
||||
import {
|
||||
setSelectedSlot,
|
||||
setSelectedChartType,
|
||||
} from "../../../../../redux/slices/tdrChartSlice";
|
||||
import { resetBrushRange } from "../../../../../redux/slices/brushSlice";
|
||||
|
||||
interface ChartSwitcherProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
slotIndex: number;
|
||||
}
|
||||
|
||||
const ChartSwitcher: React.FC<ChartSwitcherProps> = ({ isOpen, onClose }) => {
|
||||
const ChartSwitcher: React.FC<ChartSwitcherProps> = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
slotIndex,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// **Redux-States für aktive Messkurve (TDR oder Schleife)**
|
||||
const activeMode = useSelector(
|
||||
(state: RootState) => state.kueChartMode.activeMode
|
||||
);
|
||||
@@ -40,6 +52,12 @@ const ChartSwitcher: React.FC<ChartSwitcherProps> = ({ isOpen, onClose }) => {
|
||||
dispatch(setFullScreen(!isFullScreen));
|
||||
};
|
||||
|
||||
// **Slot und Messkurve setzen**
|
||||
const setChartType = (chartType: "TDR" | "Schleife") => {
|
||||
dispatch(setSelectedSlot(slotIndex));
|
||||
dispatch(setSelectedChartType(chartType));
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactModal
|
||||
isOpen={isOpen}
|
||||
@@ -112,6 +130,26 @@ const ChartSwitcher: React.FC<ChartSwitcherProps> = ({ isOpen, onClose }) => {
|
||||
height: "100%",
|
||||
}}
|
||||
>
|
||||
{/* Auswahl zwischen TDR und Schleife */}
|
||||
<div className="flex space-x-4 mb-4">
|
||||
<button
|
||||
className={`p-2 text-white ${
|
||||
activeMode === "TDR" ? "bg-blue-500" : "bg-gray-400"
|
||||
}`}
|
||||
onClick={() => setChartType("TDR")}
|
||||
>
|
||||
TDR
|
||||
</button>
|
||||
<button
|
||||
className={`p-2 text-white ${
|
||||
activeMode === "Schleife" ? "bg-blue-500" : "bg-gray-400"
|
||||
}`}
|
||||
onClick={() => setChartType("Schleife")}
|
||||
>
|
||||
Schleife
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{activeMode === "Schleife" ? (
|
||||
<>
|
||||
<h3 className="text-lg font-semibold">Schleifenmessung</h3>
|
||||
@@ -123,13 +161,7 @@ const ChartSwitcher: React.FC<ChartSwitcherProps> = ({ isOpen, onClose }) => {
|
||||
) : (
|
||||
<>
|
||||
<h3 className="text-lg font-semibold">TDR-Messung</h3>
|
||||
{/* TDR-Chart-Action-Bar */}
|
||||
{/* <TDRChartActionBar /> */}
|
||||
|
||||
{/* TDR-Chart */}
|
||||
<div style={{ flex: 1, height: "90%" }}>
|
||||
<TDRChart />
|
||||
</div>
|
||||
<TDRChart isFullScreen={isFullScreen} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ const LoopChartActionBar: React.FC = () => {
|
||||
if (!apiUrl) return;
|
||||
|
||||
try {
|
||||
console.log("📡 API-Request an:", apiUrl);
|
||||
// console.log("📡 API-Request an:", apiUrl);
|
||||
const response = await fetch(apiUrl, {
|
||||
method: "GET",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// components/main/kabelueberwachung/kue705FO/Charts/TDRChart/TDRChart.tsx
|
||||
"use client";
|
||||
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { RootState } from "../../../../../../redux/store";
|
||||
import { useSelector } from "react-redux";
|
||||
@@ -6,26 +8,22 @@ import { Chart, registerables } from "chart.js";
|
||||
import "chartjs-adapter-date-fns";
|
||||
import { getColor } from "../../../../../../utils/colors";
|
||||
|
||||
// 🟢 **Prop-Typ für isFullScreen hinzufügen**
|
||||
interface TDRChartProps {
|
||||
isFullScreen: boolean;
|
||||
}
|
||||
|
||||
const TDRChart: React.FC = () => {
|
||||
const isFullScreen = useSelector(
|
||||
(state: RootState) => state.kabelueberwachungChart.isFullScreen
|
||||
);
|
||||
|
||||
const TDRChart: React.FC<{ isFullScreen: boolean }> = ({ isFullScreen }) => {
|
||||
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||
const chartInstance = useRef<Chart | null>(null);
|
||||
|
||||
// TDR-Daten aus dem Redux Store selektieren
|
||||
const tdrChartData = useSelector(
|
||||
(state: any) => state.kabelueberwachungChart.tdrChartData
|
||||
// 🟢 **Hole den ausgewählten Slot und Messkurve aus Redux**
|
||||
const selectedSlot = useSelector(
|
||||
(state: RootState) => state.tdrChart.selectedSlot
|
||||
);
|
||||
const selectedChartType = useSelector(
|
||||
(state: RootState) => state.kueChartMode.activeMode
|
||||
);
|
||||
const tdrChartData = useSelector((state: RootState) =>
|
||||
selectedSlot !== null ? state.tdrChart.data[selectedSlot] || [] : []
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// Importiere und registriere das Zoom-Plugin innerhalb des useEffect-Hooks
|
||||
import("chartjs-plugin-zoom").then((zoomPlugin) => {
|
||||
Chart.register(...registerables, zoomPlugin.default);
|
||||
|
||||
@@ -41,15 +39,16 @@ const TDRChart: React.FC = () => {
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: "TDR Entfernung (km)",
|
||||
label: `Modul ${
|
||||
selectedSlot !== null ? selectedSlot + 1 : "?"
|
||||
} (${selectedChartType})`,
|
||||
data: tdrChartData,
|
||||
borderColor: getColor("littwin-blue"), // Nutzt automatisch die Tailwind-Farbe
|
||||
borderWidth: 0.5,
|
||||
//backgroundColor: getColor("littwin-blue"),
|
||||
borderColor: getColor("littwin-blue"),
|
||||
borderWidth: 1,
|
||||
tension: 0.1,
|
||||
parsing: {
|
||||
xAxisKey: "t", // Schlüssel für den Zeitstempel
|
||||
yAxisKey: "m", // Schlüssel für den Messwert
|
||||
xAxisKey: "t",
|
||||
yAxisKey: "m",
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -59,7 +58,7 @@ const TDRChart: React.FC = () => {
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
x: {
|
||||
type: "linear", // Lineare Skalierung für numerische Daten
|
||||
type: "linear",
|
||||
title: {
|
||||
display: true,
|
||||
text: "Entfernung (m)",
|
||||
@@ -94,7 +93,7 @@ const TDRChart: React.FC = () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [tdrChartData]);
|
||||
}, [tdrChartData, selectedSlot, selectedChartType]);
|
||||
|
||||
return (
|
||||
<div style={{ width: "100%", height: isFullScreen ? "90%" : "28rem" }}>
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
setChartOpen,
|
||||
setSlotNumber,
|
||||
} from "../../../../../redux/slices/kabelueberwachungChartSlice";
|
||||
import { setActiveMode } from "../../../../../redux/slices/kueChartModeSlice";
|
||||
import {
|
||||
setActiveMode,
|
||||
setSelectedSlot, // ✅ Importiere setSelectedSlot
|
||||
} from "../../../../../redux/slices/kueChartModeSlice";
|
||||
import { useDispatch } from "react-redux";
|
||||
|
||||
const handleOpenChartModal = (
|
||||
@@ -17,6 +20,9 @@ const handleOpenChartModal = (
|
||||
dispatch(setChartOpen(true));
|
||||
dispatch(setSlotNumber(slotIndex + 1));
|
||||
|
||||
// ✅ Speichert den gewählten Slot in Redux
|
||||
dispatch(setSelectedSlot(slotIndex));
|
||||
|
||||
if (activeButton === "TDR") {
|
||||
dispatch(setActiveMode("TDR"));
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// components/main/kabelueberwachung/kue705FO/kue705FO-Funktionen/handleButtonClick.ts
|
||||
import { Dispatch } from "react";
|
||||
import { setActiveMode } from "../../../../../redux/slices/kueChartModeSlice";
|
||||
import {
|
||||
setActiveMode,
|
||||
setSelectedSlot,
|
||||
} from "../../../../../redux/slices/kueChartModeSlice";
|
||||
|
||||
const handleButtonClick = (
|
||||
button: "Schleife" | "TDR",
|
||||
@@ -12,6 +15,9 @@ const handleButtonClick = (
|
||||
slotIndex: number,
|
||||
dispatch: Dispatch<any>
|
||||
) => {
|
||||
// 🔥 Speichert den gewählten Slot im Redux-Store
|
||||
dispatch(setSelectedSlot(slotIndex));
|
||||
|
||||
if (button === "Schleife") {
|
||||
setActiveButton("Schleife");
|
||||
setLoopTitleText("Schleifenwiderstand [kOhm]");
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
||||
|
||||
*/
|
||||
const webVersion = "1.6.137";
|
||||
const webVersion = "1.6.138";
|
||||
export default webVersion;
|
||||
|
||||
@@ -39,7 +39,7 @@ function AppContent({ Component, pageProps }: AppProps) {
|
||||
const variables = await loadWindowVariables();
|
||||
if (!variables) throw new Error("Sitzungsfehler");
|
||||
|
||||
console.log("✅ Window-Variablen geladen:", variables);
|
||||
//console.log("✅ Window-Variablen geladen:", variables);
|
||||
|
||||
const {
|
||||
last20Messages,
|
||||
|
||||
@@ -36,7 +36,7 @@ function Kabelueberwachung() {
|
||||
// Beim Laden der Seite TDR-Daten abrufen
|
||||
useEffect(() => {
|
||||
if (!tdrData || tdrData.length === 0) {
|
||||
console.log("TDR-Daten abrufen...");
|
||||
// console.log("TDR-Daten abrufen...");
|
||||
dispatch(fetchAllTDRChartData());
|
||||
}
|
||||
}, [dispatch, tdrData]);
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
|
||||
interface KueChartModeState {
|
||||
activeMode: "Schleife" | "TDR"; // 🔥 Neuer Zustand für den aktiven Modus
|
||||
activeMode: "Schleife" | "TDR"; // 🔥 Zustand für den aktiven Modus
|
||||
selectedSlot: number | null; // 🔥 Neu: Aktuell gewählter Slot
|
||||
}
|
||||
|
||||
const initialState: KueChartModeState = {
|
||||
activeMode: "Schleife", // Standard ist Schleife
|
||||
selectedSlot: null, // Standard: Kein Slot ausgewählt
|
||||
};
|
||||
|
||||
export const kueChartModeSlice = createSlice({
|
||||
@@ -16,8 +18,11 @@ export const kueChartModeSlice = createSlice({
|
||||
setActiveMode: (state, action: PayloadAction<"Schleife" | "TDR">) => {
|
||||
state.activeMode = action.payload; // 🔥 Speichert den Modus (Schleife oder TDR)
|
||||
},
|
||||
setSelectedSlot: (state, action: PayloadAction<number>) => {
|
||||
state.selectedSlot = action.payload; // 🔥 Speichert den aktiven Slot
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setActiveMode } = kueChartModeSlice.actions;
|
||||
export const { setActiveMode, setSelectedSlot } = kueChartModeSlice.actions;
|
||||
export default kueChartModeSlice.reducer;
|
||||
|
||||
@@ -4,12 +4,16 @@ import { fetchAllTDRChartData } from "../thunks/fetchAllTDRChartThunk";
|
||||
|
||||
interface TDRChartState {
|
||||
data: any[];
|
||||
selectedSlot: number | null;
|
||||
selectedChartType: "TDR" | "Schleife";
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
const initialState: TDRChartState = {
|
||||
data: [],
|
||||
selectedSlot: null,
|
||||
selectedChartType: "TDR",
|
||||
loading: false,
|
||||
error: null,
|
||||
};
|
||||
@@ -17,7 +21,17 @@ const initialState: TDRChartState = {
|
||||
const tdrChartSlice = createSlice({
|
||||
name: "tdrChart",
|
||||
initialState,
|
||||
reducers: {},
|
||||
reducers: {
|
||||
setSelectedSlot: (state, action: PayloadAction<number>) => {
|
||||
state.selectedSlot = action.payload;
|
||||
},
|
||||
setSelectedChartType: (
|
||||
state,
|
||||
action: PayloadAction<"TDR" | "Schleife">
|
||||
) => {
|
||||
state.selectedChartType = action.payload;
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder
|
||||
.addCase(fetchAllTDRChartData.pending, (state) => {
|
||||
@@ -28,7 +42,7 @@ const tdrChartSlice = createSlice({
|
||||
fetchAllTDRChartData.fulfilled,
|
||||
(state, action: PayloadAction<any[]>) => {
|
||||
state.loading = false;
|
||||
state.data = action.payload; // Speichere die neuen Daten in Redux
|
||||
state.data = action.payload;
|
||||
}
|
||||
)
|
||||
.addCase(fetchAllTDRChartData.rejected, (state, action) => {
|
||||
@@ -38,4 +52,5 @@ const tdrChartSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { setSelectedSlot, setSelectedChartType } = tdrChartSlice.actions;
|
||||
export default tdrChartSlice.reducer;
|
||||
|
||||
@@ -25,7 +25,7 @@ export const fetchAllTDRChartData = createAsyncThunk(
|
||||
|
||||
const newData = await Promise.all(fetchPromises);
|
||||
|
||||
console.log("Geladene Daten:", newData);
|
||||
//console.log("Geladene Daten:", newData);
|
||||
|
||||
// Falls die Daten leer oder identisch sind, aber initial leer waren, trotzdem speichern
|
||||
if (newData.every((d) => d === null || d === undefined)) {
|
||||
|
||||
@@ -21,7 +21,7 @@ export const fetchAnalogeEingaenge = async () => {
|
||||
const apiUrl = getApiUrl();
|
||||
if (!apiUrl) return null; // ❌ Falls SSR aktiv ist, nicht ausführen
|
||||
|
||||
console.log(`📡 API-Request an: ${apiUrl}`);
|
||||
// console.log(`📡 API-Request an: ${apiUrl}`);
|
||||
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
@@ -29,7 +29,7 @@ export const fetchAnalogeEingaenge = async () => {
|
||||
}
|
||||
|
||||
const rawData = await response.text();
|
||||
console.log("✅ Rohdaten erfolgreich geladen:", rawData);
|
||||
//console.log("✅ Rohdaten erfolgreich geladen:", rawData);
|
||||
|
||||
// **JavaScript-Variablen als Skript einfügen**
|
||||
const script = document.createElement("script");
|
||||
@@ -53,7 +53,7 @@ export const fetchAnalogeEingaenge = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ Formatierte Daten:", formattedData);
|
||||
// console.log("✅ Formatierte Daten:", formattedData);
|
||||
return formattedData;
|
||||
} catch (error) {
|
||||
console.error("❌ Fehler beim Laden der analogen Eingänge:", error);
|
||||
|
||||
@@ -20,14 +20,14 @@ export const fetchDigitaleEingaenge = async () => {
|
||||
const apiUrl = getApiUrl();
|
||||
if (!apiUrl) return null;
|
||||
|
||||
console.log(`📡 API-Request an: ${apiUrl}`);
|
||||
// console.log(`📡 API-Request an: ${apiUrl}`);
|
||||
const response = await fetch(apiUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`❌ Fehler: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
const rawData = await response.text();
|
||||
console.log("✅ Rohdaten erfolgreich geladen:", rawData);
|
||||
// console.log("✅ Rohdaten erfolgreich geladen:", rawData);
|
||||
|
||||
// **JavaScript-Variablen als Skript einfügen**
|
||||
const script = document.createElement("script");
|
||||
@@ -43,7 +43,7 @@ export const fetchDigitaleEingaenge = async () => {
|
||||
flutter: win_flutter[index] || 0,
|
||||
}));
|
||||
|
||||
console.log("✅ Formatierte Daten:", formattedData);
|
||||
// console.log("✅ Formatierte Daten:", formattedData);
|
||||
return formattedData;
|
||||
} catch (error) {
|
||||
console.error("❌ Fehler beim Laden der digitalen Eingänge:", error);
|
||||
|
||||
Reference in New Issue
Block a user