Implemented extendable system settings tab. Started implementing white labeling settings

This commit is contained in:
2026-02-21 22:20:51 +01:00
parent 94c1aac0ac
commit 9d557eea4e
13 changed files with 276 additions and 22 deletions

View File

@@ -0,0 +1,75 @@
@using LucideBlazor
@using Moonlight.Frontend.Helpers
@using Moonlight.Frontend.Services
@using Moonlight.Shared.Http
@using Moonlight.Shared.Http.Requests.Admin.Settings
@using Moonlight.Shared.Http.Responses.Admin.Settings
@using ShadcnBlazor.Extras.Common
@using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.Toasts
@using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs
@inject HttpClient HttpClient
@inject ToastService ToastService
@inject FrontendService FrontendService
<LazyLoader Load="LoadAsync">
<EnhancedEditForm Model="Request" OnValidSubmit="OnValidSubmit">
<DataAnnotationsValidator />
<FieldSet>
<FormValidationSummary />
<FieldGroup>
<Field>
<FieldLabel>Name</FieldLabel>
<TextInputField @bind-Value="Request.Name"/>
</Field>
</FieldGroup>
</FieldSet>
<SubmitButton ClassName="mt-3">
<SaveIcon/>
Save
</SubmitButton>
</EnhancedEditForm>
</LazyLoader>
@code
{
private SetWhiteLabelingDto Request;
private async Task LoadAsync(LazyLoader _)
{
var dto = await HttpClient.GetFromJsonAsync<WhiteLabelingDto>(
"api/admin/system/settings/whiteLabeling",
SerializationContext.Default.Options
);
Request = new SetWhiteLabelingDto()
{
Name = dto!.Name
};
}
private async Task<bool> OnValidSubmit(EditContext editContext, ValidationMessageStore validationMessageStore)
{
var response = await HttpClient.PostAsJsonAsync(
"api/admin/system/settings/whiteLabeling",
Request,
SerializationContext.Default.Options
);
if (response.IsSuccessStatusCode)
{
await FrontendService.ReloadAsync();
await ToastService.SuccessAsync("Setting", "Successfully updated white labeling settings");
return true;
}
await ProblemDetailsHelper.HandleProblemDetailsAsync(response, Request, validationMessageStore);
return false;
}
}

View File

@@ -4,18 +4,14 @@
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Moonlight.Shared
@using ShadcnBlazor.Buttons
@using ShadcnBlazor.Cards
@using ShadcnBlazor.Inputs
@using ShadcnBlazor.Tab
@using ShadcnBlazor.Labels
@inject NavigationManager Navigation
@inject IAuthorizationService AuthorizationService
<Tabs DefaultValue="@(Tab ?? "settings")" OnValueChanged="OnTabChanged">
<TabsList ClassName="inline-flex w-full lg:w-fit justify-start overflow-x-auto overflow-y-hidden">
<TabsTrigger Value="settings">
<TabsTrigger Value="settings" Disabled="@(!SettingsResult.Succeeded)">
<CogIcon />
Settings
</TabsTrigger>
@@ -27,7 +23,7 @@
<KeyIcon/>
API & API Keys
</TabsTrigger>
<TabsTrigger Value="diagnose">
<TabsTrigger Value="diagnose" Disabled="@(!DiagnoseResult.Succeeded)">
<HeartPulseIcon/>
Diagnose
</TabsTrigger>
@@ -36,19 +32,18 @@
Instance
</TabsTrigger>
</TabsList>
<TabsContent Value="settings">
<Card ClassName="mt-5">
<CardFooter ClassName="justify-end">
<Button>
<SaveIcon />
Save changes
</Button>
</CardFooter>
</Card>
</TabsContent>
<TabsContent Value="diagnose">
<Diagnose />
</TabsContent>
@if (SettingsResult.Succeeded)
{
<TabsContent Value="settings">
<Settings />
</TabsContent>
}
@if (DiagnoseResult.Succeeded)
{
<TabsContent Value="diagnose">
<Diagnose />
</TabsContent>
}
@if (ApiKeyAccess.Succeeded)
{
<TabsContent Value="apiKeys">
@@ -81,6 +76,8 @@
private AuthorizationResult ThemesAccess;
private AuthorizationResult InstanceResult;
private AuthorizationResult VersionsResult;
private AuthorizationResult SettingsResult;
private AuthorizationResult DiagnoseResult;
protected override async Task OnInitializedAsync()
{
@@ -90,6 +87,8 @@
ThemesAccess = await AuthorizationService.AuthorizeAsync(authState.User, Permissions.Themes.View);
InstanceResult = await AuthorizationService.AuthorizeAsync(authState.User, Permissions.System.Versions);
VersionsResult = await AuthorizationService.AuthorizeAsync(authState.User, Permissions.System.Instance);
SettingsResult = await AuthorizationService.AuthorizeAsync(authState.User, Permissions.System.Settings);
DiagnoseResult = await AuthorizationService.AuthorizeAsync(authState.User, Permissions.System.Diagnose);
}
private void OnTabChanged(string name)

View File

@@ -0,0 +1,52 @@
@using Microsoft.Extensions.Options
@using Moonlight.Frontend.Configuration
@using ShadcnBlazor.Cards
@using ShadcnBlazor.Sidebars
@inject IOptions<SystemSettingsOptions> Options
<div class="mt-5 flex flex-col md:flex-row gap-5">
<Card ClassName="flex py-2 grow-0 min-w-56 max-h-[65vh] md:min-h-[65vh]">
<CardContent ClassName="px-2 flex flex-col gap-y-1 h-full max-h-[65vh] overflow-y-auto scrollbar-thin">
@foreach (var menuPage in Pages)
{
<SidebarMenuButton @onclick="() => Navigate(menuPage)" IsActive="@(CurrentPage == menuPage)" ClassName="overflow-visible">
<DynamicComponent Type="@menuPage.IconComponentType" />
<span>@menuPage.Name</span>
</SidebarMenuButton>
}
</CardContent>
</Card>
@if (CurrentPage != null)
{
<Card ClassName="flex grow">
<CardHeader>
<CardTitle>@CurrentPage.Name</CardTitle>
<CardDescription>@CurrentPage.Description</CardDescription>
</CardHeader>
<CardContent>
<DynamicComponent Type="@CurrentPage.ComponentType" />
</CardContent>
</Card>
}
</div>
@code
{
private SystemSettingsPage[] Pages;
private SystemSettingsPage? CurrentPage;
protected override void OnInitialized()
{
Pages = Options
.Value
.Components
.OrderBy(x => x.Order)
.ToArray();
CurrentPage = Pages.FirstOrDefault();
}
private void Navigate(SystemSettingsPage page)
=> CurrentPage = page;
}