diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/ClusterDrivers.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/ClusterDrivers.razor deleted file mode 100644 index 2f9afce2..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/ClusterDrivers.razor +++ /dev/null @@ -1,83 +0,0 @@ -@page "/clusters/{ClusterId}/drivers" -@attribute [Authorize(Policy = AdminUiPolicies.AuthenticatedRead)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory - -
-

Drivers · @ClusterId

- New driver -
- - - -@if (_rows is null) -{ -

Loading…

-} -else -{ -
-
@_rows.Count driver instance@(_rows.Count == 1 ? "" : "s")
- @if (_rows.Count == 0) - { -
No driver instances for this cluster.
- } - else - { - @foreach (var d in _rows) - { -
- - @d.DriverInstanceId - · @d.Name - · @d.DriverType - @if (!d.Enabled) { Disabled } - -
-
- Edit -
-
@FormatJson(d.DriverConfig)
- @if (!string.IsNullOrWhiteSpace(d.ResilienceConfig)) - { -
Resilience overrides:
-
@FormatJson(d.ResilienceConfig)
- } -
-
- } - } -
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - private List? _rows; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - _rows = await db.DriverInstances.AsNoTracking() - .Where(d => d.ClusterId == ClusterId) - .OrderBy(d => d.DriverInstanceId) - .ToListAsync(); - } - - private static string FormatJson(string raw) - { - if (string.IsNullOrWhiteSpace(raw)) return ""; - try - { - using var doc = System.Text.Json.JsonDocument.Parse(raw); - return System.Text.Json.JsonSerializer.Serialize(doc.RootElement, - new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); - } - catch - { - return raw; - } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbCipDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbCipDriverPage.razor deleted file mode 100644 index c554aa09..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbCipDriverPage.razor +++ /dev/null @@ -1,208 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/abcip" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@using ZB.MOM.WW.OtOpcUa.Driver.AbCip -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New AB CIP driver" : "Edit AB CIP driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - - - -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "AbCip"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; - return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbLegacyDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbLegacyDriverPage.razor deleted file mode 100644 index d1b8b5d4..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/AbLegacyDriverPage.razor +++ /dev/null @@ -1,206 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/ablegacy" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New AB Legacy driver" : "Edit AB Legacy driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - - - -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "AbLegacy"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; - return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverEditRouter.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverEditRouter.razor deleted file mode 100644 index 97d25333..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverEditRouter.razor +++ /dev/null @@ -1,82 +0,0 @@ -@* Dispatch page: reads DriverInstance.DriverType and dispatches to the matching typed editor - via using _componentMap. Shows an error panel when the driver type has - no registered typed page. *@ -@page "/clusters/{ClusterId}/drivers/{DriverInstanceId}" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory - -@if (!_loaded) -{ -

Loading…

-} -else if (_existing is null) -{ -
-

Edit driver instance · @ClusterId

- Cancel -
- -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else if (ResolveComponentType() is { } pageType) -{ - -} -else -{ -
-

Edit driver instance · @ClusterId

- Cancel -
- -
- Driver instance @DriverInstanceId has an unknown DriverType value of - @_existing.DriverType. No editor is registered for this type. - Likely causes: the row was written by a newer build, or the type-string was corrupted in the database. -
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string DriverInstanceId { get; set; } = ""; - - private DriverInstance? _existing; - private bool _loaded; - - private static readonly IReadOnlyDictionary _componentMap = - new Dictionary(StringComparer.OrdinalIgnoreCase) - { - ["Modbus"] = typeof(ModbusDriverPage), - ["AbCip"] = typeof(AbCipDriverPage), - ["AbLegacy"] = typeof(AbLegacyDriverPage), - ["S7"] = typeof(S7DriverPage), - ["TwinCat"] = typeof(TwinCATDriverPage), - ["Focas"] = typeof(FocasDriverPage), - ["OpcUaClient"] = typeof(OpcUaClientDriverPage), - ["GalaxyMxGateway"] = typeof(GalaxyDriverPage), - }; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - _loaded = true; - } - - private Type? ResolveComponentType() - => _componentMap.TryGetValue(_existing!.DriverType, out var t) ? t : null; - - private IDictionary BuildParameters() - => new Dictionary - { - ["ClusterId"] = ClusterId, - ["DriverInstanceId"] = DriverInstanceId, - }; -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverTypePicker.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverTypePicker.razor deleted file mode 100644 index 6b81bfc5..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/DriverTypePicker.razor +++ /dev/null @@ -1,49 +0,0 @@ -@* Driver type picker — presents a card grid of registered driver types and links to the - per-type new-driver creation page (/clusters/{ClusterId}/drivers/new/{slug}). *@ -@page "/clusters/{ClusterId}/drivers/new" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] - -
-

New driver · @ClusterId

- Cancel -
- - - -
-
Pick a driver type
-
-
- @foreach (var t in _types) - { - - } -
-
-
- -@code { - [Parameter] public string ClusterId { get; set; } = ""; - - private sealed record DriverTypeEntry(string DisplayName, string Slug, string Icon, string Description); - - private static readonly IReadOnlyList _types = new[] - { - new DriverTypeEntry("Modbus TCP", "modbustcp", "[M]", "Modbus/TCP — generic registers/coils via port 502."), - new DriverTypeEntry("AbCip", "abcip", "[CIP]", "Allen-Bradley CompactLogix/ControlLogix via CIP."), - new DriverTypeEntry("AbLegacy", "ablegacy", "[AB]", "Allen-Bradley PLC-5/SLC-500/MicroLogix via DF1."), - new DriverTypeEntry("S7", "s7", "[S7]", "Siemens S7-300/400/1200/1500 via ISO-on-TCP."), - new DriverTypeEntry("TwinCat", "twincat", "[TC]", "Beckhoff TwinCAT via ADS."), - new DriverTypeEntry("Focas", "focas", "[FOC]", "Fanuc CNC via FOCAS library."), - new DriverTypeEntry("OpcUaClient", "opcuaclient", "[OPC]", "Upstream OPC UA server pull."), - new DriverTypeEntry("Galaxy", "galaxy", "[Gx]", "AVEVA System Platform (Wonderware) via mxaccessgw."), - }; -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/FocasDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/FocasDriverPage.razor deleted file mode 100644 index daf6f289..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/FocasDriverPage.razor +++ /dev/null @@ -1,209 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/focas" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New Fanuc FOCAS driver" : "Edit Fanuc FOCAS driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - - - - @* Tags *@ -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "Focas"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; - return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/GalaxyDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/GalaxyDriverPage.razor deleted file mode 100644 index 41fe8280..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/GalaxyDriverPage.razor +++ /dev/null @@ -1,198 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/galaxy" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New AVEVA Galaxy driver" : "Edit AVEVA Galaxy driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - - -
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "GalaxyMxGateway"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/ModbusDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/ModbusDriverPage.razor deleted file mode 100644 index 7baa8d79..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/ModbusDriverPage.razor +++ /dev/null @@ -1,214 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/modbustcp" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New Modbus/TCP driver" : "Edit Modbus/TCP driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - -
-
Connection endpoint
-
- Host / Port / Unit ID now live on the driver's device (v3 endpoint→DeviceConfig split). - Author them from the Raw tree (/raw) device modal. -
-
- - - -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "Modbus"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; - return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/OpcUaClientDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/OpcUaClientDriverPage.razor deleted file mode 100644 index 9bcf899b..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/OpcUaClientDriverPage.razor +++ /dev/null @@ -1,206 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/opcuaclient" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New OPC UA Client driver" : "Edit OPC UA Client driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - -
-
Connection endpoint
-
- The single Endpoint URL now lives on the driver's device (v3 endpoint→DeviceConfig split). - Author it from the Raw tree (/raw) device modal. The failover EndpointUrls list below stays driver-level. -
-
- - -
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "OpcUaClient"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/S7DriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/S7DriverPage.razor deleted file mode 100644 index 00f1d8b5..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/S7DriverPage.razor +++ /dev/null @@ -1,213 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/s7" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New Siemens S7 driver" : "Edit Siemens S7 driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - -
-
Connection endpoint
-
- Host / Port / Rack / Slot now live on the driver's device (v3 endpoint→DeviceConfig split). - Author them from the Raw tree (/raw) device modal. -
-
- - - -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "S7"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/TwinCATDriverPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/TwinCATDriverPage.razor deleted file mode 100644 index 696e4eba..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Clusters/Drivers/TwinCATDriverPage.razor +++ /dev/null @@ -1,214 +0,0 @@ -@page "/clusters/{ClusterId}/drivers/new/twincat" -@attribute [Authorize(Policy = AdminUiPolicies.ConfigEditor)] -@rendermode RenderMode.InteractiveServer -@using Microsoft.AspNetCore.Components.Forms -@using Microsoft.EntityFrameworkCore -@using ZB.MOM.WW.OtOpcUa.AdminUI.Clients -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration -@using ZB.MOM.WW.OtOpcUa.Configuration.Entities -@inject IDbContextFactory DbFactory -@inject NavigationManager Nav - -
-

@(IsNew ? "New Beckhoff TwinCAT driver" : "Edit Beckhoff TwinCAT driver") · @ClusterId

- Cancel -
- - -@if (!_loaded) -{ -

Loading…

-} -else if (!IsNew && _existing is null) -{ -
- Driver instance @DriverInstanceId was not found in cluster @ClusterId. -
-} -else -{ - - - - - - - @if (!IsNew && !string.IsNullOrEmpty(DriverInstanceId)) - { - - } - -
- - -
- - - - - -
-
Connection endpoint
-
- Device host addresses (AMS Net Id:port) now live on the driver's devices - (v3 endpoint→DeviceConfig split). Author them from the Raw tree (/raw) device modal. -
-
- - - -
-
Tags
-
- Tag authoring moves to the Raw tree (/raw) in v3 Batch 2. - Pre-declared driver tags have been retired. -
-
-
-
-} - -@code { - [Parameter] public string ClusterId { get; set; } = ""; - [Parameter] public string? DriverInstanceId { get; set; } - - private const string DriverTypeKey = "TwinCat"; - - private bool IsNew => string.IsNullOrEmpty(DriverInstanceId); - - private DriverIdentitySection.DriverIdentityModel _identityModel = new() { DriverType = DriverTypeKey }; - private string _driverConfigJson = "{}"; - private string? _resilienceConfig; - private byte[] _rowVersion = []; - private DriverInstance? _existing; - private bool _loaded; - private bool _busy; - private string? _error; - - // Address picker state - private bool _showPicker; - private string _pickedAddress = ""; - - private void OnAddressPicked(string address) => _pickedAddress = address; - - protected override async Task OnInitializedAsync() - { - await using var db = await DbFactory.CreateDbContextAsync(); - - if (IsNew) - { - _identityModel = new() - { - DriverInstanceId = "", - Name = "", - DriverType = DriverTypeKey, - Enabled = true, - }; - _driverConfigJson = "{}"; - } - else - { - _existing = await db.DriverInstances.AsNoTracking() - .FirstOrDefaultAsync(d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (_existing is not null) - { - _identityModel = new() - { - DriverInstanceId = _existing.DriverInstanceId, - Name = _existing.Name, - DriverType = _existing.DriverType, - Enabled = _existing.Enabled, - }; - _driverConfigJson = string.IsNullOrWhiteSpace(_existing.DriverConfig) ? "{}" : _existing.DriverConfig; - _resilienceConfig = _existing.ResilienceConfig; - _rowVersion = _existing.RowVersion; - } - } - _loaded = true; - } - - private async Task SubmitAsync() - { - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - if (IsNew) - { - if (await db.DriverInstances.AnyAsync(d => d.DriverInstanceId == _identityModel.DriverInstanceId)) - { - _error = $"Driver instance '{_identityModel.DriverInstanceId}' already exists."; return; - } - db.DriverInstances.Add(new DriverInstance - { - DriverInstanceId = _identityModel.DriverInstanceId, - ClusterId = ClusterId, - Name = _identityModel.Name, - DriverType = DriverTypeKey, - Enabled = _identityModel.Enabled, - DriverConfig = _driverConfigJson, - ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig, - }); - } - else - { - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { _error = "Row no longer exists."; return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - entity.Name = _identityModel.Name; - entity.Enabled = _identityModel.Enabled; - entity.DriverConfig = _driverConfigJson; - entity.ResilienceConfig = string.IsNullOrWhiteSpace(_resilienceConfig) ? null : _resilienceConfig; - } - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were editing. Reload to see the latest values, then re-apply your changes."; - } - catch (Exception ex) { _error = ex.Message; } - finally { _busy = false; } - } - - private async Task DeleteAsync() - { - if (IsNew) return; - _busy = true; _error = null; - try - { - await using var db = await DbFactory.CreateDbContextAsync(); - var entity = await db.DriverInstances.FirstOrDefaultAsync( - d => d.ClusterId == ClusterId && d.DriverInstanceId == DriverInstanceId); - if (entity is null) { Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); return; } - db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _rowVersion; - db.DriverInstances.Remove(entity); - await db.SaveChangesAsync(); - Nav.NavigateTo($"/clusters/{ClusterId}/drivers"); - } - catch (DbUpdateConcurrencyException) - { - _error = "Another user changed this driver instance while you were viewing it. Reload before deleting."; - } - catch (Exception ex) - { - _error = $"Delete failed: {ex.Message}. (Likely because equipment/tags still reference this driver — remove them first.)"; - } - finally { _busy = false; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/ClusterNav.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/ClusterNav.razor index 995f4a87..9d076c7a 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/ClusterNav.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/ClusterNav.razor @@ -11,7 +11,6 @@