feat(configmanager): add DataSyncFormViewModel
Add form ViewModel that wraps DataSyncSection model for two-way binding with change tracking in the ConfigManager UI.
This commit is contained in:
@@ -0,0 +1,155 @@
|
|||||||
|
using JdeScoping.ConfigManager.Models;
|
||||||
|
|
||||||
|
namespace JdeScoping.ConfigManager.ViewModels.Forms;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ViewModel for editing DataSync configuration section.
|
||||||
|
/// </summary>
|
||||||
|
public class DataSyncFormViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
private readonly DataSyncSection _model;
|
||||||
|
private readonly Action _onChanged;
|
||||||
|
|
||||||
|
public DataSyncFormViewModel(DataSyncSection model, Action onChanged)
|
||||||
|
{
|
||||||
|
_model = model ?? throw new ArgumentNullException(nameof(model));
|
||||||
|
_onChanged = onChanged ?? throw new ArgumentNullException(nameof(onChanged));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether data synchronization is enabled.
|
||||||
|
/// </summary>
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get => _model.Enabled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.Enabled != value)
|
||||||
|
{
|
||||||
|
_model.Enabled = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the check interval in minutes.
|
||||||
|
/// </summary>
|
||||||
|
public int CheckIntervalMinutes
|
||||||
|
{
|
||||||
|
get => (int)_model.CheckInterval.TotalMinutes;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var newValue = TimeSpan.FromMinutes(value);
|
||||||
|
if (_model.CheckInterval != newValue)
|
||||||
|
{
|
||||||
|
_model.CheckInterval = newValue;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum degree of parallelism.
|
||||||
|
/// </summary>
|
||||||
|
public int MaxDegreeOfParallelism
|
||||||
|
{
|
||||||
|
get => _model.MaxDegreeOfParallelism;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.MaxDegreeOfParallelism != value)
|
||||||
|
{
|
||||||
|
_model.MaxDegreeOfParallelism = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the batch size for sync operations.
|
||||||
|
/// </summary>
|
||||||
|
public int BatchSize
|
||||||
|
{
|
||||||
|
get => _model.BatchSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.BatchSize != value)
|
||||||
|
{
|
||||||
|
_model.BatchSize = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the bulk copy batch size.
|
||||||
|
/// </summary>
|
||||||
|
public int BulkCopyBatchSize
|
||||||
|
{
|
||||||
|
get => _model.BulkCopyBatchSize;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.BulkCopyBatchSize != value)
|
||||||
|
{
|
||||||
|
_model.BulkCopyBatchSize = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the lookback multiplier.
|
||||||
|
/// </summary>
|
||||||
|
public double LookbackMultiplier
|
||||||
|
{
|
||||||
|
get => _model.LookbackMultiplier;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Math.Abs(_model.LookbackMultiplier - value) > 0.001)
|
||||||
|
{
|
||||||
|
_model.LookbackMultiplier = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the purge retention days.
|
||||||
|
/// </summary>
|
||||||
|
public int PurgeRetentionDays
|
||||||
|
{
|
||||||
|
get => _model.PurgeRetentionDays;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.PurgeRetentionDays != value)
|
||||||
|
{
|
||||||
|
_model.PurgeRetentionDays = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the sync timeout in seconds.
|
||||||
|
/// </summary>
|
||||||
|
public int SyncTimeoutSeconds
|
||||||
|
{
|
||||||
|
get => _model.SyncTimeoutSeconds;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model.SyncTimeoutSeconds != value)
|
||||||
|
{
|
||||||
|
_model.SyncTimeoutSeconds = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
_onChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+76
@@ -0,0 +1,76 @@
|
|||||||
|
using JdeScoping.ConfigManager.Models;
|
||||||
|
using JdeScoping.ConfigManager.ViewModels.Forms;
|
||||||
|
|
||||||
|
namespace JdeScoping.ConfigManager.Tests.ViewModels.Forms;
|
||||||
|
|
||||||
|
public class DataSyncFormViewModelTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void Constructor_InitializesFromModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var model = new DataSyncSection
|
||||||
|
{
|
||||||
|
Enabled = true,
|
||||||
|
MaxDegreeOfParallelism = 8,
|
||||||
|
BatchSize = 25000
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var sut = new DataSyncFormViewModel(model, () => { });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
sut.Enabled.ShouldBeTrue();
|
||||||
|
sut.MaxDegreeOfParallelism.ShouldBe(8);
|
||||||
|
sut.BatchSize.ShouldBe(25000);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PropertyChange_UpdatesModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var model = new DataSyncSection { MaxDegreeOfParallelism = 4 };
|
||||||
|
var sut = new DataSyncFormViewModel(model, () => { });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
sut.MaxDegreeOfParallelism = 16;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
model.MaxDegreeOfParallelism.ShouldBe(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PropertyChange_InvokesOnChanged()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var model = new DataSyncSection();
|
||||||
|
var changedInvoked = false;
|
||||||
|
var sut = new DataSyncFormViewModel(model, () => changedInvoked = true);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
sut.BatchSize = 10000;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
changedInvoked.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PropertyChange_RaisesPropertyChanged()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var model = new DataSyncSection();
|
||||||
|
var sut = new DataSyncFormViewModel(model, () => { });
|
||||||
|
var propertyChangedRaised = false;
|
||||||
|
sut.PropertyChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (e.PropertyName == nameof(DataSyncFormViewModel.LookbackMultiplier))
|
||||||
|
propertyChangedRaised = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
sut.LookbackMultiplier = 2.5;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
propertyChangedRaised.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user