feat: Admin Area System: Database Backup/Restore and Danger Zone
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { DestroyRef, Injectable, computed, inject, signal } from '@angular/core';
|
||||
import { DestroyRef, Injectable, computed, effect, inject, signal } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
BoardCard,
|
||||
@@ -17,11 +17,13 @@ import {
|
||||
} from './challenges.pure';
|
||||
import { ChallengesApiService } from './challenges.service';
|
||||
import { EventSourceLike } from '../../core/services/event-status.pure';
|
||||
import { SystemDataChangeService } from '../../core/services/system-data-change.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ChallengesStore {
|
||||
private readonly api: ChallengesApiService;
|
||||
private readonly destroyRef: DestroyRef;
|
||||
private readonly dataChanges: SystemDataChangeService | null;
|
||||
|
||||
private readonly _board = signal<BoardResponse | null>(null);
|
||||
private readonly _eventState = signal<EventStatePayloadLike['state']>('unconfigured');
|
||||
@@ -35,10 +37,35 @@ export class ChallengesStore {
|
||||
|
||||
private readonly solveListeners = new Map<string, Set<(p: SolveEventLivePayload) => void>>();
|
||||
|
||||
constructor(api?: ChallengesApiService, destroyRef?: DestroyRef) {
|
||||
constructor(api?: ChallengesApiService, destroyRef?: DestroyRef, dataChanges?: SystemDataChangeService) {
|
||||
this.api = api ?? inject(ChallengesApiService);
|
||||
this.destroyRef = destroyRef ?? inject(DestroyRef);
|
||||
this.dataChanges = dataChanges ?? null;
|
||||
this.destroyRef.onDestroy(() => this.stop());
|
||||
this.installDataChangeListeners();
|
||||
}
|
||||
|
||||
private installDataChangeListeners(): void {
|
||||
if (!this.dataChanges) return;
|
||||
const lastSeen = { ts: 0 };
|
||||
effect(() => {
|
||||
const evts = this.dataChanges!.events();
|
||||
const latest = evts[evts.length - 1];
|
||||
if (!latest || latest.ts === lastSeen.ts) return;
|
||||
lastSeen.ts = latest.ts;
|
||||
if (latest.kind === 'challenges-wiped' || latest.kind === 'restore-completed' || latest.kind === 'scores-reset') {
|
||||
this.reset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposed for callers that want to clear the cached board/selected detail
|
||||
* after a destructive operation (e.g. challenge wipe). The signal
|
||||
* subscription above re-evaluates when `events()` mutates.
|
||||
*/
|
||||
invalidateForSystemChange(_kind: 'scores-reset' | 'challenges-wiped' | 'restore-completed'): void {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
readonly board = this._board.asReadonly();
|
||||
|
||||
Reference in New Issue
Block a user