from rich.markup import escape from textual import on from textual.app import ComposeResult from textual.binding import Binding from textual.containers import Horizontal, VerticalScroll from textual.widgets import DataTable, Static import portfolio from fields import get_path, to_form_text from tui.content_pane import ContentPane from tui.record_editor import RecordEditor PREVIEW_LENGTH = 60 class ProfilePane(ContentPane): BINDINGS = [ Binding("e", "edit", "Edit"), Binding("r", "reload", "Reload"), ] content_file = portfolio.PROFILE.file def compose(self) -> ComposeResult: with Horizontal(classes="split-layout"): yield DataTable(cursor_type="row", zebra_stripes=True) with VerticalScroll(classes="detail-scroll"): yield Static("", id="profile-detail") def on_mount(self): table = self.table() table.add_column("Field", key="field") table.add_column("Value", key="value") self.reload() def reload(self, focus_key: str | None = None): profile = portfolio.load_records(portfolio.PROFILE) table = self.table() table.clear() for spec in portfolio.PROFILE.fields: text = to_form_text(spec.kind, get_path(profile, spec.path)).replace("\n", " ยท ") preview = text if len(text) <= PREVIEW_LENGTH else text[:PREVIEW_LENGTH] + "..." table.add_row(spec.label, preview, key=spec.path) self.restore_cursor(focus_key) self.show_field(self.selected_key()) def show_field(self, path: str | None): spec = next((item for item in portfolio.PROFILE.fields if item.path == path), None) detail = self.query_one("#profile-detail", Static) if not spec: detail.update("") return value = to_form_text(spec.kind, get_path(portfolio.load_records(portfolio.PROFILE), spec.path)) hint = f"\n[dim]{spec.hint}[/dim]" if spec.hint else "" detail.update(f"[b]{escape(spec.label)}[/b]{hint}\n\n{escape(value) or '[dim]empty[/dim]'}\n\n[dim]Press e or Enter to edit the profile.[/dim]") @on(DataTable.RowHighlighted) def highlight_changed(self, event: DataTable.RowHighlighted): self.show_field(event.row_key.value if event.row_key else None) @on(DataTable.RowSelected) def row_selected(self): self.action_edit() def action_edit(self): profile = portfolio.load_records(portfolio.PROFILE) focus_key = self.selected_key() def saved(result: dict | None): if result is not None: self.run_now(lambda: portfolio.save_record(portfolio.PROFILE, None, result), "Saved profile", focus_key) self.app.push_screen(RecordEditor("Edit profile", portfolio.PROFILE.fields, profile), saved)