Arbeitsstand gesichert: Deploymentcenter-Integration (D-0 bis D-5) und Einfenster-Shell

Sicherungscommit vor dem Aufraeumen des Repos, damit nachvollziehbar bleibt,
welcher Stand vor der Bereinigung galt. Build gruen, 476 Tests gruen.

Zwei Straenge, die sich ueber .csproj, Program.cs und appsettings.json
ueberschneiden und darum gemeinsam abgelegt werden:

Deploymentcenter-Integration (P3c, Plan D-0 bis D-5 code-seitig fertig):
- Deploymentcenter.Client 2.5.0 als lokales Paket, Source-Mapping erweitert
- DeploymentcenterOptions, DeploymentcenterErrorReporter, LicenseGate/LicenseCli
- WatchdogHeartbeatService auf die Deploymentcenter-API umgestellt
  (version, os, checks, metrics, status stopped)
- Security: MasterKeyResolver, SecretRedactor, FilePermissions
- Directory.Build.props mit zentraler Version 0.1.0 (Packager-Versionsdisziplin)
- deploy/: Packager-Vorlage und systemd-Unit; echte Zugangsdaten bleiben
  ueber .gitignore aussen vor
- setup.json fuer die Erstinstallation
- UMSETZUNGSPLAN-Deploymentcenter-Integration.md; ANALYSE-Linux-Portierung.md
  verweist auf den neuen Plan

Einfenster-Shell (UI-Redesign):
- ShellWindow + ShellNavModel als Seitenleisten-Shell
- WindowMenuBar und WindowMenuModel entfallen
- Modul- und Kernfenster auf die Shell-Einbettung angepasst

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-08-22 10:42:22 +02:00
co-authored by Claude Opus 5
parent ac5e16f0a6
commit dd8da3fd3f
58 changed files with 3932 additions and 650 deletions
@@ -1,17 +1,12 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:acc="using:PolyTrader.Modules.Accounting.Models"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
x:Class="PolyTrader.App.Avalonia.Views.Modules.AccountingWindow"
Title="Accounting"
Width="1571" Height="1067">
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:acc="using:PolyTrader.Modules.Accounting.Models"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
x:Class="PolyTrader.App.Avalonia.Views.Modules.AccountingWindow">
<!-- Drei Tabs (Übersicht/BWA, Ledger, Abruf/Status), Aufbau nach
docs/UI-SPEZIFIKATION-WinForms.md. KPI-Kacheln zweizeilig wie zuvor. -->
<DockPanel>
<controls:WindowMenuBar Name="menuBar" DockPanel.Dock="Top" />
<Border Classes="statusbar" DockPanel.Dock="Bottom">
<TextBlock Name="lblStatus" Text="Bereit." />
</Border>
@@ -164,4 +159,4 @@
</TabControl>
</DockPanel>
</Window>
</UserControl>
@@ -21,7 +21,7 @@ namespace PolyTrader.App.Avalonia.Views.Modules
/// Accounting: Periodenabrechnung mit KPI-Kacheln und Monatsübersicht, Ledger-Ansicht und
/// Abruf-/Status-Tab. Layout vollständig in AccountingWindow.axaml.
/// </summary>
public partial class AccountingWindow : Window
public partial class AccountingWindow : UserControl
{
private readonly ObservableCollection<MonthlyRow> _monthly = new();
private readonly ObservableCollection<LedgerEntry> _ledger = new();
@@ -43,8 +43,6 @@ namespace PolyTrader.App.Avalonia.Views.Modules
ILedgerRepository ledgerRepo, IIngestRunRepository runRepo,
AccountingIngestService ingest, TerminalLogger logger) : this()
{
this.FindControl<Controls.WindowMenuBar>("menuBar")!.Attach(host, "accounting.main", this);
_state = state;
_reports = reports;
_ledgerRepo = ledgerRepo;
@@ -157,7 +155,12 @@ namespace PolyTrader.App.Avalonia.Views.Modules
try
{
var picker = await StorageProvider.SaveFilePickerAsync(new global::Avalonia.Platform.Storage.FilePickerSaveOptions
// Seit der Umstellung auf Seiten ist „this" kein TopLevel mehr – der Dateidialog
// gehört dem Shell-Fenster und wird über den Baum aufgelöst.
var storage = TopLevel.GetTopLevel(this)?.StorageProvider;
if (storage == null) { Status("Kein Fenster für den Dateidialog verfügbar."); return; }
var picker = await storage.SaveFilePickerAsync(new global::Avalonia.Platform.Storage.FilePickerSaveOptions
{
Title = pdf ? "PDF-Export" : "CSV-Export",
SuggestedFileName = $"abrechnung_{_statement.From:yyyyMMdd}_{_statement.To:yyyyMMdd}" + (pdf ? ".pdf" : ".csv"),
@@ -1,11 +1,9 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
xmlns:ct="using:PolyTraderSharp.Models"
x:Class="PolyTrader.App.Avalonia.Views.Modules.CopyTradingWindow"
Title="Copytrading"
Width="1714" Height="1167">
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
xmlns:ct="using:PolyTraderSharp.Models"
x:Class="PolyTrader.App.Avalonia.Views.Modules.CopyTradingWindow">
<!--
Ein Fenster fürs ganze Modul, vier Tabs – Aufbau nach docs/UI-SPEZIFIKATION-WinForms.md.
@@ -13,8 +11,6 @@
Pixelbreiten sind in Sternbreiten übersetzt, damit das Fenster mitwächst.
-->
<DockPanel>
<controls:WindowMenuBar Name="menuBar" DockPanel.Dock="Top" />
<TabControl>
<TabItem Header="Master-Trader">
@@ -160,4 +156,4 @@
</TabControl>
</DockPanel>
</Window>
</UserControl>
@@ -17,7 +17,7 @@ namespace PolyTrader.App.Avalonia.Views.Modules
/// Copytrading-Fenster mit vier Tabs: Master-Trader, Offene Trades, Geschlossene Trades,
/// Account-Einstellungen. Layout vollständig in CopyTradingWindow.axaml.
/// </summary>
public partial class CopyTradingWindow : Window
public partial class CopyTradingWindow : UserControl
{
private readonly ObservableCollection<TrackedTrader> _traders = new();
private readonly ObservableCollection<AccountAssignment> _assignments = new();
@@ -39,8 +39,6 @@ namespace PolyTrader.App.Avalonia.Views.Modules
ITrackedTraderRepository traderRepo, ICopyTradingAccountSettingsRepository settingsRepo,
ICopyTradeLogRepository tradeLog) : this()
{
this.FindControl<WindowMenuBar>("menuBar")!.Attach(host, "copytrading.main", this);
_state = state;
_copyState = copyState;
_traderRepo = traderRepo;
@@ -103,8 +101,9 @@ namespace PolyTrader.App.Avalonia.Views.Modules
gridOpen.ItemsSource = null; gridOpen.ItemsSource = _openTrades;
gridClosed.ItemsSource = null; gridClosed.ItemsSource = _closedTrades;
}
// Kein Abmelden: Seiten leben in der Einfenster-Shell bis zum Programmende
// (siehe AvaloniaUiHost), ein Gegenstueck zu Window.Closed gibt es nicht.
Shell.ThemeManager.ThemeChanged += OnTheme;
Closed += (_, _) => Shell.ThemeManager.ThemeChanged -= OnTheme;
}
// ===== Master-Trader =====
@@ -1,16 +1,12 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:rf="using:PolyTrader.Modules.ResolutionFarming.Models"
x:Class="PolyTrader.App.Avalonia.Views.Modules.ResolutionFarmingWindow"
Title="ResolutionFarming"
Width="1429" Height="1030">
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:rf="using:PolyTrader.Modules.ResolutionFarming.Models"
x:Class="PolyTrader.App.Avalonia.Views.Modules.ResolutionFarmingWindow">
<!-- Vier Tabs (Kandidaten / Positionen / Historie+Statistik / Settings), Aufbau nach
docs/UI-SPEZIFIKATION-WinForms.md: je Tab ein Grid mit „Aktualisieren", Konto-Auswahl oben. -->
<DockPanel>
<controls:WindowMenuBar Name="menuBar" DockPanel.Dock="Top" />
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Konto:" VerticalAlignment="Center" />
@@ -94,4 +90,4 @@
</TabControl>
</DockPanel>
</Window>
</UserControl>
@@ -15,7 +15,7 @@ namespace PolyTrader.App.Avalonia.Views.Modules
/// ResolutionFarming: Kandidaten, offene Positionen, Historie und Einstellungen je Konto.
/// Layout vollständig in ResolutionFarmingWindow.axaml.
/// </summary>
public partial class ResolutionFarmingWindow : Window
public partial class ResolutionFarmingWindow : UserControl
{
private readonly ObservableCollection<RfCandidate> _candidates = new();
private readonly ObservableCollection<RfPosition> _positions = new();
@@ -35,8 +35,6 @@ namespace PolyTrader.App.Avalonia.Views.Modules
IRfCandidateRepository candidateRepo, IRfPositionRepository positionRepo,
IRfClosedTradeRepository closedRepo, IRfSettingsRepository settingsRepo) : this()
{
this.FindControl<WindowMenuBar>("menuBar")!.Attach(host, "resolutionfarming.main", this);
_state = state;
_candidateRepo = candidateRepo;
_positionRepo = positionRepo;
@@ -1,20 +1,15 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:PolyTrader.App.Avalonia.Controls"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
xmlns:sup="using:PolyTrader.Modules.Supervisor.Persistence"
xmlns:cf="using:PolyTrader.Modules.Supervisor.Counterfactual"
xmlns:svc="using:PolyTrader.Modules.Supervisor.Services"
x:Class="PolyTrader.App.Avalonia.Views.Modules.SupervisorWindow"
Title="Supervisor"
Width="1786" Height="1163">
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
xmlns:sup="using:PolyTrader.Modules.Supervisor.Persistence"
xmlns:cf="using:PolyTrader.Modules.Supervisor.Counterfactual"
xmlns:svc="using:PolyTrader.Modules.Supervisor.Services"
x:Class="PolyTrader.App.Avalonia.Views.Modules.SupervisorWindow">
<!-- Vier Tabs (Analyse / Dossiers / Berichte / Counterfactual), Aufbau nach
docs/UI-SPEZIFIKATION-WinForms.md. Der Analyse-Tab ist chat-artig: Verlauf oben,
Eingabe unten, Profil- und Modellauswahl in der Werkzeugleiste. -->
<DockPanel>
<controls:WindowMenuBar Name="menuBar" DockPanel.Dock="Top" />
<TabControl>
<TabItem Header="Analyse">
@@ -126,4 +121,4 @@
</TabControl>
</DockPanel>
</Window>
</UserControl>
@@ -19,7 +19,7 @@ namespace PolyTrader.App.Avalonia.Views.Modules
/// Supervisor: Analyse-Chat gegen den Agenten, Dossiers je Signal, gespeicherte Berichte und
/// Counterfactuals. Layout vollständig in SupervisorWindow.axaml.
/// </summary>
public partial class SupervisorWindow : Window
public partial class SupervisorWindow : UserControl
{
private readonly ObservableCollection<ChatEntry> _chat = new();
private readonly ObservableCollection<SignalSummary> _signals = new();
@@ -38,8 +38,6 @@ namespace PolyTrader.App.Avalonia.Views.Modules
ISupervisorReportRepository reportRepo, ISupervisorCounterfactualRepository cfRepo,
TerminalLogger logger) : this()
{
this.FindControl<Controls.WindowMenuBar>("menuBar")!.Attach(host, "supervisor.main", this);
_agent = agent;
_dossiers = dossiers;
_reportRepo = reportRepo;