[Playgrounds P5] Videos layer — official per-lesson + student-submitted / staff-approved per lesson block #328

Closed
opened 2026-07-02 00:51:17 +00:00 by spikerj · 2 comments
Owner

Phase P5 of epic #323. Third content layer (after books #326, text #327). Largest phase — expect to split into sub-tickets once the design settles.

What: two video tracks surfaced in the shared playground shell:

  1. Official videos — per lesson, produced by SpikerSoft (none exist yet; the model and player land first, content follows)
  2. Community videos — per lesson block (TutorialPanel), submitted by users/students, visible only after admin/staff approval

Model (backend):

  • Video entity: lesson number + optional panel index, kind (official | community), submitter, status (pending | approved | rejected), title, duration, storage ref, rejection note
  • Submission endpoint ([Authorize] — submitting is a logged-in action) + moderation endpoints (staff/admin roles)
  • Approved-video read path on the anonymous-readable lesson detail endpoints (LessonsController)
  • Media pipeline: reuse the existing event-driven media processing pattern (SpikerSoft.EventHandlers.BlogMediaProcessor is prior art — transcode/thumbnail via a new or generalized handler per the worker-architecture conventions)
  • Storage/serving decision: same store the blog media pipeline targets; document size/length limits

Moderation (frontend admin):

  • Admin approval queue page mirroring /admin/blog-moderation (list pending, preview, approve/reject with note); add to the Management menu with a pending-count badge like the existing issue-badge pattern in menu-bar.component.html

Playground (frontend):

  • Videos tab/pane in LanguagePlaygroundShellComponent: official video for the lesson + approved community videos for the current block
  • Submit flow from the playground (logged-in users), with clear pending-review state for the submitter
  • Player consistent with existing media components; i18n chrome

Acceptance: an approved community video appears on its lesson block in all five playgrounds; unapproved videos are never publicly visible; staff can approve/reject with an audit trail (who, when).

Phase P5 of epic #323. Third content layer (after books #326, text #327). Largest phase — expect to split into sub-tickets once the design settles. **What:** two video tracks surfaced in the shared playground shell: 1. **Official videos** — per lesson, produced by SpikerSoft (none exist yet; the model and player land first, content follows) 2. **Community videos** — per lesson **block** (`TutorialPanel`), submitted by users/students, visible only after admin/staff approval **Model (backend):** - [ ] Video entity: lesson number + optional panel index, kind (official | community), submitter, status (pending | approved | rejected), title, duration, storage ref, rejection note - [ ] Submission endpoint (`[Authorize]` — submitting is a logged-in action) + moderation endpoints (staff/admin roles) - [ ] Approved-video read path on the anonymous-readable lesson detail endpoints (`LessonsController`) - [ ] Media pipeline: reuse the existing event-driven media processing pattern (`SpikerSoft.EventHandlers.BlogMediaProcessor` is prior art — transcode/thumbnail via a new or generalized handler per the worker-architecture conventions) - [ ] Storage/serving decision: same store the blog media pipeline targets; document size/length limits **Moderation (frontend admin):** - [ ] Admin approval queue page mirroring `/admin/blog-moderation` (list pending, preview, approve/reject with note); add to the Management menu with a pending-count badge like the existing `issue-badge` pattern in `menu-bar.component.html` **Playground (frontend):** - [ ] **Videos** tab/pane in `LanguagePlaygroundShellComponent`: official video for the lesson + approved community videos for the current block - [ ] Submit flow from the playground (logged-in users), with clear pending-review state for the submitter - [ ] Player consistent with existing media components; i18n chrome **Acceptance:** an approved community video appears on its lesson block in all five playgrounds; unapproved videos are never publicly visible; staff can approve/reject with an audit trail (who, when).
spikerj added the enhancement label 2026-07-02 00:51:17 +00:00
Author
Owner

Sub-ticket breakdown (PR series)

Sub Issue Scope
P5a #336 Backend foundation — LessonVideo model, submission + moderation endpoints, approved-read path (no pipeline)
P5b #337 Media pipeline — upload, virus scan, ffmpeg transcode + thumbnail, storage/serving (event-driven, mirrors BlogMediaProcessor)
P5c #338 Admin moderation queue page (mirrors /admin/blog-moderation) + Management menu badge
P5d #339 Videos tab in the shared playground shell + submit flow (all five playgrounds)

Order: #336 first (stable contract) → #337 pipeline + #338 moderation UI (parallel) → #339 playground UI. Starting on #336 now.

## Sub-ticket breakdown (PR series) | Sub | Issue | Scope | |---|---|---| | P5a | #336 | Backend foundation — `LessonVideo` model, submission + moderation endpoints, approved-read path (no pipeline) | | P5b | #337 | Media pipeline — upload, virus scan, ffmpeg transcode + thumbnail, storage/serving (event-driven, mirrors BlogMediaProcessor) | | P5c | #338 | Admin moderation queue page (mirrors `/admin/blog-moderation`) + Management menu badge | | P5d | #339 | Videos tab in the shared playground shell + submit flow (all five playgrounds) | Order: **#336 first** (stable contract) → #337 pipeline + #338 moderation UI (parallel) → #339 playground UI. Starting on #336 now.
Author
Owner

P5 (Videos layer) complete — all four sub-tickets merged and closed:

  • #336 P5a — model + moderation/read endpoints (LessonVideo, lessonVideos collection)
  • #338 P5c — admin moderation queue + Management-menu pending badge
  • #339 P5d — playground Videos tab (official + approved community, submit flow, login CTA)
  • #337 P5b — media pipeline (upload → ClamAV scan → ffmpeg transcode + poster → move → static serving)

Acceptance met: approved community videos surface on their lesson block across all five playgrounds via the shared shell; unapproved videos are never publicly visible; staff approve/reject with an audit trail; uploaded raw video is scanned, transcoded to a web-safe MP4 with a poster, and served from the final store, with failures landing in a terminal state without exposure.

Follow-up (optional, non-blocking): the SPA submit flow currently posts a video URL (P5d); wiring the in-browser file upload to POST /api/Lessons/{n}/videos/upload is a small frontend follow-up.

P5 (Videos layer) complete — all four sub-tickets merged and closed: - **#336** P5a — model + moderation/read endpoints (`LessonVideo`, `lessonVideos` collection) - **#338** P5c — admin moderation queue + Management-menu pending badge - **#339** P5d — playground Videos tab (official + approved community, submit flow, login CTA) - **#337** P5b — media pipeline (upload → ClamAV scan → ffmpeg transcode + poster → move → static serving) **Acceptance met:** approved community videos surface on their lesson block across all five playgrounds via the shared shell; unapproved videos are never publicly visible; staff approve/reject with an audit trail; uploaded raw video is scanned, transcoded to a web-safe MP4 with a poster, and served from the final store, with failures landing in a terminal state without exposure. **Follow-up (optional, non-blocking):** the SPA submit flow currently posts a video URL (P5d); wiring the in-browser file upload to `POST /api/Lessons/{n}/videos/upload` is a small frontend follow-up.
Sign in to join this conversation.