< Summary

Information
Class: Chronicis.Client.Components.Articles.ArticleDetailWikiLinkAutocomplete
Assembly: Chronicis.Client
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Articles/ArticleDetailWikiLinkAutocomplete.razor
Line coverage
0%
Covered lines: 0
Uncovered lines: 41
Coverable lines: 41
Total lines: 142
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
BuildRenderTree(...)0%342180%
get_Suggestions()100%210%
get_Loading()100%210%
get_SelectedIndex()100%210%
get_SelectedIndexChanged()100%210%
get_OnSelect()100%210%
get_Position()100%210%
get_Query()100%210%
get_OnCreate()100%210%
get_IsExternalQuery()100%210%
OnSuggestionClick()100%210%
OnSuggestionHover()0%620%
OnCreateClick()100%210%
GetArticleName()0%620%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Client/Components/Articles/ArticleDetailWikiLinkAutocomplete.razor

#LineLine coverage
 1@*
 2    ArticleDetailWikiLinkAutocomplete Component
 3
 4    This is a legacy autocomplete implementation specifically for ArticleDetail.razor.
 5    It differs from the newer WikiLinkAutocomplete component (in Shared) which uses
 6    WikiLinkAutocompleteService for centralized state management.
 7
 8    Key differences:
 9    - Direct parameter-based control (no service dependency)
 10    - Custom positioning logic for inline editing
 11    - Create-new-article option in the autocomplete dropdown
 12
 13    TODO: Consider migrating ArticleDetail to use the service-based approach
 14*@
 15
 16@inject ILogger<WikiLinkAutocomplete> Logger
 17
 18<div class="wiki-link-autocomplete"
 19     style="left: @($"{Position.X}px"); top: @($"{Position.Y}px");">
 20
 021    @if (Loading)
 22    {
 23        <div class="wiki-link-loading">
 24            Searching...
 25        </div>
 26    }
 027    else if (!Suggestions.Any())
 28    {
 29        <div class="wiki-link-no-results">
 030            @if (Query.Length < 3)
 31            {
 32                <text>Type at least 3 characters to search</text>
 33            }
 34            else
 35            {
 036                @if (IsExternalQuery)
 37                {
 38                    <text>No results found</text>
 39                }
 40                else
 41                {
 42                    <text>No articles found</text>
 43                    <div class="wiki-link-create-option" @onclick="OnCreateClick">
 44                        <span class="wiki-link-create-icon">+</span>
 045                        Create "@GetArticleName()" in Wiki root
 46                    </div>
 47                }
 48            }
 49        </div>
 50    }
 51    else
 52    {
 053        @for (int i = 0; i < Suggestions.Count; i++)
 54        {
 055            var suggestion = Suggestions[i];
 056            var index = i;
 057            var isSelected = index == SelectedIndex;
 58
 59            <div class="wiki-link-suggestion @(isSelected ? "selected" : "")"
 060                 @onclick="() => OnSuggestionClick(suggestion)"
 061                 @onmouseenter="() => OnSuggestionHover(index)">
 62                <div class="wiki-link-suggestion-title">
 063                    @suggestion.DisplayTitle
 064                    @if (suggestion.IsExternal && !string.IsNullOrWhiteSpace(suggestion.SourceBadge))
 65                    {
 066                        <span class="wiki-link-suggestion-badge">@suggestion.SourceBadge</span>
 67                    }
 68                </div>
 069                @if (!string.IsNullOrWhiteSpace(suggestion.SecondaryText))
 70                {
 071                    <div class="wiki-link-suggestion-path">@suggestion.SecondaryText</div>
 72                }
 73            </div>
 74        }
 75    }
 76</div>
 77
 78@code {
 79    [Parameter]
 080    public List<WikiLinkAutocompleteItem> Suggestions { get; set; } = new();
 81
 82    [Parameter]
 083    public bool Loading { get; set; }
 84
 85    [Parameter]
 086    public int SelectedIndex { get; set; }
 87
 88    [Parameter]
 089    public EventCallback<int> SelectedIndexChanged { get; set; }
 90
 91    [Parameter]
 092    public EventCallback<WikiLinkAutocompleteItem> OnSelect { get; set; }
 93
 94    [Parameter]
 095    public (double X, double Y) Position { get; set; }
 96
 97    [Parameter]
 098    public string Query { get; set; } = string.Empty;
 99
 100    [Parameter]
 0101    public EventCallback<string> OnCreate { get; set; }
 102
 103    [Parameter]
 0104    public bool IsExternalQuery { get; set; }
 105
 106    private async Task OnSuggestionClick(WikiLinkAutocompleteItem suggestion)
 107    {
 0108        Logger.LogDebug("WikiLinkAutocomplete: OnSuggestionClick called for {Title}", suggestion.Title);
 0109        await OnSelect.InvokeAsync(suggestion);
 0110        Logger.LogDebug("WikiLinkAutocomplete: OnSelect.InvokeAsync completed");
 0111    }
 112
 113    private async Task OnSuggestionHover(int index)
 114    {
 0115        if (SelectedIndex != index)
 116        {
 0117            await SelectedIndexChanged.InvokeAsync(index);
 118        }
 0119    }
 120
 121    private async Task OnCreateClick()
 122    {
 0123        var articleName = GetArticleName();
 0124        Logger.LogDebug("WikiLinkAutocomplete: OnCreateClick called for {Name}", articleName);
 0125        await OnCreate.InvokeAsync(articleName);
 0126    }
 127
 128    private string GetArticleName()
 129    {
 130        // If query contains path separators, extract just the article name (last segment)
 0131        var segments = Query.Split('/');
 0132        var name = segments.Last().Trim();
 133
 134        // Capitalize first letter
 0135        if (!string.IsNullOrEmpty(name))
 136        {
 0137            name = char.ToUpper(name[0]) + name.Substring(1);
 138        }
 139
 0140        return name;
 141    }
 142}