Extract workspace campaign coordinator
This commit is contained in:
@@ -208,144 +208,23 @@ public partial class Workspace : IAsyncDisposable
|
||||
return SetMobilePanelAsync("log");
|
||||
}
|
||||
|
||||
private async Task OnCampaignSelectionChangedAsync(ChangeEventArgs args)
|
||||
{
|
||||
if (!Guid.TryParse(args.Value?.ToString(), out var campaignId))
|
||||
return;
|
||||
private Task OnCampaignSelectionChangedAsync(ChangeEventArgs args) => CampaignsFlow.OnCampaignSelectionChangedAsync(args);
|
||||
|
||||
SelectedCampaignId = campaignId;
|
||||
await JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", CampaignSessionKey, campaignId.ToString());
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
IsScreenMenuOpen = false;
|
||||
}
|
||||
private Task OnCampaignCreatedAsync(Guid campaignId) => CampaignsFlow.OnCampaignCreatedAsync(campaignId);
|
||||
|
||||
private async Task OnCampaignCreatedAsync(Guid campaignId)
|
||||
{
|
||||
await ReloadCampaignsAsync(campaignId);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
SetStatus("Campaign created.", false);
|
||||
}
|
||||
private void OpenCreateCharacterModal() => CampaignsFlow.OpenCreateCharacterModal();
|
||||
|
||||
private void OpenCreateCharacterModal()
|
||||
{
|
||||
CreateCharacterInitialModel = new()
|
||||
{
|
||||
Name = string.Empty,
|
||||
CampaignId = SelectedCampaignId?.ToString() ?? CharacterCampaignOptions.FirstOrDefault()?.Id.ToString() ?? string.Empty,
|
||||
OwnerUsername = string.Empty
|
||||
};
|
||||
private Task OpenEditCharacterModal(CharacterSummary character) => CampaignsFlow.OpenEditCharacterModal(character);
|
||||
|
||||
CreateCharacterFormVersion++;
|
||||
CanEditCharacterOwner = false;
|
||||
ShowCreateCharacterModal = true;
|
||||
}
|
||||
private void CloseCharacterModals() => CampaignsFlow.CloseCharacterModals();
|
||||
|
||||
private async Task OpenEditCharacterModal(CharacterSummary character)
|
||||
{
|
||||
if (IsCurrentUserGm || IsCurrentUserAdmin)
|
||||
await LoadKnownUsernamesAsync();
|
||||
private Task OnCharacterCreatedAsync(Guid? campaignId) => CampaignsFlow.OnCharacterCreatedAsync(campaignId);
|
||||
|
||||
EditingCharacterId = character.Id;
|
||||
EditCharacterInitialModel = new()
|
||||
{
|
||||
Name = character.Name,
|
||||
CampaignId = character.CampaignId?.ToString() ?? string.Empty,
|
||||
OwnerUsername = string.Empty
|
||||
};
|
||||
private Task OnCharacterUpdatedAsync(Guid? campaignId) => CampaignsFlow.OnCharacterUpdatedAsync(campaignId);
|
||||
|
||||
EditCharacterFormVersion++;
|
||||
CanEditCharacterOwner = IsCurrentUserGm || IsCurrentUserAdmin;
|
||||
ShowEditCharacterModal = true;
|
||||
}
|
||||
private Task DeleteSelectedCampaignAsync() => CampaignsFlow.DeleteSelectedCampaignAsync();
|
||||
|
||||
private void CloseCharacterModals()
|
||||
{
|
||||
ShowCreateCharacterModal = false;
|
||||
ShowEditCharacterModal = false;
|
||||
CanEditCharacterOwner = false;
|
||||
EditingCharacterId = null;
|
||||
}
|
||||
|
||||
private async Task OnCharacterCreatedAsync(Guid? campaignId)
|
||||
{
|
||||
CloseCharacterModals();
|
||||
await ReloadCampaignsAsync(campaignId);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
SetStatus("Character created.", false);
|
||||
}
|
||||
|
||||
private async Task OnCharacterUpdatedAsync(Guid? campaignId)
|
||||
{
|
||||
CloseCharacterModals();
|
||||
await ReloadCampaignsAsync(campaignId);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
SetStatus(campaignId.HasValue ? "Character updated." : "Character unlinked from campaign.", false);
|
||||
}
|
||||
|
||||
private async Task DeleteSelectedCampaignAsync()
|
||||
{
|
||||
if (SelectedCampaign is null || IsMutating || !CanDeleteSelectedCampaign)
|
||||
return;
|
||||
|
||||
var confirmed = await JS.InvokeAsync<bool>("confirm", $"Delete campaign '{SelectedCampaign.Name}'?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
IsMutating = true;
|
||||
try
|
||||
{
|
||||
_ = await ApiClient.RequestAsync<bool>("DELETE", $"/api/campaigns/{SelectedCampaign.Id}");
|
||||
await ReloadCampaignsAsync(null);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
SetStatus("Campaign deleted.", false);
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
SetStatus(ex.Message, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsMutating = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteCharacterAsync(CharacterSummary character)
|
||||
{
|
||||
if (IsMutating || !CanDeleteCharacter(character))
|
||||
return;
|
||||
|
||||
var confirmed = await JS.InvokeAsync<bool>("confirm", $"Delete character '{character.Name}'?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
IsMutating = true;
|
||||
try
|
||||
{
|
||||
_ = await ApiClient.RequestAsync<bool>("DELETE", $"/api/characters/{character.Id}");
|
||||
await ReloadCampaignsAsync(SelectedCampaignId);
|
||||
await ReloadCharacterCampaignOptionsAsync();
|
||||
await RefreshCampaignScopeAsync();
|
||||
await SyncStateEventsAsync();
|
||||
SetStatus("Character deleted.", false);
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
SetStatus(ex.Message, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsMutating = false;
|
||||
}
|
||||
}
|
||||
private Task DeleteCharacterAsync(CharacterSummary character) => CampaignsFlow.DeleteCharacterAsync(character);
|
||||
|
||||
private async Task SelectCharacterAsync(Guid characterId)
|
||||
{
|
||||
@@ -354,15 +233,9 @@ public partial class Workspace : IAsyncDisposable
|
||||
await EnsureSelectedCharacterActiveAsync();
|
||||
}
|
||||
|
||||
private bool CanEditCharacter(CharacterSummary character)
|
||||
{
|
||||
return User is not null && (character.OwnerUserId == User.Id || IsCurrentUserGm || IsCurrentUserAdmin);
|
||||
}
|
||||
private bool CanEditCharacter(CharacterSummary character) => CampaignsFlow.CanEditCharacter(character);
|
||||
|
||||
private bool CanDeleteCharacter(CharacterSummary character)
|
||||
{
|
||||
return User is not null && (character.OwnerUserId == User.Id || IsCurrentUserAdmin);
|
||||
}
|
||||
private bool CanDeleteCharacter(CharacterSummary character) => CampaignsFlow.CanDeleteCharacter(character);
|
||||
|
||||
private static bool CanActivateCharacter(CharacterSummary character, UserSummary? user)
|
||||
{
|
||||
@@ -891,6 +764,16 @@ public partial class Workspace : IAsyncDisposable
|
||||
private bool IsPlayScreen => State.IsPlayScreen;
|
||||
private bool IsManagementScreen => State.IsManagementScreen;
|
||||
private bool IsAdminScreen => State.IsAdminScreen;
|
||||
private WorkspaceCampaignCoordinator CampaignsFlow => m_CampaignsFlow ??= new(
|
||||
State,
|
||||
Feedback,
|
||||
JS,
|
||||
ApiClient,
|
||||
LoadKnownUsernamesAsync,
|
||||
ReloadCampaignsAsync,
|
||||
ReloadCharacterCampaignOptionsAsync,
|
||||
RefreshCampaignScopeAsync,
|
||||
SyncStateEventsAsync);
|
||||
private WorkspaceAdminCoordinator Admin => m_Admin ??= new(
|
||||
State,
|
||||
Feedback,
|
||||
@@ -943,6 +826,7 @@ public partial class Workspace : IAsyncDisposable
|
||||
private const string MobilePanelSessionKey = "play-panel";
|
||||
private const int CampaignLogWindowSize = 25;
|
||||
|
||||
private WorkspaceCampaignCoordinator? m_CampaignsFlow;
|
||||
private WorkspaceAdminCoordinator? m_Admin;
|
||||
private WorkspaceFeedbackService? m_Feedback;
|
||||
private WorkspaceSessionCoordinator? m_Session;
|
||||
|
||||
193
RpgRoller/Components/Pages/WorkspaceCampaignCoordinator.cs
Normal file
193
RpgRoller/Components/Pages/WorkspaceCampaignCoordinator.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using RpgRoller.Contracts;
|
||||
|
||||
namespace RpgRoller.Components.Pages;
|
||||
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class WorkspaceCampaignCoordinator
|
||||
{
|
||||
public WorkspaceCampaignCoordinator(
|
||||
WorkspaceState state,
|
||||
WorkspaceFeedbackService feedback,
|
||||
IJSRuntime js,
|
||||
RpgRollerApiClient apiClient,
|
||||
Func<Task> loadKnownUsernamesAsync,
|
||||
Func<Guid?, Task> reloadCampaignsAsync,
|
||||
Func<Task> reloadCharacterCampaignOptionsAsync,
|
||||
Func<Task> refreshCampaignScopeAsync,
|
||||
Func<Task> syncStateEventsAsync)
|
||||
{
|
||||
m_State = state;
|
||||
m_Feedback = feedback;
|
||||
m_JS = js;
|
||||
m_ApiClient = apiClient;
|
||||
m_LoadKnownUsernamesAsync = loadKnownUsernamesAsync;
|
||||
m_ReloadCampaignsAsync = reloadCampaignsAsync;
|
||||
m_ReloadCharacterCampaignOptionsAsync = reloadCharacterCampaignOptionsAsync;
|
||||
m_RefreshCampaignScopeAsync = refreshCampaignScopeAsync;
|
||||
m_SyncStateEventsAsync = syncStateEventsAsync;
|
||||
}
|
||||
|
||||
public async Task OnCampaignSelectionChangedAsync(ChangeEventArgs args)
|
||||
{
|
||||
if (!Guid.TryParse(args.Value?.ToString(), out var campaignId))
|
||||
return;
|
||||
|
||||
m_State.SelectedCampaignId = campaignId;
|
||||
await m_JS.InvokeVoidAsync("rpgRollerApi.setSessionValue", CampaignSessionKey, campaignId.ToString());
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_State.IsScreenMenuOpen = false;
|
||||
}
|
||||
|
||||
public async Task OnCampaignCreatedAsync(Guid campaignId)
|
||||
{
|
||||
await m_ReloadCampaignsAsync(campaignId);
|
||||
await m_ReloadCharacterCampaignOptionsAsync();
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_Feedback.SetStatus("Campaign created.", false);
|
||||
}
|
||||
|
||||
public void OpenCreateCharacterModal()
|
||||
{
|
||||
m_State.CreateCharacterInitialModel = new()
|
||||
{
|
||||
Name = string.Empty,
|
||||
CampaignId = m_State.SelectedCampaignId?.ToString() ?? m_State.CharacterCampaignOptions.FirstOrDefault()?.Id.ToString() ?? string.Empty,
|
||||
OwnerUsername = string.Empty
|
||||
};
|
||||
|
||||
m_State.CreateCharacterFormVersion += 1;
|
||||
m_State.CanEditCharacterOwner = false;
|
||||
m_State.ShowCreateCharacterModal = true;
|
||||
}
|
||||
|
||||
public async Task OpenEditCharacterModal(CharacterSummary character)
|
||||
{
|
||||
if (m_State.IsCurrentUserGm || m_State.IsCurrentUserAdmin)
|
||||
await m_LoadKnownUsernamesAsync();
|
||||
|
||||
m_State.EditingCharacterId = character.Id;
|
||||
m_State.EditCharacterInitialModel = new()
|
||||
{
|
||||
Name = character.Name,
|
||||
CampaignId = character.CampaignId?.ToString() ?? string.Empty,
|
||||
OwnerUsername = string.Empty
|
||||
};
|
||||
|
||||
m_State.EditCharacterFormVersion += 1;
|
||||
m_State.CanEditCharacterOwner = m_State.IsCurrentUserGm || m_State.IsCurrentUserAdmin;
|
||||
m_State.ShowEditCharacterModal = true;
|
||||
}
|
||||
|
||||
public void CloseCharacterModals()
|
||||
{
|
||||
m_State.ShowCreateCharacterModal = false;
|
||||
m_State.ShowEditCharacterModal = false;
|
||||
m_State.CanEditCharacterOwner = false;
|
||||
m_State.EditingCharacterId = null;
|
||||
}
|
||||
|
||||
public async Task OnCharacterCreatedAsync(Guid? campaignId)
|
||||
{
|
||||
CloseCharacterModals();
|
||||
await m_ReloadCampaignsAsync(campaignId);
|
||||
await m_ReloadCharacterCampaignOptionsAsync();
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_Feedback.SetStatus("Character created.", false);
|
||||
}
|
||||
|
||||
public async Task OnCharacterUpdatedAsync(Guid? campaignId)
|
||||
{
|
||||
CloseCharacterModals();
|
||||
await m_ReloadCampaignsAsync(campaignId);
|
||||
await m_ReloadCharacterCampaignOptionsAsync();
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_Feedback.SetStatus(campaignId.HasValue ? "Character updated." : "Character unlinked from campaign.", false);
|
||||
}
|
||||
|
||||
public async Task DeleteSelectedCampaignAsync()
|
||||
{
|
||||
if (m_State.SelectedCampaign is null || m_State.IsMutating || !m_State.CanDeleteSelectedCampaign)
|
||||
return;
|
||||
|
||||
var confirmed = await m_JS.InvokeAsync<bool>("confirm", $"Delete campaign '{m_State.SelectedCampaign.Name}'?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
m_State.IsMutating = true;
|
||||
try
|
||||
{
|
||||
_ = await m_ApiClient.RequestAsync<bool>("DELETE", $"/api/campaigns/{m_State.SelectedCampaign.Id}");
|
||||
await m_ReloadCampaignsAsync(null);
|
||||
await m_ReloadCharacterCampaignOptionsAsync();
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_Feedback.SetStatus("Campaign deleted.", false);
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
m_Feedback.SetStatus(ex.Message, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_State.IsMutating = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteCharacterAsync(CharacterSummary character)
|
||||
{
|
||||
if (m_State.IsMutating || !CanDeleteCharacter(character))
|
||||
return;
|
||||
|
||||
var confirmed = await m_JS.InvokeAsync<bool>("confirm", $"Delete character '{character.Name}'?");
|
||||
if (!confirmed)
|
||||
return;
|
||||
|
||||
m_State.IsMutating = true;
|
||||
try
|
||||
{
|
||||
_ = await m_ApiClient.RequestAsync<bool>("DELETE", $"/api/characters/{character.Id}");
|
||||
await m_ReloadCampaignsAsync(m_State.SelectedCampaignId);
|
||||
await m_ReloadCharacterCampaignOptionsAsync();
|
||||
await m_RefreshCampaignScopeAsync();
|
||||
await m_SyncStateEventsAsync();
|
||||
m_Feedback.SetStatus("Character deleted.", false);
|
||||
}
|
||||
catch (ApiRequestException ex)
|
||||
{
|
||||
m_Feedback.SetStatus(ex.Message, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
m_State.IsMutating = false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanEditCharacter(CharacterSummary character)
|
||||
{
|
||||
return m_State.User is not null && (character.OwnerUserId == m_State.User.Id || m_State.IsCurrentUserGm || m_State.IsCurrentUserAdmin);
|
||||
}
|
||||
|
||||
public bool CanDeleteCharacter(CharacterSummary character)
|
||||
{
|
||||
return m_State.User is not null && (character.OwnerUserId == m_State.User.Id || m_State.IsCurrentUserAdmin);
|
||||
}
|
||||
|
||||
private readonly RpgRollerApiClient m_ApiClient;
|
||||
private readonly WorkspaceFeedbackService m_Feedback;
|
||||
private readonly IJSRuntime m_JS;
|
||||
private readonly Func<Task> m_LoadKnownUsernamesAsync;
|
||||
private readonly Func<Task> m_ReloadCharacterCampaignOptionsAsync;
|
||||
private readonly Func<Guid?, Task> m_ReloadCampaignsAsync;
|
||||
private readonly Func<Task> m_RefreshCampaignScopeAsync;
|
||||
private readonly WorkspaceState m_State;
|
||||
private readonly Func<Task> m_SyncStateEventsAsync;
|
||||
|
||||
private const string CampaignSessionKey = "campaign";
|
||||
}
|
||||
Reference in New Issue
Block a user