Files
RpgRoller/RpgRoller/Components/Pages/Workspace.razor

211 lines
9.5 KiB
Plaintext

@using RpgRoller.Components.Pages.HomeControls
<div class="@AppCssClass">
<p class="sr-only" aria-live="polite">@LiveAnnouncement</p>
@if (HasHealthIssue)
{
<section class="health-banner" role="alert">
<div>
<strong>API currently unavailable.</strong>
<p>@HealthIssueMessage</p>
</div>
<button type="button" @onclick="RetryAfterHealthIssueAsync">Retry</button>
</section>
}
<div class="workspace-shell">
<AppHeader
User="User"
ShowCampaign="true"
CampaignName="@SelectedCampaignName"
ShowConnectionState="true"
ConnectionStateLabel="@ConnectionStateLabel"
ConnectionStateCssClass="@ConnectionStateCssClass"
IsMenuOpen="IsScreenMenuOpen"
MenuButtonId="workspace-screen-menu-button"
MenuId="workspace-screen-menu"
MenuItems="HeaderMenuItems"
ToggleMenuRequested="ToggleScreenMenu"
LogoutRequested="LogoutAsync"/>
@if (IsPlayScreen)
{
<main class="play-screen @(MobilePanel == "log" ? "mobile-log" : "mobile-character")">
<CharacterPanel
IsCampaignDataLoading="IsCampaignDataLoading"
SelectedCampaign="PlaySelectedCampaign"
SelectedCharacterId="PlaySelectedCharacterId"
SelectedCharacter="PlaySelectedCharacter"
IsMutating="IsMutating"
SelectedCharacterSkills="PlaySelectedCharacterSkills"
SelectedCharacterSkillGroups="PlaySelectedCharacterSkillGroups"
SelectedCampaignRulesetId="@(PlaySelectedCampaign?.RulesetId ?? string.Empty)"
RollVisibility="RollVisibility"
RollVisibilityChanged="OnRollVisibilityChanged"
OwnerLabel="OwnerLabel"
SkillDefinitionLabel="SkillDefinitionLabel"
CanEditCharacter="CanEditCharacter"
CanEditSkill="CanEditSkill"
CharacterSelected="SelectCharacterAsync"
EditCharacterRequested="OpenEditCharacterModal"
SkillCreated="OnSkillCreatedAsync"
SkillUpdated="OnSkillUpdatedAsync"
SkillGroupCreated="OnSkillGroupCreatedAsync"
SkillGroupUpdated="OnSkillGroupUpdatedAsync"
SkillDeleted="OnSkillDeletedAsync"
SkillGroupDeleted="OnSkillGroupDeletedAsync"
ErrorOccurred="OnCharacterPanelErrorAsync"
RollRequested="RollSkillAsync"/>
<CampaignLogPanel
IsCampaignDataLoading="IsCampaignDataLoading"
CampaignLog="PlayVisibleCampaignLog"
ExpandedRollId="ExpandedCampaignLogRollId"
FreshRollId="FreshCampaignLogRollId"
ToggleRollDetailRequested="ToggleRollDetailAsync"
ResolveRollDetail="ResolveRollDetail"
IsRollDetailLoading="IsRollDetailLoading"
GetRollDetailError="GetRollDetailError"/>
</main>
<nav class="mobile-bottom-nav" aria-label="Play panel selector">
<button type="button" class="switch @(MobilePanel == "character" ? "active" : string.Empty)"
@onclick="SetMobilePanelCharacterAsync">Character
</button>
<button type="button" class="switch @(MobilePanel == "log" ? "active" : string.Empty)"
@onclick="SetMobilePanelLogAsync">Log
</button>
</nav>
}
else if (IsManagementScreen)
{
<CampaignManagementPanel
Campaigns="Campaigns"
SelectedCampaignId="SelectedCampaignId"
SelectedCampaign="SelectedCampaign"
Rulesets="Rulesets"
IsMutating="IsMutating"
OwnerLabel="OwnerLabel"
CanEditCharacter="CanEditCharacter"
CanDeleteCharacter="CanDeleteCharacter"
CanDeleteCampaign="CanDeleteSelectedCampaign"
CampaignSelectionChanged="OnCampaignSelectionChangedAsync"
CampaignCreated="OnCampaignCreatedAsync"
DeleteCampaignRequested="DeleteSelectedCampaignAsync"
CreateCharacterRequested="OpenCreateCharacterModal"
EditCharacterRequested="OpenEditCharacterModal"
DeleteCharacterRequested="DeleteCharacterAsync"/>
}
else if (IsAdminScreen)
{
<main class="management-screen">
@if (IsCurrentUserAdmin)
{
<section class="card">
<div class="section-head">
<h2>Database</h2>
</div>
<p class="muted">Download the current SQLite file for backup or offline inspection.</p>
<div class="management-actions">
<a class="action-link" href="@AdminDatabaseDownloadUrl" download>Download SQLite database</a>
</div>
</section>
}
<section class="card">
<div class="section-head">
<h2>User Management</h2>
</div>
@if (IsAdminDataLoading)
{
<p class="empty">Loading users...</p>
}
else if (!IsCurrentUserAdmin)
{
<p class="empty">Admin role is required to manage users.</p>
}
else if (AdminUsers.Count == 0)
{
<p class="empty">No users found.</p>
}
else
{
<ul class="management-list">
@foreach (var user in AdminUsers)
{
<li>
<div>
<strong>@user.Username</strong>
<p class="muted">@user.DisplayName</p>
<p class="muted">Roles: @(user.Roles.Count == 0 ? "none" : string.Join(", ", user.Roles))</p>
</div>
<div class="skill-chip-actions">
<button type="button"
class="chip-button"
disabled="@(IsMutating || user.Id == User?.Id)"
@onclick="() => ToggleAdminRoleAsync(user)">
<span aria-hidden="true" class="emoji">🛡️</span>
<span class="sr-only">Toggle admin role for @user.Username</span>
</button>
<button type="button"
class="chip-button"
disabled="@(IsMutating || user.Id == User?.Id)"
@onclick="() => DeleteUserAsync(user)">
<span aria-hidden="true" class="emoji">🗑️</span>
<span class="sr-only">Delete user @user.Username</span>
</button>
</div>
</li>
}
</ul>
}
</section>
</main>
}
</div>
@if (Toasts.Count > 0)
{
<div class="toast-stack" aria-live="polite" aria-atomic="false">
@foreach (var toast in Toasts)
{
<div class="toast @(toast.IsError ? "error" : "success")" role="status">
<p>@toast.Message</p>
</div>
}
</div>
}
</div>
<CharacterFormModal
Visible="ShowCreateCharacterModal"
Title="Create Character"
SubmitLabel="Create Character"
NameInputId="character-create-name"
CampaignInputId="character-create-campaign"
OwnerUsernameInputId="character-create-owner"
InitialModel="CreateCharacterInitialModel"
FormVersion="CreateCharacterFormVersion"
EditingCharacterId="null"
CampaignOptions="CharacterCampaignOptions"
IsMutating="IsMutating"
AllowOwnerEdit="false"
AvailableUsernames="KnownUsernames"
CharacterSaved="OnCharacterCreatedAsync"
CancelRequested="CloseCharacterModals"/>
<CharacterFormModal
Visible="ShowEditCharacterModal"
Title="Edit Character"
SubmitLabel="Save Character"
NameInputId="character-edit-name"
CampaignInputId="character-edit-campaign"
OwnerUsernameInputId="character-edit-owner"
InitialModel="EditCharacterInitialModel"
FormVersion="EditCharacterFormVersion"
EditingCharacterId="EditingCharacterId"
CampaignOptions="CharacterCampaignOptions"
IsMutating="IsMutating"
AllowOwnerEdit="CanEditCharacterOwner"
AvailableUsernames="KnownUsernames"
CharacterSaved="OnCharacterUpdatedAsync"
CancelRequested="CloseCharacterModals"/>