fix: always show Config tab and fix 404 on sidebar navigation
Config tab now always visible (not just when app selected). Shows all- app config table at /config, single-app detail at /config/:appId. Fixed 404 when clicking sidebar nodes while on Config tab — the sidebar navigation built /config/appId/routeId which had no route. Now falls back to exchanges tab for route-level navigation from config. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,15 +3,11 @@ import type { TabKey, Scope } from '../hooks/useScope';
|
|||||||
import { TabKpis } from './TabKpis';
|
import { TabKpis } from './TabKpis';
|
||||||
import styles from './ContentTabs.module.css';
|
import styles from './ContentTabs.module.css';
|
||||||
|
|
||||||
const BASE_TABS = [
|
const TABS = [
|
||||||
{ label: 'Exchanges', value: 'exchanges' },
|
{ label: 'Exchanges', value: 'exchanges' },
|
||||||
{ label: 'Dashboard', value: 'dashboard' },
|
{ label: 'Dashboard', value: 'dashboard' },
|
||||||
{ label: 'Runtime', value: 'runtime' },
|
{ label: 'Runtime', value: 'runtime' },
|
||||||
{ label: 'Logs', value: 'logs' },
|
{ label: 'Logs', value: 'logs' },
|
||||||
];
|
|
||||||
|
|
||||||
const TABS_WITH_CONFIG = [
|
|
||||||
...BASE_TABS,
|
|
||||||
{ label: 'Config', value: 'config' },
|
{ label: 'Config', value: 'config' },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -22,12 +18,10 @@ interface ContentTabsProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ContentTabs({ active, onChange, scope }: ContentTabsProps) {
|
export function ContentTabs({ active, onChange, scope }: ContentTabsProps) {
|
||||||
// Config tab only shown when an app is selected
|
|
||||||
const tabs = scope.appId ? TABS_WITH_CONFIG : BASE_TABS;
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={tabs}
|
tabs={TABS}
|
||||||
active={active}
|
active={active}
|
||||||
onChange={(v) => onChange(v as TabKey)}
|
onChange={(v) => onChange(v as TabKey)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -604,7 +604,9 @@ function LayoutContent() {
|
|||||||
const appMatch = path.match(/^\/apps\/([^/]+)(?:\/(.+))?$/);
|
const appMatch = path.match(/^\/apps\/([^/]+)(?:\/(.+))?$/);
|
||||||
if (appMatch) {
|
if (appMatch) {
|
||||||
const [, sAppId, sRouteId] = appMatch;
|
const [, sAppId, sRouteId] = appMatch;
|
||||||
navigate(sRouteId ? `/${scope.tab}/${sAppId}/${sRouteId}` : `/${scope.tab}/${sAppId}`, { state });
|
// Config tab only supports /config/:appId — fall back to exchanges for route-level
|
||||||
|
const tab = (scope.tab === 'config' && sRouteId) ? 'exchanges' : scope.tab;
|
||||||
|
navigate(sRouteId ? `/${tab}/${sAppId}/${sRouteId}` : `/${tab}/${sAppId}`, { state });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ export const router = createBrowserRouter([
|
|||||||
{ path: 'logs/:appId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
{ path: 'logs/:appId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
||||||
{ path: 'logs/:appId/:routeId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
{ path: 'logs/:appId/:routeId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
||||||
|
|
||||||
// Config tab (per-app, accessible to VIEWER+)
|
// Config tab (accessible to VIEWER+, shows all apps or single app)
|
||||||
{ path: 'config', element: <Navigate to="/exchanges" replace /> },
|
{ path: 'config', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
||||||
{ path: 'config/:appId', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
{ path: 'config/:appId', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
||||||
|
|
||||||
// Legacy redirects — Sidebar uses hardcoded /apps/... and /agents/... paths
|
// Legacy redirects — Sidebar uses hardcoded /apps/... and /agents/... paths
|
||||||
|
|||||||
Reference in New Issue
Block a user