140 lines
4.2 KiB
Plaintext
140 lines
4.2 KiB
Plaintext
@using System.Diagnostics.CodeAnalysis
|
|
@using LucideBlazor
|
|
@using ShadcnBlazor.Sidebars
|
|
|
|
@inject NavigationManager Navigation
|
|
|
|
@implements IDisposable
|
|
|
|
@{
|
|
var url = new Uri(Navigation.Uri);
|
|
}
|
|
|
|
<Sidebar Variant="SidebarVariant.Sidebar" Collapsible="SidebarCollapsible.Icon">
|
|
<SidebarHeader>
|
|
<SidebarMenu>
|
|
<SidebarMenuItem>
|
|
<SidebarMenuButton>
|
|
<a href="/" class="flex flex-row items-center">
|
|
<img alt="Logo" src="/_content/Moonlight.Frontend/logo.svg" class="size-6"/>
|
|
<span class="ms-2.5 text-lg font-semibold">Moonlight</span>
|
|
</a>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
</SidebarMenu>
|
|
</SidebarHeader>
|
|
|
|
<SidebarContent>
|
|
@foreach (var group in Items.GroupBy(x => x.Group))
|
|
{
|
|
<SidebarGroup>
|
|
@if (!string.IsNullOrWhiteSpace(group.Key))
|
|
{
|
|
<SidebarGroupLabel>
|
|
@group.Key
|
|
</SidebarGroupLabel>
|
|
}
|
|
|
|
<SidebarGroupContent>
|
|
<SidebarMenu>
|
|
@foreach (var item in group)
|
|
{
|
|
var isActive = item.IsExactPath
|
|
? item.Path == url.LocalPath
|
|
: url.LocalPath.StartsWith(item.Path, StringComparison.OrdinalIgnoreCase);
|
|
|
|
<SidebarMenuItem @key="item">
|
|
<SidebarMenuButton IsActive="@isActive">
|
|
<Slot>
|
|
<a href="@item.Path" @attributes="context">
|
|
<DynamicComponent Type="item.IconType"/>
|
|
<span>@item.Name</span>
|
|
</a>
|
|
</Slot>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
}
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
}
|
|
</SidebarContent>
|
|
|
|
<SidebarFooter>
|
|
<NavUser/>
|
|
</SidebarFooter>
|
|
</Sidebar>
|
|
|
|
@code
|
|
{
|
|
private readonly List<SidebarItem> Items = new();
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
Items.AddRange([
|
|
new()
|
|
{
|
|
Name = "Overview",
|
|
IconType = typeof(LayoutDashboardIcon),
|
|
Path = "/",
|
|
IsExactPath = true
|
|
},
|
|
new()
|
|
{
|
|
Name = "Overview",
|
|
IconType = typeof(LayoutDashboardIcon),
|
|
Path = "/admin",
|
|
IsExactPath = true,
|
|
Group = "Admin"
|
|
},
|
|
new()
|
|
{
|
|
Name = "Users",
|
|
IconType = typeof(UsersRoundIcon),
|
|
Path = "/users",
|
|
IsExactPath = false,
|
|
Group = "Admin"
|
|
},
|
|
new()
|
|
{
|
|
Name = "Settings",
|
|
IconType = typeof(SettingsIcon),
|
|
Path = "/admin/settings",
|
|
IsExactPath = false,
|
|
Group = "Admin"
|
|
}
|
|
]);
|
|
|
|
Navigation.LocationChanged += OnLocationChanged;
|
|
}
|
|
|
|
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Ignored
|
|
}
|
|
}
|
|
|
|
private record SidebarItem
|
|
{
|
|
public string Name { get; set; }
|
|
public string Path { get; set; }
|
|
public bool IsExactPath { get; set; }
|
|
public string? Group { get; set; }
|
|
|
|
// Used to prevent the IL-Trimming from removing this type as its dynamically assigned a type and we
|
|
// need it to work properly
|
|
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
|
|
public Type IconType { get; set; }
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Navigation.LocationChanged -= OnLocationChanged;
|
|
}
|
|
} |