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 16b39acc..c5e29aa0 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,9 +16,6 @@ - - - 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 deleted file mode 100644 index 4b77bbef..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/RelayAliasConvert.razor +++ /dev/null @@ -1,154 +0,0 @@ -@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; } - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/AliasTagModal.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/AliasTagModal.razor deleted file mode 100644 index d6b3bc9f..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Shared/Uns/AliasTagModal.razor +++ /dev/null @@ -1,249 +0,0 @@ -@* Create/edit modal for a Galaxy alias tag — an equipment Tag bound to a GalaxyMxGateway driver that - surfaces a Galaxy attribute (its tag_name.AttributeName reference) under a friendly UNS name. A focused - sibling of TagModal: it drops the generic driver/tag-config surface and instead embeds the Galaxy - live-browse picker so the operator picks the Galaxy reference straight into FullName. The host page owns - visibility and supplies the owning equipment id (create) or the loaded AliasTagEditDto (edit), plus the - equipment's candidate Galaxy gateways. On a successful save it raises OnSaved so the host can refresh the - equipment's tags in place. *@ -@using System.ComponentModel.DataAnnotations -@using Microsoft.AspNetCore.Components.Forms -@using ZB.MOM.WW.OtOpcUa.AdminUI.Uns -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers -@using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Pickers -@using ZB.MOM.WW.OtOpcUa.Configuration.Enums -@inject IUnsTreeService Svc - -@if (Visible) -{ - - -} - -@code { - // Same OPC UA built-in type names the TagModal offers, kept in sync. - private static readonly string[] DataTypes = - ["Boolean", "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", - "Int64", "UInt64", "Float", "Double", "String", "DateTime", "Guid", "ByteString"]; - - /// Whether the modal is shown. The host owns this flag. - [Parameter] public bool Visible { get; set; } - - /// true to create a new alias; false to edit . - [Parameter] public bool IsNew { get; set; } - - /// The owning equipment id the created alias binds to (used only on create). - [Parameter] public string? EquipmentId { get; set; } - - /// The alias being edited, when is false. - [Parameter] public AliasTagEditDto? Existing { get; set; } - - /// The candidate Galaxy gateways — scoped to the equipment's cluster by the host — as - /// (DriverInstanceId, Display, DriverConfig) triples. The config feeds the live-browse picker. - [Parameter] public IReadOnlyList<(string DriverInstanceId, string Display, string DriverConfig)> Gateways { get; set; } - = Array.Empty<(string, string, string)>(); - - /// Raised after a successful create/save so the host can refresh the equipment's tags and close. - [Parameter] public EventCallback OnSaved { get; set; } - - /// Raised when the user cancels so the host can close. - [Parameter] public EventCallback OnCancel { get; set; } - - private FormModel _form = new(); - private bool _busy; - private string? _error; - private bool _showPicker; - - // The selected gateway's DriverConfig JSON — fed to the Galaxy picker so it browses the right gateway. - private string _selectedGatewayConfig = "{}"; - - // Tracks which open this modal last loaded for, so unrelated Blazor Server re-renders don't rebuild - // _form and clobber in-progress edits. Null while closed. - private string? _loadedKey; - - protected override void OnParametersSet() - { - if (!Visible) - { - _loadedKey = null; // closed → next open reloads fresh - return; - } - - // Guard against unrelated re-renders. In Blazor Server any live-status push re-invokes - // OnParametersSet; without this the rebuild below would silently discard whatever the operator - // has typed. Only rebuild when the modal OPENS or the target entity CHANGES. - var key = IsNew ? "" : Existing?.TagId; - if (key == _loadedKey) return; // same open, re-render → preserve in-progress form edits - _loadedKey = key; - - if (IsNew) - { - _form = new FormModel(); - // Auto-select when exactly one gateway, so the picker can browse without an extra click. - if (Gateways.Count == 1) { _form.DriverInstanceId = Gateways[0].DriverInstanceId; } - } - else if (Existing is not null) - { - _form = new FormModel - { - Name = Existing.Name, - DriverInstanceId = Existing.DriverInstanceId, - DataType = Existing.DataType, - AccessLevel = Existing.AccessLevel, - FullName = Existing.FullName, - }; - } - _error = null; - _showPicker = false; - SyncSelectedGatewayConfig(); - } - - // Keeps the picker's browse config aligned with the chosen gateway whenever the operator switches it. - private void OnGatewayChanged() => SyncSelectedGatewayConfig(); - - private void SyncSelectedGatewayConfig() - { - var match = Gateways.FirstOrDefault(g => g.DriverInstanceId == _form.DriverInstanceId); - _selectedGatewayConfig = string.IsNullOrEmpty(match.DriverConfig) ? "{}" : match.DriverConfig; - } - - private void OnAddressPicked(string address) => _form.FullName = address; - - private async Task SaveAsync() - { - // Client validation: Name, FullName, and a chosen gateway are all required for a usable alias. - if (string.IsNullOrWhiteSpace(_form.Name)) { _error = "Name is required."; return; } - if (string.IsNullOrWhiteSpace(_form.DriverInstanceId)) { _error = "Pick a Galaxy gateway."; return; } - if (string.IsNullOrWhiteSpace(_form.FullName)) { _error = "A Galaxy reference is required — type it or browse to pick one."; return; } - - _busy = true; - _error = null; - try - { - // On create the TagId is system-minted (the alias has no operator-typed id field), matching the - // service's own NewTagId() shape: "TAG-" + 12 hex chars. Ignored on update. - var tagId = IsNew ? $"TAG-{Guid.NewGuid().ToString("N")[..12]}" : Existing!.TagId; - var input = new AliasTagInput(tagId, _form.Name, _form.DriverInstanceId, _form.DataType, _form.AccessLevel, _form.FullName); - - var result = IsNew - ? await Svc.CreateAliasTagAsync(EquipmentId!, input) - : await Svc.UpdateAliasTagAsync(Existing!.TagId, input, Existing.RowVersion); - - if (result.Ok) - { - await OnSaved.InvokeAsync(); - } - else - { - _error = result.Error; - } - } - finally - { - _busy = false; - } - } - - private Task CancelAsync() => OnCancel.InvokeAsync(); - - private sealed class FormModel - { - [Required] public string Name { get; set; } = ""; - [Required] public string DriverInstanceId { get; set; } = ""; - public string DataType { get; set; } = "Float"; - public TagAccessLevel AccessLevel { get; set; } = TagAccessLevel.Read; - [Required] public string FullName { get; set; } = ""; - } -} diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagEditDto.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagEditDto.cs deleted file mode 100644 index 3115a57e..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagEditDto.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns; -using ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -/// The editable state of a Galaxy alias tag, loaded for the alias edit modal. -/// is parsed out of the tag's TagConfig {"FullName":…}. -/// The tag's stable id (read-only on edit). -/// The tag name. -/// The bound Galaxy gateway driver id. -/// The OPC UA built-in type name. -/// The tag-level access baseline. -/// The Galaxy object reference parsed from TagConfig; empty string when absent. -/// The optimistic-concurrency token last read. -public sealed record AliasTagEditDto( - string TagId, string Name, string DriverInstanceId, string DataType, - TagAccessLevel AccessLevel, string FullName, byte[] RowVersion); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagInput.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagInput.cs deleted file mode 100644 index d7bca06d..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/AliasTagInput.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns; - -using ZB.MOM.WW.OtOpcUa.Configuration.Enums; - -/// -/// Operator-editable fields for a Galaxy alias tag (an equipment Tag bound to the Galaxy gateway). -/// is the picked Galaxy reference (tag_name.AttributeName); it is stored -/// as the tag's TagConfig {"FullName":…}. AccessLevel defaults to ReadOnly at the call site. -/// -/// Stable unique tag id; only honoured on create. -/// Tag display name; unique within the owning equipment. -/// The bound Galaxy gateway driver instance. -/// OPC UA built-in type name (Boolean / Int32 / Float / etc.). -/// Tag-level OPC UA access baseline (default ReadOnly). -/// The Galaxy reference (tag_name.AttributeName) this alias surfaces. -public sealed record AliasTagInput( - string TagId, string Name, string DriverInstanceId, string DataType, - TagAccessLevel AccessLevel, string FullName); diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/RelayConversion.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/RelayConversion.cs deleted file mode 100644 index cf1ce6ed..00000000 --- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/RelayConversion.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns; - -/// One relay VirtualTag that will/would become an alias Tag. -/// The owning equipment whose relay virtual tag is converted. -/// The relay virtual tag's name (becomes the alias tag's name). -/// The resolved Galaxy reference the alias surfaces (any {{equip}} token expanded). -/// The OPC UA built-in type name carried over from the virtual tag. -public sealed record RelayConversionItem(string EquipmentId, string VirtualTagName, string FullName, string DataType); - -/// One relay VirtualTag that cannot be converted, with the reason. -/// The owning equipment whose virtual tag was skipped. -/// The skipped virtual tag's name. -/// A human-readable explanation of why the virtual tag was not converted. -public sealed record RelayConversionSkip(string EquipmentId, string VirtualTagName, string Reason); - -/// Outcome of a (dry-run or applied) conversion pass. -/// The relay virtual tags that were (or, on dry-run, would be) converted to alias tags. -/// The candidate virtual tags that could not be converted, each with a reason. -/// true when the pass mutated the config; false for a dry-run preview. -public sealed record RelayConversionResult( - IReadOnlyList Converted, - IReadOnlyList Skipped, - bool Applied);