2 Commits

17 changed files with 397 additions and 404 deletions

View File

@@ -24,8 +24,8 @@
<PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.1"/> <PackageReference Include="Microsoft.AspNetCore.Components.Authorization" Version="10.0.1"/>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1"/> <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="10.0.1"/>
<PackageReference Include="Riok.Mapperly" Version="4.3.1-next.0"/> <PackageReference Include="Riok.Mapperly" Version="4.3.1-next.0"/>
<PackageReference Include="ShadcnBlazor" Version="1.0.10" /> <PackageReference Include="ShadcnBlazor" Version="1.0.11" />
<PackageReference Include="ShadcnBlazor.Extras" Version="1.0.10" /> <PackageReference Include="ShadcnBlazor.Extras" Version="1.0.11" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,10 +1,9 @@
@using Moonlight.Frontend.UI.Admin.Components @using Moonlight.Frontend.UI.Admin.Components
@using Moonlight.Shared.Http.Requests.ApiKeys @using Moonlight.Shared.Http.Requests.ApiKeys
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -15,56 +14,57 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="SubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6">
<FieldGroup>
<DataAnnotationsValidator/>
<FormValidationSummary/> <FormValidationSummary/>
<div class="grid gap-2"> <FieldSet>
<Label for="keyName">Name</Label> <Field>
<FieldLabel for="keyName">Name</FieldLabel>
<TextInputField @bind-Value="Request.Name" id="keyName" placeholder="My API key"/> <TextInputField @bind-Value="Request.Name" id="keyName" placeholder="My API key"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="keyDescription">Description</FieldLabel>
<Label for="keyDescription">Description</Label> <TextareaInputField @bind-Value="Request.Description" id="keyDescription" placeholder="What this key is for"/>
<textarea </Field>
@bind="Request.Description" <Field>
id="keyDescription" <FieldLabel>Permissions</FieldLabel>
maxlength="100" <FieldContent>
class="border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm"
placeholder="What this key is for">
</textarea>
</div>
<div class="grid gap-2">
<Label>Permissions</Label>
<PermissionSelector Permissions="Permissions"/> <PermissionSelector Permissions="Permissions"/>
</div> </FieldContent>
</div> </Field>
</FormHandler> </FieldSet>
<Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<DialogFooter ClassName="justify-end gap-x-1"> <SubmitButton>Save changes</SubmitButton>
<WButtom OnClick="() => FormHandler.SubmitAsync()">Save changes</WButtom> </Field>
</DialogFooter> </FieldGroup>
</EnhancedEditForm>
@code @code
{ {
[Parameter] public Func<CreateApiKeyDto, Task> OnSubmit { get; set; } [Parameter] public Func<CreateApiKeyDto, Task> OnSubmit { get; set; }
private CreateApiKeyDto Request; private CreateApiKeyDto Request;
private FormHandler FormHandler;
private List<string> Permissions = new(); private List<string> Permissions = new();
protected override void OnInitialized() protected override void OnInitialized()
{ {
Request = new(); Request = new()
{
Permissions = []
};
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.Permissions = Permissions.ToArray(); Request.Permissions = Permissions.ToArray();
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -1,11 +1,9 @@
@using Moonlight.Frontend.UI.Admin.Components @using Moonlight.Frontend.UI.Admin.Components
@using Moonlight.Shared.Http.Requests.Roles @using Moonlight.Shared.Http.Requests.Roles
@using ShadcnBlazor.Buttons
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -18,41 +16,36 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="OnSubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6"> <FieldGroup>
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid gap-2"> <FieldSet>
<Label for="roleName">Name</Label> <Field>
<FieldLabel for="roleName">Name</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Name" @bind-Value="Request.Name"
id="roleName" id="roleName"
placeholder="My fancy role"/> placeholder="My fancy role"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="keyDescription">Description</FieldLabel>
<Label for="roleDescription">Description</Label> <TextareaInputField @bind-Value="Request.Description" id="keyDescription"
<textarea placeholder="Describe what the role should be used for"/>
@bind="Request.Description" </Field>
id="roleDescription" <Field>
maxlength="100" <FieldLabel>Permissions</FieldLabel>
class="border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm" <FieldContent>
placeholder="Describe what the role should be used for">
</textarea>
</div>
<div class="grid gap-2">
<Label>Permissions</Label>
<PermissionSelector Permissions="Permissions"/> <PermissionSelector Permissions="Permissions"/>
</div> </FieldContent>
</div> </Field>
</FormHandler> </FieldSet>
<Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<DialogFooter ClassName="justify-end gap-x-1"> <SubmitButton>Save changes</SubmitButton>
<WButtom OnClick="SubmitAsync">Save changes</WButtom> </Field>
</DialogFooter> </FieldGroup>
</EnhancedEditForm>
@code @code
{ {
@@ -60,7 +53,6 @@
private CreateRoleDto Request; private CreateRoleDto Request;
private List<string> Permissions; private List<string> Permissions;
private FormHandler FormHandler;
protected override void OnInitialized() protected override void OnInitialized()
{ {
@@ -72,15 +64,13 @@
Permissions = new(); Permissions = new();
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.Permissions = Permissions.ToArray(); Request.Permissions = Permissions.ToArray();
await FormHandler.SubmitAsync();
}
private async Task OnSubmitAsync()
{
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -1,9 +1,8 @@
@using Moonlight.Shared.Http.Requests.Users @using Moonlight.Shared.Http.Requests.Users
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -16,50 +15,50 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="SubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6">
<FieldGroup>
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid gap-2"> <FieldSet>
<Label for="username">Username</Label> <Field>
<FieldLabel for="username">Username</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Username" @bind-Value="Request.Username"
id="username" id="username"
placeholder="Name of the user"/> placeholder="Name of the user"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="emailAddress">Email Address</FieldLabel>
<Label for="emailAddress">Email Address</Label>
<TextInputField <TextInputField
@bind-Value="Request.Email" @bind-Value="Request.Email"
id="emailAddress" id="emailAddress"
Type="email"
placeholder="email@of.user"/> placeholder="email@of.user"/>
</div> </Field>
</div> </FieldSet>
</FormHandler> <Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<SubmitButton>Save changes</SubmitButton>
<DialogFooter ClassName="justify-end gap-x-1"> </Field>
<WButtom OnClick="_ => FormHandler.SubmitAsync()">Save changes</WButtom> </FieldGroup>
</DialogFooter> </EnhancedEditForm>
@code @code
{ {
[Parameter] public Func<CreateUserDto, Task> OnSubmit { get; set; } [Parameter] public Func<CreateUserDto, Task> OnSubmit { get; set; }
private CreateUserDto Request; private CreateUserDto Request;
private FormHandler FormHandler;
protected override void OnInitialized() protected override void OnInitialized()
{ {
Request = new(); Request = new();
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -32,9 +32,9 @@
SearchPlaceholder="Search user" SearchPlaceholder="Search user"
ValueSelector="dto => dto.Username" ValueSelector="dto => dto.Username"
Source="LoadUsersAsync"/> Source="LoadUsersAsync"/>
<WButtom OnClick="AddAsync" Variant="ButtonVariant.Outline" Size="ButtonSize.Icon"> <WButton OnClick="AddAsync" Variant="ButtonVariant.Outline" Size="ButtonSize.Icon">
<PlusIcon/> <PlusIcon/>
</WButtom> </WButton>
</div> </div>
</div> </div>
<div class="mt-3"> <div class="mt-3">
@@ -50,9 +50,9 @@
<CellTemplate> <CellTemplate>
<TableCell> <TableCell>
<div class="flex justify-end me-1.5"> <div class="flex justify-end me-1.5">
<WButtom OnClick="_ => RemoveAsync(context)" Variant="ButtonVariant.Destructive" Size="ButtonSize.Icon"> <WButton OnClick="_ => RemoveAsync(context)" Variant="ButtonVariant.Destructive" Size="ButtonSize.Icon">
<TrashIcon/> <TrashIcon/>
</WButtom> </WButton>
</div> </div>
</TableCell> </TableCell>
</CellTemplate> </CellTemplate>

View File

@@ -3,10 +3,9 @@
@using Moonlight.Shared.Http.Requests.ApiKeys @using Moonlight.Shared.Http.Requests.ApiKeys
@using Moonlight.Shared.Http.Responses.ApiKeys @using Moonlight.Shared.Http.Responses.ApiKeys
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -17,37 +16,32 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="SubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6"> <FieldGroup>
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid gap-2"> <FieldSet>
<Label for="keyName">Name</Label> <Field>
<FieldLabel for="keyName">Name</FieldLabel>
<TextInputField @bind-Value="Request.Name" id="keyName" placeholder="My API key"/> <TextInputField @bind-Value="Request.Name" id="keyName" placeholder="My API key"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="keyDescription">Description</FieldLabel>
<Label for="keyDescription">Description</Label> <TextareaInputField @bind-Value="Request.Description" id="keyDescription" placeholder="What this key is for"/>
<textarea </Field>
@bind="Request.Description" <Field>
id="keyDescription" <FieldLabel>Permissions</FieldLabel>
maxlength="100" <FieldContent>
class="border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm"
placeholder="What this key is for">
</textarea>
</div>
<div class="grid gap-2">
<Label>Permissions</Label>
<PermissionSelector Permissions="Permissions"/> <PermissionSelector Permissions="Permissions"/>
</div> </FieldContent>
</div> </Field>
</FormHandler> </FieldSet>
<Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<DialogFooter ClassName="justify-end gap-x-1"> <SubmitButton>Save changes</SubmitButton>
<WButtom OnClick="_ => FormHandler.SubmitAsync()">Save changes</WButtom> </Field>
</DialogFooter> </FieldGroup>
</EnhancedEditForm>
@code @code
{ {
@@ -55,7 +49,6 @@
[Parameter] public ApiKeyDto Key { get; set; } [Parameter] public ApiKeyDto Key { get; set; }
private UpdateApiKeyDto Request; private UpdateApiKeyDto Request;
private FormHandler FormHandler;
private List<string> Permissions = new(); private List<string> Permissions = new();
protected override void OnInitialized() protected override void OnInitialized()
@@ -64,10 +57,12 @@
Permissions = Key.Permissions.ToList(); Permissions = Key.Permissions.ToList();
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.Permissions = Permissions.ToArray(); Request.Permissions = Permissions.ToArray();
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -12,7 +12,7 @@
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>
Updating instance... Updating instance to @Version...
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
@@ -75,6 +75,8 @@ else
@code @code
{ {
[Parameter] public string Version { get; set; }
private int Progress; private int Progress;
private int CurrentStep; private int CurrentStep;

View File

@@ -2,12 +2,10 @@
@using Moonlight.Frontend.UI.Admin.Components @using Moonlight.Frontend.UI.Admin.Components
@using Moonlight.Shared.Http.Requests.Roles @using Moonlight.Shared.Http.Requests.Roles
@using Moonlight.Shared.Http.Responses.Admin @using Moonlight.Shared.Http.Responses.Admin
@using ShadcnBlazor.Buttons
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -20,41 +18,36 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="OnSubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6"> <FieldGroup>
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid gap-2"> <FieldSet>
<Label for="roleName">Name</Label> <Field>
<FieldLabel for="roleName">Name</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Name" @bind-Value="Request.Name"
id="roleName" id="roleName"
placeholder="My fancy role"/> placeholder="My fancy role"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="keyDescription">Description</FieldLabel>
<Label for="roleDescription">Description</Label> <TextareaInputField @bind-Value="Request.Description" id="keyDescription"
<textarea placeholder="Describe what the role should be used for"/>
@bind="Request.Description" </Field>
id="roleDescription" <Field>
maxlength="100" <FieldLabel>Permissions</FieldLabel>
class="border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm" <FieldContent>
placeholder="Describe what the role should be used for">
</textarea>
</div>
<div class="grid gap-2">
<Label>Permissions</Label>
<PermissionSelector Permissions="Permissions"/> <PermissionSelector Permissions="Permissions"/>
</div> </FieldContent>
</div> </Field>
</FormHandler> </FieldSet>
<Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<DialogFooter ClassName="justify-end gap-x-1"> <SubmitButton>Save changes</SubmitButton>
<WButtom OnClick="SubmitAsync">Save changes</WButtom> </Field>
</DialogFooter> </FieldGroup>
</EnhancedEditForm>
@code @code
{ {
@@ -63,7 +56,6 @@
private UpdateRoleDto Request; private UpdateRoleDto Request;
private List<string> Permissions; private List<string> Permissions;
private FormHandler FormHandler;
protected override void OnInitialized() protected override void OnInitialized()
{ {
@@ -71,15 +63,12 @@
Permissions = Role.Permissions.ToList(); Permissions = Role.Permissions.ToList();
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.Permissions = Permissions.ToArray(); Request.Permissions = Permissions.ToArray();
await FormHandler.SubmitAsync();
}
private async Task OnSubmitAsync()
{
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -2,10 +2,9 @@
@using Moonlight.Shared.Http.Requests.Users @using Moonlight.Shared.Http.Requests.Users
@using Moonlight.Shared.Http.Responses.Users @using Moonlight.Shared.Http.Responses.Users
@using ShadcnBlazor.Dialogs @using ShadcnBlazor.Dialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Labels
@inherits ShadcnBlazor.Extras.Dialogs.DialogBase @inherits ShadcnBlazor.Extras.Dialogs.DialogBase
@@ -18,33 +17,32 @@
</DialogDescription> </DialogDescription>
</DialogHeader> </DialogHeader>
<FormHandler @ref="FormHandler" Model="Request" OnValidSubmit="SubmitAsync"> <EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync">
<div class="flex flex-col gap-6"> <FieldGroup>
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid gap-2"> <FieldSet>
<Label for="username">Username</Label> <Field>
<FieldLabel for="username">Username</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Username" @bind-Value="Request.Username"
id="username" id="username"
placeholder="Name of the user"/> placeholder="Name of the user"/>
</div> </Field>
<Field>
<div class="grid gap-2"> <FieldLabel for="emailAddress">Email Address</FieldLabel>
<Label for="emailAddress">Email Address</Label>
<TextInputField <TextInputField
@bind-Value="Request.Email" @bind-Value="Request.Email"
id="emailAddress" id="emailAddress"
Type="email"
placeholder="email@of.user"/> placeholder="email@of.user"/>
</div> </Field>
</div> </FieldSet>
</FormHandler> <Field Orientation="FieldOrientation.Horizontal" ClassName="justify-end">
<SubmitButton>Save changes</SubmitButton>
<DialogFooter ClassName="justify-end gap-x-1"> </Field>
<WButtom OnClick="_ => FormHandler.SubmitAsync()">Save changes</WButtom> </FieldGroup>
</DialogFooter> </EnhancedEditForm>
@code @code
{ {
@@ -52,17 +50,17 @@
[Parameter] public UserDto User { get; set; } [Parameter] public UserDto User { get; set; }
private UpdateUserDto Request; private UpdateUserDto Request;
private FormHandler FormHandler;
protected override void OnInitialized() protected override void OnInitialized()
{ {
Request = UserMapper.ToUpdate(User); Request = UserMapper.ToUpdate(User);
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
await OnSubmit.Invoke(Request); await OnSubmit.Invoke(Request);
await CloseAsync(); await CloseAsync();
return true;
} }
} }

View File

@@ -133,7 +133,11 @@
{ {
<CardTitle ClassName="text-lg text-primary">Update available</CardTitle> <CardTitle ClassName="text-lg text-primary">Update available</CardTitle>
<CardAction ClassName="self-center"> <CardAction ClassName="self-center">
<Button @onclick="LaunchUpdateModalAsync">Update</Button> <Button>
<Slot>
<a href="/admin/system?tab=instance" @attributes="context">Update</a>
</Slot>
</Button>
</CardAction> </CardAction>
} }
</CardHeader> </CardHeader>
@@ -156,10 +160,4 @@
await InvokeAsync(StateHasChanged); await InvokeAsync(StateHasChanged);
} }
private async Task LaunchUpdateModalAsync() => await DialogService.LaunchAsync<UpdateInstanceModal>(onConfigure: model =>
{
model.ShowCloseButton = false;
model.ClassName = "sm:max-w-4xl!";
});
} }

View File

@@ -44,10 +44,10 @@
</Alert> </Alert>
</CardContent> </CardContent>
<CardFooter ClassName="justify-end"> <CardFooter ClassName="justify-end">
<WButtom OnClick="DiagnoseAsync" disabled="@(!AccessResult.Succeeded)"> <WButton OnClick="DiagnoseAsync" disabled="@(!AccessResult.Succeeded)">
<StethoscopeIcon/> <StethoscopeIcon/>
Start diagnostics Start diagnostics
</WButtom> </WButton>
</CardFooter> </CardFooter>
</Card> </Card>
</div> </div>

View File

@@ -38,14 +38,6 @@
</TabsList> </TabsList>
<TabsContent Value="settings"> <TabsContent Value="settings">
<Card ClassName="mt-5"> <Card ClassName="mt-5">
<CardContent>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-5">
<div class="col-span-1 grid gap-3">
<Label for="instance-name">Instance Name</Label>
<TextInputField id="instance-name" />
</div>
</div>
</CardContent>
<CardFooter ClassName="justify-end"> <CardFooter ClassName="justify-end">
<Button> <Button>
<SaveIcon /> <SaveIcon />

View File

@@ -1,13 +1,18 @@
@using LucideBlazor @using LucideBlazor
@using Moonlight.Frontend.UI.Admin.Modals
@using Moonlight.Shared.Http.Responses.Admin @using Moonlight.Shared.Http.Responses.Admin
@using ShadcnBlazor.Cards @using ShadcnBlazor.Cards
@using ShadcnBlazor.Emptys @using ShadcnBlazor.Emptys
@using ShadcnBlazor.Buttons @using ShadcnBlazor.Buttons
@using ShadcnBlazor.Extras.AlertDialogs
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Common
@using ShadcnBlazor.Extras.Dialogs
@using ShadcnBlazor.Fields @using ShadcnBlazor.Fields
@using ShadcnBlazor.Selects @using ShadcnBlazor.Selects
@inject HttpClient HttpClient @inject HttpClient HttpClient
@inject DialogService DialogService
@inject AlertDialogService AlertDialogService
<div class="mt-5"> <div class="mt-5">
<LazyLoader Load="LoadAsync"> <LazyLoader Load="LoadAsync">
@@ -23,26 +28,25 @@
<CardContent> <CardContent>
<FieldGroup> <FieldGroup>
<FieldSet> <FieldSet>
<FieldLegend>Update instance</FieldLegend>
<FieldDescription>
Select the version you want to update to
</FieldDescription>
<Field> <Field>
<FieldLabel> <FieldLabel>
Version Version
</FieldLabel> </FieldLabel>
<Select DefaultValue="Testy"> <FieldContent>
<SelectTrigger> <Select DefaultValue="@SelectedVersion" @bind-Value="SelectedVersion">
<SelectTrigger ClassName="w-64">
<SelectValue/> <SelectValue/>
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent ClassName="w-64">
<SelectItem Value="Testy">Testy</SelectItem> <SelectItem Value="v2.1">v2.1</SelectItem>
<SelectItem Value="v2.1.1">v2.1.1</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</FieldContent>
</Field> </Field>
</FieldSet> </FieldSet>
<Field Orientation="FieldOrientation.Horizontal"> <Field Orientation="FieldOrientation.Horizontal">
<Button>Apply</Button> <Button @onclick="ApplyAsync">Apply</Button>
</Field> </Field>
</FieldGroup> </FieldGroup>
</CardContent> </CardContent>
@@ -103,9 +107,29 @@
@code @code
{ {
private ContainerHelperStatusDto StatusDto; private ContainerHelperStatusDto StatusDto;
private string SelectedVersion = "v2.1";
private async Task LoadAsync(LazyLoader _) private async Task LoadAsync(LazyLoader _)
{ {
StatusDto = (await HttpClient.GetFromJsonAsync<ContainerHelperStatusDto>("api/admin/ch/status"))!; StatusDto = (await HttpClient.GetFromJsonAsync<ContainerHelperStatusDto>("api/admin/ch/status"))!;
} }
private async Task ApplyAsync()
{
await AlertDialogService.ConfirmDangerAsync(
"Moonlight Rebuild",
"If you continue the moonlight instance will become unavailable during the rebuild process. This will impact users on this instance",
async () =>
{
await DialogService.LaunchAsync<UpdateInstanceModal>(
parameters => { parameters[nameof(UpdateInstanceModal.Version)] = SelectedVersion; },
onConfigure: model =>
{
model.ShowCloseButton = false;
model.ClassName = "sm:max-w-4xl!";
}
);
}
);
}
} }

View File

@@ -6,11 +6,11 @@
@using Moonlight.Frontend.Services @using Moonlight.Frontend.Services
@using Moonlight.Shared.Http.Requests.Themes @using Moonlight.Shared.Http.Requests.Themes
@using ShadcnBlazor.Buttons @using ShadcnBlazor.Buttons
@using ShadcnBlazor.Labels
@using ShadcnBlazor.Cards @using ShadcnBlazor.Cards
@using ShadcnBlazor.Extras.Editors @using ShadcnBlazor.Extras.Editors
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.Toasts @using ShadcnBlazor.Extras.Toasts
@using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Switches @using ShadcnBlazor.Switches
@@ -21,6 +21,7 @@
@inject ToastService ToastService @inject ToastService ToastService
@inject FrontendService FrontendService @inject FrontendService FrontendService
<EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync" Context="editFormContext">
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<h1 class="text-xl font-semibold">Create theme</h1> <h1 class="text-xl font-semibold">Create theme</h1>
@@ -37,54 +38,55 @@
</a> </a>
</Slot> </Slot>
</Button> </Button>
<Button @onclick="SubmitAsync"> <SubmitButton>
<CheckIcon/> <CheckIcon/>
Continue Continue
</Button> </SubmitButton>
</div> </div>
</div> </div>
<div class="mt-8"> <div class="mt-8">
<Card> <Card>
<CardContent> <CardContent>
<FormHandler @ref="Form" OnValidSubmit="OnSubmitAsync" Model="Request"> <FieldGroup>
<div class="flex flex-col gap-6">
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5"> <FieldSet ClassName="grid grid-cols-1 lg:grid-cols-2">
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeName">Name</Label> <FieldLabel for="themeName">Name</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Name" @bind-Value="Request.Name"
id="themeName" id="themeName"
placeholder="My cool theme"/> placeholder="My cool theme"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeVersion">Version</Label> <FieldLabel for="themeVersion">Version</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Version" @bind-Value="Request.Version"
id="themeVersion" id="themeVersion"
Type="text" Type="text"
placeholder="1.0.0"/> placeholder="1.0.0"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeAuthor">Author</Label> <FieldLabel for="themeAuthor">Author</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Author" @bind-Value="Request.Author"
id="themeAuthor" id="themeAuthor"
Type="text" Type="text"
placeholder="Your name"/> placeholder="Your name"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeAuthor">Is Enabled</Label> <FieldLabel for="themeAuthor">Is Enabled</FieldLabel>
<FieldContent>
<Switch @bind-Value="Request.IsEnabled"/> <Switch @bind-Value="Request.IsEnabled"/>
</div> </FieldContent>
</div> </Field>
</FieldSet>
<Field>
<style> <style>
.cm-editor { .cm-editor {
max-height: 400px; max-height: 400px;
@@ -92,15 +94,16 @@
} }
</style> </style>
<div class="grid gap-2"> <FieldLabel for="themeAuthor">CSS Content</FieldLabel>
<Label for="themeAuthor">CSS Content</Label> <FieldContent>
<Editor @ref="Editor" Language="EditorLanguage.Css" InitialValue="@Request.CssContent"/> <Editor @ref="Editor" Language="EditorLanguage.Css" InitialValue="@Request.CssContent"/>
</div> </FieldContent>
</div> </Field>
</FormHandler> </FieldGroup>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</EnhancedEditForm>
@code @code
{ {
@@ -109,17 +112,12 @@
CssContent = "/* Define your css here */" CssContent = "/* Define your css here */"
}; };
private FormHandler Form;
private Editor Editor; private Editor Editor;
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.CssContent = await Editor.GetValueAsync(); Request.CssContent = await Editor.GetValueAsync();
await Form.SubmitAsync();
}
private async Task OnSubmitAsync()
{
await HttpClient.PostAsJsonAsync( await HttpClient.PostAsJsonAsync(
"/api/admin/themes", "/api/admin/themes",
Request, Request,
@@ -134,5 +132,7 @@
await FrontendService.ReloadAsync(); await FrontendService.ReloadAsync();
Navigation.NavigateTo("/admin/system?tab=themes"); Navigation.NavigateTo("/admin/system?tab=themes");
return true;
} }
} }

View File

@@ -8,12 +8,12 @@
@using Moonlight.Shared.Http.Requests.Themes @using Moonlight.Shared.Http.Requests.Themes
@using Moonlight.Shared.Http.Responses.Themes @using Moonlight.Shared.Http.Responses.Themes
@using ShadcnBlazor.Buttons @using ShadcnBlazor.Buttons
@using ShadcnBlazor.Labels
@using ShadcnBlazor.Cards @using ShadcnBlazor.Cards
@using ShadcnBlazor.Extras.Common @using ShadcnBlazor.Extras.Common
@using ShadcnBlazor.Extras.Editors @using ShadcnBlazor.Extras.Editors
@using ShadcnBlazor.Extras.FormHandlers @using ShadcnBlazor.Extras.Forms
@using ShadcnBlazor.Extras.Toasts @using ShadcnBlazor.Extras.Toasts
@using ShadcnBlazor.Fields
@using ShadcnBlazor.Inputs @using ShadcnBlazor.Inputs
@using ShadcnBlazor.Switches @using ShadcnBlazor.Switches
@@ -24,6 +24,8 @@
@inject ToastService ToastService @inject ToastService ToastService
@inject FrontendService FrontendService @inject FrontendService FrontendService
<LazyLoader Load="LoadAsync">
<EnhancedEditForm Model="Request" OnValidSubmit="OnSubmitAsync" Context="editFormContext">
<div class="flex flex-row justify-between"> <div class="flex flex-row justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<h1 class="text-xl font-semibold">Update theme</h1> <h1 class="text-xl font-semibold">Update theme</h1>
@@ -40,55 +42,55 @@
</a> </a>
</Slot> </Slot>
</Button> </Button>
<Button @onclick="SubmitAsync"> <SubmitButton>
<CheckIcon/> <CheckIcon/>
Continue Continue
</Button> </SubmitButton>
</div> </div>
</div> </div>
<div class="mt-8"> <div class="mt-8">
<Card> <Card>
<CardContent> <CardContent>
<LazyLoader Load="LoadAsync"> <FieldGroup>
<FormHandler @ref="Form" OnValidSubmit="OnSubmitAsync" Model="Request">
<div class="flex flex-col gap-6">
<FormValidationSummary/> <FormValidationSummary/>
<DataAnnotationsValidator/>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5"> <FieldSet ClassName="grid grid-cols-1 lg:grid-cols-2">
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeName">Name</Label> <FieldLabel for="themeName">Name</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Name" @bind-Value="Request.Name"
id="themeName" id="themeName"
placeholder="My cool theme"/> placeholder="My cool theme"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeVersion">Version</Label> <FieldLabel for="themeVersion">Version</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Version" @bind-Value="Request.Version"
id="themeVersion" id="themeVersion"
Type="text" Type="text"
placeholder="1.0.0"/> placeholder="1.0.0"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeAuthor">Author</Label> <FieldLabel for="themeAuthor">Author</FieldLabel>
<TextInputField <TextInputField
@bind-Value="Request.Author" @bind-Value="Request.Author"
id="themeAuthor" id="themeAuthor"
Type="text" Type="text"
placeholder="Your name"/> placeholder="Your name"/>
</div> </Field>
<div class="col-span-1 grid gap-2"> <Field>
<Label for="themeAuthor">Is Enabled</Label> <FieldLabel for="themeAuthor">Is Enabled</FieldLabel>
<FieldContent>
<Switch @bind-Value="Request.IsEnabled"/> <Switch @bind-Value="Request.IsEnabled"/>
</div> </FieldContent>
</div> </Field>
</FieldSet>
<Field>
<style> <style>
.cm-editor { .cm-editor {
max-height: 400px; max-height: 400px;
@@ -96,16 +98,18 @@
} }
</style> </style>
<div class="grid gap-2"> <FieldLabel for="themeAuthor">CSS Content</FieldLabel>
<Label for="themeAuthor">CSS Content</Label> <FieldContent>
<Editor @ref="Editor" Language="EditorLanguage.Css" InitialValue="@Request.CssContent"/> <Editor @ref="Editor" Language="EditorLanguage.Css"
</div> InitialValue="@Request.CssContent"/>
</div> </FieldContent>
</FormHandler> </Field>
</LazyLoader> </FieldGroup>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
</EnhancedEditForm>
</LazyLoader>
@code @code
{ {
@@ -114,7 +118,6 @@
private UpdateThemeDto Request; private UpdateThemeDto Request;
private ThemeDto Theme; private ThemeDto Theme;
private FormHandler Form;
private Editor Editor; private Editor Editor;
private async Task LoadAsync(LazyLoader _) private async Task LoadAsync(LazyLoader _)
@@ -125,14 +128,10 @@
Request = ThemeMapper.ToUpdate(Theme); Request = ThemeMapper.ToUpdate(Theme);
} }
private async Task SubmitAsync() private async Task<bool> OnSubmitAsync(EditContext editContext, ValidationMessageStore validationMessageStore)
{ {
Request.CssContent = await Editor.GetValueAsync(); Request.CssContent = await Editor.GetValueAsync();
await Form.SubmitAsync();
}
private async Task OnSubmitAsync()
{
await HttpClient.PatchAsJsonAsync( await HttpClient.PatchAsJsonAsync(
$"/api/admin/themes/{Theme.Id}", $"/api/admin/themes/{Theme.Id}",
Request, Request,
@@ -147,5 +146,7 @@
await FrontendService.ReloadAsync(); await FrontendService.ReloadAsync();
Navigation.NavigateTo("/admin/system?tab=themes"); Navigation.NavigateTo("/admin/system?tab=themes");
return true;
} }
} }

View File

@@ -4,10 +4,13 @@ namespace Moonlight.Shared.Http.Requests.ApiKeys;
public class CreateApiKeyDto public class CreateApiKeyDto
{ {
[Required]
[MaxLength(30)] [MaxLength(30)]
public string Name { get; set; } public string Name { get; set; }
[MaxLength(300)] public string Description { get; set; } = ""; [MaxLength(300)] public string Description { get; set; } = "";
[Required]
public string[] Permissions { get; set; } public string[] Permissions { get; set; }
} }

View File

@@ -4,10 +4,12 @@ namespace Moonlight.Shared.Http.Requests.ApiKeys;
public class UpdateApiKeyDto public class UpdateApiKeyDto
{ {
[Required]
[MaxLength(30)] [MaxLength(30)]
public string Name { get; set; } public string Name { get; set; }
[MaxLength(300)] public string Description { get; set; } = ""; [MaxLength(300)] public string Description { get; set; } = "";
[Required]
public string[] Permissions { get; set; } public string[] Permissions { get; set; }
} }