Settings nach Avalonia - PropertyGrid durch kategorisierten Editor ersetzt

Der PropertyGrid-Ersatz ist EIN wiederverwendbares Steuerelement statt Handarbeit je Feld:
Controls/SettingsEditor zeigt ein beliebiges Einstellungsobjekt nach Richards Vorlage -
Kategorie-Ueberschrift, Beschriftung links, Feld rechts, Erklaerung klein darunter.

- SettingsModelBuilder liest die Attribute, die fuers PropertyGrid ohnehin gepflegt waren:
  [Category] gruppiert, [DisplayName] beschriftet, [Description] wird zum Hinweistext,
  [Browsable(false)] blendet aus (Watchdog-Token, Lizenzschluessel bleiben unsichtbar).
  Ergebnis fuer ServerSettings: 6 Abschnitte, 15 Felder - ohne eine Zeile Feld-Code.
- Layout-Regel gewahrt: WELCHE Felder es gibt, kommt als Daten; WIE ein Feld aussieht,
  steht deklarativ als DataTemplate je Feldtyp (Text/Zahl/Ja-Nein/Auswahl/Nur-Lese).
- Damit sind auch die drei restlichen PropertyGrid-Stellen (Account-Einstellungen,
  Master-Trader, ResolutionFarming) mit je einem Aufruf erledigt.

SettingsWindow: Server-Settings + Polymarket-Accounts, Master-Key erzeugen,
OpenRouter-Key/Watchdog-Token setzen, Test-Heartbeat. Rueckmeldungen laufen ueber die
Statuszeile statt ueber Dialoge - nur echte Entscheidungen bekommen einen Dialog
(neu: Views/DialogWindow fuer Hinweis/Rueckfrage/maskierte Eingabe, Avalonia hat keine MessageBox).

Nebenbei einen offenen Punkt der Linux-Analyse erledigt: Schluesseldateien (master.key,
openrouter.key) werden jetzt per File.SetUnixFileMode auf 600 gesetzt. Auf Linux legt
File.WriteAllText sonst mit ueblicher umask 644 an - weltweit lesbar.

Lizenzdialog bewusst NICHT portiert: haengt am alten LicenseLabrador-SDK, das mit der
Deploymentcenter-Anbindung (P3c) ohnehin ersetzt wird - waere Wegwerfarbeit.

Smoke-UI prueft jetzt zusaetzlich die Feldzahl des Editors: ein Fenster kann fehlerfrei
konstruieren und trotzdem leer sein, wenn die Attribute verlorengehen.

Verifiziert: Solution baut, 442 Tests gruen, --smoke-ui gruen (5 Fenster + Editor-Pruefung),
Linux-Publish laeuft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-06 20:55:47 +02:00
co-authored by Claude Opus 5
parent 0b8728b25f
commit 4ba8149e64
9 changed files with 873 additions and 1 deletions
@@ -0,0 +1,75 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:models="using:PolyTraderSharp.Models"
x:Class="PolyTrader.App.Avalonia.Views.SettingsWindow"
Title="Server Settings"
Width="1185" Height="820">
<!--
Einstellungen. Ersetzt die beiden PropertyGrids der WinForms-Fassung durch den
kategorisierten SettingsEditor (Überschrift, Beschriftung links, Feld rechts,
Erklärung klein darunter).
-->
<DockPanel>
<controls:WindowMenuBar Name="menuBar" DockPanel.Dock="Top" />
<Border Classes="statusbar" DockPanel.Dock="Bottom">
<TextBlock Name="lblStatus" Text="Bereit." />
</Border>
<TabControl>
<TabItem Header="Allgemeine Einstellungen">
<DockPanel>
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal">
<Button Name="btnSave" Content="Speichern" />
<Button Name="btnReload" Content="Neu laden" />
<Separator Margin="6,0" />
<Button Name="btnGenMasterKey" Content="Master-Key erzeugen"
ToolTip.Tip="Erzeugt einen zufälligen AES-Master-Key (nur wenn noch keiner existiert)." />
<Button Name="btnOpenRouterKey" Content="OpenRouter-Key setzen …"
ToolTip.Tip="Speichert den OpenRouter-API-Key für den Supervisor (gitignorierte Datei openrouter.key)." />
<Button Name="btnWatchdogToken" Content="Watchdog-Token setzen …"
ToolTip.Tip="Speichert den Watchdog-Agent-Token (maskierte Eingabe, bei gesetztem Master-Key verschlüsselt)." />
<Button Name="btnTestWatchdog" Content="Test-Heartbeat senden"
ToolTip.Tip="Sendet sofort einen Heartbeat an den konfigurierten Watchdog-Server." />
</StackPanel>
</Border>
<controls:SettingsEditor Name="editorServer" />
</DockPanel>
</TabItem>
<TabItem Header="Polymarket Accounts">
<DockPanel>
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal">
<Button Name="btnAccNew" Content="Neuer Account" />
<Button Name="btnAccDelete" Content="Löschen" />
<Button Name="btnAccSave" Content="Account speichern" />
</StackPanel>
</Border>
<Grid ColumnDefinitions="380,4,*">
<DataGrid Name="gridAccounts" Grid.Column="0" x:DataType="models:AccountState">
<DataGrid.Columns>
<DataGridTextColumn Header="#" Width="50" Binding="{Binding AccountId}" />
<DataGridTextColumn Header="Name" Width="*" Binding="{Binding Name}" />
<DataGridCheckBoxColumn Header="Demo" Width="60" Binding="{Binding IsDemo}" />
<DataGridCheckBoxColumn Header="Aktiv" Width="60" Binding="{Binding IsActive}" />
</DataGrid.Columns>
</DataGrid>
<GridSplitter Grid.Column="1" Background="#DDDDDD" />
<controls:SettingsEditor Name="editorAccount" Grid.Column="2" />
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</DockPanel>
</Window>