You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Show the learner's bookmarks list inside the learning MFE
Context
Learners can bookmark a unit from inside the learning MFE, but there's no in-MFE page to see the bookmarks they've made. The "my bookmarks" list is still the old server-rendered Backbone page at /courses/{course_id}/bookmarks/, and the MFE only links out to it. This issue is about building that list view in the MFE so the legacy page can go away.
The backend is already done. The bookmarks REST API (openedx/core/djangoapps/bookmarks/, mounted at /api/bookmarks/v1/bookmarks/) serves a paginated, course-filtered list with everything the list needs, so this is frontend-only work.
What exists today
Creating bookmarks works in the MFE.src/courseware/course/bookmark/BookmarkButton.jsx renders in the unit view through UnitTitleSlot, and src/courseware/course/bookmark/data/api.js calls the REST API to create and delete bookmarks (POST/DELETE on /api/bookmarks/v1/bookmarks/).
The list view is legacy. The bookmarks list is a RequireJS/Backbone bundle under openedx/features/course_bookmarks/ (course_bookmarks_factory.js, a Backbone model/collection/view, and a bookmarks-list.underscore template), rendered by CourseBookmarksView into a Mako page. There's no waffle flag on it; it's gated by enrollment.
The MFE links out to it. The bookmarks entry point is the outline's Course Tools widget (src/course-home/outline-tab/widgets/CourseTools.jsx), which renders a plain <a href={courseTool.url}>. That url comes from the backend Course Tool plugin (openedx/features/course_bookmarks/plugins.py) and points at the legacy page.
The list API is ready.GET /api/bookmarks/v1/bookmarks/?course_id={course_id}&fields=display_name,path returns the learner's bookmarks for a course, paginated, with display_name and a path breadcrumb to the block. This is the same API the legacy list already consumes.
Proposed approach
Add a bookmarks list view in the MFE. Add a route and a component that fetches the learner's bookmarks for the course and renders them as a list, each linking to the unit in the courseware. Reuse the existing bookmark API client in src/courseware/course/bookmark/data/ by adding a getBookmarks(courseId) GET.
Point the entry at the MFE. Once the view exists, route the Course Tools "Bookmarks" link to the in-MFE page instead of the legacy URL. That's a small backend change to CourseBookmarksTool.url() in openedx/features/course_bookmarks/plugins.py.
Where the list lives: a dedicated route reached from Course Tools, or a courseware tab. Match whatever pattern the custom-pages work (frontend-app-learning#2056) settles on for consistency.
Block links: the API path gives the breadcrumb to the block; confirm it carries enough to build the in-courseware link to each bookmarked unit, or resolve the unit URL the same way the outline does.
Empty and paginated states: the legacy view handles "no bookmarks yet" and pages at 10/page. Decide whether to page or load all for a course.
Removing from the list: whether the list view also lets a learner remove a bookmark, or just navigates. The delete API already exists either way.
Legacy page: openedx/features/course_bookmarks/views/course_bookmarks.py (CourseBookmarksView); templates under openedx/features/course_bookmarks/templates/; Backbone bundle under openedx/features/course_bookmarks/static/course_bookmarks/; Course Tool plugin openedx/features/course_bookmarks/plugins.py.
REST API: openedx/core/djangoapps/bookmarks/ (views.pyBookmarksListView / BookmarksDetailView, urls at /api/bookmarks/v1/bookmarks/).
MFE today: src/courseware/course/bookmark/BookmarkButton.jsx, src/courseware/course/bookmark/data/api.js; entry point src/course-home/outline-tab/widgets/CourseTools.jsx.
Related: frontend-app-learning#2056 (custom pages, same "build the MFE view then drop the legacy bundle" shape), frontend-app-learning#2014 (React Query conversion of the existing bookmark toggle).
Show the learner's bookmarks list inside the learning MFE
Context
Learners can bookmark a unit from inside the learning MFE, but there's no in-MFE page to see the bookmarks they've made. The "my bookmarks" list is still the old server-rendered Backbone page at
/courses/{course_id}/bookmarks/, and the MFE only links out to it. This issue is about building that list view in the MFE so the legacy page can go away.The backend is already done. The bookmarks REST API (
openedx/core/djangoapps/bookmarks/, mounted at/api/bookmarks/v1/bookmarks/) serves a paginated, course-filtered list with everything the list needs, so this is frontend-only work.What exists today
src/courseware/course/bookmark/BookmarkButton.jsxrenders in the unit view throughUnitTitleSlot, andsrc/courseware/course/bookmark/data/api.jscalls the REST API to create and delete bookmarks (POST/DELETEon/api/bookmarks/v1/bookmarks/).openedx/features/course_bookmarks/(course_bookmarks_factory.js, a Backbone model/collection/view, and abookmarks-list.underscoretemplate), rendered byCourseBookmarksViewinto a Mako page. There's no waffle flag on it; it's gated by enrollment.src/course-home/outline-tab/widgets/CourseTools.jsx), which renders a plain<a href={courseTool.url}>. Thaturlcomes from the backend Course Tool plugin (openedx/features/course_bookmarks/plugins.py) and points at the legacy page.GET /api/bookmarks/v1/bookmarks/?course_id={course_id}&fields=display_name,pathreturns the learner's bookmarks for a course, paginated, withdisplay_nameand apathbreadcrumb to the block. This is the same API the legacy list already consumes.Proposed approach
src/courseware/course/bookmark/data/by adding agetBookmarks(courseId)GET.CourseBookmarksTool.url()inopenedx/features/course_bookmarks/plugins.py.openedx/features/course_bookmarks/bundle, its Mako templates, and the legacy view can be removed. That removal is tracked back in Inventory the current state of the MFEs and Legacy Pages openedx-platform#38936.Open questions
pathgives the breadcrumb to the block; confirm it carries enough to build the in-courseware link to each bookmarked unit, or resolve the unit URL the same way the outline does.References
openedx/features/course_bookmarks/views/course_bookmarks.py(CourseBookmarksView); templates underopenedx/features/course_bookmarks/templates/; Backbone bundle underopenedx/features/course_bookmarks/static/course_bookmarks/; Course Tool pluginopenedx/features/course_bookmarks/plugins.py.openedx/core/djangoapps/bookmarks/(views.pyBookmarksListView/BookmarksDetailView, urls at/api/bookmarks/v1/bookmarks/).src/courseware/course/bookmark/BookmarkButton.jsx,src/courseware/course/bookmark/data/api.js; entry pointsrc/course-home/outline-tab/widgets/CourseTools.jsx.