Fixed some permissions. Cleaned some UIs

This commit is contained in:
Marcel Baumgartner
2023-07-17 16:22:22 +02:00
parent 0a86aa8aa4
commit 0015001d7c
11 changed files with 457 additions and 478 deletions

View File

@@ -135,10 +135,10 @@ public static class Permissions
Description = "Edit server image settings in the admin area" Description = "Edit server image settings in the admin area"
}; };
public static Permission AdminServerImageIndex = new() public static Permission AdminServerImages = new()
{ {
Index = 21, Index = 21,
Name = "Admin Server Image", Name = "Admin Server Images",
Description = "Access the server image management page in the admin area" Description = "Access the server image management page in the admin area"
}; };

View File

@@ -1,22 +0,0 @@
<div class="card mb-5 mb-xl-10">
<div class="card-body pt-0 pb-0">
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/nodes">
<TL>Nodes</TL>
</a>
</li>
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/nodes/ddos">
<TL>DDos</TL>
</a>
</li>
</ul>
</div>
</div>
@code
{
[Parameter]
public int Index { get; set; } = 0;
}

View File

@@ -0,0 +1,37 @@
<div class="card mb-5 mb-xl-10">
<div class="card-body pt-0 pb-0">
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/servers">
<TL>Overview</TL>
</a>
</li>
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/servers/manager">
<TL>Manager</TL>
</a>
</li>
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 2 ? "active" : "")" href="/admin/servers/cleanup">
<TL>Cleanup</TL>
</a>
</li>
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 3 ? "active" : "")" href="/admin/nodes">
<TL>Nodes</TL>
</a>
</li>
<li class="nav-item mt-2">
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 4 ? "active" : "")" href="/admin/servers/images">
<TL>Images</TL>
</a>
</li>
</ul>
</div>
</div>
@code
{
[Parameter]
public int Index { get; set; } = 0;
}

View File

@@ -92,60 +92,13 @@ else
<span class="menu-title"><TL>System</TL></span> <span class="menu-title"><TL>System</TL></span>
</a> </a>
</div> </div>
<div data-kt-menu-trigger="click" class="menu-item menu-accordion"> <div class="menu-item">
<span class="menu-link"> <a class="menu-link" href="/admin/servers">
<span class="menu-icon"> <span class="menu-icon">
<i class="bx bx-server"></i> <i class="bx bx-server"></i>
</span> </span>
<span class="menu-title"><TL>Servers</TL></span> <span class="menu-title"><TL>Servers</TL></span>
<span class="menu-arrow"></span> </a>
</span>
<div class="menu-sub menu-sub-accordion">
<div class="menu-item">
<a class="menu-link" href="/admin/servers">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title"><TL>Overview</TL></span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/servers/manager">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title"><TL>Manager</TL></span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/servers/cleanup">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title"><TL>Cleanup</TL></span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/nodes">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title"><TL>Nodes</TL></span>
</a>
</div>
<div class="menu-item">
<a class="menu-link" href="/admin/servers/images">
<span class="menu-bullet">
<span class="bullet bullet-dot"></span>
</span>
<span class="menu-title"><TL>Images</TL></span>
</a>
</div>
</div>
</div> </div>
<div class="menu-item"> <div class="menu-item">
<a class="menu-link" href="/admin/webspaces"> <a class="menu-link" href="/admin/webspaces">

View File

@@ -99,4 +99,6 @@
{ {
await Event.Off("node.ddos", this); await Event.Off("node.ddos", this);
} }
//TODO: Move to security
} }

View File

@@ -15,7 +15,7 @@
@attribute [PermissionRequired(nameof(Permissions.AdminNodes))] @attribute [PermissionRequired(nameof(Permissions.AdminNodes))]
<AdminNodesNavigation Index="0"/> <AdminServersNavigation Index="3" />
<LazyLoader @ref="LazyLoader" Load="Load"> <LazyLoader @ref="LazyLoader" Load="Load">
<div class="card"> <div class="card">

View File

@@ -1,6 +1,7 @@
@page "/admin/servers/cleanup" @page "/admin/servers/cleanup"
@using Moonlight.App.Events @using Moonlight.App.Events
@using Moonlight.App.Services.Background @using Moonlight.App.Services.Background
@using Moonlight.Shared.Components.Navigations
@inject CleanupService CleanupService @inject CleanupService CleanupService
@inject EventSystem Event @inject EventSystem Event
@@ -9,6 +10,8 @@
@attribute [PermissionRequired(nameof(Permissions.AdminServerCleanup))] @attribute [PermissionRequired(nameof(Permissions.AdminServerCleanup))]
<AdminServersNavigation Index="2" />
<div class="row g-5 g-xl-10 mb-5 mb-xl-10"> <div class="row g-5 g-xl-10 mb-5 mb-xl-10">
<div class="col-xl-3"> <div class="col-xl-3">
<div class="card card-flush bgi-no-repeat bgi-size-contain bgi-position-x-end h-xl-100" style="background-color: #170049;"> <div class="card card-flush bgi-no-repeat bgi-size-contain bgi-position-x-end h-xl-100" style="background-color: #170049;">

View File

@@ -12,252 +12,252 @@
@inject ToastService ToastService @inject ToastService ToastService
@inject FileDownloadService FileDownloadService @inject FileDownloadService FileDownloadService
<OnlyAdmin> @attribute [PermissionRequired(nameof(Permissions.AdminServerImageEdit))]
<div class="row"> <div class="row">
<LazyLoader @ref="LazyLoader" Load="Load"> <LazyLoader @ref="LazyLoader" Load="Load">
@if (Image == null) @if (Image == null)
{ {
<div class="alert alert-danger"> <div class="alert alert-danger">
<TL>No image with this id found</TL> <TL>No image with this id found</TL>
</div>
}
else
{
<div class="row">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Name</TL>
</label>
<input @bind="Image.Name" type="text" class="form-control">
</div> </div>
<div class="mb-10"> }
<label class="form-label"> else
<TL>Description</TL> {
</label> <div class="row">
<textarea @bind="Image.Description" type="text" class="form-control"></textarea> <div class="col-xl-6 mb-5 mb-xl-10">
</div> <div class="card card-body">
<div class="mb-10"> <div class="mb-10">
<label class="form-label"> <label class="form-label">
<TL>Background image url</TL> <TL>Name</TL>
</label> </label>
<input <input @bind="Image.Name" type="text" class="form-control">
@bind="Image.BackgroundImageUrl" </div>
type="text" <div class="mb-10">
class="form-control" <label class="form-label">
placeholder="@(SmartTranslateService.Translate("Leave empty for the default background image"))"> <TL>Description</TL>
</div> </label>
</div> <textarea @bind="Image.Description" type="text" class="form-control"></textarea>
</div> </div>
<div class="col-xl-6 mb-5 mb-xl-10"> <div class="mb-10">
<div class="card card-body"> <label class="form-label">
<label class="form-label"> <TL>Background image url</TL>
<TL>Tags</TL> </label>
</label> <input
<div class="input-group mb-5"> @bind="Image.BackgroundImageUrl"
<input @bind="AddTagName" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Enter tag name"))"> type="text"
<button @onclick="AddTag" class="btn btn-primary"> class="form-control"
<TL>Add</TL> placeholder="@(SmartTranslateService.Translate("Leave empty for the default background image"))">
</button> </div>
</div>
<div>
@if (Tags.Any())
{
<div class="row">
@foreach (var tag in Tags)
{
<button @onclick="() => RemoveTag(tag)" class="col m-3 btn btn-outline-primary mw-25">
@(tag)
</button>
}
</div> </div>
}
else
{
<div class="alert alert-primary">
<TL>No tags found</TL>
</div>
}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<label class="form-label">
<TL>Docker images</TL>
</label>
<div class="input-group mb-5">
<input @bind="NewDockerImage.Name" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Enter docker image name"))">
<button @onclick="AddDockerImage" class="btn btn-primary">
<TL>Add</TL>
</button>
</div>
<div>
@if (Image.DockerImages.Any())
{
<div class="row">
@foreach (var imageDocker in Image.DockerImages)
{
<button @onclick="() => RemoveDockerImage(imageDocker)" class="col m-3 btn btn-outline-primary mw-25">
@(imageDocker.Name)
</button>
}
</div>
}
else
{
<div class="alert alert-primary">
<TL>No docker images found</TL>
</div>
}
</div>
</div>
</div>
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Default image</TL>
</label>
<select @bind="DefaultImageIndex" class="form-select">
@foreach (var image in Image.DockerImages)
{
<option value="@(image.Id)">@(image.Name)</option>
}
</select>
</div>
<div class="mb-10">
<label class="form-label">
<TL>Allocations</TL>
</label>
<input @bind="Image.Allocations" type="number" class="form-control">
</div>
</div>
</div>
</div>
<div class="row mx-0">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Startup command</TL>
</label>
<input @bind="Image.Startup" type="text" class="form-control">
</div>
<div class="row">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="mb-10">
<label class="form-label">
<TL>Install container</TL>
</label>
<input @bind="Image.InstallDockerImage" type="text" class="form-control">
</div> </div>
</div> <div class="col-xl-6 mb-5 mb-xl-10">
<div class="col-xl-6 mb-5 mb-xl-10"> <div class="card card-body">
<div class="mb-10"> <label class="form-label">
<label class="form-label"> <TL>Tags</TL>
<TL>Install entry</TL> </label>
</label> <div class="input-group mb-5">
<input @bind="Image.InstallEntrypoint" type="text" class="form-control"> <input @bind="AddTagName" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Enter tag name"))">
</div> <button @onclick="AddTag" class="btn btn-primary">
</div> <TL>Add</TL>
</div>
<div class="card card-flush">
<FileEditor @ref="Editor" Language="shell" InitialData="@(Image.InstallScript)" HideControls="true"/>
</div>
</div>
</div>
<div class="row my-8">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Configuration files</TL>
</label>
<textarea @bind="Image.ConfigFiles" class="form-control"></textarea>
</div>
</div>
</div>
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Startup detection</TL>
</label>
<input @bind="Image.StartupDetection" type="text" class="form-control">
</div>
<div class="mb-10">
<label class="form-label">
<TL>Stop command</TL>
</label>
<input @bind="Image.StopCommand" type="text" class="form-control">
</div>
</div>
</div>
</div>
<div class="row my-6">
<div class="card card-body">
<div class="input-group mb-5">
<input type="text" @bind="ImageVariable.Key" placeholder="@(SmartTranslateService.Translate("Key"))" class="form-control">
<input type="text" @bind="ImageVariable.DefaultValue" placeholder="@(SmartTranslateService.Translate("Default value"))" class="form-control">
<button @onclick="AddVariable" class="btn btn-primary">
<TL>Add</TL>
</button>
</div>
<div>
@if (Image!.Variables.Any())
{
<div class="row">
@foreach (var variable in Image!.Variables)
{
<div class="input-group mb-3">
<input type="text" @bind="variable.Key" placeholder="@(SmartTranslateService.Translate("Key"))" class="form-control">
<input type="text" @bind="variable.DefaultValue" placeholder="@(SmartTranslateService.Translate("Default value"))" class="form-control">
<button @onclick="() => RemoveVariable(variable)" class="btn btn-danger">
<TL>Remove</TL>
</button> </button>
</div> </div>
} <div>
@if (Tags.Any())
{
<div class="row">
@foreach (var tag in Tags)
{
<button @onclick="() => RemoveTag(tag)" class="col m-3 btn btn-outline-primary mw-25">
@(tag)
</button>
}
</div>
}
else
{
<div class="alert alert-primary">
<TL>No tags found</TL>
</div>
}
</div>
</div>
</div> </div>
} </div>
else <div class="row">
{ <div class="col-xl-6 mb-5 mb-xl-10">
<div class="alert alert-primary"> <div class="card card-body">
<TL>No variables found</TL> <label class="form-label">
<TL>Docker images</TL>
</label>
<div class="input-group mb-5">
<input @bind="NewDockerImage.Name" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Enter docker image name"))">
<button @onclick="AddDockerImage" class="btn btn-primary">
<TL>Add</TL>
</button>
</div>
<div>
@if (Image.DockerImages.Any())
{
<div class="row">
@foreach (var imageDocker in Image.DockerImages)
{
<button @onclick="() => RemoveDockerImage(imageDocker)" class="col m-3 btn btn-outline-primary mw-25">
@(imageDocker.Name)
</button>
}
</div>
}
else
{
<div class="alert alert-primary">
<TL>No docker images found</TL>
</div>
}
</div>
</div>
</div> </div>
} <div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Default image</TL>
</label>
<select @bind="DefaultImageIndex" class="form-select">
@foreach (var image in Image.DockerImages)
{
<option value="@(image.Id)">@(image.Name)</option>
}
</select>
</div>
<div class="mb-10">
<label class="form-label">
<TL>Allocations</TL>
</label>
<input @bind="Image.Allocations" type="number" class="form-control">
</div>
</div>
</div>
</div>
<div class="row mx-0">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Startup command</TL>
</label>
<input @bind="Image.Startup" type="text" class="form-control">
</div>
<div class="row">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="mb-10">
<label class="form-label">
<TL>Install container</TL>
</label>
<input @bind="Image.InstallDockerImage" type="text" class="form-control">
</div>
</div>
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="mb-10">
<label class="form-label">
<TL>Install entry</TL>
</label>
<input @bind="Image.InstallEntrypoint" type="text" class="form-control">
</div>
</div>
</div>
<div class="card card-flush">
<FileEditor @ref="Editor" Language="shell" InitialData="@(Image.InstallScript)" HideControls="true"/>
</div>
</div>
</div>
<div class="row my-8">
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Configuration files</TL>
</label>
<textarea @bind="Image.ConfigFiles" class="form-control"></textarea>
</div>
</div>
</div>
<div class="col-xl-6 mb-5 mb-xl-10">
<div class="card card-body">
<div class="mb-10">
<label class="form-label">
<TL>Startup detection</TL>
</label>
<input @bind="Image.StartupDetection" type="text" class="form-control">
</div>
<div class="mb-10">
<label class="form-label">
<TL>Stop command</TL>
</label>
<input @bind="Image.StopCommand" type="text" class="form-control">
</div>
</div>
</div>
</div>
<div class="row my-6">
<div class="card card-body">
<div class="input-group mb-5">
<input type="text" @bind="ImageVariable.Key" placeholder="@(SmartTranslateService.Translate("Key"))" class="form-control">
<input type="text" @bind="ImageVariable.DefaultValue" placeholder="@(SmartTranslateService.Translate("Default value"))" class="form-control">
<button @onclick="AddVariable" class="btn btn-primary">
<TL>Add</TL>
</button>
</div>
<div>
@if (Image!.Variables.Any())
{
<div class="row">
@foreach (var variable in Image!.Variables)
{
<div class="input-group mb-3">
<input type="text" @bind="variable.Key" placeholder="@(SmartTranslateService.Translate("Key"))" class="form-control">
<input type="text" @bind="variable.DefaultValue" placeholder="@(SmartTranslateService.Translate("Default value"))" class="form-control">
<button @onclick="() => RemoveVariable(variable)" class="btn btn-danger">
<TL>Remove</TL>
</button>
</div>
}
</div>
}
else
{
<div class="alert alert-primary">
<TL>No variables found</TL>
</div>
}
</div>
</div>
</div>
<div class="row">
<div class="card card-body">
<div class="d-flex justify-content-end">
<a href="/admin/servers/images" class="btn btn-danger me-3">
<TL>Cancel</TL>
</a>
<WButton Text="@(SmartTranslateService.Translate("Export"))"
WorkingText="@(SmartTranslateService.Translate("Exporting"))"
CssClasses="btn-primary me-3"
OnClick="Export">
</WButton>
<WButton Text="@(SmartTranslateService.Translate("Save"))"
WorkingText="@(SmartTranslateService.Translate("Saving"))"
CssClasses="btn-success"
OnClick="Save">
</WButton>
</div>
</div>
</div>
}
</LazyLoader>
</div> </div>
</div>
</div>
<div class="row">
<div class="card card-body">
<div class="d-flex justify-content-end">
<a href="/admin/servers/images" class="btn btn-danger me-3">
<TL>Cancel</TL>
</a>
<WButton Text="@(SmartTranslateService.Translate("Export"))"
WorkingText="@(SmartTranslateService.Translate("Exporting"))"
CssClasses="btn-primary me-3"
OnClick="Export">
</WButton>
<WButton Text="@(SmartTranslateService.Translate("Save"))"
WorkingText="@(SmartTranslateService.Translate("Saving"))"
CssClasses="btn-success"
OnClick="Save">
</WButton>
</div>
</div>
</div>
}
</LazyLoader>
</div>
</OnlyAdmin>
@code @code
{ {

View File

@@ -9,6 +9,7 @@
@using System.Text @using System.Text
@using Moonlight.App.Helpers @using Moonlight.App.Helpers
@using Newtonsoft.Json @using Newtonsoft.Json
@using Moonlight.Shared.Components.Navigations
@inject Repository<Image> ImageRepository @inject Repository<Image> ImageRepository
@inject Repository<ImageVariable> ImageVariableRepository @inject Repository<ImageVariable> ImageVariableRepository
@@ -16,95 +17,95 @@
@inject SmartTranslateService SmartTranslateService @inject SmartTranslateService SmartTranslateService
@inject AlertService AlertService @inject AlertService AlertService
<OnlyAdmin> @attribute [PermissionRequired(nameof(Permissions.AdminServerImages))]
<div class="row">
<LazyLoader @ref="LazyLoader" Load="Load"> <AdminServersNavigation Index="4" />
<div class="card">
<div class="card-header border-0 pt-5"> <LazyLoader @ref="LazyLoader" Load="Load">
<h3 class="card-title align-items-start flex-column"> <div class="card">
<span class="card-label fw-bold fs-3 mb-1"> <div class="card-header border-0 pt-5">
<TL>Images</TL> <h3 class="card-title align-items-start flex-column">
</span> <span class="card-label fw-bold fs-3 mb-1">
</h3> <TL>Images</TL>
<div class="card-toolbar"> </span>
<a href="/admin/servers/images/new" class="btn btn-sm btn-light-success me-3"> </h3>
<i class="bx bx-layer-plus"></i> <div class="card-toolbar">
<TL>New image</TL> <a href="/admin/servers/images/new" class="btn btn-sm btn-light-success me-3">
</a> <i class="bx bx-layer-plus"></i>
<InputFile OnChange="OnFileChanged" type="file" id="fileUpload" hidden="" multiple=""/> <TL>New image</TL>
<label for="fileUpload" class="btn btn-sm btn-light-primary me-3"> </a>
<span class="svg-icon svg-icon-2"> <InputFile OnChange="OnFileChanged" type="file" id="fileUpload" hidden="" multiple=""/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <label for="fileUpload" class="btn btn-sm btn-light-primary me-3">
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z" fill="currentColor"></path> <span class="svg-icon svg-icon-2">
<path d="M10.4 3.60001L12 6H21C21.6 6 22 6.4 22 7V19C22 19.6 21.6 20 21 20H3C2.4 20 2 19.6 2 19V4C2 3.4 2.4 3 3 3H9.20001C9.70001 3 10.2 3.20001 10.4 3.60001ZM16 11.6L12.7 8.29999C12.3 7.89999 11.7 7.89999 11.3 8.29999L8 11.6H11V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H16Z" fill="currentColor"></path> <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.3" d="M11 11.6V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H11Z" fill="currentColor"></path> <path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z" fill="currentColor"></path>
</svg> <path d="M10.4 3.60001L12 6H21C21.6 6 22 6.4 22 7V19C22 19.6 21.6 20 21 20H3C2.4 20 2 19.6 2 19V4C2 3.4 2.4 3 3 3H9.20001C9.70001 3 10.2 3.20001 10.4 3.60001ZM16 11.6L12.7 8.29999C12.3 7.89999 11.7 7.89999 11.3 8.29999L8 11.6H11V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H16Z" fill="currentColor"></path>
</span> <path opacity="0.3" d="M11 11.6V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H11Z" fill="currentColor"></path>
<TL>Import</TL> </svg>
</label>
<InputFile OnChange="OnEggFileChanged" type="file" id="eggFileUpload" hidden="" multiple=""/>
<label for="eggFileUpload" class="btn btn-sm btn-light-primary">
<span class="svg-icon svg-icon-2">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z" fill="currentColor"></path>
<path d="M10.4 3.60001L12 6H21C21.6 6 22 6.4 22 7V19C22 19.6 21.6 20 21 20H3C2.4 20 2 19.6 2 19V4C2 3.4 2.4 3 3 3H9.20001C9.70001 3 10.2 3.20001 10.4 3.60001ZM16 11.6L12.7 8.29999C12.3 7.89999 11.7 7.89999 11.3 8.29999L8 11.6H11V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H16Z" fill="currentColor"></path>
<path opacity="0.3" d="M11 11.6V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H11Z" fill="currentColor"></path>
</svg>
</span>
<TL>Import pterodactyl egg</TL>
</label>
</div>
</div>
<div class="card-body pt-0">
@if (Images.Any())
{
<div class="table-responsive">
<Table TableItem="Image" Items="Images" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Name)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Description"))" Field="@(x => x.Description)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Uuid"))" Field="@(x => x.Uuid)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Servers with this image"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
<Template>
@{
var i = ServersCount.TryGetValue(context, out var value) ? value.ToString() : "N/A";
}
<span>
@(i)
</span> </span>
</Template> <TL>Import</TL>
</Column> </label>
<Column TableItem="Image" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false"> <InputFile OnChange="OnEggFileChanged" type="file" id="eggFileUpload" hidden="" multiple=""/>
<Template> <label for="eggFileUpload" class="btn btn-sm btn-light-primary">
<a href="/admin/servers/images/edit/@(context.Id)"> <span class="svg-icon svg-icon-2">
@(SmartTranslateService.Translate("Edit")) <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
</a> <path opacity="0.3" d="M10 4H21C21.6 4 22 4.4 22 5V7H10V4Z" fill="currentColor"></path>
</Template> <path d="M10.4 3.60001L12 6H21C21.6 6 22 6.4 22 7V19C22 19.6 21.6 20 21 20H3C2.4 20 2 19.6 2 19V4C2 3.4 2.4 3 3 3H9.20001C9.70001 3 10.2 3.20001 10.4 3.60001ZM16 11.6L12.7 8.29999C12.3 7.89999 11.7 7.89999 11.3 8.29999L8 11.6H11V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H16Z" fill="currentColor"></path>
</Column> <path opacity="0.3" d="M11 11.6V17C11 17.6 11.4 18 12 18C12.6 18 13 17.6 13 17V11.6H11Z" fill="currentColor"></path>
<Column TableItem="Image" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false"> </svg>
<Template> </span>
<WButton Text="@(SmartTranslateService.Translate("Delete"))" <TL>Import pterodactyl egg</TL>
WorkingText="@(SmartTranslateService.Translate("Deleting"))" </label>
CssClasses="btn-danger" </div>
OnClick="() => Delete(context)"> </div>
</WButton> <div class="card-body pt-0">
</Template> @if (Images.Any())
</Column> {
<Pager ShowPageNumber="true" ShowTotalCount="true"/> <div class="table-responsive">
</Table> <Table TableItem="Image" Items="Images" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Name)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Description"))" Field="@(x => x.Description)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Uuid"))" Field="@(x => x.Uuid)" Sortable="true" Filterable="true"/>
<Column TableItem="Image" Title="@(SmartTranslateService.Translate("Servers with this image"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
<Template>
@{
var i = ServersCount.TryGetValue(context, out var value) ? value.ToString() : "N/A";
}
<span>
@(i)
</span>
</Template>
</Column>
<Column TableItem="Image" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
<Template>
<a href="/admin/servers/images/edit/@(context.Id)">
@(SmartTranslateService.Translate("Edit"))
</a>
</Template>
</Column>
<Column TableItem="Image" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
<Template>
<WButton Text="@(SmartTranslateService.Translate("Delete"))"
WorkingText="@(SmartTranslateService.Translate("Deleting"))"
CssClasses="btn-danger"
OnClick="() => Delete(context)">
</WButton>
</Template>
</Column>
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
</Table>
</div>
}
else
{
<div class="alert alert-info">
<TL>No images found</TL>
</div>
}
</div>
</div> </div>
} </LazyLoader>
else
{
<div class="alert alert-info">
<TL>No images found</TL>
</div>
}
</div>
</div>
</LazyLoader>
</div>
</OnlyAdmin>
@code @code
{ {

View File

@@ -4,14 +4,16 @@
@using Moonlight.App.Repositories.Servers @using Moonlight.App.Repositories.Servers
@using BlazorTable @using BlazorTable
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using Moonlight.Shared.Components.Navigations
@inject ServerRepository ServerRepository @inject ServerRepository ServerRepository
@inject SmartTranslateService SmartTranslateService @inject SmartTranslateService SmartTranslateService
@attribute [PermissionRequired(nameof(Permissions.AdminServers))] @attribute [PermissionRequired(nameof(Permissions.AdminServers))]
<div class="row"> <AdminServersNavigation Index="0" />
<LazyLoader Load="Load">
<LazyLoader Load="Load">
<div class="card"> <div class="card">
<div class="card-header border-0 pt-5"> <div class="card-header border-0 pt-5">
<h3 class="card-title align-items-start flex-column"> <h3 class="card-title align-items-start flex-column">
@@ -65,7 +67,6 @@
</div> </div>
</div> </div>
</LazyLoader> </LazyLoader>
</div>
@code @code
{ {
@@ -76,6 +77,8 @@
Servers = ServerRepository Servers = ServerRepository
.Get() .Get()
.Include(x => x.Owner) .Include(x => x.Owner)
.ToArray() // Execute query and use the moonlight instance to sort
.OrderBy(x => x.Id)
.ToArray(); .ToArray();
return Task.CompletedTask; return Task.CompletedTask;

View File

@@ -6,7 +6,7 @@
@using Moonlight.App.Database.Entities @using Moonlight.App.Database.Entities
@using BlazorTable @using BlazorTable
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using Moonlight.App.ApiClients.Daemon.Resources @using Moonlight.Shared.Components.Navigations
@using Moonlight.App.ApiClients.Wings @using Moonlight.App.ApiClients.Wings
@using Moonlight.App.Helpers @using Moonlight.App.Helpers
@using Moonlight.App.Models.Misc @using Moonlight.App.Models.Misc
@@ -20,82 +20,84 @@
@attribute [PermissionRequired(nameof(Permissions.AdminServerManager))] @attribute [PermissionRequired(nameof(Permissions.AdminServerManager))]
<div class="card mb-5"> <AdminServersNavigation Index="1"/>
<div class="card">
<div class="card-header">
<span class="card-title">
@if (IsRunning)
{
<span><TL>Status</TL>:&nbsp;<TL>Currently scanning</TL> @(Node?.Name)</span>
}
else
{
<span><TL>Status</TL>:&nbsp;<TL>Scan complete</TL></span>
}
</span>
<div class="card-toolbar">
<WButton Text="@(SmartTranslateService.Translate("Refresh"))"
WorkingText="@(SmartTranslateService.Translate("Working"))"
CssClasses="btn-primary me-2"
OnClick="() => Task.Run(Scan)">
</WButton>
<WButton Text="@(SmartTranslateService.Translate("Stop all"))"
WorkingText="@(SmartTranslateService.Translate("Working"))"
CssClasses="btn-danger me-2"
OnClick="StopAll">
</WButton>
<WButton Text="@(SmartTranslateService.Translate("Kill all"))"
WorkingText="@(SmartTranslateService.Translate("Working"))"
CssClasses="btn-danger"
OnClick="KillAll">
</WButton>
</div>
</div>
<div class="card-body"> <div class="card-body">
<WButton Text="@(SmartTranslateService.Translate("Refresh"))" <div class="table-responsive">
WorkingText="@(SmartTranslateService.Translate("Working"))" <Table TableItem="RunningServer" Items="RunningServers" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
CssClasses="btn-primary" <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Server.Name)" Sortable="true" Filterable="true">
OnClick="() => Task.Run(Scan)"> <Template>
</WButton> <a href="/server/@(context.Server.Uuid)">@(context.Server.Name)</a>
<WButton Text="@(SmartTranslateService.Translate("Stop all"))" </Template>
WorkingText="@(SmartTranslateService.Translate("Working"))" </Column>
CssClasses="btn-danger" <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Cpu usage"))" Field="@(x => x.Container.Cpu)" Sortable="true" Filterable="true">
OnClick="StopAll"> <Template>
</WButton> <span>@(context.Container.Cpu)%</span>
<WButton Text="@(SmartTranslateService.Translate("Kill all"))" </Template>
WorkingText="@(SmartTranslateService.Translate("Working"))" </Column>
CssClasses="btn-danger" <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Memory usage"))" Field="@(x => x.Container.Memory)" Sortable="true" Filterable="true">
OnClick="KillAll"> <Template>
</WButton> <span>@(Formatter.FormatSize(context.Container.Memory))</span>
</div> </Template>
</div> </Column>
<div class="card mb-5 bg-secondary"> <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Network in"))" Field="@(x => x.Container.NetworkIn)" Sortable="true" Filterable="true">
<div class="card-body d-flex align-items-center"> <Template>
@if (IsRunning) <span>@(Formatter.FormatSize(context.Container.NetworkIn))</span>
{ </Template>
<h4><TL>Currently scanning</TL>: @(Node?.Name)</h4> </Column>
} <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Network out"))" Field="@(x => x.Container.NetworkOut)" Sortable="true" Filterable="true">
else <Template>
{ <span>@(Formatter.FormatSize(context.Container.NetworkOut))</span>
<TL>Scan complete</TL> </Template>
} </Column>
</div> <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Image"))" Field="@(x => x.Server.Image.Name)" Sortable="true" Filterable="true">
</div> <Template>
<div class="card card-body"> <a href="/admin/servers/images/edit/@(context.Server.Image.Id)">@(context.Server.Image.Name)</a>
<div class="table-responsive"> </Template>
<Table TableItem="RunningServer" Items="RunningServers" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted"> </Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Server.Name)" Sortable="true" Filterable="true"> <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Node"))" Field="@(x => x.Server.Node.Name)" Sortable="true" Filterable="true">
<Template> <Template>
<a href="/server/@(context.Server.Uuid)">@(context.Server.Name)</a> <a href="/admin/nodes/view/@(context.Server.Node.Id)">@(context.Server.Node.Name)</a>
</Template> </Template>
</Column> </Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Cpu usage"))" Field="@(x => x.Container.Cpu)" Sortable="true" Filterable="true"> <Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Owner"))" Field="@(x => x.Server.Owner.Email)" Sortable="true" Filterable="true">
<Template> <Template>
<span>@(context.Container.Cpu)%</span> <a href="/admin/users/view/@(context.Server.Owner.Id)/">@context.Server.Owner.Email</a>
</Template> </Template>
</Column> </Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Memory usage"))" Field="@(x => x.Container.Memory)" Sortable="true" Filterable="true"> <Pager ShowPageNumber="true" ShowTotalCount="true"/>
<Template> </Table>
<span>@(Formatter.FormatSize(context.Container.Memory))</span> </div>
</Template>
</Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Network in"))" Field="@(x => x.Container.NetworkIn)" Sortable="true" Filterable="true">
<Template>
<span>@(Formatter.FormatSize(context.Container.NetworkIn))</span>
</Template>
</Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Network out"))" Field="@(x => x.Container.NetworkOut)" Sortable="true" Filterable="true">
<Template>
<span>@(Formatter.FormatSize(context.Container.NetworkOut))</span>
</Template>
</Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Image"))" Field="@(x => x.Server.Image.Name)" Sortable="true" Filterable="true">
<Template>
<a href="/admin/servers/images/edit/@(context.Server.Image.Id)">@(context.Server.Image.Name)</a>
</Template>
</Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Node"))" Field="@(x => x.Server.Node.Name)" Sortable="true" Filterable="true">
<Template>
<a href="/admin/nodes/view/@(context.Server.Node.Id)">@(context.Server.Node.Name)</a>
</Template>
</Column>
<Column TableItem="RunningServer" Title="@(SmartTranslateService.Translate("Owner"))" Field="@(x => x.Server.Owner.Email)" Sortable="true" Filterable="true">
<Template>
<a href="/admin/users/view/@(context.Server.Owner.Id)/">@context.Server.Owner.Email</a>
</Template>
</Column>
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
</Table>
</div> </div>
</div> </div>