refactor: extract duplicated utility functions into shared modules
Consolidate 20+ duplicate function definitions across UI components into three shared util files (format-utils, agent-utils, config-draft-utils). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useState, useMemo, useCallback } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
import { ExternalLink, RefreshCw, Pencil, UserPlus, UserMinus, Play, Square, Clock, Skull, HeartPulse, Route, Send, Activity } from 'lucide-react';
|
||||
import { ExternalLink, RefreshCw, Pencil } from 'lucide-react';
|
||||
import {
|
||||
StatCard, StatusDot, Badge, MonoText,
|
||||
GroupCard, DataTable, EventFeed,
|
||||
@@ -13,31 +13,11 @@ import { useApplicationLogs } from '../../api/queries/logs';
|
||||
import { useApplicationConfig, useUpdateApplicationConfig } from '../../api/queries/commands';
|
||||
import type { ConfigUpdateResponse } from '../../api/queries/commands';
|
||||
import type { AgentInstance } from '../../api/types';
|
||||
import { timeAgo } from '../../utils/format-utils';
|
||||
import { formatUptime, mapLogLevel, eventSeverity, eventIcon } from '../../utils/agent-utils';
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
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 formatUptime(seconds?: number): string {
|
||||
if (!seconds) return '\u2014';
|
||||
const days = Math.floor(seconds / 86400);
|
||||
const hours = Math.floor((seconds % 86400) / 3600);
|
||||
const mins = Math.floor((seconds % 3600) / 60);
|
||||
if (days > 0) return `${days}d ${hours}h`;
|
||||
if (hours > 0) return `${hours}h ${mins}m`;
|
||||
return `${mins}m`;
|
||||
}
|
||||
|
||||
function formatErrorRate(rate?: number): string {
|
||||
if (rate == null) return '\u2014';
|
||||
return `${(rate * 100).toFixed(1)}%`;
|
||||
@@ -104,16 +84,6 @@ const LOG_LEVEL_ITEMS: ButtonGroupItem[] = [
|
||||
{ value: 'trace', label: 'Trace', color: 'var(--text-muted)' },
|
||||
];
|
||||
|
||||
function mapLogLevel(level: string): LogEntry['level'] {
|
||||
switch (level?.toUpperCase()) {
|
||||
case 'ERROR': return 'error';
|
||||
case 'WARN': case 'WARNING': return 'warn';
|
||||
case 'DEBUG': return 'debug';
|
||||
case 'TRACE': return 'trace';
|
||||
default: return 'info';
|
||||
}
|
||||
}
|
||||
|
||||
// ── AgentHealth page ─────────────────────────────────────────────────────────
|
||||
|
||||
export default function AgentHealth() {
|
||||
@@ -195,35 +165,6 @@ export default function AgentHealth() {
|
||||
|
||||
// Map events to FeedEvent
|
||||
const feedEvents: FeedEvent[] = useMemo(() => {
|
||||
const eventIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case 'REGISTERED': return <UserPlus size={14} />;
|
||||
case 'DEREGISTERED': return <UserMinus size={14} />;
|
||||
case 'AGENT_STARTED': return <Play size={14} />;
|
||||
case 'AGENT_STOPPED': return <Square size={14} />;
|
||||
case 'WENT_STALE': return <Clock size={14} />;
|
||||
case 'WENT_DEAD': return <Skull size={14} />;
|
||||
case 'RECOVERED': return <HeartPulse size={14} />;
|
||||
case 'ROUTE_STATE_CHANGED': return <Route size={14} />;
|
||||
case 'COMMAND_DELIVERED':
|
||||
case 'COMMAND_ACKNOWLEDGED': return <Send size={14} />;
|
||||
default: return <Activity size={14} />;
|
||||
}
|
||||
};
|
||||
|
||||
const eventSeverity = (type: string): FeedEvent['severity'] => {
|
||||
switch (type) {
|
||||
case 'WENT_DEAD':
|
||||
case 'AGENT_STOPPED':
|
||||
case 'DEREGISTERED': return 'error';
|
||||
case 'WENT_STALE': return 'warning';
|
||||
case 'RECOVERED':
|
||||
case 'REGISTERED':
|
||||
case 'AGENT_STARTED': return 'success';
|
||||
default: return 'running';
|
||||
}
|
||||
};
|
||||
|
||||
const mapped = (events ?? []).map((e: { id: number; instanceId: string; eventType: string; detail: string; timestamp: string }) => ({
|
||||
id: String(e.id),
|
||||
severity: eventSeverity(e.eventType),
|
||||
|
||||
Reference in New Issue
Block a user