Skip to content

feat(gradebook): add gradebook with column picker and CSV export#8400

Open
LWS49 wants to merge 1 commit into
lws49/feat-table-column-pickerfrom
lws49/feat-gradebook-export
Open

feat(gradebook): add gradebook with column picker and CSV export#8400
LWS49 wants to merge 1 commit into
lws49/feat-table-column-pickerfrom
lws49/feat-gradebook-export

Conversation

@LWS49
Copy link
Copy Markdown
Collaborator

@LWS49 LWS49 commented May 21, 2026

Summary

Adds a Gradebook page (GET /courses/:id/gradebook) that shows a matrix of students and their grades across all published assessments. Staff can toggle which columns to include and export a filtered CSV. To support this, the column picker dialog introduced in #8399 is utilized.

Features:

  • Column picker controls which student info and assessment columns are shown and exported
  • Max marks exported at the second row; only shown when at least one assessment is selected
  • Null/undefined grades display as - and export as blank; 0 grades display and export as 0
  • Horizontal scrolling and pagination supported
  • Name column is always selected and cannot be toggled off; all other columns can be toggled
  • Gamification columns available when gamification is enabled in course settings
  • Exporting selected rows is supported
  • Column visibility is persisted - leaving and returning to the page restores the same view
  • When no students are enrolled in the course, an empty state with

Known follow-up: investigate replacing the raw SQL grade summary query with a lazy ActiveRecord::Relation-based implementation to allow deferral until enumeration.

Design decisions

  • Name is always locked on - simplified over "at least one of name/email must be selected" because that adds complexity with little utility; there is almost no real-world case where a user wants email without name, and if there is, the user can easily delete the name column from the export.

  • Any valid column selection (including name-only) renders in the table - restricting export or disabling controls when only name is selected does not match user expectations from the UI; users should be able to render or export whatever valid selection they have made.

  • Infomodal when only student info is selected, but no hard block - informs the user of the unusual state without preventing the action.

  • check-types now passes --noEmit - tsconfig.json sets outDir: dist, so a bare tsc invocation emits compiled JS into dist/ as a side effect. Adding --noEmit restricts the script to type-checking only and prevents polluting the dist directory when a developer runs yarn check-types locally. dist/ is also added to testPathIgnorePatterns in jest.config.js as a matching safeguard - Jest would otherwise attempt to scan any previously emitted JS files there.

Regression prevention

  • Course::Assessment.max_grades: covers empty input, correct aggregation, excludes other courses' assessments, excludes assessments with no questions
  • Course::Assessment::Submission.grade_summary: covers empty student/assessment IDs, graded submissions, excludes attempting submissions, only counts current answers
  • Course::GradebookController: controller integration tests
  • IndentedCheckbox moved from course/duplication/components to lib/components/core - all six existing consumers updated; no behaviour change
  • jest.config.js: added dist/ to testPathIgnorePatterns - prevents Jest from scanning emitted JS if tsc was ever run without --noEmit
  • Backward compatibility fully preserved; no changes to existing table behaviour outside the new Gradebook page

Views

Default view has name and all grades selected. If gamification is enabled, its columns will be selected in default view too.

image

Info modal pops up if only student info is selected. When gamification is disabled, message only mentions grade columns

image

View with only student name

image

Blank state view with no students

image

@LWS49 LWS49 force-pushed the lws49/feat-gradebook-export branch 4 times, most recently from 3525c59 to 702f85e Compare May 21, 2026 11:43
@LWS49 LWS49 marked this pull request as ready for review May 21, 2026 11:53
@LWS49 LWS49 force-pushed the lws49/feat-gradebook-export branch 8 times, most recently from 5b85fc0 to fa7a036 Compare May 25, 2026 05:47
Introduces a course-wide gradebook showing per-student grades across all assessments. Instructors can toggle which assessment columns are visible via a hierarchical column picker (grouped by category/tab), then export the current view to CSV.

Backend adds GradebookController#index (JSON), ability guard, and model methods on Assessment and Submission for fetching grade data.

Table lib gains reusable ColumnPickerTemplate, MuiColumnPickerDialog, ColumnPickerTreeGroup, and toolbar integration used by the gradebook.
@LWS49 LWS49 force-pushed the lws49/feat-gradebook-export branch from fa7a036 to 031c2e1 Compare May 25, 2026 05:53
@LWS49 LWS49 changed the base branch from master to lws49/feat-table-column-picker May 26, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant