Skip to content

feat/instructor-course-authoring#98

Merged
ebouchut merged 3 commits into
devfrom
feat/instructor-course-authoring
Jul 13, 2026
Merged

feat/instructor-course-authoring#98
ebouchut merged 3 commits into
devfrom
feat/instructor-course-authoring

Conversation

@ebouchut

@ebouchut ebouchut commented Jul 13, 2026

Copy link
Copy Markdown
Owner

This PR:

  • Add the UI for instructor course authoring and the write-side service allowing instructors to create, order, publish, and restore courses.
  • Add a per-course roster page (list of students enrolled in a course) so instructors view enrollments and can remove active students.
  • Add instructor role, auditing for publish/archive/restore, and removed enrollments.
  • Add glossary entries for Publish and Roster.

Details

InstructorCourseService enforces ownership and lifecycle transitions:
- DRAFT => PUBLISHED,
- archive from DRAFT/PUBLISHED,
- restore => DRAFT)

  • with HTTP error semantics and first-publish behavior

Lesson handling:

  • Append at max+1 and reorder swap temporary negative position to satisfy DB constraints.
  • Forms reuse existing accessible error wiring (aria-invalid,-aria-describedby, alert summary).
  • Roster table lists username, status, enrollment/drop dates
  • instructor drop action reuses drop rules and is audited as ENROLLMENT_DROPPED_BY_INSTRUCTOR.
  • AuditService records publish/archive/restore actions with client IP

InstructorCourseFlowTest covers:
- create/edit/validation lesson
- add/reorder/publish,
- course publish and access control roster listing and drop,
- audit checks.

Glossary updated (EN/FR) for "Publish" and "Roster".

ebouchut added 3 commits July 13, 2026 16:07
The instructor area under /instructor/courses (already role-gated)
lets an instructor create and edit their courses and lessons, publish,
archive, and restore them, and reorder lessons.

InstructorCourseService owns the write side: ownership is enforced at
the service level (someone else's course answers 403), lifecycle
transitions follow CONTRIBUTING.md (publish from DRAFT, archive from
DRAFT or PUBLISHED, restore to DRAFT, anything else 409), and
published_at is stamped on the first publish only. Publish, archive,
and restore actions are recorded through AuditService with the client
IP, like the password-reset flow.

Lessons append at position max plus one, and reordering swaps with the
neighbor through a temporary negative position because
uq_lessons_course_position is not deferrable (proven against real
Postgres in the repository test). Forms reuse the register.html error
wiring (aria-invalid, aria-describedby, alert summary); the security
matrix tightens the instructor gate to 200 with a seeded user.
The course editor links to a roster page listing every enrollment of
the course (username, status, enrollment and drop dates) in an
accessible data table. The instructor can remove an actively enrolled
student: this reuses the student-side drop rules (idempotent,
COMPLETED untouched) and is audited as
ENROLLMENT_DROPPED_BY_INSTRUCTOR, distinct from a self-drop.

InstructorCourseFlowTest drives the whole instructor journey end to
end: create with a validation error on the way, add and reorder
lessons, publish lesson and course, watch the student catalogue pick
the course up, get a 409 on a double publish and a 403 as another
instructor, list the roster, drop the student, and check the audit
trail and that drafts stay invisible.
Both glossaries gain the two domain terms the instructor area
introduces, EN and FR kept in sync per the glossary rule: Publish
(make a draft visible to students; the first publication stamps
published_at) and Roster (the enrolled students of a course, which
instructors can remove a student from). Archive was already defined.
@codecov

codecov Bot commented Jul 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.50943% with 71 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.90%. Comparing base (d4245e5) to head (7850802).

Files with missing lines Patch % Lines
...ut/learndev/course/InstructorCourseController.java 51.51% 45 Missing and 3 partials ⚠️
...uchut/learndev/course/InstructorCourseService.java 79.27% 22 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##                dev      #98      +/-   ##
============================================
- Coverage     82.96%   76.90%   -6.06%     
- Complexity       97      141      +44     
============================================
  Files            27       31       +4     
  Lines           364      576     +212     
  Branches         25       36      +11     
============================================
+ Hits            302      443     +141     
- Misses           40      106      +66     
- Partials         22       27       +5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ebouchut ebouchut added this to the v0.9 - Code Freeze milestone Jul 13, 2026
@ebouchut ebouchut added the documentation Improvements or additions to documentation label Jul 13, 2026
@ebouchut ebouchut merged commit 66e8e3c into dev Jul 13, 2026
7 checks passed
@ebouchut ebouchut deleted the feat/instructor-course-authoring branch July 13, 2026 14:16
@github-project-automation github-project-automation Bot moved this from In Progress to Done in learn-dev-project Jul 13, 2026
@ebouchut ebouchut added course Course/Lesson legal Legal topics, such as licensing, GDPR... labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend course Course/Lesson documentation Improvements or additions to documentation frontend legal Legal topics, such as licensing, GDPR...

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant