Skip to content

Conversation

@PKulkoRaccoonGang
Copy link
Contributor

@PKulkoRaccoonGang PKulkoRaccoonGang commented Sep 5, 2025

Warning

Currently, the list of courses returned by the API /search/v1/course_discovery/ does not contain courses for which the enrollment date has expired (enrollment_end). We plan to discuss this during a code review on the backend side.

Description

This PR introduces several improvements related to the course listing on the Home page and prepares the foundation for upcoming changes on the Catalog page. It also includes enhancements to the CourseCard component, API integration updates, and minor UI improvements.

  • added course list for the Home page
  • interaction with the course-discovery API has been moved to the application level (this API will also be used on Catalog page)
  • getCourseDiscoveryUrl changed from /search/course_discovery/ to /search/v1/course_discovery/ (updated version of existing API)
  • updated CourseCard component:
    • improved alternative text for the main course image
    • added changes for the organization logo (one of the next backend PRs will add the necessary changes for this)
    • added course number
    • added logic to display the correct course start date (according to the legacy template)
  • updated test mocks according to API changes
  • added new plugin slots (for card list and card)

Useful information

Legacy templates

Figma design

Initial setup

  1. Clone and install the tutor-mfe plugin from the draft PR that adds support for Catalog MFE.
  2. Go to http://apps.local.openedx.io:1998/catalog/

How Has This Been Tested?

  1. Go to Course Home page (http://apps.local.openedx.io:1998/catalog/).
  2. When loading the page, a loader (spinner) is displayed.
  3. If there are no courses, an alert is displayed with information about this.
image
  1. If an error occurred while loading the page content - an error message is displayed (message taken from LearnerDashboard MFE).
image
  1. If the value of the COURSES_ARE_BROWSABLE flag is false, the course list is not displayed.
  2. Create a new course from Studio.
  3. Check the display of the course card on the new Course Home page.
  4. By clicking on the course card, the New Course About page opens (http://apps.local.openedx.io:1998/catalog/courses/<course_id>/about) without full page reloading (React Router).
  5. If the number of courses is greater than the HOMEPAGE_COURSE_MAX (Django site configurations) value, or 9, the button "View all courses" is displayed.
image
  1. Check the usage of new plugin slots (for card list and card) based on existing examples.

@openedx-webhooks
Copy link

openedx-webhooks commented Sep 5, 2025

Thanks for the pull request, @PKulkoRaccoonGang!

This repository is currently maintained by @openedx/committers-frontend.

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.

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Sep 5, 2025
@PKulkoRaccoonGang PKulkoRaccoonGang self-assigned this Sep 5, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in Contributions Sep 5, 2025
@PKulkoRaccoonGang PKulkoRaccoonGang changed the title feat: added courses list for Home page feat: [FC-86] Home page course list section Sep 5, 2025
@PKulkoRaccoonGang PKulkoRaccoonGang force-pushed the Peter_Kulko/courses-list-for-home-page branch from d1b90de to e1921f1 Compare September 5, 2025 16:21
@codecov
Copy link

codecov bot commented Sep 5, 2025

Codecov Report

❌ Patch coverage is 98.13084% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.90%. Comparing base (667f82b) to head (b5345cf).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/home/components/index.ts 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #18      +/-   ##
==========================================
+ Coverage   96.41%   96.90%   +0.48%     
==========================================
  Files          36       42       +6     
  Lines         251      323      +72     
  Branches       32       50      +18     
==========================================
+ Hits          242      313      +71     
- Misses          9       10       +1     

☔ View full report in Codecov by Sentry.
📢 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.

page_size: pageSize,
page_index: pageIndex,
});
.post(getCourseDiscoveryUrl(), formData);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

[inform/question]: During testing, I realized that the course_discovery API only returns courses for which enrollment_end is either not specified or the enrollment date for the course has not yet expired. We will address this issue on the backend side.

But, it seems strange to me that the legacy page displayed courses for which the enrollment date had passed and a student (or new student), upon seeing this course, would not be able to register for it.

Do you have any thoughts on this?

@mphilbrick211 mphilbrick211 added the FC Relates to an Axim Funded Contribution project label Sep 10, 2025
@mphilbrick211 mphilbrick211 moved this from Needs Triage to In Eng Review in Contributions Sep 10, 2025
Copy link
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

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

Overall this looks great!

I left a couple comments about the loading/error/non-browsable states, but nothing that feels like it'll require major effort to resolve.

I also had some thoughts about the plugin slots being added that feel out of scope for this PR but should be addressed.

Things that make sense to address in a follow-up issue:

  • pluginProps for the HomeCourseCardSlot and HomeCoursesListSlot
    • I think this is more important for HomeCourseCardSlot than HomeCoursesListSlot. If a site operator is fully replacing the list they are more likely to have ways to fetch the data, but if they are just replacing the cards they'll likely want to use the course info associated with each card that is being replaced.
    • I think this makes sense as a follow-up issue (to be completed as part of this FC) instead of blocking this PR because:
      • This PR satisfies the "has slots" requirement
      • Updating the slots to include relevant pluginProps makes sense to me as a standalone PR


if (isCoursesLoading) {
return (
<Loading />
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the vh-100 in the Loading component is causing issues.

The spinner appears at the bottom of the screen at a standard window height for me
image

and it if off screen entirely at smaller heights

Screencast.From.2025-09-11.13-23-41.mp4

Copy link
Contributor

@brian-smith-tcril brian-smith-tcril Sep 11, 2025

Choose a reason for hiding this comment

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

Maybe it'd be worth considering using the Paragon card loading state here? That might be complicated because we don't know how many courses to expect (so we don't know how many cards to render), but it might still be worth looking into.

Copy link
Contributor Author

@PKulkoRaccoonGang PKulkoRaccoonGang Sep 15, 2025

Choose a reason for hiding this comment

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

The previous loading state for course list section has been updated to use the Paragon card loading state.

Since we cannot predict the exact number of courses, I suggest using getConfig().HOMEPAGE_COURSE_MAX || DEFAULT_COURSES_COUNT to determine how many skeleton cards to display (by default, this would be 9 cards).

Overall, I like how the loading appears using the card loading state. What are your thoughts?

Added in 2a50033

Example with Slow 4G (slow loading speed)

Screen.Recording.Sept.15.2025.from.Video.Trimmer.mp4

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree using the card loading state here looks great!

I am a bit curious about how plugin authors/site operators will feel about needing to handle the isLoading state in their CourseCard replacements if they aren't replacing CoursesList, but I can already think of a non-breaking way to address one of the concerns I'm foreseeing:

  • "I want to replace the loaded CourseCard component. I don't want to implement a loading state for my replacement. I don't want to replace the CoursesList component. I want to show one loading icon instead of one per card."
    • We could wrap the contents of the Container being returned in the if (isCoursesLoading) block with a slot that can be used for a generic loading state.

Copy link
Contributor

Choose a reason for hiding this comment

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

In my local testing this feels a little "jumpy" with a fast connection

Screencast.From.2025-09-15.10-42-39.mp4

I expect this won't be an issue with sites that have 9 or more courses displayed on the home page. I also think part of what is making it feel "jumpy" to me is the footer moving (which feels like the same issue as #20)

Copy link
Contributor Author

@PKulkoRaccoonGang PKulkoRaccoonGang Sep 16, 2025

Choose a reason for hiding this comment

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

I am a bit curious about how plugin authors/site operators will feel about needing to handle the isLoading state in their CourseCard replacements if they aren't replacing CoursesList

On the one hand, without a generic loader slot, operators need to handle isLoading for each individual course card. On the other hand, by introducing a generic loader slot, we can give operators the option to provide a custom loader for the entire course list section if they replace course cards through slots.

At first glance, these two approaches may look similar, but adding a custom loader for the course list section seems simpler than implementing a custom skeleton (or another solution) for each individual card.

The only downside I see with this approach is that operators will need to take extra steps if they only want to replace the course card itself. However, this feels like a logical and very flexible solution 💯

Added in: dacb685

I also think part of what is making it feel "jumpy" to me is the footer moving (which feels like the same issue as #20)

This non-pinned footer causes certain issues, but I think that even with a pinned footer, we would still see minor layout "jump". In the future, when the footer has the correct position, it will look better, but the key issue is that if there is a significant difference between the value of HOMEPAGE_COURSE_MAX (or DEFAULT_COURSES_COUNT) and the actual number of courses on the page, the number of loading skeletons displayed will not match the real number of course cards.

For example, if HOMEPAGE_COURSE_MAX is set to 9, we will show 9 skeleton cards, but if there are only 3 courses in total, the final result will be 3 cards.

I tried porting the footer changes from the Learning MFE and checking how the course card loading looks with a pinned footer. It definitely looks better, but it doesn’t fully solve the problem of the mismatch between skeleton cards and the actual number of course cards.

Screen.Recording.Sept.16.2025.from.Video.Trimmer.mp4

That said, I agree with your point that this issue is most noticeable when the platform has only a small number of courses, which I believe is not a common case.

@PKulkoRaccoonGang PKulkoRaccoonGang force-pushed the Peter_Kulko/courses-list-for-home-page branch from 2693b29 to 2a50033 Compare September 15, 2025 08:34
@PKulkoRaccoonGang
Copy link
Contributor Author

I also had some thoughts about the plugin slots being added that feel out of scope for this PR but should be addressed.

@brian-smith-tcril I don't mind doing this in a separate PR (added the appropriate TODO for future changes)

Additionally, the latest updates include improvements to the course cards’ loading state, the Badge for the organization name, and a few minor enhancements. Please take a look when you have a chance.

@brian-smith-tcril
Copy link
Contributor

Overall, everything looks great in my local testing!

Are the dependencies on the checklist in the PR description up to date?

I also had some thoughts about the plugin slots being added that feel out of scope for this PR but should be addressed.

@brian-smith-tcril I don't mind doing this in a separate PR (added the appropriate TODO for future changes)

That looks great! It might also be worth making a GH issue to track that.

@PKulkoRaccoonGang
Copy link
Contributor Author

PKulkoRaccoonGang commented Sep 16, 2025

It might also be worth making a GH issue to track that.

Created new issue: #22

Are the dependencies on the checklist in the PR description up to date?

Yes, this PR is currently awaiting review completion for two backend PRs:

@brian-smith-tcril
Copy link
Contributor

Thanks @PKulkoRaccoonGang!

Overall this PR LGTM!

I'm going to hold off on merging it until the 2 backend PRs are merged and I've had a chance to test this against the latest upstream versions of edx-platform and edx-search, as it is possible changes in those PRs as a result of their respective reviews will need to be reflected in this.

@sarina
Copy link

sarina commented Oct 1, 2025

Since the edx-platform PRs have been merged, should this PR be updated to resolve conflicts and ensure things are at least working with edx-platform changes?

@PKulkoRaccoonGang PKulkoRaccoonGang force-pushed the Peter_Kulko/courses-list-for-home-page branch from dacb685 to a684fdb Compare October 3, 2025 12:03
@brian-smith-tcril
Copy link
Contributor

LGTM!

The changes in b5345cf look great, and I've verified this works when running against the latest master branches of edx-platform and edx-search.

@brian-smith-tcril brian-smith-tcril merged commit 1cf6194 into openedx:master Oct 3, 2025
6 checks passed
@github-project-automation github-project-automation bot moved this from In Eng Review to Done in Contributions Oct 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FC Relates to an Axim Funded Contribution project open-source-contribution PR author is not from Axim or 2U

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants