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:
53
ui/src/utils/agent-utils.ts
Normal file
53
ui/src/utils/agent-utils.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { FeedEvent } from '@cameleer/design-system';
|
||||
import type { LogEntry } from '@cameleer/design-system';
|
||||
import { UserPlus, UserMinus, Play, Square, Clock, Skull, HeartPulse, Route, Send, Activity } from 'lucide-react';
|
||||
import { createElement } from 'react';
|
||||
|
||||
export 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`;
|
||||
}
|
||||
|
||||
export 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';
|
||||
}
|
||||
}
|
||||
|
||||
export function 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';
|
||||
}
|
||||
}
|
||||
|
||||
export function eventIcon(type: string) {
|
||||
switch (type) {
|
||||
case 'REGISTERED': return createElement(UserPlus, { size: 14 });
|
||||
case 'DEREGISTERED': return createElement(UserMinus, { size: 14 });
|
||||
case 'AGENT_STARTED': return createElement(Play, { size: 14 });
|
||||
case 'AGENT_STOPPED': return createElement(Square, { size: 14 });
|
||||
case 'WENT_STALE': return createElement(Clock, { size: 14 });
|
||||
case 'WENT_DEAD': return createElement(Skull, { size: 14 });
|
||||
case 'RECOVERED': return createElement(HeartPulse, { size: 14 });
|
||||
case 'ROUTE_STATE_CHANGED': return createElement(Route, { size: 14 });
|
||||
case 'COMMAND_DELIVERED':
|
||||
case 'COMMAND_ACKNOWLEDGED': return createElement(Send, { size: 14 });
|
||||
default: return createElement(Activity, { size: 14 });
|
||||
}
|
||||
}
|
||||
20
ui/src/utils/config-draft-utils.ts
Normal file
20
ui/src/utils/config-draft-utils.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export function applyTracedProcessorUpdate(
|
||||
prev: Record<string, string>,
|
||||
processorId: string,
|
||||
mode: string,
|
||||
): Record<string, string> {
|
||||
if (mode === 'REMOVE') {
|
||||
const next = { ...prev };
|
||||
delete next[processorId];
|
||||
return next;
|
||||
}
|
||||
return { ...prev, [processorId]: mode };
|
||||
}
|
||||
|
||||
export function applyRouteRecordingUpdate(
|
||||
prev: Record<string, boolean>,
|
||||
routeId: string,
|
||||
recording: boolean,
|
||||
): Record<string, boolean> {
|
||||
return { ...prev, [routeId]: recording };
|
||||
}
|
||||
32
ui/src/utils/format-utils.ts
Normal file
32
ui/src/utils/format-utils.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export function formatDuration(ms: number): string {
|
||||
if (ms >= 60_000) return `${(ms / 1000).toFixed(0)}s`;
|
||||
if (ms >= 1000) return `${(ms / 1000).toFixed(2)}s`;
|
||||
return `${ms}ms`;
|
||||
}
|
||||
|
||||
export function formatDurationShort(ms: number | undefined): string {
|
||||
if (ms == null) return '-';
|
||||
if (ms < 1000) return `${ms}ms`;
|
||||
return `${(ms / 1000).toFixed(1)}s`;
|
||||
}
|
||||
|
||||
export function statusLabel(s: string): string {
|
||||
switch (s) {
|
||||
case 'COMPLETED': return 'OK';
|
||||
case 'FAILED': return 'ERR';
|
||||
case 'RUNNING': return 'RUN';
|
||||
default: return s;
|
||||
}
|
||||
}
|
||||
|
||||
export 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`;
|
||||
}
|
||||
Reference in New Issue
Block a user