feat(configmanager): add RegexEditorView Avalonia UI

Implements editor with:
- Column name input
- Mode toggle (Find & Replace / Match & Extract)
- Pattern and Replacement inputs
- Case insensitive checkbox
- NonMatchBehavior dropdown
- Live test/preview section with result display
- Pattern examples help box
This commit is contained in:
Joseph Doherty
2026-01-22 07:21:11 -05:00
parent 6095f3dca0
commit 4954368284
3 changed files with 195 additions and 0 deletions
@@ -423,6 +423,10 @@ public class RegexTransformerViewModel : TransformerStepViewModelBase
}
}
/// <summary>Gets the available non-match behavior options for binding.</summary>
public static IReadOnlyList<NonMatchBehavior> NonMatchBehaviorOptions { get; } =
[NonMatchBehavior.KeepOriginal, NonMatchBehavior.ReturnNull, NonMatchBehavior.ReturnEmpty];
// Test feature properties
public string TestInput
{
@@ -0,0 +1,180 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:steps="using:JdeScoping.ConfigManager.ViewModels.PipelineSteps"
x:Class="JdeScoping.ConfigManager.Views.Editors.RegexEditorView"
x:DataType="steps:RegexTransformerViewModel">
<StackPanel Spacing="16">
<!-- Header -->
<StackPanel>
<TextBlock Text="Regex Transformer"
Foreground="#E6EDF5" FontSize="14" FontWeight="SemiBold"/>
<TextBlock Text="Transform column values using regular expressions"
Foreground="#5C6A7A" FontSize="11"/>
</StackPanel>
<!-- Column Name -->
<StackPanel Spacing="4">
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="Column"
Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<TextBlock Text="*" Foreground="#FF6B6B" FontSize="12"/>
</StackPanel>
<TextBox Text="{Binding ColumnName}"
Background="#232A35" Foreground="#E6EDF5"
BorderBrush="#3D4550" Height="36"
FontFamily="JetBrains Mono"
Watermark="BatchID"/>
<TextBlock Text="Column to apply the regex transformation"
Foreground="#5C6A7A" FontSize="11"/>
</StackPanel>
<!-- Mode Selection -->
<StackPanel Spacing="4">
<TextBlock Text="Mode" Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<StackPanel Orientation="Horizontal" Spacing="12">
<RadioButton GroupName="RegexMode"
IsChecked="{Binding IsFindReplaceMode}"
Foreground="#E6EDF5">
<TextBlock Text="Find &amp; Replace" FontSize="12"/>
</RadioButton>
<RadioButton GroupName="RegexMode"
IsChecked="{Binding IsMatchExtractMode}"
Foreground="#E6EDF5">
<TextBlock Text="Match &amp; Extract" FontSize="12"/>
</RadioButton>
</StackPanel>
</StackPanel>
<!-- Pattern -->
<StackPanel Spacing="4">
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="Pattern"
Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<TextBlock Text="*" Foreground="#FF6B6B" FontSize="12"/>
</StackPanel>
<TextBox Text="{Binding Pattern}"
Background="#232A35" Foreground="#E6EDF5"
BorderBrush="#3D4550" Height="36"
FontFamily="JetBrains Mono"
Watermark="^IIS_"/>
<TextBlock Text="{Binding PatternHelpText}"
Foreground="#5C6A7A" FontSize="11"/>
</StackPanel>
<!-- Replacement (only visible in Find & Replace mode) -->
<StackPanel Spacing="4" IsVisible="{Binding IsFindReplaceMode}">
<TextBlock Text="Replacement"
Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<TextBox Text="{Binding Replacement}"
Background="#232A35" Foreground="#E6EDF5"
BorderBrush="#3D4550" Height="36"
FontFamily="JetBrains Mono"
Watermark="(empty to remove)"/>
<TextBlock Text="Text to replace matches with (use $1, $2 for capture groups)"
Foreground="#5C6A7A" FontSize="11"/>
</StackPanel>
<!-- Options Row -->
<StackPanel Spacing="8">
<TextBlock Text="Options" Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<Grid ColumnDefinitions="*,*" RowDefinitions="Auto">
<!-- Case Insensitive Toggle -->
<CheckBox Grid.Column="0"
IsChecked="{Binding IgnoreCase}"
Foreground="#E6EDF5" FontSize="12">
<TextBlock Text="Case Insensitive" FontSize="12"/>
</CheckBox>
<!-- Non-Match Behavior -->
<StackPanel Grid.Column="1" Spacing="4">
<TextBlock Text="If No Match"
Foreground="#5C6A7A" FontSize="11"/>
<ComboBox SelectedItem="{Binding NonMatchBehavior}"
ItemsSource="{Binding NonMatchBehaviorOptions}"
Background="#232A35" Foreground="#E6EDF5"
BorderBrush="#3D4550" Height="32"
FontSize="11" MinWidth="140"/>
</StackPanel>
</Grid>
</StackPanel>
<!-- Test/Preview Section -->
<Border Background="#151920" BorderBrush="#2D3540" BorderThickness="1"
CornerRadius="4" Padding="12" Margin="0,8,0,0">
<StackPanel Spacing="12">
<TextBlock Text="Test Pattern"
Foreground="#9BA8B8" FontSize="12" FontWeight="Medium"/>
<!-- Test Input Row -->
<Grid ColumnDefinitions="*,8,Auto">
<TextBox Grid.Column="0"
Text="{Binding TestInput}"
Background="#232A35" Foreground="#E6EDF5"
BorderBrush="#3D4550" Height="36"
FontFamily="JetBrains Mono"
Watermark="IIS_12345"/>
<Button Grid.Column="2"
Content="Test"
Background="#3B82F6" Foreground="#FFFFFF"
BorderThickness="0" Height="36"
Padding="16,0"
Command="{Binding TestPatternCommand}"/>
</Grid>
<!-- Result Display -->
<Border Background="#0D0F12" BorderBrush="#2D3540" BorderThickness="1"
CornerRadius="4" Padding="10" MinHeight="44"
IsVisible="{Binding HasTestResult}">
<Grid ColumnDefinitions="Auto,8,*">
<!-- Status Icon -->
<Border Grid.Column="0"
Width="24" Height="24" CornerRadius="12"
Background="{Binding TestResultBackground}"
VerticalAlignment="Center">
<TextBlock Text="{Binding TestResultIcon}"
Foreground="#FFFFFF"
FontSize="12" FontWeight="Bold"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
<!-- Result Text -->
<StackPanel Grid.Column="2" Spacing="2" VerticalAlignment="Center">
<TextBlock Text="{Binding TestResultLabel}"
Foreground="#5C6A7A" FontSize="10"/>
<TextBlock Text="{Binding TestResultValue}"
Foreground="#E6EDF5" FontSize="12"
FontFamily="JetBrains Mono"/>
</StackPanel>
</Grid>
</Border>
<!-- Error Display -->
<Border Background="#2D1F1F" BorderBrush="#5C2626" BorderThickness="1"
CornerRadius="4" Padding="10"
IsVisible="{Binding HasTestError}">
<StackPanel Spacing="2">
<TextBlock Text="Invalid Pattern"
Foreground="#FF6B6B" FontSize="11" FontWeight="Medium"/>
<TextBlock Text="{Binding TestErrorMessage}"
Foreground="#CC8888" FontSize="11"
TextWrapping="Wrap"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
<!-- Help Info -->
<Border Background="#151920" BorderBrush="#2D3540" BorderThickness="1"
CornerRadius="4" Padding="12" Margin="0,4,0,0">
<StackPanel Spacing="4">
<TextBlock Text="Pattern Examples" Foreground="#9BA8B8" FontSize="11" FontWeight="Medium"/>
<TextBlock Text=" ^IIS_ Remove 'IIS_' prefix" Foreground="#5C6A7A" FontSize="10" FontFamily="JetBrains Mono"/>
<TextBlock Text=" _SUFFIX$ Remove '_SUFFIX' at end" Foreground="#5C6A7A" FontSize="10" FontFamily="JetBrains Mono"/>
<TextBlock Text=" (\d+) Extract first number" Foreground="#5C6A7A" FontSize="10" FontFamily="JetBrains Mono"/>
</StackPanel>
</Border>
</StackPanel>
</UserControl>
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace JdeScoping.ConfigManager.Views.Editors;
public partial class RegexEditorView : UserControl
{
public RegexEditorView()
{
InitializeComponent();
}
}