AI Implementation feature(869): Admin Area Blog and Blog Page (#58)

This commit was merged in pull request #58.
This commit is contained in:
2026-07-23 10:17:55 +00:00
parent d468cca766
commit 294873240b
32 changed files with 1798 additions and 117 deletions
+20 -3
View File
@@ -1,9 +1,9 @@
---
type: architecture
title: Key Files Index
description: One-line responsibility for important source and contract-test files, including strict event-window validation, the public bootstrap SSE listener, the challenges full-replace import flow, the authenticated player-facing challenges board, and the per-user `solvedByMe` reset on the session boundary.
tags: [architecture, key-files, event-window, validation, default-challenge-ip, sse, bootstrap, migrations, challenges, import, board, notifications, per-user, session]
timestamp: 2026-07-23T04:05:00Z
description: One-line responsibility for important source and contract-test files, including event-window, challenge, scoreboard, session, notification, and blog flows.
tags: [architecture, key-files, event-window, validation, default-challenge-ip, sse, bootstrap, migrations, challenges, import, board, notifications, per-user, session, blog]
timestamp: 2026-07-23T10:12:24Z
---
# Backend
@@ -41,6 +41,11 @@ timestamp: 2026-07-23T04:05:00Z
| `backend/src/modules/challenges/dto/challenges.dto.ts` | zod contracts (`SolveSubmitBodySchema`, `BoardQuerySchema`, `ChallengeIdParamSchema`) + DTO types for the player-facing board. |
| `backend/src/modules/challenges/scoring.util.ts` | Pure `computeLivePoints`, `rankBonusForPosition`, `compareDifficulty`, `computeAwardedPoints` (base + rank bonus), `PLAYER_COLOR_PALETTE` + `stablePlayerColorIndex` (FNV-1a → palette index), and constant-time `safeEqualString` for flag comparison. |
| `backend/src/common/errors/error-codes.ts` | Canonical error code map (now includes `EVENT_NOT_RUNNING`, `FLAG_INCORRECT`, `CHALLENGE_DISABLED`). |
| `backend/src/modules/blog/blog.module.ts` | Wires the public and admin blog controllers/services to `BlogPostEntity`. |
| `backend/src/modules/blog/admin-blog.controller.ts` | Registers administrator CRUD routes at `/api/v1/admin/blog/posts`. |
| `backend/src/modules/blog/admin-blog.service.ts` | Lists, creates, updates, publishes/drafts, and deletes posts while preserving first-publication time. |
| `backend/src/modules/blog/dto/blog.dto.ts` | Public/admin response contracts and zod validation for title, body, status, and post id. |
| `tests/backend/blog-admin.spec.ts` | Admin authorization, CRUD, validation, publication-timestamp, deletion, and public draft-hiding contracts. |
# Frontend
@@ -94,6 +99,16 @@ timestamp: 2026-07-23T04:05:00Z
| `frontend/src/app/features/scoreboard/scoreboard.page.ts` | `/scoreboard` smart page (also listed above): gates the four tabs, wires `store.loadAll()` and `store.wireSse(...)` on init, and tears them down via `store.stop()` on destroy. |
| `frontend/src/app/core/services/notification.service.ts` | Root-provided signal-backed store of `{ id, kind, message, ts }` records; `error()` / `info()` push, `dismiss(id)` / `clear()` remove. |
| `frontend/src/app/core/interceptors/error-notification.interceptor.ts` | Translates `HttpErrorResponse` into friendly messages and pushes them to `NotificationService` (with suppression for `/api/v1/auth/{login,csrf,register}` and `/api/v1/challenges/status`). |
| `frontend/src/app/core/services/blog.service.ts` | Typed Promise-based public blog list and admin CRUD HTTP client. |
| `frontend/src/app/features/blog/blog.page.ts` | `/blog` smart page with loading, error, empty, and published-list states. |
| `frontend/src/app/features/blog/blog-presenter.component.ts` | Shared sanitized Markdown post renderer used by the Blog and landing pages. |
| `frontend/src/app/features/blog/blog.pure.ts` | Pure blog-list state derivation. |
| `frontend/src/app/features/admin/blog/blog.component.ts` | `/admin/blog` post table and create/edit/delete workflow coordinator. |
| `frontend/src/app/features/admin/blog/blog-form-modal.component.ts` | Reactive title/Markdown editor with live preview and draft/publish actions. |
| `frontend/src/app/features/admin/blog/blog-delete-modal.component.ts` | Post deletion confirmation and inline failure UI. |
| `frontend/src/app/features/admin/blog/blog-form.pure.ts` | Admin form validation, form synchronization, request cleanup, and status display helpers. |
| `tests/frontend/blog-page.spec.ts` | Blog page-state and shared sanitized Markdown rendering contracts. |
| `tests/frontend/blog-admin-form.spec.ts` | Admin form validation, prefill/reset, payload, and status-label contracts. |
| `tests/frontend/challenges.pure.spec.ts` | Pure helpers: sorting, parsers, friendly error mapping, `formatDdHhMm` (`DD:HH:mm:ss`). |
| `tests/frontend/challenges.service.spec.ts` | HTTP-service contract: `getDetail` URL-encodes the id, attaches `?include=solvers`, and forwards `withCredentials: true`. |
| `tests/frontend/challenges.store.spec.ts` | Signal store: board mutation, live solve merge, listeners, `stop()`. The "marks solvedByMe" and "does not double-count" tests now call `setMyUserId('me-1')` *before* `load()` to exercise the realistic page-mount sequence. |
@@ -118,3 +133,5 @@ timestamp: 2026-07-23T04:05:00Z
- [Scoreboard Page Guide](/guides/scoreboard-page.md)
- [Challenges Board](/guides/challenges-board.md)
- [Notifications](/guides/notifications.md)
- [Blog Publishing and Reading](/guides/blog.md)
- [Blog API](/api/blog.md)