Avalonia-Portierung verbleibender UI-Elemente (A1 bis A4) umgesetzt

Paritaet mit dem WinForms-Referenzstand (Tag winforms-final) hergestellt:

- A1 & A2 (Launcher): Account-Uebersicht DataGrid (inkl. Polymarket-Profil-Button via Launcher.LaunchUriAsync), Modul-KPI-Kacheln (7T/30T PnL & Winrate) und 3-Spalten-Live-Ueberblick (Auffaellige Trades 24h, Warnungen & Fehler heute aus den JSONL-Logs, Supervisor-KI Bericht). Periodische Aktualisierung alle 30 s eingebaut.
- A3 (Copytrading): Master-Trader Werkzeugleiste um 'Neu' (AddNewTrader) und 'Loeschen' (DeleteSelectedTrader mit DialogWindow.Confirm) erweitert.
- A4 (Terminal): Log-Kontextmenue fuer 'Kopieren' und 'Alles auswaehlen' an die Live-Log-Ausgabe angefuegt.

Verifiziert: Solution baut fehlerfrei, 450 Tests gruen, --smoke-ui test erfolgreich.

Co-Authored-By: Antigravity AI <antigravity@google.com>
This commit is contained in:
Richard
2026-08-10 10:48:27 +02:00
co-authored by Antigravity AI
parent 29ea62fc7f
commit 7f0b05e9ba
7 changed files with 454 additions and 19 deletions
@@ -20,9 +20,11 @@
<TabItem Header="Master-Trader">
<DockPanel>
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Spacing="4">
<Button Name="btnTraderRefresh" Content="Aktualisieren" />
<Button Name="btnTraderNew" Content="Neu" />
<Button Name="btnTraderSave" Content="Speichern" />
<Button Name="btnTraderDelete" Content="Löschen" />
<TextBlock Name="lblTraderHint" VerticalAlignment="Center"
Margin="12,0,0,0" Foreground="{DynamicResource AppMutedTextBrush}" />
</StackPanel>
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@@ -53,7 +53,9 @@ namespace PolyTrader.App.Avalonia.Views.Modules
gridTraders.SelectionChanged += (_, _) => ShowSelectedTrader();
this.FindControl<ListBox>("listAccounts")!.ItemsSource = _assignments;
this.FindControl<Button>("btnTraderRefresh")!.Click += (_, _) => LoadTraders();
this.FindControl<Button>("btnTraderNew")!.Click += (_, _) => AddNewTrader();
this.FindControl<Button>("btnTraderSave")!.Click += (_, _) => SaveSelectedTrader();
this.FindControl<Button>("btnTraderDelete")!.Click += (_, _) => DeleteSelectedTrader();
// --- Offene Trades ---
var gridOpen = this.FindControl<DataGrid>("gridOpen")!;
@@ -145,6 +147,39 @@ namespace PolyTrader.App.Avalonia.Views.Modules
$"Gespeichert: #{trader.Id} {trader.DisplayName} ({trader.AssignedAccountIds.Count} Account(s)) um {DateTime.Now:HH:mm:ss}.";
}
private void AddNewTrader()
{
int nextId = _traders.Count > 0 ? _traders.Max(t => t.Id) + 1 : 1;
var trader = new TrackedTrader { Id = nextId, DisplayName = $"Neuer Trader {nextId}" };
_traders.Add(trader);
var grid = this.FindControl<DataGrid>("gridTraders")!;
grid.SelectedItem = trader;
this.FindControl<TextBlock>("lblTraderHint")!.Text = $"Neuer Master-Trader #{nextId} – Felder ausfüllen und Speichern.";
}
private async void DeleteSelectedTrader()
{
var grid = this.FindControl<DataGrid>("gridTraders")!;
if (grid.SelectedItem is not TrackedTrader trader)
{
this.FindControl<TextBlock>("lblTraderHint")!.Text = "Kein Trader ausgewählt.";
return;
}
int id = trader.Id;
bool confirm = await DialogWindow.Confirm(this, "Löschen bestätigen",
$"Master-Trader #{id} ({trader.DisplayName}) wirklich löschen?");
if (!confirm) return;
_traderRepo.Delete(id);
_copyState.Traders.TryRemove(id, out _);
_traders.Remove(trader);
ShowSelectedTrader();
this.FindControl<TextBlock>("lblTraderHint")!.Text = $"Master-Trader #{id} gelöscht.";
}
// ===== Offene Trades =====
private void LoadOpenTrades()