From 7bc1be1ffc0b110a3eae3c2fe30ab9179879b406 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 23 Oct 2026 07:00:47 +0700 Subject: [PATCH 1/4] ui(ied-browser): use ARSAS-specific IEC 61850 service navigation order --- Models/IedBrowserPresentation.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Models/IedBrowserPresentation.cs b/Models/IedBrowserPresentation.cs index aba5a1760..510671bff 100644 --- a/Models/IedBrowserPresentation.cs +++ b/Models/IedBrowserPresentation.cs @@ -380,16 +380,12 @@ IedBrowserTreeRow Category(string name, string key, Func> children) => new("category/" + key, name, "Category", 0, loadChildren: children); + // ARSAS navigation order is a presentation choice, not a wire/model contract. + // Stable category keys and lazy children preserve existing selected paths and + // avoid any additional MMS discovery, control or report requests. var categories = new List { - Category("GOOSE", "goose", () => BlockGroups( - IedBrowserGooseDirectory.Resolve(model, sclModel), "GoCB", labelIed)), Category("Reports", "reports", () => ReportGroups(rcbs, labelIed)), - Category("Setting Groups", "settings", () => BlockGroups(model?.SettingGroupControls, "SGCB", labelIed)), - // Files inventory belongs exclusively in the right-side - // virtualized grid. Nested file nodes duplicate content and - // inflate the compact engineering navigation. - new("category/files", "Files", "Category", 0), Category("DataSets", "datasets", () => DataSetGroups(model?.DataSets, labelIed)), Category("Data Model", "model", () => model?.LogicalDevices.Select(ld => @@ -405,7 +401,14 @@ IedBrowserTreeRow Category(string name, string key, new IedBrowserTreeRow("model/da/" + attr.MmsReference + "/" + ordinal, attr.AttributePath, "DA", 4, attr)).ToArray())) .ToArray())).ToArray())).ToArray() - ?? Array.Empty()) + ?? Array.Empty()), + // Files inventory belongs exclusively in the right-side + // virtualized grid. Nested file nodes duplicate content and + // inflate the compact engineering navigation. + new("category/files", "Files", "Category", 0), + Category("GOOSE", "goose", () => BlockGroups( + IedBrowserGooseDirectory.Resolve(model, sclModel), "GoCB", labelIed)), + Category("Setting Groups", "settings", () => BlockGroups(model?.SettingGroupControls, "SGCB", labelIed)) }; return categories; // ARSAS IED Explorer already owns device selection; never duplicate it. } From 8557114659cff9a1a5a2ccff1ed1cc6baf604db6 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 23 Oct 2026 07:00:51 +0700 Subject: [PATCH 2/4] test(ied-browser): assert six service category labels and immutable keys --- tests/ARSAS.Tests/IedBrowserPresentationTests.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs index 1e3aa10f1..2825580a0 100644 --- a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs +++ b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs @@ -141,8 +141,12 @@ public void CategoriesFollowEngineeringNavigationOrder_WithoutMmsCalls() var projection = new IedBrowserTreeProjection(); projection.Reset(roots); Assert.Equal( - ["GOOSE", "Reports", "Setting Groups", "Files", "DataSets", "Data Model"], + ["Reports", "DataSets", "Data Model", "Files", "GOOSE", "Setting Groups"], projection.Rows.Select(x => x.Title).ToArray()); + Assert.Equal( + ["category/reports", "category/datasets", "category/model", + "category/files", "category/goose", "category/settings"], + projection.Rows.Select(x => x.Key).ToArray()); Assert.All(projection.Rows, x => Assert.Equal(0, x.Depth)); } From 6246c07c5acd92ded4f86f21621b16ee7c4245bc Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 23 Oct 2026 07:04:53 +0700 Subject: [PATCH 3/4] test(ied-browser): preserve navigation routes without live IED model --- tests/ARSAS.Tests/IedBrowserPresentationTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs index 2825580a0..e1e9a49bf 100644 --- a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs +++ b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs @@ -148,6 +148,12 @@ public void CategoriesFollowEngineeringNavigationOrder_WithoutMmsCalls() "category/files", "category/goose", "category/settings"], projection.Rows.Select(x => x.Key).ToArray()); Assert.All(projection.Rows, x => Assert.Equal(0, x.Depth)); + + // A disconnected or SCL-only session retains the same category routes; + // reordering must not depend on live MMS or create placeholder children. + var withoutLiveModel = IedBrowserPresentation.Roots(null, Array.Empty()); + Assert.Equal(projection.Rows.Select(x => x.Key).ToArray(), + withoutLiveModel.Select(x => x.Key).ToArray()); } [Fact] From 6ba69896778bb599a001baed3d6255e0a4a82293 Mon Sep 17 00:00:00 2001 From: Ari Sulistiono Date: Fri, 23 Oct 2026 07:11:28 +0700 Subject: [PATCH 4/4] test(ied-browser): update RCB navigation regression to new category presentation order --- tests/ARSAS.Tests/P0BrowserRcbEnabledTruthTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ARSAS.Tests/P0BrowserRcbEnabledTruthTests.cs b/tests/ARSAS.Tests/P0BrowserRcbEnabledTruthTests.cs index e54867e56..2dd0f7494 100644 --- a/tests/ARSAS.Tests/P0BrowserRcbEnabledTruthTests.cs +++ b/tests/ARSAS.Tests/P0BrowserRcbEnabledTruthTests.cs @@ -123,8 +123,8 @@ public void VirtualTreeStartsWithExactlySixCollapsedCategories() var rows = IedBrowserPresentation.Roots(null, [Rcb()]); var tree = new IedBrowserTreeProjection(); tree.Reset(rows); - Assert.Equal(new[] { "GOOSE", "Reports", "Setting Groups", "Files", - "DataSets", "Data Model" }, tree.Rows.Select(x => x.Title)); + Assert.Equal(new[] { "Reports", "DataSets", "Data Model", "Files", + "GOOSE", "Setting Groups" }, tree.Rows.Select(x => x.Title)); Assert.All(tree.Rows, x => Assert.False(x.IsExpanded)); var reports = Assert.Single(tree.Rows.Where(x => x.Key == "category/reports"));