Skip to content

feat(gradebook): external assessment management and CSV grade import#8441

Open
LWS49 wants to merge 1 commit into
lws49/feat-gradebook-weighted-viewfrom
lws49/feat-ext-assessments
Open

feat(gradebook): external assessment management and CSV grade import#8441
LWS49 wants to merge 1 commit into
lws49/feat-gradebook-weighted-viewfrom
lws49/feat-ext-assessments

Conversation

@LWS49

@LWS49 LWS49 commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

External assessments are the only gradebook columns a professor can create, edit, and delete directly (native missions and quizzes are managed on their own assessment pages), but until now they had no proper management home and grades could only be entered one cell at a time. This PR gives externals a dedicated "Manage external assessments" panel for all CRUD, plus a CSV import wizard for bulk grade entry keyed by External ID or email. It also hardens the grade pipeline: external grade columns now store two decimal places to match the Canvas and SoftMark feeds that supply them, floor/cap bounds are applied at compute time so they affect only the weighted total without ever mutating the stored grade, and weight is forced to zero server-side when the weighted view is off. The work is stacked on the weighted-view branch, so this PR contains only the external-assessment delta.

Design decisions

  • Single "Manage external assessments" panel replaces the scattered toolbar buttons and the per-column kebab menu - one tab-agnostic, weighting-agnostic place for Add, Edit, Delete, and Import. Max marks is editable only through the Edit prompt, not inline: changing the max reinterprets every existing grade against a new denominator, so that column-definition change belongs in the deliberate dialog while the subheader stays view-only like native columns. The "External" chip remains on the header for identification.
  • Inline grade editing keeps the spreadsheet model (blur or Enter commits, Esc cancels) with no per-edit confirmation - this matches the grid idiom professors already know from Excel and Sheets, and the "are you sure" gate belongs at publish time, not on every reversible pre-publish edit.
  • Weight is zeroed server-side when the weighted view is off, on both the manual Add path and the CSV import path - previously only the manual path enforced this and the import path trusted the weightage sent by the client, so a stale or crafted request could write a nonzero weight that surfaced silently once the view was enabled. The gate sits at the controller on both paths; the import service stays a pure writer.
  • Only the two external grade columns were widened to decimal(5,2); native grade columns stay decimal(4,1). Externals are fed by Canvas and SoftMark which both supply two decimal places (an imported 87.25 was previously rounded to 87.3 on store), whereas native grading is Coursemology-native where one decimal place is fine. Widening everything would be a separate, larger change. The three integer digits are preserved, so there is no integer-range regression.

Regression prevention

  • Backend specs cover external assessment create/update/delete and grade update (including the server-side weight-zeroing on both add and import when the weighted view is off), the CSV import service (identifier resolution by External ID and email, whole-batch failure on any unresolved identifier, grade parsing and conflict detection), and the floor/cap clamping in gradebook/contribution. Model specs cover external assessment and external assessment grade validation plus the 2dp round-trip (asserting 87.25 and 99.25 persist without rounding).
  • Frontend tests cover the manage panel and its Add/Edit/Delete prompts, the import wizard end to end (identifier toggle, required-header listing, verify and grade-conflict steps), the gradebook table inline grade editing (numeric and 2dp entry guards, commit and cancel), the weighted table, the import template builder, the weighted compute, and the store.
  • Manual testing confirmed: panel gating and CRUD, inline grade commit/cancel with numeric and 2dp guards, the full import wizard including roster gating and conflict resolution, server-side weight zeroing on both paths, floor/cap affecting only the weighted view, the over-max icon on capped assessments, and the sortable External ID column in Manage Users.
  • Backward compatibility: external assessments are additive gradebook columns and the floor/cap flags never mutate stored grades (the raw "All assessments" view always shows the true value), so existing gradebooks and native grade columns are unaffected. The weight-preservation guarantee across the view toggle is structural - the toggle writes only the setting and never touches course_gradebook_contributions.weight.

@LWS49 LWS49 force-pushed the lws49/feat-ext-assessments branch from 2220631 to ad01bc8 Compare June 15, 2026 09:06
@LWS49 LWS49 changed the title Lws49/feat ext assessments feat(gradebook): add course gradebook with weighted view and external assessments Jun 15, 2026
@LWS49 LWS49 changed the title feat(gradebook): add course gradebook with weighted view and external assessments feat(gradebook): add external assessments Jun 15, 2026
@LWS49 LWS49 force-pushed the lws49/feat-gradebook-weighted-view branch 4 times, most recently from 7d9fdb4 to ade1ddf Compare June 16, 2026 07:12
@LWS49 LWS49 force-pushed the lws49/feat-ext-assessments branch from ad01bc8 to 82c7316 Compare June 16, 2026 13:58
@LWS49 LWS49 changed the title feat(gradebook): add external assessments feat(gradebook): gradebook overhaul - weights, external assessments, CSV import Jun 16, 2026
@LWS49 LWS49 force-pushed the lws49/feat-ext-assessments branch from c799dd5 to 2de895b Compare June 17, 2026 06:13
@LWS49 LWS49 force-pushed the lws49/feat-gradebook-weighted-view branch 2 times, most recently from 521efed to 2efbb02 Compare June 17, 2026 06:45
@LWS49 LWS49 force-pushed the lws49/feat-ext-assessments branch from 2de895b to e750140 Compare June 18, 2026 12:10
- add ExternalAssessment/Grade models, CRUD + grade-set endpoints gated to teaching staff, scoped to the course
- extend gradebook contributions to weight an external contributor (XOR validation), serialized as a synthetic negative-id grouping
- CSV import wizard (define/upload/verify/conflict) with dry-run preview, upsert commit, and conflict/mismatch detection
- FE store, operations, and inline add/rename/delete/grade/max editing for external columns in the gradebook table
- surface external assessments in gradebook index JSON and route weight entries to external contributions
- add controller, model, service, and component specs
@LWS49 LWS49 force-pushed the lws49/feat-ext-assessments branch from e750140 to f8c70e8 Compare June 18, 2026 15:48
@LWS49 LWS49 changed the title feat(gradebook): gradebook overhaul - weights, external assessments, CSV import feat(gradebook): external assessment management and CSV grade import Jun 23, 2026
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