fix: Cmd-K exchange selection reads exchangeId from URL params
ExchangesPage ignored the exchangeId URL parameter, so selecting an exchange from the command palette navigated to the right URL but never displayed the execution overlay. Now derives selection from URL params as fallback, and LayoutShell passes selectedExchange in state for exchange/attribute results. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,17 +20,35 @@ 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 }>();
|
||||
const { appId: scopedAppId, routeId: scopedRouteId, exchangeId: scopedExchangeId } =
|
||||
useParams<{ appId?: string; routeId?: string; exchangeId?: string }>();
|
||||
|
||||
// Restore selection from browser history state (enables Back/Forward)
|
||||
const stateSelected = (location.state as any)?.selectedExchange as SelectedExchange | undefined;
|
||||
const [selected, setSelectedInternal] = useState<SelectedExchange | null>(stateSelected ?? null);
|
||||
|
||||
// Sync from history state when the user navigates Back/Forward
|
||||
// Derive selection from URL params when no state-based selection exists (Cmd-K, bookmarks)
|
||||
const urlDerivedExchange: SelectedExchange | null =
|
||||
(scopedExchangeId && scopedAppId && scopedRouteId)
|
||||
? { executionId: scopedExchangeId, applicationName: scopedAppId, routeId: scopedRouteId }
|
||||
: null;
|
||||
|
||||
const [selected, setSelectedInternal] = useState<SelectedExchange | null>(stateSelected ?? urlDerivedExchange);
|
||||
|
||||
// Sync selection from history state or URL params on navigation changes
|
||||
useEffect(() => {
|
||||
const restored = (location.state as any)?.selectedExchange as SelectedExchange | undefined;
|
||||
setSelectedInternal(restored ?? null);
|
||||
}, [location.state]);
|
||||
if (restored) {
|
||||
setSelectedInternal(restored);
|
||||
} else if (scopedExchangeId && scopedAppId && scopedRouteId) {
|
||||
setSelectedInternal({
|
||||
executionId: scopedExchangeId,
|
||||
applicationName: scopedAppId,
|
||||
routeId: scopedRouteId,
|
||||
});
|
||||
} else {
|
||||
setSelectedInternal(null);
|
||||
}
|
||||
}, [location.state, scopedExchangeId, scopedAppId, scopedRouteId]);
|
||||
|
||||
const [splitPercent, setSplitPercent] = useState(50);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
@@ -52,10 +70,15 @@ export default function ExchangesPage() {
|
||||
});
|
||||
}, [navigate, location.pathname, location.search, location.state]);
|
||||
|
||||
// Clear selection: push a history entry without selection (so Back returns to selected state)
|
||||
// Clear selection: navigate up to route level when URL has exchangeId
|
||||
const handleClearSelection = useCallback(() => {
|
||||
setSelectedInternal(null);
|
||||
}, []);
|
||||
if (scopedExchangeId && scopedAppId && scopedRouteId) {
|
||||
navigate(`/exchanges/${scopedAppId}/${scopedRouteId}`, {
|
||||
state: { ...location.state, selectedExchange: undefined },
|
||||
});
|
||||
}
|
||||
}, [scopedExchangeId, scopedAppId, scopedRouteId, navigate, location.state]);
|
||||
|
||||
const handleSplitterDown = useCallback((e: React.PointerEvent) => {
|
||||
e.currentTarget.setPointerCapture(e.pointerId);
|
||||
|
||||
Reference in New Issue
Block a user