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: 'Exchanges', value: 'exchanges' },
|
||||||
{ label: 'Dashboard', value: 'dashboard' },
|
{ label: 'Dashboard', value: 'dashboard' },
|
||||||
{ label: 'Runtime', value: 'runtime' },
|
{ label: 'Runtime', value: 'runtime' },
|
||||||
{ label: 'Logs', value: 'logs' },
|
|
||||||
{ label: 'Config', value: 'config' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
interface ContentTabsProps {
|
interface ContentTabsProps {
|
||||||
|
|||||||
@@ -107,10 +107,10 @@ export function LogTab({ applicationId, exchangeId, processorId }: LogTabProps)
|
|||||||
{exchangeId && (
|
{exchangeId && (
|
||||||
<div className={logStyles.footer}>
|
<div className={logStyles.footer}>
|
||||||
<button
|
<button
|
||||||
onClick={() => navigate(`/logs/${applicationId}?exchangeId=${exchangeId}`)}
|
onClick={() => navigate(`/runtime/${applicationId}`)}
|
||||||
className={logStyles.openLogsButton}
|
className={logStyles.openLogsButton}
|
||||||
>
|
>
|
||||||
Open in Logs tab {'\u2192'}
|
Open in Runtime {'\u2192'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -618,9 +618,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;
|
||||||
if (scope.tab === 'config') {
|
if (scope.tab === 'apps') {
|
||||||
// Config tab: always navigate to /config/:appId (route click → same app config)
|
// Deployments tab: navigate to /apps/:appId
|
||||||
navigate(`/config/${sAppId}`, { state });
|
navigate(`/apps/${sAppId}`, { state });
|
||||||
} else {
|
} else {
|
||||||
navigate(sRouteId ? `/${scope.tab}/${sAppId}/${sRouteId}` : `/${scope.tab}/${sAppId}`, { state });
|
navigate(sRouteId ? `/${scope.tab}/${sAppId}/${sRouteId}` : `/${scope.tab}/${sAppId}`, { state });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
import { useParams, useNavigate, useLocation } from 'react-router';
|
import { useParams, useNavigate, useLocation } from 'react-router';
|
||||||
import { useCallback } from 'react';
|
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 {
|
export interface Scope {
|
||||||
tab: TabKey;
|
tab: TabKey;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export function ExchangeHeader({ detail, onCorrelatedSelect, onClearSelection }:
|
|||||||
<span className={styles.duration}>{formatDuration(detail.durationMs)}</span>
|
<span className={styles.duration}>{formatDuration(detail.durationMs)}</span>
|
||||||
<button
|
<button
|
||||||
className={styles.linkBtn}
|
className={styles.linkBtn}
|
||||||
onClick={() => navigate(`/logs/${detail.applicationId}?exchangeId=${detail.exchangeId}`)}
|
onClick={() => navigate(`/runtime/${detail.applicationId}`)}
|
||||||
title="View surrounding logs"
|
title="View surrounding logs"
|
||||||
>
|
>
|
||||||
<FileText size={12} className={styles.icon} />
|
<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 DatabaseAdminPage = lazy(() => import('./pages/Admin/DatabaseAdminPage'));
|
||||||
const ClickHouseAdminPage = lazy(() => import('./pages/Admin/ClickHouseAdminPage'));
|
const ClickHouseAdminPage = lazy(() => import('./pages/Admin/ClickHouseAdminPage'));
|
||||||
const EnvironmentsPage = lazy(() => import('./pages/Admin/EnvironmentsPage'));
|
const EnvironmentsPage = lazy(() => import('./pages/Admin/EnvironmentsPage'));
|
||||||
const AppConfigPage = lazy(() => import('./pages/Admin/AppConfigPage'));
|
|
||||||
const AppsTab = lazy(() => import('./pages/AppsTab/AppsTab'));
|
const AppsTab = lazy(() => import('./pages/AppsTab/AppsTab'));
|
||||||
const LogsPage = lazy(() => import('./pages/LogsTab/LogsPage'));
|
|
||||||
const SwaggerPage = lazy(() => import('./pages/Swagger/SwaggerPage'));
|
const SwaggerPage = lazy(() => import('./pages/Swagger/SwaggerPage'));
|
||||||
|
|
||||||
function SuspenseWrapper({ children }: { children: React.ReactNode }) {
|
function SuspenseWrapper({ children }: { children: React.ReactNode }) {
|
||||||
@@ -61,14 +59,12 @@ export const router = createBrowserRouter([
|
|||||||
{ path: 'runtime/:appId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
{ path: 'runtime/:appId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
||||||
{ path: 'runtime/:appId/:instanceId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
{ path: 'runtime/:appId/:instanceId', element: <SuspenseWrapper><RuntimePage /></SuspenseWrapper> },
|
||||||
|
|
||||||
// Logs tab
|
// Redirects for removed tabs
|
||||||
{ path: 'logs', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
{ path: 'logs', element: <Navigate to="/runtime" replace /> },
|
||||||
{ path: 'logs/:appId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
{ path: 'logs/:appId', element: <Navigate to="/runtime" replace /> },
|
||||||
{ path: 'logs/:appId/:routeId', element: <SuspenseWrapper><LogsPage /></SuspenseWrapper> },
|
{ path: 'logs/:appId/:routeId', element: <Navigate to="/runtime" replace /> },
|
||||||
|
{ path: 'config', element: <Navigate to="/apps" replace /> },
|
||||||
// Config tab (accessible to VIEWER+, shows all apps or single app)
|
{ path: 'config/:appId', element: <Navigate to="/apps" replace /> },
|
||||||
{ path: 'config', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
|
||||||
{ path: 'config/:appId', element: <SuspenseWrapper><AppConfigPage /></SuspenseWrapper> },
|
|
||||||
|
|
||||||
// Apps tab (OPERATOR+ via UI guard, shows all or single app)
|
// Apps tab (OPERATOR+ via UI guard, shows all or single app)
|
||||||
{ path: 'apps', element: <SuspenseWrapper><AppsTab /></SuspenseWrapper> },
|
{ path: 'apps', element: <SuspenseWrapper><AppsTab /></SuspenseWrapper> },
|
||||||
|
|||||||
Reference in New Issue
Block a user