Files
PolyTraderSharp/src/PolyTrader.App.Avalonia/Views/TerminalWindow.axaml
T
RichardandClaude Opus 5 9b2294cb4c
CI / Build & Tests (Linux) (push) Canceled after 0s
CI / Plattformneutralität & Hygiene (push) Canceled after 0s
Testanleitung: eigenes X-Display je Projekt fuer Parallelbetrieb
Damit mehrere Agenten gleichzeitig Oberflaechen testen koennen, bekommt jedes
Projekt eine feste Displaynummer (Vorgabe Richard):

  :99 PolyTrader, :98 Predictalytics, :97 ClawdDotNet, :96 IBKRTrader,
  :95 und absteigend fuer kuenftige Projekte.

Zwei Prozesse auf demselben Display sehen die Fenster des jeweils anderen -
Klicks landen im falschen Programm, Aufnahmen zeigen fremde Anwendungen.

Beim Durcharbeiten fielen zwei weitere Kollisionspunkte auf, die zum
Parallelbetrieb dazugehoeren und mit aufgenommen wurden:

- Screenshot- und Logdateien in /tmp brauchen ein Projektpraefix. /tmp/v_1.png
  ueberschreiben sich parallel laufende Projekte gegenseitig.
- "xvfb-run -a" darf NICHT mehr verwendet werden: Das -a sucht sich selbst ein
  freies Display und beginnt dabei bei :99 - ausgerechnet PolyTraders Nummer.
  Stattdessen "xvfb-run -n <nummer>".

Die Warnung ist nicht theoretisch: Auf der VM lag ein verwaister X98-Socket,
entstanden durch genau so einen "xvfb-run -a"-Aufruf beim smoke-ui-Test, als
:99 belegt war. Er blockierte Predictalytics' reservierte Nummer, ohne dass ein
Prozess lief. Entfernt, und die Anleitung erklaert jetzt, wie man verwaiste
Sockets erkennt (ls /tmp/.X11-unix/ gegen pgrep -a Xvfb lesen) und aufraeumt.

Weiter ergaenzt:
- pkill nie ohne Displaynummer - "pkill Xvfb" erschlaegt die Sitzungen aller
  anderen Projekte.
- DISPLAY in jedem Skript setzen, sonst landet man auf :0, dem echten Desktop.
- Die Skriptvorlage hat jetzt einen Kopf mit PROJEKT/DISP/FENSTER; das ist
  alles, was sich je Projekt unterscheidet. Praktisch gegengetestet.
- Aufraeumabschnitt und Belegungsliste um Displays und Verzeichnisse erweitert.

Nebenbei aufgefallen: Das PolyTrader-Publish lag unter ~/pt-test statt
~/polytrader-test und verletzte damit die eigene Verzeichniskonvention.
Umbenannt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 20:49:28 +02:00

93 lines
5.2 KiB
XML

<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:PolyTrader.App.Avalonia.ViewModels"
x:Class="PolyTrader.App.Avalonia.Views.TerminalWindow">
<!--
Terminal- und Log-Ansicht.
Live-Tab: farbige Log-Zeilen, abschaltbarer Autoscroll, Level-Filter.
Log-Viewer-Tab: die JSONL-Tagesdateien, filterbar nach Datum, Level, CID und Volltext.
Die Live-Ausgabe ist ein virtualisiertes ItemsControl über eine begrenzte Zeilenliste
statt einer RichTextBox. Damit entfällt das Auto-Clear der WinForms-Fassung, das bei
Erreichen der RAM-Grenze den gesamten Verlauf verwarf: es werden nur noch die ältesten
Zeilen verdrängt, der sichtbare Verlauf bleibt erhalten.
-->
<DockPanel>
<TabControl>
<TabItem Header="Live">
<DockPanel>
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Name="btnAutoscroll" Content="Stop Autoscroll" />
<Button Name="btnClear" Content="Terminal leeren" />
<Button Name="btnCopyAll" Content="Alles kopieren" />
<TextBlock Text="Level:" VerticalAlignment="Center" />
<ComboBox Name="cbLogLevel" MinWidth="150" />
<TextBlock Name="lblLiveStatus" VerticalAlignment="Center" Foreground="{DynamicResource AppMutedTextBrush}" />
</StackPanel>
</Border>
<Border Background="#1E1E1E">
<ScrollViewer Name="logScroll">
<ScrollViewer.ContextMenu>
<ContextMenu>
<MenuItem Header="Kopieren" Click="OnContextMenuCopyClick" />
<MenuItem Header="Alles auswählen" Click="OnContextMenuSelectAllClick" />
</ContextMenu>
</ScrollViewer.ContextMenu>
<ItemsControl Name="logLines" Margin="8">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="vm:LogLine">
<SelectableTextBlock Text="{Binding Text}"
Foreground="{Binding Brush}"
FontFamily="Consolas,Menlo,DejaVu Sans Mono,monospace"
FontSize="12"
TextWrapping="Wrap" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Border>
</DockPanel>
</TabItem>
<TabItem Header="Log Viewer">
<DockPanel>
<Border Classes="toolbar" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="Datum:" VerticalAlignment="Center" />
<CalendarDatePicker Name="dtViewerDate" MinWidth="150" />
<TextBlock Text="Level:" VerticalAlignment="Center" />
<ComboBox Name="cbViewerLevel" MinWidth="130" />
<TextBlock Text="CID:" VerticalAlignment="Center" />
<TextBox Name="tbViewerCid" MinWidth="150" />
<TextBlock Text="Text:" VerticalAlignment="Center" />
<TextBox Name="tbViewerText" MinWidth="220" />
<Button Name="btnViewerLoad" Content="Laden" />
<TextBlock Name="lblViewerStatus" VerticalAlignment="Center" Foreground="{DynamicResource AppMutedTextBrush}" />
</StackPanel>
</Border>
<DataGrid Name="gridLogs" x:DataType="vm:LogViewerRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Zeit" Width="Auto" Binding="{Binding Time}" />
<DataGridTextColumn Header="Level" Width="Auto" Binding="{Binding Level}" />
<DataGridTextColumn Header="CID" Width="Auto" Binding="{Binding Cid}" />
<DataGridTextColumn Header="Nachricht" Width="*" MinWidth="180" Binding="{Binding Message}" />
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</TabItem>
</TabControl>
</DockPanel>
</UserControl>