Made sidebar item collection extendable via interface. Refactored settings to system

This commit is contained in:
2025-12-27 23:54:48 +01:00
parent 05c05f1b72
commit ba942b2f8f
7 changed files with 91 additions and 56 deletions

View File

@@ -0,0 +1,228 @@
@using LucideBlazor
@using Moonlight.Shared.Http.Responses.Admin
@using ShadcnBlazor.Accordions
@using ShadcnBlazor.Alerts
@using ShadcnBlazor.Buttons
@using ShadcnBlazor.Cards
@using ShadcnBlazor.Emptys
@using ShadcnBlazor.Extras.Common
@using ShadcnBlazor.Spinners
@inject HttpClient HttpClient
<div class="grid grid-cols-1 xl:grid-cols-2 gap-5 mt-5">
<div class="col-span-1">
<Card>
<CardHeader>
<CardTitle>Automatic diagnosis</CardTitle>
<CardDescription>
Use a diagnostic report to share configuration details and errors with Moonlight developers, with
sensitive data automatically censored.
</CardDescription>
</CardHeader>
<CardContent ClassName="flex flex-col gap-y-5">
<Alert
ClassName="w-full flex flex-row items-center gap-3 border-yellow-500/80 bg-yellow-500/5 text-yellow-500">
<div class="flex shrink-0 items-center">
<TriangleAlertIcon ClassName="size-6 text-yellow-500/60"/>
</div>
<div class="flex flex-1 items-center justify-between gap-4">
<div class="flex flex-col gap-0.5">
<AlertTitle>Notice</AlertTitle>
<AlertDescription ClassName="text-yellow-500/80">
Only share these reports with the moonlight developers or the corresponding plugin
developers.
Even though we do our best to censor sensitive data it may still contain information you
dont want a random person on the internet to know
</AlertDescription>
</div>
</div>
</Alert>
</CardContent>
<CardFooter ClassName="justify-end">
<WButtom OnClick="DiagnoseAsync">
<StethoscopeIcon/>
Start diagnostics
</WButtom>
</CardFooter>
</Card>
</div>
<div class="col-span-1">
<Card>
<CardContent ClassName="flex justify-center items-center">
@if (IsLoading)
{
<Spinner ClassName="size-10"/>
}
else
{
if (HasDiagnosed)
{
if (Entries.Length == 0)
{
<Empty>
<EmptyHeader>
<EmptyMedia Variant="EmptyMediaVariant.Icon">
<SearchIcon/>
</EmptyMedia>
<EmptyTitle>No results available</EmptyTitle>
<EmptyDescription>
Diagnosis didnt return any results
</EmptyDescription>
</EmptyHeader>
</Empty>
}
else
{
<Accordion
ClassName="w-full"
Type="AccordionType.Single">
@for (var i = 0; i < Entries.Length; i++)
{
var entry = Entries[i];
var textColor = entry.Level switch
{
DiagnoseLevel.Error => "text-destructive",
DiagnoseLevel.Warning => "text-yellow-300",
DiagnoseLevel.Healthy => "text-green-500"
};
<AccordionItem
ClassName="overflow-hidden border bg-background px-4 first:rounded-t-lg last:rounded-b-lg last:border-b"
Value="@($"diagnoseEntry{i}")">
<AccordionTrigger className="hover:no-underline">
<div class="flex items-center gap-3">
@switch (entry.Level)
{
case DiagnoseLevel.Error:
<CircleXIcon ClassName="@textColor"/>
break;
case DiagnoseLevel.Warning:
<TriangleAlertIcon ClassName="@textColor"/>
break;
case DiagnoseLevel.Healthy:
<CircleCheckIcon ClassName="@textColor"/>
break;
}
<div class="flex flex-col items-start text-left">
<span class="@textColor">
@entry.Title
</span>
<span class="text-sm text-muted-foreground">
@(string.Join(" / ", entry.Tags))
</span>
</div>
</div>
</AccordionTrigger>
<AccordionContent ClassName="ps-7">
<div class="text-muted-foreground flex flex-col gap-y-3">
@if (!string.IsNullOrWhiteSpace(entry.StackStrace))
{
<div
class="rounded-xl p-2.5 bg-black max-h-36 overflow-auto scrollbar-thin">
@entry.StackStrace
</div>
}
@if (!string.IsNullOrWhiteSpace(entry.Message))
{
<p>
@entry.Message
</p>
}
@if (
!string.IsNullOrWhiteSpace(entry.ReportUrl) ||
!string.IsNullOrWhiteSpace(entry.StackStrace) ||
!string.IsNullOrWhiteSpace(entry.SolutionUrl)
)
{
<div class="flex justify-end gap-x-1">
@if (!string.IsNullOrWhiteSpace(entry.StackStrace))
{
<Button Variant="ButtonVariant.Outline">
<CopyIcon/>
Copy
</Button>
}
@if (!string.IsNullOrWhiteSpace(entry.SolutionUrl))
{
<Button Variant="ButtonVariant.Outline">
<Slot>
<a href="@entry.SolutionUrl" @attributes="context">
<WrenchIcon/>
Show suggested solution
</a>
</Slot>
</Button>
}
@if (!string.IsNullOrWhiteSpace(entry.ReportUrl))
{
<Button Variant="ButtonVariant.Outline">
<Slot>
<a href="@entry.ReportUrl" @attributes="context">
<GitBranchIcon/>
Report on Github
</a>
</Slot>
</Button>
}
</div>
}
</div>
</AccordionContent>
</AccordionItem>
}
</Accordion>
}
}
else
{
<Empty>
<EmptyHeader>
<EmptyMedia Variant="EmptyMediaVariant.Icon">
<CircleQuestionMarkIcon/>
</EmptyMedia>
<EmptyTitle>No results available yet</EmptyTitle>
<EmptyDescription>
Press the start button to start the automatic diagnosis
</EmptyDescription>
</EmptyHeader>
</Empty>
}
}
</CardContent>
</Card>
</div>
</div>
@code
{
private bool IsLoading = false;
private bool HasDiagnosed = false;
private DiagnoseResultResponse[] Entries;
private async Task DiagnoseAsync()
{
IsLoading = true;
HasDiagnosed = false;
await InvokeAsync(StateHasChanged);
var results = await HttpClient.GetFromJsonAsync<DiagnoseResultResponse[]>("api/admin/system/diagnose");
Entries = results ?? [];
IsLoading = false;
HasDiagnosed = true;
await InvokeAsync(StateHasChanged);
}
}