198 lines
5.6 KiB
TypeScript
198 lines
5.6 KiB
TypeScript
import { useState } from 'react';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import {
|
|
Box,
|
|
Typography,
|
|
Paper,
|
|
Table,
|
|
TableBody,
|
|
TableCell,
|
|
TableContainer,
|
|
TableHead,
|
|
TableRow,
|
|
Chip,
|
|
FormControl,
|
|
InputLabel,
|
|
Select,
|
|
MenuItem,
|
|
Pagination,
|
|
} from '@mui/material';
|
|
import {
|
|
Error as ErrorIcon,
|
|
Warning as WarningIcon,
|
|
CheckCircle as CheckIcon,
|
|
Info as InfoIcon,
|
|
Speed as SpeedIcon,
|
|
} from '@mui/icons-material';
|
|
import { logsApi, serversApi } from '../utils/api';
|
|
|
|
|
|
const LOGS_PER_PAGE = 25;
|
|
|
|
export default function Logs() {
|
|
const [page, setPage] = useState(1);
|
|
const [eventType, setEventType] = useState<string>('');
|
|
const [serverFilter, setServerFilter] = useState<number | ''>('');
|
|
|
|
const { data: servers } = useQuery({
|
|
queryKey: ['servers'],
|
|
queryFn: async () => {
|
|
const response = await serversApi.getAll();
|
|
return response.data;
|
|
},
|
|
});
|
|
|
|
const { data: logs } = useQuery({
|
|
queryKey: ['logs', eventType, serverFilter],
|
|
queryFn: async () => {
|
|
const response = await logsApi.getAll({
|
|
event_type: eventType || undefined,
|
|
server_id: serverFilter || undefined,
|
|
limit: 100,
|
|
});
|
|
return response.data;
|
|
},
|
|
});
|
|
|
|
const getEventIcon = (eventType: string) => {
|
|
switch (eventType) {
|
|
case 'panic':
|
|
return <ErrorIcon color="error" />;
|
|
case 'error':
|
|
return <ErrorIcon color="error" />;
|
|
case 'warning':
|
|
return <WarningIcon color="warning" />;
|
|
case 'fan_change':
|
|
return <SpeedIcon color="info" />;
|
|
case 'info':
|
|
return <InfoIcon color="info" />;
|
|
default:
|
|
return <CheckIcon color="success" />;
|
|
}
|
|
};
|
|
|
|
const getEventColor = (eventType: string) => {
|
|
switch (eventType) {
|
|
case 'panic':
|
|
return 'error';
|
|
case 'error':
|
|
return 'error';
|
|
case 'warning':
|
|
return 'warning';
|
|
case 'fan_change':
|
|
return 'info';
|
|
case 'info':
|
|
return 'default';
|
|
default:
|
|
return 'default';
|
|
}
|
|
};
|
|
|
|
const totalPages = Math.ceil((logs?.length || 0) / LOGS_PER_PAGE);
|
|
const paginatedLogs = logs?.slice((page - 1) * LOGS_PER_PAGE, page * LOGS_PER_PAGE);
|
|
|
|
return (
|
|
<Box>
|
|
<Typography variant="h4" gutterBottom>
|
|
System Logs
|
|
</Typography>
|
|
|
|
<Paper sx={{ p: 2, mb: 2 }}>
|
|
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
|
|
<FormControl sx={{ minWidth: 150 }}>
|
|
<InputLabel>Event Type</InputLabel>
|
|
<Select
|
|
value={eventType}
|
|
label="Event Type"
|
|
onChange={(e) => setEventType(e.target.value)}
|
|
>
|
|
<MenuItem value="">All</MenuItem>
|
|
<MenuItem value="panic">Panic</MenuItem>
|
|
<MenuItem value="error">Error</MenuItem>
|
|
<MenuItem value="warning">Warning</MenuItem>
|
|
<MenuItem value="fan_change">Fan Change</MenuItem>
|
|
<MenuItem value="info">Info</MenuItem>
|
|
</Select>
|
|
</FormControl>
|
|
|
|
<FormControl sx={{ minWidth: 200 }}>
|
|
<InputLabel>Server</InputLabel>
|
|
<Select
|
|
value={serverFilter}
|
|
label="Server"
|
|
onChange={(e) => setServerFilter(e.target.value as number | '')}
|
|
>
|
|
<MenuItem value="">All Servers</MenuItem>
|
|
{servers?.map((server) => (
|
|
<MenuItem key={server.id} value={server.id}>
|
|
{server.name}
|
|
</MenuItem>
|
|
))}
|
|
</Select>
|
|
</FormControl>
|
|
</Box>
|
|
</Paper>
|
|
|
|
<TableContainer component={Paper}>
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell width={50}></TableCell>
|
|
<TableCell>Time</TableCell>
|
|
<TableCell>Server</TableCell>
|
|
<TableCell>Type</TableCell>
|
|
<TableCell>Message</TableCell>
|
|
<TableCell>Details</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{paginatedLogs?.map((log) => (
|
|
<TableRow key={log.id} hover>
|
|
<TableCell>{getEventIcon(log.event_type)}</TableCell>
|
|
<TableCell>
|
|
{new Date(log.timestamp).toLocaleString()}
|
|
</TableCell>
|
|
<TableCell>
|
|
{log.server_id
|
|
? servers?.find((s) => s.id === log.server_id)?.name ||
|
|
`Server ${log.server_id}`
|
|
: 'System'}
|
|
</TableCell>
|
|
<TableCell>
|
|
<Chip
|
|
size="small"
|
|
label={log.event_type}
|
|
color={getEventColor(log.event_type) as any}
|
|
/>
|
|
</TableCell>
|
|
<TableCell>{log.message}</TableCell>
|
|
<TableCell>{log.details}</TableCell>
|
|
</TableRow>
|
|
))}
|
|
{!paginatedLogs?.length && (
|
|
<TableRow>
|
|
<TableCell colSpan={6} align="center">
|
|
<Typography color="text.secondary" sx={{ py: 4 }}>
|
|
No logs found
|
|
</Typography>
|
|
</TableCell>
|
|
</TableRow>
|
|
)}
|
|
</TableBody>
|
|
</Table>
|
|
</TableContainer>
|
|
|
|
{totalPages > 1 && (
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 3 }}>
|
|
<Pagination
|
|
count={totalPages}
|
|
page={page}
|
|
onChange={(_, value) => setPage(value)}
|
|
color="primary"
|
|
/>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|