Improved image editor and added more options
This commit is contained in:
parent
4e5124cc1b
commit
aaee81e9c4
13 changed files with 1282 additions and 18 deletions
1043
Moonlight/Core/Database/Migrations/20240129160704_AddedAllowUserToChangeDockerImage.Designer.cs
generated
Normal file
1043
Moonlight/Core/Database/Migrations/20240129160704_AddedAllowUserToChangeDockerImage.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,29 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.Core.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedAllowUserToChangeDockerImage : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "AllowUserToChangeDockerImage",
|
||||||
|
table: "ServerImages",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "AllowUserToChangeDockerImage",
|
||||||
|
table: "ServerImages");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -275,6 +275,9 @@ namespace Moonlight.Core.Database.Migrations
|
||||||
b.Property<int>("AllocationsNeeded")
|
b.Property<int>("AllocationsNeeded")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("AllowUserToChangeDockerImage")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("Author")
|
b.Property<string>("Author")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
|
@ -22,5 +22,6 @@ public class ServerImage
|
||||||
public List<ServerImageVariable> Variables { get; set; } = new();
|
public List<ServerImageVariable> Variables { get; set; } = new();
|
||||||
|
|
||||||
public int DefaultDockerImageIndex { get; set; } = 0;
|
public int DefaultDockerImageIndex { get; set; } = 0;
|
||||||
|
public bool AllowUserToChangeDockerImage { get; set; }
|
||||||
public List<ServerDockerImage> DockerImages { get; set; }
|
public List<ServerDockerImage> DockerImages { get; set; }
|
||||||
}
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Moonlight.Features.Servers.Models.Forms.Admin.Images;
|
||||||
|
|
||||||
|
public class CreateImageVariable
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "You need to specify a key")]
|
||||||
|
[Description("This is the environment variable name")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[Description("This is the default value which will be set when a server is created")]
|
||||||
|
public string DefaultValue { get; set; } = "";
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "You need to specify a display name")]
|
||||||
|
[Description("This is the display name of the variable which will be shown to the user if enabled to edit/view the variable")]
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
|
||||||
|
[Description("This text should describe what the variable does for the user if allowed to view and/or change")]
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
|
||||||
|
[Description("Allow the user to edit the variable. Wont work if view is disabled")]
|
||||||
|
public bool AllowUserToEdit { get; set; } = false;
|
||||||
|
|
||||||
|
[Description("Allow the user to view the variable but not edit it unless specified otherwise")]
|
||||||
|
public bool AllowUserToView { get; set; } = false;
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Moonlight.Features.Servers.Models.Forms.Admin.Images;
|
||||||
|
|
||||||
|
public class UpdateImageVariable
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "You need to specify a key")]
|
||||||
|
[Description("This is the environment variable name")]
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
[Description("This is the default value which will be set when a server is created")]
|
||||||
|
public string DefaultValue { get; set; } = "";
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "You need to specify a display name")]
|
||||||
|
[Description("This is the display name of the variable which will be shown to the user if enabled to edit/view the variable")]
|
||||||
|
public string DisplayName { get; set; }
|
||||||
|
|
||||||
|
[Description("This text should describe what the variable does for the user if allowed to view and/or change")]
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
|
||||||
|
[Description("Allow the user to edit the variable. Wont work if view is disabled")]
|
||||||
|
public bool AllowUserToEdit { get; set; } = false;
|
||||||
|
|
||||||
|
[Description("Allow the user to view the variable but not edit it unless specified otherwise")]
|
||||||
|
public bool AllowUserToView { get; set; } = false;
|
||||||
|
}
|
|
@ -2,9 +2,12 @@
|
||||||
|
|
||||||
@using Moonlight.Features.Servers.Entities
|
@using Moonlight.Features.Servers.Entities
|
||||||
@using Moonlight.Core.Repositories
|
@using Moonlight.Core.Repositories
|
||||||
|
@using Moonlight.Core.Services.Interop
|
||||||
@using Moonlight.Features.Servers.UI.Components
|
@using Moonlight.Features.Servers.UI.Components
|
||||||
|
@using Moonlight.Core.Exceptions
|
||||||
|
|
||||||
@inject Repository<ServerImage> ImageRepository
|
@inject Repository<ServerImage> ImageRepository
|
||||||
|
@inject ToastService ToastService
|
||||||
|
|
||||||
<LazyLoader ShowAsCard="true" Load="Load">
|
<LazyLoader ShowAsCard="true" Load="Load">
|
||||||
@if (Image == null)
|
@if (Image == null)
|
||||||
|
@ -14,6 +17,14 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<AdminImageViewNavigation Index="2" ImageId="@Id" />
|
<AdminImageViewNavigation Index="2" ImageId="@Id" />
|
||||||
|
|
||||||
|
<ParseConfigEditor @ref="ParseConfigEditor" InitialContent="@Image.ParseConfigurations" />
|
||||||
|
|
||||||
|
<div class="card card-body mt-5">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<WButton Text="Save" CssClasses="btn btn-success" OnClick="OnSave" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
|
|
||||||
|
@ -24,6 +35,8 @@
|
||||||
|
|
||||||
private ServerImage? Image;
|
private ServerImage? Image;
|
||||||
|
|
||||||
|
private ParseConfigEditor ParseConfigEditor;
|
||||||
|
|
||||||
private Task Load(LazyLoader arg)
|
private Task Load(LazyLoader arg)
|
||||||
{
|
{
|
||||||
Image = ImageRepository
|
Image = ImageRepository
|
||||||
|
@ -32,4 +45,19 @@
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task OnSave()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Image!.ParseConfigurations = await ParseConfigEditor.ValidateAndGet();
|
||||||
|
ImageRepository.Update(Image);
|
||||||
|
|
||||||
|
await ToastService.Success("Successfully updated image");
|
||||||
|
}
|
||||||
|
catch (DisplayException e)
|
||||||
|
{
|
||||||
|
await ToastService.Danger(e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<button type="submit" class="btn btn-success">Create</button>
|
<button type="submit" class="btn btn-success">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SmartForm>
|
</SmartForm>
|
||||||
|
|
|
@ -6,18 +6,45 @@
|
||||||
@using Moonlight.Features.Servers.UI.Components
|
@using Moonlight.Features.Servers.UI.Components
|
||||||
@using BlazorTable
|
@using BlazorTable
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using Moonlight.Core.Services.Interop
|
||||||
|
@using Microsoft.AspNetCore.Components.Forms
|
||||||
|
|
||||||
@inject Repository<ServerImage> ImageRepository
|
@inject Repository<ServerImage> ImageRepository
|
||||||
|
@inject ToastService ToastService
|
||||||
|
|
||||||
<LazyLoader ShowAsCard="true" Load="Load">
|
<LazyLoader ShowAsCard="true" Load="Load">
|
||||||
@if (Image == null)
|
@if (Image == null)
|
||||||
{
|
{
|
||||||
<NotFoundAlert />
|
<NotFoundAlert/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<AdminImageViewNavigation Index="4" ImageId="@Id" />
|
<AdminImageViewNavigation Index="4" ImageId="@Id"/>
|
||||||
|
|
||||||
|
<div class="card mb-5">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row ">
|
||||||
|
<div class="col-md-6 col-12">
|
||||||
|
<label class="form-label">Default docker image</label>
|
||||||
|
<SmartSelect TField="ServerDockerImage"
|
||||||
|
@bind-Value="SelectedDockerImage"
|
||||||
|
Items="Image.DockerImages"
|
||||||
|
DisplayField="@(x => x.Name)"
|
||||||
|
CanBeNull="true"/>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 col-12">
|
||||||
|
<label class="form-label">Allow user to change the docker image</label>
|
||||||
|
<div class="form-check">
|
||||||
|
<InputCheckbox @bind-Value="Image.AllowUserToChangeDockerImage" class="form-check-input"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex justify-content-end">
|
||||||
|
<WButton Text="Save" CssClasses="btn btn-success" OnClick="OnSave"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<AutoListCrud TItem="ServerDockerImage"
|
<AutoListCrud TItem="ServerDockerImage"
|
||||||
TRootItem="ServerImage"
|
TRootItem="ServerImage"
|
||||||
TCreateForm="CreateDockerImage"
|
TCreateForm="CreateDockerImage"
|
||||||
|
@ -26,10 +53,10 @@
|
||||||
RootItem="Image"
|
RootItem="Image"
|
||||||
Title="Manage docker images">
|
Title="Manage docker images">
|
||||||
<View>
|
<View>
|
||||||
<Column TableItem="ServerDockerImage" Field="@(x => x.Id)" Title="Id" />
|
<Column TableItem="ServerDockerImage" Field="@(x => x.Id)" Title="Id"/>
|
||||||
<Column TableItem="ServerDockerImage" Field="@(x => x.DisplayName)" Title="Display name" />
|
<Column TableItem="ServerDockerImage" Field="@(x => x.DisplayName)" Title="Display name"/>
|
||||||
<Column TableItem="ServerDockerImage" Field="@(x => x.Name)" Title="Name" />
|
<Column TableItem="ServerDockerImage" Field="@(x => x.Name)" Title="Name"/>
|
||||||
<Column TableItem="ServerDockerImage" Field="@(x => x.AutoPull)" Title="">
|
<Column TableItem="ServerDockerImage" Field="@(x => x.AutoPull)" Title="Auto pull">
|
||||||
<Template>
|
<Template>
|
||||||
@if (context.AutoPull)
|
@if (context.AutoPull)
|
||||||
{
|
{
|
||||||
|
@ -48,18 +75,54 @@
|
||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter] public int Id { get; set; }
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
private ServerImage? Image;
|
private ServerImage? Image;
|
||||||
|
|
||||||
|
private ServerDockerImage? SelectedDockerImage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Image == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (Image.DefaultDockerImageIndex >= Image.DockerImages.Count)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (Image.DefaultDockerImageIndex == -1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Image.DockerImages[Image.DefaultDockerImageIndex];
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Image == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
Image.DefaultDockerImageIndex = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image.DefaultDockerImageIndex = Image.DockerImages.IndexOf(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Task Load(LazyLoader arg)
|
private Task Load(LazyLoader arg)
|
||||||
{
|
{
|
||||||
Image = ImageRepository
|
Image = ImageRepository
|
||||||
.Get()
|
.Get()
|
||||||
.Include(x => x.DockerImages)
|
.Include(x => x.DockerImages)
|
||||||
.FirstOrDefault(x => x.Id == Id);
|
.FirstOrDefault(x => x.Id == Id);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task OnSave()
|
||||||
|
{
|
||||||
|
ImageRepository.Update(Image!);
|
||||||
|
|
||||||
|
await ToastService.Success("Successfully updated image");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<button type="submit" class="btn btn-success">Create</button>
|
<button type="submit" class="btn btn-success">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SmartForm>
|
</SmartForm>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="d-flex justify-content-end">
|
<div class="d-flex justify-content-end">
|
||||||
<button type="submit" class="btn btn-success">Create</button>
|
<button type="submit" class="btn btn-success">Save</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SmartForm>
|
</SmartForm>
|
||||||
|
|
|
@ -3,24 +3,65 @@
|
||||||
@using Moonlight.Features.Servers.Entities
|
@using Moonlight.Features.Servers.Entities
|
||||||
@using Moonlight.Core.Repositories
|
@using Moonlight.Core.Repositories
|
||||||
@using Moonlight.Features.Servers.UI.Components
|
@using Moonlight.Features.Servers.UI.Components
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using BlazorTable
|
||||||
|
@using Moonlight.Features.Servers.Models.Forms.Admin.Images
|
||||||
|
|
||||||
@inject Repository<ServerImage> ImageRepository
|
@inject Repository<ServerImage> ImageRepository
|
||||||
|
|
||||||
<LazyLoader ShowAsCard="true" Load="Load">
|
<LazyLoader ShowAsCard="true" Load="Load">
|
||||||
@if (Image == null)
|
@if (Image == null)
|
||||||
{
|
{
|
||||||
<NotFoundAlert />
|
<NotFoundAlert/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<AdminImageViewNavigation Index="5" ImageId="@Id" />
|
<AdminImageViewNavigation Index="5" ImageId="@Id"/>
|
||||||
|
|
||||||
|
<AutoListCrud TItem="ServerImageVariable"
|
||||||
|
TRootItem="ServerImage"
|
||||||
|
TCreateForm="CreateImageVariable"
|
||||||
|
TUpdateForm="UpdateImageVariable"
|
||||||
|
Field="@(x => x.Variables)"
|
||||||
|
RootItem="Image"
|
||||||
|
Title="Manage image variables">
|
||||||
|
<View>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.Id)" Title="Id"/>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.DisplayName)" Title="Display name"/>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.Key)" Title="Key"/>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.DefaultValue)" Title="Default value"/>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.AllowUserToView)" Title="View">
|
||||||
|
<Template>
|
||||||
|
@if (context.AllowUserToView)
|
||||||
|
{
|
||||||
|
<i class="bx bx-sm bx-check text-success"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="bx bx-sm bx-x text-danger"></i>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="ServerImageVariable" Field="@(x => x.AllowUserToEdit)" Title="Edit">
|
||||||
|
<Template>
|
||||||
|
@if (context.AllowUserToEdit)
|
||||||
|
{
|
||||||
|
<i class="bx bx-sm bx-check text-success"></i>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<i class="bx bx-sm bx-x text-danger"></i>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
</View>
|
||||||
|
</AutoListCrud>
|
||||||
}
|
}
|
||||||
</LazyLoader>
|
</LazyLoader>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
{
|
{
|
||||||
[Parameter]
|
[Parameter] public int Id { get; set; }
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
private ServerImage? Image;
|
private ServerImage? Image;
|
||||||
|
|
||||||
|
@ -28,8 +69,9 @@
|
||||||
{
|
{
|
||||||
Image = ImageRepository
|
Image = ImageRepository
|
||||||
.Get()
|
.Get()
|
||||||
|
.Include(x => x.Variables)
|
||||||
.FirstOrDefault(x => x.Id == Id);
|
.FirstOrDefault(x => x.Id == Id);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -38,6 +38,7 @@
|
||||||
<Folder Include="Features\Servers\Http\Resources\" />
|
<Folder Include="Features\Servers\Http\Resources\" />
|
||||||
<Folder Include="Features\StoreSystem\Helpers\" />
|
<Folder Include="Features\StoreSystem\Helpers\" />
|
||||||
<Folder Include="Features\Ticketing\Models\Abstractions\" />
|
<Folder Include="Features\Ticketing\Models\Abstractions\" />
|
||||||
|
<Folder Include="storage\plugins\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in a new issue