Add page for browsing levels

This commit is contained in:
jvyden 2021-11-28 23:35:40 -05:00
commit 3d39bfedb6
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
10 changed files with 275 additions and 36 deletions

View file

@ -59,19 +59,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
QueuedLevel? queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (queuedLevel != null) return this.Ok();
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
this.database.QueuedLevels.Add
(
new QueuedLevel
{
SlotId = id,
UserId = user.UserId,
}
);
await this.database.SaveChangesAsync();
await this.database.QueueLevel(user, slot);
return this.Ok();
}
@ -82,10 +73,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
QueuedLevel? queuedLevel = await this.database.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (queuedLevel != null) this.database.QueuedLevels.Remove(queuedLevel);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
await this.database.SaveChangesAsync();
await this.database.UnqueueLevel(user, slot);
return this.Ok();
}
@ -140,19 +131,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
HeartedLevel? heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (heartedLevel != null) return this.Ok();
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
this.database.HeartedLevels.Add
(
new HeartedLevel
{
SlotId = id,
UserId = user.UserId,
}
);
await this.database.SaveChangesAsync();
await this.database.HeartLevel(user, slot);
return this.Ok();
}
@ -163,10 +145,10 @@ namespace LBPUnion.ProjectLighthouse.Controllers
User? user = await this.database.UserFromGameRequest(this.Request);
if (user == null) return this.StatusCode(403, "");
HeartedLevel? heartedLevel = await this.database.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == id);
if (heartedLevel != null) this.database.HeartedLevels.Remove(heartedLevel);
Slot? slot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (slot == null) return this.NotFound();
await this.database.SaveChangesAsync();
await this.database.UnheartLevel(user, slot);
return this.Ok();
}

View file

@ -0,0 +1,77 @@
#nullable enable
using System.Threading.Tasks;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Levels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Controllers.Website
{
[ApiController]
[Route("slot/{id:int}")]
public class SlotPageController : ControllerBase
{
private readonly Database database;
public SlotPageController(Database database)
{
this.database = database;
}
[HttpGet("heart")]
public async Task<IActionResult> HeartLevel([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? heartedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (heartedSlot == null) return this.NotFound();
await this.database.HeartLevel(user, heartedSlot);
return this.Redirect("~/slot/" + id);
}
[HttpGet("unheart")]
public async Task<IActionResult> UnheartLevel([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? heartedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (heartedSlot == null) return this.NotFound();
await this.database.UnheartLevel(user, heartedSlot);
return this.Redirect("~/slot/" + id);
}
[HttpGet("queue")]
public async Task<IActionResult> QueueLevel([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? queuedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (queuedSlot == null) return this.NotFound();
await this.database.QueueLevel(user, queuedSlot);
return this.Redirect("~/slot/" + id);
}
[HttpGet("unqueue")]
public async Task<IActionResult> UnqueueLevel([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
Slot? queuedSlot = await this.database.Slots.FirstOrDefaultAsync(s => s.SlotId == id);
if (queuedSlot == null) return this.NotFound();
await this.database.UnqueueLevel(user, queuedSlot);
return this.Redirect("~/slot/" + id);
}
}
}

View file

@ -116,6 +116,56 @@ namespace LBPUnion.ProjectLighthouse
await this.SaveChangesAsync();
}
public async Task HeartLevel(User user, Slot heartedSlot)
{
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == heartedSlot.SlotId);
if (heartedLevel != null) return;
this.HeartedLevels.Add
(
new HeartedLevel
{
SlotId = heartedSlot.SlotId,
UserId = user.UserId,
}
);
await this.SaveChangesAsync();
}
public async Task UnheartLevel(User user, Slot heartedSlot)
{
HeartedLevel? heartedLevel = await this.HeartedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == heartedSlot.SlotId);
if (heartedLevel != null) this.HeartedLevels.Remove(heartedLevel);
await this.SaveChangesAsync();
}
public async Task QueueLevel(User user, Slot queuedSlot)
{
QueuedLevel? queuedLevel = await this.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == queuedSlot.SlotId);
if (queuedLevel != null) return;
this.QueuedLevels.Add
(
new QueuedLevel
{
SlotId = queuedSlot.SlotId,
UserId = user.UserId,
}
);
await this.SaveChangesAsync();
}
public async Task UnqueueLevel(User user, Slot queuedSlot)
{
QueuedLevel? queuedLevel = await this.QueuedLevels.FirstOrDefaultAsync(q => q.UserId == user.UserId && q.SlotId == queuedSlot.SlotId);
if (queuedLevel != null) this.QueuedLevels.Remove(queuedLevel);
await this.SaveChangesAsync();
}
#endregion
#region Game Token Shenanigans

View file

@ -29,6 +29,7 @@ namespace LBPUnion.ProjectLighthouse.Pages.Layouts
{
new PageNavigationItem("Home", "/", "home"),
new PageNavigationItem("Photos", "/photos/0", "camera"),
new PageNavigationItem("Levels", "/slots/0", "certificate"),
};
public readonly List<PageNavigationItem> NavigationItemsRight = new()

View file

@ -5,6 +5,7 @@ using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Pages.Layouts;
using LBPUnion.ProjectLighthouse.Types;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -23,7 +24,6 @@ namespace LBPUnion.ProjectLighthouse.Pages
public async Task<IActionResult> OnGet([FromRoute] int pageNumber)
{
const int pageSize = 20;
this.PhotoCount = await StatisticsHelper.PhotoCount();
this.PageNumber = pageNumber;
@ -31,8 +31,8 @@ namespace LBPUnion.ProjectLighthouse.Pages
this.Photos = await this.Database.Photos.Include
(p => p.Creator)
.OrderByDescending(p => p.Timestamp)
.Skip(pageNumber * pageSize)
.Take(pageSize)
.Skip(pageNumber * ServerStatics.PageSize)
.Take(ServerStatics.PageSize)
.ToListAsync();
return this.Page();

View file

@ -0,0 +1,86 @@
@page "/slots/{pageNumber:int}"
@using LBPUnion.ProjectLighthouse.Types
@using LBPUnion.ProjectLighthouse.Types.Levels
@using Microsoft.EntityFrameworkCore
@model LBPUnion.ProjectLighthouse.Pages.SlotsPage
@{
Layout = "Layouts/BaseLayout";
}
<h1>Levels</h1>
<p>There are @Model.SlotCount total levels!</p>
@foreach (Slot slot in Model.Slots)
{
string slotName = string.IsNullOrEmpty(slot.Name) ? "Unnamed Level" : slot.Name;
bool isQueued = false;
bool isHearted = false;
if (Model.User != null)
{
isQueued = await Model.Database.QueuedLevels.FirstOrDefaultAsync(h => h.SlotId == slot.SlotId && h.UserId == Model.User.UserId) != null;
isHearted = await Model.Database.HeartedLevels.FirstOrDefaultAsync(h => h.SlotId == slot.SlotId && h.UserId == Model.User.UserId) != null;
}
<div class="ui segment">
<div class="ui grid">
<div class="eight wide column">
<h2 style="margin-bottom: 2px;">@slotName</h2>
<div class="statsUnderTitle" style="margin-bottom: 10px;">
<i class="pink heart icon" title="Hearts"></i> <span>@slot.Hearts</span>
<i class="blue play icon" title="Plays"></i> <span>@slot.Plays</span>
<i class="green thumbs up icon" title="Yays"></i> <span>@slot.Thumbsup</span>
<i class="red thumbs down icon" title="Boos"></i> <span>@slot.Thumbsdown</span>
@if (slot.GameVersion == GameVersion.LittleBigPlanet1)
{
<i class="yellow star icon" title="LBP1 Stars"></i>
<span>@slot.RatingLBP1</span>
}
</div>
<p>
<i>Created by <a href="/user/@slot.Creator?.UserId">@slot.Creator?.Username</a></i>
</p>
</div>
<div class="eight wide right aligned column">
@if (Model.User != null)
{
if (isHearted)
{
<a class="ui pink tiny button" href="/slot/@slot.SlotId/unheart" title="Unheart">
<i class="broken heart icon" style="margin: 0"></i>
</a>
}
else
{
<a class="ui pink tiny button" href="/slot/@slot.SlotId/heart" title="Heart">
<i class="heart icon" style="margin: 0"></i>
</a>
}
if (isQueued)
{
<a class="ui yellow tiny button" href="/slot/@slot.SlotId/unqueue" title="Unqueue">
<i class="bell slash icon" style="margin: 0"></i>
</a>
}
else
{
<a class="ui yellow tiny button" href="/slot/@slot.SlotId/queue" title="Queue">
<i class="bell icon" style="margin: 0"></i>
</a>
}
}
</div>
</div>
</div>
}
@if (Model.PageNumber != 0)
{
<a href="/slots/@(Model.PageNumber - 1)">Previous Page</a>
}
<a href="/slots/@(Model.PageNumber + 1)">Next Page</a>

View file

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using JetBrains.Annotations;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.Pages.Layouts;
using LBPUnion.ProjectLighthouse.Types.Levels;
using LBPUnion.ProjectLighthouse.Types.Settings;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Pages
{
public class SlotsPage : BaseLayout
{
public SlotsPage([NotNull] Database database) : base(database)
{}
public int SlotCount;
public List<Slot> Slots;
public int PageNumber;
public async Task<IActionResult> OnGet([FromRoute] int pageNumber)
{
this.SlotCount = await StatisticsHelper.SlotCount();
this.PageNumber = pageNumber;
this.Slots = await this.Database.Slots.Include
(p => p.Creator)
.OrderByDescending(p => p.FirstUploaded)
.Skip(pageNumber * ServerStatics.PageSize)
.Take(ServerStatics.PageSize)
.ToListAsync();
return this.Page();
}
}
}

View file

@ -14,7 +14,7 @@
<p>
<i>@Model.ProfileUser.Status</i>
</p>
<div class="userStats">
<div class="statsUnderTitle">
<i class="pink heart icon" title="Hearts"></i> <span>@Model.ProfileUser.Hearts</span>
<i class="blue comment icon" title="Comments"></i> <span>@Model.ProfileUser.Comments</span>
<i class="green upload icon" title="Uploaded Levels"></i><span>@Model.ProfileUser.UsedSlots / @ServerSettings.Instance.EntitledSlots</span>

View file

@ -8,11 +8,11 @@ div.main {
flex: 1;
}
div.userStats > i {
div.statsUnderTitle > i {
margin-right: 2px;
}
div.userStats > span {
div.statsUnderTitle > span {
margin-right: 5px;
}

View file

@ -25,5 +25,7 @@ namespace LBPUnion.ProjectLighthouse.Types.Settings
}
public static bool IsUnitTesting => AppDomain.CurrentDomain.GetAssemblies().Any(assembly => assembly.FullName.StartsWith("xunit"));
public const int PageSize = 20;
}
}