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. } diff --git a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs index 1e3aa10f1..e1e9a49bf 100644 --- a/tests/ARSAS.Tests/IedBrowserPresentationTests.cs +++ b/tests/ARSAS.Tests/IedBrowserPresentationTests.cs @@ -141,9 +141,19 @@ 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)); + + // 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] 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"));