From 66abb1fe3a6544500e8500fe96d5e7309a5cc549 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Sat, 28 Mar 2026 13:59:20 +0100 Subject: [PATCH] feat(ui): restructure router for tab-based navigation with legacy redirects Co-Authored-By: Claude Sonnet 4.6 --- ui/src/router.tsx | 64 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 18 deletions(-) diff --git a/ui/src/router.tsx b/ui/src/router.tsx index 48eadc04..8c9383f8 100644 --- a/ui/src/router.tsx +++ b/ui/src/router.tsx @@ -1,4 +1,4 @@ -import { createBrowserRouter, Navigate } from 'react-router'; +import { createBrowserRouter, Navigate, useParams } from 'react-router'; import { ProtectedRoute } from './auth/ProtectedRoute'; import { LoginPage } from './auth/LoginPage'; import { OidcCallback } from './auth/OidcCallback'; @@ -6,12 +6,9 @@ import { LayoutShell } from './components/LayoutShell'; import { lazy, Suspense } from 'react'; import { Spinner } from '@cameleer/design-system'; -const Dashboard = lazy(() => import('./pages/Dashboard/Dashboard')); -const ExchangeDetail = lazy(() => import('./pages/ExchangeDetail/ExchangeDetail')); -const RoutesMetrics = lazy(() => import('./pages/Routes/RoutesMetrics')); -const RouteDetail = lazy(() => import('./pages/Routes/RouteDetail')); -const AgentHealth = lazy(() => import('./pages/AgentHealth/AgentHealth')); -const AgentInstance = lazy(() => import('./pages/AgentInstance/AgentInstance')); +const ExchangesPage = lazy(() => import('./pages/Exchanges/ExchangesPage')); +const DashboardPage = lazy(() => import('./pages/DashboardTab/DashboardPage')); +const RuntimePage = lazy(() => import('./pages/RuntimeTab/RuntimePage')); const AdminLayout = lazy(() => import('./pages/Admin/AdminLayout')); const RbacPage = lazy(() => import('./pages/Admin/RbacPage')); const AuditLogPage = lazy(() => import('./pages/Admin/AuditLogPage')); @@ -29,6 +26,20 @@ function SuspenseWrapper({ children }: { children: React.ReactNode }) { ); } +/** Redirect legacy /apps/:appId/:routeId paths to /exchanges/:appId/:routeId */ +function LegacyAppRedirect() { + const { appId, routeId } = useParams<{ appId: string; routeId?: string }>(); + const path = routeId ? `/exchanges/${appId}/${routeId}` : `/exchanges/${appId}`; + return ; +} + +/** Redirect legacy /agents/:appId/:instanceId paths to /runtime/:appId/:instanceId */ +function LegacyAgentRedirect() { + const { appId, instanceId } = useParams<{ appId: string; instanceId?: string }>(); + const path = instanceId ? `/runtime/${appId}/${instanceId}` : `/runtime/${appId}`; + return ; +} + export const router = createBrowserRouter([ { path: '/login', element: }, { path: '/oidc/callback', element: }, @@ -38,17 +49,34 @@ export const router = createBrowserRouter([ { element: , children: [ - { index: true, element: }, - { path: 'apps', element: }, - { path: 'apps/:appId', element: }, - { path: 'apps/:appId/:routeId', element: }, - { path: 'exchanges/:id', element: }, - { path: 'routes', element: }, - { path: 'routes/:appId', element: }, - { path: 'routes/:appId/:routeId', element: }, - { path: 'agents', element: }, - { path: 'agents/:appId', element: }, - { path: 'agents/:appId/:instanceId', element: }, + // Default redirect + { index: true, element: }, + + // Exchanges tab + { path: 'exchanges', element: }, + { path: 'exchanges/:appId', element: }, + { path: 'exchanges/:appId/:routeId', element: }, + { path: 'exchanges/:appId/:routeId/:exchangeId', element: }, + + // Dashboard tab + { path: 'dashboard', element: }, + { path: 'dashboard/:appId', element: }, + { path: 'dashboard/:appId/:routeId', element: }, + + // Runtime tab + { path: 'runtime', element: }, + { path: 'runtime/:appId', element: }, + { path: 'runtime/:appId/:instanceId', element: }, + + // Legacy redirects — Sidebar uses hardcoded /apps/... and /agents/... paths + { path: 'apps', element: }, + { path: 'apps/:appId', element: }, + { path: 'apps/:appId/:routeId', element: }, + { path: 'agents', element: }, + { path: 'agents/:appId', element: }, + { path: 'agents/:appId/:instanceId', element: }, + + // Admin (unchanged) { path: 'admin', element: ,