Several improvements to Grief Reports (#263)

* Redesign reports page, add ability to dismiss reports

* Delete report's attached jpeg when dismissing report
This commit is contained in:
jvyden 2022-04-04 16:05:18 -04:00 committed by GitHub
commit 0298d5e69b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 13 deletions

View file

@ -16,7 +16,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0"/> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0"/>
<PackageReference Include="Selenium.WebDriver" Version="4.1.0"/> <PackageReference Include="Selenium.WebDriver" Version="4.1.0"/>
<PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="98.0.4758.8000"/> <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="100.0.4896.6000"/>
<PackageReference Include="xunit" Version="2.4.1"/> <PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View file

@ -52,4 +52,29 @@ public class AdminReportController : ControllerBase
return this.Redirect("~/admin/reports/0"); return this.Redirect("~/admin/reports/0");
} }
[HttpGet("dismiss")]
public async Task<IActionResult> DismissReport([FromRoute] int id)
{
User? user = this.database.UserFromWebRequest(this.Request);
if (user == null || !user.IsAdmin) return this.StatusCode(403, "");
GriefReport? report = await this.database.Reports.FirstOrDefaultAsync(r => r.ReportId == id);
if (report == null) return this.NotFound();
if (System.IO.File.Exists(Path.Combine("png", $"{report.JpegHash}.png")))
{
System.IO.File.Delete(Path.Combine("png", $"{report.JpegHash}.png"));
}
if (System.IO.File.Exists(Path.Combine("r", report.JpegHash)))
{
System.IO.File.Delete(Path.Combine("r", report.JpegHash));
}
this.database.Reports.Remove(report);
await this.database.SaveChangesAsync();
return this.Redirect("~/admin/reports/0");
}
} }

View file

@ -15,7 +15,9 @@
<i class="search icon"></i> <i class="search icon"></i>
</div> </div>
</form> </form>
<div class="ui divider"></div> <div class="ui divider"></div>
<script> <script>
let subjects = []; let subjects = [];
let bounds = []; let bounds = [];
@ -23,6 +25,7 @@
let ctx = []; let ctx = [];
let images = []; let images = [];
</script> </script>
@foreach (GriefReport report in Model.Reports) @foreach (GriefReport report in Model.Reports)
{ {
<div class="ui segment"> <div class="ui segment">
@ -30,9 +33,16 @@
<canvas class="hide-subjects" id="canvas-subjects-@report.ReportId" width="1920" height="1080" <canvas class="hide-subjects" id="canvas-subjects-@report.ReportId" width="1920" height="1080"
style="position: absolute; transform: rotate(180deg)"> style="position: absolute; transform: rotate(180deg)">
</canvas> </canvas>
<img id="game-image-@report.ReportId" src="/gameAssets/@report.JpegHash" alt="Grief report picture" style="width: 100%; height: auto; border-radius: .28571429rem;"> <img class="hover-region" id="game-image-@report.ReportId" src="/gameAssets/@report.JpegHash" alt="Grief report picture" style="width: 100%; height: auto; border-radius: .28571429rem;">
</div> </div>
<p><i>Report submitted by <b><a href="/user/@report.ReportingPlayerId">@report.ReportingPlayer.Username</a></b></i></p> <p>
<i>
Report submitted by
<b>
<a href="/user/@report.ReportingPlayerId">@report.ReportingPlayer.Username</a>
</b>
</i>
</p>
<b class="hover-players" id="hover-subjects-2-@report.ReportId">Report contains @report.XmlPlayers.Length @(report.XmlPlayers.Length == 1 ? "player" : "players")</b> <b class="hover-players" id="hover-subjects-2-@report.ReportId">Report contains @report.XmlPlayers.Length @(report.XmlPlayers.Length == 1 ? "player" : "players")</b>
@foreach (ReportPlayer player in report.XmlPlayers) @foreach (ReportPlayer player in report.XmlPlayers)
{ {
@ -40,14 +50,32 @@
<a href="/">@player.Name</a> <a href="/">@player.Name</a>
</div> </div>
} }
<div><b>Report time: </b>@(DateTimeOffset.FromUnixTimeMilliseconds(report.Timestamp).ToString("R"))</div>
<div><b>Report reason: </b>@report.Type</div> <br>
<div><b>Level ID:</b> @report.LevelId</div> <div>
<div><b>Level type:</b> @report.LevelType</div> <b>Report time: </b>@(DateTimeOffset.FromUnixTimeMilliseconds(report.Timestamp).ToString("R"))
<div><b>Level owner:</b> @report.LevelOwner</div> </div>
<div id="hover-bounds-@report.ReportId" class="hover-region"><b>Hover to see reported region</b></div> <div>
<a class="ui red tiny button" href="/admin/report/@report.ReportId/remove" title="Delete"> <b>Report reason: </b>@report.Type
<i class="trash icon" style="margin: 0"></i> </div>
<div>
<b>Level ID:</b> @report.LevelId
</div>
<div>
<b>Level type:</b> @report.LevelType
</div>
<div>
<b>Level owner:</b> @report.LevelOwner
</div>
<br>
<a class="ui green small button" href="/admin/report/@report.ReportId/dismiss">
<i class="checkmark icon"></i>
<span>Dismiss</span>
</a>
<a class="ui red small button" href="/admin/report/@report.ReportId/remove">
<i class="trash icon"></i>
<span>Remove all related assets</span>
</a> </a>
</div> </div>
<script> <script>
@ -60,6 +88,7 @@
ctx[@report.ReportId] = canvases[@report.ReportId].getContext('2d'); ctx[@report.ReportId] = canvases[@report.ReportId].getContext('2d');
</script> </script>
} }
<script> <script>
function getReportId(name){ function getReportId(name){
let split = name.split("-"); let split = name.split("-");
@ -71,16 +100,26 @@
document.querySelectorAll(".hover-players").forEach(item => { document.querySelectorAll(".hover-players").forEach(item => {
item.addEventListener('mouseenter', function () { item.addEventListener('mouseenter', function () {
let reportId = getReportId(item.id); let reportId = getReportId(item.id);
const canvas = canvases[reportId];
displayType = 1; displayType = 1;
canvases[reportId].className = "photo-subjects";
canvas.className = "photo-subjects";
redraw(reportId); redraw(reportId);
}); });
}); });
document.querySelectorAll(".hover-region").forEach(item => { document.querySelectorAll(".hover-region").forEach(item => {
item.addEventListener('mouseenter', function () { item.addEventListener('mouseenter', function () {
let reportId = getReportId(item.id); let reportId = getReportId(item.id);
const canvas = canvases[reportId];
const image = document.getElementById("game-image-" + reportId.toString());
displayType = 0; displayType = 0;
canvases[reportId].className = "photo-subjects";
canvas.className = "photo-subjects";
canvas.width = image.offsetWidth;
canvas.height = image.clientHeight; // space for names to hang off
redraw(reportId); redraw(reportId);
}); });
}); });
@ -90,6 +129,7 @@
}); });
}); });
}, false); }, false);
function redraw(reportId){ function redraw(reportId){
let context = ctx[reportId]; let context = ctx[reportId];
let canvas = canvases[reportId]; let canvas = canvases[reportId];