refactor: unify "Executions" → "Exchanges" terminology
Rename all references from "Execution/executions/execCount" to "Exchange/exchanges/exchangeCount" to align with Apache Camel's native Exchange concept. Java class names (CamelExecutionException, HttpOperationFailedException) are preserved as-is. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -24,24 +24,24 @@ import { MonoText } from '../../design-system/primitives/MonoText/MonoText'
|
||||
import { Badge } from '../../design-system/primitives/Badge/Badge'
|
||||
|
||||
// Mock data
|
||||
import { executions, type Execution } from '../../mocks/executions'
|
||||
import { exchanges, type Exchange } from '../../mocks/exchanges'
|
||||
import { routes } from '../../mocks/routes'
|
||||
import { agents } from '../../mocks/agents'
|
||||
import { kpiMetrics } from '../../mocks/metrics'
|
||||
|
||||
// ─── Sidebar app list (static) ───────────────────────────────────────────────
|
||||
const APPS = [
|
||||
{ id: 'order-service', name: 'order-service', agentCount: 2, health: 'live' as const, execCount: 1433 },
|
||||
{ id: 'payment-svc', name: 'payment-svc', agentCount: 1, health: 'live' as const, execCount: 912 },
|
||||
{ id: 'shipment-tracker', name: 'shipment-tracker', agentCount: 2, health: 'live' as const, execCount: 471 },
|
||||
{ id: 'notification-hub', name: 'notification-hub', agentCount: 1, health: 'stale' as const, execCount: 128 },
|
||||
{ id: 'order-service', name: 'order-service', agentCount: 2, health: 'live' as const, exchangeCount: 1433 },
|
||||
{ id: 'payment-svc', name: 'payment-svc', agentCount: 1, health: 'live' as const, exchangeCount: 912 },
|
||||
{ id: 'shipment-tracker', name: 'shipment-tracker', agentCount: 2, health: 'live' as const, exchangeCount: 471 },
|
||||
{ id: 'notification-hub', name: 'notification-hub', agentCount: 1, health: 'stale' as const, exchangeCount: 128 },
|
||||
]
|
||||
|
||||
// ─── Sidebar routes (top 3) ───────────────────────────────────────────────────
|
||||
const SIDEBAR_ROUTES = routes.slice(0, 3).map((r) => ({
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
execCount: r.execCount,
|
||||
exchangeCount: r.exchangeCount,
|
||||
}))
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
||||
@@ -55,7 +55,7 @@ function formatTimestamp(date: Date): string {
|
||||
return date.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit', second: '2-digit' })
|
||||
}
|
||||
|
||||
function statusToVariant(status: Execution['status']): 'success' | 'error' | 'running' | 'warning' {
|
||||
function statusToVariant(status: Exchange['status']): 'success' | 'error' | 'running' | 'warning' {
|
||||
switch (status) {
|
||||
case 'completed': return 'success'
|
||||
case 'failed': return 'error'
|
||||
@@ -64,7 +64,7 @@ function statusToVariant(status: Execution['status']): 'success' | 'error' | 'ru
|
||||
}
|
||||
}
|
||||
|
||||
function statusLabel(status: Execution['status']): string {
|
||||
function statusLabel(status: Exchange['status']): string {
|
||||
switch (status) {
|
||||
case 'completed': return 'OK'
|
||||
case 'failed': return 'ERR'
|
||||
@@ -74,7 +74,7 @@ function statusLabel(status: Execution['status']): string {
|
||||
}
|
||||
|
||||
// ─── Table columns ────────────────────────────────────────────────────────────
|
||||
const COLUMNS: Column<Execution>[] = [
|
||||
const COLUMNS: Column<Exchange>[] = [
|
||||
{
|
||||
key: 'status',
|
||||
header: 'Status',
|
||||
@@ -142,7 +142,7 @@ const COLUMNS: Column<Execution>[] = [
|
||||
},
|
||||
]
|
||||
|
||||
function durationClass(ms: number, status: Execution['status']): string {
|
||||
function durationClass(ms: number, status: Exchange['status']): string {
|
||||
if (status === 'failed') return styles.durBreach
|
||||
if (ms < 100) return styles.durFast
|
||||
if (ms < 200) return styles.durNormal
|
||||
@@ -154,10 +154,10 @@ function durationClass(ms: number, status: Execution['status']): string {
|
||||
function buildSearchData(): SearchResult[] {
|
||||
const results: SearchResult[] = []
|
||||
|
||||
for (const exec of executions) {
|
||||
for (const exec of exchanges) {
|
||||
results.push({
|
||||
id: exec.id,
|
||||
category: 'execution',
|
||||
category: 'exchange',
|
||||
title: `${exec.orderId} — ${exec.route}`,
|
||||
badges: [{ label: statusLabel(exec.status), color: statusToVariant(exec.status) }],
|
||||
meta: `${exec.correlationId} · ${formatDuration(exec.durationMs)} · ${exec.customer}`,
|
||||
@@ -171,7 +171,7 @@ function buildSearchData(): SearchResult[] {
|
||||
category: 'route',
|
||||
title: route.name,
|
||||
badges: [{ label: route.group }],
|
||||
meta: `${route.execCount.toLocaleString()} executions · ${route.successRate}% success`,
|
||||
meta: `${route.exchangeCount.toLocaleString()} exchanges · ${route.successRate}% success`,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -192,11 +192,11 @@ const SEARCH_DATA = buildSearchData()
|
||||
|
||||
// ─── Filter options ───────────────────────────────────────────────────────────
|
||||
const STATUS_FILTERS = [
|
||||
{ label: 'All', value: 'all', count: executions.length },
|
||||
{ label: 'OK', value: 'completed', count: executions.filter((e) => e.status === 'completed').length, color: 'success' as const },
|
||||
{ label: 'Warn', value: 'warning', count: executions.filter((e) => e.status === 'warning').length },
|
||||
{ label: 'Error', value: 'failed', count: executions.filter((e) => e.status === 'failed').length, color: 'error' as const },
|
||||
{ label: 'Running', value: 'running', count: executions.filter((e) => e.status === 'running').length, color: 'running' as const },
|
||||
{ label: 'All', value: 'all', count: exchanges.length },
|
||||
{ label: 'OK', value: 'completed', count: exchanges.filter((e) => e.status === 'completed').length, color: 'success' as const },
|
||||
{ label: 'Warn', value: 'warning', count: exchanges.filter((e) => e.status === 'warning').length },
|
||||
{ label: 'Error', value: 'failed', count: exchanges.filter((e) => e.status === 'failed').length, color: 'error' as const },
|
||||
{ label: 'Running', value: 'running', count: exchanges.filter((e) => e.status === 'running').length, color: 'running' as const },
|
||||
]
|
||||
|
||||
const SHORTCUTS = [
|
||||
@@ -213,12 +213,12 @@ export function Dashboard() {
|
||||
const [search, setSearch] = useState('')
|
||||
const [selectedId, setSelectedId] = useState<string | undefined>()
|
||||
const [panelOpen, setPanelOpen] = useState(false)
|
||||
const [selectedExecution, setSelectedExecution] = useState<Execution | null>(null)
|
||||
const [selectedExchange, setSelectedExchange] = useState<Exchange | null>(null)
|
||||
const [paletteOpen, setPaletteOpen] = useState(false)
|
||||
|
||||
// Filter executions
|
||||
const filteredExecutions = useMemo(() => {
|
||||
let data = executions
|
||||
// Filter exchanges
|
||||
const filteredExchanges = useMemo(() => {
|
||||
let data = exchanges
|
||||
|
||||
const statusFilter = activeFilters.find((f) =>
|
||||
['completed', 'failed', 'running', 'warning', 'all'].includes(f.value),
|
||||
@@ -242,20 +242,20 @@ export function Dashboard() {
|
||||
return data
|
||||
}, [activeFilters, search])
|
||||
|
||||
function handleRowClick(row: Execution) {
|
||||
function handleRowClick(row: Exchange) {
|
||||
setSelectedId(row.id)
|
||||
setSelectedExecution(row)
|
||||
setSelectedExchange(row)
|
||||
setPanelOpen(true)
|
||||
}
|
||||
|
||||
function handleRowAccent(row: Execution): 'error' | 'warning' | undefined {
|
||||
function handleRowAccent(row: Exchange): 'error' | 'warning' | undefined {
|
||||
if (row.status === 'failed') return 'error'
|
||||
if (row.status === 'warning') return 'warning'
|
||||
return undefined
|
||||
}
|
||||
|
||||
// Build detail panel tabs for selected execution
|
||||
const detailTabs = selectedExecution
|
||||
// Build detail panel tabs for selected exchange
|
||||
const detailTabs = selectedExchange
|
||||
? [
|
||||
{
|
||||
label: 'Overview',
|
||||
@@ -264,43 +264,43 @@ export function Dashboard() {
|
||||
<div className={styles.overviewTab}>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Order ID</span>
|
||||
<MonoText size="sm">{selectedExecution.orderId}</MonoText>
|
||||
<MonoText size="sm">{selectedExchange.orderId}</MonoText>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Route</span>
|
||||
<span>{selectedExecution.route}</span>
|
||||
<span>{selectedExchange.route}</span>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Status</span>
|
||||
<span className={styles.statusCell}>
|
||||
<StatusDot variant={statusToVariant(selectedExecution.status)} />
|
||||
<span>{statusLabel(selectedExecution.status)}</span>
|
||||
<StatusDot variant={statusToVariant(selectedExchange.status)} />
|
||||
<span>{statusLabel(selectedExchange.status)}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Duration</span>
|
||||
<MonoText size="sm">{formatDuration(selectedExecution.durationMs)}</MonoText>
|
||||
<MonoText size="sm">{formatDuration(selectedExchange.durationMs)}</MonoText>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Customer</span>
|
||||
<MonoText size="sm">{selectedExecution.customer}</MonoText>
|
||||
<MonoText size="sm">{selectedExchange.customer}</MonoText>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Agent</span>
|
||||
<MonoText size="sm">{selectedExecution.agent}</MonoText>
|
||||
<MonoText size="sm">{selectedExchange.agent}</MonoText>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Correlation ID</span>
|
||||
<MonoText size="xs">{selectedExecution.correlationId}</MonoText>
|
||||
<MonoText size="xs">{selectedExchange.correlationId}</MonoText>
|
||||
</div>
|
||||
<div className={styles.overviewRow}>
|
||||
<span className={styles.overviewLabel}>Timestamp</span>
|
||||
<MonoText size="xs">{selectedExecution.timestamp.toISOString()}</MonoText>
|
||||
<MonoText size="xs">{selectedExchange.timestamp.toISOString()}</MonoText>
|
||||
</div>
|
||||
{selectedExecution.errorMessage && (
|
||||
{selectedExchange.errorMessage && (
|
||||
<div className={styles.errorBlock}>
|
||||
<div className={styles.errorClass}>{selectedExecution.errorClass}</div>
|
||||
<div className={styles.errorMessage}>{selectedExecution.errorMessage}</div>
|
||||
<div className={styles.errorClass}>{selectedExchange.errorClass}</div>
|
||||
<div className={styles.errorMessage}>{selectedExchange.errorMessage}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -312,8 +312,8 @@ export function Dashboard() {
|
||||
content: (
|
||||
<div className={styles.processorsTab}>
|
||||
<ProcessorTimeline
|
||||
processors={selectedExecution.processors}
|
||||
totalMs={selectedExecution.durationMs}
|
||||
processors={selectedExchange.processors}
|
||||
totalMs={selectedExchange.durationMs}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
@@ -332,13 +332,13 @@ export function Dashboard() {
|
||||
value: 'error',
|
||||
content: (
|
||||
<div className={styles.errorTab}>
|
||||
{selectedExecution.errorMessage ? (
|
||||
{selectedExchange.errorMessage ? (
|
||||
<>
|
||||
<div className={styles.errorClass}>{selectedExecution.errorClass}</div>
|
||||
<pre className={styles.errorPre}>{selectedExecution.errorMessage}</pre>
|
||||
<div className={styles.errorClass}>{selectedExchange.errorClass}</div>
|
||||
<pre className={styles.errorPre}>{selectedExchange.errorMessage}</pre>
|
||||
</>
|
||||
) : (
|
||||
<div className={styles.emptyTabMsg}>No error for this execution.</div>
|
||||
<div className={styles.emptyTabMsg}>No error for this exchange.</div>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
@@ -358,11 +358,11 @@ export function Dashboard() {
|
||||
/>
|
||||
}
|
||||
detail={
|
||||
selectedExecution ? (
|
||||
selectedExchange ? (
|
||||
<DetailPanel
|
||||
open={panelOpen}
|
||||
onClose={() => setPanelOpen(false)}
|
||||
title={`${selectedExecution.orderId} — ${selectedExecution.route}`}
|
||||
title={`${selectedExchange.orderId} — ${selectedExchange.route}`}
|
||||
tabs={detailTabs}
|
||||
/>
|
||||
) : undefined
|
||||
@@ -410,13 +410,13 @@ export function Dashboard() {
|
||||
className={styles.filterBar}
|
||||
/>
|
||||
|
||||
{/* Executions table */}
|
||||
{/* Exchanges table */}
|
||||
<div className={styles.tableSection}>
|
||||
<div className={styles.tableHeader}>
|
||||
<span className={styles.tableTitle}>Recent Executions</span>
|
||||
<span className={styles.tableTitle}>Recent Exchanges</span>
|
||||
<div className={styles.tableRight}>
|
||||
<span className={styles.tableMeta}>
|
||||
{filteredExecutions.length.toLocaleString()} of {executions.length.toLocaleString()} executions
|
||||
{filteredExchanges.length.toLocaleString()} of {exchanges.length.toLocaleString()} exchanges
|
||||
</span>
|
||||
<Badge label="LIVE" color="success" />
|
||||
</div>
|
||||
@@ -424,7 +424,7 @@ export function Dashboard() {
|
||||
|
||||
<DataTable
|
||||
columns={COLUMNS}
|
||||
data={filteredExecutions}
|
||||
data={filteredExchanges}
|
||||
onRowClick={handleRowClick}
|
||||
selectedId={selectedId}
|
||||
sortable
|
||||
|
||||
Reference in New Issue
Block a user