1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-10 15:20:48 -05:00

QOL updates for profile meta

implement filterable meta for issue #158
update translations and use humanizer lib with datetime/timespan for issue #80
This commit is contained in:
RaidMax
2020-08-17 21:21:11 -05:00
parent 25ad16495e
commit 6e27dd9dce
78 changed files with 1800 additions and 775 deletions

View File

@ -242,7 +242,7 @@ namespace WebfrontCore.Controllers
{
var info = new ActionInfo()
{
ActionButtonLabel = "Generate",
ActionButtonLabel = Localization["WEBFRONT_ACTION_LABEL_GENERATE_TOKEN"],
Name = "GenerateLoginToken",
Action = "GenerateLoginTokenAsync",
Inputs = new List<InputInfo>()

View File

@ -27,7 +27,7 @@ namespace WebfrontCore.Controllers
ViewBag.Title = _translationLookup["WEBFRONT_NAV_AUDIT_LOG"];
ViewBag.InitialOffset = DEFAULT_COUNT;
var auditItems = await _auditInformationRepository.ListAuditInformation(new PaginationInfo()
var auditItems = await _auditInformationRepository.ListAuditInformation(new PaginationRequest()
{
Count = DEFAULT_COUNT
});
@ -35,7 +35,7 @@ namespace WebfrontCore.Controllers
return View(auditItems);
}
public async Task<IActionResult> ListAuditLog([FromQuery] PaginationInfo paginationInfo)
public async Task<IActionResult> ListAuditLog([FromQuery] PaginationRequest paginationInfo)
{
ViewBag.EnableColorCodes = Manager.GetApplicationSettings().Configuration().EnableColorCodes;
var auditItems = await _auditInformationRepository.ListAuditInformation(paginationInfo);

View File

@ -2,12 +2,15 @@
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using SharedLibraryCore.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebfrontCore.ViewComponents;
using static SharedLibraryCore.Database.Models.EFClient;
using static SharedLibraryCore.Database.Models.EFPenalty;
@ -15,12 +18,14 @@ namespace WebfrontCore.Controllers
{
public class ClientController : BaseController
{
public ClientController(IManager manager) : base(manager)
{
private readonly IMetaService _metaService;
public ClientController(IManager manager, IMetaService metaService) : base(manager)
{
_metaService = metaService;
}
public async Task<IActionResult> ProfileAsync(int id)
public async Task<IActionResult> ProfileAsync(int id, MetaType? metaFilterType)
{
var client = await Manager.GetClientService().Get(id);
@ -29,8 +34,8 @@ namespace WebfrontCore.Controllers
return NotFound();
}
var activePenalties = (await Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId, client.IPAddress))
.Where(_penalty => _penalty.Type != PenaltyType.Flag);
var activePenalties = (await Manager.GetPenaltyService().GetActivePenaltiesAsync(client.AliasLinkId, client.IPAddress));
int displayLevelInt = (int)client.Level;
string displayLevel = client.Level.ToLocalizedLevelName();
@ -49,7 +54,7 @@ namespace WebfrontCore.Controllers
ClientId = client.ClientId,
IPAddress = client.IPAddressString,
NetworkId = client.NetworkId,
Meta = new List<ProfileMeta>(),
Meta = new List<InformationResponse>(),
Aliases = client.AliasLink.Children
.Select(_alias => _alias.Name)
.GroupBy(_alias => _alias.StripColors())
@ -65,38 +70,32 @@ namespace WebfrontCore.Controllers
.Prepend(client.CurrentAlias.IPAddress.ConvertIPtoString())
.Distinct()
.ToList(),
HasActivePenalty = activePenalties.Count() > 0,
ActivePenaltyType = activePenalties.Count() > 0 ? activePenalties.First().Type.ToString() : null,
HasActivePenalty = activePenalties.Any(_penalty => _penalty.Type != PenaltyType.Flag),
Online = Manager.GetActiveClients().FirstOrDefault(c => c.ClientId == client.ClientId) != null,
TimeOnline = (DateTime.UtcNow - client.LastConnection).TimeSpanText(),
LinkedAccounts = client.LinkedAccounts
TimeOnline = (DateTime.UtcNow - client.LastConnection).HumanizeForCurrentCulture(),
LinkedAccounts = client.LinkedAccounts,
MetaFilterType = metaFilterType
};
var meta = await MetaService.GetRuntimeMeta(client.ClientId, 0, 1, DateTime.UtcNow);
var gravatar = await new MetaService().GetPersistentMeta("GravatarEmail", client);
var meta = await _metaService.GetRuntimeMeta<InformationResponse>(new ClientPaginationRequest
{
ClientId = client.ClientId,
Before = DateTime.UtcNow
}, MetaType.Information);
var gravatar = await _metaService.GetPersistentMeta("GravatarEmail", client);
if (gravatar != null)
{
clientDto.Meta.Add(new ProfileMeta()
clientDto.Meta.Add(new InformationResponse()
{
Key = "GravatarEmail",
Type = ProfileMeta.MetaType.Other,
Type = MetaType.Other,
Value = gravatar.Value
});
}
var currentPenalty = activePenalties.FirstOrDefault();
if (currentPenalty != null && currentPenalty.Type == PenaltyType.TempBan)
{
clientDto.Meta.Add(new ProfileMeta()
{
Key = Localization["WEBFRONT_CLIENT_META_REMAINING_BAN"],
Value = ((currentPenalty.Expires - DateTime.UtcNow) ?? new TimeSpan()).TimeSpanText(),
When = currentPenalty.When
});
}
clientDto.Meta.AddRange(Authorized ? meta : meta.Where(m => !m.Sensitive));
clientDto.ActivePenalty = activePenalties.OrderByDescending(_penalty => _penalty.Type).FirstOrDefault();
clientDto.Meta.AddRange(Authorized ? meta : meta.Where(m => !m.IsSensitive));
string strippedName = clientDto.Name.StripColors();
ViewBag.Title = strippedName.Substring(strippedName.Length - 1).ToLower()[0] == 's' ?
@ -160,14 +159,17 @@ namespace WebfrontCore.Controllers
return View("Find/Index", clientsDto);
}
public async Task<IActionResult> Meta(int id, int count, int offset, DateTime? startAt)
public async Task<IActionResult> Meta(int id, int count, int offset, long? startAt, MetaType? metaFilterType)
{
IEnumerable<ProfileMeta> meta = await MetaService.GetRuntimeMeta(id, startAt == null ? offset : 0, count, startAt ?? DateTime.UtcNow);
if (!Authorized)
var request = new ClientPaginationRequest
{
meta = meta.Where(_meta => !_meta.Sensitive);
}
ClientId = id,
Count = count,
Offset = offset,
Before = DateTime.FromFileTimeUtc(startAt ?? DateTime.UtcNow.ToFileTimeUtc())
};
var meta = await ProfileMetaListViewComponent.GetClientMeta(_metaService, metaFilterType, Client.Level, request);
if (meta.Count() == 0)
{

View File

@ -19,6 +19,10 @@ using Stats.Dtos;
using Stats.Helpers;
using StatsWeb;
using StatsWeb.Dtos;
/*using Stats.Dtos;
using Stats.Helpers;
using StatsWeb;
using StatsWeb.Dtos;*/
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -125,6 +129,7 @@ namespace WebfrontCore
services.AddSingleton(Program.ApplicationServiceProvider.GetService<ITranslationLookup>());
services.AddSingleton(Program.ApplicationServiceProvider.GetService<SharedLibraryCore.Interfaces.ILogger>());
services.AddSingleton(Program.ApplicationServiceProvider.GetService<IEnumerable<IManagerCommand>>());
services.AddSingleton(Program.ApplicationServiceProvider.GetService<IMetaService>());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -1,7 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Services;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using System;
using System.Collections.Generic;
using System.Linq;
@ -12,18 +13,70 @@ namespace WebfrontCore.ViewComponents
{
public class ProfileMetaListViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(int clientId, int count, int offset, DateTime? startAt)
private readonly IMetaService _metaService;
public ProfileMetaListViewComponent(IMetaService metaService)
{
_metaService = metaService;
}
public async Task<IViewComponentResult> InvokeAsync(int clientId, int count, int offset, DateTime? startAt, MetaType? metaType)
{
var level = (EFClient.Permission)Enum.Parse(typeof(EFClient.Permission), UserClaimsPrincipal.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value ?? "User");
IEnumerable<ProfileMeta> meta = await MetaService.GetRuntimeMeta(clientId, offset, count, startAt ?? DateTime.UtcNow);
if (level < EFClient.Permission.Trusted)
var request = new ClientPaginationRequest
{
meta = meta.Where(_meta => !_meta.Sensitive);
}
ClientId = clientId,
Count = count,
Offset = offset,
Before = startAt,
};
var meta = await GetClientMeta(_metaService, metaType, level, request);
ViewBag.Localization = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex;
return View("_List", meta);
}
public static async Task<IEnumerable<IClientMeta>> GetClientMeta(IMetaService metaService, MetaType? metaType, EFClient.Permission level, ClientPaginationRequest request)
{
IEnumerable<IClientMeta> meta = null;
if (metaType == null) // all types
{
meta = await metaService.GetRuntimeMeta(request);
}
else
{
switch (metaType)
{
case MetaType.Information:
meta = await metaService.GetRuntimeMeta<InformationResponse>(request, metaType.Value);
break;
case MetaType.AliasUpdate:
meta = await metaService.GetRuntimeMeta<UpdatedAliasResponse>(request, metaType.Value);
break;
case MetaType.ChatMessage:
meta = await metaService.GetRuntimeMeta<MessageResponse>(request, metaType.Value);
break;
case MetaType.Penalized:
meta = await metaService.GetRuntimeMeta<AdministeredPenaltyResponse>(request, metaType.Value);
break;
case MetaType.ReceivedPenalty:
meta = await metaService.GetRuntimeMeta<ReceivedPenaltyResponse>(request, metaType.Value);
break;
default:
break;
}
}
if (level < EFClient.Permission.Trusted)
{
meta = meta.Where(_meta => !_meta.IsSensitive);
}
return meta;
}
}
}

View File

@ -1,17 +1,17 @@
@model SharedLibraryCore.Dtos.PlayerInfo
@using SharedLibraryCore.Database.Models
@using SharedLibraryCore.Interfaces
@using SharedLibraryCore
@model SharedLibraryCore.Dtos.PlayerInfo
@{
string match = System.Text.RegularExpressions.Regex.Match(Model.Name.ToUpper(), "[A-Z]").Value;
string shortCode = match == string.Empty ? "?" : match;
var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex;
string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value;
bool isTempBanned = Model.ActivePenaltyType == "TempBan";
bool isFlagged = Model.LevelInt == (int)SharedLibraryCore.Database.Models.EFClient.Permission.Flagged;
bool isPermBanned = Model.LevelInt == (int)SharedLibraryCore.Database.Models.EFClient.Permission.Banned;
var informationMeta = Model.Meta
.Where(_meta => _meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Information)
.OrderBy(_meta => _meta.Order)
.GroupBy(_meta => _meta.Column)
.OrderBy(_grouping => _grouping.Key);
bool isTempBanned = Model.ActivePenalty?.Type == EFPenalty.PenaltyType.TempBan;
string translationKey = $"WEBFRONT_PROFILE_{Model.ActivePenalty?.Type.ToString().ToUpper()}_INFO";
var ignoredMetaTypes = new[] { MetaType.Information, MetaType.Other, MetaType.QuickMessage };
}
<div id="profile_wrapper" class="pb-3 row d-flex flex-column flex-lg-row">
@ -23,7 +23,7 @@
}
</div>
<!-- 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="w-75 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 ml-auto mr-auto" style="overflow-wrap: anywhere">
<div class="mt-n2 flex-fill d-block d-lg-inline-flex">
<div id="profile_name" class="client-name h1 mb-0"><color-code value="@Model.Name" allow="@ViewBag.EnableColorCodes"></color-code></div>
@if (ViewBag.Authorized)
@ -31,6 +31,7 @@
<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>
}
</div>
@if (ViewBag.Authorized)
{
<div id="profile_aliases" class="text-muted pt-0 pt-lg-2 pb-2">
@ -49,9 +50,34 @@
}
</div>
}
<div id="profile_level" class="font-weight-bold h4 mb-0 level-color-@Model.LevelInt @(isTempBanned ? "penalties-color-tempban" : "")">
@Model.Level @(isTempBanned ? $"({loc["WEBFRONT_PROFILE_TEMPBAN"]})" : "")
</div>
@if (Model.ActivePenalty != null)
{
<div class="font-weight-bold h4 mb-0 penalties-color-@Model.ActivePenalty.Type.ToString().ToLower()">
@foreach (var result in Utilities.SplitTranslationTokens(translationKey))
{
switch (result.MatchValue)
{
case "reason":
<span class="text-white font-weight-lighter">@(ViewBag.Authorized ? !string.IsNullOrEmpty(Model.ActivePenalty.AutomatedOffense) && Model.ActivePenalty.Type != EFPenalty.PenaltyType.Warning ? Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_ANTICHEAT_DETECTION"], Model.ActivePenalty.AutomatedOffense) : Model.ActivePenalty.Offense : Model.ActivePenalty.Offense)</span>
break;
case "time":
<span class="text-white font-weight-lighter">
@Utilities.HumanizeForCurrentCulture(Model.ActivePenalty.Expires.Value - DateTime.UtcNow)
</span>
break;
default:
<span>@result.MatchValue</span>
break;
}
}
</div>
}
else
{
<div id="profile_level" class="font-weight-bold h4 mb-0 level-color-@Model.LevelInt">
@Model.Level
</div>
}
</div>
@if (ViewBag.Authorized)
{
@ -89,23 +115,32 @@
</div>
<div id="profile_info" class="row d-block d-lg-flex flex-row border-bottom border-top pt-2 pb-2">
@foreach (var metaColumn in informationMeta)
{
<div class="text-center text-lg-left mr-0 mr-lg-4">
@foreach (var meta in metaColumn)
<partial name="Meta/_Information.cshtml" model="@Model.Meta" />
</div>
<div class="row border-bottom">
<div class="text-center bg-dark p-2 pl-3 pr-4 text-muted col-12 col-md-auto" id="filter_meta_container_button">
<span class="oi oi-sort-ascending"></span>
<a>Filter Meta</a>
</div>
<div class="d-none d-md-flex flex-fill" id="filter_meta_container">
@foreach (MetaType type in Enum.GetValues(typeof(MetaType)))
{
if (!ignoredMetaTypes.Contains(type))
{
<div class="profile-meta-entry" title="@(string.IsNullOrEmpty(meta.Extra) ? meta.Key : meta.Extra)">
<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>
<a asp-action="ProfileAsync" asp-controller="Client"
class="nav-link p-2 pl-3 pr-3 text-center col-12 col-md-auto text-md-left @(Model.MetaFilterType.HasValue && Model.MetaFilterType.Value.ToString() == type.ToString() ? "btn-primary text-white" : "text-muted")"
asp-route-id="@Model.ClientId"
asp-route-metaFilterType="@type"
data-meta-type="@type">@type.ToTranslatedName()</a>
}
</div>
}
}
</div>
</div>
<div class="row d-md-flex pt-2">
<div id="profile_events" class="text-muted text-left ml-sm-0">
@await Component.InvokeAsync("ProfileMetaList", new { clientId = Model.ClientId, count = 30, offset = 0 })
<div id="profile_events" class="text-muted text-left pl-4 pr-4 pl-md-0 pr-md-0">
@await Component.InvokeAsync("ProfileMetaList", new { clientId = Model.ClientId, count = 30, offset = 0, startAt = DateTime.UtcNow, metaType = Model.MetaFilterType })
</div>
</div>
@ -122,5 +157,5 @@
<script type="text/javascript" src="~/js/loader.js"></script>
<script type="text/javascript" src="~/js/profile.js"></script>
</environment>
<script>initLoader('/Client/Meta/@Model.ClientId', '#profile_events', 30);</script>
<script>initLoader('/Client/Meta/@Model.ClientId', '#profile_events', 30, 30, [{ 'name': 'metaFilterType', 'value': '@Model.MetaFilterType' }]);</script>
}

View File

@ -0,0 +1,53 @@
@using SharedLibraryCore.Dtos.Meta.Responses
@model AdministeredPenaltyResponse
@{
string localizationKey = $"WEBFRONT_CLIENT_META_PENALIZED_{Model.PenaltyType.ToString().ToUpper()}_V2";
}
<div class="d-inline">
@foreach (var match in Utilities.SplitTranslationTokens(localizationKey))
{
if (match.IsInterpolation)
{
if (match.MatchValue == "action")
{
<span class="penalties-color-@Model.PenaltyType.ToString().ToLower()">@match.TranslationValue</span>
}
else if (match.MatchValue == "offender")
{
<span class="text-highlight">
<a class="link-inverse" href="@Model.OffenderClientId">
<color-code value="@Model.OffenderName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</span>
}
else if (match.MatchValue == "reason")
{
<span class="text-white">
@if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != SharedLibraryCore.Database.Models.EFPenalty.PenaltyType.Warning)
{
<span>@Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_ANTICHEAT_DETECTION"], Model.AutomatedOffense)</span>
<span class="oi oi-list-rich align-top text-primary automated-penalty-info-detailed" data-penalty-id="@Model.PenaltyId" style="margin-top: 0.125rem;" title="@ViewBag.Localization["WEBFRONT_CLIENT_META_AC_METRIC"]"></span>
}
else
{
<color-code value="@Model.Offense" allow="@ViewBag.EnableColorCodes"></color-code>
}
</span>
}
else if (match.MatchValue == "time")
{
<span class="text-white">@Model.LengthText</span>
}
}
else
{
<span>@match.MatchValue</span>
}
}
</div>

View File

@ -0,0 +1,43 @@
@model IEnumerable<SharedLibraryCore.Dtos.Meta.Responses.InformationResponse>
@{
var informationMeta = Model
.Where(_meta => _meta.Type == SharedLibraryCore.Interfaces.MetaType.Information)
.OrderBy(_meta => _meta.Order)
.GroupBy(_meta => _meta.Column)
.OrderBy(_grouping => _grouping.Key);
}
@foreach (var metaColumn in informationMeta)
{
<div class="text-center text-lg-left mr-0 mr-lg-4">
@foreach (var meta in metaColumn)
{
<div class="profile-meta-entry" title="@meta.ToolTipText">
@{var results = Utilities.SplitTranslationTokens(meta.Key);}
@if (results.Any(_result => _result.IsInterpolation))
{
foreach (var result in results)
{
if (result.IsInterpolation)
{
<span class="profile-meta-value text-primary"><color-code value="@meta.Value" allow="@ViewBag.EnableColorCodes"></color-code></span>
}
else
{
<span class="profile-meta-title text-muted">@result.MatchValue</span>
}
}
}
else
{
<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>
}
</div>
}

View File

@ -0,0 +1,9 @@
@using SharedLibraryCore.Dtos.Meta.Responses;
@model MessageResponse
<span class="client-message" data-serverid="@Model.ServerId" data-when="@Model.When.ToFileTimeUtc()">
<span class="oi oi-chevron-right text-white-50 align-middle client-message-prefix" title="@ViewBag.Localization["WEBFRONT_PROFILE_MESSAGE_CONTEXT"]" style="font-size: 0.75rem; margin-top: -0.256rem"></span>
<span class="text-muted">
<color-code value="@Model.Message" allow="@ViewBag.EnableColorCodes"></color-code>
</span>
</span>

View File

@ -0,0 +1,74 @@
@using SharedLibraryCore.Dtos.Meta.Responses
@using SharedLibraryCore
@model ReceivedPenaltyResponse
@{
string localizationKey = $"WEBFRONT_CLIENT_META_WAS_PENALIZED_{Model.PenaltyType.ToString().ToUpper()}_V2";
}
<div class="d-inline">
@foreach (var match in Utilities.SplitTranslationTokens(localizationKey))
{
if (match.IsInterpolation)
{
if (match.MatchValue == "action")
{
<span class="penalties-color-@Model.PenaltyType.ToString().ToLower()">@match.TranslationValue</span>
}
else if (match.MatchValue == "punisher")
{
<span class="text-highlight">
<a class="link-inverse" href="@Model.PunisherClientId">
<color-code value="@Model.PunisherName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</span>
}
else if (match.MatchValue == "reason")
{
<span class="text-white">
@if (ViewBag.Authorized && !string.IsNullOrEmpty(Model.AutomatedOffense) && Model.PenaltyType != SharedLibraryCore.Database.Models.EFPenalty.PenaltyType.Warning)
{
<span>@Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_ANTICHEAT_DETECTION"], Model.AutomatedOffense)</span>
<span class="oi oi-list-rich align-top text-primary automated-penalty-info-detailed" data-penalty-id="@Model.PenaltyId" style="margin-top: 0.125rem;" title="@ViewBag.Localization["WEBFRONT_CLIENT_META_AC_METRIC"]"></span>
}
else
{
<color-code value="@Model.Offense" allow="@ViewBag.EnableColorCodes"></color-code>
}
</span>
}
else if (match.MatchValue == "time")
{
<span class="text-white">@Model.LengthText</span>
}
}
else
{
<span>@match.MatchValue</span>
}
}
@if (Model.ClientId != Model.OffenderClientId)
{
<span>&mdash;</span>
@foreach (var helperResult in Utilities.SplitTranslationTokens("WEBFRONT_PROFILE_LINKED_ACCOUNT"))
{
if (!helperResult.IsInterpolation)
{
<span>@helperResult.MatchValue</span>
}
else
{
<a class="link-inverse" href="@Model.OffenderClientId">
<color-code value="@Model.OffenderName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
}
}
}
</div>

View File

@ -0,0 +1,27 @@
@using SharedLibraryCore.Dtos.Meta.Responses
@using SharedLibraryCore
@model UpdatedAliasResponse
@foreach (var token in Utilities.SplitTranslationTokens("WEBFRONT_PROFILE_META_CONNECT_ALIAS"))
{
if (token.IsInterpolation)
{
switch (token.MatchValue)
{
case "action":
<span class="text-warning">@token.TranslationValue</span>
break;
case "alias":
<span class="text-white">
<color-code value="@Model.Name" allow="@ViewBag.EnableColorCodes"></color-code>
[@Model.IPAddress]
</span>
break;
}
}
else
{
<span class="text-muted">@token.MatchValue</span>
}
}

View File

@ -1,94 +1,66 @@
@model IEnumerable<SharedLibraryCore.Dtos.ProfileMeta>
@using SharedLibraryCore.Interfaces;
@model IEnumerable<IClientMeta>
@{
Layout = null;
var timeSinceLastEvent = DateTime.MinValue;
var lastHeaderEventDate = DateTime.UtcNow;
dynamic formatPenaltyInfo(SharedLibraryCore.Dtos.ProfileMeta meta)
TimeSpan timeSpanForEvent(DateTime When)
{
var penalty = meta.Value as SharedLibraryCore.Dtos.PenaltyInfo;
var timePassed = (DateTime.UtcNow - When);
var daysPassed = timePassed.TotalDays;
var minutesPassed = timePassed.TotalMinutes;
string localizationKey = meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Penalized ?
$"WEBFRONT_CLIENT_META_PENALIZED_{penalty.PenaltyTypeText.ToUpper()}" :
$"WEBFRONT_CLIENT_META_WAS_PENALIZED_{penalty.PenaltyTypeText.ToUpper()}";
string localizationMessage = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex[localizationKey];
var regexMatch = System.Text.RegularExpressions.Regex.Match(localizationMessage, @"^.*{{([^{}]+)}}.+$");
string penaltyType = regexMatch.Groups[1].Value.ToString();
var secondMatch = System.Text.RegularExpressions.Regex.Match(localizationMessage, @"\{\{.+\}\}(.+)\{0\}(.+)\{1\}");
return new
if (minutesPassed <= 60)
{
Type = meta.Type,
Match = secondMatch,
Penalty = penalty,
PenaltyType = penaltyType
};
return TimeSpan.FromMinutes(5);
}
if (minutesPassed > 60 && daysPassed <= 1)
{
return TimeSpan.FromHours(1);
}
if (daysPassed > 1 && daysPassed <= 7)
{
return TimeSpan.FromDays(1);
}
if (daysPassed > 7 && daysPassed <= 31)
{
return TimeSpan.FromDays(31);
}
if (daysPassed > 31 && daysPassed <= 365)
{
return TimeSpan.FromDays(31);
}
else
{
return TimeSpan.FromDays(365);
}
}
}
@if (Model.Count() == 0)
{
<div class="p2 text-muted profile-event-timestep">@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_NONE"]</div>
<div class="p2 text-muted profile-event-timestep">@ViewBag.Localization["WEBFRONT_CLIENT_META_NONE"]</div>
}
@foreach (var meta in Model.OrderByDescending(_meta => _meta.When))
{
@if (Math.Abs((meta.When - timeSinceLastEvent).TotalDays) >= 1)
@if ((lastHeaderEventDate - meta.When) > timeSpanForEvent(lastHeaderEventDate))
{
<div class="p2 text-white profile-event-timestep">
<span class="text-primary">&mdash;</span>
<span>@SharedLibraryCore.Utilities.GetTimePassed(meta.When, true)</span>
<span>@meta.When.HumanizeForCurrentCulture()</span>
</div>
timeSinceLastEvent = meta.When;
lastHeaderEventDate = meta.When;
}
@switch (meta.Type)
{
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"]"> <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">
@{ var penaltyInfo = formatPenaltyInfo(meta); }
@if (meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Penalized)
{
<span class="penalties-color-@penaltyInfo.Penalty.PenaltyTypeText.ToLower()">@penaltyInfo.PenaltyType</span>
<span>@penaltyInfo.Match.Groups[1].ToString()</span> <!-- by -->
<span class="text-highlight">
<!-- punisher -->
<a class="link-inverse" href="@penaltyInfo.Penalty.OffenderId">
<color-code value="@penaltyInfo.Penalty.OffenderName" allow="@ViewBag.EnableColorCodes"></color-code>
</a>
</span>
<span>@penaltyInfo.Match.Groups[2].ToString()</span> <!-- for -->
<span class="@(ViewBag.Authorized ? "automated-penalty-info-detailed" : "")} text-white"
data-penalty-id="@penaltyInfo.Penalty.Id"><color-code value="@penaltyInfo.Penalty.Offense" allow="@ViewBag.EnableColorCodes"></color-code> @(ViewBag.Authorized ? penaltyInfo.Penalty.AdditionalPenaltyInformation : "")</span>
}
@if (meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.ReceivedPenalty)
{
<span class="penalties-color-@penaltyInfo.Penalty.PenaltyTypeText.ToLower()">@penaltyInfo.PenaltyType</span> <!-- actioned -->
<span>@penaltyInfo.Match.Groups[1].ToString()</span> <!-- by -->
<span class="text-highlight">
<a class="link-inverse" href="@penaltyInfo.Penalty.PunisherId">
<color-code value="@penaltyInfo.Penalty.PunisherName" allow="@ViewBag.EnableColorCodes"></color-code>
</a> <!-- punisher -->
</span>
<span>@penaltyInfo.Match.Groups[2]</span>
<span class="@(ViewBag.Authorized ? "automated-penalty-info-detailed" : "") text-white"
data-penalty-id="@penaltyInfo.Penalty.Id">
<color-code value="@penaltyInfo.Penalty.Offense" allow="@ViewBag.EnableColorCodes"></color-code> @(ViewBag.Authorized ? penaltyInfo.Penalty.AdditionalPenaltyInformation : "")
</span>
}
</div>
break;
}
}
<div class="profile-meta-entry loader-data-time" data-time="@meta.When.ToFileTimeUtc()" title="@Utilities.FormatExt(ViewBag.Localization["WEBFRONT_PROFILE_META_DATE_OCCURRED"], meta.When.ToString())">
<partial name="~/Views/Client/Profile/Meta/_@(meta.GetType().Name).cshtml" model="meta" />
</div>
}

View File

@ -1,4 +1,5 @@
@using SharedLibraryCore
@using WebfrontCore
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, SharedLibraryCore
@addTagHelper *, SharedLibraryCore
@addTagHelper *, WebfrontCore

View File

@ -64,20 +64,20 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BuildBundlerMinifier" Version="3.2.435" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="BuildWebCompiler" Version="1.12.405" />
<PackageReference Include="FluentValidation.AspNetCore" Version="8.6.2" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.0.96" />
<PackageReference Include="FluentValidation.AspNetCore" Version="9.1.2" />
<PackageReference Include="Microsoft.Web.LibraryManager.Build" Version="2.1.76" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.3" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.7" />
</ItemGroup>
<ItemGroup>
<Folder Include="wwwroot\lib\canvas.js\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Plugins\Web\StatsWeb\StatsWeb.csproj" />
<ProjectReference Include="..\SharedLibraryCore\SharedLibraryCore.csproj" />

View File

@ -1,7 +1,10 @@
[
[
{
"outputFile": "wwwroot/css/global.css",
"inputFile": "wwwroot/css/src/main.scss",
"sourceMap": false
"inputFile": "wwwroot/css/src/main.scss"
},
{
"outputFile": "wwwroot/css/src/profile.css",
"inputFile": "wwwroot/css/src/profile.scss"
}
]

View File

@ -1,5 +1,4 @@
@import 'bootstrap-custom.scss';
@import 'profile.scss';
@import 'profile.scss';
$icon-font-path: '/font/' !default;
@import '../../lib/open-iconic/font/css/open-iconic-bootstrap.scss';
@ -195,7 +194,7 @@ form *, select {
font-size: 1rem;
}
.client-message, .automated-penalty-info-detailed, .oi {
.oi {
cursor: pointer;
}

View File

@ -1,4 +1,6 @@
.level-bgcolor-console {
@import 'bootstrap-custom.scss';
.level-bgcolor-console {
background-color: grey;
}
@ -194,3 +196,8 @@
#profile_events span {
word-break: break-all;
}
#filter_meta_container .nav-link:hover {
background-color: $dark;
color: $white !important;
}

View File

@ -5,12 +5,14 @@ let startAt = null;
let isLoaderLoading = false;
let loadUri = '';
let loaderResponseId = '';
let additionalParams = [];
function initLoader(location, loaderId, count = 10, start = count) {
function initLoader(location, loaderId, count = 10, start = count, additional) {
loadUri = location;
loaderResponseId = loaderId;
loadCount = count;
loaderOffset = start;
additionalParams = additional;
setupListeners();
}
@ -21,7 +23,13 @@ function loadMoreItems() {
showLoader();
isLoaderLoading = true;
$.get(loadUri, { offset: loaderOffset, count: loadCount, startAt: startAt })
let params = { offset: loaderOffset, count: loadCount, startAt: startAt };
for (i = 0; i < additionalParams.length; i++) {
let param = additionalParams[i];
params[param.name] = param.value;
}
$.get(loadUri, params)
.done(function (response) {
$(loaderResponseId).append(response);
if (response.trim().length === 0) {

View File

@ -11,7 +11,15 @@
});
/* set the end time for initial event query */
startAt = $('#profile_events').children().last().data('time');
startAt = $('.loader-data-time').last().data('time');
$('#filter_meta_container_button').click(function () {
$('#filter_meta_container').hide();
$('#filter_meta_container').removeClass('d-none');
$('#filter_meta_container').addClass('d-block');
$('#filter_meta_container').slideDown();
});
/*
* load context of chat
@ -20,6 +28,14 @@
$(document).on('click', '.client-message', function (e) {
showLoader();
const location = $(this);
$('.client-message-prefix').removeClass('oi-chevron-bottom');
$('.client-message-prefix').removeClass('oi-chevron-right');
$('.client-message-prefix').addClass('oi-chevron-right');
$(this).children().filter('.client-message-prefix').removeClass('oi-chevron-right');
$(this).children().filter('.client-message-prefix').addClass('oi-chevron-bottom');
$.get('/Stats/GetMessageAsync', {
'serverId': $(this).data('serverid'),
'when': $(this).data('when')