diff --git a/src/mocks/exchanges.ts b/src/mocks/exchanges.ts index a8d5d84..c39f17a 100644 --- a/src/mocks/exchanges.ts +++ b/src/mocks/exchanges.ts @@ -313,3 +313,74 @@ export const exchanges: Exchange[] = [ ], }, ] + +// ── Generate additional exchanges to reach ~200 total ──────────────────────── + +const GEN_ROUTES = [ + 'order-intake', 'payment-validate', 'order-enrichment', 'shipment-dispatch', + 'payment-process', 'shipment-track', 'inventory-sync', 'notification-send', + 'audit-log', 'customer-update', 'refund-process', 'invoice-generate', +] +const GEN_ROUTE_GROUPS = [ + 'order-flow', 'payment-flow', 'shipment-flow', 'inventory-flow', + 'notification-flow', 'audit-flow', 'customer-flow', 'billing-flow', +] +const GEN_AGENTS = ['prod-1', 'prod-2', 'prod-3', 'prod-4'] +const GEN_STATUSES: Exchange['status'][] = [ + 'completed', 'completed', 'completed', 'completed', 'completed', + 'completed', 'failed', 'warning', 'running', +] +const GEN_PROCESSORS: ProcessorData[][] = [ + [ + { name: 'from(jms:queue)', type: 'consumer', durationMs: 4, status: 'ok', startMs: 0 }, + { name: 'unmarshal(json)', type: 'transform', durationMs: 6, status: 'ok', startMs: 4 }, + { name: 'validate(schema)', type: 'process', durationMs: 10, status: 'ok', startMs: 10 }, + { name: 'to(target)', type: 'to', durationMs: 15, status: 'ok', startMs: 20 }, + ], + [ + { name: 'from(jms:queue)', type: 'consumer', durationMs: 5, status: 'ok', startMs: 0 }, + { name: 'enrich(external-api)', type: 'enrich', durationMs: 120, status: 'slow', startMs: 5 }, + { name: 'to(target)', type: 'to', durationMs: 20, status: 'ok', startMs: 125 }, + ], + [ + { name: 'from(jms:queue)', type: 'consumer', durationMs: 3, status: 'ok', startMs: 0 }, + { name: 'to(external-gateway)', type: 'to', durationMs: 400, status: 'fail', startMs: 3 }, + ], +] +const GEN_ERRORS = [ + { msg: 'org.apache.camel.CamelExecutionException: Timeout after 5000ms', cls: 'org.apache.camel.CamelExecutionException' }, + { msg: 'java.sql.SQLTransientConnectionException: Connection pool exhausted', cls: 'java.sql.SQLTransientConnectionException' }, + { msg: 'org.apache.camel.component.http.HttpOperationFailedException: HTTP 502 Bad Gateway', cls: 'org.apache.camel.component.http.HttpOperationFailedException' }, +] + +const BASE_TIME = new Date('2026-03-18T08:00:00').getTime() + +for (let i = 0; i < 185; i++) { + const idx = exchanges.length + const status = GEN_STATUSES[i % GEN_STATUSES.length] + const route = GEN_ROUTES[i % GEN_ROUTES.length] + const routeGroup = GEN_ROUTE_GROUPS[i % GEN_ROUTE_GROUPS.length] + const isFailed = status === 'failed' + const durationMs = isFailed + ? 1000 + ((i * 37) % 4000) + : status === 'running' + ? 10000 + ((i * 53) % 20000) + : 30 + ((i * 73) % 400) + const err = isFailed ? GEN_ERRORS[i % GEN_ERRORS.length] : undefined + + exchanges.push({ + id: `E-2026-03-18-${String(idx + 200).padStart(5, '0')}`, + orderId: `OP-${80000 + idx}`, + customer: `CUST-${10000 + ((i * 131) % 90000)}`, + route, + routeGroup, + status, + durationMs, + timestamp: new Date(BASE_TIME - i * 2 * 60 * 1000), + correlationId: `cmr-${i.toString(16).padStart(8, '0')}-gen`, + agent: GEN_AGENTS[i % GEN_AGENTS.length], + ...(err ? { errorMessage: err.msg, errorClass: err.cls } : {}), + processors: GEN_PROCESSORS[i % GEN_PROCESSORS.length].map((p) => ({ ...p })), + ...(i % 3 === 0 ? { correlationGroup: `${routeGroup}-${String(Math.floor(i / 3)).padStart(3, '0')}` } : {}), + }) +} diff --git a/src/pages/Dashboard/Dashboard.module.css b/src/pages/Dashboard/Dashboard.module.css index 72fb682..b508c2b 100644 --- a/src/pages/Dashboard/Dashboard.module.css +++ b/src/pages/Dashboard/Dashboard.module.css @@ -4,7 +4,10 @@ overflow-y: auto; padding: 20px 24px 40px; min-width: 0; + min-height: 0; background: var(--bg-body); + display: flex; + flex-direction: column; } /* Filter bar spacing */ @@ -19,6 +22,10 @@ border-radius: var(--radius-lg); box-shadow: var(--shadow-card); overflow: hidden; + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; } .tableHeader { diff --git a/src/pages/Dashboard/Dashboard.tsx b/src/pages/Dashboard/Dashboard.tsx index 3f71f7f..ed63d96 100644 --- a/src/pages/Dashboard/Dashboard.tsx +++ b/src/pages/Dashboard/Dashboard.tsx @@ -425,6 +425,7 @@ export function Dashboard() { selectedId={selectedId} sortable flush + fillHeight rowAccent={handleRowAccent} expandedContent={(row) => row.errorMessage ? ( diff --git a/src/pages/Inventory/sections/CompositesSection.tsx b/src/pages/Inventory/sections/CompositesSection.tsx index 49bbf64..84e7cae 100644 --- a/src/pages/Inventory/sections/CompositesSection.tsx +++ b/src/pages/Inventory/sections/CompositesSection.tsx @@ -135,13 +135,27 @@ interface TableRow { exchanges: number } -const TABLE_DATA: TableRow[] = [ - { id: '1', name: 'order-ingest', method: 'POST', status: 'live', exchanges: 1243 }, - { id: '2', name: 'payment-validate', method: 'POST', status: 'live', exchanges: 987 }, - { id: '3', name: 'inventory-check', method: 'GET', status: 'stale', exchanges: 432 }, - { id: '4', name: 'notify-customer', method: 'POST', status: 'live', exchanges: 876 }, - { id: '5', name: 'archive-order', method: 'PUT', status: 'dead', exchanges: 54 }, +const ROUTE_PREFIXES = [ + 'order', 'payment', 'inventory', 'customer', 'shipment', 'user', 'cart', + 'refund', 'stock', 'email', 'webhook', 'cache', 'log', 'rate', 'health', + 'session', 'config', 'metrics', 'batch', 'audit', 'invoice', 'product', + 'catalog', 'search', 'report', 'export', 'import', 'sync', 'alert', 'ticket', ] +const ROUTE_SUFFIXES = [ + 'ingest', 'validate', 'check', 'notify', 'archive', 'track', 'auth', + 'update', 'process', 'sync', 'dispatch', 'relay', 'invalidate', 'aggregate', + 'limit', 'refresh', 'reload', 'export', 'import', 'purge', +] +const METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] +const STATUSES = ['live', 'live', 'live', 'live', 'stale', 'stale', 'dead'] + +const TABLE_DATA: TableRow[] = Array.from({ length: 500 }, (_, i) => ({ + id: String(i + 1), + name: `${ROUTE_PREFIXES[i % ROUTE_PREFIXES.length]}-${ROUTE_SUFFIXES[(i * 7) % ROUTE_SUFFIXES.length]}`, + method: METHODS[i % METHODS.length], + status: STATUSES[i % STATUSES.length], + exchanges: ((i * 1337 + 421) % 9990) + 10, +})) const NOW = new Date() const minsAgo = (n: number) => new Date(NOW.getTime() - n * 60 * 1000) @@ -468,12 +482,13 @@ export function CompositesSection() { title="DataTable" description="Sortable, paginated table with row click, accent rows, and page size selector." > -
+