import { useMemo } from 'react'; import { useNavigate } from 'react-router'; import { DataTable, Badge, MonoText } from '@cameleer/design-system'; import type { Column } from '@cameleer/design-system'; import { useAllApplicationConfigs } from '../../api/queries/commands'; import type { ApplicationConfig } from '../../api/queries/commands'; import styles from './AppConfigPage.module.css'; type ConfigRow = ApplicationConfig & { id: string }; type BadgeColor = 'primary' | 'success' | 'warning' | 'error' | 'running' | 'auto'; function timeAgo(iso?: string): string { if (!iso) return '\u2014'; const diff = Date.now() - new Date(iso).getTime(); const secs = Math.floor(diff / 1000); if (secs < 60) return `${secs}s ago`; const mins = Math.floor(secs / 60); if (mins < 60) return `${mins}m ago`; const hours = Math.floor(mins / 60); if (hours < 24) return `${hours}h ago`; return `${Math.floor(hours / 24)}d ago`; } function logLevelColor(level?: string): BadgeColor { switch (level?.toUpperCase()) { case 'ERROR': return 'error'; case 'WARN': return 'warning'; case 'DEBUG': return 'running'; default: return 'success'; } } function engineLevelColor(level?: string): BadgeColor { switch (level?.toUpperCase()) { case 'NONE': return 'error'; case 'MINIMAL': return 'warning'; case 'COMPLETE': return 'running'; default: return 'success'; } } function payloadColor(mode?: string): BadgeColor { switch (mode?.toUpperCase()) { case 'INPUT': case 'OUTPUT': return 'warning'; case 'BOTH': return 'running'; default: return 'auto'; } } export default function AppConfigPage() { const navigate = useNavigate(); const { data: configs } = useAllApplicationConfigs(); const columns: Column[] = useMemo(() => [ { key: 'application', header: 'Application', sortable: true, render: (_val, row) => {row.application}, }, { key: 'logForwardingLevel', header: 'Log Level', render: (_val, row) => { const val = row.logForwardingLevel ?? 'INFO'; return ; }, }, { key: 'engineLevel', header: 'Engine Level', render: (_val, row) => { const val = row.engineLevel ?? 'REGULAR'; return ; }, }, { key: 'payloadCaptureMode', header: 'Payload Capture', render: (_val, row) => { const val = row.payloadCaptureMode ?? 'NONE'; return ; }, }, { key: 'metricsEnabled', header: 'Metrics', width: '80px', render: (_val, row) => ( ), }, { key: 'tracedProcessors', header: 'Traced', width: '70px', render: (_val, row) => { const count = row.tracedProcessors ? Object.keys(row.tracedProcessors).length : 0; return count > 0 ? : 0; }, }, { key: 'taps', header: 'Taps', width: '70px', render: (_val, row) => { const total = row.taps?.length ?? 0; const enabled = row.taps?.filter(t => t.enabled).length ?? 0; if (total === 0) return 0; return ; }, }, { key: 'version', header: 'v', width: '40px', render: (_val, row) => {row.version}, }, { key: 'updatedAt', header: 'Updated', render: (_val, row) => {timeAgo(row.updatedAt)}, }, ], []); function handleRowClick(row: ConfigRow) { navigate(`/admin/appconfig/${row.application}`); } return (
columns={columns} data={(configs ?? []).map(c => ({ ...c, id: c.application }))} onRowClick={handleRowClick} pageSize={50} />
); }