Upgraded server images to new mooncore forms

This commit is contained in:
Marcel Baumgartner
2024-06-27 11:50:44 +02:00
parent 53509ecf63
commit 326bd09662
15 changed files with 604 additions and 144 deletions

View File

@@ -50,4 +50,9 @@ public class DataContext : DbContext
);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}

View File

@@ -15,8 +15,8 @@
<div class="mt-5">
<FastCrud TItem="ApiKey"
OnConfigure="OnConfigure"
OnConfigureCreate="OnConfigureCreate"
OnConfigureEdit="OnConfigureEdit">
OnConfigureCreate="OnConfigureFrom"
OnConfigureEdit="OnConfigureFrom">
<View>
<MCBColumn TItem="ApiKey" Field="@(x => x.Key)" Title="Key">
<Template>
@@ -66,7 +66,7 @@
};
}
private void OnConfigureCreate(FastConfiguration<ApiKey> configuration)
private void OnConfigureFrom(FastConfiguration<ApiKey> configuration, ApiKey _)
{
configuration.AddProperty(x => x.Description)
.WithDefaultComponent()
@@ -81,6 +81,4 @@
.WithDefaultComponent()
.WithName("Permissions");
}
private void OnConfigureEdit(FastConfiguration<ApiKey> configuration, ApiKey _) => OnConfigureCreate(configuration);
}

View File

@@ -67,7 +67,7 @@
};
}
private void OnConfigureCreate(FastConfiguration<User> configuration)
private void OnConfigureCreate(FastConfiguration<User> configuration, User _)
{
configuration.AddProperty(x => x.Username)
.WithDefaultComponent()

View File

@@ -7,5 +7,5 @@ public class ServerDockerImage
public string DisplayName { get; set; } = "";
public string Name { get; set; } = "";
public bool AutoPull { get; set; }
public bool AutoPull { get; set; } = true;
}

View File

@@ -10,13 +10,13 @@ public class ServerImage
public string? UpdateUrl { get; set; }
public string? DonateUrl { get; set; }
public string StartupCommand { get; set; } = "";
public string OnlineDetection { get; set; } = "";
public string StopCommand { get; set; } = "";
public string StartupCommand { get; set; } = "echo Startup command here";
public string OnlineDetection { get; set; } = "Running";
public string StopCommand { get; set; } = "^C";
public string InstallShell { get; set; } = "";
public string InstallDockerImage { get; set; } = "";
public string InstallScript { get; set; } = "";
public string InstallShell { get; set; } = "/bin/bash";
public string InstallDockerImage { get; set; } = "debian:latest";
public string InstallScript { get; set; } = "#! /bin/bash\necho Done";
public string ParseConfiguration { get; set; } = "[]";
public int AllocationsNeeded { get; set; } = 1;

View File

@@ -0,0 +1,53 @@
@using Moonlight.Features.Servers.Entities
@using MoonCore.Blazor.Forms.Fast.Components
@inherits BaseFastFormComponent<int>
<div class="col-md-6 col-12">
<label class="form-label">@Name</label>
<MCBSelect TField="ServerDockerImage"
@bind-Value="SelectedDockerImage"
Items="SortedImages"
DisplayField="@(x => x.Name)"/>
</div>
@code
{
private ServerDockerImage? SelectedDockerImage
{
get
{
if (Binder.Value >= SortedImages.Count)
return null;
if (Binder.Value == -1)
return null;
return SortedImages[Binder.Value];
}
set
{
if (value == null)
{
Binder.Value = -1;
return;
}
Binder.Value = SortedImages.IndexOf(value);
}
}
private List<ServerDockerImage> SortedImages;
protected override void OnInitialized()
{
ArgumentNullException.ThrowIfNull(AdditionalOptions);
var image = AdditionalOptions.Get<ServerImage>("Image");
SortedImages = image.DockerImages
.OrderBy(x => x.Id)
.ToList();
}
}

View File

@@ -0,0 +1,41 @@
@using MoonCore.Blazor.Forms.Fast.Components
@using Moonlight.Features.FileManager.UI.Components
@inherits BaseFastFormComponent<string>
<div class="col-12">
<label class="form-label">
@Name
</label>
<Editor InitialContent="@Binder.Value"
Mode="@Mode"
Lines="@Lines"
EnableAutoInit="true"
OnChanged="OnValueChanged"/>
</div>
@code
{
private int Lines;
private string Mode;
protected override void OnInitialized()
{
if (AdditionalOptions == null)
{
Lines = 25;
Mode = "sh";
return;
}
Lines = AdditionalOptions.GetNullable<int?>("Lines") ?? 25;
Mode = AdditionalOptions.GetNullable<string?>("Mode") ?? "sh";
}
private Task OnValueChanged(string val)
{
Binder.Value = val;
return Task.CompletedTask;
}
}

View File

@@ -1,8 +1,14 @@
@using Moonlight.Features.Servers.Models.Forms.Admin.Images.DockerImages
@using Microsoft.AspNetCore.Components.Forms
@using MoonCore.Abstractions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using MoonCore.Exceptions
@using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Models.Forms.Admin.Images
@inject Repository<ServerImage> ImageRepository
@inject Repository<ServerDockerImage> DockerImageRepository
@*
<div class="card mb-10">
<div class="card-body">
<div class="row g-8">
@@ -22,19 +28,18 @@
</div>
</div>
</div>
</div>
@*
<AutoListCrud TItem="ServerDockerImage"
TRootItem="ServerImage"
TCreateForm="CreateDockerImage"
TUpdateForm="UpdateDockerImage"
RootItem="Image"
Field="@(x => x.DockerImages)">
</div>*@
<FastCrud TItem="ServerDockerImage"
Loader="Loader"
OnConfigure="OnConfigure"
OnConfigureCreate="OnConfigureForm"
OnConfigureEdit="OnConfigureForm">
<View>
<CrudColumn TItem="ServerDockerImage" Field="@(x => x.Id)" Title="Id"/>
<CrudColumn TItem="ServerDockerImage" Field="@(x => x.DisplayName)" Title="Display name"/>
<CrudColumn TItem="ServerDockerImage" Field="@(x => x.Name)" Title="Name"/>
<CrudColumn TItem="ServerDockerImage" Field="@(x => x.AutoPull)" Title="Auto pull">
<MCBColumn TItem="ServerDockerImage" Field="@(x => x.Id)" Title="Id"/>
<MCBColumn TItem="ServerDockerImage" Field="@(x => x.DisplayName)" Title="Display name"/>
<MCBColumn TItem="ServerDockerImage" Field="@(x => x.Name)" Title="Name"/>
<MCBColumn TItem="ServerDockerImage" Field="@(x => x.AutoPull)" Title="Auto pull">
<Template>
@if (context.AutoPull)
{
@@ -45,41 +50,78 @@
<i class="bx bx-sm bx-x text-danger"></i>
}
</Template>
</CrudColumn>
</MCBColumn>
</View>
<NoItemsView>
<IconAlert Title="No docker images found" Color="primary" Icon="bx-search-alt">
Add a new docker image in order to get started. Need help? Check out our <a href="https://docs.moonlightpanel.xyz">documentation</a>
</IconAlert>
</NoItemsView>
</AutoListCrud>
*@
</FastCrud>
@code
{
[Parameter] public ServerImage Image { get; set; }
[Parameter] public UpdateImageDetailedForm Form { get; set; }
private ServerDockerImage? SelectedDockerImage
private IEnumerable<ServerDockerImage> Loader(Repository<ServerDockerImage> repository)
{
get
{
if (Form.DefaultDockerImage >= Image.DockerImages.Count)
return null;
if (Form.DefaultDockerImage == -1)
return null;
return Image.DockerImages[Form.DefaultDockerImage];
}
set
{
if (value == null)
{
Form.DefaultDockerImage = -1;
return;
return Image.DockerImages;
}
Form.DefaultDockerImage = Image.DockerImages.IndexOf(value);
}
private void OnConfigure(FastCrudConfiguration<ServerDockerImage> configuration)
{
configuration.CustomCreate = dockerImage =>
{
Image.DockerImages.Add(dockerImage);
ImageRepository.Update(Image);
return Task.CompletedTask;
};
configuration.CustomDelete = dockerImage =>
{
Image.DockerImages.Remove(dockerImage);
ImageRepository.Update(Image);
try
{
DockerImageRepository.Delete(dockerImage);
}
catch (Exception)
{
/* Dont fail here */
}
return Task.CompletedTask;
};
configuration.ValidateCreate = dockerImage =>
{
if (Image.DockerImages.Any(x => x.Name == dockerImage.Name))
throw new DisplayException("A docker image with this name does already exist");
return Task.CompletedTask;
};
configuration.ValidateEdit = dockerImage =>
{
if (Image.DockerImages.Any(x => x.Name == dockerImage.Name && x.Id != dockerImage.Id))
throw new DisplayException("A docker image with this name does already exist");
return Task.CompletedTask;
};
}
private void OnConfigureForm(FastConfiguration<ServerDockerImage> configuration, ServerDockerImage _)
{
configuration.AddProperty(x => x.Name)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name"))
.WithDescription("This is the name of the docker image. E.g. moonlightpanel/moonlight:canary");
configuration.AddProperty(x => x.DisplayName)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithDescription("This will be shown if the user is able to change the docker image as the image name");
configuration.AddProperty(x => x.AutoPull)
.WithComponent<bool, SwitchComponent>()
.WithDescription("Specifies if the docker image should be pulled/updated when creating a server instance. Disable this for only local existing docker images");
}
}

View File

@@ -0,0 +1,159 @@
@using Mappy.Net
@using MoonCore.Blazor.Forms.Fast.Components
@using Moonlight.Features.Servers.Models
@using Moonlight.Features.Servers.Models.Forms.Admin.Images.Parsing
@using Newtonsoft.Json
@inherits BaseFastFormComponent<string>
<div class="d-flex justify-content-end mb-3">
<button @onclick="AddConfig" type="button" class="btn btn-icon btn-success">
<i class="bx bx-sm bx-plus"></i>
</button>
</div>
@foreach (var config in Configs)
{
<div class="accordion mt-1" id="accordionPc">
<div class="accordion-item mb-3">
<div class="accordion-header" id="apch@(config.GetHashCode())">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#apcb@(config.GetHashCode())" aria-expanded="false" aria-controls="apcb@(config.GetHashCode())">
<span class="h5">@(string.IsNullOrEmpty(config.Key.File) ? "File path is missing" : config.Key.File)</span>
</button>
</div>
<div id="apcb@(config.GetHashCode())" class="accordion-collapse collapse" aria-labelledby="apch@(config.GetHashCode())" data-bs-parent="#accordionPc">
<div class="accordion-body">
<div class="row g-5">
<div class="col-md-5">
<label class="form-label">File path</label>
<div class="form-text fs-5 mb-2 mt-0">
A relative path from the servers main directory to the file you want to modify
</div>
<input @bind="config.Key.File" @onfocusout="RefreshProperty" type="text" class="form-control" placeholder="e.g. configs/paper-global.yml">
</div>
<div class="col-md-5">
<label class="form-label">Type</label>
<div class="form-text fs-5 mb-2 mt-0">
This specifies the type of parser to use. e.g. "properties" or "file"
</div>
<input @bind="config.Key.Type" @onfocusout="RefreshProperty" type="text" class="form-control" placeholder="properties">
</div>
<div class="col-md-2">
<div class="text-end">
<WButton OnClick="() => RemoveConfig(config.Key)" CssClasses="btn btn-danger">Remove</WButton>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header border-bottom-0">
<div class="card-title"></div>
<div class="card-toolbar">
<button @onclick="() => AddOption(config.Key)" type="button" class="btn btn-icon btn-success">
<i class="bx bx-sm bx-plus"></i>
</button>
</div>
</div>
<div class="card-body pt-0">
<div class="row g-4">
@foreach (var option in config.Value)
{
<div class="col-md-6">
<div class="input-group">
<input @bind="option.Key" @onfocusout="RefreshProperty" type="text" class="form-control" placeholder="Key">
<input @bind="option.Value" @onfocusout="RefreshProperty" type="text" class="form-control" placeholder="Value (Variables with {{VARIABLE}})">
<WButton OnClick="() => RemoveOption(config.Key, option)" CssClasses="btn btn-danger">Remove</WButton>
</div>
</div>
}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
@code
{
[Parameter] public string InitialContent { get; set; }
private Dictionary<ParseConfigForm, List<ParseConfigOptionForm>> Configs = new();
protected override async Task OnInitializedAsync()
{
await Set(Binder.Value);
}
private async Task RefreshProperty()
{
Binder.Value = await Get();
}
public async Task Set(string content)
{
Configs.Clear();
var configs = JsonConvert.DeserializeObject<ServerParseConfig[]>(content) ?? [];
foreach (var config in configs)
{
var options = config.Configuration.Select(x => new ParseConfigOptionForm()
{
Key = x.Key,
Value = x.Value
}).ToList();
Configs.Add(Mapper.Map<ParseConfigForm>(config), options);
}
await InvokeAsync(StateHasChanged);
}
public Task<string> Get()
{
var finalConfigs = Configs.Select(x => new ServerParseConfig()
{
File = x.Key.File,
Type = x.Key.Type,
Configuration = x.Value.ToDictionary(y => y.Key, y => y.Value)
}).ToList();
var result = JsonConvert.SerializeObject(finalConfigs);
return Task.FromResult(result);
}
private async Task AddConfig()
{
Configs.Add(new(), new());
await InvokeAsync(StateHasChanged);
await RefreshProperty();
}
private async Task RemoveConfig(ParseConfigForm config)
{
Configs.Remove(config);
await InvokeAsync(StateHasChanged);
await RefreshProperty();
}
private async Task AddOption(ParseConfigForm config)
{
Configs[config].Add(new());
await InvokeAsync(StateHasChanged);
await RefreshProperty();
}
private async Task RemoveOption(ParseConfigForm config, ParseConfigOptionForm option)
{
Configs[config].Remove(option);
await InvokeAsync(StateHasChanged);
await RefreshProperty();
}
}

View File

@@ -1,20 +1,25 @@
@using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Models.Forms.Admin.Images.Variables
@using BlazorTable
@*
<AutoListCrud TItem="ServerImageVariable"
TRootItem="ServerImage"
TCreateForm="CreateImageVariable"
TUpdateForm="UpdateImageVariable"
RootItem="Image"
Field="@(x => x.Variables)">
@using MoonCore.Abstractions
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Exceptions
@using Moonlight.Features.Servers.Entities.Enums
@inject Repository<ServerImage> ImageRepository
@inject Repository<ServerImageVariable> VariableRepository
<FastCrud TItem="ServerImageVariable"
Loader="Loader"
OnConfigure="OnConfigure"
OnConfigureCreate="OnConfigureForm"
OnConfigureEdit="OnConfigureForm">
<View>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.Id)" Title="Id"/>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.DisplayName)" Title="Display name"/>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.Key)" Title="Key"/>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.DefaultValue)" Title="Default value"/>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.Filter)" Title="Filter"/>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.AllowView)" Title="View">
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.Id)" Title="Id"/>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.DisplayName)" Title="Display name"/>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.Key)" Title="Key"/>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.DefaultValue)" Title="Default value"/>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.Filter)" Title="Filter"/>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.AllowView)" Title="View">
<Template>
@if (context.AllowView)
{
@@ -25,8 +30,8 @@
<i class="bx bx-sm bx-x text-danger"></i>
}
</Template>
</CrudColumn>
<CrudColumn TItem="ServerImageVariable" Field="@(x => x.AllowEdit)" Title="Edit">
</MCBColumn>
<MCBColumn TItem="ServerImageVariable" Field="@(x => x.AllowEdit)" Title="Edit">
<Template>
@if (context.AllowEdit)
{
@@ -37,16 +42,98 @@
<i class="bx bx-sm bx-x text-danger"></i>
}
</Template>
</CrudColumn>
</MCBColumn>
</View>
<NoItemsView>
<IconAlert Title="No variables found" Color="primary" Icon="bx-search-alt">
Add a new variable in order to get started. Need help? Check out our <a href="https://docs.moonlightpanel.xyz">documentation</a>
</IconAlert>
</NoItemsView>
</AutoListCrud>
*@
</FastCrud>
@code
{
[Parameter] public ServerImage Image { get; set; }
private IEnumerable<ServerImageVariable> Loader(Repository<ServerImageVariable> _)
{
return Image.Variables;
}
private void OnConfigure(FastCrudConfiguration<ServerImageVariable> configuration)
{
configuration.CustomCreate = variable =>
{
Image.Variables.Add(variable);
ImageRepository.Update(Image);
return Task.CompletedTask;
};
configuration.CustomDelete = variable =>
{
Image.Variables.Remove(variable);
ImageRepository.Update(Image);
try
{
VariableRepository.Delete(variable);
}
catch (Exception)
{
/* dont fail here */
}
return Task.CompletedTask;
};
configuration.ValidateCreate = variable =>
{
if (Image.Variables.Any(x => x.Key == variable.Key))
throw new DisplayException("A variable with this key already exists");
return Task.CompletedTask;
};
configuration.ValidateEdit = variable =>
{
if (Image.Variables.Any(x => x.Key == variable.Key && x.Id != variable.Id))
throw new DisplayException("A variable with this key already exists");
return Task.CompletedTask;
};
}
private void OnConfigureForm(FastConfiguration<ServerImageVariable> configuration, ServerImageVariable _)
{
configuration.AddProperty(x => x.Key)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithDescription("This is the environment variable name");
configuration.AddProperty(x => x.DefaultValue)
.WithDefaultComponent()
.WithDescription("This is the default value which will be set when a server is created");
configuration.AddProperty(x => x.DisplayName)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithDescription("This is the display name of the variable which will be shown to the user if enabled to edit/view the variable");
configuration.AddProperty(x => x.Description)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithDescription("This text should describe what the variable does for the user if allowed to view and/or change");
configuration.AddProperty(x => x.AllowView)
.WithComponent<bool, SwitchComponent>()
.WithDescription("Allow the user to view the variable but not edit it unless specified otherwise");
configuration.AddProperty(x => x.AllowEdit)
.WithComponent<bool, SwitchComponent>()
.WithDescription("Allow the user to edit the variable. Wont work if view is disabled");
configuration.AddProperty(x => x.Type)
.WithComponent<ServerImageVariableType, EnumSelectComponent<ServerImageVariableType>>()
.WithDescription("Specifies the type of the variable. This specifies what ui the user will see for the variable. You can also specify the options which are available using the filter field");
configuration.AddProperty(x => x.Filter)
.WithDefaultComponent()
.WithDescription("(Optional)\nText: A regex filter which will check if the user input mathes a correct variable value\nSelect: Specify the available values seperated by a semicolon");
}
}

View File

@@ -1,7 +1,5 @@
@using System.ComponentModel.DataAnnotations
@using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Models.Forms.Admin.Nodes
@using BlazorTable
@using MoonCore.Abstractions
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@@ -41,8 +39,8 @@
<FastCrud TItem="ServerAllocation"
Loader="Loader"
OnConfigure="OnConfigure"
OnConfigureCreate="OnConfigureCreate"
OnConfigureEdit="OnConfigureEdit"
OnConfigureCreate="OnConfigureForm"
OnConfigureEdit="OnConfigureForm"
@ref="Crud">
<View>
<MCBColumn TItem="ServerAllocation" Field="@(x => x.Id)" Title="Id"/>
@@ -169,11 +167,12 @@
return Task.CompletedTask;
};
/*
configuration.CustomEdit = allocation =>
{
AllocationRepository.Update(allocation);
return Task.CompletedTask;
};
};*/
configuration.CustomDelete = allocation =>
{
@@ -193,7 +192,7 @@
};
}
private void OnConfigureCreate(FastConfiguration<ServerAllocation> configuration)
private void OnConfigureForm(FastConfiguration<ServerAllocation> configuration, ServerAllocation _)
{
configuration.AddProperty(x => x.IpAddress)
.WithDefaultComponent()
@@ -204,6 +203,4 @@
.WithDefaultComponent()
.WithValidation<int>(x => x >= 1 && x <= 65535 ? ValidationResult.Success : new ValidationResult("You need to provide a valid port"));
}
private void OnConfigureEdit(FastConfiguration<ServerAllocation> configuration, ServerAllocation _) => OnConfigureCreate(configuration);
}

View File

@@ -1,5 +1,6 @@
@page "/admin/servers/images"
@using System.ComponentModel.DataAnnotations
@using Moonlight.Features.Servers.UI.Components
@using Microsoft.EntityFrameworkCore
@using MoonCore.Abstractions
@@ -7,9 +8,11 @@
@using Moonlight.Features.Servers.Entities
@using Moonlight.Features.Servers.Helpers
@using Moonlight.Features.Servers.Models.Forms.Admin.Images
@using Microsoft.AspNetCore.Components.Forms
@using MoonCore.Helpers
@using MoonCore.Blazor.Forms.Fast.Components
@using MoonCore.Blazor.Models.Fast
@using MoonCore.Blazor.Models.Fast.Validators
@using Moonlight.Features.Servers.UI.ImageComponents
@inject Repository<Server> ServerRepository
@inject Repository<ServerImageVariable> VariableRepository
@@ -26,14 +29,11 @@
<AdminServersNavigation Index="2"/>
<AutoCrud TItem="ServerImage"
TCreateForm="CreateImageForm"
TUpdateForm="UpdateImageForm"
Loader="Load"
ValidateDelete="ValidateDelete"
ValidateAdd="ValidateAdd"
CustomDelete="CustomDelete"
@ref="Crud">
<FastCrud TItem="ServerImage"
Loader="Loader"
OnConfigure="OnConfigure"
OnConfigureCreate="OnConfigureForm"
OnConfigureEdit="OnConfigureForm">
<View>
<MCBColumn TItem="ServerImage" Field="@(x => x.Id)" Title="Id" Filterable="true"/>
<MCBColumn TItem="ServerImage" Field="@(x => x.Name)" Title="Name" Filterable="true">
@@ -68,61 +68,139 @@
</div>
</Template>
</MCBColumn>
</View>@*
<NoItemsView>
<IconAlert Title="No images found" Color="primary" Icon="bx-search-alt">
Download and import a image from our <a href="https://github.com/Moonlight-Panel/Images">repository</a> or create a new one. Need help? Check out our <a href="https://docs.moonlightpanel.xyz">documentation</a>
</IconAlert>
</NoItemsView>
<OverviewToolbar>
<SmartCustomFileSelect @ref="EggUpload" OnFileSelected="ImportEgg">
<a class="btn btn-info me-3">
</View>
<ViewToolbar>
<MCBCustomFileSelect @ref="EggUpload" OnFileSelected="ImportEgg">
<a class="btn btn-info me-2">
Import egg
</a>
</SmartCustomFileSelect>
<SmartCustomFileSelect @ref="ImageUpload" OnFileSelected="Import">
</MCBCustomFileSelect>
<MCBCustomFileSelect @ref="ImageUpload" OnFileSelected="Import">
<a class="btn btn-info me-3">
Import
</a>
</SmartCustomFileSelect>
</OverviewToolbar>*@
</AutoCrud>
</MCBCustomFileSelect>
</ViewToolbar>
</FastCrud>
@code
{
private AutoCrud<ServerImage, CreateImageForm, UpdateImageForm> Crud;
private FastCrud<ServerImage> Crud;
private MCBCustomFileSelect ImageUpload;
private MCBCustomFileSelect EggUpload;
private IEnumerable<ServerImage> Load(Repository<ServerImage> repository)
private IEnumerable<ServerImage> Loader(Repository<ServerImage> repository)
{
return repository.Get();
return repository
.Get()
.Include(x => x.DockerImages)
.Include(x => x.Variables);
}
private Task ValidateDelete(ServerImage serverImage)
private void OnConfigure(FastCrudConfiguration<ServerImage> configuration)
{
if (ServerRepository.Get().Any(x => x.Image.Id == serverImage.Id))
configuration.ValidateDelete = image =>
{
if (ServerRepository.Get().Any(x => x.Image.Id == image.Id))
throw new DisplayException("A server using this image exists. Please delete the servers using this image to continue");
return Task.CompletedTask;
};
configuration.CustomDelete = CustomDelete;
}
private Task ValidateAdd(ServerImage image)
private void OnConfigureForm(FastConfiguration<ServerImage> configuration, ServerImage image)
{
// Set defaults
// General
configuration.AddProperty(x => x.Name)
.WithDefaultComponent()
.WithPage("General")
.WithValidation(FastValidators.Required);
image.StopCommand = "^C";
image.StartupCommand = "echo Startup command here";
image.AllocationsNeeded = 1;
image.InstallScript = "#! /bin/bash\necho Done";
image.InstallShell = "/bin/bash";
image.InstallDockerImage = "debian:latest";
image.OnlineDetection = "Running";
image.AllowDockerImageChange = false;
image.DefaultDockerImage = 0;
image.ParseConfiguration = "[]";
configuration.AddProperty(x => x.Author)
.WithDefaultComponent()
.WithPage("General")
.WithValidation(FastValidators.Required);
return Task.CompletedTask;
configuration.AddProperty(x => x.DonateUrl)
.WithDefaultComponent()
.WithPage("General")
.WithDescription("Provide a url here in order to give people the ability to donate for your work");
configuration.AddProperty(x => x.UpdateUrl)
.WithDefaultComponent()
.WithPage("General")
.WithDescription("A http(s) url directly to a json file which will serve as an update for the image. When a update is fetched, it will just get this url and try to load it");
// Power
configuration.AddProperty(x => x.StartupCommand)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithPage("Start, Stop & Status")
.WithDescription("This command will be executed at the start of a server. You can use environment variables in a {} here");
configuration.AddProperty(x => x.OnlineDetection)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithPage("Start, Stop & Status")
.WithDescription("A regex string specifying that a server is online when the daemon finds a match in the console output matching this expression");
configuration.AddProperty(x => x.StopCommand)
.WithDefaultComponent()
.WithValidation(FastValidators.Required)
.WithPage("Start, Stop & Status")
.WithDescription("A command which will be sent to the servers stdin when it should get stopped. Power signals can be achived by using ^. E.g. ^C");
// Parsing
configuration.AddProperty(x => x.ParseConfiguration)
.WithComponent<string, ImageParseConfigEditor>()
.WithPage("Parsing");
configuration.AddCustomPage("Variables", ComponentHelper.FromType<ImageVariables>(parameters =>
{
parameters.Add("Image", image);
}));
configuration.AddCustomPage("Docker Images", ComponentHelper.FromType<ImageDockerImages>(parameters =>
{
parameters.Add("Image", image);
}));
configuration.AddProperty(x => x.AllowDockerImageChange)
.WithComponent<bool, SwitchComponent>()
.WithPage("Miscellaneous")
.WithDescription("This toggle specifies if a user is allowed to change the docker image from the list of docker images associated to the image");
configuration.AddProperty(x => x.DefaultDockerImage)
.WithComponent<int, DefaultDockerImage>()
.WithAdditionalOption("Image", image)
.WithPage("Miscellaneous");
configuration.AddProperty(x => x.AllocationsNeeded)
.WithDefaultComponent()
.WithPage("Miscellaneous")
.WithValidation<int>(x => x > 1 ? ValidationResult.Success : new ValidationResult("This specifies the amount of allocations needed for this image in order to create a server"));
configuration.AddProperty(x => x.InstallDockerImage)
.WithDefaultComponent()
.WithPage("Installation")
.WithName("Docker Image")
.WithValidation(FastValidators.Required)
.WithValidation(RegexValidator.Create("^(?:[a-zA-Z0-9\\-\\.]+\\/)?[a-zA-Z0-9\\-]+(?:\\/[a-zA-Z0-9\\-]+)*(?::[a-zA-Z0-9_\\.-]+)?$", "You need to provide a valid docker image name"));
configuration.AddProperty(x => x.InstallShell)
.WithDefaultComponent()
.WithPage("Installation")
.WithName("Shell")
.WithValidation(FastValidators.Required);
configuration.AddProperty(x => x.InstallScript)
.WithComponent<string, EditorComponent>()
.WithPage("Installation")
.WithName("Script")
.WithValidation(FastValidators.Required);
}
private Task CustomDelete(ServerImage serverImage)

View File

@@ -207,7 +207,7 @@
};
}
private void OnConfigureCreate(FastConfiguration<ServerNode> configuration)
private void OnConfigureCreate(FastConfiguration<ServerNode> configuration, ServerNode _)
{
configuration.AddProperty(x => x.Name)
.WithDefaultComponent()

View File

@@ -92,7 +92,7 @@
};
}
private void OnConfigureCreate(FastConfiguration<ServerNetwork> configuration)
private void OnConfigureCreate(FastConfiguration<ServerNetwork> configuration, ServerNetwork _)
{
configuration.AddProperty(x => x.Name)
.WithDefaultComponent()

View File

@@ -94,7 +94,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MoonCore" Version="1.4.1" />
<PackageReference Include="MoonCore.Blazor" Version="1.1.0" />
<PackageReference Include="MoonCore.Blazor" Version="1.1.1" />
<PackageReference Include="Otp.NET" Version="1.3.0" />
<PackageReference Include="QRCoder" Version="1.4.3" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.6.2" />