Skip to content

Update sections on re-import; let admins edit a section's staff and capacity - #28

Merged
pancakereport merged 6 commits into
mainfrom
edit-sections
Oct 28, 2026
Merged

pancakereport merged 6 commits into
mainfrom
edit-sections

Conversation

@pancakereport

@pancakereport pancakereport commented Oct 28, 2026 •

Copy link
Copy Markdown

Fixes #3 and fixes #17.

Re-importing sections (#3)

Importing the Sections sheet a second time used to add another copy of every section. Now:

  • A row whose type, day, start, end and location exactly match an existing section updates that section. Its staff, capacity, tags and "Can Self Enroll" setting change, and its students stay enrolled.
  • If several sections or rows share a type, time and location (for example "Online"), the row's staff email must also match.
  • Rows that match no section are added as new sections. Sections missing from the sheet are left alone; an admin can delete an empty section from its Roster tab.
  • The success message says how many sections were added and how many were updated. The import modal explains how re-importing works.
  • A capacity must be a whole number that isn't negative, or the import stops with a clear error. Before, the cell's text went to the database unchecked.

Editing a section (#17)

In a section's Settings tab, admins can now set:

  • Staff Member: a dropdown plus "Unassigned", as described in this comment on #17. Swapping TAs no longer needs a reset and re-import. The list shows:

    • TAs and teachers in this course on bCourses who have signed in to Sections, going by their bCourses roles at their last sign-in.
    • People listed in an imported Sections sheet who haven't signed in yet.
    • The section's current staff member, always.

    Global admins aren't listed unless they're a TA or teacher in this course on bCourses. Assigning a section to someone who is staff in bCourses but hasn't opened this course in Sections yet also records their staff role here.

  • Capacity

Both the Settings tab and the import refuse a capacity below the section's current enrollment, as requested in #3. A capacity error from a re-import starts with the sheet's row number.

Clearer day and time errors (related to #7)

A day or time that couldn't be read used to cause a server error, so the Settings tab and both sheet imports only said "Something went wrong." This was one cause of the uninformative errors in #7, which this PR doesn't close. Now, in the Settings tab and both imports:

  • A day other than M, T, W, Th or F (including lowercase "m") gives "Day must be one of M, T, W, Th, F, not 'm'."
  • A time that isn't hh:mm followed by a or p with a leading 0 (such as 10am, 8:30a or 10:00) gives an error showing the expected form, like 08:30a or 02:15p.
  • An hour or minute out of range (such as 13:00p) gives "isn't a time on a 12-hour clock".
  • 10:00x used to be saved as 10:00 a.m.; it's now rejected.
  • A section must end after it starts: an end time at or before the start time is rejected.
  • Time errors from either import start with the sheet's row number.

Submit Changes now gives feedback. Changes are sent one at a time while the button shows "Saving…". A message beside the button then says the settings saved, says how many saved if any failed (each error also shows at the top of the page), or says there was nothing to save. After a submit, every field is refilled with the section's saved value, so a rejected value isn't left in its field to be sent again.

Testing

  • 9 new backend tests cover:
    • re-importing updates sections without duplicating them
    • sections at the same time and place are told apart by staff
    • the import can't shrink a section below its enrollment
    • editing capacity
    • reassigning a section's staff
    • who the staff list includes and who can be assigned (bCourses roles, imported staff, global admins)
    • the new endpoints are admin-only
    • day and time errors, and end times that aren't after the start, in the Settings tab
    • time errors in the Sections import name the row
  • pytest server passes on SQLite (58 tests).
  • The staff list's database query was run by hand against a local Postgres and returned the expected people. That was an earlier form of the query, which also listed global admins; removing them only dropped one condition.
  • Running the whole test suite against Postgres hung and was stopped without finding out why.
  • yarn typecheck, yarn lint and yarn build pass.
  • Not yet tried by hand against the sandbox.

Follow-up

Per #3, berkeley-cdss/docs#76 updates the sections docs for the re-import behavior and the new Settings fields. Merge it after this PR is deployed.

🤖 Generated with Claude Code

…apacity

Importing the Sections sheet again used to add a second copy of every
section. Now a row with the same type, day, time and location as an
existing section updates that section's staff, capacity, tags and
self-enrollment, keeping its students. When several sections share a
time and place (e.g. "Online"), the staff email tells them apart. Rows
that match nothing are added, sections missing from the sheet are kept,
and the import reports how many sections it added and updated. The
import modal explains this.

Admins can also change a section's staff member and capacity from its
Settings tab, so swapping TAs no longer needs a reset and re-import.
Neither path can set a capacity below the section's enrollment.

Fixes #3, fixes #17.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🚀 Staging Preview Deployed!

URL: https://preview-sections-pr-28-137456085712.us-west1.run.app

pancakereport and others added 4 commits October 28, 2026 11:06
The staff field in a section's Settings tab was a text box for an
email. As described on #17, it's now a dropdown of everyone on staff in
the course (from a new admin-only list_staff API), plus "Unassigned",
and update_section_staff takes the chosen person's id.

Submitting settings gave no sign that anything happened unless it
failed, and errors appear at the top of the page, out of view of the
button. The changes are now sent one at a time while the button shows
"Saving…", and a message beside the button says whether they all saved,
how many did if some failed, or that there was nothing to save.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A person's role in an offering is only synced with Canvas when they
open its pages, so the staff dropdown missed TAs who had signed in but
not yet opened the course, and kept TAs removed from the Canvas course.
For anyone who has signed in, the dropdown and update_section_staff now
go by their Canvas roles from their last sign-in. People imported from
a spreadsheet who haven't signed in still go by their role here.
Assigning a section to someone on staff in Canvas also records that
role here.

Global admins aren't listed unless they're on staff in this course in
Canvas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings sends its changes one at a time, so when the capacity failed
before a new location was saved, the message named the old location.
It now just says the capacity can't go below the enrollment. In the
import, where several sections may be updated, the message starts with
the sheet's row number instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rror

A day or time the parser couldn't read (a lowercase "m", "10am", "8:30a"
without the leading 0, "10:00" without a or p, or "13:00p") raised a
plain Python error, so the Settings tab and the sheet imports only said
"Something went wrong." (see #7). They now say what was wrong and what
form is expected. "10:00x" used to be saved as 10:00a and is now
rejected, and a section can no longer end at or before its start. Sheet
import errors about times name the row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pancakereport

Copy link
Copy Markdown
Author

remaining bug: in the time parser, 12:30a is read as 12:30 p.m., not 12:30 a.m. This is not fixed because a section at that hour is unlikely and changing how times are read could stop enrollment imports from matching existing sections.

A rejected value, like "weds" for the day, stayed in its field, so the
next submit sent it again. After submitting, the Settings tab now loads
the section again and fills every field with its saved value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pancakereport
pancakereport merged commit 02b4ae6 into main Oct 28, 2026
10 checks passed
@pancakereport
pancakereport deleted the edit-sections branch October 28, 2026 21:27
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.

More flexibility editing an existing section Re-importing sections causes duplicate sections

1 participant