mirror of
https://github.com/8damon/Blackbird-Platform
synced 2026-06-21 13:41:12 +00:00
356 lines
21 KiB
XML
356 lines
21 KiB
XML
<Window x:Class="BlackbirdOperator.MainWindow"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
mc:Ignorable="d"
|
|
Title="Blackbird Operator"
|
|
Width="1680"
|
|
Height="960"
|
|
MinWidth="1320"
|
|
MinHeight="760"
|
|
ResizeMode="CanResize"
|
|
Background="{StaticResource WinBgBrush}"
|
|
SnapsToDevicePixels="True"
|
|
UseLayoutRounding="True">
|
|
<Border Background="{StaticResource WinBgBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
SnapsToDevicePixels="True">
|
|
<DockPanel Background="{StaticResource WinBgBrush}" LastChildFill="True">
|
|
|
|
<!-- Top command bar -->
|
|
<Border DockPanel.Dock="Top"
|
|
Background="{StaticResource CommandBarBackgroundBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,0,0,1"
|
|
Padding="12,10"
|
|
SnapsToDevicePixels="True">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<StackPanel Orientation="Horizontal">
|
|
<TextBlock x:Name="AdapterSummaryText"
|
|
Foreground="{StaticResource WinMutedTextBrush}"
|
|
VerticalAlignment="Center" />
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Button x:Name="ConfigureNetworkButton"
|
|
Content="Configure Network"
|
|
Click="ConfigureNetworkButton_Click" />
|
|
<Button x:Name="ResetConfigButton"
|
|
Content="Reset Config"
|
|
Click="ResetConfigButton_Click" />
|
|
<TextBox x:Name="ManualAddressBox"
|
|
Width="200"
|
|
Height="26"
|
|
Margin="0,0,8,0"
|
|
VerticalContentAlignment="Center"
|
|
ToolTip="Manual VM address or hostname" />
|
|
<Button x:Name="ConnectAddressButton"
|
|
Content="Connect Address"
|
|
Click="ConnectAddressButton_Click" />
|
|
<Button x:Name="RefreshNodesButton"
|
|
Content="Refresh Nodes"
|
|
Click="RefreshNodesButton_Click" />
|
|
<Button x:Name="ConnectNodeButton"
|
|
Content="Connect"
|
|
Click="ConnectNodeButton_Click" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Three-column body: node list | control center | node detail -->
|
|
<Grid Margin="12">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="300" />
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="300" />
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- LEFT: Node list -->
|
|
<Border Grid.Column="0"
|
|
Background="{StaticResource WinPanelBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
Margin="0,0,10,0"
|
|
SnapsToDevicePixels="True">
|
|
<DockPanel>
|
|
<Border DockPanel.Dock="Top"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,0,0,1"
|
|
Padding="10,8"
|
|
SnapsToDevicePixels="True">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock Text="Nodes" FontWeight="SemiBold" />
|
|
<TextBlock Grid.Column="1"
|
|
x:Name="NodeCountText"
|
|
Foreground="{StaticResource WinMutedTextBrush}" />
|
|
</Grid>
|
|
</Border>
|
|
<DataGrid x:Name="NodesGrid"
|
|
ItemsSource="{Binding Nodes}"
|
|
AutoGenerateColumns="False"
|
|
HeadersVisibility="Column"
|
|
SelectionMode="Single"
|
|
SelectionUnit="FullRow"
|
|
CanUserAddRows="False"
|
|
CanUserDeleteRows="False"
|
|
CanUserResizeRows="False"
|
|
IsReadOnly="True"
|
|
SelectionChanged="NodesGrid_SelectionChanged"
|
|
MouseDoubleClick="NodesGrid_MouseDoubleClick">
|
|
<DataGrid.Columns>
|
|
<DataGridTextColumn Header="Node" Binding="{Binding DisplayName}" Width="*" />
|
|
<DataGridTextColumn Header="Addr" Binding="{Binding Address}" Width="*" />
|
|
<DataGridTextColumn Header="State" Binding="{Binding StatusSummary}" Width="*" />
|
|
<DataGridTextColumn Header="Driver" Binding="{Binding DriverStatus}" Width="*" />
|
|
</DataGrid.Columns>
|
|
</DataGrid>
|
|
</DockPanel>
|
|
</Border>
|
|
|
|
<!-- MIDDLE: Control center -->
|
|
<Border Grid.Column="1"
|
|
Background="{StaticResource WinPanelBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
Margin="0,0,10,0"
|
|
SnapsToDevicePixels="True">
|
|
<DockPanel>
|
|
<Border DockPanel.Dock="Top"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,0,0,1"
|
|
Padding="10,8"
|
|
SnapsToDevicePixels="True">
|
|
<TextBlock Text="Control Center" FontWeight="SemiBold" />
|
|
</Border>
|
|
|
|
<!-- Command input bar -->
|
|
<Border DockPanel.Dock="Top"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,0,0,1"
|
|
Padding="10,8">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<Button Grid.Column="0"
|
|
Content="Ping"
|
|
Margin="0,0,6,0"
|
|
Tag="PING"
|
|
Click="QuickCommandButton_Click" />
|
|
<Button Grid.Column="1"
|
|
Content="Status"
|
|
Margin="0,0,6,0"
|
|
Tag="STATUS"
|
|
Click="QuickCommandButton_Click" />
|
|
<Button Grid.Column="2"
|
|
x:Name="SendFileButton"
|
|
Content="Send File"
|
|
Margin="0,0,12,0"
|
|
Click="SendFileButton_Click" />
|
|
<TextBox Grid.Column="4"
|
|
x:Name="CommandInputBox"
|
|
Height="26"
|
|
Margin="0,0,6,0"
|
|
VerticalContentAlignment="Center"
|
|
ToolTip="Command (e.g. PING, STATUS) — Enter to send"
|
|
KeyDown="CommandInputBox_KeyDown" />
|
|
<Button Grid.Column="5"
|
|
x:Name="SendCommandButton"
|
|
Content="Send"
|
|
Click="SendCommandButton_Click" />
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Output area + status -->
|
|
<Border DockPanel.Dock="Bottom"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,1,0,0"
|
|
Padding="10,8">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*" />
|
|
<ColumnDefinition Width="Auto" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock x:Name="OperatorStatusText"
|
|
Foreground="{StaticResource WinMutedTextBrush}"
|
|
TextWrapping="NoWrap"
|
|
TextTrimming="CharacterEllipsis"
|
|
VerticalAlignment="Center"
|
|
Text="Waiting for discovery traffic." />
|
|
<Button Grid.Column="1"
|
|
Content="Clear"
|
|
Margin="8,0,0,0"
|
|
Click="ClearCommandOutputButton_Click" />
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- File drop zone -->
|
|
<Border x:Name="FileDropZone"
|
|
DockPanel.Dock="Bottom"
|
|
Height="52"
|
|
AllowDrop="True"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,1,0,0"
|
|
SnapsToDevicePixels="True"
|
|
DragEnter="FileDropZone_DragEnter"
|
|
DragLeave="FileDropZone_DragLeave"
|
|
DragOver="FileDropZone_DragOver"
|
|
Drop="FileDropZone_Drop">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock Grid.Column="0"
|
|
Text="↓"
|
|
FontSize="16"
|
|
VerticalAlignment="Center"
|
|
Margin="12,0,8,0"
|
|
Foreground="{StaticResource WinMutedTextBrush}" />
|
|
<StackPanel Grid.Column="1"
|
|
VerticalAlignment="Center">
|
|
<TextBlock x:Name="FileDropPrimaryText"
|
|
Text="Drop file to send to node"
|
|
FontSize="12"
|
|
Foreground="{StaticResource WinMutedTextBrush}" />
|
|
<TextBlock x:Name="FileDropSecondaryText"
|
|
Text="File is uploaded and analyzed on the remote node"
|
|
FontSize="10"
|
|
Margin="0,2,0,0"
|
|
Foreground="{StaticResource WinMutedTextBrush}" />
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<TextBox x:Name="CommandOutputBox"
|
|
IsReadOnly="True"
|
|
TextWrapping="Wrap"
|
|
VerticalScrollBarVisibility="Auto"
|
|
AcceptsReturn="True"
|
|
FontFamily="Consolas"
|
|
FontSize="12"
|
|
Background="#FF0A0A0A"
|
|
Foreground="#FFCCCCCC"
|
|
BorderThickness="0"
|
|
Padding="12" />
|
|
</DockPanel>
|
|
</Border>
|
|
|
|
<!-- RIGHT: Node detail -->
|
|
<Border Grid.Column="2"
|
|
Background="{StaticResource WinPanelBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
SnapsToDevicePixels="True">
|
|
<DockPanel>
|
|
<Border DockPanel.Dock="Top"
|
|
Background="{StaticResource WinHeaderBrush}"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="0,0,0,1"
|
|
Padding="10,8"
|
|
SnapsToDevicePixels="True">
|
|
<TextBlock Text="Node Detail" FontWeight="SemiBold" />
|
|
</Border>
|
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
|
<StackPanel Margin="10">
|
|
<Border Background="#FF111111"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
Padding="10"
|
|
Margin="0,0,0,10">
|
|
<StackPanel>
|
|
<TextBlock x:Name="DetailTitleText"
|
|
FontSize="14"
|
|
FontWeight="SemiBold"
|
|
Text="No node selected" />
|
|
<TextBlock x:Name="DetailSubtitleText"
|
|
Margin="0,5,0,0"
|
|
Foreground="{StaticResource WinMutedTextBrush}"
|
|
TextWrapping="Wrap"
|
|
Text="Select a node to query live status." />
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<UniformGrid Columns="2" Margin="0,0,0,10">
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,6,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="Address" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailAddressText" Margin="0,4,0,0" TextWrapping="Wrap" />
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,0,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="Status Port" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailPortText" Margin="0,4,0,0" />
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,6,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="OS" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailOsText" Margin="0,4,0,0" TextWrapping="Wrap" FontSize="11" />
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,0,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="Kernel" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailKernelText" Margin="0,4,0,0" FontSize="11" />
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,6,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="Controller" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailControllerText" Margin="0,4,0,0" FontSize="11" />
|
|
</StackPanel>
|
|
</Border>
|
|
<Border Background="#FF101010" BorderBrush="{StaticResource WinBorderBrush}" BorderThickness="1" Margin="0,0,0,6" Padding="8">
|
|
<StackPanel>
|
|
<TextBlock Text="Observed" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailLastSeenText" Margin="0,4,0,0" FontSize="11" />
|
|
</StackPanel>
|
|
</Border>
|
|
</UniformGrid>
|
|
|
|
<Border Background="#FF101010"
|
|
BorderBrush="{StaticResource WinBorderBrush}"
|
|
BorderThickness="1"
|
|
Padding="8"
|
|
Margin="0,0,0,10">
|
|
<StackPanel>
|
|
<TextBlock Text="Live Flags" Foreground="{StaticResource WinMutedTextBrush}" FontSize="10" />
|
|
<TextBlock x:Name="DetailFlagsText"
|
|
Margin="0,6,0,0"
|
|
TextWrapping="Wrap"
|
|
FontSize="11" />
|
|
</StackPanel>
|
|
</Border>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
</DockPanel>
|
|
</Border>
|
|
</Grid>
|
|
</DockPanel>
|
|
</Border>
|
|
</Window>
|
|
|
|
|
|
|