< Summary

Information
Class: Chronicis.Client.Components.Routing.ChronicisRouteView
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Routing/ChronicisRouteView.razor
Line coverage
0%
Covered lines: 0
Uncovered lines: 83
Coverable lines: 83
Total lines: 126
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
get_RouteData()100%210%
RenderPageWithLayout()0%4260%
RenderPageComponent(...)0%620%
DetermineLayoutType(...)0%2040%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Routing/ChronicisRouteView.razor

#LineLine coverage
 1@using Microsoft.AspNetCore.Components.Authorization
 2@using Microsoft.AspNetCore.Components.Routing
 3@using Microsoft.AspNetCore.Components.Rendering
 4@using Microsoft.AspNetCore.Authorization
 5
 6@*
 7    ChronicisRouteView - Custom route view that prevents layout flicker
 8
 9    This component intelligently determines which layout to use based on:
 10    1. Explicit @layout directive on the page (public pages with PublicLayout)
 11    2. [Authorize] attribute (authenticated pages get AuthenticatedLayout)
 12    3. Default to PublicLayout for pages without explicit layout or auth
 13
 14    This prevents the "flash" of AuthenticatedLayout on public pages.
 15
 16    It also provides a styled "Authorizing" screen instead of the default
 17    unstyled "Authorizing..." text.
 18*@
 19
 20<CascadingAuthenticationState>
 021    @RenderPageWithLayout()
 22</CascadingAuthenticationState>
 23
 24@code {
 25    [Parameter]
 026    public RouteData RouteData { get; set; } = default!;
 27
 028    private RenderFragment RenderPageWithLayout() => builder =>
 029    {
 030        var pageType = RouteData.PageType;
 031        var layoutType = DetermineLayoutType(pageType);
 032        var requiresAuth = pageType.GetCustomAttributes(typeof(AuthorizeAttribute), true).Any();
 033
 034        if (layoutType != null)
 035        {
 036            // Render with layout
 037            builder.OpenComponent<LayoutView>(0);
 038            builder.AddAttribute(1, "Layout", layoutType);
 039            builder.AddAttribute(2, "ChildContent", (RenderFragment)(contentBuilder =>
 040            {
 041                if (requiresAuth)
 042                {
 043                    // Use AuthorizeRouteView for pages with [Authorize]
 044                    contentBuilder.OpenComponent<AuthorizeRouteView>(0);
 045                    contentBuilder.AddAttribute(1, "RouteData", RouteData);
 046                    contentBuilder.AddAttribute(2, "Authorizing", (RenderFragment)(authorizingBuilder =>
 047                    {
 048                        authorizingBuilder.OpenComponent<AuthorizingScreen>(0);
 049                        authorizingBuilder.CloseComponent();
 050                    }));
 051                    contentBuilder.AddAttribute(3, "NotAuthorized", (RenderFragment<AuthenticationState>)(authState =>
 052                    {
 053                        return notAuthBuilder =>
 054                        {
 055                            notAuthBuilder.OpenComponent<RedirectToLogin>(0);
 056                            notAuthBuilder.CloseComponent();
 057                        };
 058                    }));
 059                    contentBuilder.CloseComponent();
 060                }
 061                else
 062                {
 063                    // Render public page directly
 064                    RenderPageComponent(contentBuilder, pageType, RouteData);
 065                }
 066            }));
 067            builder.CloseComponent();
 068        }
 069        else
 070        {
 071            // No layout specified
 072            if (requiresAuth)
 073            {
 074                builder.OpenComponent<AuthorizeRouteView>(0);
 075                builder.AddAttribute(1, "RouteData", RouteData);
 076                builder.AddAttribute(2, "Authorizing", (RenderFragment)(authorizingBuilder =>
 077                {
 078                    authorizingBuilder.OpenComponent<AuthorizingScreen>(0);
 079                    authorizingBuilder.CloseComponent();
 080                }));
 081                builder.AddAttribute(3, "NotAuthorized", (RenderFragment<AuthenticationState>)(authState =>
 082                {
 083                    return notAuthBuilder =>
 084                    {
 085                        notAuthBuilder.OpenComponent<RedirectToLogin>(0);
 086                        notAuthBuilder.CloseComponent();
 087                    };
 088                }));
 089                builder.CloseComponent();
 090            }
 091            else
 092            {
 093                RenderPageComponent(builder, pageType, RouteData);
 094            }
 095        }
 096    };
 97
 98    private void RenderPageComponent(RenderTreeBuilder builder, Type pageType, RouteData routeData)
 99    {
 0100        builder.OpenComponent(0, pageType);
 0101        foreach (var kvp in routeData.RouteValues)
 102        {
 0103            builder.AddAttribute(1, kvp.Key, kvp.Value);
 104        }
 0105        builder.CloseComponent();
 0106    }
 107
 108    private Type? DetermineLayoutType(Type pageType)
 109    {
 110        // Check if page has explicit @layout directive
 0111        var layoutAttribute = pageType.GetCustomAttributes(typeof(LayoutAttribute), true)
 0112            .OfType<LayoutAttribute>()
 0113            .FirstOrDefault();
 114
 0115        if (layoutAttribute != null)
 116        {
 0117            return layoutAttribute.LayoutType;
 118        }
 119
 120        // Check if page requires authentication
 0121        var requiresAuth = pageType.GetCustomAttributes(typeof(AuthorizeAttribute), true).Any();
 122
 123        // Default to AuthenticatedLayout for pages requiring auth, PublicLayout otherwise
 0124        return requiresAuth ? typeof(AuthenticatedLayout) : typeof(PublicLayout);
 125    }
 126}