feat: Student course catalog#97
Merged
Merged
Conversation
Students can browse the published courses at /courses and open a course page listing its published lessons. CourseService owns the student visibility rule: PUBLISHED is visible, an enrolled student keeps read access to an ARCHIVED course, DRAFT is never visible, and invisible content answers 404 so drafts do not leak. New derived queries: lessons by course and status in reading order, enrollment by (user, course). The navigation gains a Courses entry for logged-in users, and the security matrix tightens /courses from gate-pass 404 to 200 now that the controller exists.
EnrollmentService owns the student-side lifecycle: enrolling is idempotent, only published courses accept new enrollments (404 otherwise, drafts do not leak), a DROPPED row is re-activated instead of inserted twice (the (user, course) pair is the primary key), and dropping stamps dropped_at while leaving COMPLETED untouched. The course page gains Register and Quit actions (POST + CSRF, PRG redirects with ?enrolled / ?dropped confirmation alerts, matching the ?registered idiom), hides Register on non-published courses, and the catalogue marks the courses the student is enrolled in.
An actively enrolled student reads a published lesson at
/courses/{courseId}/lessons/{lessonId}: the Markdown is rendered to
sanitized HTML by MarkdownRenderer (cached, ADR-0013) and emitted with
th:utext, with previous/next links in reading order. A student who is
not enrolled is redirected to the course page with an enroll-required
hint instead of a 403 (the Register button is right there). Lessons
that are draft, archived, or belong to another course answer 404. The
course page lesson list now links each lesson.
The dashboard placeholder becomes the real "My courses" view: the active enrollments of the logged-in user (dropped ones excluded), each with its status and enrollment date, linking back to the course page. GET /dashboard moves from AuthController to a DashboardController in the course package, since the page renders enrollment data. StudentCourseFlowTest drives the whole student journey end to end: browse (draft courses hidden), bounce off a lesson before enrolling, enroll, read a lesson (Markdown rendered to HTML), reject an unknown lesson, see the dashboard list the course, drop, and see it gone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is part 2 of 2 in a stack made with GitButler: