chore: remove /dev/diagram test page
No longer needed — the ProcessDiagram is now integrated into ExchangeDetail via the ExecutionDiagram wrapper. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,131 +0,0 @@
|
||||
.page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.header h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: var(--text-primary, #1A1612);
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.controls select {
|
||||
padding: 6px 10px;
|
||||
border: 1px solid var(--border, #E4DFD8);
|
||||
border-radius: var(--radius-sm, 5px);
|
||||
background: var(--bg-surface, #FFFFFF);
|
||||
color: var(--text-primary, #1A1612);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.diagramPane {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
min-height: 400px;
|
||||
border: 1px dashed var(--border, #E4DFD8);
|
||||
border-radius: var(--radius-md, 8px);
|
||||
color: var(--text-muted, #9C9184);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sidePanel {
|
||||
width: 280px;
|
||||
flex-shrink: 0;
|
||||
padding: 12px;
|
||||
border: 1px solid var(--border, #E4DFD8);
|
||||
border-radius: var(--radius-md, 8px);
|
||||
background: var(--bg-surface, #FFFFFF);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidePanel h3 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary, #5C5347);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.nodeInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.fieldLabel {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted, #9C9184);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.field code, .field pre {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 12px;
|
||||
color: var(--text-primary, #1A1612);
|
||||
background: var(--bg-inset, #F0EDE8);
|
||||
padding: 4px 6px;
|
||||
border-radius: 3px;
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.hint {
|
||||
color: var(--text-muted, #9C9184);
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.log {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.logEntry {
|
||||
font-family: var(--font-mono, monospace);
|
||||
font-size: 11px;
|
||||
color: var(--text-secondary, #5C5347);
|
||||
padding: 2px 0;
|
||||
border-bottom: 1px solid var(--border-subtle, #EDE9E3);
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useGlobalFilters } from '@cameleer/design-system';
|
||||
import { ProcessDiagram } from '../../components/ProcessDiagram';
|
||||
import type { NodeConfig, NodeAction } from '../../components/ProcessDiagram';
|
||||
import { useRouteCatalog } from '../../api/queries/catalog';
|
||||
import styles from './DevDiagram.module.css';
|
||||
|
||||
export default function DevDiagram() {
|
||||
const { timeRange } = useGlobalFilters();
|
||||
const { data: catalog } = useRouteCatalog(
|
||||
timeRange.start.toISOString(),
|
||||
timeRange.end.toISOString(),
|
||||
);
|
||||
|
||||
const [selectedApp, setSelectedApp] = useState('');
|
||||
const [selectedRoute, setSelectedRoute] = useState('');
|
||||
const [selectedNodeId, setSelectedNodeId] = useState('');
|
||||
const [direction, setDirection] = useState<'LR' | 'TB'>('LR');
|
||||
const [actionLog, setActionLog] = useState<string[]>([]);
|
||||
|
||||
// Extract applications and routes from catalog
|
||||
// Catalog shape: Array<{ appId, routes: [{ routeId }] }>
|
||||
const { apps, routes } = useMemo(() => {
|
||||
if (!catalog) return { apps: [] as string[], routes: [] as string[] };
|
||||
const appArr = (catalog as Array<{ appId: string; routes?: Array<{ routeId: string }> }>)
|
||||
.map(a => a.appId)
|
||||
.sort();
|
||||
const filtered = selectedApp
|
||||
? (catalog as Array<{ appId: string; routes?: Array<{ routeId: string }> }>)
|
||||
.filter(a => a.appId === selectedApp)
|
||||
.flatMap(a => (a.routes || []).map(r => r.routeId))
|
||||
: [];
|
||||
return { apps: appArr, routes: filtered };
|
||||
}, [catalog, selectedApp]);
|
||||
|
||||
// All route IDs for the selected app (for drill-down resolution)
|
||||
const knownRouteIds = useMemo(() => {
|
||||
if (!catalog || !selectedApp) return new Set<string>();
|
||||
const app = (catalog as Array<{ appId: string; routes?: Array<{ routeId: string }> }>)
|
||||
.find(a => a.appId === selectedApp);
|
||||
return new Set((app?.routes ?? []).map(r => r.routeId));
|
||||
}, [catalog, selectedApp]);
|
||||
|
||||
// Mock node configs for testing
|
||||
const nodeConfigs = useMemo(() => {
|
||||
const map = new Map<string, NodeConfig>();
|
||||
// We'll add some mock configs if we have a route loaded
|
||||
map.set('log1', { traceEnabled: true });
|
||||
map.set('to1', { tapExpression: '${header.orderId}' });
|
||||
return map;
|
||||
}, []);
|
||||
|
||||
const handleNodeAction = (nodeId: string, action: NodeAction) => {
|
||||
const msg = `[${new Date().toLocaleTimeString()}] ${action}: ${nodeId}`;
|
||||
setActionLog(prev => [msg, ...prev.slice(0, 19)]);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.page}>
|
||||
<div className={styles.header}>
|
||||
<h2>Process Diagram (Dev)</h2>
|
||||
<div className={styles.controls}>
|
||||
<select
|
||||
value={selectedApp}
|
||||
onChange={e => { setSelectedApp(e.target.value); setSelectedRoute(''); }}
|
||||
>
|
||||
<option value="">Select application...</option>
|
||||
{apps.map(app => <option key={app} value={app}>{app}</option>)}
|
||||
</select>
|
||||
<select
|
||||
value={selectedRoute}
|
||||
onChange={e => setSelectedRoute(e.target.value)}
|
||||
disabled={!selectedApp}
|
||||
>
|
||||
<option value="">Select route...</option>
|
||||
{routes.map(r => <option key={r} value={r}>{r}</option>)}
|
||||
</select>
|
||||
<select value={direction} onChange={e => setDirection(e.target.value as 'LR' | 'TB')}>
|
||||
<option value="LR">Left → Right</option>
|
||||
<option value="TB">Top → Bottom</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.content}>
|
||||
<div className={styles.diagramPane}>
|
||||
{selectedApp && selectedRoute ? (
|
||||
<ProcessDiagram
|
||||
application={selectedApp}
|
||||
routeId={selectedRoute}
|
||||
direction={direction}
|
||||
selectedNodeId={selectedNodeId}
|
||||
onNodeSelect={setSelectedNodeId}
|
||||
onNodeAction={handleNodeAction}
|
||||
nodeConfigs={nodeConfigs}
|
||||
knownRouteIds={knownRouteIds}
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.placeholder}>
|
||||
Select an application and route to view the diagram
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={styles.sidePanel}>
|
||||
<h3>Selected Node</h3>
|
||||
{selectedNodeId ? (
|
||||
<div className={styles.nodeInfo}>
|
||||
<div className={styles.field}>
|
||||
<span className={styles.fieldLabel}>Node ID</span>
|
||||
<code>{selectedNodeId}</code>
|
||||
</div>
|
||||
{nodeConfigs.has(selectedNodeId) && (
|
||||
<div className={styles.field}>
|
||||
<span className={styles.fieldLabel}>Config</span>
|
||||
<pre>{JSON.stringify(nodeConfigs.get(selectedNodeId), null, 2)}</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<p className={styles.hint}>Click a node to inspect it</p>
|
||||
)}
|
||||
|
||||
<h3>Action Log</h3>
|
||||
<div className={styles.log}>
|
||||
{actionLog.length === 0 ? (
|
||||
<p className={styles.hint}>Hover a node and use the toolbar</p>
|
||||
) : (
|
||||
actionLog.map((msg, i) => (
|
||||
<div key={i} className={styles.logEntry}>{msg}</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -20,7 +20,6 @@ const DatabaseAdminPage = lazy(() => import('./pages/Admin/DatabaseAdminPage'));
|
||||
const OpenSearchAdminPage = lazy(() => import('./pages/Admin/OpenSearchAdminPage'));
|
||||
const AppConfigPage = lazy(() => import('./pages/Admin/AppConfigPage'));
|
||||
const SwaggerPage = lazy(() => import('./pages/Swagger/SwaggerPage'));
|
||||
const DevDiagram = lazy(() => import('./pages/DevDiagram/DevDiagram'));
|
||||
|
||||
function SuspenseWrapper({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
@@ -64,7 +63,6 @@ export const router = createBrowserRouter([
|
||||
],
|
||||
},
|
||||
{ path: 'api-docs', element: <SuspenseWrapper><SwaggerPage /></SuspenseWrapper> },
|
||||
{ path: 'dev/diagram', element: <SuspenseWrapper><DevDiagram /></SuspenseWrapper> },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user