Skip to content

fix(web): keep an assignment's row in place on write - #755

Open
graphics80 wants to merge 2 commits into
foundation50:mainfrom
graphics80:fix/assignments-json-row-order
Open

fix(web): keep an assignment's row in place on write#755
graphics80 wants to merge 2 commits into
foundation50:mainfrom
graphics80:fix/assignments-json-row-order

Conversation

@graphics80

Copy link
Copy Markdown
Contributor

Summary

editAssignment, setAssignmentLock, and setAssignmentClosed rebuilt <classroom>/assignments.json as "every entry except this slug, then the updated entry", so touching an assignment moved its row to the end of the array. They now go through a small replaceAssignmentEntry helper that replaces the row where it sits.

That matches the CLI, which is the other side of this contract and writes the rule down: UpsertAssignment — "Position preserved on replace; new slugs append" — and gh teacher assignment lock assigns back into the same index. It also matches the web app's own renameAssignment, which already maps in place; deleteAssignment is a plain filter and createAssignment/copyAssignment append new slugs, both already correct.

What the old shape cost teachers:

  • gh teacher assignment list prints entries in file order (no sort), so locking hw1 in the web app moved it below hw9 in the terminal and in --json output.
  • A one-field flag flip committed as a whole-row delete + re-add, so git log -p assignments.json no longer showed what actually changed.

No reader is affected — every consumer looks entries up by slug — so this is an ordering and diff-hygiene fix, not a behavior change for students or grading.

The helper replaces the first match only, like UpsertAssignment: a hand-edited manifest can hold two rows for one slug, and each caller builds its entry from the first of them, so replacing both would overwrite the second row's own content.

Also updates the comment at rename.ts:286, which cited "the lock flip's filter+push" as the counter-example for mapping in place — that pattern no longer exists after this change.

Closes #754

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Refactor / maintenance

Checklist

  • I built, tested, and linted the module(s) I touched: cd web && npm run check (web only — no Go or Python change).
  • If I changed a cross-binary contract, I updated schemas/*.schema.json and every mirror (Go / Python / TypeScript), and the parity tests pass. — n/a: no schema or field change; this aligns the web app with the CLI's existing write behavior.
  • If I added or changed a CLI command or flag, I documented it in the wiki (not in a README). — n/a: no CLI change.
  • My commits follow Conventional Commits.

Each of the three writers gets a regression test asserting the surrounding rows keep their positions, plus one for the duplicate-slug manifest; all three position tests fail on main.

The edit, lock, and close writers rebuilt assignments.json as everything
except the slug plus the updated entry, moving the row to the end. The
CLI replaces in place ("Position preserved on replace"), and its
`assignment list` prints file order, so a web-side lock reordered the
teacher's listing and made every flag flip a whole-row diff.
Copilot AI lite review requested due to automatic review settings August 26, 2026 11:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes an ordering/diff-hygiene issue in the web app’s writers for <classroom>/assignments.json by updating existing assignment entries in-place rather than removing and re-appending them (which previously moved the touched row to the end of the array). This aligns web write behavior with the CLI contract (“Position preserved on replace; new slugs append”) and improves the auditability of config repo diffs and CLI list output order.

Changes:

  • Added a replaceAssignmentEntry helper to replace the first matching assignment row by slug while preserving array position.
  • Updated editAssignment, setAssignmentLock, and setAssignmentClosed to use the helper instead of filter + push.
  • Added regression tests ensuring row position is preserved (and that duplicate-slug manifests only rewrite the first match), plus updated a related comment in rename.ts.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
web/src/domain/assignments/createEdit.ts Introduces replaceAssignmentEntry and uses it in the three affected writers to preserve row position.
web/src/domain/assignments/rename.ts Updates an explanatory comment to remove the now-stale “filter+push” reference.
web/src/domain/assignments.test.ts Adds regression tests covering position preservation for edit/lock/close, plus a duplicate-slug scenario.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread web/src/domain/assignments/rename.ts Outdated
Comment on lines +286 to +287
// Map in place so the entry keeps its position in the array: a rename
// shouldn't reorder the manifest (see replaceAssignmentEntry).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded — the comment now names createEdit.ts and the CLI's UpsertAssignment instead of a symbol that isn't in this file. 14dc5bd

@rongxin-liu
rongxin-liu self-requested a review August 26, 2026 23:29
@rongxin-liu rongxin-liu added enhancement New feature or request CLI CLI tools (cli/) Web Web frontend (web/) labels Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLI CLI tools (cli/) enhancement New feature or request Web Web frontend (web/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web: editing, locking, or closing an assignment moves its row to the end of assignments.json

3 participants