Started implementing star crud

This commit is contained in:
2024-12-05 17:27:17 +01:00
parent 3b77b3df1e
commit 291b80cc60
13 changed files with 342 additions and 79 deletions

View File

@@ -0,0 +1,77 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MoonCore.Attributes;
using MoonCore.Extended.Helpers;
using MoonCore.Helpers;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.Stars;
using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages;
using MoonlightServers.Shared.Http.Responses.Admin.Stars;
using MoonlightServers.Shared.Http.Responses.Admin.StarVariables;
namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars;
[ApiController]
[Route("api/admin/servers/stars")]
public class StarController : Controller
{
private readonly CrudHelper<Star, StarDetailResponse> CrudHelper;
public StarController(CrudHelper<Star, StarDetailResponse> crudHelper)
{
CrudHelper = crudHelper;
CrudHelper.QueryModifier = stars => stars
.Include(x => x.Variables)
.Include(x => x.DockerImages);
CrudHelper.LateMapper = (star, response) =>
{
response.DockerImages = star.DockerImages
.Select(x => Mapper.Map<StarDockerImageDetailResponse>(x))
.ToArray();
response.Variables = star.Variables
.Select(x => Mapper.Map<StarVariableDetailResponse>(x))
.ToArray();
return response;
};
}
[HttpGet]
[RequirePermission("admin.servers.stars.get")]
public async Task<IPagedData<StarDetailResponse>> Get([FromQuery] int page, [FromQuery] int pageSize)
{
return await CrudHelper.Get(page, pageSize);
}
[HttpGet("{id:int}")]
[RequirePermission("admin.servers.stars.get")]
public async Task<StarDetailResponse> GetSingle([FromRoute] int id)
{
return await CrudHelper.GetSingle(id);
}
[HttpPost]
[RequirePermission("admin.servers.stars.create")]
public async Task<StarDetailResponse> Create([FromBody] CreateStarRequest request)
{
return await CrudHelper.Create(request);
}
[HttpPatch("{id:int}")]
[RequirePermission("admin.servers.stars.update")]
public async Task<StarDetailResponse> Update([FromRoute] int id, [FromBody] UpdateStarRequest request)
{
return await CrudHelper.Update(id, request);
}
[HttpDelete("{id:int}")]
[RequirePermission("admin.servers.stars.delete")]
public async Task Delete([FromRoute] int id)
{
await CrudHelper.Delete(id);
}
}

View File

@@ -20,7 +20,6 @@
<ItemGroup>
<Folder Include="Database\Migrations\"/>
<Folder Include="Helpers\"/>
<Folder Include="Http\Controllers\" />
<Folder Include="Http\Middleware\"/>
<Folder Include="Implementations\"/>
<Folder Include="Interfaces\"/>

View File

@@ -5,75 +5,8 @@
@import "additions/fonts.css";
@import "additions/buttons.css";
@import "additions/cards.css";
@import "additions/forms.css";
@import "additions/progress.css";
@import "additions/scrollbar.css";
@import "additions/loaders.css";
@import "tailwindcss/utilities";
#blazor-error-ui {
display: none;
}
#loader {
display: block;
width: 10rem;
height: 10rem;
border-radius: 50%;
border: 3px solid transparent;
border-top-color: #9370DB;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
@apply border-t-primary-500
}
#loader:before {
content: "";
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
border-radius: 50%;
border: 3px solid transparent;
-webkit-animation: spin 3s linear infinite;
animation: spin 3s linear infinite;
@apply border-t-tertiary-500
}
#loader:after {
content: "";
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
border-radius: 50%;
border: 3px solid transparent;
-webkit-animation: spin 1.5s linear infinite;
animation: spin 1.5s linear infinite;
@apply border-t-info-500
}
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}

View File

@@ -0,0 +1,59 @@
@page "/admin/servers/stars/create"
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Forms
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@inject HttpApiClient ApiClient
@inject NavigationManager Navigation
@inject ToastService ToastService
<PageHeader Title="Create Star">
<WButton OnClick="_ => GoBack()" CssClasses="btn btn-secondary">
<i class="icon-chevron-left mr-1"></i>
Back
</WButton>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary">
<i class="icon-check mr-1"></i>
Create
</WButton>
</PageHeader>
<div class="mt-5">
<HandleForm @ref="Form" Model="Request" OnValidSubmit="OnSubmit">
<GeneratedForm TForm="CreateStarRequest" Model="Request" OnConfigure="OnConfigure"/>
</HandleForm>
</div>
@code
{
private HandleForm Form;
private CreateStarRequest Request;
protected override void OnInitialized()
{
Request = new();
}
private void OnConfigure(FormConfiguration<CreateStarRequest> configuration)
{
}
private async Task OnSubmit()
{
await ApiClient.Post("api/admin/servers/stars", Request);
await ToastService.Success("Successfully created Star");
await GoBack();
}
private Task GoBack()
{
Navigation.NavigateTo(ComponentHelper.GetRouteOfComponent<Index>()!);
return Task.CompletedTask;
}
}

View File

@@ -0,0 +1,29 @@
@page "/admin/servers/stars"
@using MoonCore.Blazor.Tailwind.MinimalCrud
@using MoonCore.Helpers
@using MoonCore.Models
@using MoonCore.Blazor.Tailwind.DataTable
@using MoonlightServers.Shared.Http.Responses.Admin.Stars
@inject HttpApiClient ApiClient
<MinimalCrud TItem="StarDetailResponse" OnConfigure="OnConfigure">
<ChildContent>
<DataColumn TItem="StarDetailResponse" Field="@(x => x.Id)" Title="Id" IsSortable="true"/>
</ChildContent>
</MinimalCrud>
@code
{
private void OnConfigure(MinimalCrudOptions<StarDetailResponse> options)
{
options.Title = "Stars";
options.ItemLoader = async (page, pageSize) =>
await ApiClient.GetJson<PagedData<StarDetailResponse>>($"api/admin/servers/stars?page={page}&pageSize={pageSize}");
options.CreateUrl = ComponentHelper.GetRouteOfComponent<Create>();
options.UpdateUrl = item => ComponentHelper.GetRouteOfComponent<Update>(item.Id)!;
options.DeleteFunction = async item => await ApiClient.Delete($"api/admin/servers/stars/{item.Id}");
}
}

View File

@@ -0,0 +1,61 @@
@page "/admin/servers/stars/update/{Id:int}"
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Forms
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@using MoonlightServers.Shared.Http.Responses.Admin.Stars
@inject HttpApiClient ApiClient
@inject NavigationManager Navigation
@inject ToastService ToastService
<LazyLoader Load="Load">
<PageHeader Title="Update Star">
<button @onclick="GoBack" type="button" class="btn btn-secondary">
<i class="icon-chevron-left mr-1"></i>
Back
</button>
<WButton OnClick="_ => Form.Submit()" CssClasses="btn btn-primary">
<i class="icon-check mr-1"></i>
Update
</WButton>
</PageHeader>
<div class="mt-5">
<HandleForm @ref="Form" Model="Request" OnValidSubmit="OnSubmit">
<GeneratedForm TForm="UpdateStarRequest" Model="Request" OnConfigure="OnConfigure"/>
</HandleForm>
</div>
</LazyLoader>
@code
{
[Parameter] public int Id { get; set; }
private HandleForm Form;
private UpdateStarRequest Request;
private async Task Load(LazyLoader _)
{
var detail = await ApiClient.GetJson<StarDetailResponse>($"api/stars/{Id}");
Request = Mapper.Map<UpdateStarRequest>(detail);
}
private void OnConfigure(FormConfiguration<UpdateStarRequest> configuration)
{
}
private async Task OnSubmit()
{
await ApiClient.Patch($"api/stars/{Id}", Request);
await ToastService.Success("Successfully updated Star");
GoBack();
}
private void GoBack()
=> Navigation.NavigateTo(ComponentHelper.GetRouteOfComponent<Index>()!);
}

View File

@@ -0,0 +1,45 @@
using System.ComponentModel.DataAnnotations;
namespace MoonlightServers.Shared.Http.Requests.Admin.Stars;
public class CreateStarRequest
{
[Required(ErrorMessage = "You need to specify a name")]
public string Name { get; set; }
[Required(ErrorMessage = "You need to specify a author")]
public string Author { get; set; }
public string? UpdateUrl { get; set; }
public string? DonateUrl { get; set; }
[Required(ErrorMessage = "You need to specify a startup command")]
public string StartupCommand { get; set; } = "echo Starting up :)";
[Required(ErrorMessage = "You need to specify a stop command")]
public string StopCommand { get; set; } = "^C";
[Required(ErrorMessage = "You need to specify a online detection string")]
public string OnlineDetection { get; set; }
[Required(ErrorMessage = "You need to specify an install shell")]
public string InstallShell { get; set; } = "/bin/bash";
[Required(ErrorMessage = "You need to specify an install docker image")]
[RegularExpression("^(?:(?=[^:\\/]{1,253})(?!-)[a-zA-Z0-9-]{1,63}(?<!-)(?:\\.(?!-)[a-zA-Z0-9-]{1,63}(?<!-))*(?::[0-9]{1,5})?\\/)?((?![._-])(?:[a-z0-9._-]*)(?<![._-])(?:\\/(?![._-])[a-z0-9._-]*(?<![._-]))*)(?::(?![.-])[a-zA-Z0-9_.-]{1,128})?$", ErrorMessage = "You need to specify a valid docker image")]
public string InstallDockerImage { get; set; } = "debian:latest";
[Required(ErrorMessage = "You need to specify an install script")]
public string InstallScript { get; set; } = "echo Installing...";
[Range(0, 20, ErrorMessage = "You need to provide a valid amount of allocations")]
public int RequiredAllocations { get; set; } = 1;
public bool AllowDockerImageChange { get; set; } = false;
[Required(ErrorMessage = "You need to provide parse configuration")]
public string ParseConfiguration { get; set; } = "[]";
}

View File

@@ -0,0 +1,6 @@
namespace MoonlightServers.Shared.Http.Requests.Admin.Stars;
public class UpdateStarRequest
{
}

View File

@@ -0,0 +1,10 @@
namespace MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages;
public class StarDockerImageDetailResponse
{
public int Id { get; set; }
public string DisplayName { get; set; }
public string Identifier { get; set; }
public bool AutoPulling { get; set; }
}

View File

@@ -0,0 +1,20 @@
using MoonlightServers.Shared.Enums;
namespace MoonlightServers.Shared.Http.Responses.Admin.StarVariables;
public class StarVariableDetailResponse
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Key { get; set; }
public string DefaultValue { get; set; }
public bool AllowViewing { get; set; }
public bool AllowEditing { get; set; }
public StarVariableType Type { get; set; }
public string? Filter { get; set; }
}

View File

@@ -0,0 +1,34 @@
using MoonlightServers.Shared.Http.Responses.Admin.StarDockerImages;
using MoonlightServers.Shared.Http.Responses.Admin.StarVariables;
namespace MoonlightServers.Shared.Http.Responses.Admin.Stars;
public class StarDetailResponse
{
public int Id { get; set; }
// References
public StarVariableDetailResponse[] Variables { get; set; }
public StarDockerImageDetailResponse[] DockerImages { get; set; }
// Meta
public string Name { get; set; }
public string Author { get; set; }
public string? UpdateUrl { get; set; }
public string? DonateUrl { get; set; }
// Start and stop
public string StartupCommand { get; set; }
public string StopCommand { get; set; }
public string OnlineDetection { get; set; }
// Install
public string InstallShell { get; set; }
public string InstallDockerImage { get; set; }
public string InstallScript { get; set; }
// Misc
public int RequiredAllocations { get; set; }
public bool AllowDockerImageChange { get; set; }
public string ParseConfiguration { get; set; }
}

View File

@@ -1,6 +0,0 @@
namespace MoonlightServers.Shared.Http.Responses;
public class ExampleResponse
{
public int Number { get; set; }
}

View File

@@ -6,8 +6,4 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Http\Requests\"/>
</ItemGroup>
</Project>