openedx / openedx/frontend-app-learning
Show the learner's bookmarks list inside the learning MFE
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 70
- Forks
- 335
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 35
Description
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.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/). - 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 abookmarks-list.underscoretemplate), rendered byCourseBookmarksViewinto 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}>. Thaturlcomes 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,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
- 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 agetBookmarks(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()inopenedx/features/course_bookmarks/plugins.py. - Retire the legacy page. With the MFE serving the list, the
openedx/features/course_bookmarks/bundle, its Mako templates, and the legacy view can be removed. That removal is tracked back in openedx/openedx-platform#38936.
Open questions
- 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
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. - 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.
References
- Tracker: openedx/openedx-platform#38936 (Course Bookmarks row).
- Legacy page:
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. - 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 pointsrc/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).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/course-home/outline-tab/widgets/CourseTools.jsx and src/courseware/course/bookmark/data/api.js, then compare the route pattern from frontend-app-learning#2056. Trace the existing API and legacy entry points named in the issue; done means the MFE renders the course's bookmark list with unit links and CourseBookmarksTool.url() points to it, with empty and pagination behavior decided.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, react
- Domain
- backend, frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100