feat: trace data indicators, inline tap config, and detail tab gating
All checks were successful
CI / build (push) Successful in 1m46s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 1m25s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 1m57s

Trace data visibility:
- ProcessorNode now includes hasTraceData flag computed from captured
  body/headers during tree conversion
- ConfigBadge shows teal for tracing configured, green when data captured
- Search results show green footprints icon for exchanges with trace data
- New has_trace_data column on executions table (V11 migration with backfill)
- OpenSearch documents and ExecutionSummary include the flag

Inline tap configuration:
- Extracted reusable TapConfigModal component from RouteDetail
- Diagram context menu opens tap modal inline instead of navigating away
- Toggle-trace action works immediately with toast feedback
- Modal closes only on ESC, Cancel, Save, or Delete (not backdrop click)

Detail panel tab gating:
- Headers, Input, Output tabs disabled when no data is available
- Works at both exchange and processor level
- Falls back to Info tab when active tab becomes empty

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-29 13:08:58 +02:00
parent 5103f40196
commit 3d71345181
22 changed files with 568 additions and 41 deletions

View File

@@ -0,0 +1,111 @@
.body {
display: flex;
flex-direction: column;
gap: 12px;
}
.formRow {
display: flex;
gap: 12px;
}
.formRow > * {
flex: 1;
}
.monoTextarea {
font-family: var(--font-mono);
font-size: 12px;
}
.typeSelector {
display: flex;
gap: 8px;
}
.typeOption {
padding: 4px 12px;
border-radius: var(--radius-sm);
font-size: 11px;
cursor: pointer;
border: 1px solid var(--border-subtle);
background: transparent;
color: var(--text-muted);
transition: all 0.12s;
}
.typeOption:hover {
border-color: var(--border);
color: var(--text-secondary);
}
.typeOptionActive {
background: var(--amber-bg);
color: var(--amber-deep);
border-color: var(--amber);
font-weight: 600;
}
.footer {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 8px;
}
.footerLeft {
display: flex;
flex: 1;
}
.testSection {
display: flex;
flex-direction: column;
gap: 8px;
}
.testTabs {
display: flex;
gap: 4px;
}
.testTabBtn {
padding: 4px 12px;
border-radius: 6px;
font-size: 11px;
cursor: pointer;
border: 1px solid transparent;
background: transparent;
color: var(--text-muted);
}
.testTabBtnActive {
background: var(--bg-hover);
color: var(--text-primary);
border-color: var(--text-muted);
}
.testBody {
margin-top: 4px;
}
.testResult {
padding: 10px 14px;
border-radius: var(--radius-md);
font-family: var(--font-mono);
font-size: 12px;
white-space: pre-wrap;
word-break: break-all;
}
.testSuccess {
background: var(--success-bg);
border: 1px solid var(--success-border);
color: var(--success);
}
.testError {
background: var(--error-bg);
border: 1px solid var(--error-border);
color: var(--error);
}