Implement portrait generation and retrieval for people in the school system. Added new API endpoints for generating and fetching portraits, including support for avatar and full-body images. Updated the client-side to handle portrait states and display options. Enhanced the person card UI to include tabs for overview and portrait, with appropriate localization strings. Updated solution files to include new test projects. Adjusted server configuration for SwarmUI integration.
ci / server (push) Failing after 3m46s
ci / client (push) Failing after 14s

This commit is contained in:
Leonid Pershin
2026-08-20 04:14:41 +03:00
parent 871178909e
commit dfa9a25dca
32 changed files with 1538 additions and 121 deletions
+25 -1
View File
@@ -262,6 +262,10 @@ no Chemistry; a related tongue from the name set may sit beside the native at a
overload does not slow walking. Home and locker stay in `people.json` and are not on this card.
The people list does not include any of these fields.
`hasAvatar` and `hasFullBody` tell the client whether PNG files already exist on disk for this
person. They are filled on the HTTP thread after the worker returns the card; generation does
not happen on this request.
```json
{
"id": "f0.c0",
@@ -308,10 +312,30 @@ The people list does not include any of these fields.
}
],
"carryMass": 1.2,
"carryCapacity": 14
"carryCapacity": 14,
"hasAvatar": false,
"hasFullBody": false
}
```
### `GET /api/schools/{id}/people/{personId}/portrait`
Returns a generated PNG when one exists. Query `kind=avatar|full` selects head-and-shoulders or
full-body. Unknown school is `404` `unknown-school`; unknown person is `404` `unknown-person`;
missing file is `404` `portrait-missing`. Invalid `kind` is `400` `invalid-query`. Content-Type
is `image/png`. Opening the card does not generate; use POST when the player asks.
### `POST /api/schools/{id}/people/{personId}/portrait`
Generates (or regenerates) a portrait through SwarmUI on the server. Same `kind` query as GET.
Success is `201` with `{ "kind", "hasAvatar", "hasFullBody" }` and a `Location` header pointing
at GET. SwarmUI is not configured when `SwarmUi:BaseUrl` is empty — `503` `swarmui-not-configured`.
Swarm errors are `502` `swarmui-unavailable`; a slow backend is `504` `swarmui-timeout`. Files
land under `saves/{id}.portraits/` and survive until the school is deleted.
`GET /api/status` includes `swarmUiConfigured` so the client can disable generate buttons without
trying POST first.
### `GET /api/schools/{id}/staffing`
Money, uncovered subjects, the applicant pool and current staff. Reads the **published**