feat: Responsive Darstellung der Last-20-Meldungen-Tabelle ohne Pagination
- Tabelle nutzt jetzt den verfügbaren vertikalen Platz mit `flex-grow` und `h-full` - Scrollen statt Pagination: mehr Meldungen sichtbar in einem Blick - Anpassung an das Layout der Übersichtsseite (dashboard.tsx) - Design orientiert sich an bestehender meldungen.tsx-Komponente
This commit is contained in:
@@ -4,15 +4,17 @@ import { useSelector, useDispatch } from "react-redux";
|
|||||||
import { RootState } from "../../../redux/store";
|
import { RootState } from "../../../redux/store";
|
||||||
import { setLast20Messages } from "../../../redux/slices/last20MessagesSlice";
|
import { setLast20Messages } from "../../../redux/slices/last20MessagesSlice";
|
||||||
|
|
||||||
const Last20MessagesTable: React.FC = () => {
|
type Props = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Last20MessagesTable: React.FC<Props> = ({ className }) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
// Holt last20Messages aus Redux
|
|
||||||
const rawLast20Messages = useSelector(
|
const rawLast20Messages = useSelector(
|
||||||
(state: RootState) => state.last20MessagesSlice.last20Messages
|
(state: RootState) => state.last20MessagesSlice.last20Messages
|
||||||
);
|
);
|
||||||
|
|
||||||
// Holt Daten aus `window.win_last20Messages` und speichert sie in Redux
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadWindowMessages = () => {
|
const loadWindowMessages = () => {
|
||||||
if (typeof window !== "undefined" && (window as any).win_last20Messages) {
|
if (typeof window !== "undefined" && (window as any).win_last20Messages) {
|
||||||
@@ -20,84 +22,72 @@ const Last20MessagesTable: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialen Wert setzen
|
|
||||||
loadWindowMessages();
|
loadWindowMessages();
|
||||||
|
|
||||||
// Falls die Daten erst später geladen werden, überprüfe jede Sekunde
|
|
||||||
const interval = setInterval(loadWindowMessages, 1000);
|
const interval = setInterval(loadWindowMessages, 1000);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
// Hilfsfunktion zum Parsen der Nachrichten
|
|
||||||
const parseMessages = (messages: string | null) => {
|
const parseMessages = (messages: string | null) => {
|
||||||
if (!messages) return [];
|
if (!messages) return [];
|
||||||
|
|
||||||
const rows = messages
|
return messages
|
||||||
.split("<tr>")
|
.split("<tr>")
|
||||||
.slice(1) // erstes Element ist leer
|
.slice(1)
|
||||||
.map((row) => {
|
.map((row) =>
|
||||||
const cols = row
|
row
|
||||||
.replace(/<\/tr>/, "")
|
.replace(/<\/tr>/, "")
|
||||||
.split("</td><td>")
|
.split("</td><td>")
|
||||||
.map((col) => col.replace(/<[^>]+>/g, ""));
|
.map((col) => col.replace(/<[^>]+>/g, ""))
|
||||||
return cols;
|
);
|
||||||
});
|
|
||||||
|
|
||||||
return rows;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const last20Messages = parseMessages(rawLast20Messages);
|
const allMessages = parseMessages(rawLast20Messages);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white shadow-md rounded-lg w-full lg:w-2/3 overflow-auto flex ">
|
<div className={`bg-white shadow-md rounded-lg overflow-auto ${className}`}>
|
||||||
<table className="min-w-full border border-gray-200 text-left table-fixed ">
|
<h1 className="text-xl font-bold mb-4">Letzte 20 Meldungen</h1>
|
||||||
<thead className="bg-gray-100 border-b border-gray-300">
|
|
||||||
|
<div className="overflow-x-auto overflow-y-auto border rounded shadow-sm h-[95%]">
|
||||||
|
<table className="min-w-full border">
|
||||||
|
<thead className="bg-gray-100 text-left sticky top-0 z-10">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="py-1 px-4 text-gray-700 text-sm font-medium">ID</th>
|
<th className="p-2 border">ID</th>
|
||||||
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
|
<th className="p-2 border">Modul</th>
|
||||||
Modul
|
<th className="p-2 border">Zeitstempel</th>
|
||||||
</th>
|
<th className="p-2 border">Meldung</th>
|
||||||
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
|
<th className="p-2 border">Status</th>
|
||||||
Zeitstempel
|
|
||||||
</th>
|
|
||||||
<th className="py-1 px-4 text-gray-700 text-sm font-medium w-2/3">
|
|
||||||
Meldung
|
|
||||||
</th>
|
|
||||||
<th className="py-1 px-4 text-gray-700 text-sm font-medium">
|
|
||||||
Status
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="text-xs text-gray-600 laptop:text-xs flex-shrink-0">
|
<tbody>
|
||||||
{last20Messages.length > 0 ? (
|
{allMessages.length === 0 ? (
|
||||||
last20Messages.map((columns, index) => (
|
|
||||||
<tr
|
|
||||||
key={index}
|
|
||||||
className="border-b border-gray-200 hover:bg-gray-50"
|
|
||||||
>
|
|
||||||
<td className="px-4 w-1/7">{columns[0]}</td>
|
|
||||||
<td className="px-4 w-1/7">{columns[1]}</td>
|
|
||||||
<td className="px-4 w-3/7 whitespace-nowrap">
|
|
||||||
<div className="flex flex-row space-x-2">
|
|
||||||
<span>{columns[2].split(" ")[0]}</span>
|
|
||||||
<span>{columns[2].split(" ")[1]}</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className="px-4 w-2/7">{columns[3]}</td>
|
|
||||||
<td className="px-4 w-1/7">{columns[4]}</td>
|
|
||||||
</tr>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<tr>
|
<tr>
|
||||||
<td className="px-4 text-center" colSpan={5}>
|
<td
|
||||||
|
colSpan={5}
|
||||||
|
className="text-center italic text-gray-500 p-4"
|
||||||
|
>
|
||||||
Keine Meldungen verfügbar.
|
Keine Meldungen verfügbar.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
) : (
|
||||||
|
allMessages.map((msg, index) => (
|
||||||
|
<tr key={index} className="hover:bg-gray-50">
|
||||||
|
<td className="border p-2">{msg[0]}</td>
|
||||||
|
<td className="border p-2">{msg[1]}</td>
|
||||||
|
<td className="border p-2 whitespace-nowrap">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<span>{msg[2]?.split(" ")[0]}</span>
|
||||||
|
<span>{msg[2]?.split(" ")[1]}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="border p-2">{msg[3]}</td>
|
||||||
|
<td className="border p-2">{msg[4]}</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const Dashboard: React.FC = () => {
|
|||||||
|
|
||||||
{/* Hauptbereich mit Meldungstabelle und Baugruppenträger */}
|
{/* Hauptbereich mit Meldungstabelle und Baugruppenträger */}
|
||||||
<div className="flex flex-col lg:flex-row gap-4 flex-grow overflow-hidden">
|
<div className="flex flex-col lg:flex-row gap-4 flex-grow overflow-hidden">
|
||||||
<Last20MessagesTable className="w-full lg:w-2/3" />
|
<Last20MessagesTable className="w-full lg:w-2/3 h-full" />
|
||||||
|
|
||||||
<div className="shadow-md rounded-lg w-full lg:w-1/3 flex flex-col gap-2">
|
<div className="shadow-md rounded-lg w-full lg:w-1/3 flex flex-col gap-2">
|
||||||
<VersionInfo className="w-full p-3 text-sm" />
|
<VersionInfo className="w-full p-3 text-sm" />
|
||||||
|
|||||||
Reference in New Issue
Block a user