LANCommander/LANCommander.Server/UI/Pages/Servers/Index.razor
2025-08-01 02:35:23 -05:00

168 lines
5.4 KiB
Text

@page "/Servers"
@using LANCommander.Server.Services.Abstractions
@using LANCommander.Server.Services.Enums
@using LANCommander.Server.UI.Pages.Servers.Components
@attribute [Authorize(Roles = RoleService.AdministratorRoleName)]
@inject ServerService ServerService
@inject NavigationManager NavigationManager
@inject ModalService ModalService
@inject IServiceProvider ServiceProvider
<PageHeader Title="Servers" Subtitle="@Total.ToString()" />
<DataTable
@ref="Table"
TItem="Server"
Size="TableSize.Small"
@bind-SelectedRows="SelectedServers"
@bind-Total="Total"
Responsive
ColumnPicker
Searchable
SearchProperty="s => s.Name">
<RightToolbar>
@if (SelectedServers != null && SelectedServers.Count() > 0)
{
<Button Type="@ButtonType.Primary" OnClick="() => StartServers()">Start</Button>
<Popconfirm OnConfirm="() => StopServers()" Title="Are you sure you want to kill these server processes?">
<Button Danger Type="@ButtonType.Primary">Stop</Button>
</Popconfirm>
}
<Button Type="@ButtonType.Default" OnClick="OpenImportDialog">Import</Button>
<Button OnClick="@(() => NavigationManager.NavigateTo("/Servers/Add"))" Type="@ButtonType.Primary">Add Server</Button>
</RightToolbar>
<Columns>
<Selection Key="@(context.Id.ToString())" />
<BoundDataColumn
Property="s => s.Game"
Include="Game.Media">
<Flex Align="FlexAlign.Center" Gap="FlexGap.Middle">
@if (context.Game != null)
{
<Image Src="@GetIcon(context.Game)" Height="32" Width="32" Preview="false"></Image>
<span>@context.Game?.Title</span>
}
</Flex>
</BoundDataColumn>
<BoundDataColumn Property="s => s.Name" Sortable DefaultSortOrder="SortDirection.Ascending" />
<BoundDataColumn Property="s => s.Port" Sortable />
<BoundDataColumn Property="s => s.CreatedOn" Title="Created On" Sortable>
<LocalTime Value="context.UpdatedOn" />
</BoundDataColumn>
<BoundDataColumn Property="s => s.CreatedBy != null ? s.CreatedBy.UserName : String.Empty" Title="Created By" Sortable Include="CreatedBy" />
<BoundDataColumn Property="s => s.UpdatedOn" Title="Updated On" Sortable>
<LocalTime Value="context.UpdatedOn" />
</BoundDataColumn>
<BoundDataColumn Property="s => s.UpdatedBy != null ? s.UpdatedBy.UserName : String.Empty" Title="Updated By" Sortable Include="UpdatedBy" />
<DataActions TData="string">
<ServerControl ServerId="context.Id" />
<a href="/Servers/@(context.Id)" class="ant-btn ant-btn-default">Edit</a>
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this server?">
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger/>
</Popconfirm>
</DataActions>
</Columns>
<PaginationTemplate>
<Pagination
Total="context.Total"
PageSize="context.PageSize"
Current="context.PageIndex"
DefaultPageSize="25"
PageSizeOptions="new [] { 25, 50, 100, 200 }"
ShowSizeChanger
OnChange="context.HandlePageChange" />
</PaginationTemplate>
</DataTable>
@code {
DataTable<Server> Table;
bool Loading = true;
int Total;
IEnumerable<Server> SelectedServers;
protected override async Task OnInitializedAsync()
{
Loading = false;
}
async Task Delete(Server server)
{
Loading = true;
await Task.Yield();
await InvokeAsync(StateHasChanged);
await ServerService.DeleteAsync(server);
await Task.Yield();
await InvokeAsync(StateHasChanged);
Loading = false;
}
string GetIcon(Game game)
{
var media = game?.Media?.FirstOrDefault(m => m.Type == SDK.Enums.MediaType.Icon);
if (media != null)
return $"/api/Media/{media.Id}/Download?fileId={media.FileId}";
else
return "/favicon.ico";
}
async Task StartServers()
{
foreach (var engine in ServiceProvider.GetServices<IServerEngine>())
{
foreach (var server in SelectedServers)
{
try
{
if (engine.IsManaging(server.Id))
engine.StartAsync(server.Id);
}
catch { }
}
}
}
void StopServers()
{
foreach (var engine in ServiceProvider.GetServices<IServerEngine>())
{
foreach (var server in SelectedServers)
{
if (engine.IsManaging(server.Id))
engine.StopAsync(server.Id);
}
}
}
async Task OpenImportDialog()
{
var options = new ImportDialogOptions
{
Hint = "Only LCX files are supported for importing games"
};
var modalOptions = new ModalOptions
{
Title = "Import Game",
DestroyOnClose = true,
MaskClosable = false,
Footer = null,
};
var modalRef = ModalService.CreateModal<ImportUploadDialog, ImportDialogOptions>(modalOptions, options);
modalRef.OnOk = modalRef.OnCancel;
}
}