Implement people management features by adding API endpoints for retrieving school rosters and individual person cards. Enhance the UI to support a people browser with filtering and pagination capabilities. Update localization strings for improved user experience and ensure robust handling of person data. Revise documentation to reflect new API functionalities and update tests to validate the new features.
ci / server (push) Failing after 11s
ci / client (push) Successful in 17s

This commit is contained in:
Leonid Pershin
2026-08-18 19:44:42 +03:00
parent 52c5082418
commit 533bd80f5e
23 changed files with 2134 additions and 47 deletions
@@ -1,5 +1,7 @@
using HSchool.Content;
using HSchool.People;
using HSchool.Protocol;
using HSchool.Server.Api;
using HSchool.Server.Net;
using HSchool.Simulation;
using Microsoft.Extensions.Options;
@@ -52,6 +54,23 @@ internal sealed class GameLoopService(
}
}
/// <summary>
/// Menu-style read of one school's published roster and frozen catalog. Does not post to the
/// mailbox — the list is HTTP over a snapshot, the same way the menu reads clocks.
/// </summary>
public PublishedSchoolPeople? FindPeople(int schoolId)
{
foreach (var worker in Volatile.Read(ref _publishedWorkers))
{
if (worker.Id == schoolId)
{
return new PublishedSchoolPeople(worker.Snapshot, worker.RosterSnapshot, worker.CatalogSnapshot);
}
}
return null;
}
public Task ReloadFromDiskAsync(CancellationToken cancellationToken)
{
var completion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
@@ -148,6 +167,19 @@ internal sealed class GameLoopService(
case GameCommand.WorkerFailed failed:
HandleWorkerFailed(failed.SchoolId);
break;
case GameCommand.GetPerson getPerson:
HandleGetPerson(getPerson);
break;
}
}
private void HandleGetPerson(GameCommand.GetPerson command)
{
if (!_workers.TryGetValue(command.SchoolId, out var worker)
|| !worker.Post(new WorkerCommand.GetPerson(command.PersonId, command.Locale, command.Result)))
{
command.Result.TrySetResult(new PersonCardResult(null, PersonLookupError.UnknownSchool));
}
}
@@ -548,3 +580,5 @@ internal sealed class GameLoopService(
}
}
}
internal sealed record PublishedSchoolPeople(SchoolState School, Roster? Roster, DefCatalog? Catalog);