feat: Implement container logs functionality in InstancesViewModel
- Added properties for managing container logs, including log entries, service filters, and auto-refresh options. - Introduced commands for refreshing logs, toggling auto-refresh, and closing the logs panel. - Implemented log fetching logic with error handling and status messages. - Integrated log display in the InstancesView with a dedicated logs panel. feat: Enhance navigation to Instances page with auto-selection - Added method to navigate to the Instances page and auto-select an instance based on abbreviation. feat: Update SettingsViewModel to load and save Bitwarden configuration - Integrated Bitwarden configuration loading from IOptions and saving to appsettings.json. - Added properties for Bitwarden instance project ID and connection status. - Updated UI to reflect Bitwarden settings and connection status. feat: Add advanced options for instance creation - Introduced a new expander in CreateInstanceView for advanced options, including purging stale volumes. feat: Improve InstanceDetailsWindow with pending setup banner - Added a banner to indicate pending setup for Xibo OAuth credentials, with editable fields for client ID and secret. fix: Update appsettings.json to include Bitwarden configuration structure - Added Bitwarden section to appsettings.json for storing configuration values. chore: Update Docker Compose template with health checks - Added health check configuration for web service in template.yml to ensure service availability. refactor: Drop AppSettings table from database - Removed AppSettings table and related migration files as part of database cleanup. feat: Create ServiceLogEntry DTO for log management - Added ServiceLogEntry class to represent individual log entries from Docker services.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:OTSSignsOrchestrator.Desktop.ViewModels"
|
||||
xmlns:dto="using:OTSSignsOrchestrator.Core.Models.DTOs"
|
||||
x:Class="OTSSignsOrchestrator.Desktop.Views.InstancesView"
|
||||
x:DataType="vm:InstancesViewModel">
|
||||
|
||||
@@ -37,45 +38,118 @@
|
||||
<TextBlock DockPanel.Dock="Bottom" Text="{Binding StatusMessage}" Classes="status"
|
||||
Margin="0,10,0,0" />
|
||||
|
||||
<!-- Services panel (shown when inspecting) -->
|
||||
<Border DockPanel.Dock="Right" Width="360"
|
||||
IsVisible="{Binding SelectedServices.Count}"
|
||||
Classes="card" Margin="16,0,0,0">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Stack Services" Classes="sectionTitle"
|
||||
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,10" />
|
||||
<ItemsControl ItemsSource="{Binding SelectedServices}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="#232336" CornerRadius="6" Padding="12,10" Margin="0,3"
|
||||
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="1">
|
||||
<StackPanel Spacing="3">
|
||||
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="13" />
|
||||
<TextBlock Text="{Binding Image}" FontSize="11"
|
||||
Foreground="{StaticResource TextMutedBrush}" />
|
||||
<TextBlock Text="{Binding Replicas, StringFormat='Replicas: {0}'}"
|
||||
FontSize="11" Foreground="{StaticResource TextSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<!-- Main content: split into upper (grid + services) and lower (logs) -->
|
||||
<Grid RowDefinitions="*,Auto,Auto">
|
||||
|
||||
<!-- Instance list -->
|
||||
<DataGrid ItemsSource="{Binding Instances}"
|
||||
SelectedItem="{Binding SelectedInstance}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Stack" Binding="{Binding StackName}" Width="150" />
|
||||
<DataGridTextColumn Header="Abbrev" Binding="{Binding CustomerAbbrev}" Width="70" />
|
||||
<DataGridTextColumn Header="Services" Binding="{Binding ServiceCount}" Width="70" />
|
||||
<DataGridTextColumn Header="Host" Binding="{Binding HostLabel}" Width="150" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
<!-- Upper area: instance list + services side panel -->
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto">
|
||||
|
||||
<!-- Instance list -->
|
||||
<DataGrid Grid.Column="0"
|
||||
ItemsSource="{Binding Instances}"
|
||||
SelectedItem="{Binding SelectedInstance}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
CanUserResizeColumns="True">
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Stack" Binding="{Binding StackName}" Width="150" />
|
||||
<DataGridTextColumn Header="Abbrev" Binding="{Binding CustomerAbbrev}" Width="70" />
|
||||
<DataGridTextColumn Header="Services" Binding="{Binding ServiceCount}" Width="70" />
|
||||
<DataGridTextColumn Header="Host" Binding="{Binding HostLabel}" Width="150" />
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Services panel (shown when inspecting) -->
|
||||
<Border Grid.Column="1" Width="360"
|
||||
IsVisible="{Binding SelectedServices.Count}"
|
||||
Classes="card" Margin="16,0,0,0">
|
||||
<StackPanel Spacing="4">
|
||||
<TextBlock Text="Stack Services" Classes="sectionTitle"
|
||||
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,10" />
|
||||
<ItemsControl ItemsSource="{Binding SelectedServices}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Background="#232336" CornerRadius="6" Padding="12,10" Margin="0,3"
|
||||
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="1">
|
||||
<StackPanel Spacing="3">
|
||||
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" FontSize="13" />
|
||||
<TextBlock Text="{Binding Image}" FontSize="11"
|
||||
Foreground="{StaticResource TextMutedBrush}" />
|
||||
<TextBlock Text="{Binding Replicas, StringFormat='Replicas: {0}'}"
|
||||
FontSize="11" Foreground="{StaticResource TextSecondaryBrush}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Grid splitter between instances and logs -->
|
||||
<GridSplitter Grid.Row="1" Height="6" HorizontalAlignment="Stretch"
|
||||
IsVisible="{Binding IsLogsPanelVisible}"
|
||||
Background="Transparent" />
|
||||
|
||||
<!-- Container Logs Panel -->
|
||||
<Border Grid.Row="2" Classes="card" Margin="0,4,0,0"
|
||||
IsVisible="{Binding IsLogsPanelVisible}"
|
||||
MinHeight="180" MaxHeight="400">
|
||||
<DockPanel>
|
||||
<!-- Logs toolbar -->
|
||||
<Grid DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto" Margin="0,0,0,8">
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="8"
|
||||
VerticalAlignment="Center">
|
||||
<TextBlock Text="Container Logs" Classes="sectionTitle"
|
||||
Foreground="{StaticResource AccentBrush}" />
|
||||
<ComboBox ItemsSource="{Binding LogServiceFilter}"
|
||||
SelectedItem="{Binding SelectedLogService}"
|
||||
MinWidth="200" FontSize="12"
|
||||
ToolTip.Tip="Filter logs by service" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Grid.Column="1" Text="{Binding LogsStatusMessage}"
|
||||
FontSize="11" Foreground="{StaticResource TextMutedBrush}"
|
||||
VerticalAlignment="Center" HorizontalAlignment="Center" />
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6"
|
||||
VerticalAlignment="Center">
|
||||
<Button Content="Refresh" Command="{Binding RefreshLogsCommand}"
|
||||
FontSize="11" Padding="8,4"
|
||||
ToolTip.Tip="Fetch latest logs" />
|
||||
<ToggleButton IsChecked="{Binding IsLogsAutoRefresh}"
|
||||
Content="Auto"
|
||||
FontSize="11" Padding="8,4"
|
||||
ToolTip.Tip="Toggle auto-refresh (every 5 seconds)"
|
||||
Command="{Binding ToggleLogsAutoRefreshCommand}" />
|
||||
<Button Content="✕" Command="{Binding CloseLogsPanelCommand}"
|
||||
FontSize="11" Padding="6,4"
|
||||
ToolTip.Tip="Close logs panel" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<!-- Log entries list -->
|
||||
<Border Background="#1a1a2e" CornerRadius="4" Padding="8"
|
||||
BorderBrush="{StaticResource BorderSubtleBrush}" BorderThickness="1">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Auto">
|
||||
<ItemsControl ItemsSource="{Binding LogEntries}"
|
||||
x:DataType="vm:InstancesViewModel">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="dto:ServiceLogEntry">
|
||||
<TextBlock Text="{Binding DisplayLine}"
|
||||
FontFamily="Cascadia Mono,Consolas,Menlo,monospace"
|
||||
FontSize="11" Padding="0,1"
|
||||
TextWrapping="NoWrap"
|
||||
Foreground="#cccccc" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
|
||||
Reference in New Issue
Block a user