This commit is contained in:
Ismail Ali
2025-06-26 22:56:20 +02:00
parent 137839da98
commit b9651a53a9
82 changed files with 7476 additions and 4171 deletions

View File

@@ -5,7 +5,6 @@ import { useEffect, useState } from "react";
import { Provider } from "react-redux";
import store, { useAppDispatch } from "@/redux/store";
import { AppProps } from "next/app";
import { loadWindowVariables } from "@/utils/loadWindowVariables";
import Header from "@/components/header/Header";
import Navigation from "@/components/navigation/Navigation";
@@ -43,7 +42,7 @@ function AppContent({
pageProps: AppProps["pageProps"];
}): JSX.Element {
const dispatch = useAppDispatch();
const [sessionExpired, setSessionExpired] = useState(false);
const [sessionExpired] = useState(false);
const mode = "DIA0"; // oder aus Router oder Session
const type = 0; // Beispiel: 0 für "loop", 1 für "iso" (bitte ggf. anpassen)
useEffect(() => {
@@ -93,7 +92,7 @@ function AppContent({
intervalId = setInterval(loadAndDispatch, 10000);
return () => clearInterval(intervalId);
}
}, []);
}, [dispatch]);
return (
<div className="flex flex-col h-screen overflow-hidden">

View File

@@ -1,14 +1,23 @@
"use client"; ///pages/analogeEingaenge.tsx
import React, { useState, useEffect } from "react";
import AnalogInputsTable from "../components/main/analogInputs/AnalogInputsTable";
import AnalogInputsChart from "../components/main/analogInputs/AnalogInputsChart";
import AnalogInputsSettingsModal from "../components/main/analogInputs/AnalogInputsSettingsModal";
import { getAnalogInputsThunk } from "../redux/thunks/getAnalogInputsThunk";
import { useAppDispatch } from "../redux/store";
import AnalogInputsTable from "@/components/main/analogInputs/AnalogInputsTable";
import AnalogInputsChart from "@/components/main/analogInputs/AnalogInputsChart";
import AnalogInputsSettingsModal from "@/components/main/analogInputs/AnalogInputsSettingsModal";
import { getAnalogInputsThunk } from "@/redux/thunks/getAnalogInputsThunk";
import { useAppDispatch } from "@/redux/store";
export interface AnalogInput2 {
id: number;
label?: string;
offset?: number | string;
factor?: number | string;
loggerInterval: string;
unit?: string;
}
function AnalogInputs() {
const [selectedId, setSelectedId] = useState<number | null>(null);
const [selectedInput, setSelectedInput] = useState<any | null>(null);
const [selectedInput, setSelectedInput] = useState<AnalogInput2 | null>(null);
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
const dispatch = useAppDispatch();
@@ -26,18 +35,20 @@ function AnalogInputs() {
<div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)]">
<div className="container mx-auto">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-white rounded-lg p-4 ">
<div className="bg-white rounded-lg p-4">
<h2 className="text-xl font-semibold mb-4 text-gray-700">
Messwerteingänge
</h2>
<AnalogInputsTable
setSelectedId={setSelectedId}
setSelectedInput={setSelectedInput}
setSelectedInput={(input) =>
setSelectedInput(input as unknown as AnalogInput2)
}
setIsSettingsModalOpen={setIsSettingsModalOpen}
/>
</div>
<div className="bg-white shadow-lg rounded-lg p-4 border border-gray-200 ">
<div className="bg-white shadow-lg rounded-lg p-4 border border-gray-200">
<h2 className="text-xl font-semibold mb-4 text-gray-700">
Messkurve Messwerteingang {selectedId ?? ""}
</h2>
@@ -46,11 +57,13 @@ function AnalogInputs() {
</div>
</div>
<AnalogInputsSettingsModal
selectedInput={selectedInput}
isOpen={isSettingsModalOpen}
onClose={() => setIsSettingsModalOpen(false)}
/>
{selectedInput !== null && (
<AnalogInputsSettingsModal
selectedInput={selectedInput}
isOpen={isSettingsModalOpen}
onClose={() => setIsSettingsModalOpen(false)}
/>
)}
</div>
);
}

View File

@@ -9,7 +9,7 @@ export default async function handler(
res: NextApiResponse
) {
try {
const result: Record<number, any[]> = {};
const result: Record<number, unknown[]> = {};
for (let i = 1; i <= 8; i++) {
const filePath = path.join(
@@ -22,10 +22,11 @@ export default async function handler(
try {
const fileContent = await fs.readFile(filePath, "utf-8");
result[99 + i] = JSON.parse(fileContent); // z.B. 100 für AE1, 101 für AE2
} catch (err) {
result[99 + i] = JSON.parse(fileContent); // z. B. 100 für AE1, 101 für AE2
} catch (error) {
console.warn(
`Mock-Datei für analogInput${i} nicht gefunden oder fehlerhaft.`
`Mock-Datei für analogInput${i} nicht gefunden oder fehlerhaft.`,
error
);
result[99 + i] = [];
}

View File

@@ -1,4 +1,4 @@
// /pages/api/cpl/getDigitalOutputsJsonHandler.ts
// /pages/api/cpl/getDigitalOutputsHandler.ts
import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
@@ -12,7 +12,7 @@ export default async function handler(
const mode = process.env.NEXT_PUBLIC_CPL_MODE ?? "json";
if (mode === "json") {
// Lese JSON-Datei z.B. digitalOutputsMockData.json
// Lese JSON-Datei z.B. digitalOutputsMockData.json
const filePath = path.join(
process.cwd(),
"mocks/api/SERVICE/digitalOutputsMockData.json"

View File

@@ -20,6 +20,10 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).send(data);
} catch (error) {
res.status(404).json({ error: "File not found" });
console.error(
"Fehler bei der Verarbeitung von kabelueberwachungAPIHandler:",
error
);
res.status(500).json({ error: "Interner Serverfehler" });
}
}

View File

@@ -21,6 +21,7 @@ export default async function handler(
res.setHeader("Content-Type", "text/javascript"); // wichtig!
res.status(200).send(data);
} catch (error) {
res.status(404).json({ error: "File not found" });
console.error("Fehler beim Laden der letzten 20 Meldungen:", error);
res.status(500).json({ error: "Interner Serverfehler" });
}
}

View File

@@ -6,6 +6,13 @@ import { promises as fs } from "fs";
function parseDate(str: string): Date {
return new Date(str.replace(" ", "T"));
}
export type Message = {
id: number;
timestamp: string;
text: string;
level: string;
// oder alles, was dein `result` konkret enthält
};
export default async function handler(
req: NextApiRequest,
@@ -38,8 +45,8 @@ export default async function handler(
}
if (fromDate && toDate) {
const filtered = data.filter((msg: any) => {
const messageDate = parseDate(msg.t);
const filtered = data.filter((msg: Message) => {
const messageDate = parseDate(msg.timestamp);
return messageDate >= fromDate! && messageDate <= toDate!;
});

View File

@@ -20,6 +20,7 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).send(data);
} catch (error) {
console.error("Error processing opcuaAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -3,10 +3,24 @@ import { NextApiRequest, NextApiResponse } from "next";
import path from "path";
import fs from "fs/promises";
// Typ für einzelne Einträge im JSON-Array
type ChartDataEntry = {
timestamp?: string;
zeit?: string;
time?: string;
[key: string]: unknown; // zusätzliche Werte erlaubt
};
// Hilfsfunktion: JSON-Datei laden
async function loadJsonData(filePath: string) {
async function loadJsonData(filePath: string): Promise<ChartDataEntry[]> {
const data = await fs.readFile(filePath, "utf8");
return JSON.parse(data);
const parsed = JSON.parse(data);
if (!Array.isArray(parsed)) {
throw new Error("Ungültiges Format: Erwartet ein Array");
}
return parsed;
}
export default async function handler(
@@ -32,20 +46,23 @@ export default async function handler(
try {
const jsonData = await loadJsonData(jsonFilePath);
// Filtern nach Datum, wenn angegeben
let filteredData = jsonData;
if (vonDatum && bisDatum) {
const von = new Date(`${vonDatum}T00:00:00`);
const bis = new Date(`${bisDatum}T23:59:59`);
filteredData = jsonData.filter((item: any) => {
const timestamp = new Date(item.t);
return timestamp >= von && timestamp <= bis;
filteredData = jsonData.filter((item) => {
const dateString = item.timestamp ?? item.zeit ?? item.time;
const itemDate = dateString ? new Date(dateString) : null;
return itemDate !== null && itemDate >= von && itemDate <= bis;
});
}
return res.status(200).json(filteredData);
res.status(200).json(filteredData);
} catch (error) {
return res.status(404).json({ error: "File not found or read error" });
console.error("Fehler beim Lesen der Slot-Daten:", error);
res.status(500).json({ error: "Fehler beim Lesen der Slot-Daten" });
}
}

View File

@@ -20,6 +20,7 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).send(data);
} catch (error) {
console.error("Error processing systemAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -20,6 +20,7 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).send(data);
} catch (error) {
console.error("Error processing systemVoltTempAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -26,6 +26,7 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).json(JSON.parse(data));
} catch (error) {
console.error("Error processing tdmDataAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -26,6 +26,7 @@ export default async function handler(
const data = await fs.readFile(filePath, "utf-8");
res.status(200).json(JSON.parse(data));
} catch (error) {
console.error("Error processing tdrDataAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -21,6 +21,7 @@ export default async function handler(
const fileContent = await fs.readFile(filePath, "utf-8");
res.status(200).json(JSON.parse(fileContent));
} catch (error) {
console.error("Error processing tdrReferenceCurveAPIHandler:", error);
res.status(404).json({ error: "File not found" });
}
}

View File

@@ -34,7 +34,6 @@ if (!mockFilePath) {
// Funktion zum Parsen bei jsSimulatedProd
function extractMockData(raw: string) {
const context = {};
const func = new Function(
"context",
`
@@ -81,11 +80,9 @@ export default async function handler(
const rawContent = fs.readFileSync(mockFilePath!, "utf-8");
// 3⃣ JSON vs JS Verarbeitung
const data =
mode === "json" ? JSON.parse(rawContent) : extractMockData(rawContent);
// 4⃣ Aktualisieren der Felder
if (typeof label === "string") data.win_de_label[id - 1] = label;
if (typeof invert === "number") data.win_de_invert[id - 1] = invert;
if (typeof timeFilter === "number")
@@ -97,7 +94,6 @@ export default async function handler(
if (typeof eingangOffline === "number")
data.win_de_offline[id - 1] = eingangOffline;
// 5⃣ Speichern
if (mode === "json") {
fs.writeFileSync(mockFilePath!, JSON.stringify(data, null, 2), "utf-8");
} else {
@@ -128,8 +124,12 @@ var win_de_label = ${JSON.stringify(data.win_de_label, null, 2)};
weighting,
eingangOffline,
});
} catch (err: any) {
console.error("Fehler beim Schreiben:", err);
} catch (err: unknown) {
if (err instanceof Error) {
console.error("Fehler beim Schreiben:", err.message);
} else {
console.error("Unbekannter Fehler beim Schreiben:", err);
}
return res.status(500).json({ error: "Update fehlgeschlagen" });
}
}

View File

@@ -6,7 +6,7 @@ export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
let { key, value, slot } = req.query;
const { key, value, slot } = req.query;
if (
typeof key !== "string" ||

View File

@@ -29,6 +29,7 @@ export default async function handler(
await fs.writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
res.status(200).json({ success: true });
} catch (error) {
console.error("Error processing updateTdrReferenceCurveAPIHandler:", error);
res.status(500).json({ error: "Failed to save file" });
}
}

View File

@@ -32,7 +32,7 @@ export default async function handler(
}
const arrayRaw = match[0].match(/\[(.*)\]/s)?.[1] || "";
let values = arrayRaw
const values = arrayRaw
.split(",")
.map((v) => v.trim())
.map((v) => (v === "" ? "0" : v))
@@ -45,10 +45,7 @@ export default async function handler(
}
// Bereinige kaputte Endzeilen wie ")"
fileContent = fileContent.replace(
/^\s*[\)\(a-zA-Z0-9\/\:\. ]{2,40}\s*$/gm,
""
);
fileContent = fileContent.replace(/^\s*[)(a-zA-Z0-9/:. ]{2,40}\s*$/gm, "");
await fs.writeFile(filePath, fileContent, "utf-8");

View File

@@ -1,6 +1,5 @@
"use client"; //pages/dashboard.tsx
import React, { useEffect } from "react";
import { useRouter } from "next/navigation";
import "tailwindcss/tailwind.css";
import "@fontsource/roboto";
import "bootstrap-icons/font/bootstrap-icons.css";

View File

@@ -1,43 +1,40 @@
"use client";
// /pages/digitalInputs.tsx
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "../redux/store";
import { useDispatch } from "react-redux";
import { AppDispatch } from "@/redux/store";
import InputModal from "../components/main/einausgaenge/modals/InputModal";
import InputModal from "@/components/main/einausgaenge/modals/InputModal";
import { getDigitalInputsThunk } from "@/redux/thunks/getDigitalInputsThunk";
import { getDigitalOutputsThunk } from "../redux/thunks/getDigitalOutputsThunk";
import DigitalInputs from "../components/main/einausgaenge/DigitalInputs";
import DigitalInputs from "@/components/main/einausgaenge/DigitalInputs";
const EinAusgaenge: React.FC = () => {
const dispatch = useDispatch<AppDispatch>();
const digitalInputs = useSelector(
(state: RootState) => state.digitalInputsSlice.inputs
);
const digitalOutputs = useSelector(
(state: RootState) => state.digitalOutputsSlice.outputs
);
interface DigitalInput {
id: number;
eingangOffline: boolean;
status: boolean;
label: string;
[key: string]: unknown;
}
const [selectedInput, setSelectedInput] = useState<DigitalInput | null>(null);
const [selectedInput, setSelectedInput] = useState(null);
const [selectedOutput, setSelectedOutput] = useState(null);
const [isInputModalOpen, setIsInputModalOpen] = useState(false);
const [isOutputModalOpen, setIsOutputModalOpen] = useState(false);
useEffect(() => {
dispatch(getDigitalInputsThunk());
dispatch(getDigitalOutputsThunk());
const interval = setInterval(() => {
dispatch(getDigitalInputsThunk());
dispatch(getDigitalOutputsThunk());
}, 10000);
return () => clearInterval(interval);
}, [dispatch]);
const openInputModal = (input: any) => {
const openInputModal = (input: DigitalInput) => {
setSelectedInput(input);
setIsInputModalOpen(true);
};
@@ -47,16 +44,6 @@ const EinAusgaenge: React.FC = () => {
setIsInputModalOpen(false);
};
const openOutputModal = (output: any) => {
setSelectedOutput(output);
setIsOutputModalOpen(true);
};
const closeOutputModal = () => {
setSelectedOutput(null);
setIsOutputModalOpen(false);
};
return (
<div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)] laptop:h-[calc(100vh-10vh-5vh)] xl:h-[calc(100vh-10vh-6vh)] laptop:gap-0">
<h1 className="text-base font-semibold mb-2">Meldungseingänge</h1>

View File

@@ -1,23 +1,22 @@
"use client"; // /pages/digitalOutputs.tsx
"use client";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch, RootState } from "@/redux/store";
import { useDispatch } from "react-redux";
import { AppDispatch } from "@/redux/store";
import DigitalOutputsModal from "../components/main/einausgaenge/modals/DigitalOutputsModal";
import DigitalOutputs from "../components/main/einausgaenge/DigitalOutputsWidget";
import { getDigitalInputsThunk } from "@/redux/thunks/getDigitalInputsThunk";
import { getDigitalOutputsThunk } from "@/redux/thunks/getDigitalOutputsThunk";
import DigitalOutputs from "../components/main/einausgaenge/DigitalOutputsWidget";
import type { DigitalOutput } from "@/types/digitalOutput";
const EinAusgaenge: React.FC = () => {
const dispatch = useDispatch<AppDispatch>();
const digitalOutputs = useSelector(
(state: RootState) => state.digitalOutputsSlice.outputs
const [selectedOutput, setSelectedOutput] = useState<DigitalOutput | null>(
null
);
const [selectedOutput, setSelectedOutput] = useState(null);
const [isOutputModalOpen, setIsOutputModalOpen] = useState(false);
useEffect(() => {
@@ -31,7 +30,7 @@ const EinAusgaenge: React.FC = () => {
return () => clearInterval(interval);
}, [dispatch]);
const openOutputModal = (output: any) => {
const openOutputModal = (output: DigitalOutput) => {
setSelectedOutput(output);
setIsOutputModalOpen(true);
};
@@ -45,16 +44,17 @@ const EinAusgaenge: React.FC = () => {
<div className="flex flex-col gap-3 p-4 h-[calc(100vh-13vh-8vh)] laptop:h-[calc(100vh-10vh-5vh)] xl:h-[calc(100vh-10vh-6vh)] laptop:gap-0">
<h1 className="text-base font-semibold mb-2">Schaltausgänge</h1>
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4 items-start ">
<div className="grid grid-cols-1 xl:grid-cols-3 gap-4 items-start">
<DigitalOutputs openOutputModal={openOutputModal} />
</div>
{/* ✅ Modal aktiv einbinden */}
<DigitalOutputsModal
selectedOutput={selectedOutput}
isOpen={isOutputModalOpen}
closeOutputModal={closeOutputModal}
/>
{selectedOutput && (
<DigitalOutputsModal
selectedOutput={selectedOutput}
isOpen={isOutputModalOpen}
closeOutputModal={closeOutputModal}
/>
)}
</div>
);
};

View File

@@ -1,6 +1,6 @@
"use client"; // /pages/kabelueberwachung.tsx
import React, { useState, useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { useSearchParams } from "next/navigation";
import Kue705FO from "../components/main/kabelueberwachung/kue705FO/Kue705FO";
import { useDispatch, useSelector } from "react-redux";
import { AppDispatch } from "../redux/store"; // Adjust the path to your Redux store file
@@ -10,10 +10,10 @@ import { getKueDataThunk } from "../redux/thunks/getKueDataThunk";
function Kabelueberwachung() {
const dispatch: AppDispatch = useDispatch();
const searchParams = useSearchParams(); // URL-Parameter holen
const initialRack = parseInt(searchParams.get("rack")) || 1; // Rack-Nummer aus URL oder 1
const initialRack = parseInt(searchParams.get("rack") ?? "1") || 1; // Rack-Nummer aus URL oder 1
const [activeRack, setActiveRack] = useState(initialRack); // Nutze initialRack als Startwert
const [alarmStatus, setAlarmStatus] = useState([]); // Alarmstatus
const [activeRack, setActiveRack] = useState<number>(initialRack); // Nutze initialRack als Startwert
const [alarmStatus, setAlarmStatus] = useState<boolean[]>([]); // Alarmstatus
// Redux-Variablen aus dem Store abrufen
const {
@@ -25,53 +25,51 @@ function Kabelueberwachung() {
kueResidence,
kueCableBreak,
kueGroundFault,
} = useSelector((state) => state.kueDataSlice);
//----------------------------------------------------------------
// 🚀 **TDR-Daten bereits in Redux abrufen**
// Redux-Variablen abrufen
const tdrData = useSelector((state) => state.tdrChartSlice.data);
const loading = useSelector((state) => state.tdrChartSlice.loading);
const error = useSelector((state) => state.tdrChartSlice.error);
//----------------------------------------------------------------
} = useSelector((state: RootState) => state.kueDataSlice);
//----------------------------------------------------------------
// Alarmstatus basierend auf Redux-Variablen berechnen
const updateAlarmStatus = () => {
const updatedAlarmStatus = kueIso.map((_, index) => {
return (
(kueAlarm1 && kueAlarm1[index]) ||
(kueAlarm2 && kueAlarm2[index]) ||
(kueCableBreak && kueCableBreak[index]) ||
(kueGroundFault && kueGroundFault[index])
);
});
const updateAlarmStatus = React.useCallback(() => {
const updatedAlarmStatus = kueIso.map(
(_: number | string, index: number) => {
return Boolean(
(kueAlarm1 && kueAlarm1[index]) ||
(kueAlarm2 && kueAlarm2[index]) ||
(kueCableBreak && kueCableBreak[index]) ||
(kueGroundFault && kueGroundFault[index])
);
}
);
setAlarmStatus(updatedAlarmStatus);
};
}, [kueIso, kueAlarm1, kueAlarm2, kueCableBreak, kueGroundFault]);
// Alarmstatus initial berechnen und alle 10 Sekunden aktualisieren
useEffect(() => {
updateAlarmStatus();
const interval = setInterval(updateAlarmStatus, 10000);
return () => clearInterval(interval);
}, [kueIso, kueAlarm1, kueAlarm2, kueCableBreak, kueGroundFault]);
}, [updateAlarmStatus]);
// Modul- und Rack-Daten aufbereiten
const allModules = kueIso.map((iso, index) => ({
const allModules = kueIso.map((iso: number | string, index: number) => ({
isolationswert: iso,
schleifenwiderstand: kueResidence[index],
modulName: kueID[index] || `Modul ${index + 1}`, // Eindeutiger Name pro Index
kueOnlineStatus: kueOnline[index],
alarmStatus: alarmStatus[index],
tdrLocation: [], // Placeholder, replace with actual tdrLocation if available
}));
//console.log("Alle Module:", allModules);
const racks = {
rack1: allModules.slice(0, 8),
rack2: allModules.slice(8, 16),
rack3: allModules.slice(16, 24),
rack4: allModules.slice(24, 32),
};
const racks = React.useMemo(
() => ({
rack1: allModules.slice(0, 8),
rack2: allModules.slice(8, 16),
rack3: allModules.slice(16, 24),
rack4: allModules.slice(24, 32),
}),
[allModules]
);
// Konsolenausgaben für jede Rack-Aufteilung
/* console.log(
@@ -92,7 +90,7 @@ function Kabelueberwachung() {
); */
// Funktion zum Wechseln des Racks
const changeRack = (rack) => {
const changeRack = (rack: number) => {
setActiveRack(rack);
console.log(`Aktives Rack geändert zu: ${rack}`);
};
@@ -101,20 +99,11 @@ function Kabelueberwachung() {
/* console.log(`Aktives Rack: ${activeRack}`);
console.log(
`Rack ${activeRack} Modulnamen:`,
racks[`rack${activeRack}`].map((slot) => slot.modulName)
racks[`rack${activeRack as 1 | 2 | 3 | 4}` as keyof typeof racks].map((slot: any) => slot.modulName)
); */
}, [activeRack, racks]);
//-----------------------------------------------------------
const {
data: loopData,
loading: loopLoading,
error: loopError,
} = useSelector((state: RootState) => state.loopChartSlice);
// Zugriff z.B. auf Schleifenwiderstand von DIA1
const dia1Schleifen = loopData["DIA1"]?.[4];
const dia0Iso = loopData["DIA0"]?.[3];
//------------------------------------------------------------
useEffect(() => {
@@ -122,13 +111,12 @@ function Kabelueberwachung() {
console.log("📦 Lade KUE-Daten aus getKueDataThunk...");
dispatch(getKueDataThunk());
}
}, []);
}, [dispatch, kueIso.length]);
//------------------------------------------------------------
//----------------------------------------------------------------
// JSX rendering
return (
<div className="bg-gray-100 flex-1 p-6 text-black xl:p-4 2xl:p-6 h-[calc(100vh-13vh-8vh)]">
<h1 className="text-2xl xl:text-xl mb-4">Kabelüberwachung</h1>
<div>
<div className="mb-4">
{[1, 2, 3, 4].map((rack) => (
<button
@@ -145,21 +133,38 @@ function Kabelueberwachung() {
))}
</div>
<div className="flex flex-row space-x-8 xl:space-x-0 2xl:space-x-8 qhd:space-x-16 ml-[5%] mt-[5%]">
{racks[`rack${activeRack}`].map((slot, index) => {
const slotIndex = index + (activeRack - 1) * 8;
return (
<div key={index} className="flex">
<Kue705FO
isolationswert={slot.isolationswert}
schleifenwiderstand={slot.schleifenwiderstand}
modulName={slot.modulName}
kueOnline={slot.kueOnlineStatus}
alarmStatus={slot.alarmStatus}
slotIndex={slotIndex}
/>
</div>
);
})}
{(
racks[
`rack${activeRack as 1 | 2 | 3 | 4}` as keyof typeof racks
] as typeof allModules
).map(
(
slot: {
isolationswert: number | string;
schleifenwiderstand: number | string;
modulName: string;
kueOnlineStatus: number;
alarmStatus?: boolean;
tdrLocation: number[];
},
index: number
) => {
const slotIndex = index + (activeRack - 1) * 8;
return (
<div key={index} className="flex">
<Kue705FO
isolationswert={slot.isolationswert}
schleifenwiderstand={slot.schleifenwiderstand}
modulName={slot.modulName}
kueOnline={slot.kueOnlineStatus}
alarmStatus={slot.alarmStatus}
slotIndex={slotIndex}
tdrLocation={slot.tdrLocation}
/>
</div>
);
}
)}
</div>
</div>
);

View File

@@ -1,7 +1,7 @@
"use client";
// /pages/meldungen.tsx
import React, { useState, useEffect } from "react";
import DateRangePickerMeldungen from "../components/main/meldungen/DateRangePickerMeldungen";
import DateRangePickerMeldungen from "@/components/main/meldungen/DateRangePickerMeldungen";
type Meldung = {
t: string;
@@ -41,7 +41,7 @@ export default function Messages() {
typeof window !== "undefined" && window.location.hostname === "localhost";
//http://10.10.0.118/CPL?Service/empty.ACP&MSS1=2025;06;01;2025;06;26;All
const url = isDev
? `/api/cpl/messages?MSS1=${fy};${fm};${fd};${ty};${tm};${td};All`
? `/api/cpl/messages`
: `/CPL?Service/ae.ACP&MSS1=${fy};${fm};${fd};${ty};${tm};${td};All`;
try {
@@ -67,6 +67,7 @@ export default function Messages() {
// einmal beim laden de Seite die Meldungen abrufen
useEffect(() => {
fetchMessages();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (

View File

@@ -12,6 +12,7 @@ import {
Title,
Tooltip,
Legend,
TooltipItem,
} from "chart.js";
import { Line } from "react-chartjs-2";
@@ -124,7 +125,7 @@ const SystemPage = () => {
},
tooltip: {
callbacks: {
label: function (context: any) {
label: function (context: TooltipItem<"line">) {
const label = context.dataset.label || "";
const value =
context.parsed.y !== null ? context.parsed.y.toFixed(2) : "";