Simplify rank badges and implement profile tags (#880)

* Simplify website rank badges to use semantic classes

* Fix ambiguity between partial display types

* Add profile vanity tags and needed migration

* Make form field read only to non-administrators

* Display lock icon if user is not admin to minimize confusion

* Also display lock icon for username field since it's readonly

* Fix up naming consistency issues and edit migration accordingly

* Apply suggestions from code review

* Add space between placeholder property and ternary operator
This commit is contained in:
koko 2023-08-28 16:37:06 -04:00 committed by GitHub
parent a316c866c5
commit be5a29d3c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 19 deletions

View file

@ -27,4 +27,7 @@
<data name="title" xml:space="preserve">
<value>{0}'s user page</value>
</data>
<data name="profile_tag" xml:space="preserve">
<value>Profile Tag</value>
</data>
</root>

View file

@ -5,6 +5,7 @@ public static class ProfileStrings
public static readonly TranslatableString Title = create("title");
public static readonly TranslatableString Biography = create("biography");
public static readonly TranslatableString NoBiography = create("no_biography");
public static readonly TranslatableString ProfileTag = create("profile_tag");
private static TranslatableString create(string key) => new(TranslationAreas.Profile, key);
}

View file

@ -28,7 +28,7 @@ public static class FormattingExtensions
return permissionLevel switch
{
PermissionLevel.Administrator => "red",
PermissionLevel.Moderator => "rgb(200, 130, 0)",
PermissionLevel.Moderator => "orange",
_ => "",
};
}

View file

@ -25,10 +25,16 @@
<a href="~/user/@Model.UserId">@Model.Username</a>
@if (Model.IsModerator)
{
<span class="permissionBadge" style="background-color: @Model.PermissionLevel.ToHtmlColor();">
<span class="profile-tag ui label @Model.PermissionLevel.ToHtmlColor()">
@Model.PermissionLevel.ToString()
</span>
}
@if (!string.IsNullOrWhiteSpace(Model.ProfileTag))
{
<span class="profile-tag ui label">
@Model.ProfileTag
</span>
}
</h2>
}
else
@ -37,10 +43,16 @@
@Model.Username
@if (Model.IsModerator)
{
<span class="permissionBadge" style="background-color: @Model.PermissionLevel.ToHtmlColor();">
<span class="profile-tag ui label @Model.PermissionLevel.ToHtmlColor()">
@Model.PermissionLevel.ToString()
</span>
}
@if (!string.IsNullOrWhiteSpace(Model.ProfileTag))
{
<span class="profile-tag ui label">
@Model.ProfileTag
</span>
}
</h1>
}
@{

View file

@ -61,7 +61,7 @@ function onSubmit(e){
</div>
</div>
<div class="field">
<label style="text-align: left" for="username">@Model.Translate(GeneralStrings.Username)</label>
<label style="text-align: left" for="username">@Model.Translate(GeneralStrings.Username) <i class="ui icon lock"></i></label>
<input type="text" name="username" id="username" value="@Model.ProfileUser.Username" placeholder="Username" readonly>
</div>
@if (ServerConfiguration.Instance.Mail.MailEnabled && (Model.User == Model.ProfileUser || Model.User!.IsAdmin))
@ -71,6 +71,16 @@ function onSubmit(e){
<input type="text" name="email" id="email" required value="@Model.ProfileUser.EmailAddress" placeholder="Email Address">
</div>
}
<div class="field">
<label style="text-align: left" for="profileTag">
@Model.Translate(ProfileStrings.ProfileTag)
@if (!Model.User!.IsAdmin)
{
<i class="ui icon lock"></i>
}
</label>
<input type="text" name="profileTag" id="profileTag" value="@Model.ProfileUser.ProfileTag" placeholder="Profile Tag" @(!Model.User!.IsAdmin ? "readonly" : "")>
</div>
<div class="field">
<label style="text-align: left" for="biography">@Model.Translate(ProfileStrings.Biography)</label>
<textarea name="biography" id="biography" spellcheck="false" placeholder="Biography">@HttpUtility.HtmlDecode(Model.ProfileUser.Biography)</textarea>

View file

@ -20,7 +20,17 @@ public class UserSettingsPage : BaseLayout
{}
[SuppressMessage("ReSharper", "SpecifyStringComparison")]
public async Task<IActionResult> OnPost([FromRoute] int userId, [FromForm] string? avatar, [FromForm] string? username, [FromForm] string? email, [FromForm] string? biography, [FromForm] string? timeZone, [FromForm] string? language)
public async Task<IActionResult> OnPost
(
[FromRoute] int userId,
[FromForm] string? avatar,
[FromForm] string? username,
[FromForm] string? email,
[FromForm] string profileTag,
[FromForm] string? biography,
[FromForm] string? timeZone,
[FromForm] string? language
)
{
this.ProfileUser = await this.Database.Users.FirstOrDefaultAsync(u => u.UserId == userId);
if (this.ProfileUser == null) return this.NotFound();
@ -33,6 +43,8 @@ public class UserSettingsPage : BaseLayout
if (avatarHash != null) this.ProfileUser.IconHash = avatarHash;
if (this.User.IsAdmin) this.ProfileUser.ProfileTag = profileTag;
if (biography != null)
{
biography = CensorHelper.FilterMessage(biography);

View file

@ -0,0 +1,30 @@
using LBPUnion.ProjectLighthouse.Database;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ProjectLighthouse.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20230827004014_AddProfileVanityTagsToUsers")]
public partial class AddProfileVanityTagsToUsers : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "ProfileTag",
table: "Users",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ProfileTag",
table: "Users");
}
}
}

View file

@ -16,7 +16,7 @@ namespace ProjectLighthouse.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.8")
.HasAnnotation("ProductVersion", "7.0.10")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LBPUnion.ProjectLighthouse.Types.Entities.Interaction.HeartedLevelEntity", b =>
@ -858,6 +858,9 @@ namespace ProjectLighthouse.Migrations
b.Property<string>("PlanetHashLBPVita")
.HasColumnType("longtext");
b.Property<string>("ProfileTag")
.HasColumnType("longtext");
b.Property<int>("ProfileVisibility")
.HasColumnType("int");

View file

@ -244,19 +244,9 @@ div.cardStatsUnderTitle > span {
/*#region User permission badge */
.permissionBadge {
width: auto;
height: auto;
color: white;
background-color: inherit;
border: 0px solid black;
border-radius: 50px;
font-weight: 200;
font-size: 10pt;
padding: 1px;
padding-left: 6px;
padding-right: 6px;
vertical-align: top;
.profile-tag {
position: relative;
bottom: 0.45rem;
}
/*#endregion User permission badge */

View file

@ -72,6 +72,7 @@ public class UserEntity
public string PlanetHashLBP2 { get; set; } = "";
// ReSharper disable once InconsistentNaming
public string PlanetHashLBP2CC { get; set; } = "";
public string PlanetHashLBP3 { get; set; } = "";
@ -130,6 +131,8 @@ public class UserEntity
// should not be adjustable by user
public bool CommentsEnabled { get; set; } = true;
public string ProfileTag { get; set; } = "";
#nullable enable
public override bool Equals(object? obj)