Merge feature/admin-pause in main

This commit is contained in:
mregosar committed 2026-10-26 00:50:27 +01:00
commit 1d627c212a
4 files changed
+20

No files matched your search

+2
View File
@@ -217,6 +217,8 @@ function MatchAdminCard({ m, run, busy, token, reload, setNotice }) {
<Link className="btn btn-sm" to={`/m/${id}`}>Ansehen</Link> <Link className="btn btn-sm" to={`/m/${id}`}>Ansehen</Link>
{m.status === 'lobby' && btn('Veto starten', { path: '/veto/start' }, 'btn-primary')} {m.status === 'lobby' && btn('Veto starten', { path: '/veto/start' }, 'btn-primary')}
{(m.server?.status === 'configured') && btn('Aufwärmphase beenden', { path: '/server/warmup-end' })} {(m.server?.status === 'configured') && btn('Aufwärmphase beenden', { path: '/server/warmup-end' })}
{(m.server?.status === 'configured') && btn('Pausieren', { path: '/server/pause', confirm: 'Match pausieren?' })}
{(m.server?.status === 'configured') && btn('Fortsetzen', { path: '/server/resume' })}
{(m.server?.status === 'configured') && hasNext && btn('Nächste Map', { path: '/series/next' })} {(m.server?.status === 'configured') && hasNext && btn('Nächste Map', { path: '/series/next' })}
{m.server && ['start_failed', 'failed', 'stopped', 'config_failed', 'ready'].includes(m.server.status) && !closed && {m.server && ['start_failed', 'failed', 'stopped', 'config_failed', 'ready'].includes(m.server.status) && !closed &&
btn('Server neu starten / wiederholen', { path: '/server/retry' })} btn('Server neu starten / wiederholen', { path: '/server/retry' })}
+2
View File
@@ -92,6 +92,8 @@ export function createAdminRouter({ service, manager, config }) {
action('server/stop', (v) => manager.stopByOrganizer(v)); action('server/stop', (v) => manager.stopByOrganizer(v));
action('server/retry', (v) => manager.retry(v)); action('server/retry', (v) => manager.retry(v));
action('server/warmup-end', (v) => manager.endWarmup(v)); action('server/warmup-end', (v) => manager.endWarmup(v));
action('server/pause', (v) => manager.setPaused(v, true));
action('server/resume', (v) => manager.setPaused(v, false));
action('series/next', (v) => manager.loadNextMap(v)); action('series/next', (v) => manager.loadNextMap(v));
action('veto/start', (v) => service.startVeto(v)); action('veto/start', (v) => service.startVeto(v));
action('veto/action', (v, b) => service.vetoAction( action('veto/action', (v, b) => service.vetoAction(
+15
View File
@@ -391,6 +391,21 @@ export class ServerManager {
this.service.changed(viewer.matchId); this.service.changed(viewer.matchId);
} }
/** Admin: pausiert oder setzt das laufende Match auf dem Server fort (mp_pause_match / mp_unpause_match). */
async setPaused(viewer, paused) {
this.service.require(viewer, 'organizer');
const row = this.row(viewer.matchId);
if (row?.status !== 'configured') throw new HttpError(409, 'Der Server ist nicht bereit', 'wrong_state');
if (!this.adapter.sendCommands) throw new HttpError(501, 'Dieser Adapter unterstützt keine Befehle', 'unsupported');
try {
await this.adapter.sendCommands(JSON.parse(row.handle), [paused ? 'mp_pause_match' : 'mp_unpause_match']);
} catch (err) {
throw new HttpError(502, `Befehl konnte nicht gesendet werden: ${err.message}`, 'server_error');
}
this.service.log(viewer.matchId, 'server', paused ? 'Match pausiert (Admin)' : 'Match fortgesetzt (Admin)');
this.service.changed(viewer.matchId);
}
/** Demo-Modus: simuliert einen Matchverlauf, indem echte CS2-Logzeilen erzeugt und ausgewertet werden. */ /** Demo-Modus: simuliert einen Matchverlauf, indem echte CS2-Logzeilen erzeugt und ausgewertet werden. */
startDemoSimulation(matchId) { startDemoSimulation(matchId) {
const match = this.service.getMatch(matchId); const match = this.service.getMatch(matchId);
+1
View File
@@ -401,6 +401,7 @@ test('Admin-Modus: Anmeldung, Verwaltung aller Matches, Sperre ohne Anmeldung',
// Ein Match abbrechen wie ein Admin // Ein Match abbrechen wie ein Admin
assert.equal((await call('POST', `/admin/matches/${id}/cancel`, { ...admin, body: {} })).status, 200); assert.equal((await call('POST', `/admin/matches/${id}/cancel`, { ...admin, body: {} })).status, 200);
assert.equal((await call('POST', `/admin/matches/${id}/server/pause`, { ...admin, body: {} })).status, 409, 'ohne Server keine Pause');
assert.equal(app.service.getMatch(id).status, 'cancelled'); assert.equal(app.service.getMatch(id).status, 'cancelled');
// Endgültig löschen // Endgültig löschen