refactor: consolidate tabs — remove standalone Logs and Config tabs
Logs functionality already exists in Runtime tab (AgentHealth/AgentInstance). Config functionality moved to Deployments tab ConfigSubTab. Old routes redirect to /runtime and /apps respectively. Navigation links updated throughout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,6 @@ const BASE_TABS = [
|
||||
{ label: 'Exchanges', value: 'exchanges' },
|
||||
{ label: 'Dashboard', value: 'dashboard' },
|
||||
{ label: 'Runtime', value: 'runtime' },
|
||||
{ label: 'Logs', value: 'logs' },
|
||||
{ label: 'Config', value: 'config' },
|
||||
];
|
||||
|
||||
interface ContentTabsProps {
|
||||
|
||||
@@ -107,10 +107,10 @@ export function LogTab({ applicationId, exchangeId, processorId }: LogTabProps)
|
||||
{exchangeId && (
|
||||
<div className={logStyles.footer}>
|
||||
<button
|
||||
onClick={() => navigate(`/logs/${applicationId}?exchangeId=${exchangeId}`)}
|
||||
onClick={() => navigate(`/runtime/${applicationId}`)}
|
||||
className={logStyles.openLogsButton}
|
||||
>
|
||||
Open in Logs tab {'\u2192'}
|
||||
Open in Runtime {'\u2192'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -618,9 +618,9 @@ function LayoutContent() {
|
||||
const appMatch = path.match(/^\/apps\/([^/]+)(?:\/(.+))?$/);
|
||||
if (appMatch) {
|
||||
const [, sAppId, sRouteId] = appMatch;
|
||||
if (scope.tab === 'config') {
|
||||
// Config tab: always navigate to /config/:appId (route click → same app config)
|
||||
navigate(`/config/${sAppId}`, { state });
|
||||
if (scope.tab === 'apps') {
|
||||
// Deployments tab: navigate to /apps/:appId
|
||||
navigate(`/apps/${sAppId}`, { state });
|
||||
} else {
|
||||
navigate(sRouteId ? `/${scope.tab}/${sAppId}/${sRouteId}` : `/${scope.tab}/${sAppId}`, { state });
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import { useParams, useNavigate, useLocation } from 'react-router';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export type TabKey = 'exchanges' | 'dashboard' | 'runtime' | 'logs' | 'config' | 'apps';
|
||||
export type TabKey = 'exchanges' | 'dashboard' | 'runtime' | 'apps';
|
||||
|
||||
const VALID_TABS = new Set<TabKey>(['exchanges', 'dashboard', 'runtime', 'logs', 'config', 'apps']);
|
||||
const VALID_TABS = new Set<TabKey>(['exchanges', 'dashboard', 'runtime', 'apps']);
|
||||
|
||||
export interface Scope {
|
||||
tab: TabKey;
|
||||
|
||||
@@ -118,7 +118,7 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }:
|
||||
<span className={styles.duration}>{formatDuration(detail.durationMs)}</span>
|
||||
<button
|
||||
className={styles.linkBtn}
|
||||
onClick={() => navigate(`/logs/${detail.applicationId}?exchangeId=${detail.exchangeId}`)}
|
||||
onClick={() => navigate(`/runtime/${detail.applicationId}`)}
|
||||
title="View surrounding logs"
|
||||
>
|
||||
<FileText size={12} className={styles.icon} />
|
||||
|
||||
@@ -18,9 +18,7 @@ const OidcConfigPage = lazy(() => import('./pages/Admin/OidcConfigPage'));
|
||||
const DatabaseAdminPage = lazy(() => import('./pages/Admin/DatabaseAdminPage'));
|
||||
const ClickHouseAdminPage = lazy(() => import('./pages/Admin/ClickHouseAdminPage'));
|
||||
const EnvironmentsPage = lazy(() => import('./pages/Admin/EnvironmentsPage'));
|
||||
const AppConfigPage = lazy(() => import('./pages/Admin/AppConfigPage'));
|
||||
const AppsTab = lazy(() => import('./pages/AppsTab/AppsTab'));
|
||||
const LogsPage = lazy(() => import('./pages/LogsTab/LogsPage'));
|
||||
const SwaggerPage = lazy(() => import('./pages/Swagger/SwaggerPage'));
|
||||
|
||||
function SuspenseWrapper({ children }: { children: React.ReactNode }) {
|
||||
@@ -61,14 +59,12 @@ export const router = createBrowserRouter([
|
||||
{ path: 'runtime/:appId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
||||
{ path: 'runtime/:appId/:instanceId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
||||
|
||||
// Logs tab
|
||||
{ path: 'logs', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
||||
{ path: 'logs/:appId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
||||
{ path: 'logs/:appId/:routeId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
||||
|
||||
// Config tab (accessible to VIEWER+, shows all apps or single app)
|
||||
{ path: 'config', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
||||
{ path: 'config/:appId', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
||||
// Redirects for removed tabs
|
||||
{ path: 'logs', element: <Navigate to="/runtime" replace /> },
|
||||
{ path: 'logs/:appId', element: <Navigate to="/runtime" replace /> },
|
||||
{ path: 'logs/:appId/:routeId', element: <Navigate to="/runtime" replace /> },
|
||||
{ path: 'config', element: <Navigate to="/apps" replace /> },
|
||||
{ path: 'config/:appId', element: <Navigate to="/apps" replace /> },
|
||||
|
||||
// Apps tab (OPERATOR+ via UI guard, shows all or single app)
|
||||
{ path: 'apps', element: <SuspenseWrapper><AppsTab /></SuspenseWrapper> },
|
||||
|
||||
Reference in New Issue
Block a user