feat(library): add the game data correction dialog
Build, Test & Push Frontend / quality-check (push) Successful in 17s
Build, Test & Push Frontend / docker (push) Successful in 25s

This commit is contained in:
lobo committed 2026-09-28 09:31:39 +02:00
1 parent afe00ceae9
commit 6601277961
9 files changed
+434 -3

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
import {apiFetch} from './api.js';
import {ROLES} from './admin.js';
const JSON_HEADERS = {'Content-Type': 'application/json'};
const url = (appid, field) =>
`${import.meta.env.VITE_CORE_API_URL}/api/library/games/${appid}/corrections/${field}`;
/**
* IGDB's genre names, the values Core stores. Each has a STATS.GENRE key (see genreKey).
*/
export const IGDB_GENRES = ['Adventure', 'Arcade', 'Card & Board Game', 'Fighting', "Hack and slash/Beat 'em up",
'Indie', 'MOBA', 'Music', 'Pinball', 'Platform', 'Point-and-click', 'Puzzle', 'Quiz/Trivia', 'Racing',
'Real Time Strategy (RTS)', 'Role-playing (RPG)', 'Shooter', 'Simulator', 'Sport', 'Strategy', 'Tactical',
'Turn-based strategy (TBS)', 'Visual Novel'];
// SPEEDRUN is the speedrun link, not a stored mood.
export const CORRECTABLE_MOODS = ['STORY', 'COOP', 'CHILL', 'ACTION', 'SCARY'];
/**
* An AUDITOR or higher, by the active role: an admin viewing as USER cannot correct.
*/
export const canCorrect = (currentUser) =>
!!currentUser && ROLES.indexOf(currentUser.activeRole) >= ROLES.indexOf('AUDITOR');
/**
* PUT: 204, 400 {code: INVALID_CORRECTION, message}, 403 below AUDITOR, 404 unknown game.
*/
export const saveCorrection = (appid, field, value) =>
apiFetch(url(appid, field), {method: 'PUT', headers: JSON_HEADERS, body: JSON.stringify({value})});
/**
* DELETE: back to the source's value, 204.
*/
export const resetCorrection = (appid, field) => apiFetch(url(appid, field), {method: 'DELETE'});
+22
View File
@@ -0,0 +1,22 @@
import {describe, expect, it} from 'vitest';
import en from '../../public/i18n/en.json';
import de from '../../public/i18n/de.json';
import {canCorrect, IGDB_GENRES} from './corrections.js';
import {genreKey} from './stats.js';
describe('corrections', () => {
it('knows a text for every IGDB genre it offers', () => {
for (const genre of IGDB_GENRES) {
expect(en.STATS.GENRE[genreKey(genre)], genre).toBeTruthy();
expect(de.STATS.GENRE[genreKey(genre)], genre).toBeTruthy();
}
});
it('lets only an active AUDITOR or higher correct', () => {
expect(canCorrect({role: 'AUDITOR', activeRole: 'AUDITOR'})).toBe(true);
expect(canCorrect({role: 'PLATFORM_ADMIN', activeRole: 'PLATFORM_ADMIN'})).toBe(true);
expect(canCorrect({role: 'PLATFORM_ADMIN', activeRole: 'USER'})).toBe(false);
expect(canCorrect({role: 'USER', activeRole: 'USER'})).toBe(false);
expect(canCorrect(null)).toBe(false);
});
});