diff --git a/ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationCaseController.cs b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationCaseController.cs similarity index 98% rename from ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationCaseController.cs rename to ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationCaseController.cs index 23673697..3b972138 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationCaseController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationCaseController.cs @@ -3,7 +3,7 @@ using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Admin; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Moderator; [ApiController] [Route("moderation/case/{id:int}")] diff --git a/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationRemovalController.cs b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationRemovalController.cs new file mode 100644 index 00000000..db437c23 --- /dev/null +++ b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationRemovalController.cs @@ -0,0 +1,122 @@ +using LBPUnion.ProjectLighthouse.Administration; +using LBPUnion.ProjectLighthouse.PlayerData; +using LBPUnion.ProjectLighthouse.PlayerData.Profiles; +using LBPUnion.ProjectLighthouse.PlayerData.Reviews; +using LBPUnion.ProjectLighthouse.Types; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Moderator; + +[ApiController] +[Route("moderation")] +public class ModerationRemovalController : ControllerBase +{ + + private readonly Database database; + + public ModerationRemovalController(Database database) + { + this.database = database; + } + + private async Task Delete(DbSet dbSet, int id, string? callbackUrl, Func> getHandler) where T: class + { + User? user = this.database.UserFromWebRequest(this.Request); + if (user == null) return this.Redirect("~/login"); + + T? item = await getHandler(user, id); + if (item == null) return this.Redirect("~/404"); + + dbSet.Remove(item); + await this.database.SaveChangesAsync(); + + return this.Redirect(callbackUrl ?? "~/"); + } + + [HttpGet("deleteScore/{scoreId:int}")] + public async Task DeleteScore(int scoreId, [FromQuery] string? callbackUrl) + { + return await this.Delete(this.database.Scores, scoreId, callbackUrl, async (user, id) => + { + Score? score = await this.database.Scores.Include(s => s.Slot).FirstOrDefaultAsync(s => s.ScoreId == id); + if (score == null) return null; + + if (!user.IsModerator && score.Slot.CreatorId != user.UserId) return null; + + return score; + }); + } + + [HttpGet("deleteComment/{commentId:int}")] + public async Task DeleteComment(int commentId, [FromQuery] string? callbackUrl) + { + User? user = this.database.UserFromWebRequest(this.Request); + if (user == null) return this.Redirect("~/login"); + + Comment? comment = await this.database.Comments.FirstOrDefaultAsync(c => c.CommentId == commentId); + if (comment == null) return this.Redirect("~/404"); + + if (comment.Deleted) return this.Redirect(callbackUrl ?? "~/"); + + bool canDelete; + switch (comment.Type) + { + case CommentType.Level: + int slotCreatorId = await this.database.Slots.Where(s => s.SlotId == comment.TargetId) + .Select(s => s.CreatorId) + .FirstOrDefaultAsync(); + canDelete = user.UserId == comment.PosterUserId || user.UserId == slotCreatorId; + break; + case CommentType.Profile: + canDelete = user.UserId == comment.PosterUserId || user.UserId == comment.TargetId; + break; + default: throw new ArgumentOutOfRangeException(); + } + + if (!canDelete && !user.IsModerator) return this.Redirect(callbackUrl ?? "~/"); + + comment.Deleted = true; + comment.DeletedBy = user.Username; + comment.DeletedType = !canDelete && user.IsModerator ? "moderator" : "user"; + await this.database.SaveChangesAsync(); + + return this.Redirect(callbackUrl ?? "~/"); + } + + [HttpGet("deleteReview/{reviewId:int}")] + public async Task DeleteReview(int reviewId, [FromQuery] string? callbackUrl) + { + User? user = this.database.UserFromWebRequest(this.Request); + if (user == null) return this.Redirect("~/login"); + + Review? review = await this.database.Reviews.Include(r => r.Slot).FirstOrDefaultAsync(c => c.ReviewId == reviewId); + if (review == null) return this.Redirect("~/404"); + + if (review.Deleted) return this.Redirect(callbackUrl ?? "~/"); + + bool canDelete = review.Slot?.CreatorId == user.UserId; + if (!canDelete && !user.IsModerator) return this.Redirect(callbackUrl ?? "~/"); + + review.Deleted = true; + review.DeletedBy = !canDelete && user.IsModerator ? DeletedBy.Moderator : DeletedBy.LevelAuthor; + await this.database.SaveChangesAsync(); + + return this.Redirect(callbackUrl ?? "~/"); + } + + [HttpGet("deletePhoto/{photoId:int}")] + public async Task DeletePhoto(int photoId, [FromQuery] string? callbackUrl) + { + return await this.Delete(this.database.Photos, photoId, callbackUrl, async (user, id) => + { + Photo? photo = await this.database.Photos.Include(p => p.Slot).FirstOrDefaultAsync(p => p.PhotoId == id); + if (photo == null) return null; + + if (!user.IsModerator && photo.Slot?.CreatorId != user.UserId) return null; + + return photo; + }); + } + +} \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationSlotController.cs b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationSlotController.cs similarity index 99% rename from ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationSlotController.cs rename to ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationSlotController.cs index d00db37e..f5cacba2 100644 --- a/ProjectLighthouse.Servers.Website/Controllers/Admin/ModerationSlotController.cs +++ b/ProjectLighthouse.Servers.Website/Controllers/Moderator/ModerationSlotController.cs @@ -1,12 +1,12 @@ #nullable enable using LBPUnion.ProjectLighthouse.Configuration; +using LBPUnion.ProjectLighthouse.Helpers; using LBPUnion.ProjectLighthouse.Levels; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using LBPUnion.ProjectLighthouse.Helpers; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Admin; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Controllers.Moderator; [ApiController] [Route("moderation/slot/{id:int}")] diff --git a/ProjectLighthouse.Servers.Website/Extensions/PartialExtensions.cs b/ProjectLighthouse.Servers.Website/Extensions/PartialExtensions.cs index 6b6ca5ac..bc3468d7 100644 --- a/ProjectLighthouse.Servers.Website/Extensions/PartialExtensions.cs +++ b/ProjectLighthouse.Servers.Website/Extensions/PartialExtensions.cs @@ -1,3 +1,4 @@ +using LBPUnion.ProjectLighthouse.Levels; using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using Microsoft.AspNetCore.Html; @@ -13,7 +14,9 @@ public static class PartialExtensions public static ViewDataDictionary WithTime(this ViewDataDictionary viewData, string timeZone) => WithKeyValue(viewData, "TimeZone", timeZone); - private static ViewDataDictionary WithKeyValue(this ViewDataDictionary viewData, string key, object value) + public static ViewDataDictionary CanDelete(this ViewDataDictionary viewData, bool canDelete) => WithKeyValue(viewData, "CanDelete", canDelete); + + private static ViewDataDictionary WithKeyValue(this ViewDataDictionary viewData, string key, object? value) { try { @@ -33,6 +36,25 @@ public static class PartialExtensions public static Task ToLink(this User user, IHtmlHelper helper, ViewDataDictionary viewData, string language, string timeZone = "", bool includeStatus = false) => helper.PartialAsync("Partials/Links/UserLinkPartial", user, viewData.WithLang(language).WithTime(timeZone).WithKeyValue("IncludeStatus", includeStatus)); - public static Task ToHtml(this Photo photo, IHtmlHelper helper, ViewDataDictionary viewData, string language, string timeZone) - => helper.PartialAsync("Partials/PhotoPartial", photo, viewData.WithLang(language).WithTime(timeZone)); + public static Task ToHtml + ( + this Slot slot, + IHtmlHelper helper, + ViewDataDictionary viewData, + User? user, + string callbackUrl, + string language = "", + string timeZone = "", + bool isMobile = false, + bool showLink = false, + bool isMini = false + ) => + helper.PartialAsync("Partials/SlotCardPartial", slot, viewData.WithLang(language).WithTime(timeZone) + .WithKeyValue("User", user) + .WithKeyValue("CallbackUrl", callbackUrl) + .WithKeyValue("ShowLink", showLink) + .WithKeyValue("IsMobile", isMobile)); + + public static Task ToHtml(this Photo photo, IHtmlHelper helper, ViewDataDictionary viewData, string language, string timeZone, bool canDelete = false) + => helper.PartialAsync("Partials/PhotoPartial", photo, viewData.WithLang(language).WithTime(timeZone).CanDelete(canDelete)); } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml similarity index 86% rename from ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml index 0cf5d127..14ef42f1 100644 --- a/ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml @@ -1,5 +1,5 @@ @page "/verifyEmail" -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.CompleteEmailVerificationPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email.CompleteEmailVerificationPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml.cs similarity index 95% rename from ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml.cs index 0da6a3e2..da9fc1c4 100644 --- a/ProjectLighthouse.Servers.Website/Pages/CompleteEmailVerificationPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Email/CompleteEmailVerificationPage.cshtml.cs @@ -6,7 +6,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email; public class CompleteEmailVerificationPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml similarity index 87% rename from ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml index b187bffb..b13e0b84 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml @@ -1,5 +1,5 @@ @page "/login/sendVerificationEmail" -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.SendVerificationEmailPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email.SendVerificationEmailPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml.cs similarity index 98% rename from ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml.cs index a6323d7f..cd3db846 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SendVerificationEmailPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Email/SendVerificationEmailPage.cshtml.cs @@ -9,7 +9,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email; public class SendVerificationEmailPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml similarity index 94% rename from ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml index 0bf88c98..09137830 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml @@ -1,7 +1,7 @@ @page "/login/setEmail" @using LBPUnion.ProjectLighthouse.Configuration @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.SetEmailForm +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email.SetEmailForm @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml.cs similarity index 98% rename from ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml.cs index d16eb5a9..197be21e 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SetEmailForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Email/SetEmailForm.cshtml.cs @@ -11,7 +11,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Email; public class SetEmailForm : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml index 06ab1ba2..02468066 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml @@ -63,7 +63,7 @@ else
@foreach (Slot slot in Model.LatestTeamPicks!) @* Can't reach a point where this is null *@ { - @await Html.PartialAsync("Partials/SlotCardPartial", slot, Model.GetSlotViewData(slot.SlotId, isMobile)) + @await slot.ToHtml(Html, ViewData, Model.User, $"~/slot/{slot.SlotId}", language, timeZone, isMobile, true, true)
}
@@ -80,7 +80,7 @@ else
@foreach (Slot slot in Model.NewestLevels!) @* Can't reach a point where this is null *@ { - @await Html.PartialAsync("Partials/SlotCardPartial", slot, Model.GetSlotViewData(slot.SlotId, isMobile)) + @await slot.ToHtml(Html, ViewData, Model.User, $"~/slot/{slot.SlotId}", language, timeZone, isMobile, true, true)
}
diff --git a/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml.cs index f9ad4b07..008d8fcc 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/LandingPage.cshtml.cs @@ -5,7 +5,6 @@ using LBPUnion.ProjectLighthouse.Levels; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.EntityFrameworkCore; namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; @@ -53,24 +52,4 @@ public class LandingPage : BaseLayout return this.Page(); } - - public ViewDataDictionary GetSlotViewData(int slotId, bool isMobile = false) - => new(ViewData) - { - { - "User", this.User - }, - { - "CallbackUrl", $"~/slot/{slotId}" - }, - { - "ShowLink", true - }, - { - "IsMini", true - }, - { - "IsMobile", isMobile - }, - }; } \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml similarity index 97% rename from ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml index 401ec447..656c5762 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml @@ -1,7 +1,7 @@ @page "/login" @using LBPUnion.ProjectLighthouse.Configuration @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.LoginForm +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.LoginForm @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml.cs similarity index 98% rename from ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml.cs index afd94755..ad9b18d4 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LoginForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/LoginForm.cshtml.cs @@ -13,7 +13,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class LoginForm : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml similarity index 83% rename from ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml index 8854bcb0..964ab10c 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml @@ -1,6 +1,6 @@ @page "/logout" @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.LogoutPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.LogoutPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml.cs similarity index 86% rename from ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml.cs index bf28f740..6c6118da 100644 --- a/ProjectLighthouse.Servers.Website/Pages/LogoutPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/LogoutPage.cshtml.cs @@ -1,10 +1,9 @@ #nullable enable using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; -using LBPUnion.ProjectLighthouse.Types; using Microsoft.AspNetCore.Mvc; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class LogoutPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml similarity index 95% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml index bbc2a2ab..dce63a3f 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml @@ -1,6 +1,6 @@ @page "/passwordReset" @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.PasswordResetPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.PasswordResetPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml.cs similarity index 96% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml.cs index 8791f3cd..98ca81ca 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetPage.cshtml.cs @@ -6,7 +6,7 @@ using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class PasswordResetPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml similarity index 91% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml index ace617a0..24d53f13 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml @@ -1,6 +1,6 @@ @page "/passwordResetRequest" @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.PasswordResetRequestForm +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.PasswordResetRequestForm @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml.cs similarity index 97% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml.cs index eb2109b6..f1bbd986 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequestForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequestForm.cshtml.cs @@ -8,7 +8,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class PasswordResetRequestForm : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml similarity index 76% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml index 6724cc96..bbe18b08 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml @@ -1,5 +1,5 @@ @page "/passwordResetRequired" -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.PasswordResetRequiredPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.PasswordResetRequiredPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml.cs similarity index 86% rename from ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml.cs index ff041a7a..70e45f1c 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PasswordResetRequiredPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PasswordResetRequiredPage.cshtml.cs @@ -1,10 +1,9 @@ #nullable enable using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; -using LBPUnion.ProjectLighthouse.Types; using Microsoft.AspNetCore.Mvc; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class PasswordResetRequiredPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml similarity index 90% rename from ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml index f2b3e9b9..a2e5353e 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml @@ -1,5 +1,5 @@ @page "/pirate" -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.PirateSignupPage +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.PirateSignupPage @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml.cs similarity index 92% rename from ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml.cs index 3d88a60e..efb76894 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PirateSignupPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/PirateSignupPage.cshtml.cs @@ -2,7 +2,7 @@ using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class PirateSignupPage : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml b/ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml similarity index 98% rename from ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml rename to ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml index 39e787d2..9b423b05 100644 --- a/ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml @@ -1,7 +1,7 @@ @page "/register" @using LBPUnion.ProjectLighthouse.Configuration @using LBPUnion.ProjectLighthouse.Localization.StringLists -@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.RegisterForm +@model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login.RegisterForm @{ Layout = "Layouts/BaseLayout"; diff --git a/ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml.cs similarity index 98% rename from ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml.cs rename to ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml.cs index c0ddbb5a..0453a09f 100644 --- a/ProjectLighthouse.Servers.Website/Pages/RegisterForm.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/Login/RegisterForm.cshtml.cs @@ -10,7 +10,7 @@ using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages; +namespace LBPUnion.ProjectLighthouse.Servers.Website.Pages.Login; public class RegisterForm : BaseLayout { diff --git a/ProjectLighthouse.Servers.Website/Pages/Moderation/HiddenLevelsPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/Moderation/HiddenLevelsPage.cshtml index e8122bc1..c7906a48 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Moderation/HiddenLevelsPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Moderation/HiddenLevelsPage.cshtml @@ -2,12 +2,15 @@ @using LBPUnion.ProjectLighthouse.Extensions @using LBPUnion.ProjectLighthouse.Levels @using LBPUnion.ProjectLighthouse.Localization.StringLists +@using LBPUnion.ProjectLighthouse.Servers.Website.Extensions @model LBPUnion.ProjectLighthouse.Servers.Website.Pages.Moderation.HiddenLevelsPage @{ Layout = "Layouts/BaseLayout"; Model.Title = Model.Translate(ModPanelStrings.HiddenLevels); bool isMobile = Model.Request.IsMobile(); + string language = Model.GetLanguage(); + string timeZone = Model.GetTimeZone(); }

There are @Model.SlotCount hidden levels.

@@ -15,21 +18,7 @@ @foreach (Slot slot in Model.Slots) {
- @await Html.PartialAsync("Partials/SlotCardPartial", slot, new ViewDataDictionary(ViewData) - { - { - "User", Model.User - }, - { - "CallbackUrl", $"~/moderation/hiddenLevels/{Model.PageNumber}" - }, - { - "ShowLink", true - }, - { - "IsMobile", isMobile - }, - }) + @await slot.ToHtml(Html, ViewData, Model.User, $"~/moderation/hiddenLevels/{Model.PageNumber}", language, timeZone, isMobile, true)
} diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml index 0a8c24a3..9d239584 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/CommentsPartial.cshtml @@ -8,10 +8,10 @@ string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang; string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id; TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone); + int pageOwnerId = (int?)ViewData["PageOwner"] ?? 0; }
-

Comments

@if (Model.Comments.Count == 0 && Model.CommentsEnabled) {

There are no comments.

@@ -86,6 +86,12 @@ { @decodedMessage } + @if (((Model.User?.IsModerator ?? false) || Model.User?.UserId == comment.PosterUserId || Model.User?.UserId == pageOwnerId) && !comment.Deleted) + { + + }

@TimeZoneInfo.ConvertTime(timestamp, timeZoneInfo).ToString("M/d/yyyy @ h:mm:ss tt")

@@ -96,4 +102,12 @@
} + \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/LeaderboardPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/LeaderboardPartial.cshtml new file mode 100644 index 00000000..0418b496 --- /dev/null +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/LeaderboardPartial.cshtml @@ -0,0 +1,70 @@ +@using LBPUnion.ProjectLighthouse +@using LBPUnion.ProjectLighthouse.Localization +@using LBPUnion.ProjectLighthouse.PlayerData +@using LBPUnion.ProjectLighthouse.PlayerData.Profiles +@using LBPUnion.ProjectLighthouse.Servers.Website.Extensions +@using Microsoft.EntityFrameworkCore +@{ + string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang; + string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id; + bool canDelete = (bool?)ViewData["CanDelete"] ?? false; +} +
+ @if (Model.Scores.Count == 0) + { +

There are no scores.

+ } + else + { + int count = Model.Scores.Count; +

There @(count == 1 ? "is" : "are") @count score@(count == 1 ? "" : "s").

+
+ } +
+ @for(int i = 0; i < Model.Scores.Count; i++) + { + Score score = Model.Scores[i]; + string[] playerIds = score.PlayerIds; + Database database = Model.Database; +
+ + @if(canDelete) + { + + } + @(i+1): + @score.Points points + +
+
+ @for (int j = 0; j < playerIds.Length; j++) + { + User? user = await database.Users.FirstOrDefaultAsync(u => u.Username == playerIds[j]); + if (user == null) continue; +
+ +
+ @await user.ToLink(Html, ViewData, language, timeZone) +
+
+ } +
+
+
+ @if (i != Model.Scores.Count - 1) + { +
+ } + } +
+ +
\ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/PhotoPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/PhotoPartial.cshtml index 89de6ad1..afe370c8 100644 --- a/ProjectLighthouse.Servers.Website/Pages/Partials/PhotoPartial.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/PhotoPartial.cshtml @@ -1,4 +1,3 @@ -@using System.Globalization @using System.Web @using LBPUnion.ProjectLighthouse.Levels @using LBPUnion.ProjectLighthouse.Localization @@ -9,15 +8,30 @@ @{ string language = (string?)ViewData["Language"] ?? LocalizationManager.DefaultLang; string timeZone = (string?)ViewData["TimeZone"] ?? TimeZoneInfo.Local.Id; + bool canDelete = (bool?)ViewData["CanDelete"] ?? false; TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone); }
+ @if (canDelete) + { + + + } + style="width: 100%; height: auto; border-radius: .28571429rem;" alt="Photo">

@@ -50,6 +64,12 @@ case SlotType.Local: in a level on the moon break; + case SlotType.Moon: + case SlotType.Unknown: + case SlotType.Unknown2: + case SlotType.DLC: + default: + throw new ArgumentOutOfRangeException(); } } at @TimeZoneInfo.ConvertTime(DateTime.UnixEpoch.AddSeconds(Model.Timestamp), timeZoneInfo).ToString("M/d/yyyy h:mm:ss tt") diff --git a/ProjectLighthouse.Servers.Website/Pages/Partials/ReviewPartial.cshtml b/ProjectLighthouse.Servers.Website/Pages/Partials/ReviewPartial.cshtml new file mode 100644 index 00000000..3e91ffc2 --- /dev/null +++ b/ProjectLighthouse.Servers.Website/Pages/Partials/ReviewPartial.cshtml @@ -0,0 +1,129 @@ +@using System.Web +@using LBPUnion.ProjectLighthouse.Administration +@using LBPUnion.ProjectLighthouse.Configuration +@using LBPUnion.ProjectLighthouse.Files +@using LBPUnion.ProjectLighthouse.Helpers +@using LBPUnion.ProjectLighthouse.PlayerData.Reviews + +@{ + bool isMobile = (bool?)ViewData["IsMobile"] ?? false; + bool canDelete = (bool?)ViewData["CanDelete"] ?? false; +} + +
+
+ @if (Model.Reviews.Count == 0 && Model.ReviewsEnabled) + { +

There are no reviews.

+ } + else if (!Model.ReviewsEnabled) + { + + Reviews are disabled on this level. + + } + else + { + int count = Model.Reviews.Count; +

There @(count == 1 ? "is" : "are") @count review@(count == 1 ? "" : "s").

+
+ } + + @for(int i = 0; i < Model.Reviews.Count; i++) + { + Review review = Model.Reviews[i]; + string faceHash = (review.Thumb switch { + -1 => review.Reviewer?.BooHash, + 0 => review.Reviewer?.MehHash, + 1 => review.Reviewer?.YayHash, + + _ => throw new ArgumentOutOfRangeException(), + }) ?? ""; + + if (string.IsNullOrWhiteSpace(faceHash) || !FileHelper.ResourceExists(faceHash)) + { + faceHash = ServerConfiguration.Instance.WebsiteConfiguration.MissingIconHash; + } + + string faceAlt = review.Thumb switch { + -1 => "Boo!", + 0 => "Meh.", + 1 => "Yay!", + + _ => throw new ArgumentOutOfRangeException(), + }; + + int size = isMobile ? 50 : 100; + +
+
+ @faceAlt +
+
+

@review.Reviewer?.Username

+ @if (review.Deleted) + { + if (review.DeletedBy == DeletedBy.LevelAuthor) + { +

+ This review has been deleted by the level author. +

+ } + else + { +

+ This review has been deleted by a moderator. +

+ } + } + else + { + @if (review.Labels.Length > 1) + { + @foreach (string reviewLabel in review.Labels) + { +
@LabelHelper.TranslateTag(reviewLabel)
+ } + } + @if (string.IsNullOrWhiteSpace(review.Text)) + { +

+ This review contains no text. +

+ } + else + { + { +

@HttpUtility.HtmlDecode(review.Text)

+ } + } + } +
+ @if (canDelete && !review.Deleted) + { +
+ + +
+ } +
+ @if (i != Model.Reviews.Count - 1) + { +
+ } + } +
+ @if (isMobile) + { +
+ } +
\ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml index 0af93f44..bafa73be 100644 --- a/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/PhotosPage.cshtml @@ -24,8 +24,9 @@ @foreach (Photo photo in Model.Photos) { + bool canDelete = Model.User != null && (Model.User.IsModerator || Model.User.UserId == photo.CreatorId);
- @await photo.ToHtml(Html, ViewData, language, timeZone) + @await photo.ToHtml(Html, ViewData, language, timeZone, canDelete)
} diff --git a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml index 83e3dd77..806e7d8a 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml @@ -1,12 +1,10 @@ @page "/slot/{id:int}" @using System.Web @using LBPUnion.ProjectLighthouse.Administration -@using LBPUnion.ProjectLighthouse.Configuration @using LBPUnion.ProjectLighthouse.Extensions -@using LBPUnion.ProjectLighthouse.Files @using LBPUnion.ProjectLighthouse.Helpers +@using LBPUnion.ProjectLighthouse.Localization.StringLists @using LBPUnion.ProjectLighthouse.PlayerData -@using LBPUnion.ProjectLighthouse.PlayerData.Reviews @using LBPUnion.ProjectLighthouse.Servers.Website.Extensions @model LBPUnion.ProjectLighthouse.Servers.Website.Pages.SlotPage @@ -17,7 +15,7 @@ Model.Title = HttpUtility.HtmlDecode(Model.Slot?.Name ?? ""); Model.Description = HttpUtility.HtmlDecode(Model.Slot?.Description ?? ""); - bool isMobile = this.Request.IsMobile(); + bool isMobile = Request.IsMobile(); string language = Model.GetLanguage(); string timeZone = Model.GetTimeZone(); } @@ -34,21 +32,7 @@ } -@await Html.PartialAsync("Partials/SlotCardPartial", Model.Slot, new ViewDataDictionary(ViewData) -{ - { - "User", Model.User - }, - { - "CallbackUrl", $"~/slot/{Model.Slot?.SlotId}" - }, - { - "ShowLink", false - }, - { - "IsMobile", Model.Request.IsMobile() - }, -}) +@await Model.Slot.ToHtml(Html, ViewData, Model.User, $"~/slot/{Model.Slot?.SlotId}", language, timeZone, isMobile)
@@ -66,7 +50,6 @@

Tags

@{ - string[] authorLabels; if (Model.Slot?.GameVersion == GameVersion.LittleBigPlanet1) { @@ -96,137 +79,91 @@ {
} -
- @await Html.PartialAsync("Partials/CommentsPartial", ViewData.WithLang(language).WithTime(timeZone)) -
- @if (isMobile) - { -
+
+ +
+ @{ + string outerDiv = isMobile ? + "horizontal-scroll" : + "three wide column"; + string innerDiv = isMobile ? + "ui top attached tabular menu horizontal-scroll" : + "ui vertical fluid tabular menu"; } -
-
-

Reviews

- @if (Model.Reviews.Count == 0 && Model.ReviewsEnabled) - { -

There are no reviews.

- } - else if (!Model.ReviewsEnabled) - { - - Reviews are disabled on this level. - - } - else - { - int count = Model.Reviews.Count; -

There @(count == 1 ? "is" : "are") @count review@(count == 1 ? "" : "s").

-
- } - - - @for(int i = 0; i < Model.Reviews.Count; i++) - { - Review review = Model.Reviews[i]; - string faceHash = (review.Thumb switch { - -1 => review.Reviewer?.BooHash, - 0 => review.Reviewer?.MehHash, - 1 => review.Reviewer?.YayHash, - - _ => throw new ArgumentOutOfRangeException(), - }) ?? ""; - - if (string.IsNullOrWhiteSpace(faceHash) || !FileHelper.ResourceExists(faceHash)) - { - faceHash = ServerConfiguration.Instance.WebsiteConfiguration.MissingIconHash; - } - - string faceAlt = review.Thumb switch { - -1 => "Boo!", - 0 => "Meh.", - 1 => "Yay!", - - _ => throw new ArgumentOutOfRangeException(), - }; - - int size = isMobile ? 50 : 100; - -
-
- @faceAlt -
-
-

@review.Reviewer?.Username

- @if (review.Deleted) - { - if (review.DeletedBy == DeletedBy.LevelAuthor) - { -

- This review has been deleted by the level author. -

- } - else - { -

- This review has been deleted by a moderator. -

- } - } - else - { - @if (review.Labels.Length > 1) - { - @foreach (string reviewLabel in review.Labels) - { -
@LabelHelper.TranslateTag(reviewLabel)
- } - } - @if (string.IsNullOrWhiteSpace(review.Text)) - { -

- This review contains no text. -

- } - else - { - { -

@HttpUtility.HtmlDecode(review.Text)

- } - } - } -
-
- @if (i != Model.Reviews.Count - 1) - { -
- } - } + + + @{ + string divLength = isMobile ? "sixteen" : "thirteen"; + } +
+
+ @await Html.PartialAsync("Partials/CommentsPartial", ViewData.WithLang(language).WithTime(timeZone)) +
+
+
+ @if (Model.Photos.Count != 0) + { +
+ @foreach (Photo photo in Model.Photos) + { + string width = isMobile ? "sixteen" : "eight"; + bool canDelete = Model.User != null && (Model.User.IsModerator || Model.User.UserId == photo.CreatorId || Model.User.UserId == Model.Slot?.SlotId); +
+ @await photo.ToHtml(Html, ViewData, language, timeZone, canDelete) +
+ } +
+ @if (isMobile) + { +
+ } + } + else + { +

This level has no photos yet.

+ } + +
+
+
+ @await Html.PartialAsync("Partials/ReviewPartial", new ViewDataDictionary(ViewData) + { + { + "isMobile", isMobile + }, + { + "CanDelete", (Model.User?.IsModerator ?? false) || Model.Slot?.CreatorId == Model.User?.UserId + }, + }) +
+
+
+ @await Html.PartialAsync("Partials/LeaderboardPartial", + ViewData.WithLang(language).WithTime(timeZone).CanDelete(Model.User?.IsModerator ?? false)) +
- @if (isMobile) - { -
- }
-@if (Model.Photos.Count != 0) -{ -
-

Most recent photos

- -
- @foreach (Photo photo in Model.Photos) - { -
- @await photo.ToHtml(Html, ViewData, language, timeZone) -
- } -
-
@if (isMobile) {
} -} @if (Model.User != null && Model.User.IsModerator) { @@ -281,4 +218,51 @@ {
} -} \ No newline at end of file +} + + \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml.cs index 2b34cd57..b3f8ef70 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/SlotPage.cshtml.cs @@ -16,6 +16,7 @@ public class SlotPage : BaseLayout public List Comments = new(); public List Reviews = new(); public List Photos = new(); + public List Scores = new(); public bool CommentsEnabled; public readonly bool ReviewsEnabled = ServerConfiguration.Instance.UserGeneratedContentLimits.LevelReviewsEnabled; @@ -93,6 +94,12 @@ public class SlotPage : BaseLayout .Take(10) .ToListAsync(); + this.Scores = await this.Database.Scores.OrderByDescending(s => s.Points) + .ThenByDescending(s => s.ScoreId) + .Where(s => s.SlotId == id) + .Take(10) + .ToListAsync(); + if (this.User == null) return this.Page(); foreach (Comment c in this.Comments) diff --git a/ProjectLighthouse.Servers.Website/Pages/SlotsPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/SlotsPage.cshtml index f9eb1d22..8ec9a945 100644 --- a/ProjectLighthouse.Servers.Website/Pages/SlotsPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/SlotsPage.cshtml @@ -2,6 +2,7 @@ @using LBPUnion.ProjectLighthouse.Extensions @using LBPUnion.ProjectLighthouse.Levels @using LBPUnion.ProjectLighthouse.Localization.StringLists +@using LBPUnion.ProjectLighthouse.Servers.Website.Extensions @model LBPUnion.ProjectLighthouse.Servers.Website.Pages.SlotsPage @{ @@ -9,6 +10,8 @@ Model.Title = Model.Translate(BaseLayoutStrings.HeaderSlots); bool isMobile = Model.Request.IsMobile(); + string language = Model.GetLanguage(); + string timeZone = Model.GetTimeZone(); }

There are @Model.SlotCount total levels!

@@ -24,21 +27,7 @@ @foreach (Slot slot in Model.Slots) {
- @await Html.PartialAsync("Partials/SlotCardPartial", slot, new ViewDataDictionary(ViewData) - { - { - "User", Model.User - }, - { - "CallbackUrl", $"~/slots/{Model.PageNumber}" - }, - { - "ShowLink", true - }, - { - "IsMobile", isMobile - }, - }) + @await slot.ToHtml(Html, ViewData, Model.User, $"~/slots/{Model.PageNumber}", language, timeZone, isMobile, true)
} diff --git a/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml b/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml index 47e4fd90..f267f796 100644 --- a/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml +++ b/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml @@ -2,6 +2,7 @@ @using System.Web @using LBPUnion.ProjectLighthouse.Administration @using LBPUnion.ProjectLighthouse.Extensions +@using LBPUnion.ProjectLighthouse.Levels @using LBPUnion.ProjectLighthouse.Localization.StringLists @using LBPUnion.ProjectLighthouse.PlayerData @using LBPUnion.ProjectLighthouse.Servers.Website.Extensions @@ -123,29 +124,133 @@ }
- -@if (Model.Photos != null && Model.Photos.Count != 0) -{ -
-

@Model.Translate(GeneralStrings.RecentPhotos)

- -
- @foreach (Photo photo in Model.Photos) +
+ @{ + string outerDiv = isMobile ? + "horizontal-scroll" : + "three wide column"; + string innerDiv = isMobile ? + "ui top attached tabular menu horizontal-scroll" : + "ui vertical fluid tabular menu"; + } +
+
+ + Comments + + + @Model.Translate(BaseLayoutStrings.HeaderPhotos) + + + + @Model.Translate(BaseLayoutStrings.HeaderSlots) + + + Playlists + + @if (Model.User == Model.ProfileUser) { - string width = isMobile ? "sixteen" : "eight"; -
- @await photo.ToHtml(Html, ViewData, language, timeZone) -
+ + Hearted Levels + + + Queued Levels + }
- @if (isMobile) - { -
+ @{ + string divLength = isMobile ? "sixteen" : "thirteen"; } -} - -@await Html.PartialAsync("Partials/CommentsPartial", ViewData.WithLang(language).WithTime(timeZone)) +
+
+ @await Html.PartialAsync("Partials/CommentsPartial", ViewData.WithLang(language).WithTime(timeZone)) +
+
+
+ @if (Model.Photos != null && Model.Photos.Count != 0) + { +
+ @foreach (Photo photo in Model.Photos) + { + string width = isMobile ? "sixteen" : "eight"; + bool canDelete = Model.User != null && (Model.User.IsModerator || Model.User.UserId == photo.CreatorId); +
+ @await photo.ToHtml(Html, ViewData, language, timeZone, canDelete) +
+ } +
+ @if (isMobile) + { +
+ } + } + else + { +

This user hasn't uploaded any photos

+ } +
+
+
+
+ @if (Model.HeartedSlots?.Count == 0) + { +

This user hasn't published any levels

+ } + @foreach (Slot slot in Model.Slots ?? new List()) + { +
+ @await slot.ToHtml(Html, ViewData, Model.User, $"~/user/{Model.ProfileUser.UserId}#levels", language, timeZone, isMobile, true) +
+ } +
+
+
+
+

@Model.Translate(GeneralStrings.Soon)

+
+
+ @if (Model.User == Model.ProfileUser) + { +
+
+ @if (Model.HeartedSlots?.Count == 0) + { +

You haven't hearted any levels

+ } + else + { +

You have hearted @(Model.HeartedSlots?.Count) levels

+ } + @foreach (Slot slot in Model.HeartedSlots ?? new List()) + { +
+ @await slot.ToHtml(Html, ViewData, Model.User, $"~/user/{Model.ProfileUser.UserId}#hearted", language, timeZone, isMobile, true) +
+ } +
+
+
+
+ @if (Model.QueuedSlots?.Count == 0) + { +

You haven't queued any levels

+ } + else + { +

There are @(Model.QueuedSlots?.Count) levels in your queue

+ } + @foreach (Slot slot in Model.QueuedSlots ?? new List()) + { +
+ @await slot.ToHtml(Html, ViewData, Model.User, $"~/user/{Model.ProfileUser.UserId}#queued", language, timeZone, isMobile, true) +
+ } +
+
+ } +
+
@if (Model.User != null && Model.User.IsModerator) { @@ -191,4 +296,51 @@ {
} -} \ No newline at end of file +} + + \ No newline at end of file diff --git a/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml.cs b/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml.cs index 9edc619f..e52a8f53 100644 --- a/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml.cs +++ b/ProjectLighthouse.Servers.Website/Pages/UserPage.cshtml.cs @@ -1,5 +1,6 @@ #nullable enable using LBPUnion.ProjectLighthouse.Configuration; +using LBPUnion.ProjectLighthouse.Levels; using LBPUnion.ProjectLighthouse.PlayerData; using LBPUnion.ProjectLighthouse.PlayerData.Profiles; using LBPUnion.ProjectLighthouse.Servers.Website.Pages.Layouts; @@ -18,6 +19,10 @@ public class UserPage : BaseLayout public bool IsProfileUserHearted; public List? Photos; + public List? Slots; + + public List? HeartedSlots; + public List? QueuedSlots; public User? ProfileUser; public UserPage(Database database) : base(database) @@ -50,7 +55,33 @@ public class UserPage : BaseLayout } } - this.Photos = await this.Database.Photos.Include(p => p.Slot).OrderByDescending(p => p.Timestamp).Where(p => p.CreatorId == userId).Take(6).ToListAsync(); + this.Photos = await this.Database.Photos.Include(p => p.Slot) + .OrderByDescending(p => p.Timestamp) + .Where(p => p.CreatorId == userId) + .Take(6) + .ToListAsync(); + + this.Slots = await this.Database.Slots.Include(p => p.Creator) + .OrderByDescending(s => s.LastUpdated) + .Where(p => p.CreatorId == userId) + .Take(10) + .ToListAsync(); + + if (this.User == this.ProfileUser) + { + this.QueuedSlots = await this.Database.QueuedLevels.Include(h => h.Slot) + .Where(h => this.User != null && h.UserId == this.User.UserId) + .Select(h => h.Slot) + .Where(s => s.Type == SlotType.User) + .Take(10) + .ToListAsync(); + this.HeartedSlots = await this.Database.HeartedLevels.Include(h => h.Slot) + .Where(h => this.User != null && h.UserId == this.User.UserId) + .Select(h => h.Slot) + .Where(s => s.Type == SlotType.User) + .Take(10) + .ToListAsync(); + } this.CommentsEnabled = ServerConfiguration.Instance.UserGeneratedContentLimits.LevelCommentsEnabled && this.ProfileUser.CommentsEnabled; if (this.CommentsEnabled) @@ -70,12 +101,16 @@ public class UserPage : BaseLayout foreach (Comment c in this.Comments) { - Reaction? reaction = await this.Database.Reactions.FirstOrDefaultAsync(r => r.UserId == this.User.UserId && r.TargetId == c.CommentId); + Reaction? reaction = await this.Database.Reactions.Where(r => r.TargetId == c.TargetId) + .Where(r => r.UserId == this.User.UserId) + .FirstOrDefaultAsync(); if (reaction != null) c.YourThumb = reaction.Rating; } - this.IsProfileUserHearted = await this.Database.HeartedProfiles.FirstOrDefaultAsync - (u => u.UserId == this.User.UserId && u.HeartedUserId == this.ProfileUser.UserId) != - null; + + this.IsProfileUserHearted = await this.Database.HeartedProfiles + .Where(h => h.HeartedUserId == this.ProfileUser.UserId) + .Where(h => h.UserId == this.User.UserId) + .AnyAsync(); return this.Page(); } diff --git a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs index b8074025..5ec85606 100644 --- a/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs +++ b/ProjectLighthouse/Administration/Maintenance/MaintenanceJobs/CleanupBrokenPhotosMaintenanceJob.cs @@ -68,7 +68,6 @@ public class CleanupBrokenPhotosMaintenanceJob : IMaintenanceJob } LbpFile? file = LbpFile.FromHash(photo.LargeHash); -// Console.WriteLine(file.FileType, ); if (file == null || file.FileType != LbpFileType.Jpeg && file.FileType != LbpFileType.Png) { largeHashIsInvalidFile = true; diff --git a/ProjectLighthouse/Extensions/RequestExtensions.cs b/ProjectLighthouse/Extensions/RequestExtensions.cs index 0287654c..78e257e4 100644 --- a/ProjectLighthouse/Extensions/RequestExtensions.cs +++ b/ProjectLighthouse/Extensions/RequestExtensions.cs @@ -49,10 +49,12 @@ public static class RequestExtensions private static readonly HttpClient client; [SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")] - private static async Task verifyCaptcha(string token) + private static async Task verifyCaptcha(string? token) { if (!ServerConfiguration.Instance.Captcha.CaptchaEnabled) return true; + if (token == null) return false; + List> payload = new() { new("secret", ServerConfiguration.Instance.Captcha.Secret), @@ -84,7 +86,7 @@ public static class RequestExtensions bool gotCaptcha = request.Form.TryGetValue(keyName, out StringValues values); if (!gotCaptcha) return false; - if (!await verifyCaptcha(values[0] ?? string.Empty)) return false; + if (!await verifyCaptcha(values[0])) return false; } return true; diff --git a/ProjectLighthouse/StaticFiles/css/styles.css b/ProjectLighthouse/StaticFiles/css/styles.css index 66782e5c..119133e6 100644 --- a/ProjectLighthouse/StaticFiles/css/styles.css +++ b/ProjectLighthouse/StaticFiles/css/styles.css @@ -72,6 +72,18 @@ canvas.hide-subjects { pointer-events: none; } +.horizontal-scroll::-webkit-scrollbar { + display: none; +} + +.horizontal-scroll { + overflow-x: scroll; + overflow-y: hidden; + -ms-overflow-style: none; /* IE and Edge */ + scrollbar-width: none; /* Firefox */ + width: 100%; +} + /*#region Cards*/ .card {