fix: window is not defined Fehler durch dynamischen Import von chartjs-plugin-zoom behoben

This commit is contained in:
ISA
2025-04-02 08:57:07 +02:00
parent 3aac69954a
commit 9de6ac10c4
4 changed files with 175 additions and 169 deletions

View File

@@ -1,10 +1,10 @@
"use client"; // /components/modules/kue705FO/charts/ChartSwitcher.tsx
import dynamic from "next/dynamic";
import React, { useState, useEffect } from "react";
import ReactModal from "react-modal";
import LoopChartActionBar from "./LoopMeasurementChart/LoopChartActionBar";
import TDRChartActionBar from "./TDRChart/TDRChartActionBar";
import LoopMeasurementChart from "./LoopMeasurementChart/LoopMeasurementChart";
import TDRChart from "./TDRChart/TDRChart";
import { useSelector, useDispatch } from "react-redux";
import { AppDispatch } from "../../../../../redux/store";
@@ -31,10 +31,6 @@ const ChartSwitcher: React.FC<ChartSwitcherProps> = ({
onClose,
slotIndex,
}) => {
const LoopMeasurementChart = dynamic(
() => import("./LoopMeasurementChart/LoopMeasurementChart.client"),
{ ssr: false }
);
const dispatch = useDispatch<AppDispatch>();
const chartTitle = useSelector(
(state: RootState) => state.loopChartType.chartTitle

View File

@@ -1,163 +0,0 @@
"use client";
import React, { useEffect, useRef } from "react";
import { useSelector } from "react-redux";
import { RootState } from "../../../../../../redux/store";
import {
Chart as ChartJS,
LineElement,
PointElement,
LinearScale,
TimeScale,
Title,
Tooltip,
Legend,
Filler,
} from "chart.js";
import zoomPlugin from "chartjs-plugin-zoom";
import "chartjs-adapter-date-fns";
import { de } from "date-fns/locale";
ChartJS.register(
LineElement,
PointElement,
LinearScale,
TimeScale,
Title,
Tooltip,
Legend,
Filler,
zoomPlugin
);
const LoopMeasurementChart = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const chartInstance = useRef<ChartJS | null>(null);
const { loopMeasurementCurveChartData, selectedMode, unit, isFullScreen } =
useSelector((state: RootState) => state.kabelueberwachungChartSlice);
useEffect(() => {
if (!canvasRef.current) return;
const ctx = canvasRef.current.getContext("2d");
if (!ctx) return;
const chartData = {
labels: loopMeasurementCurveChartData
.map((entry) => new Date(entry.t))
.reverse(),
datasets: [
{
label: "Messwert Minimum",
data: loopMeasurementCurveChartData.map((e) => e.i).reverse(),
borderColor: "lightgrey",
borderWidth: 1,
fill: false,
pointRadius: 0,
},
selectedMode === "DIA0"
? {
label: "Messwert",
data: loopMeasurementCurveChartData.map((e) => e.m).reverse(),
borderColor: "#00AEEF",
borderWidth: 2,
fill: false,
pointRadius: 2,
}
: {
label: "Messwert Durchschnitt",
data: loopMeasurementCurveChartData.map((e) => e.g).reverse(),
borderColor: "#00AEEF",
borderWidth: 2,
fill: false,
pointRadius: 2,
},
{
label: "Messwert Maximum",
data: loopMeasurementCurveChartData.map((e) => e.a).reverse(),
borderColor: "lightgrey",
borderWidth: 1,
fill: false,
pointRadius: 0,
},
],
};
const options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: "top" as const,
},
tooltip: {
mode: "index" as const,
intersect: false,
},
zoom: {
pan: {
enabled: true,
mode: "x" as const,
},
zoom: {
wheel: {
enabled: true,
},
pinch: {
enabled: true,
},
mode: "x" as const,
},
},
},
scales: {
x: {
type: "time" as const,
time: {
unit: "day" as const,
tooltipFormat: "dd.MM.yyyy HH:mm",
displayFormats: {
day: "dd.MM",
},
},
title: {
display: true,
text: "Zeit",
},
// Hier Deutsch setzen:
locale: de,
},
y: {
title: {
display: true,
text: unit,
},
ticks: {
precision: 0,
},
},
},
};
if (chartInstance.current) {
chartInstance.current.destroy();
}
chartInstance.current = new ChartJS(ctx, {
type: "line",
data: chartData,
options,
});
// Kein Cleanup mit Destroy, damit Zoom erhalten bleibt
}, [loopMeasurementCurveChartData, selectedMode]);
return (
<div style={{ width: "100%", height: isFullScreen ? "90%" : "400px" }}>
<canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />
</div>
);
};
export default LoopMeasurementChart;

View File

@@ -0,0 +1,173 @@
"use client";
import React, { useEffect, useRef } from "react";
import { useSelector } from "react-redux";
import { RootState } from "../../../../../../redux/store";
import {
Chart as ChartJS,
LineElement,
PointElement,
LinearScale,
TimeScale,
Title,
Tooltip,
Legend,
Filler,
} from "chart.js";
import "chartjs-adapter-date-fns";
import { de } from "date-fns/locale";
ChartJS.register(
LineElement,
PointElement,
LinearScale,
TimeScale,
Title,
Tooltip,
Legend,
Filler
);
const usePreviousData = (data: any[]) => {
const ref = useRef<any[]>([]);
useEffect(() => {
ref.current = data;
}, [data]);
return ref.current;
};
const LoopMeasurementChart = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const chartInstance = useRef<ChartJS | null>(null);
const { loopMeasurementCurveChartData, selectedMode, unit, isFullScreen } =
useSelector((state: RootState) => state.kabelueberwachungChartSlice);
const previousData = usePreviousData(loopMeasurementCurveChartData);
// Vergleichsfunktion
const isEqual = (a: any[], b: any[]): boolean => {
if (a.length !== b.length) return false;
for (let i = 0; i < a.length; i++) {
if (
a[i].t !== b[i].t ||
a[i].i !== b[i].i ||
a[i].m !== b[i].m ||
a[i].g !== b[i].g ||
a[i].a !== b[i].a
) {
return false;
}
}
return true;
};
useEffect(() => {
import("chartjs-plugin-zoom").then((zoomPlugin) => {
if (!ChartJS.registry.plugins.get("zoom")) {
ChartJS.register(zoomPlugin.default);
}
if (!canvasRef.current) return;
const ctx = canvasRef.current.getContext("2d");
if (!ctx) return;
if (isEqual(loopMeasurementCurveChartData, previousData)) {
return; // keine echte Datenänderung → nicht neu zeichnen
}
if (chartInstance.current) {
chartInstance.current.destroy();
}
const chartData = {
labels: loopMeasurementCurveChartData
.map((entry) => new Date(entry.t))
.reverse(),
datasets: [
{
label: "Messwert Minimum",
data: loopMeasurementCurveChartData.map((e) => e.i).reverse(),
borderColor: "lightgrey",
borderWidth: 1,
fill: false,
pointRadius: 0,
},
selectedMode === "DIA0"
? {
label: "Messwert",
data: loopMeasurementCurveChartData.map((e) => e.m).reverse(),
borderColor: "#00AEEF",
borderWidth: 2,
fill: false,
pointRadius: 2,
}
: {
label: "Messwert Durchschnitt",
data: loopMeasurementCurveChartData.map((e) => e.g).reverse(),
borderColor: "#00AEEF",
borderWidth: 2,
fill: false,
pointRadius: 2,
},
{
label: "Messwert Maximum",
data: loopMeasurementCurveChartData.map((e) => e.a).reverse(),
borderColor: "lightgrey",
borderWidth: 1,
fill: false,
pointRadius: 0,
},
],
};
const options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: "top" as const },
tooltip: { mode: "index" as const, intersect: false },
zoom: {
pan: { enabled: true, mode: "x" as const },
zoom: {
wheel: { enabled: true },
pinch: { enabled: true },
mode: "x" as const,
},
},
},
scales: {
x: {
type: "time" as const,
time: {
unit: "day" as const,
tooltipFormat: "dd.MM.yyyy HH:mm",
displayFormats: { day: "dd.MM" },
locale: de,
},
title: { display: true, text: "Zeit" },
},
y: {
title: { display: true, text: unit },
ticks: { precision: 0 },
},
},
};
chartInstance.current = new ChartJS(ctx, {
type: "line",
data: chartData,
options,
});
});
}, [loopMeasurementCurveChartData, selectedMode]);
return (
<div style={{ width: "100%", height: isFullScreen ? "90%" : "400px" }}>
<canvas ref={canvasRef} style={{ width: "100%", height: "100%" }} />
</div>
);
};
export default LoopMeasurementChart;

View File

@@ -6,5 +6,5 @@
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
*/
const webVersion = "1.6.200";
const webVersion = "1.6.201";
export default webVersion;