From 59225ec7029475ddb5399d1dbba3b7ff91bb5f84 Mon Sep 17 00:00:00 2001 From: Masterjun Date: Sun, 18 Aug 2024 19:13:13 +0200 Subject: [PATCH] Add various UI stuff (#1948) * make last post link cover the username as well, makes it easier to click and makes more sense in the context anyway * show submission votes in subs list and forum topics * add icon to claim button * only show "current" on wiki revisions that are actually current * show links to revision source on wiki page history * improve page history "from-to" colors, table colors were bad on dark mode * use button design for page footer * remove empty line for style * make the vote counts query robust against edited polls --- TASVideos.Common/VoteCounts.cs | 11 +++++++++ TASVideos/Extensions/EntityExtensions.cs | 21 ++++++++++++++--- TASVideos/Pages/Forum/Subforum/Index.cshtml | 4 ++-- .../Pages/Forum/Subforum/Index.cshtml.cs | 20 ++++++++++++++-- TASVideos/Pages/Forum/_Category.cshtml | 3 +-- TASVideos/Pages/Shared/_Layout.cshtml | 7 +++--- TASVideos/Pages/Shared/_VoteCounts.cshtml | 20 ++++++++++++++++ TASVideos/Pages/Submissions/Index.cshtml | 1 + TASVideos/Pages/Submissions/Index.cshtml.cs | 4 +++- TASVideos/Pages/Submissions/View.cshtml | 4 ++-- TASVideos/Pages/Wiki/PageHistory.cshtml | 23 ++++--------------- TASVideos/Pages/Wiki/ViewSource.cshtml | 4 ++-- TASVideos/wwwroot/js/wiki-page-history.js | 12 ++++------ 13 files changed, 90 insertions(+), 44 deletions(-) create mode 100644 TASVideos.Common/VoteCounts.cs create mode 100644 TASVideos/Pages/Shared/_VoteCounts.cshtml diff --git a/TASVideos.Common/VoteCounts.cs b/TASVideos.Common/VoteCounts.cs new file mode 100644 index 000000000..d79a501cf --- /dev/null +++ b/TASVideos.Common/VoteCounts.cs @@ -0,0 +1,11 @@ +namespace TASVideos.Common; + +public class VoteCounts +{ + public int VotesYes { get; init; } + public int VotesMeh { get; init; } + public int VotesNo { get; init; } + public bool UserVotedYes { get; init; } + public bool UserVotedMeh { get; init; } + public bool UserVotedNo { get; init; } +} diff --git a/TASVideos/Extensions/EntityExtensions.cs b/TASVideos/Extensions/EntityExtensions.cs index f1d2ebe52..a244e8d7d 100644 --- a/TASVideos/Extensions/EntityExtensions.cs +++ b/TASVideos/Extensions/EntityExtensions.cs @@ -1,4 +1,5 @@ -using TASVideos.Data.Entity.Awards; +using TASVideos.Common; +using TASVideos.Data.Entity.Awards; using TASVideos.Data.Entity.Forum; using TASVideos.Data.Entity.Game; using TASVideos.Pages.Forum.Posts; @@ -345,7 +346,7 @@ public static List WithAnyEntry(this IEnumerable return [.. UiDefaults.AnyEntry, .. items]; } - public static IQueryable ToSubListEntry(this IQueryable query) + public static IQueryable ToSubListEntry(this IQueryable query, int? userIdForVotes = null) { return query .Select(s => new Pages.Submissions.IndexModel.SubmissionEntry @@ -362,7 +363,21 @@ public static List WithAnyEntry(this IEnumerable Status = s.Status, Judge = s.Judge != null ? s.Judge.UserName : null, Publisher = s.Publisher != null ? s.Publisher.UserName : null, - IntendedClass = s.IntendedClass != null ? s.IntendedClass.Name : null + IntendedClass = s.IntendedClass != null ? s.IntendedClass.Name : null, + Votes = s.Topic != null && s.Topic.Poll != null + && s.Topic.Poll.PollOptions.Any(o => o.Text == SiteGlobalConstants.PollOptionYes) + && s.Topic.Poll.PollOptions.Any(o => o.Text == SiteGlobalConstants.PollOptionsMeh) + && s.Topic.Poll.PollOptions.Any(o => o.Text == SiteGlobalConstants.PollOptionNo) + ? new VoteCounts + { + VotesYes = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionYes).Votes.Count, + VotesMeh = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionsMeh).Votes.Count, + VotesNo = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionNo).Votes.Count, + UserVotedYes = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionYes).Votes.Any(v => v.UserId == userIdForVotes), + UserVotedMeh = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionsMeh).Votes.Any(v => v.UserId == userIdForVotes), + UserVotedNo = s.Topic.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionNo).Votes.Any(v => v.UserId == userIdForVotes), + } + : null, }); } diff --git a/TASVideos/Pages/Forum/Subforum/Index.cshtml b/TASVideos/Pages/Forum/Subforum/Index.cshtml index 5447c8e4c..68402f1f4 100644 --- a/TASVideos/Pages/Forum/Subforum/Index.cshtml +++ b/TASVideos/Pages/Forum/Subforum/Index.cshtml @@ -44,6 +44,7 @@ } @topic.Topics +
@{ var totalPages = (topic.Replies - 1) / ForumConstants.PostsPerPage + 1; @@ -77,8 +78,7 @@ @if (topic.LastPost is not null) {
- - + @topic.LastPost.PosterName } diff --git a/TASVideos/Pages/Forum/Subforum/Index.cshtml.cs b/TASVideos/Pages/Forum/Subforum/Index.cshtml.cs index c6d63b481..79b6dbfd6 100644 --- a/TASVideos/Pages/Forum/Subforum/Index.cshtml.cs +++ b/TASVideos/Pages/Forum/Subforum/Index.cshtml.cs @@ -1,4 +1,5 @@ -using TASVideos.Data.Entity.Forum; +using TASVideos.Common; +using TASVideos.Data.Entity.Forum; namespace TASVideos.Pages.Forum.Subforum; @@ -30,6 +31,8 @@ public async Task OnGet() return NotFound(); } + int userIdForVotes = User.GetUserId(); + Forum = forum; Topics = await db.ForumTopics .ForForum(Id) @@ -49,7 +52,17 @@ public async Task OnGet() PosterName = fp.Poster!.UserName, CreateTimestamp = fp.CreateTimestamp }) - .FirstOrDefault() + .FirstOrDefault(), + Votes = ft.Submission != null ? ft.Poll != null ? new VoteCounts + { + VotesYes = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionYes).Votes.Count, + VotesMeh = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionsMeh).Votes.Count, + VotesNo = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionNo).Votes.Count, + UserVotedYes = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionYes).Votes.Any(v => v.UserId == userIdForVotes), + UserVotedMeh = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionsMeh).Votes.Any(v => v.UserId == userIdForVotes), + UserVotedNo = ft.Poll.PollOptions.Single(o => o.Text == SiteGlobalConstants.PollOptionNo).Votes.Any(v => v.UserId == userIdForVotes), + } + : null : null, }) .OrderByDescending(ft => ft.Type) .ThenByDescending(ft => ft.LastPost!.Id) // The database does not enforce it, but we can assume a topic will always have at least one post @@ -81,6 +94,9 @@ public class ForumTopicEntry [TableIgnore] public bool IsLocked { get; init; } + [TableIgnore] + public VoteCounts? Votes { get; init; } + [TableIgnore] public LastPostEntry? LastPost { get; init; } diff --git a/TASVideos/Pages/Forum/_Category.cshtml b/TASVideos/Pages/Forum/_Category.cshtml index bc79654ff..4370c5bbe 100644 --- a/TASVideos/Pages/Forum/_Category.cshtml +++ b/TASVideos/Pages/Forum/_Category.cshtml @@ -42,8 +42,7 @@ { } diff --git a/TASVideos/Pages/Shared/_Layout.cshtml b/TASVideos/Pages/Shared/_Layout.cshtml index 82a8ce02d..b49393a5f 100644 --- a/TASVideos/Pages/Shared/_Layout.cshtml +++ b/TASVideos/Pages/Shared/_Layout.cshtml @@ -129,8 +129,9 @@ @{ var (version, sha) = Versioning.GetVersion(); } - © @DateTime.UtcNow.Year - TASVideos v@(version) - - Terms - API + © @DateTime.UtcNow.Year - TASVideos v@(version) + Terms + API @{ string? path = null; if (ViewData.GetWikiPage() is null && this.Model is not (Publications.ViewModel or Submissions.ViewModel)) @@ -138,7 +139,7 @@ path = this.Model.HttpContext.Request.Path.ToString().TrimStart('/'); } } - List referrers + List referrers

diff --git a/TASVideos/Pages/Shared/_VoteCounts.cshtml b/TASVideos/Pages/Shared/_VoteCounts.cshtml new file mode 100644 index 000000000..363cf7548 --- /dev/null +++ b/TASVideos/Pages/Shared/_VoteCounts.cshtml @@ -0,0 +1,20 @@ +@model VoteCounts? + + + @{ + int totalCount = Model!.VotesYes + Model.VotesMeh + Model.VotesNo; + if (totalCount == 0) + { + No votes + } + else + { + var support = Math.Ceiling(100 * ((Model.VotesYes + (Model.VotesMeh / 2d)) / totalCount)); + @support% + } + + if (totalCount != 0){ + (@Model.VotesYes/@Model.VotesMeh/@Model.VotesNo) + } + } + \ No newline at end of file diff --git a/TASVideos/Pages/Submissions/Index.cshtml b/TASVideos/Pages/Submissions/Index.cshtml index 3f4fe95d8..8c454e5ea 100644 --- a/TASVideos/Pages/Submissions/Index.cshtml +++ b/TASVideos/Pages/Submissions/Index.cshtml @@ -63,6 +63,7 @@
(Available for judging in @hoursRemaining hours) + } diff --git a/TASVideos/Pages/Submissions/Index.cshtml.cs b/TASVideos/Pages/Submissions/Index.cshtml.cs index 2fa6321e8..1dfccb5b7 100644 --- a/TASVideos/Pages/Submissions/Index.cshtml.cs +++ b/TASVideos/Pages/Submissions/Index.cshtml.cs @@ -43,7 +43,7 @@ public async Task OnGet() Submissions = await db.Submissions .FilterBy(Search) - .ToSubListEntry() + .ToSubListEntry(User.GetUserId()) .SortedPageOf(Search); } @@ -69,6 +69,8 @@ public class SubmissionEntry : ITimeable, ISubmissionDisplay [Sortable] public SubmissionStatus Status { get; init; } + public VoteCounts? Votes { get; init; } + [TableIgnore] public int Id { get; init; } diff --git a/TASVideos/Pages/Submissions/View.cshtml b/TASVideos/Pages/Submissions/View.cshtml index 84271b892..48cd7b7d9 100644 --- a/TASVideos/Pages/Submissions/View.cshtml +++ b/TASVideos/Pages/Submissions/View.cshtml @@ -200,8 +200,8 @@
- Claim - Claim + Claim + Claim Catalog Publish diff --git a/TASVideos/Pages/Wiki/PageHistory.cshtml b/TASVideos/Pages/Wiki/PageHistory.cshtml index 9799178dd..4a664ee4a 100644 --- a/TASVideos/Pages/Wiki/PageHistory.cshtml +++ b/TASVideos/Pages/Wiki/PageHistory.cshtml @@ -8,31 +8,16 @@ } @functions { - string RowStyles(int revision) - { - if (revision == Model.FromRevision) - { - return "table-info"; - } - - if (revision == Model.ToRevision) - { - return "table-primary"; - } - - return ""; - } - string DiffBtnStyles(int revision, bool isFrom) { if (isFrom && revision == Model.FromRevision) { - return "btn btn-info btn-sm active"; + return "btn btn-info btn-sm bg-warning"; } if (!isFrom && revision == Model.ToRevision) { - return "btn btn-info btn-sm active"; + return "btn btn-info btn-sm bg-warning"; } return "btn btn-info btn-sm"; @@ -55,8 +40,8 @@ { var revision = revisions[i]; var previousId = i < revisions.Count - 1 ? revisions[i + 1].Revision : (int?)null; - - @revision.Revision + + @revision.Revision (source) @revision.MinorEdit diff --git a/TASVideos/Pages/Wiki/ViewSource.cshtml b/TASVideos/Pages/Wiki/ViewSource.cshtml index bdde2df09..ff67852e0 100644 --- a/TASVideos/Pages/Wiki/ViewSource.cshtml +++ b/TASVideos/Pages/Wiki/ViewSource.cshtml @@ -8,7 +8,7 @@
- Revision @Model.Revision (current)
- Last Updated by @(Model.WikiPage.AuthorName ?? "Unknown") + Revision @Model.WikiPage.Revision @(Model.WikiPage.IsCurrent() ? "(current)" : "(old)")
+ Edited by @(Model.WikiPage.AuthorName ?? "Unknown")
@Model.WikiPage.Markup.ReplaceLineEndings("\n")
diff --git a/TASVideos/wwwroot/js/wiki-page-history.js b/TASVideos/wwwroot/js/wiki-page-history.js index ab75a7030..0841ed623 100644 --- a/TASVideos/wwwroot/js/wiki-page-history.js +++ b/TASVideos/wwwroot/js/wiki-page-history.js @@ -47,21 +47,17 @@ function diffBtnClicked(from, to) { function updateTableStyling() { Array.from(document.querySelectorAll('tbody[data-hasrevisions] tr')) .forEach(function (elem) { - elem.classList.remove('table-primary'); - elem.classList.remove('table-info'); - elem.querySelector("button[data-from]").classList.remove("active"); - elem.querySelector("button[data-to]").classList.remove("active"); + elem.querySelector("button[data-from]").classList.remove("bg-warning"); + elem.querySelector("button[data-to]").classList.remove("bg-warning"); }); const cur = document.querySelector(`tr[data-revision="${toRevision}"]`); if (cur) { - cur.classList.add('table-primary'); - cur.querySelector("button[data-to]").classList.add("active"); + cur.querySelector("button[data-to]").classList.add("bg-warning"); } const prev = document.querySelector(`tr[data-revision="${fromRevision}"]`); if (prev) { - prev.classList.add('table-info'); - prev.querySelector("button[data-from]").classList.add("active"); + prev.querySelector("button[data-from]").classList.add("bg-warning"); } } \ No newline at end of file