Properly organize mod panel related pages

This commit is contained in:
jvyden 2022-08-14 17:02:18 -04:00
commit 5b1342c29d
No known key found for this signature in database
GPG key ID: 18BCF2BE0262B278
10 changed files with 10 additions and 13 deletions

View file

@ -0,0 +1,24 @@
@page "/moderation/cases/{pageNumber:int}"
@using LBPUnion.ProjectLighthouse.Administration
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.CasePage
@{
Layout = "Layouts/BaseLayout";
Model.Title = "Cases";
}
<p>There are @Model.CaseCount total cases, @Model.DismissedCaseCount of which have been dismissed.</p>
<form action="/moderation/cases/0">
<div class="ui icon input">
<input type="text" autocomplete="off" name="name" placeholder="Search cases..." value="@Model.SearchValue">
<i class="search icon"></i>
</div>
</form>
<div class="ui divider"></div>
@foreach (ModerationCase @case in Model.Cases)
{
@(await Html.PartialAsync("Partials/ModerationCasePartial", @case))
}

View file

@ -0,0 +1,47 @@
using LBPUnion.ProjectLighthouse.Administration;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation;
public class CasePage : BaseLayout
{
public CasePage(Database database) : base(database)
{}
public List<ModerationCase> Cases = new();
public int CaseCount;
public int DismissedCaseCount;
public int PageAmount;
public int PageNumber;
public string SearchValue = "";
public async Task<IActionResult> OnGet([FromRoute] int pageNumber, [FromQuery] string? name)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.NotFound();
if (!user.IsModerator) return this.NotFound();
if (string.IsNullOrWhiteSpace(name)) name = "";
this.SearchValue = name.Replace(" ", string.Empty);
this.Cases = await this.Database.Cases
.Include(c => c.Creator)
.Include(c => c.Dismisser)
.OrderByDescending(c => c.CaseId)
.ToListAsync();
this.CaseCount = await this.Database.Cases.CountAsync(c => c.Reason.Contains(this.SearchValue));
this.DismissedCaseCount = await this.Database.Cases.CountAsync(c => c.Reason.Contains(this.SearchValue) && c.DismissedAt != null);
this.PageNumber = pageNumber;
this.PageAmount = Math.Max(1, (int)Math.Ceiling((double)this.CaseCount / ServerStatics.PageSize));
return this.Page();
}
}

View file

@ -0,0 +1,53 @@
@page "/moderation"
@using System.Diagnostics
@using LBPUnion.ProjectLighthouse.Administration
@using LBPUnion.ProjectLighthouse.Extensions
@using LBPUnion.ProjectLighthouse.Localization.StringLists
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.ModPanelPage
@{
Layout = "Layouts/BaseLayout";
Model.Title = Model.Translate(ModPanelStrings.ModPanelTitle);
if (Model.User == null) throw new ArgumentNullException($"{nameof(Model)}.{nameof(User)}");
// Technically, this should never happen but I'm going to handle it anyways.
if (!Model.User.IsModerator)
{
if(Debugger.IsAttached) Debugger.Break();
throw new Exception("Tried to render mod panel with user whose not mod somehow???");
}
}
<p>@Model.Translate(ModPanelStrings.Greeting, Model.User.Username)</p>
@if (!this.Request.IsMobile())
{
<div class="ui grid">
@foreach (AdminPanelStatistic statistic in Model.Statistics)
{
@await Html.PartialAsync("Partials/AdminPanelStatisticPartial", statistic)
}
</div>
<br>
}
else
{
@foreach (AdminPanelStatistic statistic in Model.Statistics)
{
@await Html.PartialAsync("Partials/AdminPanelStatisticPartial", statistic)
<br>
}
}
<h2>Actions</h2>
<a href="/moderation/bannedUsers" class="ui red button">
<i class="users icon"></i>
<span>View banned users</span>
</a><br/><br/>
<a href="/moderation/hiddenSlots" class="ui yellow button">
<i class="certificate icon"></i>
<span>View hidden levels</span>
</a>

View file

@ -0,0 +1,37 @@
using LBPUnion.ProjectLighthouse.Administration;
using LBPUnion.ProjectLighthouse.Helpers;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation;
public class ModPanelPage : BaseLayout
{
public ModPanelPage(Database database) : base(database)
{}
public List<AdminPanelStatistic> Statistics = new();
public async Task<IActionResult> OnGet()
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
if (!user.IsModerator) return this.NotFound();
this.Statistics.Add(new AdminPanelStatistic(
statisticNamePlural: "Reports",
count: await StatisticsHelper.ReportCount(),
viewAllEndpoint: "/moderation/reports/0")
);
this.Statistics.Add(new AdminPanelStatistic(
statisticNamePlural: "Cases",
count: await StatisticsHelper.DismissedCaseCount(),
viewAllEndpoint: "/moderation/cases/0",
secondStatistic: await StatisticsHelper.CaseCount())
);
return this.Page();
}
}

View file

@ -0,0 +1,32 @@
@page "/moderation/newCase"
@using LBPUnion.ProjectLighthouse.Administration
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.NewCasePage
@{
Layout = "Layouts/BaseLayout";
Model.Title = $"New {Model.Type.ToString()} Case";
}
<form method="post">
@Html.AntiForgeryToken()
<input type="hidden" name="type" value="@((int)Model.Type)"/>
<input type="hidden" name="affectedId" value="@Model.AffectedId"/>
<div class="ui left labeled input">
<label for="reason" class="ui blue label">Reason: </label>
<input type="text" name="reason" id="reason"/>
</div><br/><br/>
<div class="ui left labeled input">
<label for="mod-notes" class="ui blue label">Mod Notes: </label>
<input type="text" name="modNotes" id="mod-notes"/>
</div><br/><br/>
<div class="ui left labeled input">
<label for="expires" class="ui blue label">Expires: </label>
<input type="datetime-local" name="expires" id="expires"/>
</div><br/><br/>
<br/><input type="submit" value="Create case" class="ui red button"/>
</form>

View file

@ -0,0 +1,61 @@
using LBPUnion.ProjectLighthouse.Administration;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation;
public class NewCasePage : BaseLayout
{
public NewCasePage(Database database) : base(database)
{}
public CaseType Type { get; set; }
public int AffectedId { get; set; }
public IActionResult OnGet([FromQuery] CaseType? type, [FromQuery] int? affectedId)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null || !user.IsModerator) return this.Redirect("/login");
if (type == null) return this.BadRequest();
if (affectedId == null) return this.BadRequest();
this.Type = (CaseType)type;
this.AffectedId = (int)affectedId;
return this.Page();
}
public async Task<IActionResult> OnPost(CaseType? type, string? reason, string? modNotes, DateTime expires, int? affectedId)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null || !user.IsModerator) return this.Redirect("/login");
if (type == null) return this.BadRequest();
if (affectedId == null) return this.BadRequest();
reason ??= string.Empty;
modNotes ??= string.Empty;
// this is fucking ugly
// if id is invalid then return bad request
if (!(await ((CaseType)type).IsIdValid((int)affectedId, this.Database))) return this.BadRequest();
ModerationCase @case = new()
{
Type = (CaseType)type,
Reason = reason,
ModeratorNotes = modNotes,
ExpiresAt = expires,
CreatedAt = DateTime.Now,
CreatorId = user.UserId,
AffectedId = (int)affectedId,
};
this.Database.Cases.Add(@case);
await this.Database.SaveChangesAsync();
return this.Redirect("/moderation/cases/0");
}
}

View file

@ -0,0 +1,18 @@
@page "/moderation/report/{reportId:int}"
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.ReportPage
@{
Layout = "Layouts/BaseLayout";
Model.Title = $"Report {Model.Report.ReportId}";
}
<script>
let subjects = [];
let bounds = [];
let canvases = [];
let ctx = [];
let images = [];
</script>
@await Html.PartialAsync("Partials/ReportPartial", Model.Report)
@await Html.PartialAsync("Partials/RenderReportBoundsPartial")

View file

@ -0,0 +1,41 @@
using System.Text.Json;
using LBPUnion.ProjectLighthouse.Administration.Reports;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation;
public class ReportPage : BaseLayout
{
public ReportPage(Database database) : base(database)
{}
public GriefReport Report = null!; // Report is not used if it's null in OnGet
public async Task<IActionResult> OnGet([FromRoute] int reportId)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
if (!user.IsAdmin) return this.NotFound();
GriefReport? report = await this.Database.Reports
.Include(r => r.ReportingPlayer)
.FirstOrDefaultAsync(r => r.ReportId == reportId);
if (report == null) return this.NotFound();
report.XmlPlayers = (ReportPlayer[])JsonSerializer.Deserialize(report.Players,
typeof(ReportPlayer[]))!;
report.XmlBounds = new Marqee
{
Rect = (Rectangle)JsonSerializer.Deserialize(report.Bounds,
typeof(Rectangle))!,
};
this.Report = report;
return this.Page();
}
}

View file

@ -0,0 +1,44 @@
@page "/moderation/reports/{pageNumber:int}"
@using LBPUnion.ProjectLighthouse.Administration.Reports
@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.ReportsPage
@{
Layout = "Layouts/BaseLayout";
Model.Title = "Reports";
}
<p>There are @Model.ReportCount total reports.</p>
<form action="/moderation/reports/0">
<div class="ui icon input">
<input type="text" autocomplete="off" name="name" placeholder="Search reports..." value="@Model.SearchValue">
<i class="search icon"></i>
</div>
</form>
<div class="ui divider"></div>
<script>
let subjects = [];
let bounds = [];
let canvases = [];
let ctx = [];
let images = [];
</script>
@foreach (GriefReport report in Model.Reports)
{
@await Html.PartialAsync("Partials/ReportPartial", report)
}
@await Html.PartialAsync("Partials/RenderReportBoundsPartial")
@if (Model.PageNumber != 0)
{
<a href="/moderation/reports/@(Model.PageNumber - 1)@(Model.SearchValue.Length == 0 ? "" : "?name=" + Model.SearchValue)">Previous Page</a>
}
@(Model.PageNumber + 1) / @(Model.PageAmount)
@if (Model.PageNumber < Model.PageAmount - 1)
{
<a href="/moderation/reports/@(Model.PageNumber + 1)@(Model.SearchValue.Length == 0 ? "" : "?name=" + Model.SearchValue)">Next Page</a>
}

View file

@ -0,0 +1,64 @@
#nullable enable
using System.Text.Json;
using LBPUnion.ProjectLighthouse.Administration.Reports;
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.PlayerData.Profiles;
using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation;
public class ReportsPage : BaseLayout
{
public int PageAmount;
public int PageNumber;
public int ReportCount;
public List<GriefReport> Reports = new();
public string SearchValue = "";
public ReportsPage(Database database) : base(database)
{}
public async Task<IActionResult> OnGet([FromRoute] int pageNumber, [FromQuery] string? name)
{
User? user = this.Database.UserFromWebRequest(this.Request);
if (user == null) return this.Redirect("~/login");
if (!user.IsModerator) return this.NotFound();
if (string.IsNullOrWhiteSpace(name)) name = "";
this.SearchValue = name.Replace(" ", string.Empty);
this.ReportCount = await this.Database.Reports.Include(r => r.ReportingPlayer).CountAsync(r => r.ReportingPlayer.Username.Contains(this.SearchValue));
this.PageNumber = pageNumber;
this.PageAmount = Math.Max(1, (int)Math.Ceiling((double)this.ReportCount / ServerStatics.PageSize));
if (this.PageNumber < 0 || this.PageNumber >= this.PageAmount)
return this.Redirect($"/moderation/reports/{Math.Clamp(this.PageNumber, 0, this.PageAmount - 1)}");
this.Reports = await this.Database.Reports.Include(r => r.ReportingPlayer)
.Where(r => r.ReportingPlayer.Username.Contains(this.SearchValue))
.OrderByDescending(r => r.Timestamp)
.Skip(pageNumber * ServerStatics.PageSize)
.Take(ServerStatics.PageSize)
.ToListAsync();
foreach (GriefReport r in this.Reports)
{
r.XmlPlayers = (ReportPlayer[])JsonSerializer.Deserialize(r.Players, typeof(ReportPlayer[]))!;
r.XmlBounds = new Marqee()
{
Rect = (Rectangle)JsonSerializer.Deserialize(r.Bounds, typeof(Rectangle))!,
};
}
return this.Page();
}
}