fix: window is not defined Fehler durch dynamischen Import von chartjs-plugin-zoom behoben
This commit is contained in:
@@ -1,10 +1,10 @@
|
|||||||
"use client"; // /components/modules/kue705FO/charts/ChartSwitcher.tsx
|
"use client"; // /components/modules/kue705FO/charts/ChartSwitcher.tsx
|
||||||
import dynamic from "next/dynamic";
|
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import ReactModal from "react-modal";
|
import ReactModal from "react-modal";
|
||||||
import LoopChartActionBar from "./LoopMeasurementChart/LoopChartActionBar";
|
import LoopChartActionBar from "./LoopMeasurementChart/LoopChartActionBar";
|
||||||
import TDRChartActionBar from "./TDRChart/TDRChartActionBar";
|
import TDRChartActionBar from "./TDRChart/TDRChartActionBar";
|
||||||
|
import LoopMeasurementChart from "./LoopMeasurementChart/LoopMeasurementChart";
|
||||||
import TDRChart from "./TDRChart/TDRChart";
|
import TDRChart from "./TDRChart/TDRChart";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
import { useSelector, useDispatch } from "react-redux";
|
||||||
import { AppDispatch } from "../../../../../redux/store";
|
import { AppDispatch } from "../../../../../redux/store";
|
||||||
@@ -31,10 +31,6 @@ const ChartSwitcher: React.FC<ChartSwitcherProps> = ({
|
|||||||
onClose,
|
onClose,
|
||||||
slotIndex,
|
slotIndex,
|
||||||
}) => {
|
}) => {
|
||||||
const LoopMeasurementChart = dynamic(
|
|
||||||
() => import("./LoopMeasurementChart/LoopMeasurementChart.client"),
|
|
||||||
{ ssr: false }
|
|
||||||
);
|
|
||||||
const dispatch = useDispatch<AppDispatch>();
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
const chartTitle = useSelector(
|
const chartTitle = useSelector(
|
||||||
(state: RootState) => state.loopChartType.chartTitle
|
(state: RootState) => state.loopChartType.chartTitle
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -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;
|
||||||
@@ -6,5 +6,5 @@
|
|||||||
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
2: Patch oder Hotfix (Bugfixes oder kleine Änderungen).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
const webVersion = "1.6.200";
|
const webVersion = "1.6.201";
|
||||||
export default webVersion;
|
export default webVersion;
|
||||||
|
|||||||
Reference in New Issue
Block a user