Skip to content

Update course summary page to have accurate progress and recipients information #14646

@marcellamaki

Description

@marcellamaki

This issue is not open for contribution. Visit Contributing guidelines to learn about the contributing process and how to find suitable issues.

Overview

The Courses list page (CoursesRootPage.vue) has three columns — Progress, Learners, and
Mastery — that are hardcoded as '—' placeholders. This task replaces those placeholders
with real data: a course Status indicator, a Recipients display, and a Learner Progress tally.

Complexity: Medium
Target branch: develop

Context

CoursesRootPage.vue renders a KTable whose tableRows computed property returns
hardcoded '—' for the Progress (col 1), Learners (col 2), and Mastery (col 3) columns:

// CoursesRootPage.vue ~line 524
tableRows() {
  return this.sortedCourses.map(course => [
    course, // title
    '—',    // status   ← placeholder
    '—',    // learners ← placeholder
    '—',    // mastery  ← placeholder
    course, // visible toggle
    course, // options menu
  ]);
},

The parallel Lessons list page (LessonsRootPage.vue) shows the target pattern:

  • ProgressStatusSummary component fed a {completed, started, notStarted, helpNeeded} tally from getLessonStatusTally (classSummary Vuex getter)
  • Recipients → group names / "Entire class" from getRecipientNamesForLesson

The CourseSessionViewset (kolibri/core/courses/viewsets.py) already exposes
assignments (group collection IDs) and learner_ids (ad-hoc learners) per session via
its consolidate() method. The _compute_course_state() helper in the same file already
derives unit_phase and active_unit_id from UnitTestAssignment records but is not
yet included in the list API response.

The Change

Two column headers are renamed; the rest stay the same:

  • LearnersRecipients
  • MasteryLearner Progress
  • (Progress → Status, Visible to learners, and Options columns are unchanged)

Backend (kolibri/core/courses/viewsets.py)

Extend CourseSessionViewset.consolidate() to add two new fields per session item:

  1. unit_phase + active_unit_number + active_unit_title — call the existing _compute_course_state() helper in a batched loop over all session items; look up the active unit's ContentNode to get its title and position number.

  2. test_learner_progress — a dict {completed: N, started: N, notStarted: N, total: M} where total is the count of assigned learners (derived from learner_ids + group memberships already computed in consolidate()), and the three counts are derived from MasteryLog records for the active unit's synthetic content ID:

    • completed: learners with a complete MasteryLog (complete=True)
    • started: learners with an in-progress MasteryLog (complete=False)
    • notStarted: remaining assigned learners with no MasteryLog
    • helpNeeded is not included
      Return null when unit_phase is PreTestPending (no test activated yet).

Frontend (CoursesRootPage.vue)

  • Update tableHeaders to rename the two columns above.
  • In tableRows, replace '—' with real values:
    • Status: render phase label + unit number/title (e.g. "Pre-test running · Unit 1", "Completed", "Not started") with icon, using existing coursesStrings translatable strings and following the visual pattern in CourseSummaryPage.
    • Recipients: use the existing getRecipientNamesForCourseSession getter and render with the Recipients component (same as CourseSummaryPage).
    • Learner Progress: feed test_learner_progress into a StatusSummary component tally with {completed, started, notStarted}. Show '—' when test_learner_progress is null. Follow the StatusSummary pattern from LessonsRootPage and the tally shape from PR Add unit page #14614 (useUnitDetail.js).

How to Get There

  1. Start the dev server: pnpm devserver
  2. Log in as a coach or admin
  3. Navigate to Coach → [Class] → Courses
  4. The Courses list table is immediately visible — the Status, Recipients, and Learner Progress columns currently show for all rows
  5. To see non-placeholder data after the fix, assign a course to learners and activate a pre- or post-test from the Course Summary page

Out of Scope

  • The stacked mastery bar (red / yellow / green learner distribution) from the early design spec — deferred as a future enhancement
  • helpNeeded bucket in the Learner Progress tally
  • Any changes to the Course Summary page (CourseSummaryPage.vue)
  • The Recipients filter dropdown behavior (already works using assignments data)

Acceptance Criteria

General

  • The "Learners" column header is renamed to "Recipients"
  • The "Mastery" column header is renamed to "Learner Progress"
  • Status column: each row shows the current course phase with an icon and label:
    • "Not started" (grey dot) when no test has been activated
    • "Pre-test running · Unit N" (clock icon) when a pre-test is open
    • "Post-test running · Unit N" (clock icon) when a post-test is open
    • "Completed" (star icon) when all units are done
  • Recipients column: each row shows group names, individual learner names, or "Entire class" — matching the behavior of the Recipients column on the Lessons list page
  • Learner Progress column: each row shows a StatusSummary tally using {completed, started, notStarted} counts for the active unit's test:
    • "N have not started" when no learner has begun the test
    • "N of M have started" when some learners are in progress
    • "Completed by N of M" when some learners have finished
    • Shows when no test has been activated (unit_phase is PreTestPending)
  • All three columns update correctly when navigating between classes with different course states
  • The existing Status filter (visible / not visible) and Recipients filter still work correctly after the changes

Accessibility and i18n

  • New column headers use existing coursesStrings / coachStrings translatable strings where available; any new strings are added with message and context fields
  • Status and Learner Progress text is not hardcoded in English

Testing

  • Backend/API tests cover the new test_learner_progress and unit phase fields returned by CourseSessionViewset for the key states: not started, pre-test active, post-test active, and completed
  • Frontend tests are minimal — focus on verifying that the correct data reaches the template for a small number of representative cases; avoid testing rendering details that duplicate backend coverage
  • Any getByText assertions use string function references (e.g. entireClassLabel$()) rather than hardcoded English strings

References

  • Placeholder issue this replaces: Update course summary page to have accurate progress and recipients information #14646
  • PR Add unit page #14614 — establishes the {completed, started, notStarted} tally shape and StatusSummary usage pattern to follow
  • CoursesRootPage.vue — file under change (table rows and headers)
  • kolibri/core/courses/viewsets.pyCourseSessionViewset.consolidate() and _compute_course_state() to extend
  • LessonsRootPage.vue — parallel recipients + progress implementation to follow
  • views/common/status/StatusSummary.vue — component to reuse for Learner Progress
  • views/common/Recipients.vue — component to reuse for Recipients column
  • composables/useUnitDetail.js (PR Add unit page #14614) — tally computation pattern

AI usage

Drafted with Claude Code. Explored the codebase to identify the hardcoded placeholders,
compared with the lessons/quizzes list implementations, reviewed PR #14614 for the tally
pattern, and iterated on scope through conversation. Reviewed and edited for accuracy.

Metadata

Metadata

Assignees

Labels

P0 - criticalPriority: Release blocker or regressionbugBehavior is wrong or broken

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions