diff --git a/ui/src/pages/Exchanges/ExchangesPage.tsx b/ui/src/pages/Exchanges/ExchangesPage.tsx index 9d6f702f..53547e54 100644 --- a/ui/src/pages/Exchanges/ExchangesPage.tsx +++ b/ui/src/pages/Exchanges/ExchangesPage.tsx @@ -1,5 +1,5 @@ import { useState, useMemo, useCallback, useRef, useEffect } from 'react'; -import { useNavigate, useLocation } from 'react-router'; +import { useNavigate, useLocation, useParams } from 'react-router'; import { useGlobalFilters } from '@cameleer/design-system'; import { useExecutionDetail } from '../../api/queries/executions'; import { useDiagramByRoute } from '../../api/queries/diagrams'; @@ -16,6 +16,7 @@ import type { SelectedExchange } from '../Dashboard/Dashboard'; export default function ExchangesPage() { const navigate = useNavigate(); const location = useLocation(); + const { appId: scopedAppId, routeId: scopedRouteId } = useParams<{ appId?: string; routeId?: string }>(); // Restore selection from browser history state (enables Back/Forward) const stateSelected = (location.state as any)?.selectedExchange as SelectedExchange | undefined; @@ -70,12 +71,18 @@ export default function ExchangesPage() { document.addEventListener('pointerup', onUp); }, []); - // No exchange selected: full-width Dashboard - if (!selected) { + // Show split view when a route is scoped (sidebar) or an exchange is selected + const showSplit = !!selected || !!scopedRouteId; + + if (!showSplit) { return ; } - // Exchange selected: resizable split — Dashboard on left, diagram on right + // Determine what the right panel shows + const panelAppId = selected?.applicationName ?? scopedAppId!; + const panelRouteId = selected?.routeId ?? scopedRouteId!; + const panelExchangeId = selected?.executionId ?? undefined; + return (
@@ -84,9 +91,9 @@ export default function ExchangesPage() {
@@ -100,7 +107,7 @@ export default function ExchangesPage() { interface DiagramPanelProps { appId: string; routeId: string; - exchangeId: string; + exchangeId?: string; onCorrelatedSelect: (executionId: string, applicationName: string, routeId: string) => void; onClearSelection: () => void; } @@ -111,7 +118,8 @@ function DiagramPanel({ appId, routeId, exchangeId, onCorrelatedSelect, onClearS const timeFrom = timeRange.start.toISOString(); const timeTo = timeRange.end.toISOString(); - const { data: detail } = useExecutionDetail(exchangeId); + const { data: detail } = useExecutionDetail(exchangeId ?? null); + const diagramQuery = useDiagramByRoute(appId, routeId); const { data: catalog } = useRouteCatalog(timeFrom, timeTo); const knownRouteIds = useMemo(() => { @@ -132,7 +140,8 @@ function DiagramPanel({ appId, routeId, exchangeId, onCorrelatedSelect, onClearS } }, [appId, navigate]); - if (detail) { + // Exchange selected: show header + execution diagram + if (exchangeId && detail) { return ( <> @@ -146,9 +155,22 @@ function DiagramPanel({ appId, routeId, exchangeId, onCorrelatedSelect, onClearS ); } + // No exchange selected: show topology-only diagram + if (diagramQuery.data) { + return ( + + ); + } + return (
- Loading execution... + Loading diagram...
); }