From a58d57890ada6ceb784d4159c8bf2b3f6532dd86 Mon Sep 17 00:00:00 2001 From: jsakamoto Date: Sun, 7 Apr 2024 23:07:14 +0900 Subject: [PATCH] Fix: navigation next/prev stories, docs, and components didn't work --- .../NavigationTree/NavigationTree.razor | 50 ++--------- .../Services/Navigation/NavigationService.cs | 24 ++++++ .../Navigation/NavigationServiceTest.cs | 83 +++++++++++++++++++ .../BlazingStory.Test/_Fixtures/TestHelper.cs | 3 +- Tests/BlazingStory.Test/_Fixtures/TestHost.cs | 7 +- 5 files changed, 123 insertions(+), 44 deletions(-) diff --git a/BlazingStory/Internals/Components/SideBar/NavigationTree/NavigationTree.razor b/BlazingStory/Internals/Components/SideBar/NavigationTree/NavigationTree.razor index 6014d024..4805f951 100644 --- a/BlazingStory/Internals/Components/SideBar/NavigationTree/NavigationTree.razor +++ b/BlazingStory/Internals/Components/SideBar/NavigationTree/NavigationTree.razor @@ -46,57 +46,23 @@ } } - private ValueTask OnPreviousComponent() => this.MoveComponent(delta: -1); + private ValueTask OnPreviousComponent() => this.MoveComponent(navigateToNext: false); - private ValueTask OnNextComponent() => this.MoveComponent(delta: +1); + private ValueTask OnNextComponent() => this.MoveComponent(navigateToNext: true); - private ValueTask MoveComponent(int delta) + private ValueTask MoveComponent(bool navigateToNext) { - var navigationPath = this.RouteData?.Parameter; - - var currentComponent = default(NavigationTreeItem); - foreach (var item in this.NavigationRoot.EnumAll()) - { - if (item.Type == NavigationItemType.Component) currentComponent = item; - if (item.NavigationPath == navigationPath) break; - } - if (currentComponent == null) return ValueTask.CompletedTask; - - var componentItems = this.NavigationRoot.EnumAll() - .Where(item => item.Type == NavigationItemType.Component) - .ToArray(); - - var index = Array.IndexOf(componentItems, currentComponent); - var indexMoveTo = index + delta; - if (indexMoveTo < 0 || componentItems.Length <= indexMoveTo) return ValueTask.CompletedTask; - - var componentMoveTo = componentItems[index + delta]; - var itemMoveTo = componentMoveTo.SubItems.FirstOrDefault(); - if (itemMoveTo == null) return ValueTask.CompletedTask; - - this.NavigationRoot.EnsureExpandedTo(itemMoveTo); - - this._NavigationService?.NavigateTo(itemMoveTo); + this._NavigationService.NavigateToNextComponentItem(this.RouteData, navigateToNext); return ValueTask.CompletedTask; } - private ValueTask OnPreviousStory() => this.MoveStory(delta: -1); + private ValueTask OnPreviousStory() => this.MoveStory(navigateToNext: false); - private ValueTask OnNextStory() => this.MoveStory(delta: +1); + private ValueTask OnNextStory() => this.MoveStory(navigateToNext: true); - private ValueTask MoveStory(int delta) + private ValueTask MoveStory(bool navigateToNext) { - var storyItems = this.NavigationRoot.EnumAll() - .Where(item => item.Type == NavigationItemType.Story) - .ToArray(); - var index = Array.FindIndex(storyItems, item => this.RouteData?.Parameter == item.NavigationPath); - var indexMoveTo = index + delta; - if (indexMoveTo < 0 || storyItems.Length <= indexMoveTo) return ValueTask.CompletedTask; - - var itemMoveTo = storyItems[index + delta]; - this.NavigationRoot.EnsureExpandedTo(itemMoveTo); - - this._NavigationService?.NavigateTo(itemMoveTo); + this._NavigationService.NavigateToNextDocsOrStory(this.RouteData, navigateToNext); return ValueTask.CompletedTask; } diff --git a/BlazingStory/Internals/Services/Navigation/NavigationService.cs b/BlazingStory/Internals/Services/Navigation/NavigationService.cs index d0ee6573..c47a76d4 100644 --- a/BlazingStory/Internals/Services/Navigation/NavigationService.cs +++ b/BlazingStory/Internals/Services/Navigation/NavigationService.cs @@ -64,6 +64,30 @@ internal bool TryGetActiveNavigationItem(QueryRouteData? routeData, [NotNullWhen return true; } + internal void NavigateToNextComponentItem(QueryRouteData? routeData, bool navigateToNext) + { + if (!this.TryGetActiveNavigationItem(routeData, out var activeItem, out var _)) return; + var allComponents = this._Root.EnumAll().Where(item => item.Type is NavigationItemType.Component).ToList(); + var ativeComponentIndex = allComponents.FindIndex(item => item.EnumAll().Contains(activeItem)); + var nextComponentIndex = ativeComponentIndex + (navigateToNext ? +1 : -1); + if (nextComponentIndex < 0 || allComponents.Count <= nextComponentIndex) return; + var nextComponent = allComponents[nextComponentIndex]; + var nextItem = nextComponent.EnumAll().Where(item => item.Type is NavigationItemType.Story or NavigationItemType.Docs).FirstOrDefault(); + if (nextItem == null) return; + this.NavigateTo(nextItem); + } + + internal void NavigateToNextDocsOrStory(QueryRouteData? routeData, bool navigateToNext) + { + if (!this.TryGetActiveNavigationItem(routeData, out var activeItem, out var _)) return; + var allItems = this._Root.EnumAll().Where(item => item.Type is NavigationItemType.Docs or NavigationItemType.Story).ToList(); + var ativeIndex = allItems.FindIndex(item => item == activeItem); + var nextIndex = ativeIndex + (navigateToNext ? +1 : -1); + if (nextIndex < 0 || allItems.Count <= nextIndex) return; + var nextItem = allItems[nextIndex]; + this.NavigateTo(allItems[nextIndex]); + } + internal void NotifyLastVisitedWasUnknown() { this._LastNavigatedWasunknown = true; diff --git a/Tests/BlazingStory.Test/Internals/Services/Navigation/NavigationServiceTest.cs b/Tests/BlazingStory.Test/Internals/Services/Navigation/NavigationServiceTest.cs index 8b39e07c..74797246 100644 --- a/Tests/BlazingStory.Test/Internals/Services/Navigation/NavigationServiceTest.cs +++ b/Tests/BlazingStory.Test/Internals/Services/Navigation/NavigationServiceTest.cs @@ -1,5 +1,6 @@ using BlazingStory.Internals.Services.Navigation; using BlazingStory.Test._Fixtures; +using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; namespace BlazingStory.Test.Internals.Services.Navigation; @@ -65,4 +66,86 @@ public async Task Search_Hit_by_Caption_of_Component_Test() // Then searchResults.Dump().Is("Component | Button | Examples"); } + + [Test] + public async Task NavigateToNextComponentItem_Test() + { + // Given + await using var host = new TestHost(); + var navMan = host.Services.GetRequiredService(); + var navService = host.Services.GetRequiredService(); + navService.BuildNavigationTree(TestHelper.GetExampleStories1(host.Services), null); + + navService.NavigateToNextComponentItem(new("story", "examples-button--default-button"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/docs/examples-select--docs"); + + navService.NavigateToNextComponentItem(new("docs", "examples-select--docs"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/docs/examples-select--docs"); + } + + [Test] + public async Task NavigateToPrevComponentItem_Test() + { + // Given + await using var host = new TestHost(); + var navMan = host.Services.GetRequiredService(); + var navService = host.Services.GetRequiredService(); + navService.BuildNavigationTree(TestHelper.GetExampleStories1(host.Services), null); + + navService.NavigateToNextComponentItem(new("docs", "examples-select--docs"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/docs/examples-button--docs"); + + navService.NavigateToNextComponentItem(new("story", "examples-button--primary-button"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/docs/examples-button--docs"); + } + + [Test] + public async Task NavigateToNextDocsOrStory_Test() + { + // Given + await using var host = new TestHost(); + var navMan = host.Services.GetRequiredService(); + var navService = host.Services.GetRequiredService(); + navService.BuildNavigationTree(TestHelper.GetExampleStories1(host.Services), null); + + navService.NavigateToNextDocsOrStory(new("docs", "examples-button--docs"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/story/examples-button--default-button"); + + navService.NavigateToNextDocsOrStory(new("story", "examples-button--default-button"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/story/examples-button--primary-button"); + + navService.NavigateToNextDocsOrStory(new("story", "examples-button--primary-button"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/docs/examples-select--docs"); + + navService.NavigateToNextDocsOrStory(new("docs", "examples-select--docs"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/story/examples-select--select"); + + navService.NavigateToNextDocsOrStory(new("story", "examples-select--select"), navigateToNext: true); + navMan.Uri.Is("http://localhost/?path=/story/examples-select--select"); + } + + [Test] + public async Task NavigateToPrevDocsOrStory_Test() + { + // Given + await using var host = new TestHost(); + var navMan = host.Services.GetRequiredService(); + var navService = host.Services.GetRequiredService(); + navService.BuildNavigationTree(TestHelper.GetExampleStories1(host.Services), null); + + navService.NavigateToNextDocsOrStory(new("story", "examples-select--select"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/docs/examples-select--docs"); + + navService.NavigateToNextDocsOrStory(new("docs", "examples-select--docs"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/story/examples-button--primary-button"); + + navService.NavigateToNextDocsOrStory(new("story", "examples-button--primary-button"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/story/examples-button--default-button"); + + navService.NavigateToNextDocsOrStory(new("story", "examples-button--default-button"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/docs/examples-button--docs"); + + navService.NavigateToNextDocsOrStory(new("docs", "examples-button--docs"), navigateToNext: false); + navMan.Uri.Is("http://localhost/?path=/docs/examples-button--docs"); + } } diff --git a/Tests/BlazingStory.Test/_Fixtures/TestHelper.cs b/Tests/BlazingStory.Test/_Fixtures/TestHelper.cs index 6a878ed4..8d834a37 100644 --- a/Tests/BlazingStory.Test/_Fixtures/TestHelper.cs +++ b/Tests/BlazingStory.Test/_Fixtures/TestHelper.cs @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using RazorClassLib1.Components.Button; +using RazorClassLib1.Components.Select; using Toolbelt.Diagnostics; namespace BlazingStory.Test._Fixtures; @@ -36,7 +37,7 @@ internal static IEnumerable GetExampleStories1(IServiceProvider CreateStory