feat(adminui): B2-WP3 driver/device config modals + page-to-form refactor
Extract the 8 typed driver pages into embeddable <Driver>DriverForm bodies (channel/protocol config) and add per-driver <Driver>DeviceForm bodies (connection endpoint -> Device.DeviceConfig, v3 endpoint split). New DriverConfigModal + DeviceModal dispatch by DriverType (DriverTypeNames) for the /raw tree; Test-connect inside DeviceModal builds the merged Driver+Device config transiently via DriverDeviceConfigMerger. Routed pages now host the form bodies and keep working. Round-trip + enum-serialization guard tests for the Modbus driver form + Modbus device model; retargeted the existing page-form serialization tests + the _jsonOpts converter guard to the forms. Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
This commit is contained in:
+51
@@ -0,0 +1,51 @@
|
||||
using ZB.MOM.WW.OtOpcUa.AdminUI.Uns.TagEditors;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.PlcFamilies;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.DeviceForms;
|
||||
|
||||
/// <summary>
|
||||
/// Typed working model for an AB Legacy <c>Device</c>'s connection endpoint (the v3 endpoint→DeviceConfig
|
||||
/// split). Authors the <b>PascalCase</b> <c>HostAddress</c>/<c>PlcFamily</c> keys that
|
||||
/// <c>AbLegacyDeviceOptions</c> binds — the exact casing the seed and runtime probe
|
||||
/// (<c>PropertyNameCaseInsensitive</c>) expect. Preserves unrecognised keys across a load→save.
|
||||
/// </summary>
|
||||
public sealed class AbLegacyDeviceModel
|
||||
{
|
||||
/// <summary>PLC host / IP address.</summary>
|
||||
public string HostAddress { get; set; } = "";
|
||||
|
||||
/// <summary>Allen-Bradley legacy PLC family (SLC500 / MicroLogix / PLC-5).</summary>
|
||||
public AbLegacyPlcFamily PlcFamily { get; set; } = AbLegacyPlcFamily.Slc500;
|
||||
|
||||
private System.Text.Json.Nodes.JsonObject _bag = new();
|
||||
|
||||
/// <summary>Loads a model from a DeviceConfig JSON string, defaulting absent keys and retaining
|
||||
/// every original key so fields this editor doesn't expose survive a load→save.</summary>
|
||||
/// <param name="json">The raw DeviceConfig JSON string, or null for a new/empty device.</param>
|
||||
/// <returns>The populated <see cref="AbLegacyDeviceModel"/>.</returns>
|
||||
public static AbLegacyDeviceModel FromJson(string? json)
|
||||
{
|
||||
var o = TagConfigJson.ParseOrNew(json);
|
||||
return new AbLegacyDeviceModel
|
||||
{
|
||||
HostAddress = TagConfigJson.GetString(o, "HostAddress") ?? "",
|
||||
PlcFamily = TagConfigJson.GetEnum(o, "PlcFamily", AbLegacyPlcFamily.Slc500),
|
||||
_bag = o,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>Serializes this model back to a DeviceConfig JSON string, writing the PascalCase endpoint
|
||||
/// keys over the preserved key bag.</summary>
|
||||
/// <returns>The serialised DeviceConfig JSON string.</returns>
|
||||
public string ToJson()
|
||||
{
|
||||
TagConfigJson.Set(_bag, "HostAddress", HostAddress);
|
||||
TagConfigJson.Set(_bag, "PlcFamily", PlcFamily);
|
||||
return TagConfigJson.Serialize(_bag);
|
||||
}
|
||||
|
||||
/// <summary>Validation hook; returns an error message or null when the model is valid.</summary>
|
||||
/// <returns>An error message describing the validation failure, or <c>null</c> when the model is valid.</returns>
|
||||
public string? Validate()
|
||||
=> string.IsNullOrWhiteSpace(HostAddress) ? "Host address is required." : null;
|
||||
}
|
||||
Reference in New Issue
Block a user