refine webfront pages

finish refactor of penalty information/profile
optimize pull penalty query
start impl of quick message mapping
This commit is contained in:
RaidMax 2019-03-31 19:56:31 -05:00
parent 9393b35c39
commit 6f80f1edbb
23 changed files with 253 additions and 283 deletions

View File

@ -250,10 +250,10 @@ namespace IW4MAdmin.Application
ConfigHandler.Set((ApplicationConfiguration)new ApplicationConfiguration().Generate());
var newConfig = ConfigHandler.Configuration();
newConfig.AutoMessagePeriod = defaultConfig.AutoMessagePeriod;
newConfig.AutoMessages = defaultConfig.AutoMessages;
newConfig.GlobalRules = defaultConfig.GlobalRules;
newConfig.Maps = defaultConfig.Maps;
newConfig.QuickMessages = defaultConfig.QuickMessages;
if (newConfig.Servers == null)
{
@ -493,27 +493,15 @@ namespace IW4MAdmin.Application
return new List<ProfileMeta>();
}
var penalties = await GetPenaltyService().GetAllClientPenaltiesAsync(clientId, count, offset, startAt);
var penalties = await GetPenaltyService().GetClientPenaltyForMetaAsync(clientId, count, offset, startAt);
return penalties.Select(_penalty => new ProfileMeta()
{
Id = _penalty.PenaltyId,
Id = _penalty.Id,
Type = _penalty.PunisherId == clientId ? ProfileMeta.MetaType.Penalized : ProfileMeta.MetaType.ReceivedPenalty,
Value = new PenaltyInfo
{
Id = _penalty.PenaltyId,
OffenderName = _penalty.Offender.Name,
OffenderId = _penalty.OffenderId,
PunisherName = _penalty.Punisher.Name,
PunisherId = _penalty.PunisherId,
Offense = _penalty.Offense,
PenaltyType = _penalty.Type.ToString(),
TimeRemaining = _penalty.Expires.HasValue ? (DateTime.Now > _penalty.Expires ? "" : _penalty.Expires.ToString()) : DateTime.MaxValue.ToString(),
AutomatedOffense = _penalty.AutomatedOffense,
Expired = _penalty.Expires.HasValue && _penalty.Expires <= DateTime.UtcNow
},
When = _penalty.When,
Sensitive = _penalty.Type == Penalty.PenaltyType.Flag
Value = _penalty,
When = _penalty.TimePunished,
Sensitive = _penalty.Sensitive
})
.ToList();
}

View File

@ -16,6 +16,51 @@
"Keep grenade launcher use to a minimum",
"Balance teams at ALL times"
],
"QuickMessages": [
{
"Game": "IW4",
"Messages": {
"QUICKMESSAGE_AREA_SECURE": "Area secure!",
"QUICKMESSAGE_ARE_YOU_CRAZY": "Are you crazy?",
"QUICKMESSAGE_ATTACK_LEFT_FLANK": "Attack left flank!",
"QUICKMESSAGE_ATTACK_RIGHT_FLANK": "Attack right flank!",
"QUICKMESSAGE_COME_ON": "Come on.",
"QUICKMESSAGE_ENEMIES_SPOTTED": "Multiple contacts!",
"QUICKMESSAGE_ENEMY_DOWN": "Enemy down!",
"QUICKMESSAGE_ENEMY_GRENADE": "Enemy grenade!",
"QUICKMESSAGE_ENEMY_SPOTTED": "Contact!",
"QUICKMESSAGE_FALL_BACK": "Fall back!",
"QUICKMESSAGE_FOLLOW_ME": "On me!",
"QUICKMESSAGE_GREAT_SHOT": "Nice shot!",
"QUICKMESSAGE_GRENADE": "Grenade!",
"QUICKMESSAGE_HOLD_THIS_POSITION": "Hold this position!",
"QUICKMESSAGE_HOLD_YOUR_FIRE": "Hold your fire!",
"QUICKMESSAGE_IM_IN_POSITION": "In position.",
"QUICKMESSAGE_IM_ON_MY_WAY": "Moving.",
"QUICKMESSAGE_MOVE_IN": "Move in!",
"QUICKMESSAGE_NEED_REINFORCEMENTS": "Need reinforcements!",
"QUICKMESSAGE_NO_SIR": "Negative.",
"QUICKMESSAGE_ON_MY_WAY": "On my way.",
"QUICKMESSAGE_REGROUP": "Regroup!",
"QUICKMESSAGE_SNIPER": "Sniper!",
"QUICKMESSAGE_SORRY": "Sorry.",
"QUICKMESSAGE_SQUAD_ATTACK_LEFT_FLANK": "Squad, attack left flank!",
"QUICKMESSAGE_SQUAD_ATTACK_RIGHT_FLANK": "Squad, attack right flank!",
"QUICKMESSAGE_SQUAD_HOLD_THIS_POSITION": "Squad, hold this position!",
"QUICKMESSAGE_SQUAD_REGROUP": "Squad, regroup!",
"QUICKMESSAGE_SQUAD_STICK_TOGETHER": "Squad, stick together!",
"QUICKMESSAGE_STICK_TOGETHER": "Stick together!",
"QUICKMESSAGE_SUPPRESSING_FIRE": "Base of fire!",
"QUICKMESSAGE_TOOK_LONG_ENOUGH": "Took long enough!",
"QUICKMESSAGE_TOOK_YOU_LONG_ENOUGH": "Took you long enough!",
"QUICKMESSAGE_WATCH_SIX": "Watch your six!",
"QUICKMESSAGE_YES_SIR": "Roger.",
"QUICKMESSAGE_YOURE_CRAZY": "You're crazy!",
"QUICKMESSAGE_YOURE_NUTS": "You're nuts!",
"QUICKMESSAGE_YOU_OUTTA_YOUR_MIND": "You outta your mind?"
}
}
],
"Maps": [
{
"Game": "IW3",

View File

@ -89,16 +89,30 @@ namespace IW4MAdmin.Plugins.Stats.Web.Controllers
{
using (var ctx = new SharedLibraryCore.Database.DatabaseContext(true))
{
var penaltyInfo = await ctx.Set<Models.EFACSnapshot>()
.Where(s => s.ClientId == clientId)
int linkId = await ctx.Clients
.Where(_client => _client.ClientId == clientId)
.Select(_client => _client.AliasLinkId)
.FirstOrDefaultAsync();
var clientIds = await ctx.Clients.Where(_client => _client.AliasLinkId == linkId)
.Select(_client => _client.ClientId)
.ToListAsync();
var iqPenaltyInfo = ctx.Set<Models.EFACSnapshot>()
.Where(s => clientIds.Contains(s.ClientId))
.Include(s => s.LastStrainAngle)
.Include(s => s.HitOrigin)
.Include(s => s.HitDestination)
.Include(s => s.CurrentViewAngle)
.Include(s => s.PredictedViewAngles)
.OrderBy(s => s.When)
.ThenBy(s => s.Hits)
.ToListAsync();
.ThenBy(s => s.Hits);
#if DEBUG == true
var sql = iqPenaltyInfo.ToSql();
#endif
var penaltyInfo = await iqPenaltyInfo.ToListAsync();
return View("_PenaltyInfo", penaltyInfo);
}

View File

@ -3,10 +3,12 @@
Layout = null;
}
<div class="client-message-context bg-dark p-2 mt-2 mb-2 border-top border-bottom">
<h5>@Model.First().Time.ToString()</h5>
@foreach (var message in Model)
{
<span class="text-white">@Html.ActionLink(@message.Name, "ProfileAsync", "Client", new { id = message.ClientId})</span><span> &mdash; @message.Message</span><br />
}
<div class="client-message-context">
<h5 class="bg-primary pt-2 pb-2 pl-3 mb-0 mt-2 text-white">@Model.First().Time.ToString()</h5>
<div class="bg-dark p-3 mb-2 border-bottom">
@foreach (var message in Model)
{
<span class="text-white">@message.Name</span><span> &mdash; @message.Message</span><br />
}
</div>
</div>

View File

@ -57,6 +57,7 @@ namespace SharedLibraryCore.Configuration
public List<string> AutoMessages { get; set; }
public List<string> GlobalRules { get; set; }
public List<MapConfiguration> Maps { get; set; }
public List<QuickMessageConfiguration> QuickMessages { get; set; }
public List<string> DisallowedClientNames { get; set; }
public IBaseConfiguration Generate()

View File

@ -7,10 +7,10 @@ namespace SharedLibraryCore.Configuration
{
public class DefaultConfiguration : IBaseConfiguration
{
public int AutoMessagePeriod { get; set; }
public List<string> AutoMessages { get; set; }
public List<string> GlobalRules { get; set; }
public List<MapConfiguration> Maps { get; set; }
public List<QuickMessageConfiguration> QuickMessages {get; set;}
public IBaseConfiguration Generate() => this;

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using static SharedLibraryCore.Server;
namespace SharedLibraryCore.Configuration
{
public class QuickMessageConfiguration
{
public Game Game { get; set; }
public Dictionary<string, string> Messages { get; set; }
}
}

View File

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static SharedLibraryCore.Database.Models.EFClient;
using static SharedLibraryCore.Objects.Penalty;
namespace SharedLibraryCore.Dtos
{
@ -16,13 +14,19 @@ namespace SharedLibraryCore.Dtos
public int PunisherId { get; set; }
public ulong PunisherNetworkId { get; set; }
public string PunisherIPAddress { get; set; }
public string PunisherLevel { get; set; }
public int PunisherLevelId { get; set; }
public Permission PunisherLevel { get; set; }
public string PunisherLevelText => PunisherLevel.ToLocalizedLevelName();
public string Offense { get; set; }
public string AutomatedOffense { get; set; }
public string PenaltyType { get; set; }
public string TimePunished { get; set; }
public string TimeRemaining { get; set; }
public bool Expired { get; set; }
public PenaltyType PenaltyType { get; set; }
public string PenaltyTypeText => PenaltyType.ToString();
public DateTime TimePunished { get; set; }
public string TimePunishedString => Utilities.GetTimePassed(TimePunished, true);
public string TimeRemaining => DateTime.UtcNow > Expires ? "" : $"{((Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(TimePunished, true) : Utilities.TimeSpanText((Expires ?? DateTime.MaxValue) - DateTime.UtcNow))}";
public bool Expired => Expires.HasValue && Expires <= DateTime.UtcNow;
public DateTime? Expires { get; set; }
public override bool Sensitive => PenaltyType == PenaltyType.Flag;
public bool IsEvade { get; set; }
public string AdditionalPenaltyInformation => $"{(!string.IsNullOrEmpty(AutomatedOffense) ? $" ({AutomatedOffense})" : "")}{(IsEvade ? $" ({Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PENALTY_EVADE"]})" : "")}";
}
}

View File

@ -22,6 +22,8 @@ namespace SharedLibraryCore.Dtos
public List<ProfileMeta> Meta { get; set; }
public bool Online { get; set; }
public string TimeOnline { get; set; }
public DateTime LastConnection { get; set; }
public string LastConnectionText => Utilities.GetTimePassed(LastConnection, true);
public IDictionary<int, long> LinkedAccounts { get; set; }
}
}

View File

@ -3,8 +3,8 @@ namespace SharedLibraryCore.Dtos
{
public class SharedInfo
{
public bool Sensitive { get; set; }
public virtual bool Sensitive { get; set; }
public bool Show { get; set; } = true;
public int Id {get;set;}
}
public int Id { get; set; }
}
}

View File

@ -130,22 +130,6 @@ namespace SharedLibraryCore.Services
throw new NotImplementedException();
}
public async Task<IList<EFPenalty>> GetRecentPenalties(int count, int offset, Penalty.PenaltyType showOnly = Penalty.PenaltyType.Any)
{
using (var context = new DatabaseContext(true))
{
return await context.Penalties
.Include(p => p.Offender.CurrentAlias)
.Include(p => p.Punisher.CurrentAlias)
.Where(p => showOnly == Penalty.PenaltyType.Any ? p.Type != Penalty.PenaltyType.Any : p.Type == showOnly)
.Where(p => p.Active)
.OrderByDescending(p => p.When)
.Skip(offset)
.Take(count)
.ToListAsync();
}
}
public async Task<IList<EFPenalty>> GetClientPenaltiesAsync(int clientId)
{
using (var context = new DatabaseContext(true))
@ -159,136 +143,79 @@ namespace SharedLibraryCore.Services
}
}
public async Task<IList<EFPenalty>> GetAllClientPenaltiesAsync(int clientId, int count, int offset, DateTime? startAt)
public async Task<IList<PenaltyInfo>> GetRecentPenalties(int count, int offset, Penalty.PenaltyType showOnly = Penalty.PenaltyType.Any)
{
using (var ctx = new DatabaseContext(true))
using (var context = new DatabaseContext(true))
{
var iqPenalties = ctx.Penalties.AsNoTracking()
.Include(_penalty => _penalty.Offender.CurrentAlias)
.Include(_penalty => _penalty.Punisher.CurrentAlias)
.Where(_penalty => _penalty.Active)
.Where(_penalty => _penalty.OffenderId == clientId || _penalty.PunisherId == clientId)
.Where(_penalty => _penalty.When < startAt)
.OrderByDescending(_penalty => _penalty.When)
var iqPenalties = context.Penalties
.Where(p => showOnly == Penalty.PenaltyType.Any ? p.Type != Penalty.PenaltyType.Any : p.Type == showOnly)
.Where(p => p.Active)
.OrderByDescending(p => p.When)
.Skip(offset)
.Take(count);
.Take(count)
.Select(_penalty => new PenaltyInfo()
{
Id = _penalty.PenaltyId,
Offense = _penalty.Offense,
AutomatedOffense = _penalty.AutomatedOffense,
OffenderId = _penalty.OffenderId,
OffenderName = _penalty.Offender.CurrentAlias.Name,
PunisherId = _penalty.PunisherId,
PunisherName = _penalty.Punisher.CurrentAlias.Name,
PunisherLevel = _penalty.Punisher.Level,
PenaltyType = _penalty.Type,
Expires = _penalty.Expires,
TimePunished = _penalty.When,
IsEvade = _penalty.IsEvadedOffense
});
#if DEBUG == true
var querySql = iqPenalties.ToSql();
#endif
return await iqPenalties.ToListAsync();
}
}
/// <summary>
/// Get a read-only copy of client penalties
/// retrieves penalty information for meta service
/// </summary>
/// <param name="clientId"></param>
/// <param name="victim">Retreive penalties for clients receiving penalties, other wise given</param>
/// <param name="clientId">database id of the client</param>
/// <param name="count">how many items to retrieve</param>
/// <param name="offset">not used</param>
/// <param name="startAt">retreive penalties older than this</param>
/// <returns></returns>
public async Task<List<ProfileMeta>> ReadGetClientPenaltiesAsync(int clientId, bool victim = true)
public async Task<IList<PenaltyInfo>> GetClientPenaltyForMetaAsync(int clientId, int count, int offset, DateTime? startAt)
{
using (var context = new DatabaseContext(true))
using (var ctx = new DatabaseContext(true))
{
// todo: clean this up
if (victim)
{
var now = DateTime.UtcNow;
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
where penalty.OffenderId == clientId
join victimClient in context.Clients.AsNoTracking()
on penalty.OffenderId equals victimClient.ClientId
join victimAlias in context.Aliases.AsNoTracking()
on victimClient.CurrentAliasId equals victimAlias.AliasId
join punisherClient in context.Clients.AsNoTracking()
on penalty.PunisherId equals punisherClient.ClientId
join punisherAlias in context.Aliases.AsNoTracking()
on punisherClient.CurrentAliasId equals punisherAlias.AliasId
//orderby penalty.When descending
select new ProfileMeta()
{
Key = "Event.Penalty",
Value = new PenaltyInfo
{
Id = penalty.PenaltyId,
OffenderName = victimAlias.Name,
OffenderId = victimClient.ClientId,
PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId,
Offense = penalty.Offense,
PenaltyType = penalty.Type.ToString(),
TimeRemaining = penalty.Expires.HasValue ? (now > penalty.Expires ? "" : penalty.Expires.ToString()) : DateTime.MaxValue.ToString(),
AutomatedOffense = penalty.AutomatedOffense,
Expired = penalty.Expires.HasValue && penalty.Expires <= DateTime.UtcNow
},
When = penalty.When,
Sensitive = penalty.Type == Penalty.PenaltyType.Flag
};
// fixme: is this good and fast?
var list = await iqPenalties.ToListAsync();
list.ForEach(p =>
var iqPenalties = ctx.Penalties.AsNoTracking()
.Where(_penalty => _penalty.Active)
.Where(_penalty => _penalty.OffenderId == clientId || _penalty.PunisherId == clientId)
.Where(_penalty => _penalty.When < startAt)
.OrderByDescending(_penalty => _penalty.When)
.Skip(offset)
.Take(count)
.Select(_penalty => new PenaltyInfo()
{
// todo: why does this have to be done?
if (((PenaltyInfo)p.Value).PenaltyType.Length < 2)
{
((PenaltyInfo)p.Value).PenaltyType = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).PenaltyType)).ToString();
}
var pi = ((PenaltyInfo)p.Value);
if (pi.TimeRemaining?.Length > 0)
{
pi.TimeRemaining = (DateTime.Parse(((PenaltyInfo)p.Value).TimeRemaining) - now).TimeSpanText();
if (!pi.Expired)
{
pi.TimeRemaining = $"{pi.TimeRemaining} {Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]}";
}
}
});
return list;
}
else
{
var iqPenalties = from penalty in context.Penalties.AsNoTracking()
where penalty.PunisherId == clientId
join victimClient in context.Clients.AsNoTracking()
on penalty.OffenderId equals victimClient.ClientId
join victimAlias in context.Aliases
on victimClient.CurrentAliasId equals victimAlias.AliasId
join punisherClient in context.Clients
on penalty.PunisherId equals punisherClient.ClientId
join punisherAlias in context.Aliases
on punisherClient.CurrentAliasId equals punisherAlias.AliasId
//orderby penalty.When descending
select new ProfileMeta()
{
Key = "Event.Penalty",
Value = new PenaltyInfo
{
Id = penalty.PenaltyId,
OffenderName = victimAlias.Name,
OffenderId = victimClient.ClientId,
PunisherName = punisherAlias.Name,
PunisherId = penalty.PunisherId,
Offense = penalty.Offense,
PenaltyType = penalty.Type.ToString(),
AutomatedOffense = penalty.AutomatedOffense
},
When = penalty.When,
Sensitive = penalty.Type == Penalty.PenaltyType.Flag
};
// fixme: is this good and fast?
var list = await iqPenalties.ToListAsync();
list.ForEach(p =>
{
// todo: why does this have to be done?
if (((PenaltyInfo)p.Value).PenaltyType.Length < 2)
{
((PenaltyInfo)p.Value).PenaltyType = ((Penalty.PenaltyType)Convert.ToInt32(((PenaltyInfo)p.Value).PenaltyType)).ToString();
}
Id = _penalty.PenaltyId,
Offense = _penalty.Offense,
AutomatedOffense = _penalty.AutomatedOffense,
OffenderId = _penalty.OffenderId,
OffenderName = _penalty.Offender.CurrentAlias.Name,
PunisherId = _penalty.PunisherId,
PunisherName = _penalty.Punisher.CurrentAlias.Name,
PunisherLevel = _penalty.Punisher.Level,
PenaltyType = _penalty.Type,
Expires = _penalty.Expires,
TimePunished = _penalty.When,
IsEvade = _penalty.IsEvadedOffense
});
return list;
}
#if DEBUG == true
var querySql = iqPenalties.ToSql();
#endif
return await iqPenalties.ToListAsync();
}
}

View File

@ -596,19 +596,6 @@ namespace SharedLibraryCore
return response;
}
public static int ClientIdFromString(String[] lineSplit, int cIDPos)
{
int pID = -2; // apparently falling = -1 cID so i can't use it now
int.TryParse(lineSplit[cIDPos].Trim(), out pID);
if (pID == -1) // special case similar to mod_suicide
{
int.TryParse(lineSplit[2], out pID);
}
return pID;
}
public static Dictionary<string, string> DictionaryFromKeyValue(this string eventLine)
{
string[] values = eventLine.Substring(1).Split('\\');

View File

@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
@ -24,10 +25,14 @@ namespace WebfrontCore.Controllers
try
{
#if DEBUG == true
var client = Utilities.IW4MAdminClient();
bool loginSuccess = true;
#else
var client = Manager.GetPrivilegedClients()[clientId];
bool loginSuccess = Manager.TokenAuthenticator.AuthorizeToken(client.NetworkId, password) ||
(await Task.FromResult(SharedLibraryCore.Helpers.Hashing.Hash(password, client.PasswordSalt)))[0] == client.Password;
#endif
if (loginSuccess)
{

View File

@ -119,7 +119,7 @@ namespace WebfrontCore.Controllers
Name = c.Name,
Level = c.Level.ToLocalizedLevelName(),
LevelInt = (int)c.Level,
// todo: add back last seen for search
LastConnection = c.LastConnection,
ClientId = c.ClientId
})
.ToList();

View File

@ -10,12 +10,13 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebfrontCore.ViewComponents;
using static SharedLibraryCore.Objects.Penalty;
namespace WebfrontCore.Controllers
{
public class PenaltyController : BaseController
{
public IActionResult List(int showOnly = (int)SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
public IActionResult List(PenaltyType showOnly = PenaltyType.Any)
{
ViewBag.Description = "List of all the recent penalties (bans, kicks, warnings) on IW4MAdmin";
ViewBag.Title = Localization["WEBFRONT_PENALTY_TITLE"];
@ -24,12 +25,12 @@ namespace WebfrontCore.Controllers
return View((SharedLibraryCore.Objects.Penalty.PenaltyType)showOnly);
}
public async Task<IActionResult> ListAsync(int offset = 0, int showOnly = (int)SharedLibraryCore.Objects.Penalty.PenaltyType.Any)
public async Task<IActionResult> ListAsync(int offset = 0, PenaltyType showOnly = PenaltyType.Any)
{
return await Task.FromResult(View("_List", new ViewModels.PenaltyFilterInfo()
{
Offset = offset,
ShowOnly = (SharedLibraryCore.Objects.Penalty.PenaltyType)showOnly
ShowOnly = showOnly
}));
}
@ -47,7 +48,7 @@ namespace WebfrontCore.Controllers
// todo: this seems like it's pulling unnecessary info from LINQ to entities.
var iqPenalties = ctx.Penalties
.AsNoTracking()
.Where(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active)
.Where(p => p.Type == PenaltyType.Ban && p.Active)
.OrderByDescending(_penalty => _penalty.When)
.Select(p => new PenaltyInfo()
{
@ -61,9 +62,7 @@ namespace WebfrontCore.Controllers
PunisherNetworkId = (ulong)p.Punisher.NetworkId,
PunisherName = p.Punisher.CurrentAlias.Name,
PunisherIPAddress = Authorized ? p.Punisher.CurrentAlias.IPAddress.ConvertIPtoString() : null,
PenaltyType = p.Type.ToString(),
TimePunished = p.When.ToString(),
TimeRemaining = null,
TimePunished = p.When,
AutomatedOffense = Authorized ? p.AutomatedOffense : null,
});
#if DEBUG == true

View File

@ -1,9 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Objects;
using System;
using System.Linq;
using System.Threading.Tasks;
@ -11,42 +7,14 @@ namespace WebfrontCore.ViewComponents
{
public class PenaltyListViewComponent : ViewComponent
{
private const int PENALTY_COUNT = 15;
public async Task<IViewComponentResult> InvokeAsync(int offset, Penalty.PenaltyType showOnly)
{
string showEvadeString(EFPenalty penalty) => penalty.IsEvadedOffense == true ?
$"({Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PENALTY_EVADE"]}) " : "";
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(PENALTY_COUNT, offset, showOnly);
penalties = User.Identity.IsAuthenticated ? penalties : penalties.Where(p => !p.Sensitive).ToList();
var penalties = await Program.Manager.GetPenaltyService().GetRecentPenalties(12, offset, showOnly);
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
{
Id = p.PenaltyId,
OffenderId = p.OffenderId,
OffenderName = p.Offender.Name,
PunisherId = p.PunisherId,
PunisherName = p.Punisher.Name,
PunisherLevel = p.Punisher.Level.ToLocalizedLevelName(),
PunisherLevelId = (int)p.Punisher.Level,
#if DEBUG
Offense = !string.IsNullOrEmpty(p.AutomatedOffense) ? p.AutomatedOffense : p.Offense,
#else
Offense = (User.Identity.IsAuthenticated && !string.IsNullOrEmpty(p.AutomatedOffense)) ?
$"{showEvadeString(p)}{p.AutomatedOffense}" :
$"{showEvadeString(p)}{p.Offense}",
#endif
PenaltyType = p.Type.ToString(),
TimePunished = Utilities.GetTimePassed(p.When, false),
// show time passed if ban
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : $"{((p.Expires ?? DateTime.MaxValue).Year == DateTime.MaxValue.Year ? Utilities.GetTimePassed(p.When, true) : Utilities.TimeSpanText((p.Expires ?? DateTime.MaxValue) - DateTime.UtcNow))}",
Sensitive = p.Type == Penalty.PenaltyType.Flag,
AutomatedOffense = p.AutomatedOffense
});
#if DEBUG
penaltiesDto = penaltiesDto.ToList();
#else
penaltiesDto = User.Identity.IsAuthenticated ? penaltiesDto.ToList() : penaltiesDto.Where(p => !p.Sensitive).ToList();
#endif
return View("_List", penaltiesDto);
return View("_List", penalties);
}
}
}

View File

@ -1,24 +1,40 @@
@model List<SharedLibraryCore.Dtos.PlayerInfo>
@{
@{
var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex;
}
<div class="mr-auto ml-auto col-12 col-lg-7 border-bottom">
<h4 class="pb-2 text-center ">@ViewBag.Title</h4>
<div class="row pt-2 pb-2 bg-primary">
<div class="col-5 ">@loc["WEBFRONT_PENALTY_TEMPLATE_NAME"]</div>
<div class="col-4">@loc["WEBFRONT_PROFILE_LEVEL"]</div>
<div class="col-3 text-right">@loc["WEBFRONT_PROFILE_LSEEN"]</div>
</div>
<div class="row d-none d-lg-block ">
<h4 class="pb-2 text-center col-12">@ViewBag.Title</h4>
<div class="mr-auto ml-auto col-12 col-lg-8 border-bottom">
<div class="row pt-2 pb-2 bg-primary">
<div class="col-5 ">@loc["WEBFRONT_PENALTY_TEMPLATE_NAME"]</div>
<div class="col-4">@loc["WEBFRONT_PROFILE_LEVEL"]</div>
<div class="col-3 text-right">@loc["WEBFRONT_SEARCH_LAST_CONNECTED"]</div>
</div>
@{
foreach (var client in Model)
@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-4 level-color-@client.LevelInt">@client.Level</div>
@*<div class="col-3 text-right">@client.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]</div>*@
<div class="col-3 text-right">@client.LastConnectionText</div>
</div>
}
</div>
</div>
<div class="row d-lg-none">
<div class="w-100 bg-primary text-center h3 mb-0 p-3" style="border-bottom: 1px solid #222">@ViewBag.Title</div>
@foreach (var client in Model)
{
<div class="col-5 bg-primary font-weight-bold" style="border-bottom: 1px solid #222">
<div class="p-2">@loc["WEBFRONT_PENALTY_TEMPLATE_NAME"]</div>
<div class="p-2">@loc["WEBFRONT_PROFILE_LEVEL"]</div>
<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 level-color-@client.LevelInt">@client.Level</div>
<div class="p-2 text-white-50">@client.LastConnectionText</div>
</div>
}
</div>

View File

@ -1,12 +0,0 @@
@model IEnumerable<SharedLibraryCore.Dtos.ChatInfo>
@{
Layout = null;
}
<div class="client-message-context bg-dark p-2 mt-2 mb-2 border-top border-bottom">
<h5>@Model.First().Time.ToString()</h5>
@foreach (var message in Model)
{
<span class="text-white">@message.Name</span><span> &mdash; @message.Message</span><br />
}
</div>

View File

@ -2,7 +2,7 @@
@{
var loc = SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex;
}
<h4 class="pb-3 text-center ">@ViewBag.Title</h4>
<h4 class="pb-3 text-center">@ViewBag.Title</h4>
<div class="row">
<select class="form-control bg-dark text-muted" id="penalty_filter_selection">
@{
@ -36,7 +36,7 @@
</div>
<div class="row">
<table class="table table-striped">
<thead class="d-none d-md-table-header-group">
<thead class="d-none d-lg-table-header-group">
<tr class="bg-primary pt-2 pb-2">
<th scope="col">@loc["WEBFRONT_PENALTY_TEMPLATE_NAME"]</th>
<th scope="col">@loc["WEBFRONT_PENALTY_TEMPLATE_TYPE"]</th>
@ -53,10 +53,10 @@
})
</tbody>
</table>
<table class="table d-table d-md-none">
<table class="table d-table d-lg-none">
<tbody></tbody>
</table>
<span id="load_penalties_button" class="oi oi-chevron-bottom text-center text-primary w-100 h3 pb-0 mb-0 d-none d-md-block"></span>
<span id="load_penalties_button" class="oi oi-chevron-bottom text-center text-primary w-100 h3 pb-0 mb-0 d-none d-lg-block"></span>
</div>
@section scripts {

View File

@ -5,72 +5,72 @@
@model SharedLibraryCore.Dtos.PenaltyInfo
<tr class="d-table-row d-md-none bg-dark">
<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" })
</td>
</tr>
<tr class="d-table-row d-md-none bg-dark">
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary">@loc["WEBFRONT_PENALTY_TEMPLATE_TYPE"]</th>
<td class="penalties-color-@Model.PenaltyType.ToLower()">
<td class="penalties-color-@Model.PenaltyTypeText.ToLower()">
@Model.PenaltyType
</td>
</tr>
<tr class="d-table-row d-md-none bg-dark">
<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
@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")
</td>
</tr>
<tr class="d-table-row d-md-none bg-dark">
<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-" + Model.PunisherLevelId })
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
</td>
</tr>
<tr class="d-table-row d-md-none bg-dark">
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="w-25 bg-primary" style="border-bottom: 1px solid #222">@loc["WEBFRONT_PENALTY_TEMPLATE_TIME"]</th>
<td class="text-light mb-2 border-bottom">
@{
if (Model.TimeRemaining == string.Empty)
if (Model.Expired)
{
<span>@Model.TimePunished @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]</span>
<span>@Model.TimePunishedString</span>
}
else
{
<span> @Model.TimeRemaining</span>
<span>@Model.TimeRemaining</span>
}
}
</td>
</tr>
<tr class="d-none d-md-table-row">
<tr class="d-none d-lg-table-row">
<td>
@Html.ActionLink(Model.OffenderName, "ProfileAsync", "Client", new { id = Model.OffenderId }, new { @class = "link-inverse" })
</td>
<td class="penalties-color-@Model.PenaltyType.ToLower()">
<td class="penalties-color-@Model.PenaltyTypeText.ToLower()">
@Model.PenaltyType
</td>
<td class="text-light w-50">
@Model.Offense
@($"{Model.Offense}{(ViewBag.Authorized ? Model.AdditionalPenaltyInformation : "")}")
</td>
<td>
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + Model.PunisherLevelId })
@Html.ActionLink(Model.PunisherName, "ProfileAsync", "Client", new { id = Model.PunisherId }, new { @class = "level-color-" + (int)Model.PunisherLevel })
</td>
<td class="text-right text-light">
@{
if (Model.TimeRemaining == string.Empty)
if (Model.Expired)
{
<span>@Model.TimePunished @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"]</span>
<span>@Model.TimePunishedString</span>
}
else
{
<span> @Model.TimeRemaining </span>
<span>@Model.TimeRemaining</span>
}
}
</td>

View File

@ -9,24 +9,24 @@
var penalty = meta.Value as SharedLibraryCore.Dtos.PenaltyInfo;
string localizationKey = meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Penalized ?
$"WEBFRONT_CLIENT_META_PENALIZED_{penalty.PenaltyType.ToUpper()}" :
$"WEBFRONT_CLIENT_META_WAS_PENALIZED_{penalty.PenaltyType.ToUpper()}";
$"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();
localizationMessage = localizationMessage.Replace(penaltyType, $"<span class='penalties-color-{penalty.PenaltyType.ToLower()}'>{penaltyType}</span>");
localizationMessage = localizationMessage.Replace(penaltyType, $"<span class='penalties-color-{penalty.PenaltyTypeText.ToLower()}'>{penaltyType}</span>");
return meta.Type == SharedLibraryCore.Dtos.ProfileMeta.MetaType.Penalized ?
string.Format(localizationMessage,
$"<span class='text-highlight'><a class='link-inverse' href='{penalty.OffenderId}'>{penalty.OffenderName}</a></span>",
$"<span class='automated-penalty-info-detailed text-white' data-clientid='{penalty.OffenderId}'>{penalty.Offense}</span>")
$"<span class='{(ViewBag.Authorized ? "automated-penalty-info-detailed" : "")} text-white' data-clientid='{penalty.OffenderId}'>{penalty.Offense} {(ViewBag.Authorized ? penalty.AdditionalPenaltyInformation : "")}</span>")
.Replace("{", "")
.Replace("}", "") :
string.Format(localizationMessage,
$"<span class='text-highlight'><a class='link-inverse' href='{penalty.PunisherId}'>{penalty.PunisherName}</a></span>",
$"<span class='automated-penalty-info-detailed text-white' data-clientid='{penalty.OffenderId}'>{(ViewBag.Authorized && !string.IsNullOrEmpty(penalty.AutomatedOffense) ? $"{penalty.Offense} ({penalty.AutomatedOffense})" : penalty.Offense)}</span>",
$"<span class='{(ViewBag.Authorized ? "automated-penalty-info-detailed" : "")} text-white' data-clientid='{penalty.OffenderId}'>{penalty.Offense} {(ViewBag.Authorized ? penalty.AdditionalPenaltyInformation : "")}</span>",
penalty.Offense)
.Replace("{", "")
.Replace("}", "");
@ -55,7 +55,7 @@
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ChatMessage:
<div class="profile-meta-entry loader-data-time" data-time="@meta.When">
<span style="color:white;">></span>
<span class="client-message text-muted" data-serverid="@meta.Extra" data-when="@meta.When"> @meta.Value</span>
<span class="client-message text-muted" data-serverid="@meta.Extra" data-when="@meta.When" title="@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGE_CONTEXT"]"> @meta.Value</span>
</div>
break;
case SharedLibraryCore.Dtos.ProfileMeta.MetaType.ReceivedPenalty:

View File

@ -6318,6 +6318,10 @@ a.link-inverse:hover {
.d-md-table-header-group {
display: table-header-group !important; } }
@media (min-width: 992px) {
.d-lg-table-header-group {
display: table-header-group !important; } }
#console_command_response {
min-height: 20rem; }

View File

@ -88,7 +88,13 @@ a.link-inverse:hover {
@media (min-width: 768px) {
.d-md-table-header-group {
display: table-header-group !important
display: table-header-group !important;
}
}
@media (min-width: 992px) {
.d-lg-table-header-group {
display: table-header-group !important;
}
}