Add role bans tab to the bans admin window (#20388)

This commit is contained in:
DrSmugleaf
2023-09-22 14:08:28 -07:00
committed by GitHub
parent 8299fcbb65
commit 71ab660885
23 changed files with 437 additions and 160 deletions

View File

@@ -1,76 +0,0 @@
using System.Linq;
using System.Numerics;
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList;
[GenerateTypedNameReferences]
public sealed partial class BanListControl : Control
{
private BanListIdsPopup? _popup;
public BanListControl()
{
RobustXamlLoader.Load(this);
}
public void SetBans(List<SharedServerBan> bans)
{
foreach (var control in Bans.Children.ToArray()[1..])
{
control.Orphan();
}
foreach (var ban in bans)
{
Bans.AddChild(new HSeparator());
var line = new BanListLine(ban);
line.OnIdsClicked += LineIdsClicked;
Bans.AddChild(line);
}
}
private void ClosePopup()
{
_popup?.Close();
_popup = null;
}
private bool LineIdsClicked(BanListLine line)
{
ClosePopup();
var ban = line.Ban;
var id = ban.Id == null ? string.Empty : Loc.GetString("ban-list-id", ("id", ban.Id.Value));
var ip = ban.Address == null
? string.Empty
: Loc.GetString("ban-list-ip", ("ip", ban.Address.Value.address));
var hwid = ban.HWId == null ? string.Empty : Loc.GetString("ban-list-hwid", ("hwid", ban.HWId));
var guid = ban.UserId == null
? string.Empty
: Loc.GetString("ban-list-guid", ("guid", ban.UserId.Value.ToString()));
_popup = new BanListIdsPopup(id, ip, hwid, guid);
var box = UIBox2.FromDimensions(UserInterfaceManager.MousePositionScaled.Position, new Vector2(1, 1));
_popup.Open(box);
return true;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_popup != null)
{
UserInterfaceManager.PopupRoot.RemoveChild(_popup);
}
}
}

View File

@@ -1,21 +1,47 @@
using Content.Client.Eui;
using System.Numerics;
using Content.Client.Administration.UI.BanList.Bans;
using Content.Client.Administration.UI.BanList.RoleBans;
using Content.Client.Eui;
using Content.Shared.Administration.BanList;
using Content.Shared.Eui;
using Content.Shared.Ghost.Roles;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
namespace Content.Client.Administration.UI.BanList;
[UsedImplicitly]
public sealed class BanListEui : BaseEui
{
[Dependency] private readonly IUserInterfaceManager _ui = default!;
private BanListIdsPopup? _popup;
public BanListEui()
{
BanWindow = new BanListWindow();
BanWindow.OnClose += OnClosed;
BanControl = BanWindow.BanList;
BanControl.LineIdsClicked += OnLineIdsClicked;
RoleBanControl = BanWindow.RoleBanList;
RoleBanControl.LineIdsClicked += OnLineIdsClicked;
}
private BanListWindow BanWindow { get; }
private BanListControl BanControl { get; }
private RoleBanListControl RoleBanControl { get; }
private void OnClosed()
{
if (_popup != null)
{
_popup.Close();
_popup.Dispose();
_popup = null;
}
SendMessage(new CloseEuiMessage());
}
@@ -25,10 +51,6 @@ public sealed class BanListEui : BaseEui
BanWindow.Close();
}
private BanListWindow BanWindow { get; }
private BanListControl BanControl { get; }
public override void HandleState(EuiStateBase state)
{
if (state is not BanListEuiState s)
@@ -38,10 +60,58 @@ public sealed class BanListEui : BaseEui
s.Bans.Sort((a, b) => a.BanTime.CompareTo(b.BanTime));
BanControl.SetBans(s.Bans);
RoleBanControl.SetRoleBans(s.RoleBans);
}
public override void Opened()
{
BanWindow.OpenCentered();
}
private static string FormatDate(DateTimeOffset date)
{
return date.ToString("MM/dd/yyyy h:mm tt");
}
public static void SetData<T>(IBanListLine<T> line, SharedServerBan ban) where T : SharedServerBan
{
line.Reason.Text = ban.Reason;
line.BanTime.Text = FormatDate(ban.BanTime);
line.Expires.Text = ban.ExpirationTime == null
? Loc.GetString("ban-list-permanent")
: FormatDate(ban.ExpirationTime.Value);
if (ban.Unban is { } unban)
{
var unbanned = Loc.GetString("ban-list-unbanned", ("date", FormatDate(unban.UnbanTime)));
var unbannedBy = unban.UnbanningAdmin == null
? string.Empty
: $"\n{Loc.GetString("ban-list-unbanned-by", ("unbanner", unban.UnbanningAdmin))}";
line.Expires.Text += $"\n{unbanned}{unbannedBy}";
}
line.BanningAdmin.Text = ban.BanningAdminName;
}
private void OnLineIdsClicked<T>(IBanListLine<T> line) where T : SharedServerBan
{
_popup?.Close();
_popup = null;
var ban = line.Ban;
var id = ban.Id == null ? string.Empty : Loc.GetString("ban-list-id", ("id", ban.Id.Value));
var ip = ban.Address == null
? string.Empty
: Loc.GetString("ban-list-ip", ("ip", ban.Address.Value.address));
var hwid = ban.HWId == null ? string.Empty : Loc.GetString("ban-list-hwid", ("hwid", ban.HWId));
var guid = ban.UserId == null
? string.Empty
: Loc.GetString("ban-list-guid", ("guid", ban.UserId.Value.ToString()));
_popup = new BanListIdsPopup(id, ip, hwid, guid);
var box = UIBox2.FromDimensions(_ui.MousePositionScaled.Position, new Vector2(1, 1));
_popup.Open(box);
}
}

View File

@@ -1,59 +0,0 @@
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList;
[GenerateTypedNameReferences]
public sealed partial class BanListLine : BoxContainer
{
public readonly SharedServerBan Ban;
public event Func<BanListLine, bool>? OnIdsClicked;
public BanListLine(SharedServerBan ban)
{
RobustXamlLoader.Load(this);
Ban = ban;
IdsHidden.OnPressed += IdsPressed;
Reason.Text = ban.Reason;
BanTime.Text = FormatDate(ban.BanTime);
Expires.Text = ban.ExpirationTime == null
? Loc.GetString("ban-list-permanent")
: FormatDate(ban.ExpirationTime.Value);
if (ban.Unban is { } unban)
{
var unbanned = Loc.GetString("ban-list-unbanned", ("date", FormatDate(unban.UnbanTime)));
var unbannedBy = unban.UnbanningAdmin == null
? string.Empty
: $"\n{Loc.GetString("ban-list-unbanned-by", ("unbanner", unban.UnbanningAdmin))}";
Expires.Text += $"\n{unbanned}{unbannedBy}";
}
BanningAdmin.Text = ban.BanningAdminName;
}
private static string FormatDate(DateTimeOffset date)
{
return date.ToString("MM/dd/yyyy h:mm tt");
}
private void IdsPressed(BaseButton.ButtonEventArgs buttonEventArgs)
{
OnIdsClicked?.Invoke(this);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
IdsHidden.OnPressed -= IdsPressed;
OnIdsClicked = null;
}
}

View File

@@ -1,6 +1,11 @@
<controls:BanListWindow
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.Administration.UI.BanList"
xmlns:bans="clr-namespace:Content.Client.Administration.UI.BanList.Bans"
xmlns:roleBans="clr-namespace:Content.Client.Administration.UI.BanList.RoleBans"
SetSize="1400 400">
<controls:BanListControl Name="BanList" Access="Public"/>
<TabContainer Name="TabContainer">
<bans:BanListControl Name="BanList" Access="Public"/>
<roleBans:RoleBanListControl Name="RoleBanList" Access="Public"/>
</TabContainer>
</controls:BanListWindow>

View File

@@ -10,6 +10,9 @@ public sealed partial class BanListWindow : DefaultWindow
public BanListWindow()
{
RobustXamlLoader.Load(this);
TabContainer.SetTabTitle(0, Loc.GetString("ban-list-bans"));
TabContainer.SetTabTitle(1, Loc.GetString("ban-list-role-bans"));
}
public void SetTitlePlayer(string playerName)

View File

@@ -1,11 +1,11 @@
<controls:BanListControl
<bans:BanListControl
xmlns="https://spacestation14.io"
xmlns:controls="clr-namespace:Content.Client.Administration.UI.BanList">
xmlns:bans="clr-namespace:Content.Client.Administration.UI.BanList.Bans">
<PanelContainer StyleClasses="BackgroundDark">
<ScrollContainer>
<BoxContainer Name="Bans" Access="Public" Orientation="Vertical">
<controls:BanListHeader Name="BansHeader"/>
<bans:BanListHeader Name="BansHeader"/>
</BoxContainer>
</ScrollContainer>
</PanelContainer>
</controls:BanListControl>
</bans:BanListControl>

View File

@@ -0,0 +1,36 @@
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList.Bans;
[GenerateTypedNameReferences]
public sealed partial class BanListControl : Control
{
public event Action<BanListLine>? LineIdsClicked;
public BanListControl()
{
RobustXamlLoader.Load(this);
}
public void SetBans(List<SharedServerBan> bans)
{
for (var i = Bans.ChildCount - 1; i >= 1; i--)
{
Bans.GetChild(i).Dispose();
}
foreach (var ban in bans)
{
Bans.AddChild(new HSeparator());
var line = new BanListLine(ban);
line.IdsClicked += LineIdsClicked;
Bans.AddChild(line);
}
}
}

View File

@@ -25,7 +25,6 @@
<Label Text="{Loc ban-list-header-banning-admin}"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"/>
<cc:VSeparator/>
</BoxContainer>
</PanelContainer>
</ContainerButton>

View File

@@ -2,7 +2,7 @@
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList;
namespace Content.Client.Administration.UI.BanList.Bans;
[GenerateTypedNameReferences]
public sealed partial class BanListHeader : ContainerButton

View File

@@ -16,23 +16,26 @@
</BoxContainer>
<cc:VSeparator/>
<Label Name="Reason"
Access="Public"
SizeFlagsStretchRatio="6"
HorizontalExpand="True"
VerticalExpand="True"/>
<cc:VSeparator/>
<Label Name="BanTime"
Access="Public"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"/>
<cc:VSeparator/>
<Label Name="Expires"
Access="Public"
SizeFlagsStretchRatio="4"
HorizontalExpand="True"
ClipText="True"/>
<cc:VSeparator/>
<Label Name="BanningAdmin"
Access="Public"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"/>
<cc:VSeparator/>
</BoxContainer>

View File

@@ -0,0 +1,38 @@
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using static Robust.Client.UserInterface.Controls.BaseButton;
namespace Content.Client.Administration.UI.BanList.Bans;
[GenerateTypedNameReferences]
public sealed partial class BanListLine : BoxContainer, IBanListLine<SharedServerBan>
{
public SharedServerBan Ban { get; }
public event Action<BanListLine>? IdsClicked;
public BanListLine(SharedServerBan ban)
{
RobustXamlLoader.Load(this);
Ban = ban;
IdsHidden.OnPressed += IdsPressed;
BanListEui.SetData(this, ban);
}
private void IdsPressed(ButtonEventArgs buttonEventArgs)
{
IdsClicked?.Invoke(this);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
IdsHidden.OnPressed -= IdsPressed;
IdsClicked = null;
}
}

View File

@@ -0,0 +1,13 @@
using Content.Shared.Administration.BanList;
using Robust.Client.UserInterface.Controls;
namespace Content.Client.Administration.UI.BanList;
public interface IBanListLine<T> where T : SharedServerBan
{
T Ban { get; }
Label Reason { get; }
Label BanTime { get; }
Label Expires { get; }
Label BanningAdmin { get; }
}

View File

@@ -0,0 +1,11 @@
<roleBans:RoleBanListControl
xmlns="https://spacestation14.io"
xmlns:roleBans="clr-namespace:Content.Client.Administration.UI.BanList.RoleBans">
<PanelContainer StyleClasses="BackgroundDark">
<ScrollContainer>
<BoxContainer Name="RoleBans" Access="Public" Orientation="Vertical">
<roleBans:RoleBanListHeader Name="BansHeader"/>
</BoxContainer>
</ScrollContainer>
</PanelContainer>
</roleBans:RoleBanListControl>

View File

@@ -0,0 +1,36 @@
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList.RoleBans;
[GenerateTypedNameReferences]
public sealed partial class RoleBanListControl : Control
{
public event Action<RoleBanListLine>? LineIdsClicked;
public RoleBanListControl()
{
RobustXamlLoader.Load(this);
}
public void SetRoleBans(List<SharedServerRoleBan> bans)
{
for (var i = RoleBans.ChildCount - 1; i >= 1; i--)
{
RoleBans.GetChild(i).Dispose();
}
foreach (var ban in bans)
{
RoleBans.AddChild(new HSeparator());
var line = new RoleBanListLine(ban);
line.IdsClicked += LineIdsClicked;
RoleBans.AddChild(line);
}
}
}

View File

@@ -0,0 +1,34 @@
<ContainerButton
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls">
<PanelContainer Name="BackgroundPanel" Access="Public">
<BoxContainer
Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="4">
<Label Text="{Loc ban-list-header-ids}"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"/>
<cc:VSeparator/>
<Label Text="{Loc ban-list-header-reason}"
SizeFlagsStretchRatio="4.5"
HorizontalExpand="True"/>
<cc:VSeparator Name="ReasonSeparator" Access="Public"/>
<Label Text="{Loc ban-list-header-role}"
SizeFlagsStretchRatio="1.5"
HorizontalExpand="True"/>
<cc:VSeparator/>
<Label Text="{Loc ban-list-header-time}"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"/>
<cc:VSeparator/>
<Label Text="{Loc ban-list-header-expires}"
SizeFlagsStretchRatio="4"
HorizontalExpand="True"/>
<cc:VSeparator/>
<Label Text="{Loc ban-list-header-banning-admin}"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"/>
</BoxContainer>
</PanelContainer>
</ContainerButton>

View File

@@ -0,0 +1,14 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
namespace Content.Client.Administration.UI.BanList.RoleBans;
[GenerateTypedNameReferences]
public sealed partial class RoleBanListHeader : ContainerButton
{
public RoleBanListHeader()
{
RobustXamlLoader.Load(this);
}
}

View File

@@ -0,0 +1,46 @@
<BoxContainer
xmlns="https://spacestation14.io"
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
Orientation="Horizontal"
HorizontalExpand="True"
SeparationOverride="4">
<BoxContainer Orientation="Vertical"
SizeFlagsStretchRatio="1"
HorizontalExpand="True"
RectClipContent="True">
<Button Name="IdsHidden"
Text="{Loc 'ban-list-view'}"
HorizontalExpand="True"
VerticalExpand="True"
MouseFilter="Pass"/>
</BoxContainer>
<cc:VSeparator/>
<Label Name="Reason"
Access="Public"
SizeFlagsStretchRatio="4.5"
HorizontalExpand="True"
VerticalExpand="True"/>
<cc:VSeparator/>
<Label Name="Role"
SizeFlagsStretchRatio="1.5"
HorizontalExpand="True"
VerticalExpand="True"/>
<cc:VSeparator/>
<Label Name="BanTime"
Access="Public"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"/>
<cc:VSeparator/>
<Label Name="Expires"
Access="Public"
SizeFlagsStretchRatio="4"
HorizontalExpand="True"
ClipText="True"/>
<cc:VSeparator/>
<Label Name="BanningAdmin"
Access="Public"
SizeFlagsStretchRatio="2"
HorizontalExpand="True"
ClipText="True"/>
</BoxContainer>

View File

@@ -0,0 +1,40 @@
using Content.Shared.Administration.BanList;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using static Robust.Client.UserInterface.Controls.BaseButton;
namespace Content.Client.Administration.UI.BanList.RoleBans;
[GenerateTypedNameReferences]
public sealed partial class RoleBanListLine : BoxContainer, IBanListLine<SharedServerRoleBan>
{
public SharedServerRoleBan Ban { get; }
public event Action<RoleBanListLine>? IdsClicked;
public RoleBanListLine(SharedServerRoleBan ban)
{
RobustXamlLoader.Load(this);
Ban = ban;
IdsHidden.OnPressed += IdsPressed;
BanListEui.SetData(this, ban);
Role.Text = ban.Role;
}
private void IdsPressed(ButtonEventArgs buttonEventArgs)
{
IdsClicked?.Invoke(this);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
IdsHidden.OnPressed -= IdsPressed;
IdsClicked = null;
}
}

View File

@@ -22,7 +22,8 @@ public sealed class BanListEui : BaseEui
private Guid BanListPlayer { get; set; }
private string BanListPlayerName { get; set; } = string.Empty;
private List<SharedServerBan> Bans { get; set; } = new();
private List<SharedServerBan> Bans { get; } = new();
private List<SharedServerRoleBan> RoleBans { get; } = new();
public override void Opened()
{
@@ -40,7 +41,7 @@ public sealed class BanListEui : BaseEui
public override EuiStateBase GetNewState()
{
return new BanListEuiState(BanListPlayerName, Bans);
return new BanListEuiState(BanListPlayerName, Bans, RoleBans);
}
private void OnPermsChanged(AdminPermsChangedEventArgs args)
@@ -51,14 +52,8 @@ public sealed class BanListEui : BaseEui
}
}
private async Task LoadFromDb()
private async Task LoadBans(NetUserId userId)
{
Bans.Clear();
var userId = new NetUserId(BanListPlayer);
BanListPlayerName = (await _playerLocator.LookupIdAsync(userId))?.Username ??
string.Empty;
foreach (var ban in await _db.GetServerBansAsync(null, userId, null))
{
SharedServerUnban? unban = null;
@@ -86,6 +81,51 @@ public sealed class BanListEui : BaseEui
unban
));
}
}
private async Task LoadRoleBans(NetUserId userId)
{
foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null))
{
SharedServerUnban? unban = null;
if (ban.Unban is { } unbanDef)
{
var unbanningAdmin = unbanDef.UnbanningAdmin == null
? null
: (await _playerLocator.LookupIdAsync(unbanDef.UnbanningAdmin.Value))?.Username;
unban = new SharedServerUnban(unbanningAdmin, ban.Unban.UnbanTime.UtcDateTime);
}
RoleBans.Add(new SharedServerRoleBan(
ban.Id,
ban.UserId,
ban.Address is { } address
? (address.address.ToString(), address.cidrMask)
: null,
ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()),
ban.BanTime.UtcDateTime,
ban.ExpirationTime?.UtcDateTime,
ban.Reason,
ban.BanningAdmin == null
? null
: (await _playerLocator.LookupIdAsync(ban.BanningAdmin.Value))?.Username,
unban,
ban.Role
));
}
}
private async Task LoadFromDb()
{
Bans.Clear();
RoleBans.Clear();
var userId = new NetUserId(BanListPlayer);
BanListPlayerName = (await _playerLocator.LookupIdAsync(userId))?.Username ??
string.Empty;
await LoadBans(userId);
await LoadRoleBans(userId);
StateDirty();
}

View File

@@ -6,12 +6,14 @@ namespace Content.Shared.Administration.BanList;
[Serializable, NetSerializable]
public sealed class BanListEuiState : EuiStateBase
{
public BanListEuiState(string banListPlayerName, List<SharedServerBan> bans)
public BanListEuiState(string banListPlayerName, List<SharedServerBan> bans, List<SharedServerRoleBan> roleBans)
{
BanListPlayerName = banListPlayerName;
Bans = bans;
RoleBans = roleBans;
}
public string BanListPlayerName { get; }
public List<SharedServerBan> Bans { get; }
public List<SharedServerRoleBan> RoleBans { get; }
}

View File

@@ -4,7 +4,7 @@ using Robust.Shared.Serialization;
namespace Content.Shared.Administration.BanList;
[Serializable, NetSerializable]
public sealed record SharedServerBan(
public record SharedServerBan(
int? Id,
NetUserId? UserId,
(string address, int cidrMask)? Address,

View File

@@ -0,0 +1,18 @@
using Robust.Shared.Network;
using Robust.Shared.Serialization;
namespace Content.Shared.Administration.BanList;
[Serializable, NetSerializable]
public sealed record SharedServerRoleBan(
int? Id,
NetUserId? UserId,
(string address, int cidrMask)? Address,
string? HWId,
DateTime BanTime,
DateTime? ExpirationTime,
string Reason,
string? BanningAdminName,
SharedServerUnban? Unban,
string Role
) : SharedServerBan(Id, UserId, Address, HWId, BanTime, ExpirationTime, Reason, BanningAdminName, Unban);

View File

@@ -1,6 +1,10 @@
# UI
ban-list-bans = Bans
ban-list-role-bans = Role Bans
ban-list-header-ids = Ids
ban-list-header-reason = Reason
ban-list-header-role = Role
ban-list-header-time = Ban time
ban-list-header-expires = Expires
ban-list-header-banning-admin = Banning admin