Files
CPLv4.0/pages/dashboard.tsx
2025-02-13 20:04:31 +01:00

251 lines
8.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"; // app/dashboard/page.jsx
import React, { useEffect } from "react";
import { useRouter } from "next/navigation";
import "tailwindcss/tailwind.css";
import "@fontsource/roboto";
import "bootstrap-icons/font/bootstrap-icons.css";
import CPLStatus from "../components/main/uebersicht/modulesStatus/CPLStatus";
import KabelModulStatus from "../components/main/uebersicht/modulesStatus/KabelModulStatus";
import { Icon } from "@iconify/react";
import { useSelector } from "react-redux";
import { RootState } from "../redux/store";
import { useDispatch } from "react-redux";
import {
setOpcUaZustand,
setOpcUaActiveClientCount,
setOpcUaNodesetName,
} from "../redux/slices/variablesSlice";
import webVersion from "../config/webVersion";
import Last20MessagesTable from "../components/main/uebersicht/last20MessagesTable/Last20MessagesTable";
function Dashboard() {
const router = useRouter();
const dispatch = useDispatch();
useEffect(() => {
if (typeof window !== "undefined") {
dispatch(setOpcUaZustand(window.win_opcUaZustand || "Unbekannt"));
dispatch(
setOpcUaActiveClientCount(
Number(window.win_opcUaActiveClientCount) || 0
)
);
dispatch(setOpcUaNodesetName(window.win_opcUaNodesetName || "Unbekannt"));
}
}, []);
// Redux-Variablen abrufen
const opcUaZustand = useSelector(
(state: RootState) => state.variables.opcUaZustand
);
const opcUaActiveClientCount = useSelector(
(state: RootState) => state.variables.opcUaActiveClientCount
);
const opcUaNodesetName = useSelector(
(state: RootState) => state.variables.opcUaNodesetName
);
const rawLast20Messages = useSelector(
(state: RootState) => state.variables.last20Messages
);
const ip = useSelector((state: RootState) => state.variables.ip);
const subnet = useSelector((state: RootState) => state.variables.subnet);
const gateway = useSelector((state: RootState) => state.variables.gateway);
const appVersion = useSelector(
(state: RootState) => state.variables.appVersion
);
const kueCableBreak = useSelector(
(state: RootState) => state.variables.kueCableBreak
);
const kueOnline = useSelector(
(state: RootState) => state.variables.kueOnline
);
const kueVersion = useSelector(
(state: RootState) => state.variables.kueVersion
);
const kueAlarm1 = useSelector(
(state: RootState) => state.variables.kueAlarm1
);
const kueAlarm2 = useSelector(
(state: RootState) => state.variables.kueAlarm2
);
const kueGroundFault = useSelector(
(state: RootState) => state.variables.kueGroundFault
);
// Hilfsfunktion zum Parsen der Nachrichten
const parseMessages = (messages) => {
if (typeof messages === "string") {
messages = messages
.replace(/<tr>/g, "\n")
.replace(/<\/?td>/g, "")
.replace(/<\/tr>/g, "")
.trim();
const rows = messages.split("\n");
return rows.map((row) => [
row.substring(0, 5),
row.substring(5, 10),
row.substring(10, 29),
row.substring(33, row.length - 1),
row.substring(row.length - 1),
]);
}
return [];
};
const last20Messages = parseMessages(rawLast20Messages);
const handleModuleClick = (rackNumber) => {
router.push(`/kabelueberwachung?rack=${rackNumber}`);
};
const renderBaugruppentraeger = () => {
const baugruppen: JSX.Element[] = [];
const numBaugruppen = Math.ceil(kueOnline.length / 8);
for (let i = 0; i < numBaugruppen; i++) {
const slots = kueOnline.slice(i * 8, (i + 1) * 8);
baugruppen.push(
<div
key={i}
className="flex bg-white shadow-md rounded-lg mb-4 xl:mb-0 lg:mb-0 border border-gray-200 w-full laptop:scale-y-75 xl:scale-y-90"
>
<div className="flex gap-1">
{slots.map((version, index) => {
const slotNumber = i * 8 + index + 1;
const isSlotOnline = kueOnline[slotNumber - 1] === 1;
const moduleVersion = kueVersion[slotNumber - 1] || version;
// Berechnung der Rack-Nummer basierend auf dem slotNumber
const rackNumber = Math.ceil(slotNumber / 8); // 18 -> Rack 1, 916 -> Rack 2 usw.
return (
<div
key={slotNumber}
className="cursor-pointer"
onClick={() => handleModuleClick(rackNumber)} // Klick-Handler mit Rack-Nummer
>
<KabelModulStatus
slot={slotNumber}
isOnline={isSlotOnline}
moduleVersion={moduleVersion}
kueCableBreak={kueCableBreak}
kueAlarm1={kueAlarm1}
kueAlarm2={kueAlarm2}
kueGroundFault={kueGroundFault}
/>
</div>
);
})}
</div>
</div>
);
}
return baugruppen;
};
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 ">
<div className="flex justify-between items-center w-full lg:w-2/3">
<div className="flex justify-between gap-1 ">
<Icon
icon="ri:calendar-schedule-line"
className="text-littwin-blue text-4xl xl:text-2xl"
/>
<h1 className="text-xl font-bold text-gray-700 xl:text-base">
Letzten 20 Meldungen
</h1>
</div>
</div>
<div className="flex flex-col lg:flex-row gap-0 overflow-hidden flex-grow">
<Last20MessagesTable last20Messages={last20Messages} />
<div
className="shadow-md rounded-lg
w-full sm:w-3/4 md:w-2/3 lg:w-1/2 xl:w-1/3
flex flex-col gap-2"
>
<div className="bg-gray-50 p-4 sm:p-3 md:p-4 lg:p-2 xl:p-2 rounded-lg shadow-sm border border-gray-200 w-full ">
<h2 className="text-lg 2xl:text-lg xl:text-sm font-semibold text-gray-700 mb-2 ">
Versionsinformationen
</h2>
<div className="flex flex-row p-2 sm:p-1 md:p-2 space-x-2 laptop:p-0 xl:p-0">
<Icon
icon="bx:code-block"
className="text-xl 2xl:text-xl xl:text-base text-blue-400"
/>
<p className="text-sm 2xl:text-lg text-gray-600">
<span className="font-bold"></span> Applikationsversion:{" "}
{appVersion}
</p>
</div>
<div className="flex flex-row p-2 sm:p-1 md:p-2 space-x-2 laptop:p-0 xl:p-0">
<Icon
icon="mdi:web"
className="text-xl lg:text-base text-blue-400"
/>
<p className="text-sm sm:text-xs md:text-sm lg:text-base text-gray-600">
<span className="font-bold"></span> Webversion: {webVersion}
</p>
</div>
</div>
{renderBaugruppentraeger()}
</div>
</div>
<div className="flex-shrink-0 flex justify-between items-center mt-1 bg-white p-2 rounded-lg shadow-md border border-gray-200 laptop:m-0 laptop:scale-y-75">
<div className="flex items-center space-x-4">
<img src="/images/IP-icon.svg" alt="IP Address" className="w-6 " />
<div>
<p className="text-xs text-gray-500">IP-Adresse</p>
<p className="text-sm font-medium text-gray-700">{ip}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<img
src="/images/subnet-mask.svg"
alt="subnet mask"
className="w-6 "
/>
<div>
<p className="text-xs text-gray-500">Subnet-Maske</p>
<p className="text-sm font-medium text-gray-700">{subnet}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<img src="/images/gateway.svg" alt="gateway" className="w-6 " />
<div>
<p className="text-xs text-gray-500">Gateway</p>
<p className="text-sm font-medium text-gray-700">{gateway}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="text-xs font-bold text-blue-600">OPC-UA</div>
<div>
<p className="text-xs text-gray-500">Status</p>
<p className="text-sm font-medium text-gray-700">{opcUaZustand}</p>
</div>
</div>
<div className="flex items-center space-x-4">
<div>
<p className="text-xs text-gray-500">Nodeset Name</p>
<p className="text-sm font-medium text-gray-700">
{opcUaNodesetName}
</p>
</div>
</div>
</div>
</div>
);
}
export default Dashboard;