finish color code support (I think)

This commit is contained in:
RaidMax 2019-08-02 18:04:34 -05:00
parent dfecb99d07
commit bb42861a92
35 changed files with 990 additions and 70 deletions

View File

@ -25,6 +25,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.6" />
<PackageReference Include="RestEase" Version="1.4.9" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
</ItemGroup>

View File

@ -73,13 +73,13 @@ namespace IW4MAdmin.Application
{
#if DEBUG
// lets keep it simple and dispose of everything quickly as logging wont be that much (relatively)
Console.WriteLine(LogLine);
Console.WriteLine(LogLine.StripColors());
await File.AppendAllTextAsync(FileName, $"{LogLine}{Environment.NewLine}");
//Debug.WriteLine(msg);
#else
if (type == LogType.Error || type == LogType.Verbose)
{
Console.WriteLine(LogLine);
Console.WriteLine(LogLine.StripColors());
}
await File.AppendAllTextAsync(FileName, $"{LogLine}{Environment.NewLine}");
#endif

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using SharedLibraryCore;
using SharedLibraryCore.Dtos;
using System.Linq;
using WebfrontCore.Controllers;
@ -66,7 +67,7 @@ namespace LiveRadar.Web.Controllers
if (client != null)
{
radarUpdate.Name = client.Name;
radarUpdate.Name = client.Name.StripColors();
client.SetAdditionalProperty("LiveRadar", radarUpdate);
}

View File

@ -31,7 +31,7 @@ namespace LiveRadar
if (client != null)
{
radarUpdate.Name = client.Name;
radarUpdate.Name = client.Name.StripColors();
client.SetAdditionalProperty("LiveRadar", radarUpdate);
}
}

View File

@ -17,7 +17,7 @@
@foreach (SharedLibraryCore.Dtos.ServerInfo server in ViewBag.Servers)
{
<li class="nav-item">
<a asp-controller="Radar" asp-action="Index" asp-route-serverId="@server.ID" class="nav-link @(server.ID == ViewBag.ActiveServerId ? "active": "")" aria-selected="@(server.ID == ViewBag.ActiveServerId ? "true": "false")">@server.Name</a>
<a asp-controller="Radar" asp-action="Index" asp-route-serverId="@server.ID" class="nav-link @(server.ID == ViewBag.ActiveServerId ? "active": "")" aria-selected="@(server.ID == ViewBag.ActiveServerId ? "true": "false")"><color-code value="@server.Name" allow="@ViewBag.EnableColorCodes"></color-code></a>
</li>
}
</ul>
@ -173,7 +173,6 @@
context.canvas.height = width;
context.canvas.width = context.canvas.height;
}
stateInfo.imageScaler = (stateInfo.canvas.width() / 1024)

View File

@ -1 +1,2 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebfrontCore

View File

@ -100,10 +100,6 @@ namespace IW4MAdmin.Plugins.Stats
await Manager.AddStandardKill(E.Origin, E.Target);
}
else
{
throw new Exception();
}
break;
case GameEvent.EventType.Damage:
if (!E.Owner.CustomCallback && !ShouldIgnoreEvent(E.Origin, E.Target))

View File

@ -51,7 +51,9 @@
</div>
}
<span class="text-muted pl-1 pr-1" style="font-size: 1.25rem;">&mdash;</span>
@Html.ActionLink(stat.Name, "ProfileAsync", "Client", new { id = stat.ClientId })
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@stat.ClientId">
<color-code value="@stat.Name" allow="ViewBag.EnableColorCodes"></color-code>
</a>
</div>
<span class="text-primary">@stat.Performance</span><span class="text-muted"> @loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"]</span><br />

View File

@ -6,7 +6,9 @@
@foreach (var server in ViewBag.Servers)
{
<li class="nav-item ">
<a class="nav-link top-players-link" href="#server_@server.ID" role="tab" data-toggle="tab" aria-selected="false" data-serverid="@server.ID">@server.Name</a>
<a class="nav-link top-players-link" href="#server_@server.ID" role="tab" data-toggle="tab" aria-selected="false" data-serverid="@server.ID">
<color-code value="@server.Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</li>
}
</ul>

View File

@ -1 +1,2 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebfrontCore

View File

@ -78,7 +78,8 @@ namespace SharedLibraryCore.Configuration
public int RConPollRate { get; set; } = 5000;
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_MAX_TB")]
public TimeSpan MaximumTempBanTime { get; set; } = new TimeSpan(24 * 30, 0, 0);
[LocalizedDisplayName("SETUP_ENABLE_COLOR_CODES")]
public bool EnableColorCodes { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGE_PERIOD")]
public int AutoMessagePeriod { get; set; }
[LocalizedDisplayName("WEBFRONT_CONFIGURATION_AUTOMESSAGES")]

View File

@ -157,6 +157,8 @@ namespace SharedLibraryCore.Database
ent.HasIndex(a => a.IPAddress);
ent.Property(a => a.Name).HasMaxLength(24);
ent.HasIndex(a => a.Name);
ent.Property(_alias => _alias.SearchableName).HasMaxLength(24);
ent.HasIndex(_alias => _alias.SearchableName);
});
modelBuilder.Entity<EFMeta>(ent =>

View File

@ -15,6 +15,8 @@ namespace SharedLibraryCore.Database.Models
[Required]
[MaxLength(24)]
public string Name { get; set; }
[MaxLength(24)]
public string SearchableName { get; set; }
[Required]
public int? IPAddress { get; set; }
[Required]

View File

@ -0,0 +1,704 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using SharedLibraryCore.Database;
namespace SharedLibraryCore.Migrations
{
[DbContext(typeof(DatabaseContext))]
[Migration("20190802174908_AddSearchNameToEFAlias")]
partial class AddSearchNameToEFAlias
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.Property<int>("SnapshotId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<int>("CurrentSessionLength");
b.Property<double>("CurrentStrain");
b.Property<int>("CurrentViewAngleId");
b.Property<int>("Deaths");
b.Property<double>("Distance");
b.Property<double>("EloRating");
b.Property<int>("HitDestinationId");
b.Property<int>("HitLocation");
b.Property<int>("HitOriginId");
b.Property<int>("HitType");
b.Property<int>("Hits");
b.Property<int>("Kills");
b.Property<int>("LastStrainAngleId");
b.Property<double>("RecoilOffset");
b.Property<double>("SessionAngleOffset");
b.Property<double>("SessionSPM");
b.Property<int>("SessionScore");
b.Property<double>("StrainAngleBetween");
b.Property<int>("TimeSinceLastEvent");
b.Property<int>("WeaponId");
b.Property<DateTime>("When");
b.HasKey("SnapshotId");
b.HasIndex("ClientId");
b.HasIndex("CurrentViewAngleId");
b.HasIndex("HitDestinationId");
b.HasIndex("HitOriginId");
b.HasIndex("LastStrainAngleId");
b.ToTable("EFACSnapshot");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
{
b.Property<long>("KillId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AttackerId");
b.Property<int>("Damage");
b.Property<int?>("DeathOriginVector3Id");
b.Property<int>("DeathType");
b.Property<double>("Fraction");
b.Property<int>("HitLoc");
b.Property<bool>("IsKill");
b.Property<int?>("KillOriginVector3Id");
b.Property<int>("Map");
b.Property<long>("ServerId");
b.Property<int>("VictimId");
b.Property<int?>("ViewAnglesVector3Id");
b.Property<double>("VisibilityPercentage");
b.Property<int>("Weapon");
b.Property<DateTime>("When");
b.HasKey("KillId");
b.HasIndex("AttackerId");
b.HasIndex("DeathOriginVector3Id");
b.HasIndex("KillOriginVector3Id");
b.HasIndex("ServerId");
b.HasIndex("VictimId");
b.HasIndex("ViewAnglesVector3Id");
b.ToTable("EFClientKills");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.Property<long>("MessageId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<string>("Message");
b.Property<long>("ServerId");
b.Property<DateTime>("TimeSent");
b.HasKey("MessageId");
b.HasIndex("ClientId");
b.HasIndex("ServerId");
b.HasIndex("TimeSent");
b.ToTable("EFClientMessages");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.Property<int>("RatingHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.HasKey("RatingHistoryId");
b.HasIndex("ClientId");
b.ToTable("EFClientRatingHistory");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.Property<int>("ClientId");
b.Property<long>("ServerId");
b.Property<bool>("Active");
b.Property<double>("AverageRecoilOffset");
b.Property<int>("Deaths");
b.Property<double>("EloRating");
b.Property<int>("Kills");
b.Property<double>("MaxStrain");
b.Property<double>("RollingWeightedKDR");
b.Property<double>("SPM");
b.Property<double>("Skill");
b.Property<int>("TimePlayed");
b.Property<double>("VisionAverage");
b.HasKey("ClientId", "ServerId");
b.HasIndex("ServerId");
b.ToTable("EFClientStatistics");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.Property<int>("HitLocationCountId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId")
.HasColumnName("EFClientStatistics_ClientId");
b.Property<int>("HitCount");
b.Property<float>("HitOffsetAverage");
b.Property<int>("Location");
b.Property<float>("MaxAngleDistance");
b.Property<long>("ServerId")
.HasColumnName("EFClientStatistics_ServerId");
b.HasKey("HitLocationCountId");
b.HasIndex("ServerId");
b.HasIndex("ClientId", "ServerId");
b.ToTable("EFHitLocationCounts");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
{
b.Property<int>("RatingId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ActivityAmount");
b.Property<bool>("Newest");
b.Property<double>("Performance");
b.Property<int>("Ranking");
b.Property<int>("RatingHistoryId");
b.Property<long?>("ServerId");
b.Property<DateTime>("When");
b.HasKey("RatingId");
b.HasIndex("RatingHistoryId");
b.HasIndex("ServerId");
b.HasIndex("Performance", "Ranking", "When");
b.ToTable("EFRating");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
{
b.Property<long>("ServerId");
b.Property<bool>("Active");
b.Property<string>("EndPoint");
b.Property<int?>("GameName");
b.Property<int>("Port");
b.HasKey("ServerId");
b.ToTable("EFServers");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
{
b.Property<int>("StatisticId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<long>("ServerId");
b.Property<long>("TotalKills");
b.Property<long>("TotalPlayTime");
b.HasKey("StatisticId");
b.HasIndex("ServerId");
b.ToTable("EFServerStatistics");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
{
b.Property<int>("AliasId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<DateTime>("DateAdded");
b.Property<int?>("IPAddress");
b.Property<int>("LinkId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(24);
b.Property<string>("SearchableName")
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
b.HasIndex("LinkId");
b.HasIndex("Name");
b.HasIndex("SearchableName");
b.ToTable("EFAlias");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
{
b.Property<int>("AliasLinkId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.HasKey("AliasLinkId");
b.ToTable("EFAliasLinks");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
{
b.Property<int>("ChangeHistoryId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("Comment")
.HasMaxLength(128);
b.Property<string>("CurrentValue");
b.Property<int>("OriginEntityId");
b.Property<string>("PreviousValue");
b.Property<int>("TargetEntityId");
b.Property<DateTime>("TimeChanged");
b.Property<int>("TypeOfChange");
b.HasKey("ChangeHistoryId");
b.ToTable("EFChangeHistory");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.Property<int>("ClientId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("AliasLinkId");
b.Property<int>("Connections");
b.Property<int>("CurrentAliasId");
b.Property<DateTime>("FirstConnection");
b.Property<DateTime>("LastConnection");
b.Property<int>("Level");
b.Property<bool>("Masked");
b.Property<long>("NetworkId");
b.Property<string>("Password");
b.Property<string>("PasswordSalt");
b.Property<int>("TotalConnectionTime");
b.HasKey("ClientId");
b.HasIndex("AliasLinkId");
b.HasIndex("CurrentAliasId");
b.HasIndex("NetworkId")
.IsUnique();
b.ToTable("EFClients");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.Property<int>("MetaId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<int>("ClientId");
b.Property<DateTime>("Created");
b.Property<string>("Extra");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(32);
b.Property<DateTime>("Updated");
b.Property<string>("Value")
.IsRequired();
b.HasKey("MetaId");
b.HasIndex("ClientId");
b.HasIndex("Key");
b.ToTable("EFMeta");
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.Property<int>("PenaltyId")
.ValueGeneratedOnAdd();
b.Property<bool>("Active");
b.Property<string>("AutomatedOffense");
b.Property<DateTime?>("Expires");
b.Property<bool>("IsEvadedOffense");
b.Property<int>("LinkId");
b.Property<int>("OffenderId");
b.Property<string>("Offense")
.IsRequired();
b.Property<int>("PunisherId");
b.Property<int>("Type");
b.Property<DateTime>("When");
b.HasKey("PenaltyId");
b.HasIndex("LinkId");
b.HasIndex("OffenderId");
b.HasIndex("PunisherId");
b.ToTable("EFPenalties");
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.Property<int>("Vector3Id")
.ValueGeneratedOnAdd();
b.Property<int?>("EFACSnapshotSnapshotId");
b.Property<float>("X");
b.Property<float>("Y");
b.Property<float>("Z");
b.HasKey("Vector3Id");
b.HasIndex("EFACSnapshotSnapshotId");
b.ToTable("Vector3");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
.WithMany()
.HasForeignKey("CurrentViewAngleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
.WithMany()
.HasForeignKey("HitDestinationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
.WithMany()
.HasForeignKey("HitOriginId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
.WithMany()
.HasForeignKey("LastStrainAngleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
.WithMany()
.HasForeignKey("AttackerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
.WithMany()
.HasForeignKey("DeathOriginVector3Id");
b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
.WithMany()
.HasForeignKey("KillOriginVector3Id");
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
.WithMany()
.HasForeignKey("VictimId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
.WithMany()
.HasForeignKey("ViewAnglesVector3Id");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
.WithMany("HitLocations")
.HasForeignKey("ClientId", "ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
.WithMany("Ratings")
.HasForeignKey("RatingHistoryId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId");
});
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
.WithMany()
.HasForeignKey("ServerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
.WithMany("Children")
.HasForeignKey("LinkId")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
.WithMany()
.HasForeignKey("AliasLinkId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
.WithMany()
.HasForeignKey("CurrentAliasId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
.WithMany("Meta")
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
{
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
.WithMany("ReceivedPenalties")
.HasForeignKey("LinkId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
.WithMany("ReceivedPenalties")
.HasForeignKey("OffenderId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
.WithMany("AdministeredPenalties")
.HasForeignKey("PunisherId")
.OnDelete(DeleteBehavior.Restrict);
});
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
{
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
.WithMany("PredictedViewAngles")
.HasForeignKey("EFACSnapshotSnapshotId");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,32 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace SharedLibraryCore.Migrations
{
public partial class AddSearchNameToEFAlias : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "SearchableName",
table: "EFAlias",
maxLength: 24,
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_EFAlias_SearchableName",
table: "EFAlias",
column: "SearchableName");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_EFAlias_SearchableName",
table: "EFAlias");
migrationBuilder.DropColumn(
name: "SearchableName",
table: "EFAlias");
}
}
}

View File

@ -14,7 +14,7 @@ namespace SharedLibraryCore.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
{
@ -329,6 +329,9 @@ namespace SharedLibraryCore.Migrations
.IsRequired()
.HasMaxLength(24);
b.Property<string>("SearchableName")
.HasMaxLength(24);
b.HasKey("AliasId");
b.HasIndex("IPAddress");
@ -337,6 +340,8 @@ namespace SharedLibraryCore.Migrations
b.HasIndex("Name");
b.HasIndex("SearchableName");
b.ToTable("EFAlias");
});

View File

@ -119,7 +119,7 @@ namespace SharedLibraryCore
/// <param name="message">Message to be sent to all players</param>
public GameEvent Broadcast(string message, EFClient sender = null)
{
string formattedMessage = String.Format(RconParser.Configuration.CommandPrefixes.Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message}");
string formattedMessage = String.Format(RconParser.Configuration.CommandPrefixes.Say, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
#if DEBUG == true
Logger.WriteVerbose(message.StripColors());
@ -140,23 +140,23 @@ namespace SharedLibraryCore
/// <summary>
/// Send a message to a particular players
/// </summary>
/// <param name="Message">Message to send</param>
/// <param name="Target">EFClient to send message to</param>
protected async Task Tell(String Message, EFClient Target)
/// <param name="message">Message to send</param>
/// <param name="target">EFClient to send message to</param>
protected async Task Tell(string message, EFClient target)
{
#if !DEBUG
string formattedMessage = String.Format(RconParser.Configuration.CommandPrefixes.Tell, Target.ClientNumber, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{Message}");
if (Target.ClientNumber > -1 && Message.Length > 0 && Target.Level != EFClient.Permission.Console)
string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, target.ClientNumber, $"{(CustomSayEnabled ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console)
await this.ExecuteCommandAsync(formattedMessage);
#else
Logger.WriteVerbose($"{Target.ClientNumber}->{Message.StripColors()}");
Logger.WriteVerbose($"{target.ClientNumber}->{message.StripColors()}");
await Task.CompletedTask;
#endif
if (Target.Level == EFClient.Permission.Console)
if (target.Level == EFClient.Permission.Console)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(Message.StripColors());
Console.WriteLine(message.StripColors());
Console.ForegroundColor = ConsoleColor.Gray;
}
@ -167,12 +167,12 @@ namespace SharedLibraryCore
}
// it was a remote command so we need to add it to the command result queue
if (Target.ClientNumber < 0)
if (target.ClientNumber < 0)
{
CommandResult.Add(new CommandResponseInfo()
{
Response = Message.StripColors(),
ClientId = Target.ClientId
Response = message.StripColors(),
ClientId = target.ClientId
});
}
}

View File

@ -65,6 +65,7 @@ namespace SharedLibraryCore.Services
client.CurrentAlias = new EFAlias()
{
Name = entity.Name,
SearchableName = entity.Name.StripColors().ToLower(),
DateAdded = DateTime.UtcNow,
IPAddress = entity.IPAddress,
LinkId = linkId.Value
@ -79,6 +80,7 @@ namespace SharedLibraryCore.Services
var alias = new EFAlias()
{
Name = entity.Name,
SearchableName = entity.Name.StripColors().ToLower(),
DateAdded = DateTime.UtcNow,
IPAddress = entity.IPAddress,
Link = link
@ -194,6 +196,7 @@ namespace SharedLibraryCore.Services
IPAddress = ip,
LinkId = newAliasLink.AliasLinkId,
Name = name,
SearchableName = name.StripColors().ToLower(),
Active = true,
};
@ -422,6 +425,27 @@ namespace SharedLibraryCore.Services
}
}
public async Task<EFClient> GetClientForLogin(int clientId)
{
using (var ctx = new DatabaseContext(true))
{
return await ctx.Clients
.Select(_client => new EFClient()
{
NetworkId = _client.NetworkId,
ClientId = _client.ClientId,
CurrentAlias = new EFAlias()
{
Name = _client.CurrentAlias.Name
},
Password = _client.Password,
PasswordSalt = _client.PasswordSalt,
Level = _client.Level
})
.FirstAsync(_client => _client.ClientId == clientId);
}
}
public async Task<List<EFClient>> GetPrivilegedClients(bool includeName = true)
{
using (var context = new DatabaseContext(disableTracking: true))
@ -478,7 +502,7 @@ namespace SharedLibraryCore.Services
// want to find them by name (wildcard)
else
{
iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like(_alias.Name.ToLower(), $"%{identifier.ToLower()}%"));
iqLinkIds = iqLinkIds.Where(_alias => EF.Functions.Like((_alias.SearchableName ?? _alias.Name.ToLower()), $"%{identifier.ToLower()}%"));
}
var linkIds = await iqLinkIds
@ -489,7 +513,7 @@ namespace SharedLibraryCore.Services
var iqClients = context.Clients
.Where(_client => _client.Active);
iqClients = iqClients.Where(_client => networkId == _client.NetworkId || linkIds.Contains(_client.AliasLinkId));
// we want to project our results

View File

@ -146,12 +146,16 @@ namespace SharedLibraryCore
}
str = Regex.Replace(str, @"(\^+((?![a-z]|[A-Z]).){0,1})+", "");
string str2 = Regex.Match(str, @"(^\/+.*$)|(^.*\/+$)")
.Value
.Replace("/", " /");
return str2.Length > 0 ? str2 : str;
return str;
}
/// <summary>
/// returns a "fixed" string that prevents message truncation in IW4 (and probably other Q3 clients)
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string FixIW4ForwardSlash(this string str) => Regex.Match(str, @"(^\/+.*$)|(^.*\/+$)").Value.Replace("/", " /");
/// <summary>
/// Get the IW Engine color code corresponding to an admin level
/// </summary>

View File

@ -25,7 +25,7 @@ namespace WebfrontCore.Controllers
try
{
var privilegedClient = await Manager.GetClientService().Get(clientId);
var privilegedClient = await Manager.GetClientService().GetClientForLogin(clientId);
bool loginSuccess = false;
#if DEBUG
loginSuccess = clientId == 1;

View File

@ -52,6 +52,7 @@ namespace WebfrontCore.Controllers
ViewBag.Version = Manager.Version;
ViewBag.IsFluid = false;
ViewBag.EnableColorCodes = Manager.GetApplicationSettings().Configuration().EnableColorCodes;
}
public override void OnActionExecuting(ActionExecutingContext context)
@ -113,6 +114,7 @@ namespace WebfrontCore.Controllers
ViewBag.Pages = Pages;
ViewBag.Localization = Utilities.CurrentLocalization.LocalizationIndex;
ViewBag.CustomBranding = Manager.GetApplicationSettings().Configuration().WebfrontCustomBranding ?? "IW4MAdmin";
ViewBag.EnableColorCodes = Manager.GetApplicationSettings().Configuration().EnableColorCodes;
base.OnActionExecuting(context);
}

View File

@ -90,12 +90,13 @@ namespace WebfrontCore.Controllers
clientDto.Meta.AddRange(Authorized ? meta : meta.Where(m => !m.Sensitive));
ViewBag.Title = clientDto.Name.Substring(clientDto.Name.Length - 1).ToLower()[0] == 's' ?
clientDto.Name + "'" :
clientDto.Name + "'s";
string strippedName = clientDto.Name.StripColors();
ViewBag.Title = strippedName.Substring(strippedName.Length - 1).ToLower()[0] == 's' ?
strippedName + "'" :
strippedName + "'s";
ViewBag.Title += " " + Localization["WEBFRONT_CLIENT_PROFILE_TITLE"];
ViewBag.Description = $"Client information for {clientDto.Name}";
ViewBag.Keywords = $"IW4MAdmin, client, profile, {clientDto.Name}";
ViewBag.Description = $"Client information for {strippedName}";
ViewBag.Keywords = $"IW4MAdmin, client, profile, {strippedName}";
return View("Profile/Index", clientDto);
}
@ -130,7 +131,6 @@ namespace WebfrontCore.Controllers
return View("Privileged/Index", adminsDict);
}
public async Task<IActionResult> FindAsync(string clientName)
{
if (string.IsNullOrWhiteSpace(clientName))

View File

@ -16,16 +16,18 @@ namespace WebfrontCore.Controllers
{
if (fileName.EndsWith(".css"))
{
#if DEBUG
string cssData = await System.IO.File.ReadAllTextAsync($"X:\\IW4MAdmin\\WebfrontCore\\wwwroot\\css\\{fileName}");
cssData = await Manager.MiddlewareActionHandler.Execute(cssData, "custom_css_accent");
return Content(cssData, "text/css");
#endif
if (!_fileCache.ContainsKey(fileName))
{
#if DEBUG
string path = $"X:\\IW4MAdmin\\WebfrontCore\\wwwroot\\css\\{fileName}";
#else
string path = $"wwwroot\\css\\{fileName}";
#endif
string cssData = await System.IO.File.ReadAllTextAsync(path);
cssData = await Manager.MiddlewareActionHandler.Execute(cssData, "custom_css_accent");
_fileCache.Add(fileName, cssData);
string data = await System.IO.File.ReadAllTextAsync(path);
data = await Manager.MiddlewareActionHandler.Execute(data, "custom_css_accent");
_fileCache.Add(fileName, data);
}
return Content(_fileCache[fileName], "text/css");

View File

@ -0,0 +1,41 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using SharedLibraryCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace WebfrontCore.TagHelpers
{
[HtmlTargetElement("color-code")]
public class ColorCode : TagHelper
{
public string Value { get; set; }
public bool Allow { get; set; } = false;
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "ColorCode";
output.TagMode = TagMode.StartTagAndEndTag;
if (Allow)
{
string updated = Value;
foreach (Match match in Regex.Matches(Value, @"\^([0-9]|\:)([^\^]*)"))
{
char colorCode = match.Groups[1].ToString().Last();
updated = updated.Replace(match.Value, $"<span class='text-color-code-{(colorCode >= 48 && colorCode <= 57 ? colorCode.ToString() : ((int)colorCode).ToString())}'>{match.Groups[2].ToString()}</span>");
}
output.PreContent.SetHtmlContent(updated);
}
else
{
output.PreContent.SetHtmlContent(Value.StripColors());
}
}
}
}

View File

@ -15,7 +15,11 @@
@foreach (var client in Model)
{
<div class="row pt-2 pb-2 bg-dark">
<div class="col-5">@Html.ActionLink(client.Name, "ProfileAsync", "Client", new { id = client.ClientId })</div>
<div class="col-5">
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@client.ClientId">
<color-code value="@client.Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</div>
<div class="col-4 level-color-@client.LevelInt">@client.Level</div>
<div class="col-3 text-right">@client.LastConnectionText</div>
</div>
@ -32,7 +36,11 @@
<div class="p-2">@loc["WEBFRONT_SEARCH_LAST_CONNECTED"]</div>
</div>
<div class="col-7 bg-dark border-bottom">
<div class="p-2">@Html.ActionLink(client.Name, "ProfileAsync", "Client", new { id = client.ClientId },new { @class = "link-inverse" } )</div>
<div class="p-2">
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@client.ClientId" class="link-inverse">
<color-code value="@client.Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</div>
<div class="p-2 level-color-@client.LevelInt">@client.Level</div>
<div class="p-2 text-white-50">@client.LastConnectionText</div>
</div>

View File

@ -13,7 +13,10 @@
<div class="col-12 bg-dark pt-2 pb-2">
@foreach (var client in Model[key])
{
<span>@Html.ActionLink(client.Name, "profileasync", "client", new { id = client.ClientId }, new { @class = "" })</span><br />
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@client.ClientId">
<color-code value="@client.Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
<br />
}
</div>
}

View File

@ -25,7 +25,7 @@
<!-- Name/Level Column -->
<div class="d-block d-lg-inline-flex flex-column flex-fill text-center text-lg-left pb-3 pb-lg-0 pt-3 pt-lg-0 pl-3 pr-3">
<div class="mt-n2 flex-fill d-block d-lg-inline-flex">
<div id="profile_name" class="client-name h1 mb-0">@Model.Name</div>
<div id="profile_name" class="client-name h1 mb-0"><color-code value="@Model.Name" allow="@ViewBag.EnableColorCodes"></color-code></div>
@if (ViewBag.Authorized)
{
<div id="profile_aliases_btn" class="oi oi-caret-bottom h3 ml-0 ml-lg-2 mb-0 pt-lg-2 mt-lg-1"></div>
@ -40,7 +40,7 @@
}
@foreach (string alias in Model.Aliases)
{
@alias<br />
<color-code value="@alias" allow="@ViewBag.EnableColorCodes"></color-code><br />
}
@foreach (string ip in Model.IPs)
@ -89,7 +89,7 @@
@foreach (var meta in metaColumn)
{
<div class="profile-meta-entry" title="@(string.IsNullOrEmpty(meta.Extra) ? meta.Key : meta.Extra)">
<span class="profile-meta-value text-primary">@meta.Value</span>
<span class="profile-meta-value text-primary"><color-code value="@meta.Value" allow="@ViewBag.EnableColorCodes"></color-code></span>
<span class="profile-meta-title text-muted"> @meta.Key</span>
</div>
}

View File

@ -2,7 +2,7 @@
<div class="row justify-content-center">
<div id="console" class="col-md-8">
@Html.DropDownList("Server", Model.Select(s => new SelectListItem() { Text = s.Name, Value = s.ID.ToString() }).ToList(), new { @class = "form-control bg-dark text-light", id = "console_server_select" })
@Html.DropDownList("Server", Model.Select(s => new SelectListItem() { Text = SharedLibraryCore.Utilities.StripColors(s.Name), Value = s.ID.ToString() }).ToList(), new { @class = "form-control bg-dark text-light", id = "console_server_select" })
<div id="console_command_response" class="bg-dark p-3">
</div>
<div class="form-row">

View File

@ -8,7 +8,9 @@
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_NAME"]</th>
<td>
@Html.ActionLink(Model.OffenderName, "ProfileAsync", "Client", new { id = Model.OffenderId }, new { @class = "link-inverse" })
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@Model.OffenderId" class="link-inverse">
<color-code value="@Model.OffenderName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</td>
</tr>
@ -22,14 +24,14 @@
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_OFFENSE"]</th>
<td class="text-light">
@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")
<color-code value="@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")" allow="@ViewBag.EnableColorCodes"></color-code>
</td>
</tr>
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_ADMIN"]</th>
<td>
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
@Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
</td>
</tr>
@ -51,16 +53,18 @@
<tr class="d-none d-lg-table-row">
<td>
@Html.ActionLink(Model.OffenderName, "ProfileAsync", "Client", new { id = Model.OffenderId }, new { @class = "link-inverse" })
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@Model.OffenderId" class="link-inverse">
<color-code value="@Model.OffenderName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</td>
<td class="penalties-color-@Model.PenaltyTypeText.ToLower()">
@Model.PenaltyType
</td>
<td class="text-light w-50">
@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")
<color-code value="@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")" allow="@ViewBag.EnableColorCodes"></color-code>
</td>
<td>
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
@Html.ActionLink(SharedLibraryCore.Utilities.StripColors(Model.PunisherName), "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
</td>
<td class="text-right text-light">
@{

View File

@ -41,7 +41,10 @@
continue;
}
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}";
<span>@Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })</span><br />
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@Model.Players[i].ClientId" class="@levelColorClass">
<color-code value="@Model.Players[i].Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
<br />
}
}
</div>
@ -54,7 +57,10 @@
continue;
}
string levelColorClass = !ViewBag.Authorized ? "" : $"level-color-{Model.Players[i].LevelInt}";
<span>@Html.ActionLink(Model.Players[i].Name, "ProfileAsync", "Client", new { id = Model.Players[i].ClientId }, new { @class = levelColorClass })</span><br />
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@Model.Players[i].ClientId" class="@levelColorClass">
<color-code value="@Model.Players[i].Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
<br />
}
}
</div>
@ -86,7 +92,12 @@
}
if (Model.ChatHistory[i].Message != "CONNECTED" && Model.ChatHistory[i].Message != "DISCONNECTED")
{
<span class="text-light">@Model.ChatHistory[i].Name</span><span> &mdash; @Model.ChatHistory[i].Message.Substring(0, Math.Min(65, Model.ChatHistory[i].Message.Length)) </span><br />
<span class="text-light">
<color-code value="@Model.ChatHistory[i].Name" allow="@ViewBag.EnableColorCodes"></color-code>
</span>
<span> &mdash;
<color-code value="@Model.ChatHistory[i].Message.Substring(0, Math.Min(40, Model.ChatHistory[i].Message.Length))" allow="@ViewBag.EnableColorCodes"></color-code>
</span><br />
}
}
}

View File

@ -5,7 +5,7 @@
<div class="row server-header pt-1 pb-1 bg-primary " id="server_header_@Model.ID">
<div class="col-md-4 text-center text-md-left d-inline-flex justify-content-center justify-content-md-start">
<span>@Model.Name</span>
<color-code value="@Model.Name" allow="@ViewBag.EnableColorCodes"></color-code>
<a href="@Model.ConnectProtocolUrl" class="ml-2 mr-2 align-self-center d-none d-md-flex server-join-button" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_HOME_JOIN_DESC"]">
<span class="oi oi-play-circle mr-1 align-self-center"></span>
<span class="server-header-ip-address" style="display:none;">@Model.IPAddress</span>

View File

@ -39,7 +39,9 @@
{
<div class="p-2 mb-3 border-bottom" style="background-color: #222;">
<div class="d-flex flex-row">
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@client.ClientId" class="h4 mr-auto">@client.Name</a>
<a asp-controller="Client" asp-action="ProfileAsync" asp-route-id="@client.ClientId" class="h4 mr-auto">
<color-code value="@client.Name" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
<div class="client-location-flag align-self-center" data-ip="@client.IPAddress"></div>
</div>
<div class="d-flex flex-row">

View File

@ -51,18 +51,17 @@
}
@switch (meta.Type)
{
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ChatMessage:
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.QuickMessage:
{
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ChatMessage:
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.QuickMessage:
<div class="profile-meta-entry loader-data-time" data-time="@meta.When">
<span style="color:white;">></span>
<span class="client-message text-muted @(meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.QuickMessage ? "font-italic" : "")" data-serverid="@meta.Extra" data-when="@meta.When.ToFileTimeUtc()" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGE_CONTEXT"]"> @meta.Value</span>
<span class="client-message text-muted @(meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.QuickMessage ? "font-italic" : "")" data-serverid="@meta.Extra" data-when="@meta.When.ToFileTimeUtc()" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGE_CONTEXT"]"> <color-code value="@meta.Value" allow="@ViewBag.EnableColorCodes"></color-code></span>
</div>
break;
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ReceivedPenalty:
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.Penalized:
<div class="profile-meta-entry loader-data-time" data-time="@meta.When">@Html.Raw(formatPenalty(meta))</div>
<div class="profile-meta-entry loader-data-time" data-time="@meta.When"><color-code value="@Html.Raw(formatPenalty(meta))" allow="@ViewBag.EnableColorCodes"></color-code></div>
break;
}
}

View File

@ -1,2 +1,3 @@
@using WebfrontCore
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, WebfrontCore

View File

@ -264,3 +264,73 @@ form *, select {
background-size: contain;
background-repeat: no-repeat
}
.text-color-code-0 {
color: $dark;
}
.text-color-code-1 {
color: $red;
}
.text-color-code-2 {
color: $green;
}
.text-color-code-3 {
color: $yellow;
}
.text-color-code-4 {
color: $blue;
}
.text-color-code-5 {
color: $teal;
}
.text-color-code-5 {
color: $purple;
}
.text-color-code-7 {
color: $white;
}
.text-color-code-8, .text-color-code-9 {
color: grey;
}
.text-color-code-58 {
animation: color-change 60s infinite;
}
@keyframes color-change {
0% {
color: #ff0000;
}
16.66% {
color: #ffff00;
}
33.33% {
color: #00ff00;
}
50% {
color: #00ffff;
}
66.66% {
color: #0000ff;
}
83.33% {
color: #ff00ff;
}
100% {
color: #ff0000;
}
}