esLint
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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] = [];
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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!;
|
||||
});
|
||||
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" ||
|
||||
|
||||
@@ -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" });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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) : "";
|
||||
|
||||
Reference in New Issue
Block a user