Repository navigation
fix: omit the CCX Coach student_grades tab when the writable gradebook is unavailable #39148
Description
Description
The CCX Coach v2 metadata endpoint always advertises the student_grades tab,
regardless of whether the gradebook is actually available. In
lms/djangoapps/ccx/api/v2/serializers.py the tab list is a static tuple:
CCX_COACH_TABS = (
('enrollments', _('Enrollment'), 10),
('schedule', _('Schedule'), 20),
('student_grades', _('Student Grades'), 30),
('grading_policy', _('Grading Policy'), 40),
)The Student Grades experience depends on the writable gradebook, which is gated
by the grades.writable_gradebook waffle flag and the
WRITABLE_GRADEBOOK_URL setting. When either is missing, the MFE still renders a
Student Grades tab that cannot work, so coaches get a dead tab.
The backend can detect this, and there is already a precedent for exactly this
check.
Prior art
lms/djangoapps/instructor/views/serializers_v2.py::get_gradebook_url (~line 480)
returns None — i.e. omits the link — when either signal is unavailable:
mfe_base_url = configuration_helpers.get_value(
'WRITABLE_GRADEBOOK_URL',
getattr(settings, 'WRITABLE_GRADEBOOK_URL', None)
)
if not is_writable_gradebook_enabled(course_key) or not mfe_base_url:
return None
return f'{mfe_base_url.rstrip("/")}/{course_key}'Note configuration_helpers.get_value consults site configuration first and
falls back to the Django setting, so this honours per-site config.
is_writable_gradebook_enabled comes from lms.djangoapps.grades.api and wraps
the grades.writable_gradebook CourseWaffleFlag.
Proposed change
Build the CCX Coach tab list dynamically and omit student_grades when the
gradebook is unavailable, reusing the same two signals as the instructor
dashboard. Remaining tabs keep their existing sort_order values (10/20/40), so
gaps are expected and harmless — the MFE sorts by sort_order.
Open question: which course key to check
grades.writable_gradebook is a CourseWaffleFlag, and a course-scoped override
on the master course does not apply to the CCX key. Verified locally:
flag master=True ccx=False
Recommendation: check the CCX key (ccx-v1:...), because that is the key the
gradebook endpoints are actually called with. The tab's presence then predicts
whether the endpoint will work, instead of advertising a tab that 403s. This does
mean operators must enable the flag for the CCX key (or globally / via site
config) — worth calling out in the rollout notes.
Dependency
Even with the flag and URL configured, the gradebook REST endpoints currently
reject CCX ids; that is being fixed in #39145 ("change in endpoint to support CCX
id"). This ticket is about advertising the tab correctly and can land
independently, but the tab is only genuinely usable once #39145 merges.
Acceptance criteria
-
metadataomits thestudent_gradestab whengrades.writable_gradebook
is disabled for the course, or whenWRITABLE_GRADEBOOK_URLis not
configured (honouring site configuration). -
metadataincludes the tab when both signals are present. - Remaining tabs and their
sort_ordervalues are unchanged. - Decide and document which course key the flag is evaluated against.
- Tests cover: flag on + URL set (tab present), flag off (tab absent), URL
unset (tab absent).
Supporting information
- Epic: CCX Coach Conversion to MFE - New Endpoints #38982 (CCX Coach Conversion to MFE)
- Introduced the tab list: Create the CCX get_tabs() and basic CCX creation scaffolding #39031
- Gradebook CCX id support: feat: change in endpoint to support CCX id #39145
- Related: refactor: make CCX Coach v2 API URLs conform to ADR 0038 (remove verbs from create_ccx and remove_schedule) #39135 (ADR 0038 URL conformance), CCX Coach - Add Navigation Waffle Flag #39142 (CCX Coach MFE routing flag)
- Code:
lms/djangoapps/ccx/api/v2/serializers.py,
lms/djangoapps/grades/config/waffle.py,
lms/djangoapps/instructor/views/serializers_v2.py
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity