Add admin logs window pop out button, default to docked

Default to unmaximized
This commit is contained in:
DrSmugleaf
2021-12-09 00:05:42 +01:00
parent 7929600def
commit 81c0b1e174
8 changed files with 575 additions and 519 deletions

View File

@@ -0,0 +1,68 @@
<Control xmlns="https://spacestation14.io"
xmlns:aui="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
MinWidth="1000"
MinHeight="400">
<PanelContainer>
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#25252add"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Horizontal">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" MinWidth="400">
<Label Text="{Loc admin-logs-round}"/>
<SpinBox Name="RoundSpinBox" Value="0" MinWidth="150"/>
<Control HorizontalExpand="True"/>
<Button Name="ResetRoundButton" Text="{Loc admin-logs-reset}" HorizontalAlignment="Right"
StyleClasses="OpenRight"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" VerticalExpand="True">
<BoxContainer Orientation="Vertical" MinWidth="200">
<LineEdit Name="TypeSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-types-placeholder}"/>
<BoxContainer Orientation="Horizontal">
<Button Name="SelectAllTypesButton" Text="{Loc admin-logs-select-all}"
MinWidth="100" StyleClasses="ButtonSquare"/>
<Button Name="SelectNoTypesButton" Text="{Loc admin-logs-select-none}"
MinWidth="100" StyleClasses="ButtonSquare"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="TypesContainer" Access="Public" Orientation="Vertical"/>
</ScrollContainer>
</BoxContainer>
<aui:VSeparator/>
<BoxContainer Orientation="Vertical" MinWidth="200">
<LineEdit Name="PlayerSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-players-placeholder}"/>
<BoxContainer Orientation="Horizontal">
<Button Name="SelectAllPlayersButton" Text="{Loc admin-logs-select-all}"
MinWidth="100" StyleClasses="ButtonSquare" />
<Button Name="SelectNoPlayersButton" Text="{Loc admin-logs-select-none}"
MinWidth="100" StyleClasses="ButtonSquare"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="PlayersContainer" Access="Public" Orientation="Vertical"/>
</ScrollContainer>
</BoxContainer>
<aui:VSeparator/>
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<BoxContainer Name="TopRightContainer">
<BoxContainer Name="LogImpactContainer" Orientation="Horizontal"/>
<Control HorizontalExpand="True"/>
<Button Name="PopOutButton" Access="Public" Text="{Loc admin-logs-pop-out}"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal">
<LineEdit Name="LogSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-logs-placeholder}"/>
<Button Name="RefreshButton" Access="Public" Text="{Loc admin-logs-refresh}" StyleClasses="ButtonSquare"/>
<Button Name="NextButton" Access="Public" Text="{Loc admin-logs-next}" StyleClasses="OpenLeft"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
<BoxContainer Name="LogsContainer" Access="Public" Orientation="Vertical" VerticalExpand="True"/>
</ScrollContainer>
</BoxContainer>
</BoxContainer>
</PanelContainer>
</Control>

View File

@@ -0,0 +1,432 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.LineEdit;
namespace Content.Client.Administration.UI.Logs;
[GenerateTypedNameReferences]
public partial class AdminLogsControl : Control
{
private readonly Comparer<AdminLogTypeButton> _adminLogTypeButtonComparer =
Comparer<AdminLogTypeButton>.Create((a, b) =>
string.Compare(a.Type.ToString(), b.Type.ToString(), StringComparison.Ordinal));
private readonly Comparer<AdminLogPlayerButton> _adminLogPlayerButtonComparer =
Comparer<AdminLogPlayerButton>.Create((a, b) =>
string.Compare(a.Text, b.Text, StringComparison.Ordinal));
public AdminLogsControl()
{
RobustXamlLoader.Load(this);
TypeSearch.OnTextChanged += TypeSearchChanged;
PlayerSearch.OnTextChanged += PlayerSearchChanged;
LogSearch.OnTextChanged += LogSearchChanged;
SelectAllTypesButton.OnPressed += SelectAllTypes;
SelectNoTypesButton.OnPressed += SelectNoTypes;
SelectAllPlayersButton.OnPressed += SelectAllPlayers;
SelectNoPlayersButton.OnPressed += SelectNoPlayers;
RoundSpinBox.IsValid = i => i > 0 && i <= CurrentRound;
RoundSpinBox.ValueChanged += RoundSpinBoxChanged;
RoundSpinBox.InitDefaultButtons();
ResetRoundButton.OnPressed += ResetRoundPressed;
SetImpacts(Enum.GetValues<LogImpact>().OrderBy(impact => impact).ToArray());
SetTypes(Enum.GetValues<LogType>());
}
private int CurrentRound { get; set; }
public int SelectedRoundId => RoundSpinBox.Value;
public HashSet<LogType> SelectedTypes { get; } = new();
public HashSet<Guid> SelectedPlayers { get; } = new();
public HashSet<LogImpact> SelectedImpacts { get; } = new();
public void SetCurrentRound(int round)
{
CurrentRound = round;
ResetRoundButton.Text = Loc.GetString("admin-logs-reset-with-id", ("id", round));
UpdateResetButton();
}
public void SetRoundSpinBox(int round)
{
RoundSpinBox.Value = round;
UpdateResetButton();
}
private void RoundSpinBoxChanged(object? sender, ValueChangedEventArgs args)
{
UpdateResetButton();
}
private void UpdateResetButton()
{
ResetRoundButton.Disabled = RoundSpinBox.Value == CurrentRound;
}
private void ResetRoundPressed(ButtonEventArgs args)
{
RoundSpinBox.Value = CurrentRound;
}
private void TypeSearchChanged(LineEditEventArgs args)
{
UpdateTypes();
}
private void PlayerSearchChanged(LineEditEventArgs args)
{
UpdatePlayers();
}
private void LogSearchChanged(LineEditEventArgs args)
{
UpdateLogs();
}
private void SelectAllTypes(ButtonEventArgs args)
{
SelectedTypes.Clear();
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Pressed = true;
SelectedTypes.Add(type.Type);
}
UpdateLogs();
}
private void SelectNoTypes(ButtonEventArgs args)
{
SelectedTypes.Clear();
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Pressed = false;
type.Visible = ShouldShowType(type);
}
UpdateLogs();
}
private void SelectAllPlayers(ButtonEventArgs args)
{
SelectedPlayers.Clear();
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Pressed = true;
SelectedPlayers.Add(player.Id);
}
UpdateLogs();
}
private void SelectNoPlayers(ButtonEventArgs args)
{
SelectedPlayers.Clear();
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Pressed = false;
}
UpdateLogs();
}
public void UpdateTypes()
{
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Visible = ShouldShowType(type);
}
}
private void UpdatePlayers()
{
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Visible = ShouldShowPlayer(player);
}
}
private void UpdateLogs()
{
foreach (var child in LogsContainer.Children)
{
if (child is not AdminLogLabel log)
{
continue;
}
child.Visible = ShouldShowLog(log);
}
}
private bool ShouldShowType(AdminLogTypeButton button)
{
return button.Text != null &&
button.Text.Contains(TypeSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private bool ShouldShowPlayer(AdminLogPlayerButton button)
{
return button.Text != null &&
button.Text.Contains(PlayerSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private bool ShouldShowLog(AdminLogLabel label)
{
return SelectedTypes.Contains(label.Log.Type) &&
(SelectedPlayers.Count + label.Log.Players.Length == 0 || SelectedPlayers.Overlaps(label.Log.Players)) &&
SelectedImpacts.Contains(label.Log.Impact) &&
label.Log.Message.Contains(LogSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private void TypeButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogTypeButton) args.Button;
if (button.Pressed)
{
SelectedTypes.Add(button.Type);
}
else
{
SelectedTypes.Remove(button.Type);
}
UpdateLogs();
}
private void PlayerButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogPlayerButton) args.Button;
if (button.Pressed)
{
SelectedPlayers.Add(button.Id);
}
else
{
SelectedPlayers.Remove(button.Id);
}
UpdateLogs();
}
private void ImpactButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogImpactButton) args.Button;
if (button.Pressed)
{
SelectedImpacts.Add(button.Impact);
}
else
{
SelectedImpacts.Remove(button.Impact);
}
UpdateLogs();
}
private void SetImpacts(LogImpact[] impacts)
{
LogImpactContainer.RemoveAllChildren();
foreach (var impact in impacts)
{
var button = new AdminLogImpactButton(impact)
{
Text = impact.ToString()
};
SelectedImpacts.Add(impact);
button.OnPressed += ImpactButtonPressed;
LogImpactContainer.AddChild(button);
}
switch (impacts.Length)
{
case 0:
return;
case 1:
LogImpactContainer.GetChild(0).StyleClasses.Add("OpenRight");
return;
}
for (var i = 0; i < impacts.Length - 1; i++)
{
LogImpactContainer.GetChild(i).StyleClasses.Add("ButtonSquare");
}
LogImpactContainer.GetChild(LogImpactContainer.ChildCount - 1).StyleClasses.Add("OpenLeft");
}
private void SetTypes(LogType[] types)
{
var newTypes = types.ToHashSet();
var buttons = new SortedSet<AdminLogTypeButton>(_adminLogTypeButtonComparer);
foreach (var control in TypesContainer.Children.ToArray())
{
if (control is not AdminLogTypeButton type ||
!newTypes.Remove(type.Type))
{
continue;
}
buttons.Add(type);
}
foreach (var type in newTypes)
{
var button = new AdminLogTypeButton(type)
{
Text = type.ToString(),
Pressed = true
};
SelectedTypes.Add(type);
button.OnPressed += TypeButtonPressed;
buttons.Add(button);
}
TypesContainer.RemoveAllChildren();
foreach (var type in buttons)
{
TypesContainer.AddChild(type);
}
UpdateLogs();
}
public void SetPlayers(Dictionary<Guid, string> players)
{
var buttons = new SortedSet<AdminLogPlayerButton>(_adminLogPlayerButtonComparer);
foreach (var control in PlayersContainer.Children.ToArray())
{
if (control is not AdminLogPlayerButton player ||
!players.Remove(player.Id))
{
continue;
}
buttons.Add(player);
}
foreach (var (id, name) in players)
{
var button = new AdminLogPlayerButton(id)
{
Text = name,
Pressed = true
};
SelectedPlayers.Add(id);
button.OnPressed += PlayerButtonPressed;
buttons.Add(button);
}
PlayersContainer.RemoveAllChildren();
foreach (var player in buttons)
{
PlayersContainer.AddChild(player);
}
UpdateLogs();
}
public void AddLogs(SharedAdminLog[] logs)
{
for (var i = 0; i < logs.Length; i++)
{
ref var log = ref logs[i];
var separator = new HSeparator();
var label = new AdminLogLabel(ref log, separator);
label.Visible = ShouldShowLog(label);
LogsContainer.AddChild(label);
LogsContainer.AddChild(separator);
}
}
public void SetLogs(SharedAdminLog[] logs)
{
LogsContainer.RemoveAllChildren();
AddLogs(logs);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
TypeSearch.OnTextChanged -= TypeSearchChanged;
PlayerSearch.OnTextChanged -= PlayerSearchChanged;
LogSearch.OnTextChanged -= LogSearchChanged;
SelectAllTypesButton.OnPressed -= SelectAllTypes;
SelectNoTypesButton.OnPressed -= SelectNoTypes;
SelectAllPlayersButton.OnPressed -= SelectAllPlayers;
SelectNoPlayersButton.OnPressed -= SelectNoPlayers;
RoundSpinBox.IsValid = null;
RoundSpinBox.ValueChanged -= RoundSpinBoxChanged;
ResetRoundButton.OnPressed -= ResetRoundPressed;
}
}

View File

@@ -20,32 +20,22 @@ public class AdminLogsEui : BaseEui
public AdminLogsEui()
{
var monitor = _clyde.EnumerateMonitors().First();
ClydeWindow = _clyde.CreateWindow(new WindowCreateParameters
{
Maximized = true,
Title = "Admin Logs",
Monitor = monitor
});
ClydeWindow.RequestClosed += OnRequestClosed;
ClydeWindow.DisposeOnClose = true;
LogsWindow = new AdminLogsWindow();
LogsWindow.LogSearch.OnTextEntered += _ => RequestLogs();
LogsWindow.RefreshButton.OnPressed += _ => RequestLogs();
LogsWindow.NextButton.OnPressed += _ => NextLogs();
LogsControl = LogsWindow.Logs;
Root = _uiManager.CreateWindowRoot(ClydeWindow);
Root.AddChild(LogsWindow);
LogsControl.LogSearch.OnTextEntered += _ => RequestLogs();
LogsControl.RefreshButton.OnPressed += _ => RequestLogs();
LogsControl.NextButton.OnPressed += _ => NextLogs();
LogsControl.PopOutButton.OnPressed += _ => PopOut();
}
private WindowRoot Root { get; }
private WindowRoot? Root { get; set; }
private IClydeWindow ClydeWindow { get; }
private IClydeWindow? ClydeWindow { get; set; }
private AdminLogsWindow LogsWindow { get; }
private AdminLogsWindow? LogsWindow { get; set; }
private AdminLogsControl LogsControl { get; }
private bool FirstState { get; set; } = true;
@@ -57,12 +47,12 @@ public class AdminLogsEui : BaseEui
private void RequestLogs()
{
var request = new LogsRequest(
LogsWindow.SelectedRoundId,
LogsWindow.SelectedTypes.ToList(),
LogsControl.SelectedRoundId,
LogsControl.SelectedTypes.ToList(),
null,
null,
null,
LogsWindow.SelectedPlayers.ToArray(),
LogsControl.SelectedPlayers.ToArray(),
null,
null,
DateOrder.Descending);
@@ -76,6 +66,38 @@ public class AdminLogsEui : BaseEui
SendMessage(request);
}
private void PopOut()
{
if (LogsWindow == null)
{
return;
}
LogsControl.Orphan();
LogsWindow.Dispose();
LogsWindow = null;
var monitor = _clyde.EnumerateMonitors().First();
ClydeWindow = _clyde.CreateWindow(new WindowCreateParameters
{
Maximized = false,
Title = "Admin Logs",
Monitor = monitor,
Width = 1000,
Height = 400
});
ClydeWindow.RequestClosed += OnRequestClosed;
ClydeWindow.DisposeOnClose = true;
Root = _uiManager.CreateWindowRoot(ClydeWindow);
Root.AddChild(LogsControl);
LogsControl.PopOutButton.Disabled = true;
LogsControl.PopOutButton.Visible = false;
}
private bool TrySetFirstState(AdminLogsEuiState state)
{
if (!FirstState)
@@ -84,8 +106,8 @@ public class AdminLogsEui : BaseEui
}
FirstState = false;
LogsWindow.SetCurrentRound(state.RoundId);
LogsWindow.SetRoundSpinBox(state.RoundId);
LogsControl.SetCurrentRound(state.RoundId);
LogsControl.SetRoundSpinBox(state.RoundId);
return true;
}
@@ -100,8 +122,8 @@ public class AdminLogsEui : BaseEui
return;
}
LogsWindow.SetCurrentRound(s.RoundId);
LogsWindow.SetPlayers(s.Players);
LogsControl.SetCurrentRound(s.RoundId);
LogsControl.SetPlayers(s.Players);
if (first)
{
@@ -116,22 +138,33 @@ public class AdminLogsEui : BaseEui
switch (msg)
{
case NewLogs {Replace: true} newLogs:
LogsWindow.SetLogs(newLogs.Logs);
LogsControl.SetLogs(newLogs.Logs);
break;
case NewLogs {Replace: false} newLogs:
LogsWindow.AddLogs(newLogs.Logs);
LogsControl.AddLogs(newLogs.Logs);
break;
}
}
public override void Opened()
{
base.Opened();
LogsWindow?.OpenCentered();
}
public override void Closed()
{
base.Closed();
ClydeWindow.RequestClosed -= OnRequestClosed;
if (ClydeWindow != null)
{
ClydeWindow.RequestClosed -= OnRequestClosed;
}
LogsWindow.Dispose();
Root.Dispose();
ClydeWindow.Dispose();
LogsControl.Dispose();
LogsWindow?.Dispose();
Root?.Dispose();
ClydeWindow?.Dispose();
}
}

View File

@@ -1,64 +1,7 @@
<Control xmlns="https://spacestation14.io"
xmlns:aui="clr-namespace:Content.Client.Administration.UI.CustomControls"
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
<SS14Window xmlns="https://spacestation14.io"
xmlns:logs="clr-namespace:Content.Client.Administration.UI.Logs"
Title="{Loc admin-logs-title}"
MinWidth="1000"
MinHeight="400">
<PanelContainer>
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#25252add"/>
</PanelContainer.PanelOverride>
<BoxContainer Orientation="Horizontal">
<BoxContainer Orientation="Vertical">
<BoxContainer Orientation="Horizontal" MinWidth="400">
<Label Text="{Loc admin-logs-round}"/>
<SpinBox Name="RoundSpinBox" Value="0" MinWidth="150"/>
<Control HorizontalExpand="True"/>
<Button Name="ResetRoundButton" Text="{Loc admin-logs-reset}" HorizontalAlignment="Right"
StyleClasses="OpenRight"/>
</BoxContainer>
<BoxContainer Orientation="Horizontal" VerticalExpand="True">
<BoxContainer Orientation="Vertical" MinWidth="200">
<LineEdit Name="TypeSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-types-placeholder}"/>
<BoxContainer Orientation="Horizontal">
<Button Name="SelectAllTypesButton" Text="{Loc admin-logs-select-all}"
MinWidth="100" StyleClasses="ButtonSquare"/>
<Button Name="SelectNoTypesButton" Text="{Loc admin-logs-select-none}"
MinWidth="100" StyleClasses="ButtonSquare"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="TypesContainer" Access="Public" Orientation="Vertical"/>
</ScrollContainer>
</BoxContainer>
<aui:VSeparator/>
<BoxContainer Orientation="Vertical" MinWidth="200">
<LineEdit Name="PlayerSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-players-placeholder}"/>
<BoxContainer Orientation="Horizontal">
<Button Name="SelectAllPlayersButton" Text="{Loc admin-logs-select-all}"
MinWidth="100" StyleClasses="ButtonSquare" />
<Button Name="SelectNoPlayersButton" Text="{Loc admin-logs-select-none}"
MinWidth="100" StyleClasses="ButtonSquare"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True">
<BoxContainer Name="PlayersContainer" Access="Public" Orientation="Vertical"/>
</ScrollContainer>
</BoxContainer>
<aui:VSeparator/>
</BoxContainer>
</BoxContainer>
<BoxContainer Orientation="Vertical" HorizontalExpand="True">
<BoxContainer Name="LogImpactContainer" Orientation="Horizontal"/>
<BoxContainer Orientation="Horizontal">
<LineEdit Name="LogSearch" Access="Public" StyleClasses="actionSearchBox"
HorizontalExpand="true" PlaceHolder="{Loc admin-logs-search-logs-placeholder}"/>
<Button Name="RefreshButton" Access="Public" Text="{Loc admin-logs-refresh}" StyleClasses="ButtonSquare"/>
<Button Name="NextButton" Access="Public" Text="{Loc admin-logs-next}" StyleClasses="OpenLeft"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
<BoxContainer Name="LogsContainer" Access="Public" Orientation="Vertical" VerticalExpand="True"/>
</ScrollContainer>
</BoxContainer>
</BoxContainer>
</PanelContainer>
</Control>
<logs:AdminLogsControl Name="Logs" Access="Public"/>
</SS14Window>

View File

@@ -1,432 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Localization;
using static Robust.Client.UserInterface.Controls.BaseButton;
using static Robust.Client.UserInterface.Controls.LineEdit;
namespace Content.Client.Administration.UI.Logs;
[GenerateTypedNameReferences]
public partial class AdminLogsWindow : Control
public partial class AdminLogsWindow : SS14Window
{
private readonly Comparer<AdminLogTypeButton> _adminLogTypeButtonComparer =
Comparer<AdminLogTypeButton>.Create((a, b) =>
string.Compare(a.Type.ToString(), b.Type.ToString(), StringComparison.Ordinal));
private readonly Comparer<AdminLogPlayerButton> _adminLogPlayerButtonComparer =
Comparer<AdminLogPlayerButton>.Create((a, b) =>
string.Compare(a.Text, b.Text, StringComparison.Ordinal));
public AdminLogsWindow()
{
RobustXamlLoader.Load(this);
TypeSearch.OnTextChanged += TypeSearchChanged;
PlayerSearch.OnTextChanged += PlayerSearchChanged;
LogSearch.OnTextChanged += LogSearchChanged;
SelectAllTypesButton.OnPressed += SelectAllTypes;
SelectNoTypesButton.OnPressed += SelectNoTypes;
SelectAllPlayersButton.OnPressed += SelectAllPlayers;
SelectNoPlayersButton.OnPressed += SelectNoPlayers;
RoundSpinBox.IsValid = i => i > 0 && i <= CurrentRound;
RoundSpinBox.ValueChanged += RoundSpinBoxChanged;
RoundSpinBox.InitDefaultButtons();
ResetRoundButton.OnPressed += ResetRoundPressed;
SetImpacts(Enum.GetValues<LogImpact>().OrderBy(impact => impact).ToArray());
SetTypes(Enum.GetValues<LogType>());
}
private int CurrentRound { get; set; }
public int SelectedRoundId => RoundSpinBox.Value;
public HashSet<LogType> SelectedTypes { get; } = new();
public HashSet<Guid> SelectedPlayers { get; } = new();
public HashSet<LogImpact> SelectedImpacts { get; } = new();
public void SetCurrentRound(int round)
{
CurrentRound = round;
ResetRoundButton.Text = Loc.GetString("admin-logs-reset-with-id", ("id", round));
UpdateResetButton();
}
public void SetRoundSpinBox(int round)
{
RoundSpinBox.Value = round;
UpdateResetButton();
}
private void RoundSpinBoxChanged(object? sender, ValueChangedEventArgs args)
{
UpdateResetButton();
}
private void UpdateResetButton()
{
ResetRoundButton.Disabled = RoundSpinBox.Value == CurrentRound;
}
private void ResetRoundPressed(ButtonEventArgs args)
{
RoundSpinBox.Value = CurrentRound;
}
private void TypeSearchChanged(LineEditEventArgs args)
{
UpdateTypes();
}
private void PlayerSearchChanged(LineEditEventArgs args)
{
UpdatePlayers();
}
private void LogSearchChanged(LineEditEventArgs args)
{
UpdateLogs();
}
private void SelectAllTypes(ButtonEventArgs args)
{
SelectedTypes.Clear();
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Pressed = true;
SelectedTypes.Add(type.Type);
}
UpdateLogs();
}
private void SelectNoTypes(ButtonEventArgs args)
{
SelectedTypes.Clear();
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Pressed = false;
type.Visible = ShouldShowType(type);
}
UpdateLogs();
}
private void SelectAllPlayers(ButtonEventArgs args)
{
SelectedPlayers.Clear();
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Pressed = true;
SelectedPlayers.Add(player.Id);
}
UpdateLogs();
}
private void SelectNoPlayers(ButtonEventArgs args)
{
SelectedPlayers.Clear();
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Pressed = false;
}
UpdateLogs();
}
public void UpdateTypes()
{
foreach (var control in TypesContainer.Children)
{
if (control is not AdminLogTypeButton type)
{
continue;
}
type.Visible = ShouldShowType(type);
}
}
private void UpdatePlayers()
{
foreach (var control in PlayersContainer.Children)
{
if (control is not AdminLogPlayerButton player)
{
continue;
}
player.Visible = ShouldShowPlayer(player);
}
}
private void UpdateLogs()
{
foreach (var child in LogsContainer.Children)
{
if (child is not AdminLogLabel log)
{
continue;
}
child.Visible = ShouldShowLog(log);
}
}
private bool ShouldShowType(AdminLogTypeButton button)
{
return button.Text != null &&
button.Text.Contains(TypeSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private bool ShouldShowPlayer(AdminLogPlayerButton button)
{
return button.Text != null &&
button.Text.Contains(PlayerSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private bool ShouldShowLog(AdminLogLabel label)
{
return SelectedTypes.Contains(label.Log.Type) &&
(SelectedPlayers.Count + label.Log.Players.Length == 0 || SelectedPlayers.Overlaps(label.Log.Players)) &&
SelectedImpacts.Contains(label.Log.Impact) &&
label.Log.Message.Contains(LogSearch.Text, StringComparison.OrdinalIgnoreCase);
}
private void TypeButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogTypeButton) args.Button;
if (button.Pressed)
{
SelectedTypes.Add(button.Type);
}
else
{
SelectedTypes.Remove(button.Type);
}
UpdateLogs();
}
private void PlayerButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogPlayerButton) args.Button;
if (button.Pressed)
{
SelectedPlayers.Add(button.Id);
}
else
{
SelectedPlayers.Remove(button.Id);
}
UpdateLogs();
}
private void ImpactButtonPressed(ButtonEventArgs args)
{
var button = (AdminLogImpactButton) args.Button;
if (button.Pressed)
{
SelectedImpacts.Add(button.Impact);
}
else
{
SelectedImpacts.Remove(button.Impact);
}
UpdateLogs();
}
private void SetImpacts(LogImpact[] impacts)
{
LogImpactContainer.RemoveAllChildren();
foreach (var impact in impacts)
{
var button = new AdminLogImpactButton(impact)
{
Text = impact.ToString()
};
SelectedImpacts.Add(impact);
button.OnPressed += ImpactButtonPressed;
LogImpactContainer.AddChild(button);
}
switch (impacts.Length)
{
case 0:
return;
case 1:
LogImpactContainer.GetChild(0).StyleClasses.Add("OpenRight");
return;
}
for (var i = 0; i < impacts.Length - 1; i++)
{
LogImpactContainer.GetChild(i).StyleClasses.Add("ButtonSquare");
}
LogImpactContainer.GetChild(LogImpactContainer.ChildCount - 1).StyleClasses.Add("OpenLeft");
}
private void SetTypes(LogType[] types)
{
var newTypes = types.ToHashSet();
var buttons = new SortedSet<AdminLogTypeButton>(_adminLogTypeButtonComparer);
foreach (var control in TypesContainer.Children.ToArray())
{
if (control is not AdminLogTypeButton type ||
!newTypes.Remove(type.Type))
{
continue;
}
buttons.Add(type);
}
foreach (var type in newTypes)
{
var button = new AdminLogTypeButton(type)
{
Text = type.ToString(),
Pressed = true
};
SelectedTypes.Add(type);
button.OnPressed += TypeButtonPressed;
buttons.Add(button);
}
TypesContainer.RemoveAllChildren();
foreach (var type in buttons)
{
TypesContainer.AddChild(type);
}
UpdateLogs();
}
public void SetPlayers(Dictionary<Guid, string> players)
{
var buttons = new SortedSet<AdminLogPlayerButton>(_adminLogPlayerButtonComparer);
foreach (var control in PlayersContainer.Children.ToArray())
{
if (control is not AdminLogPlayerButton player ||
!players.Remove(player.Id))
{
continue;
}
buttons.Add(player);
}
foreach (var (id, name) in players)
{
var button = new AdminLogPlayerButton(id)
{
Text = name,
Pressed = true
};
SelectedPlayers.Add(id);
button.OnPressed += PlayerButtonPressed;
buttons.Add(button);
}
PlayersContainer.RemoveAllChildren();
foreach (var player in buttons)
{
PlayersContainer.AddChild(player);
}
UpdateLogs();
}
public void AddLogs(SharedAdminLog[] logs)
{
for (var i = 0; i < logs.Length; i++)
{
ref var log = ref logs[i];
var separator = new HSeparator();
var label = new AdminLogLabel(ref log, separator);
label.Visible = ShouldShowLog(label);
LogsContainer.AddChild(label);
LogsContainer.AddChild(separator);
}
}
public void SetLogs(SharedAdminLog[] logs)
{
LogsContainer.RemoveAllChildren();
AddLogs(logs);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
TypeSearch.OnTextChanged -= TypeSearchChanged;
PlayerSearch.OnTextChanged -= PlayerSearchChanged;
LogSearch.OnTextChanged -= LogSearchChanged;
SelectAllTypesButton.OnPressed -= SelectAllTypes;
SelectNoTypesButton.OnPressed -= SelectNoTypes;
SelectAllPlayersButton.OnPressed -= SelectAllPlayers;
SelectNoPlayersButton.OnPressed -= SelectNoPlayers;
RoundSpinBox.IsValid = null;
RoundSpinBox.ValueChanged -= RoundSpinBoxChanged;
ResetRoundButton.OnPressed -= ResetRoundPressed;
}
}

View File

@@ -1,5 +1,4 @@
using Content.Server.Administration.Logs;
using Content.Server.Administration.UI;
using Content.Server.EUI;
using Content.Shared.Administration;
using Robust.Server.Player;

View File

@@ -26,7 +26,6 @@ public sealed class AdminLogsEui : BaseEui
private readonly ISawmill _sawmill;
private readonly AdminLogSystem _logSystem;
private readonly GameTicker _gameTicker;
private int _clientBatchSize;
private bool _isLoading = true;
@@ -43,7 +42,6 @@ public sealed class AdminLogsEui : BaseEui
_configuration.OnValueChanged(CCVars.AdminLogsClientBatchSize, ClientBatchSizeChanged, true);
_logSystem = EntitySystem.Get<AdminLogSystem>();
_gameTicker = EntitySystem.Get<GameTicker>();
_filter = new LogFilter
{

View File

@@ -1,4 +1,5 @@
admin-logs-title = Admin Logs Panel
admin-logs-pop-out = Pop Out
# Round
admin-logs-round = Round{" "}