| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- # -*- coding: utf-8 -*-
- """
- Trainer SubView: Settings (F2).
- Schema-basiertes Formular fuer Trainings-Einstellungen.
- Felder werden dynamisch aus dem Settings-Schema des Trainers generiert.
- """
- from __future__ import annotations
- from textual.app import ComposeResult
- from textual.containers import Vertical
- from textual.widgets import Static, Button, Input, Switch
- from trixy_core.tui.views.base import MainView
- class TrainerSettingsView(MainView):
- """F2 im Trainer-Kontext: Trainings-Einstellungen."""
- TITLE = "Einstellungen"
- VIEW_ID = "trainer_settings"
- def __init__(self, **kwargs) -> None:
- super().__init__(**kwargs)
- self._trainer_data: dict = {}
- self._detail_data: object | None = None
- self._field_ids: list[str] = []
- def set_trainer(self, trainer_data: dict) -> None:
- """Setzt die Trainer-Basisdaten."""
- self._trainer_data = trainer_data
- self._detail_data = None
- self._field_ids = []
- def compose(self) -> ComposeResult:
- with Vertical(classes="trainer-section"):
- yield Static("[bold]Einstellungen[/bold]", classes="trainer-section-header")
- yield Vertical(id="trainer-settings-form", classes="trainer-form-container")
- yield Button("Speichern", id="trainer-settings-save", variant="success")
- yield Static("", id="trainer-settings-status")
- async def on_activate(self) -> None:
- """Laedt Schema und aktuelle Werte."""
- await self._load_detail()
- async def _load_detail(self) -> None:
- """Laedt Detail-Daten und baut das Formular auf."""
- if not self.connection or not self._trainer_data:
- return
- trainer_id = self._trainer_data.get("trainer_id", "")
- if not trainer_id:
- return
- try:
- detail = await self.connection.request_trainer_detail(trainer_id)
- except Exception:
- return
- if detail is None or detail.error:
- return
- self._detail_data = detail
- await self._build_form(detail)
- async def _build_form(self, detail: object) -> None:
- """Baut das Formular aus dem Schema dynamisch auf."""
- container = self.query_one("#trainer-settings-form", Vertical)
- # Alte Felder entfernen
- for child in list(container.children):
- await child.remove()
- self._field_ids = []
- schema = getattr(detail, "settings_schema", {})
- fields = schema.get("fields", []) if isinstance(schema, dict) else []
- settings = getattr(detail, "settings", {})
- for field_def in fields:
- name = field_def.get("name", "") or field_def.get("key", "")
- label = field_def.get("label", name)
- field_type = field_def.get("field_type", "") or field_def.get("type", "text")
- help_text = field_def.get("help_text", "") or field_def.get("help", "")
- default = field_def.get("default")
- current_value = settings.get(name, default)
- field_id = f"trainer-set-{name}"
- self._field_ids.append(field_id)
- # Label
- label_widget = Static(label, classes="trainer-field-label")
- await container.mount(label_widget)
- # Widget je nach Typ
- if field_type == "checkbox":
- widget = Switch(id=field_id, value=bool(current_value))
- elif field_type == "number":
- is_float = field_def.get("is_float", False)
- input_type = "number" if is_float else "integer"
- val_str = str(current_value) if current_value is not None else ""
- widget = Input(
- id=field_id,
- value=val_str,
- placeholder=str(default) if default is not None else "",
- type=input_type,
- )
- else:
- widget = Input(
- id=field_id,
- value=str(current_value) if current_value is not None else "",
- placeholder=field_def.get("placeholder", ""),
- )
- await container.mount(widget)
- if help_text:
- help_widget = Static(f"[dim]{help_text}[/dim]", classes="trainer-field-help")
- await container.mount(help_widget)
- def collect_settings(self) -> dict:
- """Sammelt die Einstellungswerte aus dem Formular."""
- if not self._detail_data:
- return {}
- schema = getattr(self._detail_data, "settings_schema", {})
- fields = schema.get("fields", []) if isinstance(schema, dict) else []
- result = {}
- for field_def in fields:
- name = field_def.get("name", "") or field_def.get("key", "")
- field_type = field_def.get("field_type", "") or field_def.get("type", "text")
- field_id = f"trainer-set-{name}"
- try:
- if field_type == "checkbox":
- widget = self.query_one(f"#{field_id}", Switch)
- result[name] = widget.value
- elif field_type == "number":
- widget = self.query_one(f"#{field_id}", Input)
- is_float = field_def.get("is_float", False)
- if is_float:
- result[name] = float(widget.value) if widget.value else 0.0
- else:
- result[name] = int(widget.value) if widget.value else 0
- else:
- widget = self.query_one(f"#{field_id}", Input)
- result[name] = widget.value
- except Exception:
- pass
- return result
- async def on_button_pressed(self, event: Button.Pressed) -> None:
- """Speichern-Button."""
- if event.button.id != "trainer-settings-save":
- return
- status = self.query_one("#trainer-settings-status", Static)
- if not self.connection:
- status.update("[red]Keine Verbindung[/red]")
- return
- trainer_id = self._trainer_data.get("trainer_id", "")
- settings = self.collect_settings()
- try:
- status.update("[yellow]Speichern...[/yellow]")
- result = await self.connection.write_trainer_settings(trainer_id, settings)
- if result and result.success:
- status.update("[green]Einstellungen gespeichert[/green]")
- else:
- error = result.error if result else "Unbekannter Fehler"
- status.update(f"[red]Fehler: {error}[/red]")
- except Exception as e:
- status.update(f"[red]Fehler: {e}[/red]")
|