Added owner field to server crud. Started update for server crud

This commit is contained in:
2024-12-20 18:45:38 +01:00
parent e9279fa3d1
commit 0baf9668f9
13 changed files with 381 additions and 27 deletions

View File

@@ -6,6 +6,7 @@ using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers; using MoonCore.Extended.Helpers;
using MoonCore.Helpers; using MoonCore.Helpers;
using MoonCore.Models; using MoonCore.Models;
using Moonlight.ApiServer.Database.Entities;
using MoonlightServers.ApiServer.Database.Entities; using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.Servers; using MoonlightServers.Shared.Http.Requests.Admin.Servers;
using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations; using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations;
@@ -24,6 +25,7 @@ public class ServersController : Controller
private readonly DatabaseRepository<Allocation> AllocationRepository; private readonly DatabaseRepository<Allocation> AllocationRepository;
private readonly DatabaseRepository<ServerVariable> VariableRepository; private readonly DatabaseRepository<ServerVariable> VariableRepository;
private readonly DatabaseRepository<Server> ServerRepository; private readonly DatabaseRepository<Server> ServerRepository;
private readonly DatabaseRepository<User> UserRepository;
public ServersController( public ServersController(
CrudHelper<Server, ServerDetailResponse> crudHelper, CrudHelper<Server, ServerDetailResponse> crudHelper,
@@ -31,8 +33,8 @@ public class ServersController : Controller
DatabaseRepository<Node> nodeRepository, DatabaseRepository<Node> nodeRepository,
DatabaseRepository<Allocation> allocationRepository, DatabaseRepository<Allocation> allocationRepository,
DatabaseRepository<ServerVariable> variableRepository, DatabaseRepository<ServerVariable> variableRepository,
DatabaseRepository<Server> serverRepository DatabaseRepository<Server> serverRepository,
) DatabaseRepository<User> userRepository)
{ {
CrudHelper = crudHelper; CrudHelper = crudHelper;
StarRepository = starRepository; StarRepository = starRepository;
@@ -40,6 +42,7 @@ public class ServersController : Controller
AllocationRepository = allocationRepository; AllocationRepository = allocationRepository;
VariableRepository = variableRepository; VariableRepository = variableRepository;
ServerRepository = serverRepository; ServerRepository = serverRepository;
UserRepository = userRepository;
CrudHelper.QueryModifier = servers => servers CrudHelper.QueryModifier = servers => servers
.Include(x => x.Node) .Include(x => x.Node)
@@ -51,6 +54,7 @@ public class ServersController : Controller
{ {
response.NodeId = server.Node.Id; response.NodeId = server.Node.Id;
response.StarId = server.Star.Id; response.StarId = server.Star.Id;
response.AllocationIds = server.Allocations.Select(x => x.Id).ToArray();
return response; return response;
}; };
@@ -77,6 +81,10 @@ public class ServersController : Controller
// Construct model // Construct model
var server = Mapper.Map<Server>(request); var server = Mapper.Map<Server>(request);
// Check if owner user exist
if (UserRepository.Get().All(x => x.Id != request.OwnerId))
throw new HttpApiException("No user with this id found", 400);
var star = StarRepository var star = StarRepository
.Get() .Get()
.Include(x => x.Variables) .Include(x => x.Variables)

View File

@@ -31,10 +31,12 @@
if (Request.NodeId <= 0) if (Request.NodeId <= 0)
return []; return [];
var data = await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>( var items = await PagedData<NodeAllocationDetailResponse>.All(async (page, pageSize) =>
$"api/admin/servers/nodes/{Request.NodeId}/allocations/free?page=0&pageSize=50" await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>(
$"api/admin/servers/nodes/{Request.NodeId}/allocations/free?page={page}&pageSize={pageSize}"
)
); );
return data.Items; return items;
} }
} }

View File

@@ -1,10 +1,10 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers @using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Helpers @using MoonCore.Helpers
@using MoonCore.Models @using MoonCore.Models
@using MoonlightServers.Shared.Http.Responses.Admin.Nodes @using MoonlightServers.Shared.Http.Responses.Admin.Nodes
@using MoonlightServers.Shared.Http.Responses.Admin.Stars @using MoonlightServers.Shared.Http.Responses.Admin.Stars
@using MoonCore.Blazor.Tailwind.Inputs @using MoonCore.Blazor.Tailwind.Inputs
@using Moonlight.Shared.Http.Responses.Admin.Users
@inject HttpApiClient ApiClient @inject HttpApiClient ApiClient
@@ -16,6 +16,20 @@
</div> </div>
</div> </div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Owner</label>
<div class="mt-2">
<InputItemSearchSelect TItem="UserDetailResponse"
TProperty="int"
@bind-Value="Request.OwnerId"
AllowNone="false"
Loader="Loader"
DisplayProperty="@(x => x.Email)"
ValueProperty="@(x => x.Id)"/>
</div>
</div>
<div class="sm:col-span-2"> <div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Star</label> <label class="block text-sm font-medium leading-6 text-white">Star</label>
<div class="mt-2"> <div class="mt-2">
@@ -75,15 +89,46 @@
{ {
[Parameter] public CreateServerRequest Request { get; set; } [Parameter] public CreateServerRequest Request { get; set; }
private UserDetailResponse[]? Users;
private async Task<StarDetailResponse[]> LoadStars() private async Task<StarDetailResponse[]> LoadStars()
{ {
var starData = await ApiClient.GetJson<PagedData<StarDetailResponse>>("api/admin/servers/stars?page=0&pageSize=50"); var items = await PagedData<StarDetailResponse>.All(async (page, pageSize) =>
return starData.Items; await ApiClient.GetJson<PagedData<StarDetailResponse>>(
$"api/admin/servers/stars?page={page}&pageSize={pageSize}"
)
);
return items;
} }
private async Task<NodeDetailResponse[]> LoadNodes() private async Task<NodeDetailResponse[]> LoadNodes()
{ {
var nodeData = await ApiClient.GetJson<PagedData<NodeDetailResponse>>("api/admin/servers/nodes?page=0&pageSize=50"); var items = await PagedData<NodeDetailResponse>.All(async (page, pageSize) =>
return nodeData.Items; await ApiClient.GetJson<PagedData<NodeDetailResponse>>(
$"api/admin/servers/nodes?page={page}&pageSize={pageSize}"
)
);
return items;
}
private async Task<UserDetailResponse[]> Loader(string searchTerm)
{
if (Users == null)
{
Users = await PagedData<UserDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<UserDetailResponse>>(
$"api/admin/users?page={page}&pageSize={pageSize}"
)
);
}
if (string.IsNullOrEmpty(searchTerm))
return Users;
return Users
.Where(x => x.Email.Contains(searchTerm))
.ToArray();
} }
} }

View File

@@ -0,0 +1,70 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Helpers
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Models
@using MoonlightServers.Shared.Http.Responses.Admin.StarVariables
@inject HttpApiClient ApiClient
<LazyLoader Load="Load">
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
@foreach (var variable in StarVariables)
{
// Load value of default
var value = Request.Variables.TryGetValue(variable.Key, out var val)
? val
: variable.DefaultValue;
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">
@variable.Name
</label>
<div class="mt-2">
<input type="text"
class="form-input placeholder-gray-500 w-full"
value="@value"
placeholder="@variable.DefaultValue"
@onchange="@(args => UpdateValue(variable, args))"/>
</div>
<p class="mt-1 text-sm leading-6 text-gray-400">
@variable.Description
</p>
</div>
}
</div>
</LazyLoader>
@code
{
[Parameter] public CreateServerRequest Request { get; set; }
private StarVariableDetailResponse[] StarVariables;
private async Task Load(LazyLoader _)
{
if (Request.StarId <= 0)
{
StarVariables = [];
return;
}
StarVariables = await PagedData<StarVariableDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<StarVariableDetailResponse>>(
$"api/admin/servers/stars/{Request.StarId}/variables?page={page}&pageSize={pageSize}"
)
);
}
private async Task UpdateValue(StarVariableDetailResponse starVariable, ChangeEventArgs args)
{
var value = args.Value?.ToString() ?? "";
// Remove variable from request when set to its default value
if (value == starVariable.DefaultValue && Request.Variables.ContainsKey(starVariable.Key))
Request.Variables.Remove(starVariable.Key);
else
Request.Variables[starVariable.Key] = value;
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,16 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Blazor.Tailwind.Inputs
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Bandwidth</label>
<div class="mt-2">
<input @bind="Request.Bandwidth" type="number" autocomplete="off" class="form-input w-full">
</div>
</div>
</div>
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
}

View File

@@ -0,0 +1,44 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Blazor.Tailwind.Inputs
@using MoonCore.Helpers
@using MoonCore.Models
@using MoonlightServers.Shared.Http.Responses.Admin.NodeAllocations
@using MoonlightServers.Shared.Http.Responses.Admin.Servers
@inject HttpApiClient ApiClient
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Allocations</label>
<div class="mt-2">
<InputMultiSelect TItem="NodeAllocationDetailResponse"
TProperty="int"
@bind-Value="Request.AllocationIds"
Loader="Loader"
AllowSearch="true"
DisplayProperty="@(x => $"{x.IpAddress}:{x.Port}")"
ValueProperty="@(x => x.Id)"/>
</div>
</div>
</div>
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
[Parameter] public ServerDetailResponse Server { get; set; }
private async Task<NodeAllocationDetailResponse[]> Loader()
{
// Handle unselected node
if (Server.NodeId <= 0)
return [];
var items = await PagedData<NodeAllocationDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<NodeAllocationDetailResponse>>(
$"api/admin/servers/nodes/{Server.NodeId}/allocations/free?page={page}&pageSize={pageSize}"
)
);
return items;
}
}

View File

@@ -0,0 +1,86 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Helpers
@using MoonCore.Models
@using MoonCore.Blazor.Tailwind.Inputs
@using Moonlight.Shared.Http.Responses.Admin.Users
@inject HttpApiClient ApiClient
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Name</label>
<div class="mt-2">
<input @bind="Request.Name" type="text" autocomplete="off" class="form-input w-full">
</div>
</div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Owner</label>
<div class="mt-2">
<InputItemSearchSelect TItem="UserDetailResponse"
TProperty="int"
@bind-Value="Request.OwnerId"
AllowNone="false"
Loader="Loader"
DisplayProperty="@(x => x.Email)"
ValueProperty="@(x => x.Id)"/>
</div>
</div>
</div>
<div class="border-t border-gray-100/10 pt-6 my-8">
<div class="mb-8"><h2 class="text-base font-semibold leading-7 text-gray-100">
Resources
</h2>
<p class="mt-1 text-sm leading-6 text-gray-400">Define the servers resource limit</p></div>
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Cpu</label>
<div class="mt-2">
<input @bind="Request.Cpu" type="number" autocomplete="off" class="form-input w-full">
</div>
</div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Memory</label>
<div class="mt-2">
<input @bind="Request.Memory" type="number" autocomplete="off" class="form-input w-full">
</div>
</div>
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">Disk</label>
<div class="mt-2">
<input @bind="Request.Disk" type="number" autocomplete="off" class="form-input w-full">
</div>
</div>
</div>
</div>
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
private UserDetailResponse[]? Users;
private async Task<UserDetailResponse[]> Loader(string searchTerm)
{
if (Users == null)
{
Users = await PagedData<UserDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<UserDetailResponse>>(
$"api/admin/users?page={page}&pageSize={pageSize}"
)
);
}
if (string.IsNullOrEmpty(searchTerm))
return Users;
return Users
.Where(x => x.Email.Contains(searchTerm))
.ToArray();
}
}

View File

@@ -0,0 +1,70 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonCore.Helpers
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Models
@using MoonlightServers.Shared.Http.Responses.Admin.Servers
@using MoonlightServers.Shared.Http.Responses.Admin.StarVariables
@inject HttpApiClient ApiClient
<LazyLoader Load="Load">
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
@foreach (var variable in StarVariables)
{
// Load value of default
/*
var value = Request.Variables.TryGetValue(variable.Key, out var val)
? val
: variable.DefaultValue;*/
var value = "";
<div class="sm:col-span-2">
<label class="block text-sm font-medium leading-6 text-white">
@variable.Name
</label>
<div class="mt-2">
<input type="text"
class="form-input placeholder-gray-500 w-full"
value="@value"
placeholder="@variable.DefaultValue"
@onchange="@(args => UpdateValue(variable, args))"/>
</div>
<p class="mt-1 text-sm leading-6 text-gray-400">
@variable.Description
</p>
</div>
}
</div>
</LazyLoader>
@code
{
[Parameter] public UpdateServerRequest Request { get; set; }
[Parameter] public ServerDetailResponse Server { get; set; }
private StarVariableDetailResponse[] StarVariables;
private async Task Load(LazyLoader _)
{
StarVariables = await PagedData<StarVariableDetailResponse>.All(async (page, pageSize) =>
await ApiClient.GetJson<PagedData<StarVariableDetailResponse>>(
$"api/admin/servers/stars/{Server.StarId}/variables?page={page}&pageSize={pageSize}"
)
);
}
private async Task UpdateValue(StarVariableDetailResponse starVariable, ChangeEventArgs args)
{
/*
var value = args.Value?.ToString() ?? "";
// Remove variable from request when set to its default value
if (value == starVariable.DefaultValue && Request.Variables.ContainsKey(starVariable.Key))
Request.Variables.Remove(starVariable.Key);
else
Request.Variables[starVariable.Key] = value;
await InvokeAsync(StateHasChanged);*/
}
}

View File

@@ -29,7 +29,10 @@
<GeneralServerCreate Request="Request" /> <GeneralServerCreate Request="Request" />
</Tab> </Tab>
<Tab Name="Allocations"> <Tab Name="Allocations">
<AllocationsServerCrete Request="Request" /> <AllocationsServerCreate Request="Request" />
</Tab>
<Tab Name="Variables">
<VariablesServerCreate Request="Request" />
</Tab> </Tab>
<Tab Name="Advanced"> <Tab Name="Advanced">
<AdvancedServerCreate Request="Request" /> <AdvancedServerCreate Request="Request" />

View File

@@ -6,6 +6,7 @@
@using MoonCore.Helpers @using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Requests.Admin.Servers @using MoonlightServers.Shared.Http.Requests.Admin.Servers
@using MoonlightServers.Shared.Http.Responses.Admin.Servers @using MoonlightServers.Shared.Http.Responses.Admin.Servers
@using MoonlightServers.Frontend.UI.Components.Servers.UpdateServerPartials
@inject HttpApiClient ApiClient @inject HttpApiClient ApiClient
@inject NavigationManager Navigation @inject NavigationManager Navigation
@@ -25,7 +26,20 @@
<div class="mt-5"> <div class="mt-5">
<HandleForm @ref="Form" Model="Request" OnValidSubmit="OnSubmit"> <HandleForm @ref="Form" Model="Request" OnValidSubmit="OnSubmit">
<GeneratedForm TForm="UpdateServerRequest" Model="Request" OnConfigure="OnConfigure"/> <Tabs>
<Tab Name="General">
<GeneralServerUpdate Request="Request" />
</Tab>
<Tab Name="Allocations">
<AllocationsServerUpdate Request="Request" Server="Server" />
</Tab>
<Tab Name="Variables">
<VariablesServerUpdate Request="Request" Server="Server" />
</Tab>
<Tab Name="Advanced">
<AdvancedServerUpdate Request="Request" />
</Tab>
</Tabs>
</HandleForm> </HandleForm>
</div> </div>
</LazyLoader> </LazyLoader>
@@ -36,16 +50,12 @@
private HandleForm Form; private HandleForm Form;
private UpdateServerRequest Request; private UpdateServerRequest Request;
private ServerDetailResponse Server;
private async Task Load(LazyLoader _) private async Task Load(LazyLoader _)
{ {
var detail = await ApiClient.GetJson<ServerDetailResponse>($"api/admin/servers/{Id}"); var Server = await ApiClient.GetJson<ServerDetailResponse>($"api/admin/servers/{Id}");
Request = Mapper.Map<UpdateServerRequest>(detail); Request = Mapper.Map<UpdateServerRequest>(Server);
}
private void OnConfigure(FormConfiguration<UpdateServerRequest> configuration)
{
} }
private async Task OnSubmit() private async Task OnSubmit()

View File

@@ -17,8 +17,6 @@ public class UpdateServerRequest
[Range(1, int.MaxValue, ErrorMessage = "You need to provide a valid disk amount")] [Range(1, int.MaxValue, ErrorMessage = "You need to provide a valid disk amount")]
public int Disk { get; set; } public int Disk { get; set; }
public bool UseVirtualDisk { get; set; }
[Range(0, int.MaxValue, ErrorMessage = "You need to provide a valid bandwidth amount")] [Range(0, int.MaxValue, ErrorMessage = "You need to provide a valid bandwidth amount")]
public int Bandwidth { get; set; } public int Bandwidth { get; set; }
@@ -26,10 +24,11 @@ public class UpdateServerRequest
public int DockerImageIndex { get; set; } public int DockerImageIndex { get; set; }
public int StarId { get; set; } // TODO: Add star change
//public int StarId { get; set; }
public int NodeId { get; set; } // TODO: Add transfer
//public int NodeId { get; set; }
public int[] AllocationIds { get; set; } = []; public int[] AllocationIds { get; set; } = [];
public Dictionary<string, string> Variables { get; set; } = new();
} }

View File

@@ -7,7 +7,6 @@ public class NodeDetailResponse
public string Name { get; set; } public string Name { get; set; }
public string Fqdn { get; set; } public string Fqdn { get; set; }
public string Token { get; set; }
public int HttpPort { get; set; } public int HttpPort { get; set; }
public int FtpPort { get; set; } public int FtpPort { get; set; }

View File

@@ -22,4 +22,6 @@ public class ServerDetailResponse
public int StarId { get; set; } public int StarId { get; set; }
public int NodeId { get; set; } public int NodeId { get; set; }
public int[] AllocationIds { get; set; } = [];
} }