Allow UI to delete sessions

This commit is contained in:
2024-09-07 22:26:38 -05:00
parent 0eb75994c9
commit 6b5bb96de7
11 changed files with 162 additions and 21 deletions

View File

@@ -16,9 +16,7 @@ namespace Shogi.Api.Controllers;
[Route("[controller]")] [Route("[controller]")]
public class SessionsController( public class SessionsController(
SessionRepository sessionRepository, SessionRepository sessionRepository,
ShogiApplication application, ShogiApplication application) : ControllerBase
SignInManager<ShogiUser> signInManager,
UserManager<ShogiUser> userManager) : ControllerBase
{ {
[HttpPost] [HttpPost]

View File

@@ -10,31 +10,22 @@
<row class="header"> <row class="header">
<span>Creator</span> <span>Creator</span>
<span>Seats</span> <span>Seats</span>
<span></span>
</row> </row>
<hr /> <hr />
<AuthorizeView> <AuthorizeView>
@foreach (var session in allSessions) @foreach (var session in allSessions)
{ {
<row> <row>
<div> <GameBrowserEntry Session="session" OnSessionDeleted="FetchSessions" />
<a href="play/@session.SessionId">@session.Player1</a> </row>
</div>
@if (string.IsNullOrEmpty(session.Player2))
{
<span>1 / 2</span>
}
else
{
<span>Full</span>
}
</row>
} }
</AuthorizeView> </AuthorizeView>
</div> </div>
@if (allSessions.Length == 0) @if (allSessions.Length == 0)
{ {
<p>There are no games being played.</p> <p>There are no games being played.</p>
} }
</section> </section>

View File

@@ -1,5 +1,18 @@
row { .GameBrowser {
display: grid;
grid-template-columns: 18rem 5rem;
padding-left: 5px; /* Matches box shadow on hover */
} }
.GameBrowser row {
display: block;
width: max-content;
}
.GameBrowser row.header {
display: grid;
grid-template-columns: 18rem 5rem 5rem;
gap: 1rem;
margin-bottom: 0 !important;
}
.GameBrowser row:not(:last-of-type) {
margin-bottom: 1rem;
}

View File

@@ -0,0 +1,75 @@
@using Shogi.Contracts.Types
@inject ShogiApi Api
<gameBrowserEntry>
<AuthorizeView>
@if (showDeletePrompt)
{
<modal class="PrimaryTheme ThemeVariant--Contrast">
<div style="display: flex; gap: 1rem; justify-content: flex-end;">
@if (showDeleteError)
{
<p style="color: darkred;">An error occurred.</p>
<div style="flex: 1;" />
<button @onclick="HideModal">Cancel</button>
}
else
{
<p>Do you wish to delete this session?</p>
<div style="flex: 1;" />
<button @onclick="HideModal">No</button>
<button @onclick="DeleteSession">Yes</button>
}
</div>
</modal>
}
<div>
<a href="play/@Session.SessionId">@Session.Player1</a>
</div>
@if (string.IsNullOrEmpty(Session.Player2))
{
<span>1 / 2</span>
}
else
{
<span>Full</span>
}
@if (context.User.Identity?.Name == Session.Player1)
{
<IconButton OnClick="() => showDeletePrompt = true">
<TrashCanIcon />
</IconButton>
}
</AuthorizeView>
</gameBrowserEntry>
@code {
[Parameter][EditorRequired] public SessionMetadata Session { get; set; } = default!;
[Parameter][EditorRequired] public EventCallback OnSessionDeleted { get; set; }
private bool showDeletePrompt = false;
private bool showDeleteError = false;
void HideModal()
{
showDeletePrompt = showDeleteError = false;
}
async Task DeleteSession()
{
var response = await Api.DeleteSession(Session.SessionId);
if (response.IsSuccessStatusCode)
{
showDeletePrompt = false;
showDeleteError = false;
await OnSessionDeleted.InvokeAsync();
}
else
{
showDeletePrompt = true;
showDeleteError = true;
}
}
}

View File

@@ -0,0 +1,17 @@
gameBrowserEntry {
position: relative;
display: grid;
grid-template-columns: 18rem 5rem 5rem;
padding-left: 5px; /* Matches box shadow on hover */
gap: 1rem;
place-items: center start;
}
modal {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}

View File

@@ -0,0 +1,12 @@
<button @onclick="OnClick" style="@style">
@ChildContent
</button>
@code {
[Parameter][EditorRequired] public RenderFragment ChildContent { get; set; } = default!;
[Parameter][EditorRequired] public EventCallback OnClick { get; set; }
[Parameter] public string CssWidth { get; set; } = "32px";
[Parameter] public string CssHeight { get; set; } = "32px";
private string style => $"width: {CssWidth}; height: {CssHeight};";
}

View File

@@ -0,0 +1,6 @@
button {
padding: 0.2rem;
background: none;
border: 1px solid #444;
display: grid;
}

View File

@@ -0,0 +1,12 @@
<svg viewBox="0 0 32 32"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="trash">
<path clip-rule="evenodd" d="M29.98,6.819c-0.096-1.57-1.387-2.816-2.98-2.816h-3v-1V3.001 c0-1.657-1.344-3-3-3H11c-1.657,0-3,1.343-3,3v0.001v1H5c-1.595,0-2.885,1.246-2.981,2.816H2v1.183v1c0,1.104,0.896,2,2,2l0,0v17 c0,2.209,1.791,4,4,4h16c2.209,0,4-1.791,4-4v-17l0,0c1.104,0,2-0.896,2-2v-1V6.819H29.98z M10,3.002c0-0.553,0.447-1,1-1h10 c0.553,0,1,0.447,1,1v1H10V3.002z M26,28.002c0,1.102-0.898,2-2,2H8c-1.103,0-2-0.898-2-2v-17h20V28.002z M28,8.001v1H4v-1V7.002 c0-0.553,0.447-1,1-1h22c0.553,0,1,0.447,1,1V8.001z" fill="#333333" fill-rule="evenodd" /><path clip-rule="evenodd" d="M9,28.006h2c0.553,0,1-0.447,1-1v-13c0-0.553-0.447-1-1-1H9 c-0.553,0-1,0.447-1,1v13C8,27.559,8.447,28.006,9,28.006z M9,14.005h2v13H9V14.005z" fill="#333333" fill-rule="evenodd" /><path clip-rule="evenodd" d="M15,28.006h2c0.553,0,1-0.447,1-1v-13c0-0.553-0.447-1-1-1h-2 c-0.553,0-1,0.447-1,1v13C14,27.559,14.447,28.006,15,28.006z M15,14.005h2v13h-2V14.005z" fill="#333333" fill-rule="evenodd" /><path clip-rule="evenodd" d="M21,28.006h2c0.553,0,1-0.447,1-1v-13c0-0.553-0.447-1-1-1h-2 c-0.553,0-1,0.447-1,1v13C20,27.559,20.447,28.006,21,28.006z M21,14.005h2v13h-2V14.005z" fill="#333333" fill-rule="evenodd" />
</g>
</svg>
@code {
}

View File

@@ -70,5 +70,10 @@ public class ShogiApi(HttpClient httpClient)
return httpClient.PatchAsync(Relative($"Sessions/{name}/Join"), null); return httpClient.PatchAsync(Relative($"Sessions/{name}/Join"), null);
} }
public Task<HttpResponseMessage> DeleteSession(Guid sessionId)
{
return httpClient.DeleteAsync(Relative($"Sessions/{sessionId}"));
}
private static Uri Relative(string path) => new(path, UriKind.Relative); private static Uri Relative(string path) => new(path, UriKind.Relative);
} }

View File

@@ -15,11 +15,13 @@
<ItemGroup> <ItemGroup>
<None Remove="Pages\Home\VisualAids\PromotedPieceVisualAid.razor.css" /> <None Remove="Pages\Home\VisualAids\PromotedPieceVisualAid.razor.css" />
<None Remove="Pages\Play\GameBrowserEntry.razor.css" />
<None Remove="Pages\SearchPage.razor.css" /> <None Remove="Pages\SearchPage.razor.css" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Pages\Home\VisualAids\PromotedPieceVisualAid.razor.css" /> <Content Include="Pages\Home\VisualAids\PromotedPieceVisualAid.razor.css" />
<Content Include="Pages\Play\GameBrowserEntry.razor.css" />
<Content Include="Pages\SearchPage.razor.css" /> <Content Include="Pages\SearchPage.razor.css" />
</ItemGroup> </ItemGroup>

View File

@@ -1,5 +1,6 @@
.PrimaryTheme { .PrimaryTheme {
--backgroundColor: #444444; --backgroundColor: #444444;
--middlegroundColor: #D1D1D1;
--foregroundColor: #eaeaea; --foregroundColor: #eaeaea;
--hrefColor: #99c3ff; --hrefColor: #99c3ff;
--uniformBottomMargin: 0.5rem; --uniformBottomMargin: 0.5rem;
@@ -29,6 +30,14 @@
font-size: 85%; font-size: 85%;
} }
.PrimaryTheme button:hover {
box-shadow: 0px 0px 1px 1px var(--middlegroundColor)
}
.PrimaryTheme button:active {
box-shadow: 0px 0px 1px 1px var(--middlegroundColor), 0px 1px 1px 3px var(--middlegroundColor);
}
.PrimaryTheme button.href { .PrimaryTheme button.href {
border: 0; border: 0;
background: unset; background: unset;
@@ -64,5 +73,6 @@
.PrimaryTheme .ThemeVariant--Contrast { .PrimaryTheme .ThemeVariant--Contrast {
--backgroundColor: #eaeaea; --backgroundColor: #eaeaea;
--foregroundColor: #444444; --foregroundColor: #444444;
--middlegroundColor: #5e5e5e;
--hrefColor: #0065be; --hrefColor: #0065be;
} }