diff --git a/dashboards/admin-web/src/app/(dashboard)/ops/client-logs/page.tsx b/dashboards/admin-web/src/app/(dashboard)/ops/client-logs/page.tsx
index ac10c7b3..4b14a3e6 100644
--- a/dashboards/admin-web/src/app/(dashboard)/ops/client-logs/page.tsx
+++ b/dashboards/admin-web/src/app/(dashboard)/ops/client-logs/page.tsx
@@ -1,7 +1,16 @@
'use client';
import { useEffect, useState, useCallback, useMemo } from 'react';
-import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid, Legend } from 'recharts';
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ Tooltip,
+ ResponsiveContainer,
+ CartesianGrid,
+ Legend,
+} from 'recharts';
import {
AlertTriangle,
Bug,
@@ -44,12 +53,7 @@ import {
TableHeader,
TableRow,
} from '@/components/ui/table';
-import {
- Tabs,
- TabsContent,
- TabsList,
- TabsTrigger,
-} from '@/components/ui/tabs';
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
// ─── Types ──────────────────────────────────────────────────────
@@ -192,7 +196,9 @@ function ClusterTimelineChart({ clusters }: { clusters: TelemetryCluster[] }) {
else if (c.severity === 'error') b.error += c.totalCount;
else if (c.severity === 'fatal') b.fatal += c.totalCount;
}
- return Array.from(buckets.values()).sort((a, b) => a.date.localeCompare(b.date)).slice(-14);
+ return Array.from(buckets.values())
+ .sort((a, b) => a.date.localeCompare(b.date))
+ .slice(-14);
}, [clusters]);
if (chartData.length === 0) return null;
@@ -218,9 +224,15 @@ function ClusterTimelineChart({ clusters }: { clusters: TelemetryCluster[] }) {
}}
/>
-
-
-
+
+
+
@@ -345,7 +357,7 @@ export default function ClientLogsPage() {
// Fetch ingestion metrics
useEffect(() => {
fetch('/api/telemetry/metrics')
- .then(r => r.ok ? r.json() : null)
+ .then(r => (r.ok ? r.json() : null))
.then(d => d && setIngestionMetrics(d))
.catch(() => {});
}, []);
@@ -356,20 +368,26 @@ export default function ClientLogsPage() {
setGeoLoading(true);
const sevenDaysAgo = new Date(Date.now() - 7 * 86400000).toISOString();
fetch(`/api/telemetry/geo?from=${encodeURIComponent(sevenDaysAgo)}`)
- .then(r => r.ok ? r.json() : null)
+ .then(r => (r.ok ? r.json() : null))
.then(d => d && setGeoData(d.distribution || []))
.catch(() => {})
.finally(() => setGeoLoading(false));
}, [tab]);
- const handleClusterAction = async (cluster: TelemetryCluster, action: 'resolved' | 'ignored' | 'open') => {
+ const handleClusterAction = async (
+ cluster: TelemetryCluster,
+ action: 'resolved' | 'ignored' | 'open'
+ ) => {
const pk = cluster.pk || '';
try {
- await fetch(`/api/telemetry/clusters/${encodeURIComponent(cluster.id)}?pk=${encodeURIComponent(pk)}`, {
- method: 'PATCH',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ status: action }),
- });
+ await fetch(
+ `/api/telemetry/clusters/${encodeURIComponent(cluster.id)}?pk=${encodeURIComponent(pk)}`,
+ {
+ method: 'PATCH',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ status: action }),
+ }
+ );
fetchEvents();
} catch {
// best effort
@@ -378,7 +396,8 @@ export default function ClientLogsPage() {
const handleGdprErasure = async () => {
if (!gdprUserId.trim()) return;
- if (!confirm(`Delete ALL telemetry data for user "${gdprUserId}"? This cannot be undone.`)) return;
+ if (!confirm(`Delete ALL telemetry data for user "${gdprUserId}"? This cannot be undone.`))
+ return;
setGdprLoading(true);
setGdprResult(null);
try {
@@ -402,7 +421,7 @@ export default function ClientLogsPage() {
};
// Client-side text filter
- const filteredEvents = events.filter((e) => {
+ const filteredEvents = events.filter(e => {
if (!searchQuery) return true;
const q = searchQuery.toLowerCase();
return (
@@ -417,10 +436,10 @@ export default function ClientLogsPage() {
});
// Stats
- const errorCount = events.filter((e) => e.eventType === 'error' || e.eventType === 'fatal').length;
- const warnCount = events.filter((e) => e.eventType === 'warn').length;
- const keyboardCount = events.filter((e) => e.channel === 'keyboard_extension').length;
- const uniqueSessions = new Set(events.map((e) => e.sessionId)).size;
+ const errorCount = events.filter(e => e.eventType === 'error' || e.eventType === 'fatal').length;
+ const warnCount = events.filter(e => e.eventType === 'warn').length;
+ const keyboardCount = events.filter(e => e.channel === 'keyboard_extension').length;
+ const uniqueSessions = new Set(events.map(e => e.sessionId)).size;
return (
@@ -539,7 +558,7 @@ export default function ClientLogsPage() {
setModule(e.target.value)}
+ onChange={e => setModule(e.target.value)}
/>
@@ -549,7 +568,7 @@ export default function ClientLogsPage() {
placeholder="Search events, errors, users..."
className="pl-8"
value={searchQuery}
- onChange={(e) => setSearchQuery(e.target.value)}
+ onChange={e => setSearchQuery(e.target.value)}
/>
@@ -612,18 +631,17 @@ export default function ClientLogsPage() {
) : filteredEvents.length === 0 ? (
- No telemetry events found. Events will appear here once clients start sending data.
+ No telemetry events found. Events will appear here once clients start
+ sending data.
) : (
- filteredEvents.map((evt) => (
+ filteredEvents.map(evt => (
<>
- setExpandedEvent(expandedEvent === evt.id ? null : evt.id)
- }
+ onClick={() => setExpandedEvent(expandedEvent === evt.id ? null : evt.id)}
>
{expandedEvent === evt.id ? (
@@ -690,9 +708,7 @@ export default function ClientLogsPage() {
User ID
-
- {evt.userId || '—'}
-
+ {evt.userId || '—'}
Install ID
@@ -716,7 +732,9 @@ export default function ClientLogsPage() {
{evt.errorDomain && (
- Error Domain
+
+ Error Domain
+
{evt.errorDomain}
)}
@@ -783,11 +801,12 @@ export default function ClientLogsPage() {
) : clusters.length === 0 ? (
- No error clusters found. Clusters form automatically when warn/error/fatal events arrive.
+ No error clusters found. Clusters form automatically when warn/error/fatal
+ events arrive.
) : (
- clusters.map((c) => (
+ clusters.map(c => (
{eventTypeBadge(c.severity)}
@@ -816,15 +835,24 @@ export default function ClientLogsPage() {
{c.status === 'resolved' ? (
-
+
Resolved
) : c.status === 'ignored' ? (
-
+
Ignored
) : (
-
+
Open
)}
@@ -903,7 +931,8 @@ export default function ClientLogsPage() {
- {ingestionMetrics.totalPiiBlocked} PII blocked, {ingestionMetrics.totalDuplicatesDropped} duplicates
+ {ingestionMetrics.totalPiiBlocked} PII blocked,{' '}
+ {ingestionMetrics.totalDuplicatesDropped} duplicates
@@ -951,15 +980,27 @@ export default function ClientLogsPage() {
) : geoData.length === 0 ? (
- No geo data available. Enable geo enrichment with TELEMETRY_GEO_ENABLED=true and configure TELEMETRY_GEO_API_URL.
+ No geo data available. Enable geo enrichment with{' '}
+ TELEMETRY_GEO_ENABLED=true and configure{' '}
+ TELEMETRY_GEO_API_URL.
) : (
-
-
+
+
[(value ?? 0).toLocaleString(), 'Events']}
+ formatter={(value: number | undefined) => [
+ (value ?? 0).toLocaleString(),
+ 'Events',
+ ]}
/>
@@ -1010,8 +1054,8 @@ export default function ClientLogsPage() {
GDPR Data Erasure
- Delete all telemetry events for a specific user. This action is irreversible
- and will be logged in the audit trail.
+ Delete all telemetry events for a specific user. This action is irreversible and
+ will be logged in the audit trail.
@@ -1019,7 +1063,7 @@ export default function ClientLogsPage() {
setGdprUserId(e.target.value)}
+ onChange={e => setGdprUserId(e.target.value)}
/>
{gdprResult && (
-
+
{gdprResult}
)}
diff --git a/dashboards/admin-web/src/app/(dashboard)/page.tsx b/dashboards/admin-web/src/app/(dashboard)/page.tsx
index 6d8a81ee..28df8d0b 100644
--- a/dashboards/admin-web/src/app/(dashboard)/page.tsx
+++ b/dashboards/admin-web/src/app/(dashboard)/page.tsx
@@ -365,8 +365,8 @@ export default function DashboardPage() {
-
-
+
+
@@ -381,7 +381,7 @@ export default function DashboardPage() {
@@ -408,7 +408,7 @@ export default function DashboardPage() {
border: '1px solid hsl(var(--border))',
}}
/>
-
+
diff --git a/dashboards/admin-web/src/app/(dashboard)/usage/page.tsx b/dashboards/admin-web/src/app/(dashboard)/usage/page.tsx
index b00238ce..49856300 100644
--- a/dashboards/admin-web/src/app/(dashboard)/usage/page.tsx
+++ b/dashboards/admin-web/src/app/(dashboard)/usage/page.tsx
@@ -56,10 +56,10 @@ import {
} from 'recharts';
const COLORS = [
- 'hsl(221, 83%, 53%)',
- 'hsl(142, 71%, 45%)',
- 'hsl(38, 92%, 50%)',
- 'hsl(280, 67%, 55%)',
+ 'hsl(var(--chart-1))',
+ 'hsl(var(--chart-2))',
+ 'hsl(var(--chart-4))',
+ 'hsl(var(--chart-5))',
];
function usageRecordsToDailyMetrics(records: ApiUsageRecord[]): DailyMetric[] {
@@ -88,8 +88,12 @@ export default function UsagePage() {
const [timeRange, setTimeRange] = useState('30d');
const [dailyMetrics, setDailyMetrics] = useState(mockDailyMetrics);
const [modelUsage, setModelUsage] = useState<(ApiModelBreakdown & { percentage: number })[]>([]);
- const [sourceUsage, setSourceUsage] = useState<(ApiSourceBreakdown & { percentage: number })[]>([]);
- const [productUsage, setProductUsage] = useState<(ApiProductBreakdown & { percentage: number })[]>([]);
+ const [sourceUsage, setSourceUsage] = useState<(ApiSourceBreakdown & { percentage: number })[]>(
+ []
+ );
+ const [productUsage, setProductUsage] = useState<
+ (ApiProductBreakdown & { percentage: number })[]
+ >([]);
const [users, setUsers] = useState(mockUsers);
const [cohorts, setCohorts] = useState([]);
const [selectedUserId, setSelectedUserId] = useState(null);
@@ -211,7 +215,8 @@ export default function UsagePage() {
- Viewing usage for: {users.find(u => u.id === selectedUserId)?.name || selectedUserId}
+ Viewing usage for:{' '}
+ {users.find(u => u.id === selectedUserId)?.name || selectedUserId}
({users.find(u => u.id === selectedUserId)?.email})
@@ -310,8 +315,8 @@ export default function UsagePage() {
-
-
+
+
@@ -327,7 +332,7 @@ export default function UsagePage() {
diff --git a/dashboards/admin-web/src/app/(dashboard)/users/[id]/page.tsx b/dashboards/admin-web/src/app/(dashboard)/users/[id]/page.tsx
index 8c7397ac..093036fa 100644
--- a/dashboards/admin-web/src/app/(dashboard)/users/[id]/page.tsx
+++ b/dashboards/admin-web/src/app/(dashboard)/users/[id]/page.tsx
@@ -276,8 +276,8 @@ export default function UserDetailPage() {
-
-
+
+
@@ -292,7 +292,7 @@ export default function UserDetailPage() {