<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;

namespace Bit.Client.Web.BlazorUI
{
    public partial class BitNav : IDisposable
    {
        private string? selectedKey;
        [Inject] private NavigationManager navigationManager { get; set; }
        private bool SelectedKeyHasBeenSet;

        /// <summary>
        /// (Optional) The key of the nav item initially selected.
        /// </summary>
        [Parameter] public string? InitialSelectedKey { get; set; }

        /// <summary>
        /// The key of the nav item selected by caller
        /// </summary>
        [Parameter]
        public string? SelectedKey
        {
            get => selectedKey;
            set
            {
                if (value == selectedKey) return;
                selectedKey = value;
                SelectedKeyChanged.InvokeAsync(selectedKey);

                var currentUrl = NavLinkItems.Where(nli => nli.Links != null)
                    .SelectMany(sli => sli.Links)
                    .FirstOrDefault(sli => sli.Key.Contains(selectedKey))?.Key ?? string.Empty;

                if (!string.IsNullOrEmpty(currentUrl) && navigationManager.Uri.Contains(currentUrl))
                {
                    navigationManager.NavigateTo(currentUrl);
                }
            }
        }

        [Parameter] public EventCallback<string> SelectedKeyChanged { get; set; }

        /// <summary>
        /// Indicates whether the navigation component renders on top of other content in the UI
        /// </summary>
        [Parameter] public bool IsOnTop { get; set; }

        /// <summary>
        /// A collection of link items to display in the navigation bar
        /// </summary>
        [Parameter] public ICollection<BitNavLinkItem> NavLinkItems { get; set; } = new List<BitNavLinkItem>();

        /// <summary>
        /// Function callback invoked when the chevron on a link is clicked
        /// </summary>
        [Parameter] public EventCallback<BitNavLinkItem> OnLinkExpandClick { get; set; }

        /// <summary>
        /// Function callback invoked when a link in the navigation is clicked
        /// </summary>
        [Parameter] public EventCallback<BitNavLinkItem> OnLinkClick { get; set; }

        /// <summary>
        /// The template of the header for each nav item, which is a generic RenderFramgment that accepts a BitNavLinItem as input
        /// </summary>
        [Parameter] public RenderFragment<BitNavLinkItem>? HeaderTemplate { get; set; }

        protected override string RootElementClass => "bit-nav";


        protected override async Task OnInitializedAsync()
        {
            navigationManager.LocationChanged += OnLocationChanged;
            selectedKey = selectedKey ?? InitialSelectedKey;

            await base.OnInitializedAsync();
        }

        private void OnLocationChanged(object sender, LocationChangedEventArgs args)
        {
            var currentPage = navigationManager.Uri.Replace(navigationManager.BaseUri, string.Empty);

            string currentPageKey = NavLinkItems.Where(nli => nli.Links != null)
                .SelectMany(nli => nli.Links)
                .FirstOrDefault(l => l.Url.ToLower()
                    .Contains(currentPage.ToLower())
                    )?.Key ?? string.Empty;


            if (string.IsNullOrEmpty(currentPageKey)) return;

            SelectedKey = currentPageKey;
            StateHasChanged();
        }


        private async Task OnLinkExpand(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled) return;

            if (navLinkItem.Links?.Any() ?? false)
            {
                navLinkItem.IsExpanded = !navLinkItem.IsExpanded;
            }

            await OnLinkExpandClick.InvokeAsync(navLinkItem);
        }

        private async Task HandleLinkClick(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled) return;

            await OnLinkClick.InvokeAsync(navLinkItem);

            if (navLinkItem.Url.HasNoValue() && navLinkItem.Links.Any())
            {
                await OnLinkExpand(navLinkItem);
            }
        }

        private async Task HandleClick(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled) return;

            await navLinkItem.OnClick?.InvokeAsync();
        }

        protected override void RegisterComponentClasses()
        {
            ClassBuilder.Register(() => IsOnTop
                                            ? $"{RootElementClass}-top"
                                            : $"{RootElementClass}-no-top");
        }

        private string GetLinkClass(BitNavLinkItem navLinkItem)
        {
            var enabledClass = navLinkItem.Disabled ? "disabled" : "enabled";
            var hasUrlClass = navLinkItem.Url.HasNoValue() ? "nourl" : "hasurl";

            var mainStyle = $"bit-nav-link-{enabledClass}-{hasUrlClass}-{VisualClassRegistrar()}";
            var selectedClass = navLinkItem.Key == SelectedKey ? $"bit-nav-selected-{VisualClassRegistrar()}" : string.Empty;
            var hasIcon = navLinkItem.Icon.HasNoValue()
                            ? $"bit-nav-has-not-icon-{VisualClassRegistrar()}"
                            : $"bit-nav-has-icon-{VisualClassRegistrar()}";
            var isGroup = navLinkItem.IsGroup ? $"bit-nav-isgroup-{VisualClassRegistrar()}" : string.Empty;

            return $"{mainStyle} {selectedClass} {hasIcon} {isGroup}";
        }

        public void Dispose()
        {<commit_msg>fix the issue of BitNavLinkItem.OnClick (#814)<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Routing;

namespace Bit.Client.Web.BlazorUI
{
    public partial class BitNav : IDisposable
    {
        private string? selectedKey;
        [Inject] private NavigationManager navigationManager { get; set; }
        private bool SelectedKeyHasBeenSet;

        /// <summary>
        /// (Optional) The key of the nav item initially selected.
        /// </summary>
        [Parameter] public string? InitialSelectedKey { get; set; }

        /// <summary>
        /// The key of the nav item selected by caller
        /// </summary>
        [Parameter]
        public string? SelectedKey
        {
            get => selectedKey;
            set
            {
                if (value == selectedKey) return;
                selectedKey = value;
                SelectedKeyChanged.InvokeAsync(selectedKey);

                var currentUrl = NavLinkItems.Where(nli => nli.Links != null)
                    .SelectMany(sli => sli.Links)
                    .FirstOrDefault(sli => sli.Key.Contains(selectedKey))?.Key ?? string.Empty;

                if (!string.IsNullOrEmpty(currentUrl) && navigationManager.Uri.Contains(currentUrl))
                {
                    navigationManager.NavigateTo(currentUrl);
                }
            }
        }

        [Parameter] public EventCallback<string> SelectedKeyChanged { get; set; }

        /// <summary>
        /// Indicates whether the navigation component renders on top of other content in the UI
        /// </summary>
        [Parameter] public bool IsOnTop { get; set; }

        /// <summary>
        /// A collection of link items to display in the navigation bar
        /// </summary>
        [Parameter] public ICollection<BitNavLinkItem> NavLinkItems { get; set; } = new List<BitNavLinkItem>();

        /// <summary>
        /// Function callback invoked when the chevron on a link is clicked
        /// </summary>
        [Parameter] public EventCallback<BitNavLinkItem> OnLinkExpandClick { get; set; }

        /// <summary>
        /// Function callback invoked when a link in the navigation is clicked
        /// </summary>
        [Parameter] public EventCallback<BitNavLinkItem> OnLinkClick { get; set; }

        /// <summary>
        /// The template of the header for each nav item, which is a generic RenderFramgment that accepts a BitNavLinItem as input
        /// </summary>
        [Parameter] public RenderFragment<BitNavLinkItem>? HeaderTemplate { get; set; }

        protected override string RootElementClass => "bit-nav";


        protected override async Task OnInitializedAsync()
        {
            navigationManager.LocationChanged += OnLocationChanged;
            selectedKey = selectedKey ?? InitialSelectedKey;

            await base.OnInitializedAsync();
        }

        private void OnLocationChanged(object sender, LocationChangedEventArgs args)
        {
            var currentPage = navigationManager.Uri.Replace(navigationManager.BaseUri, string.Empty);

            string currentPageKey = NavLinkItems.Where(nli => nli.Links != null)
                .SelectMany(nli => nli.Links)
                .FirstOrDefault(l => l.Url.ToLower()
                    .Contains(currentPage.ToLower())
                    )?.Key ?? string.Empty;


            if (string.IsNullOrEmpty(currentPageKey)) return;

            SelectedKey = currentPageKey;
            StateHasChanged();
        }


        private async Task OnLinkExpand(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled) return;

            if (navLinkItem.Links?.Any() ?? false)
            {
                navLinkItem.IsExpanded = !navLinkItem.IsExpanded;
            }

            await OnLinkExpandClick.InvokeAsync(navLinkItem);
        }

        private async Task HandleLinkClick(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled) return;

            await OnLinkClick.InvokeAsync(navLinkItem);

            if (navLinkItem.Url.HasNoValue() && navLinkItem.Links.Any())
            {
                await OnLinkExpand(navLinkItem);
            }
        }

        private async Task HandleClick(BitNavLinkItem navLinkItem)
        {
            if (IsEnabled is false || navLinkItem.Disabled || navLinkItem.OnClick is null) return;

            await navLinkItem.OnClick?.InvokeAsync();
        }

        protected override void RegisterComponentClasses()
        {
            ClassBuilder.Register(() => IsOnTop
                                            ? $"{RootElementClass}-top"
                                            : $"{RootElementClass}-no-top");
        }

        private string GetLinkClass(BitNavLinkItem navLinkItem)
        {
            var enabledClass = navLinkItem.Disabled ? "disabled" : "enabled";
            var hasUrlClass = navLinkItem.Url.HasNoValue() ? "nourl" : "hasurl";

            var mainStyle = $"bit-nav-link-{enabledClass}-{hasUrlClass}-{VisualClassRegistrar()}";
            var selectedClass = navLinkItem.Key == SelectedKey ? $"bit-nav-selected-{VisualClassRegistrar()}" : string.Empty;
            var hasIcon = navLinkItem.Icon.HasNoValue()
                            ? $"bit-nav-has-not-icon-{VisualClassRegistrar()}"
                            : $"bit-nav-has-icon-{VisualClassRegistrar()}";
            var isGroup = navLinkItem.IsGroup ? $"bit-nav-isgroup-{VisualClassRegistrar()}" : string.Empty;

            return $"{mainStyle} {selectedClass} {hasIcon} {isGroup}";
        }

        public void Dispose()
        {
{'fraction_non_alphanumeric': 0.10064258423063564, 'fraction_numerical': 0.0002605071205279611, 'mean_word_length': 1.9576271186440677, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7661435', 'n_tokens_mistral': 2970, 'n_tokens_neox': 2871, 'n_words': 698}