265 lines
11 KiB
Plaintext
265 lines
11 KiB
Plaintext
@page "/servers/create"
|
|
@using Moonlight.App.Services
|
|
@using Moonlight.App.Database.Entities
|
|
@using Moonlight.App.Models.Forms
|
|
@using Moonlight.App.Models.Misc
|
|
@using Moonlight.App.Repositories
|
|
@using Moonlight.App.Repositories.Servers
|
|
@using Microsoft.EntityFrameworkCore
|
|
@using Moonlight.App.Exceptions
|
|
|
|
@inject SubscriptionService SubscriptionService
|
|
@inject ImageRepository ImageRepository
|
|
@inject SmartTranslateService SmartTranslateService
|
|
@inject SmartDeployService SmartDeployService
|
|
@inject ServerRepository ServerRepository
|
|
@inject NavigationManager NavigationManager
|
|
@inject ServerService ServerService
|
|
|
|
<LazyLoader Load="Load">
|
|
@if (DeployNode == 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-25 mx-auto pt-5" alt="Not found image"/>
|
|
<div class="card-body text-center">
|
|
<h4 class="card-title">
|
|
<TL>No node found</TL>
|
|
</h4>
|
|
<p class="card-text">
|
|
<TL>No node found to deploy to</TL>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="d-flex flex-column flex-lg-row">
|
|
<div class="w-100 flex-lg-row-auto w-lg-300px mb-7 me-7 me-lg-10">
|
|
<div class="card card-flush py-4">
|
|
<div class="card-header">
|
|
<div class="card-title">
|
|
<h2>
|
|
<TL>Server details</TL>
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
<div class="card-body pt-0">
|
|
<div class="d-flex flex-column gap-10">
|
|
<div class="fv-row">
|
|
<label class="form-label">
|
|
<TL>Node</TL>
|
|
</label>
|
|
<div class="fw-bold fs-3">@(DeployNode.Name)</div>
|
|
</div>
|
|
@if (Model.Image != null)
|
|
{
|
|
var limit = Images[Model.Image];
|
|
|
|
<div class="fv-row">
|
|
<label class="form-label">
|
|
<TL>Image</TL>
|
|
</label>
|
|
<div class="fw-bold fs-3">@(Model.Image.Name)</div>
|
|
</div>
|
|
|
|
<div class="fv-row">
|
|
<label class="form-label">
|
|
<TL>CPU</TL>
|
|
</label>
|
|
<div class="fw-bold fs-3">
|
|
@{
|
|
var cpu = limit.ReadValue("cpu");
|
|
|
|
if (cpu == null)
|
|
cpu = "N/A";
|
|
else
|
|
cpu = (int.Parse(cpu) / 100).ToString();
|
|
}
|
|
@(cpu) <TL>Cores</TL>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="fv-row">
|
|
<label class="form-label">
|
|
<TL>Memory</TL>
|
|
</label>
|
|
<div class="fw-bold fs-3">@(limit.ReadValue("memory")) MB</div>
|
|
</div>
|
|
|
|
<div class="fv-row">
|
|
<label class="form-label">
|
|
<TL>Disk</TL>
|
|
</label>
|
|
<div class="fw-bold fs-3">@(limit.ReadValue("disk")) MB</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex flex-column flex-lg-row-fluid gap-7 gap-lg-10">
|
|
<div class="card card-flush py-4">
|
|
<div class="card-header">
|
|
<div class="card-title">
|
|
<h2>
|
|
<TL>Configure your server</TL>
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
<div class="card-body pt-0">
|
|
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
|
|
<label class="form-label">
|
|
<TL>Name</TL>
|
|
</label>
|
|
<div class="input-group mb-5">
|
|
<InputText @bind-Value="Model.Name" class="form-control"></InputText>
|
|
</div>
|
|
@if (Images.Any())
|
|
{
|
|
<button type="submit" class="mt-5 float-end btn btn-primary">
|
|
<TL>Create</TL>
|
|
</button>
|
|
}
|
|
else
|
|
{
|
|
<div class="alert alert-warning d-flex align-items-center p-5 mb-10">
|
|
<span>
|
|
<TL>We could not find any image in your subscription you have access to</TL>: @(Subscription == null ? SmartTranslateService.Translate("Default") : Subscription.Name)
|
|
</span>
|
|
</div>
|
|
}
|
|
</SmartForm>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
@foreach (var keyValuePair in Images)
|
|
{
|
|
bool selected = Model.Image != null && Model.Image.Id == keyValuePair.Key.Id;
|
|
|
|
<div class="col-12 col-md-4">
|
|
@if (ServerCounts[keyValuePair.Key] > keyValuePair.Value.Amount)
|
|
{
|
|
<div class="m-2 card blur">
|
|
<div class="card-body">
|
|
<h5 class="card-title text-center">@(keyValuePair.Key.Name)</h5>
|
|
<p class="card-text">
|
|
@(keyValuePair.Key.Description)
|
|
</p>
|
|
</div>
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<a href="#" class="m-2 card @(selected ? "border border-2 border-primary" : "") invisible-a" @onclick:preventDefault @onclick="() => SelectImage(keyValuePair.Key)">
|
|
<div class="card-body">
|
|
<h5 class="card-title text-center">@(keyValuePair.Key.Name)</h5>
|
|
<p class="card-text">
|
|
@(keyValuePair.Key.Description)
|
|
</p>
|
|
</div>
|
|
</a>
|
|
}
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</LazyLoader>
|
|
|
|
@code
|
|
{
|
|
[CascadingParameter]
|
|
public User User { get; set; }
|
|
|
|
private Node? DeployNode;
|
|
private Subscription? Subscription;
|
|
|
|
private Dictionary<Image, SubscriptionLimit> Images = new();
|
|
private Dictionary<Image, int> ServerCounts = new();
|
|
|
|
private ServerOrderDataModel Model = new();
|
|
|
|
private async Task Load(LazyLoader lazyLoader)
|
|
{
|
|
// Reset state
|
|
Images.Clear();
|
|
Model = new();
|
|
|
|
await lazyLoader.SetText(SmartTranslateService.Translate("Loading your subscription"));
|
|
Subscription = await SubscriptionService.GetCurrent();
|
|
|
|
await lazyLoader.SetText(SmartTranslateService.Translate("Searching for deploy node"));
|
|
DeployNode = await SmartDeployService.GetNode();
|
|
|
|
await lazyLoader.SetText(SmartTranslateService.Translate("Searching for available images"));
|
|
var images = ImageRepository.Get().ToArray();
|
|
|
|
foreach (var image in images)
|
|
{
|
|
var limit = await SubscriptionService.GetLimit("image." + image.Id);
|
|
|
|
if (limit.Amount > 0)
|
|
{
|
|
var serversCount = ServerRepository
|
|
.Get()
|
|
.Include(x => x.Owner)
|
|
.Include(x => x.Image)
|
|
.Where(x => x.Owner.Id == User.Id)
|
|
.Count(x => x.Image.Id == image.Id);
|
|
|
|
Images.Add(image, limit);
|
|
ServerCounts.Add(image, serversCount);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task OnValidSubmit()
|
|
{
|
|
var limit = await SubscriptionService.GetLimit("image." + Model.Image.Id);
|
|
|
|
if (limit.Amount > 0)
|
|
{
|
|
var serversCount = ServerRepository
|
|
.Get()
|
|
.Include(x => x.Owner)
|
|
.Include(x => x.Image)
|
|
.Where(x => x.Owner.Id == User.Id)
|
|
.Count(x => x.Image.Id == Model.Image.Id);
|
|
|
|
if (serversCount < limit.Amount)
|
|
{
|
|
if (int.TryParse(limit.ReadValue("cpu"), out int cpu) &&
|
|
int.TryParse(limit.ReadValue("memory"), out int memory) &&
|
|
int.TryParse(limit.ReadValue("disk"), out int disk))
|
|
{
|
|
var server = await ServerService.Create(
|
|
Model.Name,
|
|
cpu,
|
|
memory,
|
|
disk,
|
|
User,
|
|
Model.Image,
|
|
DeployNode
|
|
);
|
|
|
|
NavigationManager.NavigateTo($"/server/{server.Uuid}");
|
|
}
|
|
else
|
|
{
|
|
throw new DisplayException("Limits cannot be parsed");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task SelectImage(Image image)
|
|
{
|
|
Model.Image = image;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
} |