fix(adminui): preserve un-edited Modbus tag fields across edit (review)

Capture the original ModbusTagDefinition as _source in ModbusTagRow and
rewrite ToDefinition() to use 'with {}', so StringByteOrder, ArrayCount,
Deadband, UnitId, and CoalesceProhibited survive a load→edit→save cycle.
This commit is contained in:
Joseph Doherty
2026-05-29 09:18:36 -04:00
parent f655efc570
commit b351a81c8f
2 changed files with 41 additions and 6 deletions
@@ -490,20 +490,36 @@ else
public int StringLength { get; set; }
public bool WriteIdempotent { get; set; }
public ModbusTagRow Clone() => (ModbusTagRow)MemberwiseClone();
// Original record (null for newly-added rows). Preserves fields the editor doesn't expose
// (StringByteOrder, ArrayCount, Deadband, UnitId, CoalesceProhibited) across a load→save.
private ModbusTagDefinition? _source;
public ModbusTagRow Clone() => (ModbusTagRow)MemberwiseClone(); // _source is an immutable record ref — safe to share
public static ModbusTagRow FromDefinition(ModbusTagDefinition d) => new()
{
Name = d.Name, Region = d.Region, Address = d.Address, DataType = d.DataType,
Writable = d.Writable, ByteOrder = d.ByteOrder, BitIndex = d.BitIndex,
StringLength = d.StringLength, WriteIdempotent = d.WriteIdempotent,
_source = d,
};
public ModbusTagDefinition ToDefinition() => new(
Name: Name.Trim(), Region: Region, Address: (ushort)Math.Clamp(Address, 0, 65535),
DataType: DataType, Writable: Writable, ByteOrder: ByteOrder,
BitIndex: (byte)Math.Clamp(BitIndex, 0, 255), StringLength: (ushort)Math.Clamp(StringLength, 0, 65535),
WriteIdempotent: WriteIdempotent);
public ModbusTagDefinition ToDefinition()
{
var baseDef = _source ?? new ModbusTagDefinition(Name.Trim(), Region, 0, DataType);
return baseDef with
{
Name = Name.Trim(),
Region = Region,
Address = (ushort)Math.Clamp(Address, 0, 65535),
DataType = DataType,
Writable = Writable,
ByteOrder = ByteOrder,
BitIndex = (byte)Math.Clamp(BitIndex, 0, 255),
StringLength = (ushort)Math.Clamp(StringLength, 0, 65535),
WriteIdempotent = WriteIdempotent,
};
}
public static string? ValidateRow(ModbusTagRow row, IReadOnlyList<ModbusTagRow> all, int? editIndex)
{
@@ -151,4 +151,23 @@ public sealed class ModbusDriverPageFormSerializationTests
ModbusDriverPage.ModbusTagRow.ValidateRow(new() { Name = "A" }, rows, null)
.ShouldNotBeNull();
}
[Fact]
public void ToDefinition_preserves_unedited_fields()
{
var original = new ModbusTagDefinition(
"T", ModbusRegion.HoldingRegisters, 5, ModbusDataType.Int16,
StringByteOrder: ModbusStringByteOrder.LowByteFirst,
ArrayCount: 10, Deadband: 0.5, UnitId: 3, CoalesceProhibited: true);
var row = ModbusDriverPage.ModbusTagRow.FromDefinition(original);
row.Name = "Renamed";
var back = row.ToDefinition();
back.Name.ShouldBe("Renamed");
back.UnitId.ShouldBe((byte)3);
back.ArrayCount.ShouldBe(10);
back.Deadband.ShouldBe(0.5);
back.StringByteOrder.ShouldBe(ModbusStringByteOrder.LowByteFirst);
back.CoalesceProhibited.ShouldBeTrue();
}
}