From 7682d185fb454aec5001734124d540841295a723 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Thu, 11 Jun 2026 21:49:43 -0400 Subject: [PATCH] feat(adminui): relay->alias converter UI (per-equipment + fleet-wide /uns/convert-relays) --- .../Components/Layout/MainLayout.razor | 3 + .../Components/Pages/Uns/EquipmentPage.razor | 110 +++++++++++++ .../Pages/Uns/RelayAliasConvert.razor | 154 ++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/RelayAliasConvert.razor diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor index c5e29aa0..16b39acc 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Layout/MainLayout.razor @@ -16,6 +16,9 @@ + + + diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/EquipmentPage.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/EquipmentPage.razor index fc0a46ff..3489cc2c 100644 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/EquipmentPage.razor +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/EquipmentPage.razor @@ -145,6 +145,7 @@ else } + @if (!string.IsNullOrWhiteSpace(_tagError)) { @@ -196,6 +197,76 @@ else } + @if (!string.IsNullOrWhiteSpace(_convertMessage)) + { +
@_convertMessage
+ } + + @if (_convertPreview is not null) + { +
+
+ Convert relay virtual-tags to aliases + +
+
+
Will convert (@_convertPreview.Converted.Count)
+ @if (_convertPreview.Converted.Count == 0) + { +

No relay virtual-tags to convert.

+ } + else + { + + + + @foreach (var c in _convertPreview.Converted) + { + + + + + + } + +
Virtual tagFull nameData type
@c.VirtualTagName@c.FullName@c.DataType
+ } + +
Skipped (@_convertPreview.Skipped.Count)
+ @if (_convertPreview.Skipped.Count == 0) + { +

Nothing skipped.

+ } + else + { + + + + @foreach (var s in _convertPreview.Skipped) + { + + + + + } + +
Virtual tagReason
@s.VirtualTagName@s.Reason
+ } + +
+ @if (_convertPreview.Converted.Count > 0) + { + + } + +
+
+
+ } + @@ -331,6 +402,12 @@ else private bool _aliasModalIsNew; private AliasTagEditDto? _aliasModalExisting; + // --- Relay→alias converter (per-equipment). _convertPreview holds the dry-run result while the + // inline preview panel is open; null = panel closed. _convertMessage is a brief post-apply summary. --- + private RelayConversionResult? _convertPreview; + private bool _convertBusy; + private string? _convertMessage; + // --- Virtual Tags tab state. _vtags is null until the tab is first activated. --- private IReadOnlyList? _vtags; private string? _vtagError; @@ -440,6 +517,36 @@ else await ReloadTagsAsync(); } + // --- Relay→alias converter handlers (per-equipment, scoped to EquipmentId). Dry-run first to fill + // the inline preview panel; Apply mutates the draft then reloads the tags + virtual-tags lists so + // the converted vtags vanish and the new aliases appear. --- + + private async Task PreviewConvertRelaysAsync() + { + _convertMessage = null; + _convertBusy = true; + try + { + _convertPreview = await Svc.ConvertRelayVirtualTagsToAliasesAsync(EquipmentId!, dryRun: true); + } + finally { _convertBusy = false; } + } + + private async Task ApplyConvertRelaysAsync() + { + _convertBusy = true; + try + { + var r = await Svc.ConvertRelayVirtualTagsToAliasesAsync(EquipmentId!, dryRun: false); + _convertPreview = null; + _convertMessage = $"Converted {r.Converted.Count}, skipped {r.Skipped.Count}."; + // The converted virtual tags become aliases, so both lists change. + await ReloadTagsAsync(); + await ReloadVirtualTagsAsync(); + } + finally { _convertBusy = false; } + } + // --- Virtual Tags tab handlers --- private async Task ReloadVirtualTagsAsync() @@ -542,6 +649,9 @@ else _tags = null; _vtags = null; _alarms = null; + // Drop any open relay-conversion preview/summary so it can't leak across equipment changes. + _convertPreview = null; + _convertMessage = null; if (!IsNew) { _equipment = await Svc.LoadEquipmentAsync(EquipmentId!); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/RelayAliasConvert.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/RelayAliasConvert.razor new file mode 100644 index 00000000..ae769a8e --- /dev/null +++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/RelayAliasConvert.razor @@ -0,0 +1,154 @@ +@page "/uns/convert-relays" +@* Fleet-wide relay→alias converter. Previews (dry-run) and applies the conversion of pure-relay + virtual tags into Galaxy alias tags across every equipment. Edits the draft config only; the + operator publishes normally afterward. FleetAdmin-gated (mirrors RoleGrants.razor). *@ +@attribute [Microsoft.AspNetCore.Authorization.Authorize(Policy = "FleetAdmin")] +@rendermode RenderMode.InteractiveServer +@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns +@inject IUnsTreeService Svc + +Convert relays + +
+

Convert relay virtual-tags to aliases

+ Back to UNS +
+ +

+ Sweeps every equipment for pure-relay virtual tags (a script body that simply returns another + tag's value) and rewrites each one as a Galaxy alias tag. This edits the draft configuration + only — publish afterward to take effect. Run a preview first to review what will change. +

+ +
+ + @if (_applied) + { + Conversion applied. Publish to take effect. + } +
+ +@if (!string.IsNullOrWhiteSpace(_error)) +{ +
@_error
+} + +@if (_preview is not null) +{ +
+
Will convert (@_preview.Converted.Count)
+ @if (_preview.Converted.Count == 0) + { +
No relay virtual-tags to convert.
+ } + else + { +
+ + + + @foreach (var c in _preview.Converted) + { + + + + + + + } + +
EquipmentVirtual tagFull nameData type
@c.EquipmentId@c.VirtualTagName@c.FullName@c.DataType
+
+ } +
+ +
+
Skipped (@_preview.Skipped.Count)
+ @if (_preview.Skipped.Count == 0) + { +
Nothing skipped.
+ } + else + { +
+ + + + @foreach (var s in _preview.Skipped) + { + + + + + + } + +
EquipmentVirtual tagReason
@s.EquipmentId@s.VirtualTagName@s.Reason
+
+ } +
+ + @if (!_preview.Applied && _preview.Converted.Count > 0) + { +
+ @if (!_confirming) + { + + } + else + { + Convert @_preview.Converted.Count relay virtual-tag(s) to aliases in the draft? + + + } +
+ } +} + +@code { + private RelayConversionResult? _preview; + private bool _busy; + private bool _confirming; + private bool _applied; + private string? _error; + + private async Task PreviewAsync() + { + _error = null; + _confirming = false; + _applied = false; + _busy = true; + try + { + _preview = await Svc.ConvertRelayVirtualTagsToAliasesAsync(null, dryRun: true); + } + catch (Exception ex) { _error = ex.Message; } + finally { _busy = false; } + } + + private async Task ApplyAsync() + { + _error = null; + _busy = true; + try + { + await Svc.ConvertRelayVirtualTagsToAliasesAsync(null, dryRun: false); + _applied = true; + _confirming = false; + // Re-run the preview so the Converted set is now empty and only remaining skips show. + _preview = await Svc.ConvertRelayVirtualTagsToAliasesAsync(null, dryRun: true); + } + catch (Exception ex) { _error = ex.Message; } + finally { _busy = false; } + } +}