Unfinalize everyone on suggestion linking changes
This commit is contained in:
3
API.md
3
API.md
@@ -34,6 +34,7 @@ GET /api/results — leaderboard with totals, counts, averages, caller’s vote,
|
|||||||
## Admin (admin auth or admin key)
|
## Admin (admin auth or admin key)
|
||||||
POST /api/admin/results — `{ resultsOpen: bool }` locks/unlocks results and aligns player phases
|
POST /api/admin/results — `{ resultsOpen: bool }` locks/unlocks results and aligns player phases
|
||||||
GET /api/admin/vote-status — readiness overview (who finalized)
|
GET /api/admin/vote-status — readiness overview (who finalized)
|
||||||
POST /api/admin/link-suggestions — `{ sourceSuggestionId, targetSuggestionId }`; merges vote groups during Vote, clears votes in the linked group, unfinalizes affected players
|
POST /api/admin/link-suggestions — `{ sourceSuggestionId, targetSuggestionId }`; merges vote groups during Vote, clears votes in the linked group, unfinalizes **all** players
|
||||||
|
POST /api/admin/unlink-suggestions — `{ suggestionId }`; breaks links, clears votes for that group, unfinalizes **all** players
|
||||||
POST /api/admin/reset — clear suggestions/votes; keep players; reset phases/vote-final flags
|
POST /api/admin/reset — clear suggestions/votes; keep players; reset phases/vote-final flags
|
||||||
POST /api/admin/factory-reset — wipe players, suggestions, votes, state
|
POST /api/admin/factory-reset — wipe players, suggestions, votes, state
|
||||||
|
|||||||
@@ -152,14 +152,9 @@ public static class AdminEndpoints
|
|||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
var affectedPlayerIds = await db.Votes.Where(v => affectedIds.Contains(v.SuggestionId)).Select(v => v.PlayerId).Distinct().ToListAsync();
|
|
||||||
|
|
||||||
await db.Votes.Where(v => affectedIds.Contains(v.SuggestionId)).ExecuteDeleteAsync();
|
await db.Votes.Where(v => affectedIds.Contains(v.SuggestionId)).ExecuteDeleteAsync();
|
||||||
|
|
||||||
if (affectedPlayerIds.Count > 0)
|
await db.Players.ExecuteUpdateAsync(p => p.SetProperty(x => x.VotesFinal, false));
|
||||||
{
|
|
||||||
await db.Players.Where(p => affectedPlayerIds.Contains(p.Id)).ExecuteUpdateAsync(p => p.SetProperty(x => x.VotesFinal, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
await tx.CommitAsync();
|
await tx.CommitAsync();
|
||||||
|
|
||||||
@@ -167,7 +162,7 @@ public static class AdminEndpoints
|
|||||||
{
|
{
|
||||||
RootId = targetRoot,
|
RootId = targetRoot,
|
||||||
LinkedSuggestionIds = affectedIds,
|
LinkedSuggestionIds = affectedIds,
|
||||||
UnfinalizedPlayers = affectedPlayerIds.Count
|
UnfinalizedPlayers = await db.Players.CountAsync()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -209,21 +204,16 @@ public static class AdminEndpoints
|
|||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
var affectedPlayerIds = await db.Votes.Where(v => groupIds.Contains(v.SuggestionId)).Select(v => v.PlayerId).Distinct().ToListAsync();
|
|
||||||
|
|
||||||
await db.Votes.Where(v => groupIds.Contains(v.SuggestionId)).ExecuteDeleteAsync();
|
await db.Votes.Where(v => groupIds.Contains(v.SuggestionId)).ExecuteDeleteAsync();
|
||||||
|
|
||||||
if (affectedPlayerIds.Count > 0)
|
await db.Players.ExecuteUpdateAsync(p => p.SetProperty(x => x.VotesFinal, false));
|
||||||
{
|
|
||||||
await db.Players.Where(p => affectedPlayerIds.Contains(p.Id)).ExecuteUpdateAsync(p => p.SetProperty(x => x.VotesFinal, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
await tx.CommitAsync();
|
await tx.CommitAsync();
|
||||||
|
|
||||||
return Results.Ok(new
|
return Results.Ok(new
|
||||||
{
|
{
|
||||||
UnlinkedSuggestionIds = groupIds,
|
UnlinkedSuggestionIds = groupIds,
|
||||||
UnfinalizedPlayers = affectedPlayerIds.Count
|
UnfinalizedPlayers = await db.Players.CountAsync()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ Wenn ein Admin doppelte Spiele verknüpft:
|
|||||||
|
|
||||||
Mit **„Finalisieren"** werden deine Bewertungen gesperrt. Deaktiviere es, um erneut zu bearbeiten.
|
Mit **„Finalisieren"** werden deine Bewertungen gesperrt. Deaktiviere es, um erneut zu bearbeiten.
|
||||||
|
|
||||||
„Finalisieren" ist nur während der Abstimmungsphase verfügbar und wird automatisch zurückgesetzt, wenn:
|
„Finalisieren" ist nur während der Abstimmungsphase verfügbar und wird für **alle** automatisch zurückgesetzt, wenn:
|
||||||
- Ein Joker ein neues Spiel hinzufügt
|
- Ein Joker ein neues Spiel hinzufügt
|
||||||
- Ein Admin Spiele verknüpft oder trennt
|
- Ein Admin Spiele verknüpft oder trennt
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ Mit **„Finalisieren"** werden deine Bewertungen gesperrt. Deaktiviere es, um e
|
|||||||
|
|
||||||
Wenn neue Spiele hinzugefügt oder Verknüpfungen geändert werden:
|
Wenn neue Spiele hinzugefügt oder Verknüpfungen geändert werden:
|
||||||
- Betroffene Stimmen werden gelöscht
|
- Betroffene Stimmen werden gelöscht
|
||||||
- Deine Abstimmung wird automatisch zurückgesetzt
|
- Alle Abstimmungen werden automatisch zurückgesetzt
|
||||||
|
|
||||||
Überprüfe deine Liste und bewerte erneut, bevor du wieder finalisierst.
|
Überprüfe deine Liste und bewerte erneut, bevor du wieder finalisierst.
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ If an admin links duplicate games:
|
|||||||
|
|
||||||
Toggling **"Finalize"** locks your scores. Toggle it off to edit again.
|
Toggling **"Finalize"** locks your scores. Toggle it off to edit again.
|
||||||
|
|
||||||
Finalize is only available during the Vote phase and will automatically reset if:
|
Finalize is only available during the Vote phase and will automatically reset for **everyone** if:
|
||||||
- A joker adds a new game
|
- A joker adds a new game
|
||||||
- An admin links or unlinks games
|
- An admin links or unlinks games
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ Finalize is only available during the Vote phase and will automatically reset if
|
|||||||
|
|
||||||
If new games are added or links are modified:
|
If new games are added or links are modified:
|
||||||
- Affected votes are cleared
|
- Affected votes are cleared
|
||||||
- You are automatically unfinalized
|
- Everyone is automatically unfinalized
|
||||||
|
|
||||||
Review your list and rescore before finalizing again.
|
Review your list and rescore before finalizing again.
|
||||||
|
|
||||||
|
|||||||
@@ -359,6 +359,41 @@ public class AdminTests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Link_unfinalizes_all_players()
|
||||||
|
{
|
||||||
|
await using var factory = new TestWebApplicationFactory();
|
||||||
|
var admin = factory.CreateClientWithCookies();
|
||||||
|
await admin.RegisterAsync("admin", admin: true);
|
||||||
|
var p1 = factory.CreateClientWithCookies();
|
||||||
|
await p1.RegisterAsync("p1");
|
||||||
|
var p2 = factory.CreateClientWithCookies();
|
||||||
|
await p2.RegisterAsync("p2");
|
||||||
|
|
||||||
|
var a = await p1.CreateSuggestionAsync("A");
|
||||||
|
var b = await p1.CreateSuggestionAsync("B");
|
||||||
|
|
||||||
|
await admin.PostAsJsonAsync("/api/me/phase/next", new { });
|
||||||
|
await p1.PostAsJsonAsync("/api/me/phase/next", new { });
|
||||||
|
await p2.PostAsJsonAsync("/api/me/phase/next", new { });
|
||||||
|
|
||||||
|
await p1.PostAsJsonAsync("/api/votes/finalize", new { Final = true });
|
||||||
|
await p2.PostAsJsonAsync("/api/votes/finalize", new { Final = true });
|
||||||
|
|
||||||
|
var link = await admin.PostAsJsonAsync("/api/admin/link-suggestions", new
|
||||||
|
{
|
||||||
|
SourceSuggestionId = a,
|
||||||
|
TargetSuggestionId = b
|
||||||
|
});
|
||||||
|
link.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
await factory.WithDbContextAsync(async db =>
|
||||||
|
{
|
||||||
|
var players = await db.Players.Where(p => !p.IsAdmin).ToListAsync();
|
||||||
|
Assert.All(players, p => Assert.False(p.VotesFinal));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Unlink_not_found_returns_empty_payload()
|
public async Task Unlink_not_found_returns_empty_payload()
|
||||||
{
|
{
|
||||||
|
|||||||
2
SPEC.md
2
SPEC.md
@@ -23,7 +23,7 @@ Help a small Discord group (4–8 players) pick a co-op game via phased flow:
|
|||||||
- Score each suggestion 0–10
|
- Score each suggestion 0–10
|
||||||
- Players see only their own votes; can finalize/unfinalize their ballot
|
- Players see only their own votes; can finalize/unfinalize their ballot
|
||||||
- **Linked games**: admins can link duplicates; linked games share a vote group. Moving a slider on one updates all linked siblings.
|
- **Linked games**: admins can link duplicates; linked games share a vote group. Moving a slider on one updates all linked siblings.
|
||||||
- Linking two games clears votes for the linked group and unfinalizes affected players
|
- Linking or unlinking games clears votes for the linked group and unfinalizes **all** players so ballots can be reviewed again
|
||||||
|
|
||||||
## Results Phase
|
## Results Phase
|
||||||
- Visible only after admin enables results; players auto-advance when opened
|
- Visible only after admin enables results; players auto-advance when opened
|
||||||
|
|||||||
@@ -508,6 +508,7 @@ No. Suggestions and votes are read-only. Contact an admin for assistance.
|
|||||||
|
|
||||||
- Grant jokers during Vote
|
- Grant jokers during Vote
|
||||||
- Link or unlink duplicate suggestions
|
- Link or unlink duplicate suggestions
|
||||||
|
- Delete suggestions
|
||||||
- View vote readiness (who has finalized)
|
- View vote readiness (who has finalized)
|
||||||
- Delete a player (removes their suggestions and votes)
|
- Delete a player (removes their suggestions and votes)
|
||||||
- Reset the database to factory defaults
|
- Reset the database to factory defaults
|
||||||
@@ -695,6 +696,7 @@ Nein. Vorschläge und Bewertungen sind schreibgeschützt. Wende dich bei Bedarf
|
|||||||
|
|
||||||
- Joker während der Abstimmung vergeben
|
- Joker während der Abstimmung vergeben
|
||||||
- Doppelte Vorschläge verknüpfen oder trennen
|
- Doppelte Vorschläge verknüpfen oder trennen
|
||||||
|
- Vorschläge löschen
|
||||||
- Abstimmungsstatus einsehen (wer finalisiert hat)
|
- Abstimmungsstatus einsehen (wer finalisiert hat)
|
||||||
- Einen Spieler löschen (inklusive dessen Vorschläge und Stimmen)
|
- Einen Spieler löschen (inklusive dessen Vorschläge und Stimmen)
|
||||||
- Die Datenbank auf Werkseinstellungen zurücksetzen
|
- Die Datenbank auf Werkseinstellungen zurücksetzen
|
||||||
|
|||||||
Reference in New Issue
Block a user