diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/GlobalUns.razor b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/GlobalUns.razor
index a026185a..d5c23d24 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/GlobalUns.razor
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Components/Pages/Uns/GlobalUns.razor
@@ -151,18 +151,6 @@
.Select(a => (a.EntityId!, a.DisplayName))
.ToList();
- /// Returns the (Id, Display) line options inside a single cluster, for the equipment picker.
- private IReadOnlyList<(string Id, string Display)> LinesForCluster(string? clusterId) =>
- _roots
- .SelectMany(ent => ent.Children)
- .Where(c => c.Kind == UnsNodeKind.Cluster && c.ClusterId == clusterId)
- .SelectMany(c => c.Children)
- .Where(a => a.Kind == UnsNodeKind.Area)
- .SelectMany(a => a.Children)
- .Where(l => l.Kind == UnsNodeKind.Line && l.EntityId is not null)
- .Select(l => (l.EntityId!, l.DisplayName))
- .ToList();
-
///
/// Toggles a structural node's expansion. Equipment nodes are leaves (no expander),
/// so this path only ever fires for Enterprise/Cluster/Area/Line.
@@ -370,8 +358,8 @@
}
///
- /// Expands every structural node (Enterprise/Cluster/Area/Line). Equipment nodes
- /// are intentionally left collapsed because expanding them would trigger lazy loads.
+ /// Expands every structural container node (Enterprise/Cluster/Area/Line) in the tree.
+ /// Equipment is a leaf node and has no expansion; skips it.
///
private void ExpandAll()
{
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs
index 9a3617c2..4f12c413 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/IUnsTreeService.cs
@@ -103,8 +103,8 @@ public sealed record EquipmentImportResult(int Inserted, int Skipped, IReadOnlyL
///
/// Loads the structural portion of the unified-namespace (UNS) browse tree —
/// Enterprise → Cluster → Area → Line → Equipment — from the config database.
-/// Equipment children (tags/virtual tags) are summarised by count only and loaded
-/// lazily by the renderer via .
+/// Equipment is a leaf in the tree; its tags and virtual tags are accessed via the
+/// equipment detail page, not via lazy tree expansion.
///
public interface IUnsTreeService
{
@@ -117,16 +117,6 @@ public interface IUnsTreeService
/// The enterprise root nodes, each populated down to equipment.
Task> LoadStructureAsync(CancellationToken ct = default);
- ///
- /// Lazily loads the Tag and VirtualTag leaf nodes for a single equipment node.
- /// Tags are returned first (ordered by Name), followed by VirtualTags (ordered by Name).
- /// Leaf nodes carry ChildCount = 0 and HasLazyChildren = false.
- ///
- /// The equipment whose children to load.
- /// A token to cancel the load.
- /// Tag nodes followed by VirtualTag nodes; empty if the equipment has none.
- Task> LoadEquipmentChildrenAsync(string equipmentId, CancellationToken ct = default);
-
///
/// Loads the driver tags bound to a single equipment as flat row projections for the equipment
/// page's Tags tab table, ordered by Name. Each row carries the display columns plus the
diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
index e8094890..e0c0e656 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
@@ -82,51 +82,6 @@ public sealed class UnsTreeService(IDbContextFactory dbF
return UnsTreeAssembly.Build(clusters, areas, lines, equipment);
}
- ///
- public async Task> LoadEquipmentChildrenAsync(
- string equipmentId,
- CancellationToken ct = default)
- {
- await using var db = await dbFactory.CreateDbContextAsync(ct);
-
- var tagNodes = await db.Tags
- .AsNoTracking()
- .Where(t => t.EquipmentId == equipmentId)
- .OrderBy(t => t.Name)
- .Select(t => new UnsNode
- {
- Kind = UnsNodeKind.Tag,
- Key = $"tag:{t.TagId}",
- DisplayName = $"{t.Name} ({t.DataType})",
- EntityId = t.TagId,
- ClusterId = null,
- ChildCount = 0,
- HasLazyChildren = false,
- })
- .ToListAsync(ct);
-
- var vtagNodes = await db.VirtualTags
- .AsNoTracking()
- .Where(v => v.EquipmentId == equipmentId)
- .OrderBy(v => v.Name)
- .Select(v => new UnsNode
- {
- Kind = UnsNodeKind.VirtualTag,
- Key = $"vtag:{v.VirtualTagId}",
- DisplayName = $"{v.Name} (VirtualTag)",
- EntityId = v.VirtualTagId,
- ClusterId = null,
- ChildCount = 0,
- HasLazyChildren = false,
- })
- .ToListAsync(ct);
-
- var result = new List(tagNodes.Count + vtagNodes.Count);
- result.AddRange(tagNodes);
- result.AddRange(vtagNodes);
- return result;
- }
-
///
public async Task> LoadTagsForEquipmentAsync(string equipmentId, CancellationToken ct = default)
{
diff --git a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceLazyTests.cs b/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceLazyTests.cs
deleted file mode 100644
index f6403580..00000000
--- a/tests/Server/ZB.MOM.WW.OtOpcUa.AdminUI.Tests/Uns/UnsTreeServiceLazyTests.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-using Shouldly;
-using Xunit;
-using ZB.MOM.WW.OtOpcUa.AdminUI.Uns;
-
-namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns;
-
-///
-/// Verifies returns Tag leaf nodes
-/// followed by VirtualTag leaf nodes, in Name order, with the correct keys and display names.
-///
-[Trait("Category", "Unit")]
-public sealed class UnsTreeServiceLazyTests
-{
- private static UnsTreeService SeededService()
- {
- var dbName = $"uns-lazy-{Guid.NewGuid():N}";
- UnsTreeTestDb.SeedNamed(dbName);
- return new UnsTreeService(UnsTreeTestDb.Factory(dbName));
- }
-
- ///
- /// Tags come first, ordered by Name, then VirtualTags; keys follow the tag:/vtag: scheme
- /// and the Tag display name embeds the DataType.
- ///
- [Fact]
- public async Task LoadEquipmentChildren_returns_tags_then_vtags()
- {
- var service = SeededService();
-
- var children = await service.LoadEquipmentChildrenAsync(UnsTreeTestDb.SeededEquipmentId);
-
- // Seed has 2 tags (speed=Float, running=Boolean) + 1 vtag (computed).
- // Tags are ordered by Name: "running" < "speed".
- children.Count.ShouldBe(3);
-
- var running = children[0];
- running.Kind.ShouldBe(UnsNodeKind.Tag);
- running.Key.ShouldBe("tag:TAG-2");
- running.EntityId.ShouldBe("TAG-2");
- running.ClusterId.ShouldBeNull();
- running.DisplayName.ShouldContain("running");
- running.DisplayName.ShouldContain("Boolean");
- running.ChildCount.ShouldBe(0);
- running.HasLazyChildren.ShouldBeFalse();
- running.Children.ShouldBeEmpty();
-
- var speed = children[1];
- speed.Kind.ShouldBe(UnsNodeKind.Tag);
- speed.Key.ShouldBe("tag:TAG-1");
- speed.EntityId.ShouldBe("TAG-1");
- speed.DisplayName.ShouldContain("speed");
- speed.DisplayName.ShouldContain("Float");
-
- var vtag = children[2];
- vtag.Kind.ShouldBe(UnsNodeKind.VirtualTag);
- vtag.Key.ShouldBe("vtag:VTAG-1");
- vtag.EntityId.ShouldBe("VTAG-1");
- vtag.ClusterId.ShouldBeNull();
- vtag.DisplayName.ShouldContain("computed");
- vtag.DisplayName.ShouldContain("VirtualTag");
- vtag.ChildCount.ShouldBe(0);
- vtag.HasLazyChildren.ShouldBeFalse();
- vtag.Children.ShouldBeEmpty();
- }
-
- /// An equipment with no tags or virtual tags returns an empty list.
- [Fact]
- public async Task LoadEquipmentChildren_empty_for_equipment_with_none()
- {
- // Use a fresh named store and add an equipment with no tags/vtags.
- var dbName = $"uns-lazy-empty-{Guid.NewGuid():N}";
- UnsTreeTestDb.SeedNamed(dbName);
-
- // The orphan equipment id is not in the seeded fixture, so just use a novel id.
- const string emptyEquipmentId = "EQ-NO-TAGS";
- var service = new UnsTreeService(UnsTreeTestDb.Factory(dbName));
-
- var children = await service.LoadEquipmentChildrenAsync(emptyEquipmentId);
-
- children.ShouldBeEmpty();
- }
-}