diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 7d0943ff0..9cdb4dc91 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -409,7 +409,7 @@ namespace IW4MAdmin.Application Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_LAST_MAP"], Value = lastMapMeta.Value, Show = true, - Type = ProfileMeta.MetaType.Information + Type = ProfileMeta.MetaType.Information, }); } @@ -433,8 +433,10 @@ namespace IW4MAdmin.Application { Id = client.ClientId, Key = $"{Utilities.CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]} {Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PLAYER"]}", - Value = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0"), + Value = Math.Round(client.TotalConnectionTime / 3600.0, 1).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Show = true, + Column = 1, + Order = 0, Type = ProfileMeta.MetaType.Information }); @@ -444,6 +446,8 @@ namespace IW4MAdmin.Application Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_FSEEN"], Value = Utilities.GetTimePassed(client.FirstConnection, false), Show = true, + Column = 1, + Order = 1, Type = ProfileMeta.MetaType.Information }); @@ -453,16 +457,19 @@ namespace IW4MAdmin.Application Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_LSEEN"], Value = Utilities.GetTimePassed(client.LastConnection, false), Show = true, + Column = 1, + Order = 2, Type = ProfileMeta.MetaType.Information }); metaList.Add(new ProfileMeta() - { Id = client.ClientId, Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_CONNECTIONS"], - Value = client.Connections, + Value = client.Connections.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Show = true, + Column = 1, + Order = 3, Type = ProfileMeta.MetaType.Information }); @@ -471,6 +478,8 @@ namespace IW4MAdmin.Application Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_MASKED"], Value = client.Masked ? Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_TRUE"] : Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_FALSE"], Sensitive = true, + Column = 1, + Order = 4, Type = ProfileMeta.MetaType.Information }); diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index 892af0967..0a9722827 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -150,37 +150,49 @@ namespace IW4MAdmin.Plugins.Stats new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"], - Value = "#" + await StatManager.GetClientOverallRanking(clientId), + Value = "#" + (await StatManager.GetClientOverallRanking(clientId)).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 0, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"], - Value = kills, + Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 1, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"], - Value = deaths, + Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 2, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"], - Value = kdr, + Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 3, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"], - Value = performance, + Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 4, Type = ProfileMeta.MetaType.Information }, new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"], - Value = spm, + Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 0, + Order = 5, Type = ProfileMeta.MetaType.Information } }; @@ -236,45 +248,57 @@ namespace IW4MAdmin.Plugins.Stats { new ProfileMeta() { - Key = "Chest Ratio", - Value = chestRatio, + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 1", + Value = chestRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 0, Sensitive = true }, new ProfileMeta() { - Key = "Abdomen Ratio", - Value = abdomenRatio, + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 2", + Value = abdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 1, Sensitive = true }, new ProfileMeta() { - Key = "Chest To Abdomen Ratio", - Value = chestAbdomenRatio, + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 3", + Value = chestAbdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 2, Sensitive = true }, new ProfileMeta() { - Key = "Headshot Ratio", - Value = headRatio, + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 4", + Value = headRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 3, Sensitive = true }, new ProfileMeta() { - Key = "Hit Offset Average", + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 5", // todo: make sure this is wrapped somewhere else Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°", Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 4, Sensitive = true }, new ProfileMeta() { - Key = "Max Strain", - Value = Math.Round(maxStrain, 3), + Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 6", + Value = Math.Round(maxStrain, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), Type = ProfileMeta.MetaType.Information, + Column = 2, + Order = 5, Sensitive = true }, }; @@ -291,8 +315,11 @@ namespace IW4MAdmin.Plugins.Stats new ProfileMeta() { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"], - Value = await ctx.Set() - .CountAsync(_message => _message.ClientId == clientId), + Value = (await ctx.Set() + .CountAsync(_message => _message.ClientId == clientId)) + .ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), + Column = 1, + Order= 4, Type = ProfileMeta.MetaType.Information } }; @@ -335,7 +362,7 @@ namespace IW4MAdmin.Plugins.Stats using (var ctx = new DatabaseContext(disableTracking: true)) { long kills = await ctx.Set().Where(s => s.Active).SumAsync(s => s.TotalKills); - return kills.ToString("#,##0"); + return kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } } @@ -344,7 +371,7 @@ namespace IW4MAdmin.Plugins.Stats using (var ctx = new DatabaseContext(disableTracking: true)) { long playTime = await ctx.Set().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); - return (playTime / 3600.0).ToString("#,##0"); + return (playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } } diff --git a/SharedLibraryCore/Services/MetaService.cs b/SharedLibraryCore/Services/MetaService.cs index 96f81c1be..fee9a77e4 100644 --- a/SharedLibraryCore/Services/MetaService.cs +++ b/SharedLibraryCore/Services/MetaService.cs @@ -95,6 +95,51 @@ namespace SharedLibraryCore.Services if (count == 1) { + var table = new List>(); + var metaWithColumn = meta + .Where(_meta => _meta.Column != null); + + var columnGrouping = metaWithColumn + .GroupBy(_meta => _meta.Column); + + var metaToSort = meta.Except(metaWithColumn).ToList(); + + foreach (var metaItem in columnGrouping) + { + table.Add(new List(metaItem)); + } + + while (metaToSort.Count > 0) + { + var sortingMeta = metaToSort.First(); + + int indexOfSmallestColumn() + { + int index = 0; + int smallestColumnSize = int.MaxValue; + for (int i = 0; i < table.Count; i++) + { + if (table[i].Count < smallestColumnSize) + { + smallestColumnSize = table[i].Count; + index = i; + } + } + return index; + } + + int columnIndex = indexOfSmallestColumn(); + + sortingMeta.Column = columnIndex; + sortingMeta.Order = columnGrouping + .First(_group => _group.Key == columnIndex) + .Count(); + + table[columnIndex].Add(sortingMeta); + + metaToSort.Remove(sortingMeta); + } + return meta; } diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index 1c691d9de..cb7d9e43d 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -7,7 +7,9 @@ bool isTempBanned = Model.ActivePenaltyType == "TempBan"; var informationMeta = Model.Meta .Where(_meta => _meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Information) - .ToList(); + .OrderBy(_meta => _meta.Order) + .GroupBy(_meta => _meta.Column) + .OrderBy(_grouping => _grouping.Key); }
@@ -79,35 +81,18 @@
-
- @for (int i = 0; i < informationMeta.Count; i += 3) - { -
- @informationMeta[i].Value - @informationMeta[i].Key -
- } -
- -
- @for (int i = 1; i < informationMeta.Count; i += 3) - { -
- @informationMeta[i].Value - @informationMeta[i].Key -
- } -
- -
- @for (int i = 2; i < informationMeta.Count; i += 3) - { -
- @informationMeta[i].Value - @informationMeta[i].Key -
- } -
+ @foreach (var metaColumn in informationMeta) + { +
+ @foreach (var meta in metaColumn) + { +
+ @meta.Value + @meta.Key +
+ } +
+ }
diff --git a/WebfrontCore/Views/Penalty/_Penalty.cshtml b/WebfrontCore/Views/Penalty/_Penalty.cshtml index b92117678..f2ed3f95f 100644 --- a/WebfrontCore/Views/Penalty/_Penalty.cshtml +++ b/WebfrontCore/Views/Penalty/_Penalty.cshtml @@ -13,7 +13,7 @@ - @loc["WEBFRONT_PENALTY_TEMPLATE_PenaltyType"] + @loc["WEBFRONT_PENALTY_TEMPLATE_TYPE"] @Model.PenaltyType diff --git a/WebfrontCore/Views/Shared/Components/ProfileMetaList/_List.cshtml b/WebfrontCore/Views/Shared/Components/ProfileMetaList/_List.cshtml index 7cfb511eb..6e34194fc 100644 --- a/WebfrontCore/Views/Shared/Components/ProfileMetaList/_List.cshtml +++ b/WebfrontCore/Views/Shared/Components/ProfileMetaList/_List.cshtml @@ -2,6 +2,8 @@ @{ Layout = null; + var timeSinceLastEvent = DateTime.MinValue; + string formatPenalty(SharedLibraryCore.Dtos.ProfileMeta meta) { var penalty = meta.Value as SharedLibraryCore.Dtos.PenaltyInfo; @@ -11,7 +13,7 @@ $"WEBFRONT_CLIENT_META_WAS_PENALIZED_{penalty.PenaltyType.ToUpper()}"; string localizationMessage = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex[localizationKey]; - var regexMatch = System.Text.RegularExpressions.Regex.Match(localizationMessage, @"^{{([^{}]+)}}.+$"); + var regexMatch = System.Text.RegularExpressions.Regex.Match(localizationMessage, @"^.*{{([^{}]+)}}.+$"); string penaltyType = regexMatch.Groups[1].Value.ToString(); localizationMessage = localizationMessage.Replace(penaltyType, $"{penaltyType}"); @@ -24,28 +26,30 @@ .Replace("}", "") : string.Format(localizationMessage, $"{penalty.PunisherName}", - $"{penalty.Offense}", + $"{(ViewBag.Authorized && !string.IsNullOrEmpty(penalty.AutomatedOffense) ? $"{penalty.Offense} ({penalty.AutomatedOffense})" : penalty.Offense)}", penalty.Offense) .Replace("{", "") .Replace("}", ""); } } -@if (Model.Count > 0) -{ -
- - @SharedLibraryCore.Utilities.GetTimePassed(Model.First().When, true) -
-} - @if (Model.Count == 0) { -
@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_NONE"]
+
@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_NONE"]
} @foreach (var meta in Model.OrderByDescending(_meta => _meta.When)) { + @if (Math.Abs((meta.When - timeSinceLastEvent).TotalDays) >= 1) + { +
+ + @SharedLibraryCore.Utilities.GetTimePassed(meta.When, true) +
+ + timeSinceLastEvent = meta.When; + } + @switch (meta.Type) { case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ChatMessage: diff --git a/WebfrontCore/wwwroot/js/loader.js b/WebfrontCore/wwwroot/js/loader.js index f5dcf2559..b3c3e2bc9 100644 --- a/WebfrontCore/wwwroot/js/loader.js +++ b/WebfrontCore/wwwroot/js/loader.js @@ -1,5 +1,6 @@ let loaderOffset = 10; let loadCount = 10; +let loaderReachedEnd = false; let startAt = null; let isLoaderLoading = false; let loadUri = ''; @@ -14,7 +15,7 @@ function initLoader(location, loaderId, count = 10, start = count) { } function loadMoreItems() { - if (isLoaderLoading) { + if (isLoaderLoading || loaderReachedEnd) { return false; } @@ -25,6 +26,8 @@ function loadMoreItems() { $(loaderResponseId).append(response); if (response.trim().length === 0) { staleLoader(); + loaderReachedEnd = true; + $('.loader-load-more').addClass('disabled'); } $(document).trigger("loaderFinished", response); startAt = $(response).filter('.loader-data-time').last().data('time'); @@ -66,7 +69,7 @@ function setupListeners() { $window .off('scroll', ScrollHandler) .on('scroll', ScrollHandler); - $('.loader-load-more').click(function (e) { + $('.loader-load-more:not(.disabled)').click(function (e) { if (!isLoaderLoading) { loadMoreItems(); }