Skip to content

feat: Pathways Panel in Learner dashboard [FC-0137] - #875

Open
ChrisChV wants to merge 24 commits into
openedx:masterfrom
open-craft:chris/pathway-updates
Open

ChrisChV wants to merge 24 commits into
openedx:masterfrom
open-craft:chris/pathway-updates

Conversation

@ChrisChV

@ChrisChV ChrisChV commented Oct 1, 2026 •

Copy link
Copy Markdown

Description

  • Adds the ENABLE_PATHWAY_PILOT_UI config flag and the useIsPathwayPilotUIEnabled hook.
  • Adds a pathways panel grouped by category, wrapped in the new pathwaysPanel slot.
  • Adds the reusable ItemBadge component.
  • Course cards now show a "Course" badge.
  • Makes the Courses heading and the Refine filter sticky while scrolling through the courses.
  • Adds an Included in strip to course cards with their pathways. Labels that don't fit go to a "+N" popover.
  • This strip is a twin component of the course page strip implemented in feat: Pathways strip in course pages [FC-0137] frontend-app-learning#2159
image image image

Supporting Information

Testing Instructions

  • Make sure that your learner user is enrolled in +6 courses.
  • Go to the learner dashboard.
  • Verify that there are no visible changes.
  • Enable ENABLE_PATHWAY_PILOT_UI using this plugin:
from tutor import hooks

hooks.Filters.ENV_PATCHES.add_item(
    (
        "mfe-lms-common-settings",
        'FRONTEND_SITE_CONFIG["commonAppConfig"]["ENABLE_PATHWAY_PILOT_UI"] = True',
    )
)
  • Verify that the Pathways panel matches the design.
  • Scroll and verify that the course title and Refine are attached to the top.
  • Verify the new Included in in some courses. Verify that you can see the hidden pathways by clicking the count button.
  • Verify the behaviour of this Included in by resizing the screen.

Notes

  • TODO: The backend still needs to be connected once it's ready.
  • TODO: Links leading to the pathway pages still need to be added.
  • I used Claude Opus 5.5 to review my code and add some fixes like 5a5fd87

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Oct 1, 2026
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @ChrisChV!

This repository is currently maintained by @2U-aperture.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.38272% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 93.22%. Comparing base (f4767a7) to head (9268eef).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/containers/CoursesPanel/index.jsx 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #875      +/-   ##
==========================================
+ Coverage   92.46%   93.22%   +0.75%     
==========================================
  Files         151      169      +18     
  Lines        1288     1447     +159     
  Branches      269      315      +46     
==========================================
+ Hits         1191     1349     +158     
- Misses         92       93       +1     
  Partials        5        5              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ChrisChV ChrisChV changed the title feat: Pathways Panel in Learner dashboard feat: Pathways Panel in Learner dashboard [FC-0137] Oct 1, 2026

@rpenido rpenido left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great @ChrisChV!
Thank you for your work!

  • I tested this using the instructions from the PR
  • I read through the code
  • I checked for accessibility issues
  • Includes documentation

One suggestion so we can get rid of the patch while developing:

  • Put your dummy data as a mock file in the tests
  • Then, we can already implement all tests for the feature right away (we don't need the backend for that)
  • Create the api layer and, for now, return the mock data
  • Update the hook to call the api, and probably the hook code will also be final

That way, when the backend ships, we just need to update the api layer and the already tests that we wrote will help us to check if everything is fine. Also, we likely will have the coverage already sorted out.

Does that make sense? If it does, I will apply the same pattern for the other features.

categoryLabel={<FormattedMessage {...messages.courseBadge} />}
className="text-dark-900 bg-light-500"
/>
<CourseCardMenu cardId={cardId} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly in your change, but the Dropdown.Toggle is not centered with the badge.

Image

We can fix it with the following adding className="d-flex align-items-center" to it.

      <Dropdown onToggle={handleToggleDropdown}>
        <Dropdown.Toggle
          id={`course-actions-dropdown-${cardId}`}
          className="d-flex align-items-center"
          as={IconButton}
Image

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 79797d4

Comment on lines +1 to +2
.course-card-pathways {
.course-card-pathways-container {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the height strip be the same with or without the dropdown to show
more items

Suggested change
.course-card-pathways {
.course-card-pathways-container {
.course-card-pathways {
min-height: 3.5rem;
.course-card-pathways-container {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 79797d4

Comment thread src/containers/CoursesPanel/index.jsx Outdated
</Stack>
)
: (
<h2 className="dashboard-title">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They seem to have the same styles

Suggested change
<h2 className="dashboard-title">
<h2 className="course-list-title">

If we want to use the dashboard-title, we can remove the course-list-title from the scss

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 79797d4

Comment thread src/containers/CoursesPanel/messages.js Outdated
description: 'Course list heading',
},
coursesTitle: {
id: 'dahsboard.coursesTitle',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo

Suggested change
id: 'dahsboard.coursesTitle',
id: 'dashboard.coursesTitle',

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated 79797d4

Comment thread src/components/ItemBadge.tsx Outdated
Comment on lines +26 to +28
if (!useIsPathwayPilotUIEnabled()) {
return null;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving this check outside? (i.e CourseHeaderActions)

Suggested change
if (!useIsPathwayPilotUIEnabled()) {
return null;
}

The component doesn't have anything tied to Pathways and we can test it without adding the flag.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is related; this same badge is used on the Pathways cards, and using that card for courses only makes sense if another item exists—in this case, the pathways.

@ChrisChV

ChrisChV commented Oct 3, 2026 •

Copy link
Copy Markdown
Author

@rpenido Thanks for your review!

  • Put your dummy data as a mock file in the tests
  • Then, we can already implement all tests for the feature right away (we don't need the backend for that)
  • Create the api layer and, for now, return the mock data
  • Update the hook to call the api, and probably the hook code will also be final

What worries me about this is that we still don't know what the backend will be like. Creating a mock with tests means we'll have to change more code if the backend changes or if it's not as we have it set up here. I do agree with creating the hooks and the API layer, but I share the same concern. What do you think?

Edit: I've tried what you suggested in openedx/frontend-app-learning#2159, and it seems like a good approach to me. I updated that in 0cf1bf4

@rpenido

rpenido commented Oct 6, 2026

Copy link
Copy Markdown

Thanks @ChrisChV! LGTM 👍
Do you think we can close the coverage gap with the fixtures that you added?

In the Figma file we have two alternatives for the unenrollment dialog. We didn't change that, right?
image

@cassiezamparini Could you check if we want to use another design?
From figma:
image

@rpenido

rpenido commented Oct 7, 2026

Copy link
Copy Markdown

@ChrisChV, can you include the issue in the pr description?
#866

@ChrisChV

ChrisChV commented Oct 7, 2026

Copy link
Copy Markdown
Author

In the Figma file we have two alternatives for the unenrollment dialog. We didn't change that, right?

@rpenido No, I didn't see that change when I checked Figma, but I can implement it here. @cassiezamparini Is it something that was recently added?

ChrisChV and others added 4 commits October 7, 2026 15:45
…over and align it to the end of the strip

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…_mocks__

- Add tests for ItemBadge, PathwaysPanelSlot and isValidCssColor, and for
  the pathway pilot UI in CourseCard and CoursesPanel.
- Move the mock pathways from __fixtures__ to __mocks__ and leave every
  __mocks__ folder out of the coverage.
- Leave the no-document branch of isValidCssColor out of the coverage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cassiezamparini

Copy link
Copy Markdown

@rpenido @ChrisChV We can use this design:
Screenshot 2026-10-08 at 12 06 07

BUT, we need to incorporate the new text:

Unenroll from Python for Data Science?
Python for Data Science is part of the Data Engineering Fundamentals bootcamp and the Introduction to Machine Learning tutorial. By unenrolling, you will lose access to the course. If you enroll again, you may be placed in a different session of the course, and your progress might not carry over.

Is that possible? The learner needs to understand the repercussions.

@ChrisChV

ChrisChV commented Oct 8, 2026

Copy link
Copy Markdown
Author

Is that possible? The learner needs to understand the repercussions.

@cassiezamparini It is possible, but we need to consider the scenario where a course belongs to multiple pathways—specifically, how to display the titles of those N pathways within the modal. A similar situation arises in content libraries when deleting a component that is used in courses. The titles aren't mentioned there; only N and the repercussions are mentioned.

image

@cassiezamparini

Copy link
Copy Markdown

Ah got it @ChrisChV. Would this work?
Screenshot 2026-10-12 at 10 55 42

"This course is part of 1 bootcamp and 1 tutorial. If you unenroll, you'll lose access to the course, and your progress in those learning experiences may be affected. If you enroll again, you may be placed in a different session, and your progress might not carry over."

@ChrisChV

Copy link
Copy Markdown
Author

"This course is part of 1 bootcamp and 1 tutorial. If you unenroll, you'll lose access to the course, and your progress in those learning experiences may be affected. If you enroll again, you may be placed in a different session, and your progress might not carry over."

@cassiezamparini I'm a bit concerned about the translation of plurals in this modal. Categories are created by the admin, which means translations must also be managed by the admin; even without this modal, each category already needs categoryLabel (singular) and categoryLabelPlural fields, with translations added by the admin. This in itself is already somewhat complex. The introduction of this modal would add another layer of complexity in languages ​​that have multiple plural forms (such as Russian, Polish, or Arabic). The admin would need to create and save more translations; for example, in Russian, we would need to create translations for the forms: one, few, many, other. It's doable on the backend, but it adds work for the admins and room for mistakes, and it may be too much for a pilot.

A simpler option would be to not name the categories in this message, e.g. "This course is part of 2 learning experiences". That plural can be translated the usual way in the frontend, so admins wouldn't need to enter anything extra. We could switch to the per-category text later if needed.

What do you think?


@rpenido @Agrendalath has any i18n been seen in the architecture?

@cassiezamparini

Copy link
Copy Markdown

@ChrisChV Hmmm, got you.

I want to keep the category names in the modal somehow, because “bootcamps and tutorials” means something to learners and “learning experiences” doesn’t. If we leave out the count and reuse the existing plural label, would that avoid the extra plural forms for admins?

Unenroll from Python for Data Science?

This course is part of bootcamps and tutorials you’re enrolled in. You’ll lose access to the course until you enroll again. Re-enrolling may put you in a different session, and your progress might not carry over.

Would the above be workable for the pilot? Or what other ideas do you have?

@rpenido

rpenido commented Oct 13, 2026

Copy link
Copy Markdown

@rpenido @Agrendalath has any i18n been seen in the architecture?

@ChrisChV There is a discussion here:
https://openedx.atlassian.net/wiki/spaces/OEPM/pages/6630834191/Willow+Pathways+Decision+Log?focusedCommentId=6827442187

TLDR: no translations for the pilot, but we will have the title_plural field.

@ChrisChV

Copy link
Copy Markdown
Author

TLDR: no translations for the pilot, but we will have the title_plural field.

@rpenido Thanks!

Would the above be workable for the pilot? Or what other ideas do you have?

Yes, I think it is possible. I will implement it this way.

@ChrisChV
ChrisChV force-pushed the chris/pathway-updates branch from c47660d to da9d579 Compare October 17, 2026 02:16

@rpenido rpenido left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍
Thank you for your work, @ChrisChV!

  • I tested this using the instructions from the PR
  • I read through the code
  • I checked for accessibility issues
  • Includes documentation

Can you update the Testing instructions? We don't need the patch anymore, right?

@rpenido

rpenido commented Oct 18, 2026 •

Copy link
Copy Markdown

@kdmccormick and @ormsbee, this is ready for review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

open-source-contribution PR author is not from Axim or 2U

Projects

Status: Done
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants