Establish navi->list helper

Change-Id: I0bab00500aac7c0398e8e4ab60792e0f0b567bb7
diff --git a/Changes b/Changes
index 82705c1..cdd34ff 100644
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
-0.58 2024-10-08
+0.58 2024-10-14
         - Fix meta table view for key value pairs (diewald)
         - Fix warning on OAuth public clients (diewald)
+        - Introduce navi->list helper (diewald)
 
 0.57 2024-10-08
         - Support VCs via URL without queries (diewald)
diff --git a/lib/Kalamar/Plugin/KalamarPages.pm b/lib/Kalamar/Plugin/KalamarPages.pm
index 244973f..514b193 100644
--- a/lib/Kalamar/Plugin/KalamarPages.pm
+++ b/lib/Kalamar/Plugin/KalamarPages.pm
@@ -268,6 +268,33 @@
       return 1;
     }
   );
+
+  # List navi entries on top level
+  $mojo->helper(
+    'navi.list' => sub {
+      my $c = shift;
+      my $realm = shift;
+      my @list = ();
+
+      # Iterate over items
+      foreach (@{$navi->{$realm} // []}) {
+        # Fragments are not allowed on the top level - so ignore this!
+
+        # Generate url with query parameter inheritance
+        my $url = $c->url_with($realm, page => $_->{id});
+
+        # Canonicalize (for empty scopes)
+        $url->path->canonicalize;
+        $url->fragment('page-top');
+
+        push @list, {
+          url => $url,
+          title => $c->loc('Nav_' . $_->{id}, $_->{title})
+        };
+      };
+      return @list;
+    }
+  );
 }
 
 1;
diff --git a/t/navigation.t b/t/navigation.t
index bcb9c93..1f56c99 100644
--- a/t/navigation.t
+++ b/t/navigation.t
@@ -12,6 +12,8 @@
 
 # Establish test route
 $app->routes->get('/doc/:scope/:page')->to(cb => sub {}, scope => undef)->name('doc');
+$app->routes->get('/settings/:scope/:page')->to(cb => sub {}, scope => undef)->name('settings');
+
 
 # Load plugin to test
 $app->plugin('KalamarPages');
@@ -273,7 +275,27 @@
 like($render, qr!<a href="/doc/faq(?:#[^"]+)?">FAQ</a>!,
      'Path matches FAQ');
 
+# Create settings realm
+$app->navi->add(settings => (
+  'OAuth', 'oauth'
+));
 
+# Create settings realm
+$app->navi->add(settings => (
+  'Marketplace', 'marketplace'
+));
+
+$render = $app->navigation('settings');
+
+like($render, qr!/settings/oauth#page-top!);
+like($render, qr!/settings/marketplace#page-top!);
+
+my @list = $app->navi->list('settings');
+
+is($list[0]->{url}, '/settings/oauth#page-top');
+is($list[0]->{title}, 'OAuth');
+is($list[1]->{url}, '/settings/marketplace#page-top');
+is($list[1]->{title}, 'Marketplace');
 
 done_testing;