feat(configmanager): add DiffPreviewDialog

Add DiffPreviewDialog and DiffPreviewDialogViewModel to display a diff
preview of configuration changes before saving. The dialog shows line
numbers, insertions (green), deletions (red), and unchanged lines with
a dark theme matching the ConfigManager design spec.
This commit is contained in:
Joseph Doherty
2026-01-19 19:52:38 -05:00
parent 7dd4c46cb7
commit 46e94539cd
6 changed files with 407 additions and 0 deletions
@@ -0,0 +1,73 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:JdeScoping.ConfigManager.ViewModels.Dialogs"
x:Class="JdeScoping.ConfigManager.Views.Dialogs.DiffPreviewDialog"
x:DataType="vm:DiffPreviewDialogViewModel"
Title="Preview Changes"
Width="800" Height="600"
MinWidth="600" MinHeight="400"
Background="#151920"
WindowStartupLocation="CenterOwner">
<DockPanel>
<!-- Header -->
<Border DockPanel.Dock="Top" Background="#1C2128" Padding="24,16"
BorderBrush="#2D3540" BorderThickness="0,0,0,1">
<TextBlock Text="Preview Changes"
Foreground="#E6EDF5" FontSize="18" FontWeight="SemiBold"/>
</Border>
<!-- Footer -->
<Border DockPanel.Dock="Bottom" Background="#1C2128" Padding="24,16"
BorderBrush="#2D3540" BorderThickness="0,1,0,0">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
<TextBlock Foreground="#9BA8B8" FontFamily="JetBrains Mono" FontSize="12">
<Run Text="{Binding Insertions}"/> insertions, <Run Text="{Binding Deletions}"/> deletions
</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="8">
<Button Content="Cancel" Command="{Binding CancelCommand}"
Background="Transparent" BorderBrush="#3D4550"
Foreground="#9BA8B8" Padding="16,8"/>
<Button Content="Save Changes" Command="{Binding SaveCommand}"
Background="#5C9AFF" Foreground="#0D0F12"
Padding="16,8" FontWeight="Medium"/>
</StackPanel>
</Grid>
</Border>
<!-- Diff Content -->
<ScrollViewer Background="#0D0F12" Padding="0">
<ItemsControl ItemsSource="{Binding Lines}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Background}"
BorderBrush="{Binding BorderColor}"
BorderThickness="3,0,0,0"
Padding="0,2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding OldLineNumber}"
Foreground="#5C6A7A" FontFamily="JetBrains Mono" FontSize="12"
HorizontalAlignment="Right" Padding="0,0,8,0"/>
<TextBlock Grid.Column="1" Text="{Binding NewLineNumber}"
Foreground="#5C6A7A" FontFamily="JetBrains Mono" FontSize="12"
HorizontalAlignment="Right" Padding="0,0,8,0"/>
<Border Grid.Column="1" Width="1" Background="#2D3540" HorizontalAlignment="Right"/>
<TextBlock Grid.Column="2" Text="{Binding Text}"
Foreground="#E6EDF5" FontFamily="JetBrains Mono" FontSize="12"
Padding="12,0,0,0"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Window>
@@ -0,0 +1,18 @@
using Avalonia.Controls;
using JdeScoping.ConfigManager.ViewModels.Dialogs;
namespace JdeScoping.ConfigManager.Views.Dialogs;
public partial class DiffPreviewDialog : Window
{
public DiffPreviewDialog()
{
InitializeComponent();
}
public DiffPreviewDialog(DiffPreviewDialogViewModel viewModel) : this()
{
DataContext = viewModel;
viewModel.RequestClose = Close;
}
}
@@ -0,0 +1,69 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:JdeScoping.ConfigManager.ViewModels.Dialogs"
x:Class="JdeScoping.ConfigManager.Views.Dialogs.ValidationResultsDialog"
x:DataType="vm:ValidationResultsDialogViewModel"
Title="Validation Results"
Width="600" Height="500"
MinWidth="400" MinHeight="300"
Background="#151920"
WindowStartupLocation="CenterOwner">
<DockPanel>
<!-- Header -->
<Border DockPanel.Dock="Top" Background="#1C2128" Padding="24,16"
BorderBrush="#2D3540" BorderThickness="0,0,0,1">
<StackPanel>
<TextBlock Text="Validation Results"
Foreground="#E6EDF5" FontSize="18" FontWeight="SemiBold"/>
<StackPanel Orientation="Horizontal" Margin="0,8,0,0" Spacing="16">
<TextBlock Foreground="#FF6B6B" FontSize="12">
<Run Text="{Binding ErrorCount}"/> errors
</TextBlock>
<TextBlock Foreground="#FFB84D" FontSize="12">
<Run Text="{Binding WarningCount}"/> warnings
</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<!-- Footer -->
<Border DockPanel.Dock="Bottom" Background="#1C2128" Padding="24,16"
BorderBrush="#2D3540" BorderThickness="0,1,0,0">
<Button Content="Close" Command="{Binding CloseCommand}"
HorizontalAlignment="Right"
Background="#5C9AFF" Foreground="#0D0F12"
Padding="16,8" FontWeight="Medium"/>
</Border>
<!-- Content -->
<ScrollViewer Background="#0D0F12" Padding="16">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Background}"
BorderBrush="{Binding BorderColor}"
BorderThickness="3,0,0,0"
Margin="0,0,0,8"
Padding="12">
<StackPanel>
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBlock Text="{Binding Icon}"
Foreground="{Binding IconColor}"
FontSize="14"/>
<TextBlock Text="{Binding Source}"
Foreground="#5C6A7A"
FontFamily="JetBrains Mono" FontSize="11"/>
</StackPanel>
<TextBlock Text="{Binding Message}"
Foreground="#E6EDF5"
TextWrapping="Wrap"
Margin="22,4,0,0"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Window>
@@ -0,0 +1,28 @@
using Avalonia.Controls;
using JdeScoping.ConfigManager.ViewModels.Dialogs;
namespace JdeScoping.ConfigManager.Views.Dialogs;
/// <summary>
/// Dialog window for displaying validation results.
/// </summary>
public partial class ValidationResultsDialog : Window
{
/// <summary>
/// Initializes a new instance of the <see cref="ValidationResultsDialog"/> class.
/// </summary>
public ValidationResultsDialog()
{
InitializeComponent();
}
/// <summary>
/// Initializes a new instance of the <see cref="ValidationResultsDialog"/> class with a view model.
/// </summary>
/// <param name="viewModel">The view model containing validation results.</param>
public ValidationResultsDialog(ValidationResultsDialogViewModel viewModel) : this()
{
DataContext = viewModel;
viewModel.RequestClose = Close;
}
}