feat: add startup config validation and document ConfigManager pipeline editor

Add ConfigurationValidationRunner with IConfigurationValidator interface for
validating required settings at startup. Includes SecureStore and LDAP validators.
Expand ConfigManager with pipeline editing UI, dialogs, and step editors.
Update documentation with config validation guidance.
This commit is contained in:
Joseph Doherty
2026-01-21 17:47:15 -05:00
parent ceb63bfefb
commit e5fe2f06e9
88 changed files with 4995 additions and 201 deletions
@@ -0,0 +1,106 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Media;
using JdeScoping.ConfigManager.ViewModels.Forms;
using JdeScoping.ConfigManager.ViewModels.PipelineSteps;
namespace JdeScoping.ConfigManager.Views.Controls;
public partial class PipelineStepCard : UserControl
{
public static readonly StyledProperty<string> StepColorProperty =
AvaloniaProperty.Register<PipelineStepCard, string>(nameof(StepColor), "#3B82F6");
public PipelineStepCard()
{
InitializeComponent();
PointerPressed += OnPointerPressed;
PropertyChanged += OnPropertyChangedHandler;
DataContextChanged += OnDataContextChanged;
}
/// <summary>
/// Gets or sets the step color for the icon background.
/// </summary>
public string StepColor
{
get => GetValue(StepColorProperty);
set => SetValue(StepColorProperty, value);
}
private void OnPropertyChangedHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property == StepColorProperty)
{
UpdateIconColor();
}
}
private void OnDataContextChanged(object? sender, EventArgs e)
{
UpdateIconColor();
UpdateSelectionState();
if (DataContext is PipelineStepViewModelBase vm)
{
vm.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(PipelineStepViewModelBase.IsSelected))
{
UpdateSelectionState();
}
};
}
}
private void UpdateIconColor()
{
var iconBg = this.FindControl<Border>("IconBackground");
if (iconBg != null && !string.IsNullOrEmpty(StepColor))
{
if (Color.TryParse(StepColor, out var color))
{
iconBg.Background = new SolidColorBrush(color);
}
}
}
private void UpdateSelectionState()
{
var cardBorder = this.FindControl<Border>("CardBorder");
if (cardBorder != null && DataContext is PipelineStepViewModelBase vm)
{
if (vm.IsSelected)
{
cardBorder.BorderBrush = new SolidColorBrush(Color.Parse("#3B82F6"));
cardBorder.Background = new SolidColorBrush(Color.Parse("#1E2A3A"));
}
else
{
cardBorder.BorderBrush = new SolidColorBrush(Color.Parse("#3D4550"));
cardBorder.Background = new SolidColorBrush(Color.Parse("#1A1F26"));
}
}
}
private void OnPointerPressed(object? sender, PointerPressedEventArgs e)
{
// Find the PipelineEditorViewModel from the visual tree
var parent = this.Parent;
while (parent != null)
{
if (parent is UserControl uc && uc.DataContext is PipelineEditorViewModel editorVm)
{
if (DataContext is PipelineStepViewModelBase stepVm)
{
editorVm.SelectedStep = stepVm;
}
break;
}
parent = parent.Parent;
}
e.Handled = true;
}
}