R7: Dashboard-View + DashboardService (Abschluss Feinschliff) - Core/Trading/DashboardService: aggregiert Positionen/Exposure/Trades via EF (DashboardSnapshot) - UI/Views/DashboardView: Trading-Modus, aggregierte Kennzahlen, geladene Module (+ Aktivierungs-Status) - core.dashboard-View registriert (Order 5) mit dashboard-Icon - Tests: DashboardService (leer + Aggregation, InMemory) -> 58/58 gruen; smoke-ui deckt alle 5 Views ab Kurskorrektur R1-R7 abgeschlossen: IBKRTrader folgt dem PolytraderSharp-Konzept. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
99 lines
3.8 KiB
C#
99 lines
3.8 KiB
C#
using IBKRTrader.Core.Modularity;
|
||
using IBKRTrader.Core.Settings;
|
||
using IBKRTrader.Core.Trading;
|
||
using IBKRTrader.Core.Workers;
|
||
using Microsoft.Extensions.Configuration;
|
||
|
||
namespace IBKRTrader.UI.Views;
|
||
|
||
/// <summary>Core-View: Gesamtüberblick (Trading-Modus, aggregierte Kennzahlen, geladene Module).</summary>
|
||
public sealed class DashboardView : Form
|
||
{
|
||
private readonly DashboardService _dashboard;
|
||
private readonly SettingsService _settings;
|
||
private readonly IReadOnlyList<IModule> _modules;
|
||
private readonly IConfiguration _config;
|
||
private readonly int _workerCount;
|
||
|
||
private readonly Label _lblMode = new() { AutoSize = true, Location = new Point(20, 20), Font = new Font("Segoe UI", 13f, FontStyle.Bold) };
|
||
private readonly Label _lblStats = new() { AutoSize = true, Location = new Point(20, 60) };
|
||
private readonly Label _lblStatus = new() { AutoSize = true, Location = new Point(20, 90), ForeColor = SystemColors.GrayText };
|
||
private readonly DataGridView _modulesGrid = new()
|
||
{
|
||
Location = new Point(20, 130),
|
||
Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right,
|
||
ReadOnly = true,
|
||
AllowUserToAddRows = false,
|
||
RowHeadersVisible = false,
|
||
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill
|
||
};
|
||
|
||
public DashboardView(
|
||
DashboardService dashboard,
|
||
SettingsService settings,
|
||
IEnumerable<IModule> modules,
|
||
IConfiguration config,
|
||
IEnumerable<IWorker> workers)
|
||
{
|
||
_dashboard = dashboard;
|
||
_settings = settings;
|
||
_modules = modules.ToList();
|
||
_config = config;
|
||
_workerCount = workers.Count();
|
||
|
||
Text = "Dashboard";
|
||
Width = 900;
|
||
Height = 560;
|
||
StartPosition = FormStartPosition.CenterScreen;
|
||
MinimumSize = new Size(600, 400);
|
||
|
||
var modLabel = new Label { Text = "Geladene Module:", Location = new Point(20, 108), AutoSize = true };
|
||
var refresh = new Button { Text = "Aktualisieren", Location = new Point(760, 18), Width = 110, Anchor = AnchorStyles.Top | AnchorStyles.Right };
|
||
refresh.Click += async (_, _) => await RefreshAsync();
|
||
|
||
_modulesGrid.Size = new Size(ClientSize.Width - 40, ClientSize.Height - 150);
|
||
|
||
Controls.Add(_lblMode);
|
||
Controls.Add(_lblStats);
|
||
Controls.Add(_lblStatus);
|
||
Controls.Add(modLabel);
|
||
Controls.Add(_modulesGrid);
|
||
Controls.Add(refresh);
|
||
}
|
||
|
||
protected override async void OnShown(EventArgs e)
|
||
{
|
||
base.OnShown(e);
|
||
await RefreshAsync();
|
||
}
|
||
|
||
private async Task RefreshAsync()
|
||
{
|
||
var t = _settings.Settings.Trading;
|
||
_lblMode.Text = $"Trading: {t.Mode} – {(t.TradingEnabled ? "AKTIV" : "inaktiv")}";
|
||
_lblMode.ForeColor = t.TradingEnabled ? Color.SeaGreen : SystemColors.GrayText;
|
||
|
||
_modulesGrid.DataSource = _modules
|
||
.Select(m => new
|
||
{
|
||
Modul = m.Name,
|
||
Präfix = m.DbPrefix,
|
||
Status = m.GetActivationBlocker(_config) ?? "aktivierbar"
|
||
})
|
||
.ToList();
|
||
|
||
try
|
||
{
|
||
var snap = await _dashboard.GetSnapshotAsync();
|
||
_lblStats.Text = $"Offene Positionen: {snap.OpenPositions} | Exposure: {snap.TotalExposure:N2} | " +
|
||
$"Trades gesamt: {snap.TotalTrades} | Worker/Services: {_workerCount}";
|
||
_lblStatus.Text = $"Aktualisiert: {DateTime.Now:HH:mm:ss}";
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_lblStats.Text = $"Kennzahlen n/v | Worker/Services: {_workerCount}";
|
||
_lblStatus.Text = $"DB nicht erreichbar: {ex.Message}";
|
||
}
|
||
}
|
||
}
|