2026-03-13 18:03:37 +01:00
|
|
|
import { useState, useMemo } from 'react';
|
2026-03-14 14:43:18 +01:00
|
|
|
import type { ExecutionSummary } from '../../api/schema-types';
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
import { StatusPill } from '../../components/shared/StatusPill';
|
|
|
|
|
import { DurationBar } from '../../components/shared/DurationBar';
|
|
|
|
|
import { AppBadge } from '../../components/shared/AppBadge';
|
|
|
|
|
import { ProcessorTree } from './ProcessorTree';
|
|
|
|
|
import { ExchangeDetail } from './ExchangeDetail';
|
|
|
|
|
import styles from './ResultsTable.module.css';
|
|
|
|
|
|
|
|
|
|
interface ResultsTableProps {
|
|
|
|
|
results: ExecutionSummary[];
|
|
|
|
|
loading: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-13 18:03:37 +01:00
|
|
|
type SortColumn = 'startTime' | 'status' | 'agentId' | 'routeId' | 'correlationId' | 'durationMs';
|
|
|
|
|
type SortDir = 'asc' | 'desc';
|
|
|
|
|
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
function formatTime(iso: string) {
|
|
|
|
|
return new Date(iso).toLocaleTimeString('en-GB', {
|
|
|
|
|
hour: '2-digit',
|
|
|
|
|
minute: '2-digit',
|
|
|
|
|
second: '2-digit',
|
|
|
|
|
fractionalSecondDigits: 3,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-13 18:03:37 +01:00
|
|
|
function compareFn(a: ExecutionSummary, b: ExecutionSummary, col: SortColumn, dir: SortDir): number {
|
|
|
|
|
let cmp = 0;
|
|
|
|
|
switch (col) {
|
|
|
|
|
case 'startTime':
|
|
|
|
|
cmp = a.startTime.localeCompare(b.startTime);
|
|
|
|
|
break;
|
|
|
|
|
case 'status':
|
|
|
|
|
cmp = a.status.localeCompare(b.status);
|
|
|
|
|
break;
|
|
|
|
|
case 'agentId':
|
|
|
|
|
cmp = a.agentId.localeCompare(b.agentId);
|
|
|
|
|
break;
|
|
|
|
|
case 'routeId':
|
|
|
|
|
cmp = a.routeId.localeCompare(b.routeId);
|
|
|
|
|
break;
|
|
|
|
|
case 'correlationId':
|
|
|
|
|
cmp = (a.correlationId ?? '').localeCompare(b.correlationId ?? '');
|
|
|
|
|
break;
|
|
|
|
|
case 'durationMs':
|
|
|
|
|
cmp = a.durationMs - b.durationMs;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return dir === 'asc' ? cmp : -cmp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface SortableThProps {
|
|
|
|
|
label: string;
|
|
|
|
|
column: SortColumn;
|
|
|
|
|
activeColumn: SortColumn | null;
|
|
|
|
|
direction: SortDir;
|
|
|
|
|
onSort: (col: SortColumn) => void;
|
|
|
|
|
style?: React.CSSProperties;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SortableTh({ label, column, activeColumn, direction, onSort, style }: SortableThProps) {
|
|
|
|
|
const isActive = activeColumn === column;
|
|
|
|
|
return (
|
|
|
|
|
<th
|
|
|
|
|
className={`${styles.th} ${styles.thSortable} ${isActive ? styles.thActive : ''}`}
|
|
|
|
|
style={style}
|
|
|
|
|
onClick={() => onSort(column)}
|
|
|
|
|
>
|
|
|
|
|
{label}
|
|
|
|
|
<span className={styles.sortArrow}>
|
|
|
|
|
{isActive ? (direction === 'asc' ? '\u25B2' : '\u25BC') : '\u25B4'}
|
|
|
|
|
</span>
|
|
|
|
|
</th>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
export function ResultsTable({ results, loading }: ResultsTableProps) {
|
|
|
|
|
const [expandedId, setExpandedId] = useState<string | null>(null);
|
2026-03-13 18:03:37 +01:00
|
|
|
const [sortColumn, setSortColumn] = useState<SortColumn | null>(null);
|
|
|
|
|
const [sortDir, setSortDir] = useState<SortDir>('desc');
|
|
|
|
|
|
|
|
|
|
const sortedResults = useMemo(() => {
|
|
|
|
|
if (!sortColumn) return results;
|
|
|
|
|
return [...results].sort((a, b) => compareFn(a, b, sortColumn, sortDir));
|
|
|
|
|
}, [results, sortColumn, sortDir]);
|
|
|
|
|
|
|
|
|
|
function handleSort(col: SortColumn) {
|
|
|
|
|
if (sortColumn === col) {
|
|
|
|
|
setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
|
|
|
|
|
} else {
|
|
|
|
|
setSortColumn(col);
|
|
|
|
|
setSortDir('desc');
|
|
|
|
|
}
|
|
|
|
|
}
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
|
|
|
|
|
if (loading && results.length === 0) {
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.tableWrap}>
|
|
|
|
|
<div className={styles.loadingOverlay}>Loading executions...</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (results.length === 0) {
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.tableWrap}>
|
|
|
|
|
<div className={styles.emptyState}>No executions found matching your filters.</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={styles.tableWrap}>
|
|
|
|
|
<table className={styles.table}>
|
|
|
|
|
<thead className={styles.thead}>
|
|
|
|
|
<tr>
|
|
|
|
|
<th className={styles.th} style={{ width: 32 }} />
|
2026-03-13 18:03:37 +01:00
|
|
|
<SortableTh label="Timestamp" column="startTime" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
|
|
|
|
<SortableTh label="Status" column="status" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
|
|
|
|
<SortableTh label="Application" column="agentId" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
|
|
|
|
<SortableTh label="Route" column="routeId" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
|
|
|
|
<SortableTh label="Correlation ID" column="correlationId" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
|
|
|
|
<SortableTh label="Duration" column="durationMs" activeColumn={sortColumn} direction={sortDir} onSort={handleSort} />
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
2026-03-13 18:03:37 +01:00
|
|
|
{sortedResults.map((exec) => {
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
const isExpanded = expandedId === exec.executionId;
|
|
|
|
|
return (
|
|
|
|
|
<ResultRow
|
|
|
|
|
key={exec.executionId}
|
|
|
|
|
exec={exec}
|
|
|
|
|
isExpanded={isExpanded}
|
|
|
|
|
onToggle={() => setExpandedId(isExpanded ? null : exec.executionId)}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
})}
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function ResultRow({
|
|
|
|
|
exec,
|
|
|
|
|
isExpanded,
|
|
|
|
|
onToggle,
|
|
|
|
|
}: {
|
|
|
|
|
exec: ExecutionSummary;
|
|
|
|
|
isExpanded: boolean;
|
|
|
|
|
onToggle: () => void;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<tr
|
|
|
|
|
className={`${styles.row} ${isExpanded ? styles.expanded : ''}`}
|
|
|
|
|
onClick={onToggle}
|
|
|
|
|
>
|
|
|
|
|
<td className={`${styles.td} ${styles.tdExpand}`}>›</td>
|
|
|
|
|
<td className={`${styles.td} mono`}>{formatTime(exec.startTime)}</td>
|
|
|
|
|
<td className={styles.td}>
|
|
|
|
|
<StatusPill status={exec.status} />
|
|
|
|
|
</td>
|
|
|
|
|
<td className={styles.td}>
|
|
|
|
|
<AppBadge name={exec.agentId} />
|
|
|
|
|
</td>
|
|
|
|
|
<td className={`${styles.td} mono text-secondary`}>{exec.routeId}</td>
|
|
|
|
|
<td className={`${styles.td} mono text-muted ${styles.correlationId}`} title={exec.correlationId ?? ''}>
|
|
|
|
|
{exec.correlationId ?? '-'}
|
|
|
|
|
</td>
|
|
|
|
|
<td className={styles.td}>
|
2026-03-13 14:23:56 +01:00
|
|
|
<DurationBar duration={exec.durationMs} />
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
{isExpanded && (
|
|
|
|
|
<tr className={styles.detailRowVisible}>
|
2026-03-13 14:23:56 +01:00
|
|
|
<td className={styles.detailCell} colSpan={7}>
|
Add React UI with Execution Explorer, auth, and standalone deployment
- Scaffold Vite + React + TypeScript frontend in ui/ with full design
system (dark/light themes) matching the HTML mockups
- Implement Execution Explorer page: search filters, results table with
expandable processor tree and exchange detail sidebar, pagination
- Add UI authentication: UiAuthController (login/refresh endpoints),
JWT filter handles ui: subject prefix, CORS configuration
- Shared components: StatusPill, DurationBar, StatCard, AppBadge,
FilterChip, Pagination — all using CSS Modules with design tokens
- API client layer: openapi-fetch with auth middleware, TanStack Query
hooks for search/detail/snapshot queries, Zustand for state
- Standalone deployment: Nginx Dockerfile, K8s Deployment + ConfigMap +
NodePort (30080), runtime config.js for API base URL
- Embedded mode: maven-resources-plugin copies ui/dist into JAR static
resources, SPA forward controller for client-side routing
- CI/CD: UI build step, Docker build/push for server-ui image, K8s
deploy step for UI, UI credential secrets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:59:22 +01:00
|
|
|
<div className={styles.detailContent}>
|
|
|
|
|
<ProcessorTree executionId={exec.executionId} />
|
|
|
|
|
<ExchangeDetail execution={exec} />
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|