Skip to content

Commit

Permalink
Merge pull request #525 from MUnique/dev/admin-panel-improvements
Browse files Browse the repository at this point in the history
Improvements for the admin panel
  • Loading branch information
sven-n authored Nov 5, 2024
2 parents 4ebe956 + 6cfe52d commit d94a4f5
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 36 deletions.
1 change: 1 addition & 0 deletions src/Web/AdminPanel/MUnique.OpenMU.Web.AdminPanel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="Blazored.Modal" Version="6.0.1" />
<PackageReference Include="Blazored.Toast" Version="4.2.1" />
<PackageReference Include="Blazored.Typeahead" Version="4.7.0" />
<PackageReference Include="BlazorInputFile" Version="0.2.0" />
<PackageReference Include="Mapster" Version="7.4.0" />
Expand Down
18 changes: 9 additions & 9 deletions src/Web/AdminPanel/Pages/CreateConnectServerConfig.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages;

using System.ComponentModel.DataAnnotations;
using System.Threading;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Interfaces;
Expand Down Expand Up @@ -42,10 +42,10 @@ public partial class CreateConnectServerConfig : ComponentBase, IAsyncDisposable
public IDataSource<GameConfiguration> DataSource { get; set; } = null!;

/// <summary>
/// Gets or sets the modal service.
/// Gets or sets the toast service.
/// </summary>
[Inject]
public IModalService ModalService { get; set; } = null!;
public IToastService ToastService { get; set; } = null!;

/// <summary>
/// Gets or sets the navigation manager.
Expand Down Expand Up @@ -131,7 +131,6 @@ private async ValueTask<ConnectServerDefinition> CreateDefinitionByViewModelAsyn

private async Task OnSaveButtonClickAsync()
{
string text;
try
{
var gameConfiguration = await this.DataSource.GetOwnerAsync().ConfigureAwait(false);
Expand All @@ -141,13 +140,13 @@ private async Task OnSaveButtonClickAsync()
var existingServerDefinitions = (await saveContext.GetAsync<ConnectServerDefinition>().ConfigureAwait(false)).ToList();
if (existingServerDefinitions.Any(def => def.ServerId == this._viewModel?.ServerId))
{
await this.ModalService.ShowMessageAsync("Save", $"Server with Id {this._viewModel?.ServerId} already exists. Please use another value.").ConfigureAwait(true);
this.ToastService.ShowError($"Server with Id {this._viewModel?.ServerId} already exists. Please use another value.");
return;
}

if (existingServerDefinitions.Any(def => def.ClientListenerPort == this._viewModel?.NetworkPort))
{
await this.ModalService.ShowMessageAsync("Save", $"A server with tcp port {this._viewModel?.NetworkPort} already exists. Please use another tcp port.").ConfigureAwait(true);
this.ToastService.ShowError($"A server with tcp port {this._viewModel?.NetworkPort} already exists. Please use another tcp port.");
return;
}

Expand All @@ -157,24 +156,25 @@ private async Task OnSaveButtonClickAsync()
this._initState = "Saving Configuration ...";
await this.InvokeAsync(this.StateHasChanged);
var success = await saveContext.SaveChangesAsync().ConfigureAwait(true);
text = success ? "The changes have been saved." : "There were no changes to save.";

// if success, init new game server instance
if (success)
{
this.ToastService.ShowSuccess("The connection server configuration has been saved. Initializing connect server ...");
this._initState = "Initializing Connect Server ...";
await this.InvokeAsync(this.StateHasChanged);
await this.ServerInstanceManager.InitializeConnectServerAsync(connectServerDefinition.ConfigurationId);
this.NavigationManager.NavigateTo("servers");
return;
}

this.ToastService.ShowError("No changes have been saved.");
}
catch (Exception ex)
{
text = $"An unexpected error occurred: {ex.Message}.";
this.ToastService.ShowError($"An unexpected error occurred: {ex.Message}.");
}

await this.ModalService.ShowMessageAsync("Save", text).ConfigureAwait(true);
this._initState = null;
}

Expand Down
18 changes: 13 additions & 5 deletions src/Web/AdminPanel/Pages/CreateGameServerConfig.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages;
using System.ComponentModel.DataAnnotations;
using System.Threading;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Persistence;
Expand Down Expand Up @@ -48,6 +49,12 @@ public partial class CreateGameServerConfig : ComponentBase, IAsyncDisposable
[Inject]
public IModalService ModalService { get; set; } = null!;

/// <summary>
/// Gets or sets the toast service.
/// </summary>
[Inject]
public IToastService ToastService { get; set; } = null!;

/// <summary>
/// Gets or sets the navigation manager.
/// </summary>
Expand Down Expand Up @@ -152,13 +159,13 @@ private async Task OnSaveButtonClickAsync()
var existingServerDefinitions = (await saveContext.GetAsync<GameServerDefinition>().ConfigureAwait(false)).ToList();
if (existingServerDefinitions.Any(def => def.ServerID == this._viewModel?.ServerId))
{
await this.ModalService.ShowMessageAsync("Save", $"Server with Id {this._viewModel?.ServerId} already exists. Please use another value.").ConfigureAwait(true);
this.ToastService.ShowError($"Server with Id {this._viewModel?.ServerId} already exists. Please use another value.");
return;
}

if (existingServerDefinitions.Any(def => def.Endpoints.Any(endpoint => endpoint.NetworkPort == this._viewModel?.NetworkPort)))
{
await this.ModalService.ShowMessageAsync("Save", $"A server with tcp port {this._viewModel?.NetworkPort} already exists. Please use another tcp port.").ConfigureAwait(true);
this.ToastService.ShowError($"A server with tcp port {this._viewModel?.NetworkPort} already exists. Please use another tcp port.");
return;
}

Expand All @@ -168,24 +175,25 @@ private async Task OnSaveButtonClickAsync()
this._initState = "Saving Configuration ...";
await this.InvokeAsync(this.StateHasChanged);
var success = await saveContext.SaveChangesAsync().ConfigureAwait(true);
text = success ? "The changes have been saved." : "There were no changes to save.";

// if success, init new game server instance
if (success)
{
this.ToastService.ShowSuccess("The game server configuration has been saved. Initializing game server ...");
this._initState = "Initializing Game Server ...";
await this.InvokeAsync(this.StateHasChanged);
await this.ServerInstanceManager.InitializeGameServerAsync(gameServerDefinition.ServerID);
this.NavigationManager.NavigateTo("servers");
return;
}

this.ToastService.ShowError("No changes have been saved.");
}
catch (Exception ex)
{
text = $"An unexpected error occurred: {ex.Message}.";
this.ToastService.ShowError($"An unexpected error occurred: {ex.Message}.");
}

await this.ModalService.ShowMessageAsync("Save", text).ConfigureAwait(true);
this._initState = null;
}

Expand Down
18 changes: 12 additions & 6 deletions src/Web/AdminPanel/Pages/EditBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages;
using System.Reflection;
using System.Threading;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;
Expand Down Expand Up @@ -71,6 +72,12 @@ private enum DataLoadingState
[Inject]
public IModalService ModalService { get; set; } = null!;

/// <summary>
/// Gets or sets the toast service.
/// </summary>
[Inject]
public IToastService ToastService { get; set; } = null!;

/// <summary>
/// Gets or sets the configuration data source.
/// </summary>
Expand Down Expand Up @@ -221,26 +228,25 @@ await this.InvokeAsync(() =>
/// </summary>
protected async Task SaveChangesAsync()
{
string text;
try
{
if (this._persistenceContext is { } context)
{
var success = await context.SaveChangesAsync().ConfigureAwait(true);
text = success ? "The changes have been saved." : "There were no changes to save.";
var text = success ? "The changes have been saved." : "There were no changes to save.";
this.ToastService.ShowSuccess(text);
}
else
{
text = "Failed, context not initialized";
this.ToastService.ShowError("Failed, context not initialized");
}
}
catch (Exception ex)
{
this.Logger?.LogError(ex, $"Error during saving {this.Id}");
text = $"An unexpected error occured: {ex.Message}.";
var text = $"An unexpected error occured: {ex.Message}.";
this.ToastService.ShowError(text);
}

await this.ModalService.ShowMessageAsync("Save", text).ConfigureAwait(true);
}

/// <summary>
Expand Down
5 changes: 4 additions & 1 deletion src/Web/AdminPanel/Pages/EditConfigGrid.razor
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@
var targetUrl = $"edit-config/{this.TypeString}/" + context.Id;
}
<button type="button" class="btn-info" @onclick="@(() => this.NavigationManager.NavigateTo(targetUrl))">Edit</button>
<button type="button" class="btn-danger" @onclick="@(() => this.OnDeleteButtonClickAsync(context))"><span class="oi oi-trash"></span> Delete</button>
</TemplateColumn>
</QuickGrid>
</div>
<Paginator State="@_pagination" />
<Paginator State="@_pagination" />
<hr />
<button type="button" class="btn-outline-primary" @onclick="OnCreateButtonClickAsync"><span class="oi oi-plus"></span> Add New</button>
76 changes: 76 additions & 0 deletions src/Web/AdminPanel/Pages/EditConfigGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages;
using System.Collections;
using System.ComponentModel;
using System.Threading;
using Blazored.Modal;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.QuickGrid;
using Microsoft.Extensions.Logging;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Persistence;
using MUnique.OpenMU.Web.AdminPanel.Components.Form;

/// <summary>
/// Razor page which shows objects of the specified type in a grid.
Expand Down Expand Up @@ -48,6 +53,24 @@ public partial class EditConfigGrid : ComponentBase, IAsyncDisposable
[Inject]
public IPersistenceContextProvider PersistenceContextProvider { get; set; } = null!;

/// <summary>
/// Gets or sets the modal service.
/// </summary>
[Inject]
public IModalService ModalService { get; set; } = null!;

/// <summary>
/// Gets or sets the toast service.
/// </summary>
[Inject]
public IToastService ToastService { get; set; } = null!;

/// <summary>
/// Gets or sets the logger.
/// </summary>
[Inject]
public ILogger<EditConfigGrid> Logger { get; set; } = null!;

/// <summary>
/// Gets or sets the type.
/// </summary>
Expand Down Expand Up @@ -142,6 +165,59 @@ await this.InvokeAsync(async () =>
.Select(assembly => assembly.GetType(this.TypeString)).FirstOrDefault(t => t != null);
}

private async Task OnDeleteButtonClickAsync(ViewModel viewModel)
{
try
{
var dialogResult = await this.ModalService.ShowQuestionAsync("Are you sure?", $"You're about to delete '{viewModel.Name}. Are you sure?");
if (!dialogResult)
{
return;
}

var cancellationToken = this._disposeCts?.Token ?? default;
var gameConfiguration = await this.DataSource.GetOwnerAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
using var deleteContext = this.PersistenceContextProvider.CreateNewContext(gameConfiguration);
deleteContext.Attach(viewModel.Parent);
await deleteContext.DeleteAsync(viewModel.Parent).ConfigureAwait(false);
await deleteContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
this.ToastService.ShowSuccess($"Deleted '{viewModel.Name}' successfully.");
this._viewModels = null;
this._loadTask = Task.Run(() => this.LoadDataAsync(cancellationToken), cancellationToken);
}
catch (Exception ex)
{
this.Logger.LogError(ex, $"Couldn't delete '{viewModel.Name}', probably because it's referenced by another object.");
this.ToastService.ShowError($"Couldn't delete '{viewModel.Name}', probably because it's referenced by another object. For details, see log");
}
}

private async Task OnCreateButtonClickAsync()
{
var cancellationToken = this._disposeCts?.Token ?? default;
var gameConfiguration = await this.DataSource.GetOwnerAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
using var creationContext = this.PersistenceContextProvider.CreateNewContext(gameConfiguration);
var newObject = creationContext.CreateNew(this.Type!);
var parameters = new ModalParameters();
var modalType = typeof(ModalCreateNew<>).MakeGenericType(this.Type!);

parameters.Add(nameof(ModalCreateNew<object>.Item), newObject);
var options = new ModalOptions
{
DisableBackgroundCancel = true,
};

var modal = this.ModalService.Show(modalType, $"Create", parameters, options);
var result = await modal.Result.ConfigureAwait(false);
if (!result.Cancelled)
{
await creationContext.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
this.ToastService.ShowSuccess("New object successfully created.");
this._viewModels = null;
this._loadTask = Task.Run(() => this.LoadDataAsync(cancellationToken), cancellationToken);
}
}

/// <summary>
/// The view model for the grid.
/// We use this instead of the objects, because it makes the code simpler.
Expand Down
15 changes: 10 additions & 5 deletions src/Web/AdminPanel/Pages/EditMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages;
using System.Reflection;
using System.Threading;
using Blazored.Modal.Services;
using Blazored.Toast.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Routing;
Expand Down Expand Up @@ -41,6 +42,12 @@ public sealed class EditMap : ComponentBase, IDisposable
[Inject]
private IModalService ModalService { get; set; } = null!;

/// <summary>
/// Gets or sets the toast service.
/// </summary>
[Inject]
private IToastService ToastService { get; set; } = null!;

/// <summary>
/// Gets or sets the game configuration.
/// </summary>
Expand Down Expand Up @@ -209,19 +216,17 @@ private async Task LoadDataAsync(CancellationToken cancellationToken)

private async Task SaveChangesAsync()
{
string text;
try
{
var context = await this.GameConfigurationSource.GetContextAsync().ConfigureAwait(true);
var success = await context.SaveChangesAsync().ConfigureAwait(true);
text = success ? "The changes have been saved." : "There were no changes to save.";
var text = success ? "The changes have been saved." : "There were no changes to save.";
this.ToastService.ShowSuccess(text);
}
catch (Exception ex)
{
this.Logger.LogError(ex, $"Error during saving");
text = $"An unexpected error occured: {ex.Message}.";
this.ToastService.ShowError($"An unexpected error occured: {ex.Message}. See logs for more details.");
}

await this.ModalService.ShowMessageAsync("Save", text).ConfigureAwait(true);
}
}
Loading

0 comments on commit d94a4f5

Please sign in to comment.