Files
Moonlight/Moonlight/Shared/Views/Server/Index.razor
2023-06-16 17:43:48 +02:00

338 lines
12 KiB
Plaintext

@page "/server/{ServerUuid}/{Route?}"
@using Task = System.Threading.Tasks.Task
@using Moonlight.App.Repositories.Servers
@using Microsoft.EntityFrameworkCore
@using Logging.Net
@using Moonlight.App.Database.Entities
@using Moonlight.App.Events
@using Moonlight.App.Helpers.Wings
@using Moonlight.App.Helpers.Wings.Enums
@using Moonlight.App.Repositories
@using Moonlight.App.Services
@using Moonlight.App.Services.Sessions
@using Moonlight.Shared.Components.Xterm
@using Newtonsoft.Json
@inject ImageRepository ImageRepository
@inject ServerRepository ServerRepository
@inject WingsConsoleHelper WingsConsoleHelper
@inject EventSystem Event
@inject ServerService ServerService
@inject NavigationManager NavigationManager
@inject DynamicBackgroundService DynamicBackgroundService
@inject SmartTranslateService SmartTranslateService
@implements IDisposable
<LazyLoader Load="LoadData">
@if (CurrentServer == null)
{
<div class="d-flex justify-content-center flex-center">
<div class="card">
<img src="/assets/media/svg/nodata.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
<div class="card-body text-center">
<h1 class="card-title">
<TL>Server not found</TL>
</h1>
<p class="card-text fs-4">
<TL>A server with that id cannot be found or you have no access for this server</TL>
</p>
</div>
</div>
</div>
}
else
{
if (NodeOnline)
{
if (Console.ConsoleState == ConsoleState.Connected)
{
if (Console.ServerState == ServerState.Installing)
{
<div class="card">
<div class="card-body">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
<TL>Server installation is currently running</TL>
</span>
</div>
</div>
<Terminal @ref="InstallConsole"></Terminal>
</div>
</div>
}
else if (CurrentServer.Installing)
{
<div class="card">
<div class="card-body">
<div class="mb-10">
<div class="fs-2hx fw-bold text-gray-800 text-center mb-13">
<span class="me-2">
<TL>Server installation is currently running</TL>
</span>
</div>
</div>
<Terminal @ref="InstallConsole"></Terminal>
</div>
</div>
}
else if (CurrentServer.IsArchived)
{
<div class="d-flex justify-content-center flex-center">
<div class="card">
<img src="/assets/media/svg/archive.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
<div class="card-body text-center">
<h1 class="card-title">
<TL>Server is currently archived</TL>
</h1>
<p class="card-text fs-4">
<TL>This server is archived. The data of this server is stored as a backup. To restore click the unarchive button an be patient</TL>
</p>
<WButton Text="@(SmartTranslateService.Translate("Unarchive"))"
WorkingText="@(SmartTranslateService.Translate("Please wait"))"
CssClasses="btn-primary"
OnClick="UnArchive">
</WButton>
</div>
</div>
</div>
}
else
{
<CascadingValue Value="Console">
<CascadingValue Value="CurrentServer">
<CascadingValue Value="Tags">
<SmartRouter Route="@Route">
<Route Path="/">
<ServerNavigation Index="0">
<ServerConsole/>
</ServerNavigation>
</Route>
<Route Path="/files">
<ServerNavigation Index="1">
<ServerFiles/>
</ServerNavigation>
</Route>
<Route Path="/backups">
<ServerNavigation Index="2">
<ServerBackups/>
</ServerNavigation>
</Route>
<Route Path="/network">
<ServerNavigation Index="3">
<ServerNetwork/>
</ServerNavigation>
</Route>
<Route Path="/addons">
<ServerNavigation Index="4">
<ServerAddons/>
</ServerNavigation>
</Route>
<Route Path="/settings">
<ServerNavigation Index="5">
<ServerSettings/>
</ServerNavigation>
</Route>
</SmartRouter>
</CascadingValue>
</CascadingValue>
</CascadingValue>
}
}
else
{
<div class="alert alert-info">
<TL>Connecting</TL>
</div>
}
}
else
{
<div class="d-flex justify-content-center flex-center">
<div class="card">
<img src="/assets/media/svg/serverdown.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
<div class="card-body text-center">
<h1 class="card-title">
<TL>Node offline</TL>
</h1>
<p class="card-text fs-4">
<TL>The node the server is running on is currently offline</TL>
</p>
</div>
</div>
</div>
}
}
</LazyLoader>
@code
{
[Parameter]
public string ServerUuid { get; set; }
[CascadingParameter]
public User User { get; set; }
[Parameter]
public string? Route { get; set; }
private WingsConsole? Console;
private Server? CurrentServer;
private Node Node;
private bool NodeOnline = false;
private Image Image;
private NodeAllocation NodeAllocation;
private string[] Tags;
private Terminal? InstallConsole;
protected override void OnInitialized()
{
Console = new();
Console.OnConsoleStateUpdated += (_, _) => { InvokeAsync(StateHasChanged); };
Console.OnResourceUpdated += (_, _) => { InvokeAsync(StateHasChanged); };
Console.OnServerStateUpdated += (_, _) => { InvokeAsync(StateHasChanged); };
Console.OnRequestNewToken += async _ => await WingsConsoleHelper.GenerateToken(CurrentServer!);
Console.OnMessage += async (_, s) =>
{
if (Console.ServerState == ServerState.Installing)
{
if (InstallConsole != null)
{
if (s.IsInternal)
await InstallConsole.WriteLine("\x1b[38;5;16;48;5;135m\x1b[39m\x1b[1m Moonlight \x1b[0m " + s.Content + "\x1b[0m");
else
await InstallConsole.WriteLine(s.Content);
}
}
};
}
private async Task LoadData(LazyLoader lazyLoader)
{
await lazyLoader.SetText("Requesting server data");
try
{
var uuid = Guid.Parse(ServerUuid);
CurrentServer = ServerRepository
.Get()
.Include(x => x.Allocations)
.Include(x => x.Image)
.Include(x => x.Node)
.Include(x => x.Variables)
.Include(x => x.MainAllocation)
.Include(x => x.Owner)
.First(x => x.Uuid == uuid);
}
catch (Exception)
{
// ignored
}
if (CurrentServer != null)
{
if (CurrentServer.Owner.Id != User!.Id && !User.Admin)
CurrentServer = null;
}
if (CurrentServer != null)
{
await lazyLoader.SetText("Checking node online status");
NodeOnline = await ServerService.IsHostUp(CurrentServer);
if (NodeOnline)
{
await lazyLoader.SetText("Checking server variables");
var image = ImageRepository
.Get()
.Include(x => x.Variables)
.First(x => x.Id == CurrentServer.Image.Id);
// Live variable migration
foreach (var variable in image.Variables)
{
if (!CurrentServer.Variables.Any(x => x.Key == variable.Key))
{
CurrentServer.Variables.Add(new ServerVariable()
{
Key = variable.Key,
Value = variable.DefaultValue
});
ServerRepository.Update(CurrentServer);
}
}
// Tags
await lazyLoader.SetText("Requesting tags");
Tags = JsonConvert.DeserializeObject<string[]>(image.TagsJson) ?? Array.Empty<string>();
Image = image;
await lazyLoader.SetText("Connecting to console");
await ReconnectConsole();
await Event.On<Server>($"server.{CurrentServer.Uuid}.installComplete", this, server =>
{
NavigationManager.NavigateTo(NavigationManager.Uri, true);
return Task.CompletedTask;
});
await Event.On<Server>($"server.{CurrentServer.Uuid}.archiveStatusChanged", this, server =>
{
NavigationManager.NavigateTo(NavigationManager.Uri, true);
return Task.CompletedTask;
});
if (string.IsNullOrEmpty(Image.BackgroundImageUrl))
await DynamicBackgroundService.Reset();
else
await DynamicBackgroundService.Change(Image.BackgroundImageUrl);
}
}
else
{
Logger.Debug("Server is null");
}
}
private async Task ReconnectConsole()
{
await Console!.Disconnect();
await WingsConsoleHelper.ConnectWings(Console!, CurrentServer!);
}
public async void Dispose()
{
if (CurrentServer != null)
{
await Event.Off($"server.{CurrentServer.Uuid}.installComplete", this);
await Event.Off($"server.{CurrentServer.Uuid}.archiveStatusChanged", this);
}
if (Console != null)
{
Console.Dispose();
}
}
private async Task UnArchive()
{
await ServerService.UnArchiveServer(CurrentServer!);
}
}