feat: add calculator functionality with customizable permissions and … - #398
Merged
saa938 merged 3 commits intoSep 5, 2026
Merged
Conversation
Three fixes to the built-in calculator (AP-Students#333), all reproduced and verified against the running app. The student MCQ test page read the test document but never passed `calculatorDefault`/`calculatorType` to `TestRenderer`. Both props are optional, so nothing failed to compile — the assessment-level default was just silently dropped for every student, and the calculator type always fell back to graphing. Only the admin preview, which does pass them, behaved as authored. The FRQ path was already correct. Opening the panel focused its first tabbable node, which is the cross-origin Desmos iframe. Keydowns inside a cross-origin frame never reach this document, so Escape stopped dismissing the panel the moment it opened, and Tab could not get back out either. The panel now takes focus itself on open, which keeps the dismiss handler reachable, and hands focus back to the Calculator button on close. The panel was a modal sheet, so `pointer-events: none` on the body meant a student had to close the calculator before selecting an answer or moving to the next question — and the navigate-away auto-close could never fire, because navigating was impossible while it was open. It is now non-modal with no backdrop, stops above the test footer so navigation stays clickable, and ignores outside interactions so answering a question does not dismiss it. `SheetContent` grows an optional `overlay` prop for this; it defaults to true, so the navbar and peer-grading sheets are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CTRd1fAGtNecSB13TdCsE6
…culator Ten files conflicted, all because main now carries the reference-sheet half of AP-Students#333 (PR AP-Students#397), which adds an assessment-level setting, a per-assessment toolbar button, and a Radix side panel at exactly the seams the calculator uses. Every conflict was two independent features landing on adjacent lines, so both sides were kept throughout. Three needed more than a concatenation: - `normalizeFrqTemplate` — both sides re-stated the shared `sectionLabel` / `sectionSubtitle` assignments, which would have run twice. - The admin MCQ editor and the FRQ editor — both sides consumed the same settings wrapper `<div>`. The calculator group closes its own, and the reference-sheet group gets a fresh one, so the two settings groups sit side by side in the toolbar row rather than nesting. - `frq/testRenderer.tsx` — both features import a panel and a lucide icon from the same modules; the imports were combined, and the toolbar now carries Reference Sheet, then Calculator, then Exit Test. Verified after the merge: `tsc --noEmit` clean, `eslint` clean, 70/70 tests, `next build` successful, and both features present in every merged file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CTRd1fAGtNecSB13TdCsE6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds the Built-in Calculator feature from #333 (the reference-sheet half of that issue is tracked separately). Assessment authors can enable a Desmos calculator (four-function, scientific, or graphing) for MCQ tests and FRQs, set an assessment-wide default, and override it per question — so a test can be all-calculator, all-non-calculator, or a mix (e.g. Part A non-calculator, Part B calculator).
Section/set-level overrides from the issue are intentionally out of scope: neither
UnitTest(flatquestions[]) norFRQTemplate(sectionLabelis a display string, not a grouping boundary) has a structural "section" today, so this implements the two levels that actually exist — assessment default, overridden per question — which covers every example in the issue.Pull request type
Please check the type of change your PR introduces:
A summary of the change, anything else that will help review this PR
Permission model (
src/lib/calculator.ts): a pureresolveCalculatorPermission(assessmentDefault, questionOverride)shared by both MCQ and FRQ. Question setting overrides assessment default;"inherit"/absent falls through; an assessment or question with nothing configured resolves tofalse(safe default for existing assessments).Calculator overlay (
src/components/questions/CalculatorPanel.tsx): a RadixSheetside panel embedding the resolved Desmos testing-calculator URL in a sandboxed (allow-scripts allow-same-origin allow-forms) iframe, following the same sandboxing pattern already used for the Discord widget. The iframe is only mounted while the panel is open, so closing it — including the automatic close described below — discards any in-progress calculator state.Auto-close on navigation: both
testRenderer.tsx(MCQ) andfrq/testRenderer.tsx(FRQ) force-close the panel the moment the resolved permission for the current question becomesfalse, unmounting the iframe so a student can't carry a live calculator into a question it isn't allowed on, and can't reopen it via a focused-but-blocked button.Student experience: a Calculator button sits in the same toolbar row as the existing elimination-tool button (MCQ) / next to Exit Test (FRQ). It stays visible but
aria-disabled(notdisabled, so it keeps an accessible label and can't be silently skipped by assistive tech) on calculator-inactive questions, per the issue's explicit recommendation against hiding it.Author experience: MCQ test editor and FRQ editor both get a "Default Calculator" select (allowed/not-allowed) plus a "Calculator Type" select when allowed, in the existing assessment-settings area. Per-question override selects (inherit/allowed/not-allowed) are added next to the MCQ Topic field and inside each FRQ
QuestionCard, reusing each editor's existing update pattern.How Has This Been Tested? How can the reviewer test it?
npx tsc --noEmitandnpx eslintare clean on every changed/new file (only pre-existing, unrelatedpathname-possibly-null errors remain in files this PR didn't touch the affected lines of).Reviewer steps:
Checklist