- mission-control dashboard: now strip, tournament quick actions, usage sparklines, error feed, live activity, tools list - /admin/telemetry with functions/events/errors/players/usage child routes, hand-rolled svg chart primitives, decomposed activities table - error browser with grouping and mark-resolved - consolidated per-tournament enrollment screen; hub simplified with run tournament promoted - /admin/activities redirects to /admin/telemetry/functions
63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
import { Badge, Card, Group, Stack, Text, UnstyledButton } from "@mantine/core";
|
|
import { Trans } from "@lingui/react/macro";
|
|
import { useNavigate } from "@tanstack/react-router";
|
|
import { CheckCircleIcon, WarningCircleIcon } from "@phosphor-icons/react";
|
|
import { useClientErrorGroups } from "@/features/telemetry/queries";
|
|
import { RelativeTime } from "@/features/telemetry/components/shared";
|
|
import { lastNDays } from "@/features/telemetry/range";
|
|
|
|
export const ErrorsCard = () => {
|
|
const navigate = useNavigate();
|
|
const range = lastNDays(30);
|
|
|
|
const { data: groups } = useClientErrorGroups({ from: range.from, to: range.to });
|
|
|
|
return (
|
|
<UnstyledButton w="100%" onClick={() => navigate({ to: "/admin/telemetry/errors" })}>
|
|
<Card withBorder radius="md" p="md">
|
|
<Stack gap="sm">
|
|
<Group justify="space-between" wrap="nowrap">
|
|
<Text fw={600} size="sm">
|
|
<Trans>Client errors</Trans>
|
|
</Text>
|
|
{groups && groups.length > 0 ? (
|
|
<Badge color="red" variant="light">
|
|
{groups.length}
|
|
</Badge>
|
|
) : (
|
|
<CheckCircleIcon size={18} color="var(--mantine-color-green-6)" weight="fill" />
|
|
)}
|
|
</Group>
|
|
{groups && groups.length > 0 ? (
|
|
<Stack gap="xs">
|
|
{groups.slice(0, 3).map((group) => (
|
|
<Group key={group.group_hash} gap="xs" wrap="nowrap" align="flex-start">
|
|
<WarningCircleIcon
|
|
size={14}
|
|
color="var(--mantine-color-red-6)"
|
|
style={{ flexShrink: 0, marginTop: 2 }}
|
|
/>
|
|
<Stack gap={0} style={{ minWidth: 0 }}>
|
|
<Text size="xs" lineClamp={1}>
|
|
{group.sample.message}
|
|
</Text>
|
|
<Text size="xs" c="dimmed">
|
|
<RelativeTime date={group.lastSeen} />
|
|
</Text>
|
|
</Stack>
|
|
</Group>
|
|
))}
|
|
</Stack>
|
|
) : (
|
|
<Text size="sm" c="dimmed">
|
|
<Trans>No unresolved errors</Trans>
|
|
</Text>
|
|
)}
|
|
</Stack>
|
|
</Card>
|
|
</UnstyledButton>
|
|
);
|
|
};
|
|
|
|
export default ErrorsCard;
|