This commit is contained in:
nose
2025-11-27 10:59:01 -08:00
parent e9b505e609
commit 9eff65d1af
30 changed files with 2099 additions and 1095 deletions

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional, Sequence
from typing import Any, List, Optional, Sequence
from textual import work
from textual.app import App, ComposeResult
@@ -32,10 +32,9 @@ for path in (BASE_DIR, ROOT_DIR):
from menu_actions import ( # type: ignore # noqa: E402
PIPELINE_PRESETS,
PipelinePreset,
build_metadata_snapshot,
summarize_result,
)
from pipeline_runner import PipelineExecutor, PipelineRunResult # type: ignore # noqa: E402
from result_table import ResultTable # type: ignore # noqa: E402
class PresetListItem(ListItem):
@@ -73,6 +72,7 @@ class PipelineHubApp(App):
self.worker_table: Optional[DataTable] = None
self.preset_list: Optional[ListView] = None
self.status_panel: Optional[Static] = None
self.current_result_table: Optional[ResultTable] = None
self._pipeline_running = False
# ------------------------------------------------------------------
@@ -81,7 +81,7 @@ class PipelineHubApp(App):
def compose(self) -> ComposeResult: # noqa: D401 - Textual compose hook
yield Header(show_clock=True)
with Container(id="app-shell"):
with Horizontal(id="command-row"):
with Horizontal(id="command-pane"):
self.command_input = Input(
placeholder='download-data "<url>" | merge-file | add-tag | add-file -storage local',
id="pipeline-input",
@@ -174,7 +174,7 @@ class PipelineHubApp(App):
return
index = event.cursor_row
if 0 <= index < len(self.result_items):
self._display_metadata(self.result_items[index])
self._display_metadata(index)
# ------------------------------------------------------------------
# Pipeline execution helpers
@@ -216,6 +216,7 @@ class PipelineHubApp(App):
else:
self.result_items = []
self.current_result_table = run_result.result_table
self._populate_results_table()
self.refresh_workers()
@@ -228,40 +229,45 @@ class PipelineHubApp(App):
def _populate_results_table(self) -> None:
if not self.results_table:
return
self.results_table.clear()
if not self.result_items:
self.results_table.add_row("", "No results", "", "")
return
for idx, item in enumerate(self.result_items, start=1):
if isinstance(item, dict):
title = summarize_result(item)
source = item.get("source") or item.get("cmdlet_name") or item.get("cmdlet") or ""
file_path = item.get("file_path") or item.get("path") or ""
else:
title = str(item)
source = ""
file_path = ""
self.results_table.add_row(str(idx), title, source, file_path, key=str(idx - 1))
self.results_table.clear(columns=True)
def _display_metadata(self, item: Any) -> None:
if self.current_result_table and self.current_result_table.rows:
# Use ResultTable headers from the first row
first_row = self.current_result_table.rows[0]
headers = ["#"] + [col.name for col in first_row.columns]
self.results_table.add_columns(*headers)
rows = self.current_result_table.to_datatable_rows()
for idx, row_values in enumerate(rows, 1):
self.results_table.add_row(str(idx), *row_values, key=str(idx - 1))
else:
# Fallback or empty state
self.results_table.add_columns("Row", "Title", "Source", "File")
if not self.result_items:
self.results_table.add_row("", "No results", "", "")
return
# Fallback for items without a table
for idx, item in enumerate(self.result_items, start=1):
self.results_table.add_row(str(idx), str(item), "", "", key=str(idx - 1))
def _display_metadata(self, index: int) -> None:
if not self.metadata_tree:
return
root = self.metadata_tree.root
root.label = "Metadata"
root.remove_children()
payload: Dict[str, Any]
if isinstance(item, dict):
file_path = item.get("file_path") or item.get("path")
if file_path:
payload = build_metadata_snapshot(Path(file_path))
if self.current_result_table and 0 <= index < len(self.current_result_table.rows):
row = self.current_result_table.rows[index]
for col in row.columns:
root.add(f"[b]{col.name}[/b]: {col.value}")
elif 0 <= index < len(self.result_items):
item = self.result_items[index]
if isinstance(item, dict):
self._populate_tree_node(root, item)
else:
payload = item
else:
payload = {"value": str(item)}
self._populate_tree_node(root, payload)
root.expand_all()
root.add(str(item))
def _populate_tree_node(self, node, data: Any) -> None:
if isinstance(data, dict):
@@ -278,14 +284,14 @@ class PipelineHubApp(App):
def _clear_log(self) -> None:
self.log_lines = []
if self.log_output:
self.log_output.value = ""
self.log_output.text = ""
def _append_log_line(self, line: str) -> None:
self.log_lines.append(line)
if len(self.log_lines) > 500:
self.log_lines = self.log_lines[-500:]
if self.log_output:
self.log_output.value = "\n".join(self.log_lines)
self.log_output.text = "\n".join(self.log_lines)
def _append_block(self, text: str) -> None:
for line in text.strip().splitlines():