UI polishing

This commit is contained in:
2025-07-23 15:04:16 +00:00
parent 7f4800496a
commit b0e933e895
2 changed files with 51 additions and 23 deletions

View File

@@ -75,6 +75,20 @@ function DetailsModal({ open, client, groupIdToName, onClose }: DetailsModalProp
? 'IP-Adresse' ? 'IP-Adresse'
: key === 'registration_time' : key === 'registration_time'
? 'Registriert am' ? 'Registriert am'
: key === 'description'
? 'Beschreibung'
: key === 'last_alive'
? 'Letzter Kontakt'
: key === 'model'
? 'Modell'
: key === 'uuid'
? 'Client-Code'
: key === "os_version"
? 'Betriebssystem'
: key === 'software_version'
? 'Clientsoftware'
: key === 'macs'
? 'MAC-Adressen'
: key.charAt(0).toUpperCase() + key.slice(1)} : key.charAt(0).toUpperCase() + key.slice(1)}
: :
</td> </td>

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useState, useRef } from 'react'; import React, { useEffect, useState, useRef } from 'react';
import { fetchGroupsWithClients, restartClient } from './apiClients'; import { fetchGroupsWithClients, restartClient } from './apiClients';
import type { Group } from './apiClients'; import type { Group, Client } from './apiClients';
import { import {
GridComponent, GridComponent,
ColumnsDirective, ColumnsDirective,
@@ -13,25 +13,35 @@ import {
const REFRESH_INTERVAL = 15000; // 15 Sekunden const REFRESH_INTERVAL = 15000; // 15 Sekunden
// Typ für Collapse-Event
// type DetailRowCollapseArgs = {
// data?: { id?: string | number };
// };
// Typ für DataBound-Event
type DetailRowDataBoundArgs = {
data?: { id?: string | number };
};
const Dashboard: React.FC = () => { const Dashboard: React.FC = () => {
const [groups, setGroups] = useState<Group[]>([]); const [groups, setGroups] = useState<Group[]>([]);
const [expandedGroupIds, setExpandedGroupIds] = useState<string[]>([]); const [expandedGroupIds, setExpandedGroupIds] = useState<string[]>([]);
const gridRef = useRef<any>(null); const gridRef = useRef<GridComponent | null>(null);
// Funktion für das Schließen einer Gruppe (Collapse) // Funktion für das Schließen einer Gruppe (Collapse)
const onDetailCollapse = (args: any) => { // const onDetailCollapse = (args: DetailRowCollapseArgs) => {
if (args && args.data && args.data.id) { // if (args && args.data && args.data.id) {
const groupId = String(args.data.id); // const groupId = String(args.data.id);
setExpandedGroupIds(prev => prev.filter(id => String(id) !== groupId)); // setExpandedGroupIds(prev => prev.filter(id => String(id) !== groupId));
} // }
}; // };
// Registriere das Event nach dem Mount am Grid // // Registriere das Event nach dem Mount am Grid
useEffect(() => { // useEffect(() => {
if (gridRef.current) { // if (gridRef.current) {
gridRef.current.detailCollapse = onDetailCollapse; // gridRef.current.detailCollapse = onDetailCollapse;
} // }
}, []); // }, []);
// Optimiertes Update: Nur bei echten Datenänderungen wird das Grid aktualisiert // Optimiertes Update: Nur bei echten Datenänderungen wird das Grid aktualisiert
useEffect(() => { useEffect(() => {
@@ -77,7 +87,7 @@ const Dashboard: React.FC = () => {
// Health-Badge // Health-Badge
const getHealthBadge = (group: Group) => { const getHealthBadge = (group: Group) => {
const total = group.clients.length; const total = group.clients.length;
const alive = group.clients.filter((c: any) => c.is_alive).length; const alive = group.clients.filter((c: Client) => c.is_alive).length;
const ratio = total === 0 ? 0 : alive / total; const ratio = total === 0 ? 0 : alive / total;
let color = 'danger'; let color = 'danger';
let text = `${alive} / ${total} offline`; let text = `${alive} / ${total} offline`;
@@ -98,7 +108,7 @@ const Dashboard: React.FC = () => {
<ColumnsDirective> <ColumnsDirective>
<ColumnDirective field="description" headerText="Beschreibung" width="150" /> <ColumnDirective field="description" headerText="Beschreibung" width="150" />
<ColumnDirective field="ip" headerText="IP" width="120" /> <ColumnDirective field="ip" headerText="IP" width="120" />
<ColumnDirective {/* <ColumnDirective
field="last_alive" field="last_alive"
headerText="Letztes Lebenszeichen" headerText="Letztes Lebenszeichen"
width="180" width="180"
@@ -110,7 +120,7 @@ const Dashboard: React.FC = () => {
const date = new Date(dateStr); const date = new Date(dateStr);
return isNaN(date.getTime()) ? props.last_alive : date.toLocaleString(); return isNaN(date.getTime()) ? props.last_alive : date.toLocaleString();
}} }}
/> /> */}
<ColumnDirective <ColumnDirective
field="is_alive" field="is_alive"
headerText="Alive" headerText="Alive"
@@ -142,15 +152,19 @@ const Dashboard: React.FC = () => {
try { try {
const result = await restartClient(uuid); const result = await restartClient(uuid);
alert(`Neustart erfolgreich: ${result.message}`); alert(`Neustart erfolgreich: ${result.message}`);
} catch (error: any) { } catch (error: unknown) {
alert(`Fehler beim Neustart: ${error.message}`); if (error && typeof error === 'object' && 'message' in error) {
alert(`Fehler beim Neustart: ${(error as { message: string }).message}`);
} else {
alert('Unbekannter Fehler beim Neustart');
}
} }
}; };
// SyncFusion Grid liefert im Event die Zeile/Gruppe // SyncFusion Grid liefert im Event die Zeile/Gruppe
const onDetailDataBound = (args: any) => { const onDetailDataBound = (args: DetailRowDataBoundArgs) => {
if (args && args.data && args.data.id) { if (args && args.data && args.data.id) {
const groupId = args.data.id; const groupId = String(args.data.id);
setExpandedGroupIds(prev => (prev.includes(groupId) ? prev : [...prev, groupId])); setExpandedGroupIds(prev => (prev.includes(groupId) ? prev : [...prev, groupId]));
} }
}; };
@@ -176,7 +190,7 @@ const Dashboard: React.FC = () => {
<ColumnDirective <ColumnDirective
headerText="Health" headerText="Health"
width="160" width="160"
template={(props: any) => getHealthBadge(props)} template={(props: Group) => getHealthBadge(props)}
/> />
</ColumnsDirective> </ColumnsDirective>
</GridComponent> </GridComponent>