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,120 @@
using JdeScoping.ConfigManager.Models;
namespace JdeScoping.ConfigManager.ViewModels.PipelineSteps;
/// <summary>
/// Destination type for the pipeline.
/// </summary>
public enum DestinationType
{
BulkImport,
BulkMerge
}
/// <summary>
/// View model for the destination step in a pipeline.
/// </summary>
public class DestinationStepViewModel : PipelineStepViewModelBase
{
private readonly PipelineDestination _model;
public DestinationStepViewModel(PipelineDestination model, Action onChanged) : base(onChanged)
{
_model = model ?? throw new ArgumentNullException(nameof(model));
}
public override PipelineStepType StepType => PipelineStepType.Destination;
public override string DisplayName => "Destination";
public override string Icon => "󰆼"; // mdi-database
public override string Summary => !string.IsNullOrEmpty(Table) ? $"→ {Table}" : "(no table)";
/// <summary>
/// Gets or sets the destination type (BulkImport or BulkMerge).
/// </summary>
public DestinationType Type
{
get => _model.Type?.Equals("BulkImport", StringComparison.OrdinalIgnoreCase) == true
? DestinationType.BulkImport
: DestinationType.BulkMerge;
set
{
var typeStr = value == DestinationType.BulkImport ? "BulkImport" : "BulkMerge";
if (_model.Type != typeStr)
{
_model.Type = typeStr;
OnPropertyChanged();
OnPropertyChanged(nameof(IsBulkMerge));
OnPropertyChanged(nameof(TypeDescription));
NotifyChanged();
}
}
}
/// <summary>
/// Gets whether the destination type is BulkMerge (shows match columns).
/// </summary>
public bool IsBulkMerge => Type == DestinationType.BulkMerge;
/// <summary>
/// Gets a description of the current type.
/// </summary>
public string TypeDescription => Type == DestinationType.BulkImport
? "Truncate table and bulk load all data"
: "Merge data using match columns (upsert)";
/// <summary>
/// Gets or sets the destination table name.
/// </summary>
public string Table
{
get => _model.Table;
set
{
if (_model.Table != value)
{
_model.Table = value ?? string.Empty;
OnPropertyChanged();
OnPropertyChanged(nameof(Summary));
NotifyChanged();
}
}
}
/// <summary>
/// Gets or sets the match columns as newline-separated text.
/// Only used for BulkMerge type.
/// </summary>
public string MatchColumnsText
{
get => string.Join("\n", _model.MatchColumns);
set
{
var columns = (value ?? string.Empty).Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (!_model.MatchColumns.SequenceEqual(columns))
{
_model.MatchColumns = columns;
OnPropertyChanged();
NotifyChanged();
}
}
}
/// <summary>
/// Gets or sets the columns to exclude from updates as newline-separated text.
/// Only used for BulkMerge type.
/// </summary>
public string ExcludeFromUpdateText
{
get => string.Join("\n", _model.ExcludeFromUpdate);
set
{
var columns = (value ?? string.Empty).Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (!_model.ExcludeFromUpdate.SequenceEqual(columns))
{
_model.ExcludeFromUpdate = columns;
OnPropertyChanged();
NotifyChanged();
}
}
}
}