feat: Struktur für Charts verbessert und Komponenten getrennt
- `LoopMeasurementChart.tsx` und `TDRChart.tsx` erstellt für separate Diagramm-Darstellungen. - Neue Struktur unter `/components/modules/kue705FO/charts/` eingeführt. - `ChartModal.tsx` bleibt für generelle Nutzung erhalten. - Erhöhte Wartbarkeit und Modularität durch Trennung der Chart-Komponenten.
This commit is contained in:
@@ -3,13 +3,13 @@ import { render, fireEvent, screen } from "@testing-library/react";
|
|||||||
import configureStore from "redux-mock-store";
|
import configureStore from "redux-mock-store";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import "@testing-library/jest-dom";
|
import "@testing-library/jest-dom";
|
||||||
import Kue705FO from "../../../components/modules/Kue705FO";
|
import Kue705FO from "../../../components/modules/kue705FO/Kue705FO";
|
||||||
|
|
||||||
// Mocks für externe Abhängigkeiten
|
// Mocks für externe Abhängigkeiten
|
||||||
jest.mock("chart.js/auto", () => ({
|
jest.mock("chart.js/auto", () => ({
|
||||||
default: {
|
default: {
|
||||||
register: jest.fn(),
|
register: jest.fn(),
|
||||||
},
|
},
|
||||||
Chart: jest.fn().mockImplementation(() => ({
|
Chart: jest.fn().mockImplementation(() => ({
|
||||||
destroy: jest.fn(),
|
destroy: jest.fn(),
|
||||||
update: jest.fn(),
|
update: jest.fn(),
|
||||||
|
|||||||
@@ -1,66 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import ReactModal from "react-modal";
|
|
||||||
import TDRPopup from "./LoopTDRChartActionBar";
|
|
||||||
|
|
||||||
interface ChartModalProps {
|
|
||||||
isOpen: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
chartRef: React.RefObject<HTMLCanvasElement>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ChartModal: React.FC<ChartModalProps> = ({
|
|
||||||
isOpen,
|
|
||||||
onClose,
|
|
||||||
chartRef,
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<ReactModal
|
|
||||||
isOpen={isOpen}
|
|
||||||
onRequestClose={onClose}
|
|
||||||
ariaHideApp={false}
|
|
||||||
style={{
|
|
||||||
overlay: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
|
|
||||||
content: {
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
right: "auto",
|
|
||||||
bottom: "auto",
|
|
||||||
marginRight: "-50%",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
width: "80%",
|
|
||||||
maxWidth: "50rem",
|
|
||||||
height: "30rem",
|
|
||||||
padding: "1rem",
|
|
||||||
overflow: "hidden",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
onClick={onClose}
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: "0.625rem",
|
|
||||||
right: "0.625rem",
|
|
||||||
background: "transparent",
|
|
||||||
border: "none",
|
|
||||||
fontSize: "1.5rem",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<i className="bi bi-x-circle-fill"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div style={{ maxHeight: "100%", overflow: "auto" }}>
|
|
||||||
<TDRPopup />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<canvas
|
|
||||||
id="myChart"
|
|
||||||
ref={chartRef}
|
|
||||||
style={{ width: "100%", height: "20rem" }}
|
|
||||||
></canvas>
|
|
||||||
</ReactModal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ChartModal;
|
|
||||||
@@ -4,10 +4,12 @@ import { useState, useEffect } from "react";
|
|||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import { setVariables } from "../../../redux/slices/variablesSlice";
|
import { setVariables } from "../../../redux/slices/variablesSlice";
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
||||||
import handleSave, { OriginalValues } from "./handlers/handleSave";
|
import handleSave, {
|
||||||
import handleDisplayEinschalten from "./handlers/handleDisplayEinschalten";
|
OriginalValues,
|
||||||
import handleChange from "./handlers/handleChange";
|
} from "../../modules/kue705FO/handlers/handleSave";
|
||||||
import firmwareUpdate from "./handlers/firmwareUpdate";
|
import handleDisplayEinschalten from "../../modules/kue705FO/handlers/handleDisplayEinschalten";
|
||||||
|
import handleChange from "../../modules/kue705FO/handlers/handleChange";
|
||||||
|
import firmwareUpdate from "../../modules/kue705FO/handlers/firmwareUpdate";
|
||||||
import decodeToken from "../../../utils/decodeToken";
|
import decodeToken from "../../../utils/decodeToken";
|
||||||
// Props-Typen definieren
|
// Props-Typen definieren
|
||||||
interface KueModalProps {
|
interface KueModalProps {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import DateRangePicker from "./DateRangePicker";
|
import DateRangePicker from "./DateRangePicker";
|
||||||
import ChartModal from "./ChartModal"; // Importiere das Chart-Modal
|
import ChartModal from "../../modules/kue705FO/charts/ChartModal"; // Importiere das Chart-Modal
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
import { setChartData } from "../../../redux/slices/chartDataSlice";
|
import { setChartData } from "../../../redux/slices/chartDataSlice";
|
||||||
import { RootState } from "../../../redux/store";
|
import { RootState } from "../../../redux/store";
|
||||||
@@ -93,6 +93,7 @@ const LoopTDRChartActionBar: React.FC = () => {
|
|||||||
<ChartModal
|
<ChartModal
|
||||||
isOpen={showChartModal}
|
isOpen={showChartModal}
|
||||||
onClose={() => setShowChartModal(false)}
|
onClose={() => setShowChartModal(false)}
|
||||||
|
chartRef={React.createRef<HTMLCanvasElement>()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,24 +3,25 @@ import React, { useState, useEffect, useRef } from "react";
|
|||||||
import ReactModal from "react-modal";
|
import ReactModal from "react-modal";
|
||||||
import Chart from "chart.js/auto";
|
import Chart from "chart.js/auto";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import KueModal from "../modales/kueModal/KueModal";
|
import KueModal from "../../modales/kueModal/KueModal";
|
||||||
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
import "bootstrap-icons/font/bootstrap-icons.css"; // Import Bootstrap Icons
|
||||||
import { RootState } from "../../redux/store";
|
import { RootState } from "../../../redux/store";
|
||||||
import { DataTDR } from "../../redux/types/chartDataTypesTDR";
|
import { DataTDR } from "../../../redux/types/chartDataTypesTDR";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import {
|
import {
|
||||||
setSelectedChartData,
|
setSelectedChartData,
|
||||||
setSelectedFileName,
|
setSelectedFileName,
|
||||||
} from "../../redux/slices/variablesSlice";
|
} from "../../../redux/slices/variablesSlice";
|
||||||
import TDRPopup from "../modales/kueModal/LoopTDRChartActionBar";
|
import TDRPopup from "../../modales/kueModal/LoopTDRChartActionBar";
|
||||||
import { createLoopChart, createTDRChart } from "../../utils/chartUtils";
|
import { createLoopChart, createTDRChart } from "../../../utils/chartUtils";
|
||||||
import { getAlarmDisplayText } from "../../utils/alarmUtils";
|
import { getAlarmDisplayText } from "../../../utils/alarmUtils";
|
||||||
import { goLoop } from "../../utils/goLoop";
|
import { goLoop } from "../../../utils/goLoop";
|
||||||
import { goTDR } from "../../utils/goTDR";
|
import { goTDR } from "../../../utils/goTDR";
|
||||||
import { loadTDRChartData } from "../../utils/loadTDRChartData";
|
import { loadTDRChartData } from "../../../utils/loadTDRChartData";
|
||||||
import { loadLoopChartData } from "../../utils/loadLoopChartData";
|
import { loadLoopChartData } from "../../../utils/loadLoopChartData";
|
||||||
import { Kue705FOProps } from "../../types/components/Kue705FOProps";
|
import { Kue705FOProps } from "../../../types/components/Kue705FOProps";
|
||||||
import ChartModal from "../modales/kueModal/ChartModal";
|
import ChartModal from "./charts/ChartModal";
|
||||||
|
import { setActiveMode } from "../../../redux/slices/chartDataSlice";
|
||||||
|
|
||||||
const Kue705FO: React.FC<Kue705FOProps> = ({
|
const Kue705FO: React.FC<Kue705FOProps> = ({
|
||||||
isolationswert,
|
isolationswert,
|
||||||
@@ -102,6 +103,7 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
|
|||||||
setActiveButton("Schleife");
|
setActiveButton("Schleife");
|
||||||
setloopTitleText("Schleifenwiderstand [kOhm]");
|
setloopTitleText("Schleifenwiderstand [kOhm]");
|
||||||
setLoopDisplayValue(schleifenwiderstand); // Setze den Wert auf schleifenwiderstand
|
setLoopDisplayValue(schleifenwiderstand); // Setze den Wert auf schleifenwiderstand
|
||||||
|
dispatch(setActiveMode("Schleife")); // 🔥 Speichert den Modus in Redux
|
||||||
} else if (button === "TDR") {
|
} else if (button === "TDR") {
|
||||||
setActiveButton("TDR");
|
setActiveButton("TDR");
|
||||||
setloopTitleText("Entfernung [Km]");
|
setloopTitleText("Entfernung [Km]");
|
||||||
@@ -110,6 +112,7 @@ const Kue705FO: React.FC<Kue705FOProps> = ({
|
|||||||
? tdrLocation[slotIndex]
|
? tdrLocation[slotIndex]
|
||||||
: "0"
|
: "0"
|
||||||
); // Setze den Wert auf tdrLocation oder "0" als Fallback
|
); // Setze den Wert auf tdrLocation oder "0" als Fallback
|
||||||
|
dispatch(setActiveMode("TDR")); // 🔥 Speichert den Modus in Redux
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
171
components/modules/kue705FO/charts/ChartModal.tsx
Normal file
171
components/modules/kue705FO/charts/ChartModal.tsx
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import ReactModal from "react-modal";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { RootState } from "../../../../redux/store";
|
||||||
|
import Chart from "chart.js/auto";
|
||||||
|
import "chartjs-adapter-date-fns";
|
||||||
|
import { parseISO } from "date-fns";
|
||||||
|
import LoopTDRPopup from "../../../modales/kueModal/LoopTDRChartActionBar";
|
||||||
|
|
||||||
|
interface ChartModalProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChartModal: React.FC<ChartModalProps> = ({ isOpen, onClose }) => {
|
||||||
|
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const chartInstance = useRef<Chart | null>(null);
|
||||||
|
|
||||||
|
// Redux State abrufen
|
||||||
|
const chartData = useSelector((state: RootState) => state.chartData.data);
|
||||||
|
const activeMode = useSelector(
|
||||||
|
(state: RootState) => state.chartData.activeMode
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (chartRef.current && chartData.length > 0) {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = chartRef.current.getContext("2d");
|
||||||
|
if (ctx) {
|
||||||
|
const labels = chartData.map((entry) =>
|
||||||
|
entry.timestamp ? parseISO(entry.timestamp) : new Date()
|
||||||
|
);
|
||||||
|
|
||||||
|
chartInstance.current = new Chart(ctx, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Isolationswiderstand (MOhm)",
|
||||||
|
data: chartData.map((entry) => entry.isolation ?? 0),
|
||||||
|
borderColor: "rgba(0, 123, 255, 1)",
|
||||||
|
backgroundColor: "rgba(0, 123, 255, 0.2)",
|
||||||
|
tension: 0.1,
|
||||||
|
yAxisID: "y-left",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Schleifenwiderstand (kOhm)",
|
||||||
|
data: chartData.map((entry) => entry.loop ?? 0),
|
||||||
|
borderColor: "rgba(108, 117, 125, 1)",
|
||||||
|
backgroundColor: "rgba(108, 117, 125, 0.2)",
|
||||||
|
tension: 0.1,
|
||||||
|
yAxisID: "y-right",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: "time",
|
||||||
|
time: {
|
||||||
|
unit: "hour",
|
||||||
|
tooltipFormat: "dd.MM.yyyy HH:mm",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Zeit",
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
drawBorder: true, // 🔥 Stellt sicher, dass die X-Achse sichtbar ist
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
id: "y-left",
|
||||||
|
position: "left",
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "MOhm",
|
||||||
|
},
|
||||||
|
min: 0,
|
||||||
|
max:
|
||||||
|
Math.max(...chartData.map((entry) => entry.isolation ?? 1)) +
|
||||||
|
10,
|
||||||
|
grid: {
|
||||||
|
drawOnChartArea: true, // 🔥 Korrektur, damit es sich nicht überlagert
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"y-right": {
|
||||||
|
id: "y-right",
|
||||||
|
position: "right",
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "kOhm",
|
||||||
|
},
|
||||||
|
min: 0,
|
||||||
|
max: Math.max(...chartData.map((entry) => entry.loop ?? 1)) + 1,
|
||||||
|
grid: {
|
||||||
|
drawOnChartArea: false, // 🔥 Verhindert doppelte Linien
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy();
|
||||||
|
chartInstance.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [chartData, activeMode]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactModal
|
||||||
|
isOpen={isOpen}
|
||||||
|
onRequestClose={onClose}
|
||||||
|
ariaHideApp={false}
|
||||||
|
style={{
|
||||||
|
overlay: { backgroundColor: "rgba(0, 0, 0, 0.5)" },
|
||||||
|
content: {
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
right: "auto",
|
||||||
|
bottom: "auto",
|
||||||
|
marginRight: "-50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
width: "80%",
|
||||||
|
maxWidth: "50rem",
|
||||||
|
height: "30rem",
|
||||||
|
padding: "1rem",
|
||||||
|
overflow: "hidden",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
onClick={onClose}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "0.625rem",
|
||||||
|
right: "0.625rem",
|
||||||
|
background: "transparent",
|
||||||
|
border: "none",
|
||||||
|
fontSize: "1.5rem",
|
||||||
|
cursor: "pointer",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="bi bi-x-circle-fill"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Beibehaltung der UI mit Kalender und Buttons */}
|
||||||
|
<div style={{ maxHeight: "100%", overflow: "auto" }}>
|
||||||
|
<LoopTDRPopup />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Canvas für das Chart */}
|
||||||
|
<canvas
|
||||||
|
ref={chartRef}
|
||||||
|
style={{ width: "100%", height: "20rem", marginTop: "1rem" }}
|
||||||
|
></canvas>
|
||||||
|
</ReactModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ChartModal;
|
||||||
110
components/modules/kue705FO/charts/LoopMeasurementChart.tsx
Normal file
110
components/modules/kue705FO/charts/LoopMeasurementChart.tsx
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { RootState } from "../../../redux/store";
|
||||||
|
import Chart from "chart.js/auto";
|
||||||
|
import "chartjs-adapter-date-fns";
|
||||||
|
import { parseISO } from "date-fns";
|
||||||
|
|
||||||
|
const LoopMeasurementChart: React.FC = () => {
|
||||||
|
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const chartInstance = useRef<Chart | null>(null);
|
||||||
|
|
||||||
|
// Redux-Daten abrufen
|
||||||
|
const chartData = useSelector((state: RootState) => state.chartData.data);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (chartRef.current && chartData.length > 0) {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy(); // Bestehendes Chart zerstören
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = chartRef.current.getContext("2d");
|
||||||
|
if (ctx) {
|
||||||
|
const labels = chartData.map((entry) =>
|
||||||
|
entry.timestamp ? parseISO(entry.timestamp) : new Date()
|
||||||
|
);
|
||||||
|
|
||||||
|
chartInstance.current = new Chart(ctx, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Schleifenwiderstand (kOhm)",
|
||||||
|
data: chartData.map((entry) => entry.loop ?? 0),
|
||||||
|
borderColor: "rgba(75, 192, 192, 1)", // Türkis
|
||||||
|
backgroundColor: "rgba(75, 192, 192, 0.2)",
|
||||||
|
tension: 0.1,
|
||||||
|
yAxisID: "y-left",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Zusätzliche Schleifenmesswerte",
|
||||||
|
data: chartData.map((entry) => entry.additional ?? 0),
|
||||||
|
borderColor: "rgba(255, 159, 64, 1)", // Orange
|
||||||
|
backgroundColor: "rgba(255, 159, 64, 0.2)",
|
||||||
|
tension: 0.1,
|
||||||
|
yAxisID: "y-right",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: "time",
|
||||||
|
time: {
|
||||||
|
unit: "hour",
|
||||||
|
tooltipFormat: "dd.MM.yyyy HH:mm",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Zeit",
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
drawBorder: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
id: "y-left",
|
||||||
|
position: "left",
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "kOhm",
|
||||||
|
},
|
||||||
|
min: 0,
|
||||||
|
max: Math.max(...chartData.map((entry) => entry.loop ?? 1)) + 1,
|
||||||
|
},
|
||||||
|
"y-right": {
|
||||||
|
id: "y-right",
|
||||||
|
position: "right",
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: "Zusätzliche Werte",
|
||||||
|
},
|
||||||
|
min: 0,
|
||||||
|
max:
|
||||||
|
Math.max(...chartData.map((entry) => entry.additional ?? 1)) +
|
||||||
|
1,
|
||||||
|
grid: {
|
||||||
|
drawOnChartArea: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy();
|
||||||
|
chartInstance.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [chartData]);
|
||||||
|
|
||||||
|
return <canvas ref={chartRef} style={{ width: "100%", height: "20rem" }} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoopMeasurementChart;
|
||||||
71
components/modules/kue705FO/charts/TDRChart.tsx
Normal file
71
components/modules/kue705FO/charts/TDRChart.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
import { RootState } from "../../../redux/store";
|
||||||
|
import Chart from "chart.js/auto";
|
||||||
|
import "chartjs-adapter-date-fns";
|
||||||
|
import { parseISO } from "date-fns";
|
||||||
|
|
||||||
|
const TDRChart: React.FC = () => {
|
||||||
|
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||||
|
const chartInstance = useRef<Chart | null>(null);
|
||||||
|
const chartData = useSelector((state: RootState) => state.chartData.data);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (chartRef.current && chartData.length > 0) {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctx = chartRef.current.getContext("2d");
|
||||||
|
if (ctx) {
|
||||||
|
chartInstance.current = new Chart(ctx, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: chartData.map((entry) => parseISO(entry.timestamp)),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Isolationswiderstand (MOhm)",
|
||||||
|
data: chartData.map((entry) => entry.isolation ?? 0),
|
||||||
|
borderColor: "rgba(0, 123, 255, 1)",
|
||||||
|
backgroundColor: "rgba(0, 123, 255, 0.2)",
|
||||||
|
tension: 0.1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: "time",
|
||||||
|
time: {
|
||||||
|
unit: "hour",
|
||||||
|
tooltipFormat: "dd.MM.yyyy HH:mm",
|
||||||
|
},
|
||||||
|
title: { display: true, text: "Zeit" },
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
title: { display: true, text: "MOhm" },
|
||||||
|
min: 0,
|
||||||
|
max:
|
||||||
|
Math.max(...chartData.map((entry) => entry.isolation ?? 1)) +
|
||||||
|
10,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (chartInstance.current) {
|
||||||
|
chartInstance.current.destroy();
|
||||||
|
chartInstance.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [chartData]);
|
||||||
|
|
||||||
|
return <canvas ref={chartRef} style={{ width: "100%", height: "20rem" }} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TDRChart;
|
||||||
@@ -5,5 +5,5 @@
|
|||||||
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
const webVersion = "1.0.6.9";
|
const webVersion = "1.0.6.10";
|
||||||
export default webVersion;
|
export default webVersion;
|
||||||
|
|||||||
20
package-lock.json
generated
20
package-lock.json
generated
@@ -17,6 +17,7 @@
|
|||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"chart.js": "^4.4.5",
|
"chart.js": "^4.4.5",
|
||||||
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
"chartjs-plugin-zoom": "^2.0.1",
|
"chartjs-plugin-zoom": "^2.0.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"next": "^14.2.23",
|
"next": "^14.2.23",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-chartjs-2": "^5.3.0",
|
||||||
"react-date-picker": "^11.0.0",
|
"react-date-picker": "^11.0.0",
|
||||||
"react-datepicker": "^8.0.0",
|
"react-datepicker": "^8.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
@@ -2606,6 +2608,15 @@
|
|||||||
"pnpm": ">=8"
|
"pnpm": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chartjs-adapter-date-fns": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": ">=2.8.0",
|
||||||
|
"date-fns": ">=2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chartjs-plugin-zoom": {
|
"node_modules/chartjs-plugin-zoom": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-2.2.0.tgz",
|
||||||
@@ -6892,6 +6903,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-chartjs-2": {
|
||||||
|
"version": "5.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
|
||||||
|
"integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": "^4.1.1",
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-date-picker": {
|
"node_modules/react-date-picker": {
|
||||||
"version": "11.0.0",
|
"version": "11.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-11.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-date-picker/-/react-date-picker-11.0.0.tgz",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"bootstrap-icons": "^1.11.3",
|
"bootstrap-icons": "^1.11.3",
|
||||||
"chart.js": "^4.4.5",
|
"chart.js": "^4.4.5",
|
||||||
|
"chartjs-adapter-date-fns": "^3.0.0",
|
||||||
"chartjs-plugin-zoom": "^2.0.1",
|
"chartjs-plugin-zoom": "^2.0.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"next": "^14.2.23",
|
"next": "^14.2.23",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
"react-chartjs-2": "^5.3.0",
|
||||||
"react-date-picker": "^11.0.0",
|
"react-date-picker": "^11.0.0",
|
||||||
"react-datepicker": "^8.0.0",
|
"react-datepicker": "^8.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import Kue705FO from "../components/modules/Kue705FO";
|
import Kue705FO from "../components/modules/kue705FO/Kue705FO";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
function Kabelueberwachung() {
|
function Kabelueberwachung() {
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
|||||||
|
|
||||||
interface ChartDataState {
|
interface ChartDataState {
|
||||||
data: any[];
|
data: any[];
|
||||||
|
activeMode: "Schleife" | "TDR"; // 🔥 Neuer Zustand für den aktiven Modus
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: ChartDataState = {
|
const initialState: ChartDataState = {
|
||||||
data: [],
|
data: [],
|
||||||
|
activeMode: "Schleife", // Standard ist Schleife
|
||||||
};
|
};
|
||||||
|
|
||||||
export const chartDataSlice = createSlice({
|
export const chartDataSlice = createSlice({
|
||||||
@@ -18,8 +20,12 @@ export const chartDataSlice = createSlice({
|
|||||||
clearChartData: (state) => {
|
clearChartData: (state) => {
|
||||||
state.data = [];
|
state.data = [];
|
||||||
},
|
},
|
||||||
|
setActiveMode: (state, action: PayloadAction<"Schleife" | "TDR">) => {
|
||||||
|
state.activeMode = action.payload; // 🔥 Speichert den Modus (Schleife oder TDR)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setChartData, clearChartData } = chartDataSlice.actions;
|
export const { setChartData, clearChartData, setActiveMode } =
|
||||||
|
chartDataSlice.actions;
|
||||||
export default chartDataSlice.reducer;
|
export default chartDataSlice.reducer;
|
||||||
|
|||||||
Reference in New Issue
Block a user