< Summary

Information
Class: Chronicis.Client.Pages.Articles
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Pages/Articles.razor
Line coverage
0%
Covered lines: 0
Uncovered lines: 33
Coverable lines: 33
Total lines: 102
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
BuildRenderTree(...)0%2040%
get_Path()100%210%
OnInitializedAsync()0%620%
OnParametersSetAsync()0%620%
LoadArticleByPath()0%4260%
NavigateToArticle()0%2040%
OnTreeStateChanged()100%210%
Dispose()100%210%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Pages/Articles.razor

#LineLine coverage
 1@page "/article/{*Path}"
 2@attribute [Authorize]
 3@inject ITreeStateService TreeStateService
 4@inject IArticleApiService ArticleApi
 5@inject IQuoteService QuoteService
 6@inject NavigationManager Navigation
 7@implements IDisposable
 8
 9@code {
 10    private readonly ILogger<Articles> _logger;
 11
 12    // Direct constructor injection
 013    public Articles(ILogger<Articles> logger)
 14    {
 015        _logger = logger;
 016    }
 17}
 18
 019@if (TreeStateService.SelectedArticleId.HasValue && TreeStateService.SelectedArticleId.Value != Guid.Empty)
 20{
 21    <ArticleDetail />
 22}
 23else
 24{
 25    <MudPaper Elevation="2" Class="chronicis-article-card chronicis-fade-in">
 26        <h6>Loading article...</h6>
 27    </MudPaper>
 28}
 29
 30@code {
 31    [Parameter]
 032    public string? Path { get; set; }
 33
 34    protected override async Task OnInitializedAsync()
 35    {
 036        TreeStateService.OnStateChanged += OnTreeStateChanged;
 37
 38        // If URL has article path, load it
 039        if (!string.IsNullOrEmpty(Path))
 40        {
 041            await LoadArticleByPath(Path);
 42        }
 043    }
 44
 45    protected override async Task OnParametersSetAsync()
 46    {
 47        // Handle URL changes (browser back/forward)
 048        if (!string.IsNullOrEmpty(Path))
 49        {
 050            await LoadArticleByPath(Path);
 51        }
 052    }
 53
 54    private async Task LoadArticleByPath(string path)
 55    {
 56        try
 57        {
 058            var article = await ArticleApi.GetArticleByPathAsync(path);
 59
 060            if (article != null)
 61            {
 062                if (article.Id != TreeStateService.SelectedArticleId)
 63                {
 64                    // Expand path to article and select it
 065                    TreeStateService.ExpandPathToAndSelect(article.Id);
 66                }
 67            }
 68            else
 69            {
 70                // Article not found - redirect to dashboard
 071                _logger.LogWarningSanitized("Article not found for path: {Path}", path);
 072                Navigation.NavigateTo("/dashboard", replace: true);
 73            }
 074        }
 075        catch (Exception ex)
 76        {
 077            _logger.LogErrorSanitized(ex, "Error loading article by path: {Path}", path);
 078            Navigation.NavigateTo("/dashboard", replace: true);
 079        }
 080    }
 81
 82    private async Task NavigateToArticle(Guid articleId)
 83    {
 84        // Get the full article details to build path from breadcrumbs
 085        var article = await ArticleApi.GetArticleDetailAsync(articleId);
 086        if (article != null && article.Breadcrumbs.Any())
 87        {
 088            var path = string.Join("/", article.Breadcrumbs.Select(b => b.Slug));
 089            Navigation.NavigateTo($"/article/{path}");
 90        }
 091    }
 92
 93    private void OnTreeStateChanged()
 94    {
 095        InvokeAsync(StateHasChanged);
 096    }
 97
 98    public void Dispose()
 99    {
 0100        TreeStateService.OnStateChanged -= OnTreeStateChanged;
 0101    }
 102}