feat: add admin tab navigation between subpages
All checks were successful
CI / build (push) Successful in 1m19s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 52s
CI / deploy (push) Successful in 38s
CI / deploy-feature (push) Has been skipped

Add AdminLayout wrapper with Tabs component for navigating between
admin sections: User Management, Audit Log, OIDC, Database, OpenSearch.

Nest all /admin/* routes under AdminLayout using React Router's
Outlet pattern so the tab bar persists across admin page navigation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-23 22:17:33 +01:00
parent 3ccd4b6548
commit 515c942623
2 changed files with 39 additions and 6 deletions

View File

@@ -0,0 +1,26 @@
import { Outlet, useNavigate, useLocation } from 'react-router';
import { Tabs } from '@cameleer/design-system';
const ADMIN_TABS = [
{ label: 'User Management', value: '/admin/rbac' },
{ label: 'Audit Log', value: '/admin/audit' },
{ label: 'OIDC', value: '/admin/oidc' },
{ label: 'Database', value: '/admin/database' },
{ label: 'OpenSearch', value: '/admin/opensearch' },
];
export default function AdminLayout() {
const navigate = useNavigate();
const location = useLocation();
return (
<div>
<Tabs
tabs={ADMIN_TABS}
active={location.pathname}
onChange={(path) => navigate(path)}
/>
<Outlet />
</div>
);
}

View File

@@ -12,6 +12,7 @@ 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 AdminLayout = lazy(() => import('./pages/Admin/AdminLayout'));
const RbacPage = lazy(() => import('./pages/Admin/RbacPage'));
const AuditLogPage = lazy(() => import('./pages/Admin/AuditLogPage'));
const OidcConfigPage = lazy(() => import('./pages/Admin/OidcConfigPage'));
@@ -47,12 +48,18 @@ export const router = createBrowserRouter([
{ path: 'agents', element: <SuspenseWrapper><AgentHealth /></SuspenseWrapper> },
{ path: 'agents/:appId', element: <SuspenseWrapper><AgentHealth /></SuspenseWrapper> },
{ path: 'agents/:appId/:instanceId', element: <SuspenseWrapper><AgentInstance /></SuspenseWrapper> },
{ path: 'admin', element: <Navigate to="/admin/rbac" replace /> },
{ path: 'admin/rbac', element: <SuspenseWrapper><RbacPage /></SuspenseWrapper> },
{ path: 'admin/audit', element: <SuspenseWrapper><AuditLogPage /></SuspenseWrapper> },
{ path: 'admin/oidc', element: <SuspenseWrapper><OidcConfigPage /></SuspenseWrapper> },
{ path: 'admin/database', element: <SuspenseWrapper><DatabaseAdminPage /></SuspenseWrapper> },
{ path: 'admin/opensearch', element: <SuspenseWrapper><OpenSearchAdminPage /></SuspenseWrapper> },
{
path: 'admin',
element: <SuspenseWrapper><AdminLayout /></SuspenseWrapper>,
children: [
{ index: true, element: <Navigate to="/admin/rbac" replace /> },
{ path: 'rbac', element: <SuspenseWrapper><RbacPage /></SuspenseWrapper> },
{ path: 'audit', element: <SuspenseWrapper><AuditLogPage /></SuspenseWrapper> },
{ path: 'oidc', element: <SuspenseWrapper><OidcConfigPage /></SuspenseWrapper> },
{ path: 'database', element: <SuspenseWrapper><DatabaseAdminPage /></SuspenseWrapper> },
{ path: 'opensearch', element: <SuspenseWrapper><OpenSearchAdminPage /></SuspenseWrapper> },
],
},
{ path: 'api-docs', element: <SuspenseWrapper><SwaggerPage /></SuspenseWrapper> },
],
},