Show all weapons in multi-weapon VoD when filtering

This commit is contained in:
Kalle
2026-09-14 18:00:04 +03:00
parent b6b9e4eed2
commit 70216080b4
3 changed files with 47 additions and 2 deletions

View File

@@ -127,6 +127,35 @@ describe("findVods", () => {
expect(result).toHaveLength(1);
});
test("returns the vod's full weapon list with the filtered weapon first", async () => {
await VodFactory.create({
submitterUserId: users.id(1),
matches: [
{ mode: "TW", stageId: 1, startsAt: "0:00", weapons: [10, 20, 30] },
{ mode: "SZ", stageId: 2, startsAt: "5:00", weapons: [0] },
],
});
const [result] = await VodRepository.findVods({ weapon: 0 });
expect(result.weapons).toHaveLength(4);
expect(result.weapons[0]).toBe(0);
});
test("alt skin of the filtered weapon leads the list", async () => {
await VodFactory.create({
submitterUserId: users.id(1),
matches: [
{ mode: "TW", stageId: 1, startsAt: "0:00", weapons: [10, 45] },
],
});
const [result] = await VodRepository.findVods({ weapon: 40 });
expect(result.weapons).toHaveLength(2);
expect(result.weapons[0]).toBe(45);
});
test("filters by type", async () => {
for (const type of ["TOURNAMENT", "CAST", "SCRIM"] as const) {
await VodFactory.create({ submitterUserId: users.id(1), type });

View File

@@ -72,7 +72,6 @@ export async function findVods({
.whereRef("User.id", "=", "VideoMatchPlayer.playerUserId"),
).as("players"),
])
.where(vodFilters(filters))
// the page is resolved by id first: with the limit on this read, the aggregates
// of every matching vod would be computed before it applies
.where(
@@ -88,9 +87,10 @@ export async function findVods({
.execute();
const vods = result.map((value) => {
const { playerNames, players, ...vod } = value;
const { playerNames, players, weapons, ...vod } = value;
return {
...vod,
weapons: filteredWeaponFirst(weapons, filters.weapon),
pov: playerNames[0] ?? players[0],
};
});
@@ -318,6 +318,17 @@ type VodsWithMatchesDB =
type VodsTables = "Video" | "VideoMatch" | "VideoMatchPlayer";
/** The filtered weapon and its alt skins lead the list so the listing's peek always shows what was filtered for. */
function filteredWeaponFirst(
weapons: MainWeaponId[],
weapon: MainWeaponId | undefined,
) {
if (weapon === undefined) return weapons;
const filtered = new Set(weaponIdToArrayWithAlts(weapon));
return R.partition(weapons, (id) => filtered.has(id)).flat();
}
/** Conditions the filters put on the match rows. `userId` makes the vod's own filters moot: it is the user's vods regardless. */
function vodFilters({ weapon, mode, stageId, type, userId }: VodFilters) {
return (eb: ExpressionBuilder<VodsWithMatchesDB, VodsTables>) => {

View File

@@ -0,0 +1,5 @@
---
navItem: vods
type: feature
---
Filtering VODs by a weapon now shows each VOD's full weapon list, with the weapon you filtered by first