Dashboard Refactor, useProgramDashboardData#3356
Conversation
OpenAPI ChangesNo changes detected Unexpected changes? Ensure your branch is up-to-date with |
| * pure model (model/dashboardViewModel.test.ts) or the hook tests | ||
| * (hooks/useProgramDashboardData.test.tsx, useDashboardLanguagePicker.test.ts), | ||
| * NOT here. | ||
| */ |
There was a problem hiding this comment.
Many tests in this file fall outside the categories noted above, but are left in place as a safety net during the refactor.
There was a problem hiding this comment.
Pull request overview
This PR refactors the program dashboard to separate query/data orchestration from rendering by introducing useProgramDashboardData and moving requirement-tree parsing/section building into pure, well-tested utilities. It also introduces a shared parseProgramRequirementSections helper in @/common/mitxonline to structurally parse req_tree operator sections.
Changes:
- Added
useProgramDashboardData+useDashboardLanguagePickerhooks to own data fetching, composition, and language picker state. - Added/expanded pure model utilities (
buildCourseEntry,buildRequirementSections) and updated adapters/tests to align with the new “entry”-based dashboard model. - Added
parseProgramRequirementSectionsas a sharedreq_treestructural parser, with unit tests.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| frontends/main/src/common/mitxonline/index.ts | Adds shared parseProgramRequirementSections + exported type for structural parsing of program req_tree. |
| frontends/main/src/common/mitxonline.test.ts | Adds unit tests for parseProgramRequirementSections. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/test-utils.ts | Adds buildProgramScenario to standardize hook test API mocking. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/ProgramEnrollmentDisplay.tsx | Converts component into a display-only renderer backed by useProgramDashboardData. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/ProgramEnrollmentDisplay.test.tsx | Adds test-layering documentation comment (scope guidance). |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/model/dashboardViewModel.ts | Adds buildCourseEntry + buildRequirementSections; integrates shared parser; renames slot→entry resolver export. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/model/dashboardViewModel.test.ts | Adds extensive unit coverage for the new pure utilities and updated resolver name. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/model/dashboardAdapters.ts | Renames adapter to entry-based naming (adaptCourseEntryToLegacyDashboardCardProps). |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/model/dashboardAdapters.test.ts | Updates tests to entry-based adapter naming and types. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/hooks/useProgramDashboardData.ts | New composer hook that performs the 6 queries and returns render-ready program dashboard data. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/hooks/useProgramDashboardData.test.tsx | Adds renderHook suite asserting query→helper wiring + durable returned contract. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/hooks/useDashboardLanguagePicker.ts | New hook for language picker state (derive-during-render approach). |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/hooks/useDashboardLanguagePicker.test.ts | Unit tests for language picker behavior across option changes. |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/HomeEnrollmentsDisplay.test.tsx | Adds test-layering documentation comment (scope guidance). |
| frontends/main/src/app-pages/DashboardPage/CoursewareDisplay/dashboardRefactorPlan.md | Updates plan doc terminology and Phase 4 “settled decisions” notes (slot→entry terminology, etc.). |
| frontends/main/src/app-pages/DashboardPage/ContractContent.tsx | Renames usage to resolveCourseEntryForLanguage to match the entry-based model export. |
gumaerc
left a comment
There was a problem hiding this comment.
This is good to go, just noticed one small typo.
| * | ||
| * Fetches the 6 program-dashboard queries (course-run enrollments, | ||
| * programDetail, program enrollments, program courses, required programs, | ||
| * required-program courses) and composes the pure helpers in |
There was a problem hiding this comment.
nit: "required program-courses"
| * | ||
| * Fetches the 6 program-dashboard queries (course-run enrollments, | ||
| * programDetail, program enrollments, program courses, required programs, | ||
| * required-program courses) and composes the pure helpers in |
There was a problem hiding this comment.
| * required-program courses) and composes the pure helpers in | |
| * required program-courses) and composes the pure helpers in |
Folds the Phase 4 brainstorming outcomes into the plan as a SETTLED block: - (A) build the real entry constructor + adapter; rename DashboardCourseSlot → DashboardCourseEntry (code + remainder of plan doc) as step 0 - composer emits the RequirementSectionItem discriminated union + shared aux (enrollmentsByCourseId / pre-derived ancestorProgramEnrollment) - buildProgramScenario = thin entities-in mock-wirer (2a); tests own scenario - language picker: hook-owned, derive-during-render, effective key, own test - shared structure-only parseProgramRequirementSections in @/common/mitxonline; buildRequirementSections owns dashboard display policy; product parseReqTree migration is the next stacked PR; re-ask at Phase 4 exit - behavior-preservation scope: stable render is the contract, first paint negotiable except loading states Full design record (rationale + rejected alternatives) in feature_work/TODOS_AND_IDEAS/phase4-design.md (local). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…step 0) Pure rename, zero behavior change, zero production callers today: - DashboardCourseSlot → DashboardCourseEntry - resolveSlotForLanguage → resolveCourseEntryForLanguage - adaptCourseSlotToLegacyDashboardCardProps → adaptCourseEntryToLegacyDashboardCardProps - dashboardRefactorPlan.md slot vocabulary swept to "entry" Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…(Phase 4 Task B) Shared req-tree → ordered operator sections parse (ids + operator metadata + rawTitle only; no display copy/completion/entity resolution). Composed by the Phase 4 dashboard helpers (Task C). Product parseReqTree migration is a later PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…se 4 Task C) Pure model helpers composing the shared parseProgramRequirementSections into the RequirementSectionItem discriminated union; behavior-preserving extraction of the inline ProgramEnrollmentDisplay logic. getRequirementSectionTitle moved into the model. Flat-req_tree assumption documented. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Derive-during-render language-picker state (no reconcile effect). Stable contract preserved (effective key ∈ options or "" ; default = options[0]; user pick persists while valid, falls back when it disappears). Reused by Phase 5. setSelectedLanguageKey records the raw user choice. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…cenario (Phase 4 Task E) Thin composer: replicates the program dashboard's 6-query orchestration exactly and composes the pure helpers (grouping, getDistinctDashboardLanguageOptions, useDashboardLanguagePicker, buildRequirementSections) into the durable returned contract incl. shared aux (enrollmentsByCourseId, ancestorProgramEnrollment). renderHook suite asserts the returned contract (never through the adapter); buildProgramScenario is a thin entities-in mock-wirer (tests own scenario shape). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…boardData (Phase 4 Task F) Component is now purely presentational: consumes the composer hook and routes the course arm through adaptCourseEntryToLegacyDashboardCardProps. All inline query orchestration / language state / req-tree shaping removed. Behavior byte-identical — ProgramEnrollmentDisplay.test.tsx unchanged and green (the regression oracle). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Branch-review follow-ups, no production behavior change: 1. test-utils buildProgramScenario: derive requiredProgramIds via getIdsFromReqTree(program.req_tree) + Set dedup so it truly mirrors the hook's useMemo (the drift-protection comment was inaccurate; closes a silent mock-key-drift trap). 2. useProgramDashboardData: reword stale '6 queries (replicated exactly from oracle)' comment (the hook is canonical post-Task-F). 3. useProgramDashboardData: drop dead re-export of V3UserProgramEnrollment + its now-unused import. 4. dashboardViewModel: make getRequirementSectionTitle module-private (only exercised internally via buildRequirementSections; not imported directly by tests). 5. useProgramDashboardData.test: add a composer renderHook scenario exercising the program-enrollment arm (closes a wiring-layer gap). 6. parseProgramRequirementSections: doc the recursion ≡ direct-children parity under the flat-req_tree invariant. Verified: yarn test DashboardPage/ (458 pass), mitxonline.test.ts (34 pass), frontends typecheck — all green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a file-header comment to HomeEnrollmentsDisplay.test.tsx and ProgramEnrollmentDisplay.test.tsx stating what belongs in these component (layer-3) suites — seam/smoke + genuine component concerns — and that exhaustive case coverage belongs in the pure model / hook tests. Anti-bloat guardrail for future contributors. Comment-only: +33/-0, zero assertion/code changes. This is the single change to the otherwise-frozen Phase-4 behavior oracle (ProgramEnrollmentDisplay.test.tsx) — the oracle's diff vs origin/main is now exactly this one comment-only commit, no behavior change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3152be5 to
6989528
Compare
What are the relevant tickets?
For https://github.com/mitodl/hq/issues/11205
Description (What does it do?)
This PR moves logic out of ProgramEnrollmentDisplay. Now:
ProgramEnrollmentDisplayis display only, essentially zero computation, makes no queries of its own; delgates to useProgramDashboardDatauseProgramDashboardDatamakes queries and organizes data for the UI via pure functional utilities (most notabilitybuildRequirementSections). Also new isuseDashboardLanguagePickerbuildRequirementSectionsand other utilities.The new utilities are thoroughly tested. New tests also for
useProgramDashboardDataverify it is calling the utilities correctly, and tests foruseDashboardLanguagePickercheck its state / state mutation behaviors.How can this be tested?
main.