public string Search => LogSearch.Text;
private int ShownLogs { get; set; }
private int TotalLogs { get; set; }
+ private int RoundLogs { get; set; }
public bool IncludeNonPlayerLogs { get; set; }
public HashSet<LogType> SelectedTypes { get; } = new();
AddLogs(logs);
}
- private void UpdateCount(int? shown = null, int? total = null)
+ public void UpdateCount(int? shown = null, int? total = null, int? round = null)
{
if (shown != null)
{
TotalLogs = total.Value;
}
- Count.Text = Loc.GetString("admin-logs-count", ("showing", ShownLogs), ("total", TotalLogs));
+ if (round != null)
+ {
+ RoundLogs = round.Value;
+ }
+
+ Count.Text = Loc.GetString(
+ "admin-logs-count",
+ ("showing", ShownLogs), ("total", TotalLogs), ("round", RoundLogs)
+ );
}
protected override void Dispose(bool disposing)
private void NextLogs()
{
+ LogsControl.NextButton.Disabled = true;
var request = new NextLogsRequest();
SendMessage(request);
}
Maximized = false,
Title = "Admin Logs",
Monitor = monitor,
- Width = 1000,
+ Width = 1100,
Height = 400
});
LogsControl.SetCurrentRound(s.RoundId);
LogsControl.SetPlayers(s.Players);
+ LogsControl.UpdateCount(round: s.RoundLogs);
if (!FirstState)
{
<DefaultWindow xmlns="https://spacestation14.io"
xmlns:logs="clr-namespace:Content.Client.Administration.UI.Logs"
Title="{Loc admin-logs-title}"
- SetSize="1000 400">
+ SetSize="1100 400">
<logs:AdminLogsControl Name="Logs" Access="Public"/>
</DefaultWindow>
{
return Round(_currentRoundId);
}
+
+ public Task<int> CountLogs(int round)
+ {
+ return _db.CountAdminLogs(round);
+ }
}
private int _clientBatchSize;
private bool _isLoading = true;
private readonly Dictionary<Guid, string> _players = new();
+ private int _roundLogs;
private CancellationTokenSource _logSendCancellation = new();
private LogFilter _filter;
- private DefaultObjectPool<List<SharedAdminLog>> _adminLogListPool =
+ private readonly DefaultObjectPool<List<SharedAdminLog>> _adminLogListPool =
new(new ListPolicy<SharedAdminLog>());
public AdminLogsEui()
};
}
- public int CurrentRoundId => EntitySystem.Get<GameTicker>().RoundId;
+ private int CurrentRoundId => EntitySystem.Get<GameTicker>().RoundId;
public override async void Opened()
{
_adminManager.OnPermsChanged += OnPermsChanged;
- var roundId = _filter.Round ?? EntitySystem.Get<GameTicker>().RoundId;
- LoadFromDb(roundId);
+ var roundId = _filter.Round ?? CurrentRoundId;
+ await LoadFromDb(roundId);
}
private void ClientBatchSizeChanged(int value)
{
if (_isLoading)
{
- return new AdminLogsEuiState(CurrentRoundId, new Dictionary<Guid, string>())
+ return new AdminLogsEuiState(CurrentRoundId, new Dictionary<Guid, string>(), 0)
{
IsLoading = true
};
}
- var state = new AdminLogsEuiState(CurrentRoundId, _players);
+ var state = new AdminLogsEuiState(CurrentRoundId, _players, _roundLogs);
return state;
}
AnyPlayers = request.AnyPlayers,
AllPlayers = request.AllPlayers,
IncludeNonPlayers = request.IncludeNonPlayers,
- LastLogId = 0,
+ LastLogId = null,
Limit = _clientBatchSize
};
- var roundId = _filter.Round ??= EntitySystem.Get<GameTicker>().RoundId;
- LoadFromDb(roundId);
+ var roundId = _filter.Round ??= CurrentRoundId;
+ await LoadFromDb(roundId);
SendLogs(true);
break;
_logSendCancellation.Dispose();
}
- private async void LoadFromDb(int roundId)
+ private async Task LoadFromDb(int roundId)
{
_isLoading = true;
StateDirty();
- var round = await Task.Run(() => _adminLogs.Round(roundId));
- var players = round.Players
+ var round = _adminLogs.Round(roundId);
+ var count = _adminLogs.CountLogs(roundId);
+ await Task.WhenAll(round, count);
+
+ var players = (await round).Players
.ToDictionary(player => player.UserId, player => player.LastSeenUserName);
_players.Clear();
_players.Add(id, name);
}
+ _roundLogs = await count;
+
_isLoading = false;
StateDirty();
}
IAsyncEnumerable<string> CurrentRoundMessages(LogFilter? filter = null);
IAsyncEnumerable<JsonDocument> CurrentRoundJson(LogFilter? filter = null);
Task<Round> CurrentRound();
+ Task<int> CountLogs(int round);
}
{
query = filter.DateOrder switch
{
- DateOrder.Ascending => query.Where(log => log.Id < filter.LastLogId),
- DateOrder.Descending => query.Where(log => log.Id > filter.LastLogId),
+ DateOrder.Ascending => query.Where(log => log.Id > filter.LastLogId),
+ DateOrder.Descending => query.Where(log => log.Id < filter.LastLogId),
_ => throw new ArgumentOutOfRangeException(nameof(filter),
$"Unknown {nameof(DateOrder)} value {filter.DateOrder}")
};
}
}
+ public async Task<int> CountAdminLogs(int round)
+ {
+ await using var db = await GetDb();
+ return await db.DbContext.AdminLog.CountAsync(log => log.RoundId == round);
+ }
+
#endregion
#region Whitelist
IAsyncEnumerable<string> GetAdminLogMessages(LogFilter? filter = null);
IAsyncEnumerable<SharedAdminLog> GetAdminLogs(LogFilter? filter = null);
IAsyncEnumerable<JsonDocument> GetAdminLogsJson(LogFilter? filter = null);
+ Task<int> CountAdminLogs(int round);
#endregion
return _db.GetAdminLogsJson(filter);
}
+ public Task<int> CountAdminLogs(int round)
+ {
+ DbReadOpsMetric.Inc();
+ return _db.CountAdminLogs(round);
+ }
+
public Task<bool> GetWhitelistStatusAsync(NetUserId player)
{
DbReadOpsMetric.Inc();
[Serializable, NetSerializable]
public sealed class AdminLogsEuiState : EuiStateBase
{
- public AdminLogsEuiState(int roundId, Dictionary<Guid, string> players)
+ public AdminLogsEuiState(int roundId, Dictionary<Guid, string> players, int roundLogs)
{
RoundId = roundId;
Players = players;
+ RoundLogs = roundLogs;
}
public bool IsLoading { get; set; }
public int RoundId { get; }
public Dictionary<Guid, string> Players { get; }
+
+ public int RoundLogs { get; }
}
public static class AdminLogsEuiMsg
admin-logs-title = Admin Logs Panel
-admin-logs-count = Showing {$showing}/{$total}
+admin-logs-count = Showing {$showing}/{$total} of {$round}
admin-logs-pop-out = Pop Out
# Round