openedx / openedx/frontend-app-learning

Show the learner's bookmarks list inside the learning MFE

Open
#2,057 0 comments 0 reactions 0 assignees View on GitHub

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.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

  1. 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.
  2. 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.
  3. 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 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.

References

  • Tracker: openedx/openedx-platform#38936 (Course Bookmarks row).
  • 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.py BookmarksListView / 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).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.