Add UI for editing Docker hosts, add database migration
This commit is contained in:
parent
98cab7ec24
commit
b5dbda3eec
9 changed files with 3086 additions and 120 deletions
2801
LANCommander.Server.Data.SQLite/Migrations/20250324005817_AddDockerHostProperties.Designer.cs
generated
Normal file
2801
LANCommander.Server.Data.SQLite/Migrations/20250324005817_AddDockerHostProperties.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,51 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LANCommander.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddDockerHostProperties : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ContainerId",
|
||||
table: "Servers",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DockerHostId",
|
||||
table: "Servers",
|
||||
type: "TEXT",
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "Engine",
|
||||
table: "Servers",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ContainerId",
|
||||
table: "Servers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DockerHostId",
|
||||
table: "Servers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Engine",
|
||||
table: "Servers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1041,6 +1041,28 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("Roles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("RoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -1164,12 +1186,23 @@ namespace LANCommander.Migrations
|
|||
b.Property<int>("AutostartMethod")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ContainerId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid?>("CreatedById")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DockerHostId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Engine")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<Guid?>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
|
@ -1487,6 +1520,28 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("Users", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
|
|
@ -1529,66 +1584,7 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("UserCustomField");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LibraryGame", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("LibraryId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GameId", "LibraryId");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("LibraryGame");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("RoleClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserClaims", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -1609,7 +1605,7 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("UserLogins", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -1624,7 +1620,7 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("UserRoles", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b =>
|
||||
{
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
|
@ -1643,6 +1639,21 @@ namespace LANCommander.Migrations
|
|||
b.ToTable("UserTokens", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LibraryGame", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<Guid>("LibraryId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("GameId", "LibraryId");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("LibraryGame");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PageGame", b =>
|
||||
{
|
||||
b.Property<Guid>("GameId")
|
||||
|
|
@ -2345,6 +2356,15 @@ namespace LANCommander.Migrations
|
|||
b.Navigation("UpdatedBy");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.RoleClaim", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Role", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.SavePath", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy")
|
||||
|
|
@ -2530,6 +2550,15 @@ namespace LANCommander.Migrations
|
|||
b.Navigation("UpdatedBy");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserClaim", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserCustomField", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", "CreatedBy")
|
||||
|
|
@ -2555,6 +2584,43 @@ namespace LANCommander.Migrations
|
|||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserLogin", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserRole", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Role", "Role")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", "User")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Role");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.UserToken", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LibraryGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Game", null)
|
||||
|
|
@ -2570,57 +2636,6 @@ namespace LANCommander.Migrations
|
|||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Role", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Role", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<System.Guid>", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.User", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("PageGame", b =>
|
||||
{
|
||||
b.HasOne("LANCommander.Server.Data.Models.Game", null)
|
||||
|
|
@ -2737,6 +2752,11 @@ namespace LANCommander.Migrations
|
|||
b.Navigation("Scripts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.Role", b =>
|
||||
{
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LANCommander.Server.Data.Models.Server", b =>
|
||||
{
|
||||
b.Navigation("Actions");
|
||||
|
|
@ -2769,6 +2789,8 @@ namespace LANCommander.Migrations
|
|||
b.Navigation("Media");
|
||||
|
||||
b.Navigation("PlaySessions");
|
||||
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
|
|
|
|||
7
LANCommander.Server.Data/Enums/ServerEngine.cs
Normal file
7
LANCommander.Server.Data/Enums/ServerEngine.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace LANCommander.Server.Data.Enums;
|
||||
|
||||
public enum ServerEngine
|
||||
{
|
||||
Local,
|
||||
Docker
|
||||
}
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
using LANCommander.SDK.Enums;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
using LANCommander.Server.Data.Enums;
|
||||
|
||||
namespace LANCommander.Server.Data.Models
|
||||
{
|
||||
public class Server : BaseModel
|
||||
{
|
||||
public string Name { get; set; } = "";
|
||||
public ServerEngine Engine { get; set; } = ServerEngine.Local;
|
||||
public string Path { get; set; } = "";
|
||||
public string Arguments { get; set; } = "";
|
||||
public string WorkingDirectory { get; set; } = "";
|
||||
|
|
@ -14,6 +16,7 @@ namespace LANCommander.Server.Data.Models
|
|||
public string OnStartScriptPath { get; set; } = "";
|
||||
public string OnStopScriptPath { get; set; } = "";
|
||||
|
||||
public string DockerHostId { get; set; }
|
||||
public string ContainerId { get; set; } = "";
|
||||
public string Host { get; set; } = "";
|
||||
public int Port { get; set; } = 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using LANCommander.Server.Services.Factories;
|
|||
using LANCommander.Server.Services.Importers;
|
||||
using LANCommander.Server.Services.MediaGrabbers;
|
||||
using LANCommander.Server.Services.Models;
|
||||
using LANCommander.Server.Services.ServerEngines;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace LANCommander.Server.Services.Extensions;
|
||||
|
|
@ -51,6 +52,14 @@ public static class IServiceCollectionExtensions
|
|||
services.AddScoped<IImporter<Data.Models.Game>, GameImporter>();
|
||||
services.AddScoped<IImporter<Data.Models.Server>, ServerImporter>();
|
||||
services.AddScoped<IImporter<Data.Models.Redistributable>, RedistributableImporter>();
|
||||
|
||||
// Register server engines
|
||||
services.AddKeyedSingleton<IServerEngine, LocalServerEngine>("Local");
|
||||
|
||||
foreach (var dockerHost in settings.Servers.DockerHosts)
|
||||
{
|
||||
services.AddKeyedSingleton<IServerEngine, DockerServerEngine>(dockerHost.Id.ToString());
|
||||
}
|
||||
|
||||
services.AddSingleton<ServerProcessService>();
|
||||
services.AddSingleton<IPXRelayService>();
|
||||
|
|
|
|||
|
|
@ -186,11 +186,12 @@ namespace LANCommander.Server.Services.Models
|
|||
public class ServerSettings
|
||||
{
|
||||
public string StoragePath { get; set; } = "Servers";
|
||||
public IEnumerable<DockerHostConfiguration> Hosts { get; set; } = new List<DockerHostConfiguration>();
|
||||
public IEnumerable<DockerHostConfiguration> DockerHosts { get; set; } = new List<DockerHostConfiguration>();
|
||||
}
|
||||
|
||||
public class DockerHostConfiguration
|
||||
{
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
public string Name { get; set; } = "Local";
|
||||
public string Address { get; set; } = "/var/run/docker.sock";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
<Flex Direction="FlexDirection.Vertical" Gap="FlexGap.Large">
|
||||
@if (!Settings.Servers.DockerHosts.Any())
|
||||
{
|
||||
<Empty Description="@("No Docker hosts have been configured")" />
|
||||
}
|
||||
|
||||
<Collapse>
|
||||
@foreach (var dockerHost in Settings.Servers.DockerHosts)
|
||||
{
|
||||
<Panel Header="@dockerHost.Name">
|
||||
<ExtraTemplate>
|
||||
<Button Type="ButtonType.Text" Icon="@IconType.Outline.Close" Size="ButtonSize.Small" Danger OnClick="() => Remove(dockerHost)"/>
|
||||
</ExtraTemplate>
|
||||
<ChildContent>
|
||||
<Form Model="dockerHost" Layout="FormLayout.Vertical">
|
||||
<FormItem Label="Name">
|
||||
<Input @bind-Value="context.Name" BindOnInput />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="Address">
|
||||
<Input @bind-Value="context.Address" />
|
||||
</FormItem>
|
||||
</Form>
|
||||
</ChildContent>
|
||||
</Panel>
|
||||
}
|
||||
</Collapse>
|
||||
|
||||
<Flex Justify="FlexJustify.Center">
|
||||
<Button OnClick="Add" Type="ButtonType.Primary">Add Host</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
@code {
|
||||
[Parameter] public IEnumerable<DockerHostConfiguration> Values { get; set; }
|
||||
[Parameter] public EventCallback<IEnumerable<DockerHostConfiguration>> ValuesChanged { get; set; }
|
||||
|
||||
Settings Settings = SettingService.GetSettings();
|
||||
|
||||
List<DockerHostConfiguration> DockerHosts = new();
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
DockerHosts = Values.ToList();
|
||||
}
|
||||
|
||||
async Task Add()
|
||||
{
|
||||
DockerHosts.Add(new DockerHostConfiguration());
|
||||
|
||||
if (ValuesChanged.HasDelegate)
|
||||
await ValuesChanged.InvokeAsync(DockerHosts);
|
||||
}
|
||||
|
||||
async Task Remove(DockerHostConfiguration dockerHost)
|
||||
{
|
||||
DockerHosts.Remove(dockerHost);
|
||||
|
||||
if (ValuesChanged.HasDelegate)
|
||||
await ValuesChanged.InvokeAsync(DockerHosts);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,25 @@
|
|||
@page "/Settings/Servers"
|
||||
@using LANCommander.Server.UI.Pages.Settings.Components
|
||||
@inject IMessageService MessageService
|
||||
@inject ILogger<Servers> Logger
|
||||
@attribute [Authorize(Roles = RoleService.AdministratorRoleName)]
|
||||
|
||||
<PageHeader Title="Servers" />
|
||||
<PageHeader Title="Servers">
|
||||
<PageHeaderExtra>
|
||||
<Button OnClick="Save" Type="@ButtonType.Primary">Save</Button>
|
||||
</PageHeaderExtra>
|
||||
</PageHeader>
|
||||
|
||||
<PageContent>
|
||||
<Form Model="Settings" Layout="@FormLayout.Vertical">
|
||||
<FormItem Label="Storage Path">
|
||||
<FilePicker Root="@RootPath" EntrySelectable="x => x is FileManagerDirectory" @bind-Value="@context.Servers.StoragePath" OkText="Select Path" Title="Choose Path" OnSelected="OnPathSelected" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem>
|
||||
<Button OnClick="Save" Type="@ButtonType.Primary">Save</Button>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
<Divider Text="Docker Hosts" />
|
||||
|
||||
<ServerEngineEditor @bind-Values="Settings.Servers.DockerHosts" />
|
||||
</PageContent>
|
||||
|
||||
@code {
|
||||
|
|
@ -26,7 +31,12 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
SettingService.SaveSettings(Settings);
|
||||
var settings = SettingService.GetSettings();
|
||||
|
||||
settings.Servers = Settings.Servers;
|
||||
|
||||
SettingService.SaveSettings(settings);
|
||||
|
||||
MessageService.Success("Settings saved!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue