diff --git a/Moonlight/App/Helpers/WingsServerConverter.cs b/Moonlight/App/Helpers/WingsServerConverter.cs index acc7ed17..f1ebbc29 100644 --- a/Moonlight/App/Helpers/WingsServerConverter.cs +++ b/Moonlight/App/Helpers/WingsServerConverter.cs @@ -46,7 +46,7 @@ public class WingsServerConverter } // Build - wingsServer.Settings.Build.Swap = server.Memory * 2; + wingsServer.Settings.Build.Swap = server.Memory * 2; //TODO: Add config option wingsServer.Settings.Build.Threads = null!; wingsServer.Settings.Build.Cpu_Limit = server.Cpu; wingsServer.Settings.Build.Disk_Space = server.Disk; diff --git a/Moonlight/App/Models/Forms/DomainDataModel.cs b/Moonlight/App/Models/Forms/DomainDataModel.cs new file mode 100644 index 00000000..ce1bbc5a --- /dev/null +++ b/Moonlight/App/Models/Forms/DomainDataModel.cs @@ -0,0 +1,18 @@ +using System.ComponentModel.DataAnnotations; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Models.Forms; + +public class DomainDataModel +{ + [Required(ErrorMessage = "You need to specify a name")] + [MaxLength(32, ErrorMessage = "The max lenght for the name is 32 characters")] + [RegularExpression(@"^[a-z]+$", ErrorMessage = "The name should only consist of lower case characters")] + public string Name { get; set; } = ""; + + [Required(ErrorMessage = "You need to specify a shared domain")] + public SharedDomain SharedDomain { get; set; } + + [Required(ErrorMessage = "You need to specify a owner")] + public User Owner { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/ServerDataModel.cs b/Moonlight/App/Models/Forms/ServerDataModel.cs new file mode 100644 index 00000000..1b8c5008 --- /dev/null +++ b/Moonlight/App/Models/Forms/ServerDataModel.cs @@ -0,0 +1,30 @@ +using System.ComponentModel.DataAnnotations; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Models.Forms; + +public class ServerDataModel +{ + [Required(ErrorMessage = "You need to enter a name")] + [MaxLength(32, ErrorMessage = "The name cannot be longer that 32 characters")] + public string Name { get; set; } + + [Required(ErrorMessage = "You need to specify a owner")] + public User Owner { get; set; } + + [Required(ErrorMessage = "You need to specify cpu amount")] + public int Cpu { get; set; } = 100; + + [Required(ErrorMessage = "You need to specify a memory amount")] + public int Memory { get; set; } = 1024; + + [Required(ErrorMessage = "You need to specify a disk amount")] + public int Disk { get; set; } = 1024; + + [Required(ErrorMessage = "You need to specify a image")] + public Image Image { get; set; } + + public string OverrideStartup { get; set; } = ""; + + public int DockerImageIndex { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/TestDataModel.cs b/Moonlight/App/Models/Forms/TestDataModel.cs new file mode 100644 index 00000000..0fecab72 --- /dev/null +++ b/Moonlight/App/Models/Forms/TestDataModel.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Models.Forms; + +public class TestDataModel +{ + [Required] + public User User { get; set; } +} \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 816407f9..be85ac28 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -9,12 +9,10 @@ - - @@ -24,6 +22,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Moonlight/Pages/_Layout.cshtml b/Moonlight/Pages/_Layout.cshtml index b82364f4..9a6aee13 100644 --- a/Moonlight/Pages/_Layout.cshtml +++ b/Moonlight/Pages/_Layout.cshtml @@ -45,8 +45,7 @@ - - + @@ -87,7 +86,6 @@ - diff --git a/Moonlight/Shared/Components/Forms/SmartDropdown.razor b/Moonlight/Shared/Components/Forms/SmartDropdown.razor new file mode 100644 index 00000000..868d035a --- /dev/null +++ b/Moonlight/Shared/Components/Forms/SmartDropdown.razor @@ -0,0 +1,93 @@ +@typeparam T +@using Logging.Net +@inherits InputBase + + + +@code { + + [Parameter] + public IEnumerable Items { get; set; } + + [Parameter] + public Func DisplayFunc { get; set; } + + [Parameter] + public Func SearchProp { get; set; } + + private string SearchTerm + { + get => searchTerm; + set + { + FilteredItems = Items.Where(i => SearchProp(i).Contains(SearchTerm, StringComparison.OrdinalIgnoreCase)).ToList(); + searchTerm = value; + } + } + + private string searchTerm = ""; + + private List FilteredItems = new(); + + private void SelectItem(T item) + { + CurrentValue = item; + SearchTerm = ""; + FilteredItems.Clear(); + } + + protected override bool TryParseValueFromString(string? value, out T result, out string? validationErrorMessage) + { + // Check if the value is null or empty + if (string.IsNullOrEmpty(value)) + { + result = default(T)!; + validationErrorMessage = "Value cannot be null or empty"; + return false; + } + + // Try to find an item that matches the search term + var item = FilteredItems.FirstOrDefault(i => SearchProp(i).Equals(value, StringComparison.OrdinalIgnoreCase)); + if (item != null) + { + result = item; + validationErrorMessage = null; + return true; + } + else + { + result = default(T)!; + validationErrorMessage = $"No item found for search term '{value}'"; + return false; + } + } + +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Forms/SmartSelect.razor b/Moonlight/Shared/Components/Forms/SmartSelect.razor index ea246825..970f1800 100644 --- a/Moonlight/Shared/Components/Forms/SmartSelect.razor +++ b/Moonlight/Shared/Components/Forms/SmartSelect.razor @@ -11,10 +11,13 @@ @code { [Parameter] - public TField[] Items { get; set; } + public IEnumerable Items { get; set; } [Parameter] public Func DisplayField { get; set; } + + [Parameter] + public Func? OnChange { get; set; } protected override void OnInitialized() { @@ -53,6 +56,7 @@ { Value = i; ValueChanged.InvokeAsync(i); + OnChange?.Invoke(); } } } diff --git a/Moonlight/Shared/Views/Admin/Domains/New.razor b/Moonlight/Shared/Views/Admin/Domains/New.razor index a15a8239..203456ad 100644 --- a/Moonlight/Shared/Views/Admin/Domains/New.razor +++ b/Moonlight/Shared/Views/Admin/Domains/New.razor @@ -1,66 +1,51 @@ @page "/admin/domains/new" @using Moonlight.App.Services @using Moonlight.App.Database.Entities -@using Blazored.Typeahead +@using Moonlight.App.Models.Forms @using Moonlight.App.Repositories @using Moonlight.App.Repositories.Domains +@using Mappy.Net @inject SmartTranslateService SmartTranslateService @inject SharedDomainRepository SharedDomainRepository @inject DomainRepository DomainRepository @inject UserRepository UserRepository +@inject NavigationManager NavigationManager
- -
- - - - -
-
+ - -
-
-
- - - @(context.Email) - - - @(context.Email) - - +
+ + + +
-
- - +
+ + + +
+
+ + +
+ +
@@ -68,54 +53,27 @@ @code { - private string Name; + private DomainDataModel Model = new(); - private User? User; private User[] Users; - - private List SharedDomains; - - private SharedDomain? SharedDomain; - - private int SharedDomainId - { - get => SharedDomain?.Id ?? -1; - set - { - SharedDomain = SharedDomains.FirstOrDefault(x => x.Id == value); - InvokeAsync(StateHasChanged); - } - } - - private Task> SearchUsers(string input) - { - if (string.IsNullOrEmpty(input)) - { - return Task.FromResult(Array.Empty().Cast()); - } - else - { - return Task.FromResult(Users.Where(x => x.Email.ToLower().StartsWith(input))); - } - } + private SharedDomain[] SharedDomains; private Task Load(LazyLoader lazyLoader) { Users = UserRepository.Get().ToArray(); - SharedDomains = SharedDomainRepository.Get().ToList(); + SharedDomains = SharedDomainRepository.Get().ToArray(); return Task.CompletedTask; } private Task Add() { - DomainRepository.Add(new() - { - Name = Name.ToLower(), - Owner = User!, - SharedDomain = SharedDomain! - }); - + var domain = Mapper.Map(Model); + + DomainRepository.Add(domain); + + NavigationManager.NavigateTo("/admin/domains"); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/Moonlight/Shared/Views/Admin/Servers/New.razor b/Moonlight/Shared/Views/Admin/Servers/New.razor index 82093d5e..6c81dc72 100644 --- a/Moonlight/Shared/Views/Admin/Servers/New.razor +++ b/Moonlight/Shared/Views/Admin/Servers/New.razor @@ -6,7 +6,7 @@ @using Moonlight.App.Exceptions @using Moonlight.App.Services.Interop @using Logging.Net -@using Blazored.Typeahead +@using Moonlight.App.Models.Forms @inject NodeRepository NodeRepository @inject ImageRepository ImageRepository @@ -19,226 +19,182 @@ -
-
- -
- - - - -
- -
-
- - - @(context.Email) - - - @(context.Email) - - -
-
-
-
-
-
- -
- - - - - - CPU Cores (100% = 1 Core) - -
- -
- - - - - - MB - -
- -
- - - - - - MB - -
-
-
-
-
- - - @if (Image != null) - { + +
+
- + - +
- - } -
-
- -
-
- @if (Image != null) - { -
- @foreach (var vars in ServerVariables.Chunk(4)) - { -
- @foreach (var variable in vars) - { -
-
- -
- -
- -
- -
-
-
- } -
- } +
+ +
- } -
-
- -
-
-
-
+
+
+ +
+ + + + + + CPU Cores (100% = 1 Core) + +
+ +
+ + + + + + MB + +
+ +
+ + + + + + MB + +
+
+
+
+
+ +
+ +
+ @if (Model.Image != null) + { + +
+ + + + +
+ + + @foreach (var image in Model.Image.DockerImages) + { + + } + + } +
+
+ +
+
+ @if (Model.Image != null) + { +
+ @foreach (var vars in ServerVariables.Chunk(3)) + { +
+ @foreach (var variable in vars) + { +
+
+ +
+ +
+ +
+ +
+
+
+ } +
+ } +
+ } +
+
+ +
+
+
+ + Cancel + + +
+
+
+ @code { + private ServerDataModel Model = new(); + private List Images; private Node[] Nodes; private User[] Users; - private string Name = ""; - - private int Cpu = 100; - private int Memory = 4096; - private int Disk = 10240; - - private string OverrideStartup = ""; - private int DockerImageIndex = 0; - - private Image? Image; - private User? User; - private ServerVariable[] ServerVariables = Array.Empty(); - private int ImageIndex - { - get => Image == null ? 0 : Images.IndexOf(Image); - set - { - Image = Images[value]; - - if (Image == null) - ServerVariables = Array.Empty(); - else - RebuildVariables(); - - - InvokeAsync(StateHasChanged); - } - } - private void RebuildVariables() { var list = new List(); - foreach (var variable in Image.Variables) + if (Model.Image != null) { - list.Add(new() + foreach (var variable in Model.Image.Variables) { - Key = variable.Key, - Value = variable.DefaultValue - }); + list.Add(new() + { + Key = variable.Key, + Value = variable.DefaultValue + }); + } } ServerVariables = list.ToArray(); } - private Task> SearchUsers(string input) - { - if (string.IsNullOrEmpty(input)) - { - return Task.FromResult(Array.Empty().Cast()); - } - else - { - return Task.FromResult(Users.Where(x => x.Email.ToLower().StartsWith(input))); - } - } - private async Task Load(LazyLoader lazyLoader) { await lazyLoader.SetText("Loading images"); @@ -256,24 +212,18 @@ await lazyLoader.SetText("Loading users"); Users = UserRepository.Get().ToArray(); - User = Users.FirstOrDefault(); - - Image = Images.FirstOrDefault(); RebuildVariables(); - - if (Image != null) - DockerImageIndex = Image.DockerImages.Count - 1; } private async Task Create() { try { - await ServerService.Create(Name, Cpu, Memory, Disk, User, Image, null, server => + await ServerService.Create(Model.Name, Model.Cpu, Model.Memory, Model.Disk, Model.Owner, Model.Image, null, server => { - server.OverrideStartup = OverrideStartup; - server.DockerImageIndex = DockerImageIndex; + server.OverrideStartup = Model.OverrideStartup; + server.DockerImageIndex = Model.DockerImageIndex; foreach (var serverVariable in ServerVariables) { @@ -303,4 +253,10 @@ ); } } + + private async Task OnChange() + { + RebuildVariables(); + await InvokeAsync(StateHasChanged); + } } \ No newline at end of file diff --git a/Moonlight/Shared/Views/Admin/Websites/New.razor b/Moonlight/Shared/Views/Admin/Websites/New.razor index 4dcc6cfe..e4206aa5 100644 --- a/Moonlight/Shared/Views/Admin/Websites/New.razor +++ b/Moonlight/Shared/Views/Admin/Websites/New.razor @@ -2,7 +2,6 @@ @using Moonlight.App.Models.Forms @using Moonlight.App.Services -@using Blazored.Typeahead @using Moonlight.App.Database.Entities @using Moonlight.App.Repositories @@ -24,15 +23,11 @@ Owner
- - - @(context.Email) - - - @(context.Email) - - + +
+
+ @code { - [CascadingParameter] - public User User { get; set; } - - private FileAccess FileAccess; + private User[] Users; + private TestDataModel Model = new(); private Task Load(LazyLoader arg) { - FileAccess = new FtpFileAccess("vps01.so.host.endelon.link", 21, "example.com", "61P8JZzfjSNyhtZl"); - + Users = UserRepository.Get().ToArray(); + return Task.CompletedTask; } -} \ No newline at end of file + + private Task OnValidSubmit() + { + return Task.CompletedTask; + } +} diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index c0ba8c4f..a8d79100 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -513,3 +513,15 @@ Error from plesk;Error from plesk Host;Host Username;Username SRV records cannot be updated thanks to the cloudflare api client. Please delete the record and create a new one;SRV records cannot be updated thanks to the cloudflare api client. Please delete the record and create a new one +The User field is required.;The User field is required. +You need to specify a owner;You need to specify a owner +You need to specify a image;You need to specify a image +Api Url;Api Url +Api Key;Api Key +Duration;Duration +Enter duration of subscription;Enter duration of subscription +Copied code to clipboard;Copied code to clipboard +Invalid or expired subscription code;Invalid or expired subscription code +Current subscription;Current subscription +You need to specify a server image;You need to specify a server image +CPU;CPU