Switched to final fast forms implementation. Changed some stuff

This commit is contained in:
Marcel Baumgartner
2024-07-03 22:38:40 +02:00
parent ba907d5499
commit 9602a201ce
16 changed files with 146 additions and 200 deletions

View File

@@ -23,7 +23,7 @@
</div> </div>
</div> </div>
<SmartForm Model="Form" OnValidSubmit="OnValidSubmit"> <MCBForm Model="Form" OnValidSubmit="OnValidSubmit">
@if (RequiresTwoFactor) @if (RequiresTwoFactor)
{ {
<div class="fv-row mb-7"> <div class="fv-row mb-7">
@@ -57,7 +57,7 @@
@* OAuth2 Providers here *@ @* OAuth2 Providers here *@
</div> </div>
</div> </div>
</SmartForm> </MCBForm>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
@page "/admin/api/keys" @page "/admin/api/keys"
@using MoonCore.Blazor.Models.Fast @using MoonCore.Blazor.Models.FastForms
@using MoonCore.Helpers @using MoonCore.Helpers
@using Moonlight.Core.Database.Entities @using Moonlight.Core.Database.Entities
@using Moonlight.Core.UI.Components.Navigations @using Moonlight.Core.UI.Components.Navigations
@@ -66,12 +66,12 @@
}; };
} }
private void OnConfigureFrom(FastConfiguration<ApiKey> configuration, ApiKey _) private void OnConfigureFrom(FastFormConfiguration<ApiKey> configuration, ApiKey _)
{ {
configuration.AddProperty(x => x.Description) configuration.AddProperty(x => x.Description)
.WithDefaultComponent() .WithDefaultComponent()
.WithDescription("Write a note here for which application the api key is used for") .WithDescription("Write a note here for which application the api key is used for")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.ExpiresAt) configuration.AddProperty(x => x.ExpiresAt)
.WithDefaultComponent() .WithDefaultComponent()

View File

@@ -4,8 +4,6 @@
@using System.Linq.Expressions @using System.Linq.Expressions
@using Moonlight.Core.UI.Components.Navigations @using Moonlight.Core.UI.Components.Navigations
@using System.Reflection @using System.Reflection
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Helpers
@using MoonCore.Services @using MoonCore.Services
@using Moonlight.Core.Configuration @using Moonlight.Core.Configuration
@@ -140,7 +138,7 @@ else
Properties = props Properties = props
.Where(x => .Where(x =>
!x.PropertyType.Namespace.StartsWith("Moonlight") && !x.PropertyType.Namespace.StartsWith("Moonlight") &&
DefaultComponentSelector.GetDefault(x.PropertyType) != null // Check if a component has been registered for that type DefaultComponentRegistry.Get(x.PropertyType) != null // Check if a component has been registered for that type
) )
.ToArray(); .ToArray();
} }
@@ -151,7 +149,7 @@ else
await LazyLoader.Reload(); await LazyLoader.Reload();
} }
private void OnFormConfigure(FastConfiguration<object> configuration) private void OnFormConfigure(FastFormConfiguration<object> configuration)
{ {
if(CurrentModel == null) // This will technically never be true because of the ui logic if(CurrentModel == null) // This will technically never be true because of the ui logic
return; return;

View File

@@ -2,14 +2,9 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Moonlight.Core.UI.Components.Navigations @using Moonlight.Core.UI.Components.Navigations
@using MoonCore.Abstractions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using Moonlight.Core.Database.Entities @using Moonlight.Core.Database.Entities
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Core.Models.Abstractions @using Moonlight.Core.Models.Abstractions
@using Moonlight.Core.Models.Forms.Users
@inject AlertService AlertService @inject AlertService AlertService
@inject IAuthenticationProvider AuthenticationProvider @inject IAuthenticationProvider AuthenticationProvider
@@ -67,43 +62,43 @@
}; };
} }
private void OnConfigureCreate(FastConfiguration<User> configuration, User _) private void OnConfigureCreate(FastFormConfiguration<User> configuration, User _)
{ {
configuration.AddProperty(x => x.Username) configuration.AddProperty(x => x.Username)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^[a-z][a-z0-9]*$", "Usernames can only contain lowercase characters and numbers and should not start with a number")) .WithValidation(RegexValidator.Create("^[a-z][a-z0-9]*$", "Usernames can only contain lowercase characters and numbers and should not start with a number"))
.WithValidation<string>(x => x.Length >= 6 ? ValidationResult.Success : new ValidationResult("The username is too short")) .WithValidation(x => x.Length >= 6 ? ValidationResult.Success : new ValidationResult("The username is too short"))
.WithValidation<string>(x => x.Length <= 20 ? ValidationResult.Success : new ValidationResult("The username cannot be longer than 20 characters")); .WithValidation(x => x.Length <= 20 ? ValidationResult.Success : new ValidationResult("The username cannot be longer than 20 characters"));
configuration.AddProperty(x => x.Email) configuration.AddProperty(x => x.Email)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^.+@.+$", "You need to enter a valid email address")); .WithValidation(RegexValidator.Create("^.+@.+$", "You need to enter a valid email address"));
configuration.AddProperty(x => x.Password) configuration.AddProperty(x => x.Password)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation<string>(x => x.Length >= 8 ? ValidationResult.Success : new ValidationResult("The password must be at least 8 characters long")) .WithValidation(x => x.Length >= 8 ? ValidationResult.Success : new ValidationResult("The password must be at least 8 characters long"))
.WithValidation<string>(x => x.Length <= 256 ? ValidationResult.Success : new ValidationResult("The password must not be longer than 256 characters")); .WithValidation(x => x.Length <= 256 ? ValidationResult.Success : new ValidationResult("The password must not be longer than 256 characters"));
} }
private void OnConfigureEdit(FastConfiguration<User> configuration, User currentUser) private void OnConfigureEdit(FastFormConfiguration<User> configuration, User currentUser)
{ {
configuration.AddProperty(x => x.Username) configuration.AddProperty(x => x.Username)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^[a-z][a-z0-9]*$", "Usernames can only contain lowercase characters and numbers and should not start with a number")) .WithValidation(RegexValidator.Create("^[a-z][a-z0-9]*$", "Usernames can only contain lowercase characters and numbers and should not start with a number"))
.WithValidation<string>(x => x.Length >= 6 ? ValidationResult.Success : new ValidationResult("The username is too short")) .WithValidation(x => x.Length >= 6 ? ValidationResult.Success : new ValidationResult("The username is too short"))
.WithValidation<string>(x => x.Length <= 20 ? ValidationResult.Success : new ValidationResult("The username cannot be longer than 20 characters")); .WithValidation(x => x.Length <= 20 ? ValidationResult.Success : new ValidationResult("The username cannot be longer than 20 characters"));
configuration.AddProperty(x => x.Email) configuration.AddProperty(x => x.Email)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^.+@.+$", "You need to enter a valid email address")); .WithValidation(RegexValidator.Create("^.+@.+$", "You need to enter a valid email address"));
configuration.AddProperty(x => x.Totp) configuration.AddProperty(x => x.Totp)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithName("Two factor authentication") .WithName("Two factor authentication")
.WithDescription("This toggles the use of the two factor authentication"); .WithDescription("This toggles the use of the two factor authentication");
} }

View File

@@ -1,7 +1,7 @@
@using Microsoft.CSharp.RuntimeBinder
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using MoonCore.Blazor.Forms.Fast.Components
@inherits BaseFastFormComponent<int> @inherits FastFormBaseComponent<int>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<label class="form-label">@Name</label> <label class="form-label">@Name</label>
@@ -14,6 +14,8 @@
@code @code
{ {
[Parameter] public ServerImage Image { get; set; }
private ServerDockerImage? SelectedDockerImage private ServerDockerImage? SelectedDockerImage
{ {
get get
@@ -42,11 +44,7 @@
protected override void OnInitialized() protected override void OnInitialized()
{ {
ArgumentNullException.ThrowIfNull(AdditionalOptions); SortedImages = Image.DockerImages
var image = AdditionalOptions.Get<ServerImage>("Image");
SortedImages = image.DockerImages
.OrderBy(x => x.Id) .OrderBy(x => x.Id)
.ToList(); .ToList();
} }

View File

@@ -1,7 +1,6 @@
@using MoonCore.Blazor.Forms.Fast.Components
@using Moonlight.Features.FileManager.UI.Components @using Moonlight.Features.FileManager.UI.Components
@inherits BaseFastFormComponent<string> @inherits FastFormBaseComponent<string>
<div class="col-12"> <div class="col-12">
<label class="form-label"> <label class="form-label">
@@ -17,21 +16,9 @@
@code @code
{ {
private int Lines; [Parameter] public string Mode { get; set; } = "sh";
private string Mode;
protected override void OnInitialized() [Parameter] public int Lines { get; set; } = 25;
{
if (AdditionalOptions == null)
{
Lines = 25;
Mode = "sh";
return;
}
Lines = AdditionalOptions.GetNullable<int?>("Lines") ?? 25;
Mode = AdditionalOptions.GetNullable<string?>("Mode") ?? "sh";
}
private Task OnValueChanged(string val) private Task OnValueChanged(string val)
{ {

View File

@@ -1,35 +1,10 @@
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@inject Repository<ServerImage> ImageRepository @inject Repository<ServerImage> ImageRepository
@inject Repository<ServerDockerImage> DockerImageRepository @inject Repository<ServerDockerImage> DockerImageRepository
@*
<div class="card mb-10">
<div class="card-body">
<div class="row g-8">
<div class="col-md-6 col-12">
<label class="form-label">Default docker image</label>
<MCBSelect TField="ServerDockerImage"
@bind-Value="SelectedDockerImage"
Items="Image.DockerImages"
DisplayField="@(x => x.Name)"
CanBeNull="true"/>
</div>
<div class="col-md-6 col-12">
<label class="form-label">Allow user to change the docker image</label>
<div class="form-check">
<InputCheckbox @bind-Value="Form.AllowDockerImageChange" class="form-check-input"/>
</div>
</div>
</div>
</div>
</div>*@
<FastCrud TItem="ServerDockerImage" <FastCrud TItem="ServerDockerImage"
Loader="Loader" Loader="Loader"
OnConfigure="OnConfigure" OnConfigure="OnConfigure"
@@ -107,21 +82,21 @@
}; };
} }
private void OnConfigureForm(FastConfiguration<ServerDockerImage> configuration, ServerDockerImage _) private void OnConfigureForm(FastFormConfiguration<ServerDockerImage> configuration, ServerDockerImage _)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name")) .WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name"))
.WithDescription("This is the name of the docker image. E.g. moonlightpanel/moonlight:canary"); .WithDescription("This is the name of the docker image. E.g. moonlightpanel/moonlight:canary");
configuration.AddProperty(x => x.DisplayName) configuration.AddProperty(x => x.DisplayName)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithDescription("This will be shown if the user is able to change the docker image as the image name"); .WithDescription("This will be shown if the user is able to change the docker image as the image name");
configuration.AddProperty(x => x.AutoPull) configuration.AddProperty(x => x.AutoPull)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithDescription("Specifies if the docker image should be pulled/updated when creating a server instance. Disable this for only local existing docker images"); .WithDescription("Specifies if the docker image should be pulled/updated when creating a server instance. Disable this for only local existing docker images");
} }
} }

View File

@@ -1,10 +1,9 @@
@using Mappy.Net @using Mappy.Net
@using MoonCore.Blazor.Forms.Fast.Components
@using Moonlight.Features.Servers.Models @using Moonlight.Features.Servers.Models
@using Moonlight.Features.Servers.Models.Forms.Admin.Images.Parsing @using Moonlight.Features.Servers.Models.Forms.Admin.Images.Parsing
@using Newtonsoft.Json @using Newtonsoft.Json
@inherits BaseFastFormComponent<string> @inherits FastFormBaseComponent<string>
<div class="d-flex justify-content-end mb-3"> <div class="d-flex justify-content-end mb-3">
<button @onclick="AddConfig" type="button" class="btn btn-icon btn-success"> <button @onclick="AddConfig" type="button" class="btn btn-icon btn-success">

View File

@@ -1,7 +1,5 @@
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Features.Servers.Entities.Enums @using Moonlight.Features.Servers.Entities.Enums
@@ -99,11 +97,11 @@
}; };
} }
private void OnConfigureForm(FastConfiguration<ServerImageVariable> configuration, ServerImageVariable _) private void OnConfigureForm(FastFormConfiguration<ServerImageVariable> configuration, ServerImageVariable _)
{ {
configuration.AddProperty(x => x.Key) configuration.AddProperty(x => x.Key)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithDescription("This is the environment variable name"); .WithDescription("This is the environment variable name");
configuration.AddProperty(x => x.DefaultValue) configuration.AddProperty(x => x.DefaultValue)
@@ -112,24 +110,24 @@
configuration.AddProperty(x => x.DisplayName) configuration.AddProperty(x => x.DisplayName)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithDescription("This is the display name of the variable which will be shown to the user if enabled to edit/view the variable"); .WithDescription("This is the display name of the variable which will be shown to the user if enabled to edit/view the variable");
configuration.AddProperty(x => x.Description) configuration.AddProperty(x => x.Description)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithDescription("This text should describe what the variable does for the user if allowed to view and/or change"); .WithDescription("This text should describe what the variable does for the user if allowed to view and/or change");
configuration.AddProperty(x => x.AllowView) configuration.AddProperty(x => x.AllowView)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithDescription("Allow the user to view the variable but not edit it unless specified otherwise"); .WithDescription("Allow the user to view the variable but not edit it unless specified otherwise");
configuration.AddProperty(x => x.AllowEdit) configuration.AddProperty(x => x.AllowEdit)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithDescription("Allow the user to edit the variable. Wont work if view is disabled"); .WithDescription("Allow the user to edit the variable. Wont work if view is disabled");
configuration.AddProperty(x => x.Type) configuration.AddProperty(x => x.Type)
.WithComponent<ServerImageVariableType, EnumSelectComponent<ServerImageVariableType>>() .WithComponent<EnumSelectComponent<ServerImageVariableType>>()
.WithDescription("Specifies the type of the variable. This specifies what ui the user will see for the variable. You can also specify the options which are available using the filter field"); .WithDescription("Specifies the type of the variable. This specifies what ui the user will see for the variable. You can also specify the options which are available using the filter field");
configuration.AddProperty(x => x.Filter) configuration.AddProperty(x => x.Filter)

View File

@@ -1,8 +1,6 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using MoonCore.Exceptions @using MoonCore.Exceptions
@@ -192,15 +190,15 @@
}; };
} }
private void OnConfigureForm(FastConfiguration<ServerAllocation> configuration, ServerAllocation _) private void OnConfigureForm(FastFormConfiguration<ServerAllocation> configuration, ServerAllocation _)
{ {
configuration.AddProperty(x => x.IpAddress) configuration.AddProperty(x => x.IpAddress)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", "You need to provide a valid ipv4 address")); .WithValidation(RegexValidator.Create("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", "You need to provide a valid ipv4 address"));
configuration.AddProperty(x => x.Port) configuration.AddProperty(x => x.Port)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation<int>(x => x >= 1 && x <= 65535 ? ValidationResult.Success : new ValidationResult("You need to provide a valid port")); .WithValidation(x => x >= 1 && x <= 65535 ? ValidationResult.Success : new ValidationResult("You need to provide a valid port"));
} }
} }

View File

@@ -9,9 +9,6 @@
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Helpers @using Moonlight.Features.Servers.Helpers
@using Microsoft.AspNetCore.Components.Forms @using Microsoft.AspNetCore.Components.Forms
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using Moonlight.Features.Servers.UI.ImageComponents @using Moonlight.Features.Servers.UI.ImageComponents
@inject Repository<Server> ServerRepository @inject Repository<Server> ServerRepository
@@ -111,18 +108,18 @@
configuration.CustomDelete = CustomDelete; configuration.CustomDelete = CustomDelete;
} }
private void OnConfigureForm(FastConfiguration<ServerImage> configuration, ServerImage image) private void OnConfigureForm(FastFormConfiguration<ServerImage> configuration, ServerImage image)
{ {
// General // General
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("General") .WithPage("General")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Author) configuration.AddProperty(x => x.Author)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("General") .WithPage("General")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.DonateUrl) configuration.AddProperty(x => x.DonateUrl)
.WithDefaultComponent() .WithDefaultComponent()
@@ -137,25 +134,25 @@
// Power // Power
configuration.AddProperty(x => x.StartupCommand) configuration.AddProperty(x => x.StartupCommand)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithPage("Start, Stop & Status") .WithPage("Start, Stop & Status")
.WithDescription("This command will be executed at the start of a server. You can use environment variables in a {} here"); .WithDescription("This command will be executed at the start of a server. You can use environment variables in a {} here");
configuration.AddProperty(x => x.OnlineDetection) configuration.AddProperty(x => x.OnlineDetection)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithPage("Start, Stop & Status") .WithPage("Start, Stop & Status")
.WithDescription("A regex string specifying that a server is online when the daemon finds a match in the console output matching this expression"); .WithDescription("A regex string specifying that a server is online when the daemon finds a match in the console output matching this expression");
configuration.AddProperty(x => x.StopCommand) configuration.AddProperty(x => x.StopCommand)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithPage("Start, Stop & Status") .WithPage("Start, Stop & Status")
.WithDescription("A command which will be sent to the servers stdin when it should get stopped. Power signals can be achived by using ^. E.g. ^C"); .WithDescription("A command which will be sent to the servers stdin when it should get stopped. Power signals can be achived by using ^. E.g. ^C");
// Parsing // Parsing
configuration.AddProperty(x => x.ParseConfiguration) configuration.AddProperty(x => x.ParseConfiguration)
.WithComponent<string, ImageParseConfigEditor>() .WithComponent<ImageParseConfigEditor>()
.WithPage("Parsing"); .WithPage("Parsing");
configuration.AddCustomPage("Variables", ComponentHelper.FromType<ImageVariables>(parameters => configuration.AddCustomPage("Variables", ComponentHelper.FromType<ImageVariables>(parameters =>
@@ -169,38 +166,40 @@
})); }));
configuration.AddProperty(x => x.AllowDockerImageChange) configuration.AddProperty(x => x.AllowDockerImageChange)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithPage("Miscellaneous") .WithPage("Miscellaneous")
.WithDescription("This toggle specifies if a user is allowed to change the docker image from the list of docker images associated to the image"); .WithDescription("This toggle specifies if a user is allowed to change the docker image from the list of docker images associated to the image");
configuration.AddProperty(x => x.DefaultDockerImage) configuration.AddProperty(x => x.DefaultDockerImage)
.WithComponent<int, DefaultDockerImage>() .WithComponent<DefaultDockerImage>(dockerImage =>
.WithAdditionalOption("Image", image) {
dockerImage.Image = image;
})
.WithPage("Miscellaneous"); .WithPage("Miscellaneous");
configuration.AddProperty(x => x.AllocationsNeeded) configuration.AddProperty(x => x.AllocationsNeeded)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("Miscellaneous") .WithPage("Miscellaneous")
.WithValidation<int>(x => x > 1 ? ValidationResult.Success : new ValidationResult("This specifies the amount of allocations needed for this image in order to create a server")); .WithValidation(x => x > 1 ? ValidationResult.Success : new ValidationResult("This specifies the amount of allocations needed for this image in order to create a server"));
configuration.AddProperty(x => x.InstallDockerImage) configuration.AddProperty(x => x.InstallDockerImage)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("Installation") .WithPage("Installation")
.WithName("Docker Image") .WithName("Docker Image")
.WithValidation(FastValidators.Required) .WithValidation(FastFormValidators.Required)
.WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name")); .WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name"));
configuration.AddProperty(x => x.InstallShell) configuration.AddProperty(x => x.InstallShell)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("Installation") .WithPage("Installation")
.WithName("Shell") .WithName("Shell")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.InstallScript) configuration.AddProperty(x => x.InstallScript)
.WithComponent<string, EditorComponent>() .WithComponent<EditorComponent>()
.WithPage("Installation") .WithPage("Installation")
.WithName("Script") .WithName("Script")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
} }
private Task CustomDelete(ServerImage serverImage) private Task CustomDelete(ServerImage serverImage)

View File

@@ -4,9 +4,6 @@
@using Moonlight.Features.Servers.UI.Components @using Moonlight.Features.Servers.UI.Components
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using MoonCore.Blazor.Extensions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using Moonlight.Core.Database.Entities @using Moonlight.Core.Database.Entities
@@ -154,102 +151,104 @@
} }
// Shared form // Shared form
private void OnConfigureBase(FastConfiguration<Server> configuration, Server server) private void OnConfigureBase(FastFormConfiguration<Server> configuration, Server server)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
Func<User, string> usernameFunc = x => x.Username;
configuration.AddProperty(x => x.Owner) configuration.AddProperty(x => x.Owner)
.WithComponent<User, DropdownComponent<User>>() .WithComponent<DropdownComponent<User>>(component =>
.WithAdditionalOption("SearchFunc", usernameFunc) {
.WithAdditionalOption("DisplayFunc", usernameFunc) component.SearchFunc = x => x.Username;
.WithValidation(FastValidators.Required); component.DisplayFunc = x => x.Username;
})
Func<ServerImage, string> imageNameFunc = x => x.Name; .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Image) configuration.AddProperty(x => x.Image)
.WithComponent<ServerImage, DropdownComponent<ServerImage>>() .WithComponent<DropdownComponent<ServerImage>>(component =>
.WithAdditionalOption("SearchFunc", imageNameFunc) {
.WithAdditionalOption("DisplayFunc", imageNameFunc) component.SearchFunc = x => x.Name;
.WithValidation(FastValidators.Required); component.DisplayFunc = x => x.Name;
})
.WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Cpu) configuration.AddProperty(x => x.Cpu)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation<int>(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value")) .WithValidation(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value"))
.WithSection("Resources", "bxs-chip") .WithSection("Resources", "bxs-chip")
.WithDescription("The cores the server will be able to use. 100 = 1 Core"); .WithDescription("The cores the server will be able to use. 100 = 1 Core");
configuration.AddProperty(x => x.Memory) configuration.AddProperty(x => x.Memory)
.WithComponent<int, ByteSizeComponent>() .WithComponent<ByteSizeComponent>(component =>
.WithAdditionalOption("MinimumUnit", "MB") {
.WithAdditionalOption("DefaultUnit", "GB") component.MinimumUnit = "MB";
.WithValidation<int>(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value")) component.DefaultUnit = "GB";
})
.WithValidation(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value"))
.WithSection("Resources") .WithSection("Resources")
.WithDescription("The amount of memory this server will be able to use"); .WithDescription("The amount of memory this server will be able to use");
configuration.AddProperty(x => x.Disk) configuration.AddProperty(x => x.Disk)
.WithComponent<int, ByteSizeComponent>() .WithComponent<ByteSizeComponent>(component =>
.WithAdditionalOption("MinimumUnit", "MB") {
.WithAdditionalOption("DefaultUnit", "GB") component.MinimumUnit = "MB";
.WithValidation<int>(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value")) component.DefaultUnit = "GB";
})
.WithValidation(x => x > 0 ? ValidationResult.Success : new("You need to provide a valid value"))
.WithSection("Resources") .WithSection("Resources")
.WithDescription("The amount of disk space this server will be able to use"); .WithDescription("The amount of disk space this server will be able to use");
Func<ServerNode, string> nodeNameFunc = x => x.Name;
configuration.AddProperty(x => x.Node)
.WithComponent<ServerNode, DropdownComponent<ServerNode>>()
.WithAdditionalOption("SearchFunc", nodeNameFunc)
.WithAdditionalOption("DisplayFunc", nodeNameFunc)
.WithValidation(FastValidators.Required);
configuration.AddProperty(x => x.UseVirtualDisk) configuration.AddProperty(x => x.UseVirtualDisk)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithPage("Advanced options") .WithPage("Advanced options")
.WithDescription("Whether to use a virtual disk for storing server files. Dont use this if you want to overallocate as the virtual disks will fill out the space you allocate"); .WithDescription("Whether to use a virtual disk for storing server files. Dont use this if you want to overallocate as the virtual disks will fill out the space you allocate");
configuration.AddProperty(x => x.DisablePublicNetwork) configuration.AddProperty(x => x.DisablePublicNetwork)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithPage("Network") .WithPage("Network")
.WithDescription("Whether to block all incoming connections to this server from the internet"); .WithDescription("Whether to block all incoming connections to this server from the internet");
configuration.AddProperty(x => x.Allocations)
.WithComponent<MultiSelectComponent<ServerAllocation>>(component =>
{
component.SearchFunc = x => $"{x.IpAddress}:{x.Port}";
component.DisplayFunc = x => $"{x.IpAddress}:{x.Port}";
component.ItemsCallback = () =>GetAllocation(server);
})
.WithPage("Network");
} }
// Specific form // Specific form
private void OnConfigureCreate(FastConfiguration<Server> configuration, Server server) private void OnConfigureCreate(FastFormConfiguration<Server> configuration, Server server)
{ {
OnConfigureBase(configuration, server); OnConfigureBase(configuration, server);
// Allocations configuration.AddProperty(x => x.Node)
var items = AllocRepository .WithComponent<DropdownComponent<ServerNode>>(component =>
.Get() {
.FromSqlRaw("SELECT * FROM `ServerAllocations` WHERE ServerId IS NULL") component.SearchFunc = x => x.Name;
.AsEnumerable(); component.DisplayFunc = x => x.Name;
})
Func<ServerAllocation, string> buildDisplay = x => $"{x.IpAddress}:{x.Port}"; .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Allocations)
.WithMultiSelect(buildDisplay, buildDisplay, items)
.WithPage("Network");
} }
private void OnConfigureEdit(FastConfiguration<Server> configuration, Server server) private void OnConfigureEdit(FastFormConfiguration<Server> configuration, Server server)
{ {
OnConfigureBase(configuration, server); OnConfigureBase(configuration, server);
}
// Allocations private IEnumerable<ServerAllocation> GetAllocation(Server server)
var items = server.Allocations.Concat( {
if (server == null)
return Array.Empty<ServerAllocation>();
if (server.Node == null)
return Array.Empty<ServerAllocation>();
return server.Allocations.Concat(
AllocRepository AllocRepository
.Get() .Get()
.FromSqlRaw($"SELECT * FROM `ServerAllocations` WHERE ServerId IS NULL AND ServerNodeId = {server.Node.Id}") .FromSqlRaw($"SELECT * FROM `ServerAllocations` WHERE ServerId IS NULL AND ServerNodeId = {server.Node.Id}"));
.AsEnumerable());
Func<ServerAllocation, string> buildDisplay = x => $"{x.IpAddress}:{x.Port}";
configuration.AddProperty(x => x.Allocations)
.WithMultiSelect(buildDisplay, buildDisplay, items)
.WithPage("Network");
} }
} }

View File

@@ -1,7 +1,4 @@
@page "/admin/servers/nodes" @page "/admin/servers/nodes"
@using System.ComponentModel.DataAnnotations
@using Moonlight.Features.Servers.Models.Forms.Admin.Nodes
@using Moonlight.Features.Servers.UI.Components @using Moonlight.Features.Servers.UI.Components
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using MoonCore.Abstractions @using MoonCore.Abstractions
@@ -9,8 +6,6 @@
@using MoonCore.Exceptions @using MoonCore.Exceptions
@using MoonCore.Helpers @using MoonCore.Helpers
@using System.Text.RegularExpressions; @using System.Text.RegularExpressions;
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using Moonlight.Features.Servers.Api.Resources @using Moonlight.Features.Servers.Api.Resources
@using Moonlight.Features.Servers.Services @using Moonlight.Features.Servers.Services
@using Moonlight.Features.Servers.UI.NodeComponents @using Moonlight.Features.Servers.UI.NodeComponents
@@ -207,19 +202,19 @@
}; };
} }
private void OnConfigureCreate(FastConfiguration<ServerNode> configuration, ServerNode _) private void OnConfigureCreate(FastFormConfiguration<ServerNode> configuration, ServerNode _)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Fqdn) configuration.AddProperty(x => x.Fqdn)
.WithDefaultComponent() .WithDefaultComponent()
.WithDescription("This needs to be the ip or domain of the node depending on the ssl settings") .WithDescription("This needs to be the ip or domain of the node depending on the ssl settings")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Ssl) configuration.AddProperty(x => x.Ssl)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithDescription("This enables ssl for the http connections to the node. Only enable this if you have the cert installed on the node"); .WithDescription("This enables ssl for the http connections to the node. Only enable this if you have the cert installed on the node");
configuration.AddProperty(x => x.HttpPort) configuration.AddProperty(x => x.HttpPort)
@@ -231,21 +226,21 @@
.WithDescription("This is the ftp port users can use to access their servers filesystem via their ftp client"); .WithDescription("This is the ftp port users can use to access their servers filesystem via their ftp client");
} }
private void OnConfigureEdit(FastConfiguration<ServerNode> configuration, ServerNode node) private void OnConfigureEdit(FastFormConfiguration<ServerNode> configuration, ServerNode node)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("Settings") .WithPage("Settings")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Fqdn) configuration.AddProperty(x => x.Fqdn)
.WithDefaultComponent() .WithDefaultComponent()
.WithPage("Settings") .WithPage("Settings")
.WithDescription("This needs to be the ip or domain of the node depending on the ssl settings") .WithDescription("This needs to be the ip or domain of the node depending on the ssl settings")
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
configuration.AddProperty(x => x.Ssl) configuration.AddProperty(x => x.Ssl)
.WithComponent<bool, SwitchComponent>() .WithComponent<SwitchComponent>()
.WithPage("Settings") .WithPage("Settings")
.WithDescription("This enables ssl for the http connections to the node. Only enable this if you have the cert installed on the node"); .WithDescription("This enables ssl for the http connections to the node. Only enable this if you have the cert installed on the node");

View File

@@ -3,12 +3,9 @@
@using System.ComponentModel.DataAnnotations @using System.ComponentModel.DataAnnotations
@using Moonlight.Features.Servers.UI.Components @using Moonlight.Features.Servers.UI.Components
@using Moonlight.Features.Servers.Entities @using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Models.Forms.Users.Networks
@using MoonCore.Abstractions @using MoonCore.Abstractions
@using Moonlight.Core.Services @using Moonlight.Core.Services
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Exceptions @using MoonCore.Exceptions
@inject IdentityService IdentityService @inject IdentityService IdentityService
@@ -92,24 +89,24 @@
}; };
} }
private void OnConfigureCreate(FastConfiguration<ServerNetwork> configuration, ServerNetwork _) private void OnConfigureCreate(FastFormConfiguration<ServerNetwork> configuration, ServerNetwork _)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
Func<ServerNode, string> nodeDisplayField = x => x.Name;
configuration.AddProperty(x => x.Node) configuration.AddProperty(x => x.Node)
.WithComponent<ServerNode, SelectComponent<ServerNode>>() .WithComponent<SelectComponent<ServerNode>>(component =>
.WithAdditionalOption("DisplayField", nodeDisplayField) {
.WithValidation<ServerNode>(x => x != null ? ValidationResult.Success : new ValidationResult("You need to specify a node")); component.DisplayField = x => x.Name;
})
.WithValidation(x => x != null ? ValidationResult.Success : new ValidationResult("You need to specify a node"));
} }
private void OnConfigureEdit(FastConfiguration<ServerNetwork> configuration, ServerNetwork _) private void OnConfigureEdit(FastFormConfiguration<ServerNetwork> configuration, ServerNetwork _)
{ {
configuration.AddProperty(x => x.Name) configuration.AddProperty(x => x.Name)
.WithDefaultComponent() .WithDefaultComponent()
.WithValidation(FastValidators.Required); .WithValidation(FastFormValidators.Required);
} }
} }

View File

@@ -94,11 +94,16 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MoonCore" Version="1.4.1" /> <PackageReference Include="MoonCore" Version="1.4.1" />
<PackageReference Include="MoonCore.Blazor" Version="1.1.4" />
<PackageReference Include="Otp.NET" Version="1.3.0" /> <PackageReference Include="Otp.NET" Version="1.3.0" />
<PackageReference Include="QRCoder" Version="1.4.3" /> <PackageReference Include="QRCoder" Version="1.4.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" /> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />
<PackageReference Include="XtermBlazor" Version="1.10.2" /> <PackageReference Include="XtermBlazor" Version="1.10.2" />
<PackageReference Include="Z.Blazor.Diagrams" Version="3.0.2" /> <PackageReference Include="Z.Blazor.Diagrams" Version="3.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="MoonCore.Blazor">
<HintPath>..\..\..\Masu-Baumgartner\MoonCore\MoonCore\MoonCore.Blazor\bin\Debug\net8.0\MoonCore.Blazor.dll</HintPath>
</Reference>
</ItemGroup>
</Project> </Project>

View File

@@ -9,7 +9,10 @@
@using MoonCore.Blazor.Helpers @using MoonCore.Blazor.Helpers
@using MoonCore.Blazor.Forms.Table @using MoonCore.Blazor.Forms.Table
@using MoonCore.Blazor.Forms.Auto @using MoonCore.Blazor.Forms.Auto
@using MoonCore.Blazor.Forms.Fast @using MoonCore.Blazor.Models.FastForms
@using MoonCore.Blazor.Models.FastForms.Validators
@using MoonCore.Blazor.Forms.FastForms
@using MoonCore.Blazor.Forms.FastForms.Components
@using Moonlight.Core.UI @using Moonlight.Core.UI
@using Moonlight.Core.Attributes @using Moonlight.Core.Attributes