good layout

This commit is contained in:
2025-07-28 11:06:10 -04:00
parent a3c50fd845
commit 2ab3f1fe9e
7 changed files with 482 additions and 20 deletions

View File

@@ -44,6 +44,13 @@ class FlowMainDetailsPanel(Vertical):
def update_flow(self, flow: Optional['FlowStats']) -> None:
"""Update panel with main flow details"""
flow_info = f"{flow.src_ip}:{flow.src_port}" if flow else "None"
try:
debug_panel = self.app.query_one("#debug-panel")
debug_panel.add_debug_message(f"MAIN_PANEL: Update called - {flow_info}")
except:
pass
self.current_flow = flow
content_widget = self.query_one("#main-details-content", Static)
@@ -52,6 +59,14 @@ class FlowMainDetailsPanel(Vertical):
return
details = self._create_main_flow_details(flow)
# Debug what content we're actually setting
try:
debug_panel = self.app.query_one("#debug-panel")
debug_panel.add_debug_message(f"CONTENT: Setting panel content for {flow.src_ip}:{flow.src_port}")
except:
pass
content_widget.update(details)
def _create_main_flow_details(self, flow: 'FlowStats') -> RenderableType:
@@ -91,21 +106,57 @@ class FlowMainDetailsPanel(Vertical):
sections.append(Text("Enhanced Analysis", style="bold green"))
sections.append(enhanced_table)
# Timing analysis with new columns
timing_table = Table(show_header=False, box=None, padding=0)
timing_table.add_column(style="dim", width=12)
timing_table.add_column()
# Timing analysis - only show if no sub-flows exist
# Match the same logic as _should_show_subrows in flow_table_v2.py
has_subflows = (len(flow.frame_types) > 1 or
flow.enhanced_analysis.decoder_type != "Standard")
timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
timing_table.add_row("Avg ΔT:", f"{flow.avg_inter_arrival * 1000:.1f}ms")
timing_table.add_row("Std σ:", f"{flow.std_inter_arrival * 1000:.1f}ms")
timing_table.add_row("Outliers:", f"{len(flow.outlier_frames)}")
timing_table.add_row("Jitter:", f"{flow.jitter * 1000:.2f}ms")
timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
# Debug output
try:
debug_panel = self.app.query_one("#debug-panel")
debug_panel.add_debug_message(f"TIMING_LOGIC: {flow.src_ip}:{flow.src_port} - types={len(flow.frame_types)}, decoder={flow.enhanced_analysis.decoder_type}, has_subflows={has_subflows}")
except:
pass
sections.append(Text("Timing Analysis", style="bold cyan"))
sections.append(timing_table)
if not has_subflows:
try:
debug_panel = self.app.query_one("#debug-panel")
debug_panel.add_debug_message(f"BRANCH: Taking FULL timing branch for {flow.src_ip}:{flow.src_port}")
except:
pass
timing_table = Table(show_header=False, box=None, padding=0)
timing_table.add_column(style="dim", width=12)
timing_table.add_column()
timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
timing_table.add_row("Avg ΔT:", f"{flow.avg_inter_arrival * 1000:.1f}ms")
timing_table.add_row("Std σ:", f"{flow.std_inter_arrival * 1000:.1f}ms")
timing_table.add_row("Outliers:", f"{len(flow.outlier_frames)}")
timing_table.add_row("Jitter:", f"{flow.jitter * 1000:.2f}ms")
timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
sections.append(Text("Timing Analysis", style="bold cyan"))
sections.append(timing_table)
else:
try:
debug_panel = self.app.query_one("#debug-panel")
debug_panel.add_debug_message(f"BRANCH: Taking BASIC timeline branch for {flow.src_ip}:{flow.src_port}")
except:
pass
# Just show duration and timestamps for flows with sub-flows
basic_timing_table = Table(show_header=False, box=None, padding=0)
basic_timing_table.add_column(style="dim", width=12)
basic_timing_table.add_column()
basic_timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
basic_timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
basic_timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
sections.append(Text("Flow Timeline", style="bold cyan"))
sections.append(basic_timing_table)
return Group(*sections)