Add version field to star entity. Implemented a lot of the star crud

This commit is contained in:
2024-12-06 15:03:28 +01:00
parent 1520d0b2b1
commit de1b54d652
27 changed files with 1448 additions and 194 deletions

View File

@@ -10,6 +10,7 @@ public class Star
// Meta
public string Name { get; set; }
public string Version { get; set; }
public string Author { get; set; }
public string? UpdateUrl { get; set; }
public string? DonateUrl { get; set; }

View File

@@ -0,0 +1,431 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MoonlightServers.ApiServer.Database;
#nullable disable
namespace MoonlightServers.ApiServer.Database.Migrations
{
[DbContext(typeof(ServersDataContext))]
[Migration("20241206083153_AddedVersionTagForStar")]
partial class AddedVersionTagForStar
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Servers")
.HasAnnotation("ProductVersion", "8.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Allocation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("IpAddress")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("NodeId")
.HasColumnType("int");
b.Property<int>("Port")
.HasColumnType("int");
b.Property<int?>("ServerId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("NodeId");
b.HasIndex("ServerId");
b.ToTable("Allocations", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Node", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("EnableDynamicFirewall")
.HasColumnType("tinyint(1)");
b.Property<bool>("EnableTransparentMode")
.HasColumnType("tinyint(1)");
b.Property<string>("Fqdn")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("FtpPort")
.HasColumnType("int");
b.Property<int>("HttpPort")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Token")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Nodes", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Server", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Bandwidth")
.HasColumnType("int");
b.Property<int>("Cpu")
.HasColumnType("int");
b.Property<int>("Disk")
.HasColumnType("int");
b.Property<int>("DockerImageIndex")
.HasColumnType("int");
b.Property<int>("Memory")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("NodeId")
.HasColumnType("int");
b.Property<int>("OwnerId")
.HasColumnType("int");
b.Property<int>("StarId")
.HasColumnType("int");
b.Property<string>("StartupOverride")
.HasColumnType("longtext");
b.Property<bool>("UseVirtualDisk")
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.HasIndex("NodeId");
b.HasIndex("StarId");
b.ToTable("Servers", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.ServerBackup", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("Completed")
.HasColumnType("tinyint(1)");
b.Property<DateTime>("CompletedAt")
.HasColumnType("datetime(6)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<long>("Size")
.HasColumnType("bigint");
b.Property<bool>("Successful")
.HasColumnType("tinyint(1)");
b.HasKey("Id");
b.ToTable("ServerBackups", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.ServerVariable", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Key")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("ServerId")
.HasColumnType("int");
b.Property<string>("Value")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ServerId");
b.ToTable("ServerVariables", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Star", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("AllowDockerImageChange")
.HasColumnType("tinyint(1)");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("DonateUrl")
.HasColumnType("longtext");
b.Property<string>("InstallDockerImage")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("InstallScript")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("InstallShell")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("OnlineDetection")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("ParseConfiguration")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("RequiredAllocations")
.HasColumnType("int");
b.Property<string>("StartupCommand")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("StopCommand")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("UpdateUrl")
.HasColumnType("longtext");
b.Property<string>("Version")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Stars", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.StarDockerImage", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("AutoPulling")
.HasColumnType("tinyint(1)");
b.Property<string>("DisplayName")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Identifier")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("StarId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("StarId");
b.ToTable("StarDockerImages", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.StarVariable", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("AllowEditing")
.HasColumnType("tinyint(1)");
b.Property<bool>("AllowViewing")
.HasColumnType("tinyint(1)");
b.Property<string>("DefaultValue")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Filter")
.HasColumnType("longtext");
b.Property<string>("Key")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("StarId")
.HasColumnType("int");
b.Property<int>("Type")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("StarId");
b.ToTable("StarVariables", "Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Allocation", b =>
{
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Node", "Node")
.WithMany("Allocations")
.HasForeignKey("NodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Server", "Server")
.WithMany("Allocations")
.HasForeignKey("ServerId");
b.Navigation("Node");
b.Navigation("Server");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Server", b =>
{
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Node", "Node")
.WithMany("Servers")
.HasForeignKey("NodeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Star", "Star")
.WithMany()
.HasForeignKey("StarId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Node");
b.Navigation("Star");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.ServerVariable", b =>
{
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Server", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Server");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.StarDockerImage", b =>
{
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Star", "Star")
.WithMany("DockerImages")
.HasForeignKey("StarId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Star");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.StarVariable", b =>
{
b.HasOne("MoonlightServers.ApiServer.Database.Entities.Star", "Star")
.WithMany("Variables")
.HasForeignKey("StarId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Star");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Node", b =>
{
b.Navigation("Allocations");
b.Navigation("Servers");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Server", b =>
{
b.Navigation("Allocations");
});
modelBuilder.Entity("MoonlightServers.ApiServer.Database.Entities.Star", b =>
{
b.Navigation("DockerImages");
b.Navigation("Variables");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MoonlightServers.ApiServer.Database.Migrations
{
/// <inheritdoc />
public partial class AddedVersionTagForStar : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Version",
schema: "Servers",
table: "Stars",
type: "longtext",
nullable: false)
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Version",
schema: "Servers",
table: "Stars");
}
}
}

View File

@@ -251,6 +251,10 @@ namespace MoonlightServers.ApiServer.Database.Migrations
b.Property<string>("UpdateUrl")
.HasColumnType("longtext");
b.Property<string>("Version")
.IsRequired()
.HasColumnType("longtext");
b.HasKey("Id");
b.ToTable("Stars", "Servers");

View File

@@ -0,0 +1,106 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MoonCore.Attributes;
using MoonCore.Exceptions;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers;
using MoonCore.Helpers;
using MoonCore.Models;
using MoonlightServers.ApiServer.Database.Entities;
using MoonlightServers.Shared.Http.Requests.Admin.StarVariables;
using MoonlightServers.Shared.Http.Responses.Admin.StarVariables;
namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars;
[ApiController]
[Route("api/admin/servers/stars")]
public class StarVariablesController : Controller
{
private readonly CrudHelper<StarVariable, StarVariableDetailResponse> CrudHelper;
private readonly DatabaseRepository<Star> StarRepository;
private readonly DatabaseRepository<StarVariable> StarVariableRepository;
private Star Star;
public StarVariablesController(
CrudHelper<StarVariable, StarVariableDetailResponse> crudHelper,
DatabaseRepository<Star> starRepository,
DatabaseRepository<StarVariable> starVariableRepository)
{
CrudHelper = crudHelper;
StarRepository = starRepository;
StarVariableRepository = starVariableRepository;
}
private void ApplyStar(int id)
{
var star = StarRepository
.Get()
.FirstOrDefault(x => x.Id == id);
if (star == null)
throw new HttpApiException("A star with this id could not be found", 404);
Star = star;
CrudHelper.QueryModifier = variables =>
variables.Where(x => x.Star.Id == star.Id);
}
[HttpGet("{starId:int}/variables")]
[RequirePermission("admin.servers.stars.get")]
public async Task<IPagedData<StarVariableDetailResponse>> Get([FromRoute] int starId, [FromQuery] int page, [FromQuery] int pageSize)
{
ApplyStar(starId);
return await CrudHelper.Get(page, pageSize);
}
[HttpGet("{starId:int}/variables/{id:int}")]
[RequirePermission("admin.servers.stars.get")]
public async Task<StarVariableDetailResponse> GetSingle([FromRoute] int starId, [FromRoute] int id)
{
ApplyStar(starId);
return await CrudHelper.GetSingle(id);
}
[HttpPost("{starId:int}/variables")]
[RequirePermission("admin.servers.stars.create")]
public async Task<StarVariableDetailResponse> Create([FromRoute] int starId, [FromBody] CreateStarVariableRequest request)
{
ApplyStar(starId);
var starVariable = Mapper.Map<StarVariable>(request);
starVariable.Star = Star;
var finalVariable = StarVariableRepository.Add(starVariable);
return CrudHelper.MapToResult(finalVariable);
}
[HttpPatch("{starId:int}/variables/{id:int}")]
[RequirePermission("admin.servers.stars.update")]
public async Task<StarVariableDetailResponse> Update([FromRoute] int starId, [FromRoute] int id,
[FromBody] UpdateStarVariableRequest request)
{
ApplyStar(starId);
var variable = await CrudHelper.GetSingleModel(id);
variable = Mapper.Map(variable, request);
StarVariableRepository.Update(variable);
return CrudHelper.MapToResult(variable);
}
[HttpDelete("{starId:int}/variables/{id:int}")]
[RequirePermission("admin.servers.stars.delete")]
public async Task Delete([FromRoute] int starId, [FromRoute] int id)
{
ApplyStar(starId);
await CrudHelper.Delete(id);
}
}

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using MoonCore.Attributes;
using MoonCore.Extended.Abstractions;
using MoonCore.Extended.Helpers;
using MoonCore.Helpers;
using MoonCore.Models;
@@ -14,13 +15,15 @@ namespace MoonlightServers.ApiServer.Http.Controllers.Admin.Stars;
[ApiController]
[Route("api/admin/servers/stars")]
public class StarController : Controller
public class StarsController : Controller
{
private readonly CrudHelper<Star, StarDetailResponse> CrudHelper;
private readonly DatabaseRepository<Star> StarRepository;
public StarController(CrudHelper<Star, StarDetailResponse> crudHelper)
public StarsController(CrudHelper<Star, StarDetailResponse> crudHelper, DatabaseRepository<Star> starRepository)
{
CrudHelper = crudHelper;
StarRepository = starRepository;
CrudHelper.QueryModifier = stars => stars
.Include(x => x.Variables)
@@ -58,7 +61,25 @@ public class StarController : Controller
[RequirePermission("admin.servers.stars.create")]
public async Task<StarDetailResponse> Create([FromBody] CreateStarRequest request)
{
return await CrudHelper.Create(request);
var star = Mapper.Map<Star>(request);
// Default values
star.DonateUrl = null;
star.UpdateUrl = null;
star.Version = "1.0.0";
star.StartupCommand = "echo Starting up :)";
star.StopCommand = "^C";
star.OnlineDetection = "Online text";
star.InstallShell = "/bin/bash";
star.InstallDockerImage = "debian:latest";
star.InstallScript = "echo Installing...";
star.RequiredAllocations = 1;
star.AllowDockerImageChange = false;
star.ParseConfiguration = "[]";
var finalStar = StarRepository.Add(star);
return CrudHelper.MapToResult(finalStar);
}
[HttpPatch("{id:int}")]

View File

@@ -1,90 +0,0 @@
@using MoonCore.Blazor.Tailwind.Forms
@using MoonlightServers.Shared.Enums
@typeparam TPropertyType where TPropertyType : class, MoonlightServers.Shared.Interfaces.IStarVariable
@inherits BaseFormComponent<List<TPropertyType>>
<div class="flex justify-end mb-5">
<button type="button" @onclick="AddVariable" class="btn btn-primary">Add variable</button>
</div>
<div class="grid grid-cols-2 gap-4">
@foreach (var variable in Binder.Value)
{
<div class="col-span-1 card p-0">
<div class="card-body grid grid-cols-2 gap-2">
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Name</label>
<input @bind="variable.Name" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Description</label>
<input @bind="variable.Description" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Key</label>
<input @bind="variable.Key" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Default Value</label>
<input @bind="variable.DefaultValue" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Viewing</label>
<Switch @bind-Value="variable.AllowViewing" />
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Editing</label>
<Switch @bind-Value="variable.AllowEditing" />
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Type</label>
<select @bind="variable.Type" class="form-select w-full">
@foreach (var val in Enum.GetValues<StarVariableType>())
{
<option value="@val">@val</option>
}
</select>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Filter</label>
<input @bind="variable.Filter" type="text" class="form-input w-full"/>
</div>
</div>
<div class="card-footer">
<div class="flex justify-end mx-2">
<button @onclick="() => DeleteVariable(variable)" class="btn btn-danger">
<i class="icon-trash mr-2"></i>
Remove
</button>
</div>
</div>
</div>
}
</div>
@code
{
private async Task AddVariable()
{
Binder.Value.Add(Activator.CreateInstance<TPropertyType>());
await InvokeAsync(StateHasChanged);
}
private async Task DeleteVariable(TPropertyType variable)
{
Binder.Value.Remove(variable);
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,77 @@
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonCore.Blazor.Tailwind.Components
@using MoonlightServers.Shared.Models
@inherits BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new parse configuration</h1>
<HandleForm @ref="HandleForm" Model="Form" OnValidSubmit="OnValidSubmit">
<div class="grid grid-cols-2 gap-x-2 gap-y-4">
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">File</label>
<input @bind="Form.File" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Type</label>
<select @bind="Form.Parser" class="form-select w-full">
@foreach (var val in Enum.GetValues<FileParsers>())
{
<option value="@val">@val</option>
}
</select>
</div>
<div class="col-span-2">
<button @onclick="AddEntry" class="btn btn-primary w-full">Add entry</button>
</div>
@foreach (var entry in Form.Entries)
{
<div class="col-span-2">
<div class="flex flex-row">
<input @bind="entry.Key" placeholder="Key" class="form-input placeholder-gray-500 grow rounded-r-none"/>
<input @bind="entry.Value" placeholder="Value" class="form-input placeholder-gray-500 grow rounded-none"/>
<button @onclick="() => RemoveEntry(entry)" class="btn btn-danger grow-0 rounded-l-none">
<i class="icon-x"></i>
</button>
</div>
</div>
}
</div>
</HandleForm>
<div class="mt-5 flex space-x-2">
<WButton OnClick="_ => Hide()" CssClasses="btn btn-secondary grow">Cancel</WButton>
<WButton OnClick="_ => Submit()" CssClasses="btn btn-primary grow">Create</WButton>
</div>
@code
{
[Parameter] public Func<ParseConfiguration, Task> OnSubmit { get; set; }
private ParseConfiguration Form = new();
private HandleForm HandleForm;
private async Task OnValidSubmit()
{
await OnSubmit.Invoke(Form);
await Hide();
}
private Task Submit() => HandleForm.Submit();
private async Task AddEntry()
{
Form.Entries.Add(new());
await InvokeAsync(StateHasChanged);
}
private async Task RemoveEntry(ParseConfiguration.ParseConfigurationEntry entry)
{
Form.Entries.Remove(entry);
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,79 @@
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Blazor.Tailwind.Components
@inherits BaseModal
<h1 class="mb-5 font-semibold text-xl">Add a new variable</h1>
<HandleForm @ref="HandleForm" Model="Form" OnValidSubmit="OnValidSubmit">
<div class="grid grid-cols-2 gap-2">
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Name</label>
<input @bind="Form.Name" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Description</label>
<input @bind="Form.Description" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Key</label>
<input @bind="Form.Key" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Default Value</label>
<input @bind="Form.DefaultValue" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Viewing</label>
<Switch @bind-Value="Form.AllowViewing"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Editing</label>
<Switch @bind-Value="Form.AllowEditing"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Type</label>
<select @bind="Form.Type" class="form-select w-full">
@foreach (var val in Enum.GetValues<StarVariableType>())
{
<option value="@val">@val</option>
}
</select>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Filter</label>
<input @bind="Form.Filter" type="text" class="form-input w-full"/>
</div>
</div>
</HandleForm>
<div class="mt-5 flex space-x-2">
<WButton OnClick="_ => Hide()" CssClasses="btn btn-secondary grow">Cancel</WButton>
<WButton OnClick="_ => Submit()" CssClasses="btn btn-primary grow">Create</WButton>
</div>
@code
{
[Parameter] public Func<CreateStarVariableRequest, Task> OnSubmit { get; set; }
private CreateStarVariableRequest Form = new();
private HandleForm HandleForm;
private async Task OnValidSubmit()
{
await OnSubmit.Invoke(Form);
await Hide();
}
private Task Submit() => HandleForm.Submit();
}

View File

@@ -0,0 +1,84 @@
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Helpers
@using MoonlightServers.Shared.Models
@inherits BaseModal
<h1 class="mb-5 font-semibold text-xl">Update parse configuration</h1>
<HandleForm @ref="HandleForm" Model="Form" OnValidSubmit="OnValidSubmit">
<div class="grid grid-cols-2 gap-x-2 gap-y-4">
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">File</label>
<input @bind="Form.File" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Type</label>
<select @bind="Form.Parser" class="form-select w-full">
@foreach (var val in Enum.GetValues<FileParsers>())
{
<option value="@val">@val</option>
}
</select>
</div>
<div class="col-span-2">
<button @onclick="AddEntry" class="btn btn-primary w-full">Add entry</button>
</div>
@foreach (var entry in Form.Entries)
{
<div class="col-span-2">
<div class="flex flex-row">
<input @bind="entry.Key" placeholder="Key" class="form-input placeholder-gray-500 grow rounded-r-none"/>
<input @bind="entry.Value" placeholder="Value" class="form-input placeholder-gray-500 grow rounded-none"/>
<button @onclick="() => RemoveEntry(entry)" class="btn btn-danger grow-0 rounded-l-none">
<i class="icon-x"></i>
</button>
</div>
</div>
}
</div>
</HandleForm>
<div class="mt-5 flex space-x-2">
<WButton OnClick="_ => Submit()" CssClasses="btn btn-primary grow">Save changes</WButton>
</div>
@code
{
[Parameter] public Func<ParseConfiguration, Task> OnSubmit { get; set; }
[Parameter] public ParseConfiguration Configuration { get; set; }
private ParseConfiguration Form;
private HandleForm HandleForm;
protected override void OnInitialized()
{
// Manual mapping :(
Form = Configuration;
}
private async Task OnValidSubmit()
{
await OnSubmit.Invoke(Form);
await Hide();
}
private Task Submit() => HandleForm.Submit();
private async Task AddEntry()
{
Form.Entries.Add(new());
await InvokeAsync(StateHasChanged);
}
private async Task RemoveEntry(ParseConfiguration.ParseConfigurationEntry entry)
{
Form.Entries.Remove(entry);
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,87 @@
@using MoonCore.Blazor.Tailwind.Modals.Components
@using MoonlightServers.Shared.Enums
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Responses.Admin.StarVariables
@inherits BaseModal
<h1 class="mb-5 font-semibold text-xl">Update variable</h1>
<HandleForm @ref="HandleForm" Model="Form" OnValidSubmit="OnValidSubmit">
<div class="grid grid-cols-2 gap-2">
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Name</label>
<input @bind="Form.Name" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Description</label>
<input @bind="Form.Description" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Key</label>
<input @bind="Form.Key" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Default Value</label>
<input @bind="Form.DefaultValue" type="text" class="form-input w-full"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Viewing</label>
<Switch @bind-Value="Form.AllowViewing"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Allow Editing</label>
<Switch @bind-Value="Form.AllowEditing"/>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Type</label>
<select @bind="Form.Type" class="form-select w-full">
@foreach (var val in Enum.GetValues<StarVariableType>())
{
<option value="@val">@val</option>
}
</select>
</div>
<div class="col-span-1">
<label class="block text-sm font-medium leading-6 text-white">Filter</label>
<input @bind="Form.Filter" type="text" class="form-input w-full"/>
</div>
</div>
</HandleForm>
<div class="mt-5 flex space-x-2">
<WButton OnClick="_ => Hide()" CssClasses="btn btn-secondary grow">Cancel</WButton>
<WButton OnClick="_ => Submit()" CssClasses="btn btn-primary grow">Update</WButton>
</div>
@code
{
[Parameter] public Func<UpdateStarVariableRequest, Task> OnSubmit { get; set; }
[Parameter] public StarVariableDetailResponse Variable { get; set; }
private UpdateStarVariableRequest Form;
private HandleForm HandleForm;
protected override void OnInitialized()
{
Form = Mapper.Map<UpdateStarVariableRequest>(Variable);
}
private async Task OnValidSubmit()
{
await OnSubmit.Invoke(Form);
await Hide();
}
private Task Submit() => HandleForm.Submit();
}

View File

@@ -0,0 +1,41 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
<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">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">Version</label>
<div class="mt-2">
<input @bind="Request.Version" 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">Author</label>
<div class="mt-2">
<input @bind="Request.Author" 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">Donate Url</label>
<div class="mt-2">
<input @bind="Request.DonateUrl" 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">Update Url</label>
<div class="mt-2">
<input @bind="Request.UpdateUrl" type="text" autocomplete="off" class="form-input w-full">
</div>
</div>
</div>
</div>
@code
{
[Parameter] public UpdateStarRequest Request { get; set; }
}

View File

@@ -0,0 +1,28 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
<div>
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-3">
<label class="block text-sm font-medium leading-6 text-white">Docker Image</label>
<div class="mt-2">
<input @bind="Request.InstallDockerImage" type="text" autocomplete="off" class="form-input w-full">
</div>
</div>
<div class="sm:col-span-3">
<label class="block text-sm font-medium leading-6 text-white">Shell</label>
<div class="mt-2">
<input @bind="Request.InstallShell" type="text" autocomplete="off" class="form-input w-full">
</div>
</div>
<div class="sm:col-span-6">
<label class="block text-sm font-medium leading-6 text-white">Script</label>
<div class="mt-2">
<textarea @bind="Request.InstallScript" class="form-textarea w-full"></textarea>
</div>
</div>
</div>
</div>
@code
{
[Parameter] public UpdateStarRequest Request { get; set; }
}

View File

@@ -0,0 +1,133 @@
@using System.Text.Json
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonCore.Blazor.Tailwind.Modals
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonlightServers.Frontend.UI.Components.Stars.Modals
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@using MoonlightServers.Shared.Models
@inject ILogger<ParseConfigStarUpdate> Logger
@inject ModalService ModalService
@inject AlertService AlertService
@inject ToastService ToastService
<div class="flex justify-end mb-5">
<button type="button" @onclick="AddConfig" class="btn btn-primary">Add parse configuration</button>
</div>
@if (HasParseError)
{
}
else
{
<div class="grid sm:grid-cols-2 xl:grid-cols-3 gap-4">
@foreach (var configuration in Configurations)
{
<div class="col-span-1 card card-body p-2.5">
<div class="flex items-center justify-between">
<div class="ml-3">
<i class="icon-file-cog text-xl align-middle"></i>
<span class="align-middle text-lg">@configuration.File</span>
</div>
<div class="gap-x-2">
<button @onclick="() => UpdateConfig(configuration)" class="btn btn-primary">
<i class="icon-settings text-base"></i>
</button>
<button @onclick="() => DeleteConfig(configuration)" class="btn btn-danger">
<i class="icon-trash text-base"></i>
</button>
</div>
</div>
</div>
}
</div>
}
@code
{
[Parameter] public UpdateStarRequest Request { get; set; }
private List<ParseConfiguration> Configurations;
private bool HasParseError = false;
protected override Task OnInitializedAsync()
{
ReadFromJson();
return Task.CompletedTask;
}
private async Task AddConfig()
{
Func<ParseConfiguration, Task> onSubmit = async configuration =>
{
Configurations.Add(configuration);
SaveChanges();
await InvokeAsync(StateHasChanged);
await ToastService.Success("Successfully created parse configuration");
};
await ModalService.Launch<CreateParseConfigModal>(parameters =>
{
parameters.Add("OnSubmit", onSubmit);
}, "max-w-xl");
}
private async Task UpdateConfig(ParseConfiguration configuration)
{
Func<ParseConfiguration, Task> onSubmit = async _ =>
{
SaveChanges();
await InvokeAsync(StateHasChanged);
await ToastService.Success("Successfully updated parse configuration");
};
await ModalService.Launch<UpdateParseConfigModal>(parameters =>
{
parameters.Add("OnSubmit", onSubmit);
parameters.Add("Configuration", configuration);
}, "max-w-xl");
}
private async Task DeleteConfig(ParseConfiguration configuration)
{
await AlertService.ConfirmDanger(
"Parse configuration deletion",
"Do you really want to delete the selected parse configuration",
async () =>
{
Configurations.Remove(configuration);
SaveChanges();
await InvokeAsync(StateHasChanged);
await ToastService.Success("Successfully deleted parse configuration");
}
);
}
private void SaveChanges()
{
Request.ParseConfiguration = JsonSerializer.Serialize(Configurations);
ReadFromJson();
}
private void ReadFromJson()
{
try
{
Configurations = JsonSerializer.Deserialize<List<ParseConfiguration>>(Request.ParseConfiguration)
?? throw new ArgumentNullException();
HasParseError = false;
}
catch (Exception e)
{
Logger.LogWarning("An error occured while reading parse configuration: {e}", e);
HasParseError = true;
}
}
}

View File

@@ -0,0 +1,28 @@
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
<div>
<div class="grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
<div class="sm:col-span-4">
<label class="block text-sm font-medium leading-6 text-white">Startup Command</label>
<div class="mt-2">
<input @bind="Request.StartupCommand" 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">Stop Command</label>
<div class="mt-2">
<input @bind="Request.StopCommand" 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">Online Detection</label>
<div class="mt-2">
<input @bind="Request.OnlineDetection" type="text" autocomplete="off" class="form-input w-full">
</div>
</div>
</div>
</div>
@code
{
[Parameter] public UpdateStarRequest Request { get; set; }
}

View File

@@ -0,0 +1,112 @@
@using MoonCore.Blazor.Tailwind.Alerts
@using MoonlightServers.Shared.Http.Responses.Admin.Stars
@using MoonlightServers.Shared.Http.Responses.Admin.StarVariables
@using MoonCore.Blazor.Tailwind.Components
@using MoonCore.Blazor.Tailwind.Modals
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@using MoonCore.Models
@using MoonlightServers.Frontend.UI.Components.Stars.Modals
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@inject HttpApiClient ApiClient
@inject ModalService ModalService
@inject AlertService AlertService
@inject ToastService ToastService
<div class="flex justify-end mb-5">
<button type="button" @onclick="AddVariable" class="btn btn-primary">Add variable</button>
</div>
<LazyLoader @ref="LazyLoader" Load="Load">
<div class="grid sm:grid-cols-2 xl:grid-cols-3 gap-4">
@foreach (var variable in Variables)
{
<div class="col-span-1 card card-body p-2.5">
<div class="flex items-center justify-between">
<div class="ml-3">
<i class="icon-variable text-xl align-middle"></i>
<span class="align-middle text-lg">@variable.Name</span>
</div>
<div class="gap-x-2">
<button @onclick="() => UpdateVariable(variable)" class="btn btn-primary">
<i class="icon-settings text-base"></i>
</button>
<button @onclick="() => DeleteVariable(variable)" class="btn btn-danger">
<i class="icon-trash text-base"></i>
</button>
</div>
</div>
</div>
}
</div>
</LazyLoader>
@code
{
[Parameter] public StarDetailResponse Star { get; set; }
private StarVariableDetailResponse[] Variables;
private LazyLoader LazyLoader;
private async Task Load(LazyLoader arg)
{
var pagedVariables = await ApiClient.GetJson<PagedData<StarVariableDetailResponse>>(
$"api/admin/servers/stars/{Star.Id}/variables?page=0&pageSize=50"
);
Variables = pagedVariables.Items;
}
private async Task AddVariable()
{
Func<CreateStarVariableRequest, Task> onSubmit = async request =>
{
await ApiClient.Post($"api/admin/servers/stars/{Star.Id}/variables", request);
await ToastService.Success("Successfully created variable");
await LazyLoader.Reload();
};
await ModalService.Launch<CreateStarVariableModal>(parameters =>
{
parameters.Add("OnSubmit", onSubmit);
}, "max-w-xl");
}
private async Task UpdateVariable(StarVariableDetailResponse variable)
{
Func<UpdateStarVariableRequest, Task> onSubmit = async request =>
{
await ApiClient.Patch($"api/admin/servers/stars/{Star.Id}/variables/{variable.Id}", request);
await ToastService.Success("Successfully updated variable");
await LazyLoader.Reload();
};
await ModalService.Launch<UpdateStarVariableModel>(parameters =>
{
parameters.Add("OnSubmit", onSubmit);
parameters.Add("Variable", variable);
}, "max-w-xl");
}
private async Task DeleteVariable(StarVariableDetailResponse variable)
{
await AlertService.ConfirmDanger(
"Delete variable",
"Do you really want to delete the selected variable? This cannot be undone",
async () =>
{
await ApiClient.Delete($"api/admin/servers/stars/{Star.Id}/variables/{variable.Id}");
await ToastService.Success("Successfully deleted variable");
await LazyLoader.Reload();
}
);
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -4,6 +4,7 @@
@using MoonCore.Blazor.Tailwind.Forms
@using MoonCore.Blazor.Tailwind.Toasts
@using MoonCore.Helpers
@using Moonlight.Client.Services
@using MoonlightServers.Frontend.UI.Components.Forms
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@using MoonlightServers.Shared.Http.Requests.Admin.StarVariables
@@ -11,6 +12,7 @@
@inject HttpApiClient ApiClient
@inject NavigationManager Navigation
@inject ToastService ToastService
@inject IdentityService IdentityService
<PageHeader Title="Create Star">
<button @onclick="GoBack" class="btn btn-secondary">
@@ -42,46 +44,12 @@
private void OnConfigure(FormConfiguration<CreateStarRequest> configuration)
{
var generalPage = configuration.WithPage("General");
generalPage.WithField(x => x.Name);
generalPage.WithField(x => x.Author);
generalPage.WithField(x => x.DonateUrl);
generalPage.WithField(x => x.UpdateUrl);
var startStopStatusPage = configuration.WithPage("Start, Stop & Status");
startStopStatusPage.WithField(x => x.StartupCommand);
startStopStatusPage.WithField(x => x.StopCommand);
startStopStatusPage.WithField(x => x.OnlineDetection);
var installationPage = configuration.WithPage("Installation");
installationPage.WithField(x => x.InstallShell);
installationPage.WithField(x => x.InstallDockerImage);
installationPage.WithField(x => x.InstallScript, fieldConfiguration =>
{
fieldConfiguration.Columns = 6;
});
var parseConfigurationPage = configuration.WithPage("Parse configuration");
parseConfigurationPage.WithField(x => x.ParseConfiguration);
var variablesPage = configuration.WithPage("Variables");
configuration.WithField(x => x.Name);
variablesPage.WithField(x => x.Variables, fieldConfiguration =>
{
fieldConfiguration.Columns = 6;
fieldConfiguration.Label = "";
})
.WithComponent<StarVariableComponent<CreateStarVariableRequest>>();
var miscPage = configuration.WithPage("Miscellaneous");
miscPage.WithField(x => x.AllowDockerImageChange);
miscPage.WithField(x => x.RequiredAllocations);
configuration.WithField(x => x.Author, fieldConfiguration =>
{
fieldConfiguration.DefaultValue = IdentityService.Email;
});
}
private async Task OnSubmit()

View File

@@ -16,7 +16,27 @@
<MinimalCrud TItem="StarDetailResponse" OnConfigure="OnConfigure">
<ChildContent>
<DataColumn TItem="StarDetailResponse" Field="@(x => x.Id)" Title="Id" IsSortable="true"/>
<DataColumn TItem="StarDetailResponse" Field="@(x => x.Name)" Title="Name" IsSortable="true"/>
<DataColumn TItem="StarDetailResponse" Field="@(x => x.Version)" Title="Version" IsSortable="true"/>
<DataColumn TItem="StarDetailResponse" Field="@(x => x.Author)" Title="Author"/>
</ChildContent>
<ItemActions>
@if (!string.IsNullOrEmpty(context.DonateUrl))
{
<a href="@context.DonateUrl" class="text-red-500 mr-3">
<i class="icon-heart align-middle"></i>
<span class="align-middle">Donate</span>
</a>
}
@if (!string.IsNullOrEmpty(context.UpdateUrl))
{
<a href="#" @onclick:preventDefault class="text-tertiary-500 mr-3">
<i class="icon-refresh-cw align-middle"></i>
<span class="align-middle">Update</span>
</a>
}
</ItemActions>
</MinimalCrud>
@code

View File

@@ -6,6 +6,7 @@
@using MoonCore.Helpers
@using MoonlightServers.Shared.Http.Requests.Admin.Stars
@using MoonlightServers.Shared.Http.Responses.Admin.Stars
@using MoonlightServers.Frontend.UI.Components.Stars.UpdateStarPartials
@inject HttpApiClient ApiClient
@inject NavigationManager Navigation
@@ -25,7 +26,29 @@
<div class="mt-5">
<HandleForm @ref="Form" Model="Request" OnValidSubmit="OnSubmit">
<GeneratedForm TForm="UpdateStarRequest" Model="Request" OnConfigure="OnConfigure"/>
<Tabs>
<Tab Name="General">
<GeneralStarUpdate Request="Request" />
</Tab>
<Tab Name="Start, Stop & Status">
<StartStopStatusStarUpdate Request="Request" />
</Tab>
<Tab Name="Parse Configuration">
<ParseConfigStarUpdate Request="Request" />
</Tab>
<Tab Name="Installation">
<InstallationStarUpdate Request="Request" />
</Tab>
<Tab Name="Variables">
<VariablesStarUpdate Star="Detail" />
</Tab>
</Tabs>
</HandleForm>
</div>
</LazyLoader>
@@ -36,21 +59,55 @@
private HandleForm Form;
private UpdateStarRequest Request;
private StarDetailResponse Detail;
private async Task Load(LazyLoader _)
{
var detail = await ApiClient.GetJson<StarDetailResponse>($"api/stars/{Id}");
Request = Mapper.Map<UpdateStarRequest>(detail);
Detail = await ApiClient.GetJson<StarDetailResponse>($"api/admin/servers/stars/{Id}");
Request = Mapper.Map<UpdateStarRequest>(Detail);
}
private void OnConfigure(FormConfiguration<UpdateStarRequest> configuration)
{
var generalPage = configuration.WithPage("General");
generalPage.WithField(x => x.Name);
generalPage.WithField(x => x.Version);
generalPage.WithField(x => x.Author);
generalPage.WithField(x => x.DonateUrl);
generalPage.WithField(x => x.UpdateUrl);
var startStopStatusPage = configuration.WithPage("Start, Stop & Status");
startStopStatusPage.WithField(x => x.StartupCommand);
startStopStatusPage.WithField(x => x.StopCommand);
startStopStatusPage.WithField(x => x.OnlineDetection);
var installationPage = configuration.WithPage("Installation");
installationPage.WithField(x => x.InstallShell);
installationPage.WithField(x => x.InstallDockerImage);
installationPage.WithField(x => x.InstallScript, fieldConfiguration =>
{
fieldConfiguration.Columns = 6;
});
var parseConfigurationPage = configuration.WithPage("Parse configuration");
parseConfigurationPage.WithField(x => x.ParseConfiguration);
var variablesPage = configuration.WithPage("Variables");
var miscPage = configuration.WithPage("Miscellaneous");
miscPage.WithField(x => x.AllowDockerImageChange);
miscPage.WithField(x => x.RequiredAllocations);
}
private async Task OnSubmit()
{
await ApiClient.Patch($"api/stars/{Id}", Request);
await ApiClient.Patch($"api/admin/servers/stars/{Id}", Request);
await ToastService.Success("Successfully updated Star");
GoBack();

View File

@@ -0,0 +1,7 @@
namespace MoonlightServers.Shared.Enums;
public enum FileParsers
{
File = 0,
Properties = 1
}

View File

@@ -1,10 +1,9 @@
using System.ComponentModel.DataAnnotations;
using MoonlightServers.Shared.Enums;
using MoonlightServers.Shared.Interfaces;
namespace MoonlightServers.Shared.Http.Requests.Admin.StarVariables;
public class CreateStarVariableRequest : IStarVariable
public class CreateStarVariableRequest
{
[Required(ErrorMessage = "You need to specify a variable name")]
public string Name { get; set; }

View File

@@ -0,0 +1,25 @@
using System.ComponentModel.DataAnnotations;
using MoonlightServers.Shared.Enums;
namespace MoonlightServers.Shared.Http.Requests.Admin.StarVariables;
public class UpdateStarVariableRequest
{
[Required(ErrorMessage = "You need to specify a variable name")]
public string Name { get; set; }
[Required(ErrorMessage = "You need to specify a variable description", AllowEmptyStrings = true)]
public string Description { get; set; } = "";
[Required(ErrorMessage = "You need to specify a variable key")]
public string Key { get; set; }
[Required(ErrorMessage = "You need to specify a variable default value", AllowEmptyStrings = true)]
public string DefaultValue { get; set; } = "";
public bool AllowViewing { get; set; }
public bool AllowEditing { get; set; }
public StarVariableType Type { get; set; } = StarVariableType.Text;
public string? Filter { get; set; } = null;
}

View File

@@ -10,39 +10,4 @@ public class CreateStarRequest
[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; } = "[]";
public List<CreateStarVariableRequest> Variables { get; set; } = new();
}

View File

@@ -1,6 +1,48 @@
using System.ComponentModel.DataAnnotations;
namespace MoonlightServers.Shared.Http.Requests.Admin.Stars;
public class UpdateStarRequest
{
[Required(ErrorMessage = "You need to specify a name")]
public string Name { get; set; }
[Required(ErrorMessage = "You need to specify a version")]
public string Version { 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; }
[Required(ErrorMessage = "You need to specify a stop command")]
public string StopCommand { get; set; }
[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; }
[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; }
[Required(ErrorMessage = "You need to specify an install script")]
public string InstallScript { get; set; }
[Range(0, 20, ErrorMessage = "You need to provide a valid amount of allocations")]
public int RequiredAllocations { get; set; }
public bool AllowDockerImageChange { get; set; }
[Required(ErrorMessage = "You need to provide parse configuration")]
public string ParseConfiguration { get; set; }
}

View File

@@ -13,6 +13,7 @@ public class StarDetailResponse
// Meta
public string Name { get; set; }
public string Version { get; set; }
public string Author { get; set; }
public string? UpdateUrl { get; set; }
public string? DonateUrl { get; set; }

View File

@@ -1,20 +0,0 @@
using MoonlightServers.Shared.Enums;
namespace MoonlightServers.Shared.Interfaces;
public interface IStarVariable // For a common abstraction between create and update model to use in a shared form component
{
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,17 @@
using MoonlightServers.Shared.Enums;
namespace MoonlightServers.Shared.Models;
public class ParseConfiguration
{
public string File { get; set; }
public FileParsers Parser { get; set; }
public List<ParseConfigurationEntry> Entries { get; set; } = new();
public class ParseConfigurationEntry
{
public string Key { get; set; }
public string Value { get; set; }
}
}