You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(routing): not-found page for unknown URLs; menu editor warns about links that match no route (#8103) - #8108
A URL that matches no route now shows a "Page not found" page (da: "Siden blev ikke fundet") instead of silently redirecting to My eForms. The page shows the requested URL, which stays in the address bar, and has a button to the start page.
The menu editor warns when an internal link matches no route:
a hint under the link field in the custom-link and edit dialogs;
a warning icon on menu rows whose link matches no route.
The edit dialog offers "Restore default link" for an entry created from a plugin template whose link was changed.
Root cause
app.routing.ts ended with {path: '**', redirectTo: ''}. A menu entry with a wrong link therefore opened My eForms, with no hint that anything was wrong:
a plugin link saved without the /plugins prefix;
a link to a removed plugin route.
The menu editor accepted such links without checking them.
Details
** now renders NotFoundComponent inside FullLayoutComponent, behind IsAuthGuard (logged-out visitors still go to login). It must stay the last app route: AppModule also imports PluginsModule eagerly, so plugin routes are appended at root level after it, where nothing can reach them. This is why a plugin link without /plugins lands on the not-found page.
linkMatchesRoute (common/helpers/route-match.helper.ts) walks the router config in the router's first-match order and stops at **. Lazy modules are not loaded for the check:
A matched lazy route vouches for the paths under it.
The plugin routes (plugins.routing.ts) and My eForms' sub-modules are supplied up front. The sub-modules come from the new side-effect-free eforms-route-paths.ts, which eforms.routing.ts now also uses.
A menu template's default link always passes.
External links are not checked.
"Restore default link" only looks in plugin templates. A core item dragged in but not yet saved carries RelatedTemplateItemId = 1, not its own id.
Five new translation keys, translated into all 26 languages.
Not done: the issue's optional part 3 (record who saved the menu, single-transaction save) needs backend work and is left for a separate change.
…ns about links that match no route (#8103)
A URL that matched no route was redirected to My eForms by the catch-all
`{path: '**', redirectTo: ''}`, so a menu entry with a wrong link (a plugin
link without the /plugins prefix, a removed plugin route) silently opened
My eForms, and the menu editor accepted such links without a word.
- The catch-all now renders a "Page not found" page inside the full layout,
showing the requested URL (which stays in the address bar) and a button to
the start page. Logged-out visitors are still sent to login.
- The menu editor checks internal links against the app's routes: a warning
under the link field in the custom-link and edit dialogs, and a warning
icon on menu rows whose link matches no route. Lazy modules are not
loaded for this; a matched lazy route vouches for the paths under it, with
the plugin routes and My eForms' sub-modules supplied up front. A menu
template's default link always passes.
- The edit dialog offers "Restore default link" for an entry created from a
plugin template whose link was changed.
- Five new translation keys in every language.
Refs #8103
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
Warning
Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds a proper “not found” experience for unknown URLs and improves the navigation menu editor by warning when internal links don’t match any reachable route, reducing silent misnavigation (e.g., bad plugin links without /plugins).
Changes:
Replace the wildcard redirect with a guarded NotFoundComponent so unknown URLs render a “Page not found” page while keeping the original URL.
Introduce route-walk helpers/services (linkMatchesRoute, MenuLinkRouteService) and wire them into menu editor UI (warnings + “Restore default link”).
…8103)
mat-icon is aria-hidden by default; the warning icon now has role="img",
aria-hidden="false" and the translated warning as its aria-label, so
screen reader users hear it too.
Refs #8103
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The default-link lookup stops working after the menu is saved and reloaded. The API rebuilds link items in SimpleLinkBehavior, where assigning MenuTemplateId is commented out, so GetCurrentNavigationMenu subsequently returns relatedTemplateItemId: null; this lookup then cannot identify the plugin template and the promised “Restore default link” action disappears. Preserve or reconstruct the plugin template relationship during menu persistence (without assigning the core template's placeholder id) and cover the save/reload case.
The reason will be displayed to describe this comment to others. Learn more.
Set aside: no provider is missing. Router is @Injectable({providedIn: 'root'}) in @angular/router 20, so TestBed builds one (with an empty route config) without provideRouter. The test-angular-unit check on this PR ran this spec and it passes (PASS …/navigation-menu-custom-link.component.spec.ts, 41/41 suites).
The reason will be displayed to describe this comment to others. Learn more.
Set aside, same as on the custom-link spec: Router is root-provided in @angular/router 20, so the TestBed injects a Router with no routes — which is exactly what the #8103 link-check tests rely on ("The TestBed router has no routes"). test-angular-unit on this PR passes this spec, including the new assertions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Root cause
app.routing.tsended with{path: '**', redirectTo: ''}. A menu entry with a wrong link therefore opened My eForms, with no hint that anything was wrong:/pluginsprefix;The menu editor accepted such links without checking them.
Details
**now rendersNotFoundComponentinsideFullLayoutComponent, behindIsAuthGuard(logged-out visitors still go to login). It must stay the last app route: AppModule also importsPluginsModuleeagerly, so plugin routes are appended at root level after it, where nothing can reach them. This is why a plugin link without/pluginslands on the not-found page.linkMatchesRoute(common/helpers/route-match.helper.ts) walks the router config in the router's first-match order and stops at**. Lazy modules are not loaded for the check:plugins.routing.ts) and My eForms' sub-modules are supplied up front. The sub-modules come from the new side-effect-freeeforms-route-paths.ts, whicheforms.routing.tsnow also uses.RelatedTemplateItemId = 1, not its own id.Tests
Tests/c/navigation-menu.unknown-route.spec.ts:/pluginsboth show the not-found page and keep the URL; the start-page button works./no-such-page, does not warn for/advanced/sites, and drops the warning when the link is made external.route-match.helper.spec.ts: route-walk cases, including My eForms sub-pages and plugin prefixes.navigation-menu-item-edit.component.spec.ts: the warning, an external link, a template default link, and "Restore default link".Not verified
ng build --configuration developmentpasses) with the API proxied to a local app.tscandcheck-button-conventions.jsare clean.Refs #8103
🤖 Generated with Claude Code