This is the first step toward clearing out the redundant metadata from the
coursewareMetadata and getting it from a common source - the courseHomeMetadata.
remove username from coursewareMetadata
Remove courseAccess from coursewareMetadata.
Fix all unit tests
Modify classes that use metadataModel to use courseHomeMetadata for common data.
metadataModel still exists as a mechanism to distinguish if a component is under
courseware or courseHome, and it will be renamed or removed in a later refactor.
In an attempt to debug some odd LMS errors (which would happen if
you loaded an MFE page with spaces instead of plus signs), this
commit notices page requests with spaces in the course key and
switches it out for plus signs, logging the incident.
* [feat] MICROBA-1523 Add notices redirect to learning MFE
To support the notices plugin on platform, this adds a redirect to the
course home page. If a user lands on that page and has not acknowledged
a notice, the user will be redirected to notice instead of the course
home.
URL format: /goal-unsubscribe/<uuid-token>
This is designed to be used in the new course goals feature, where
emails will be sent to learners and those emails will include a
link to this landing page, as an unsubscribe link.
Also, update calls to the LMS course home API to not include the
/v1/ fragment anymore, as we're moving to an unversioned API.
AA-907
* Update MFE to use the new “brand-openedx” repository.
This will allow the MFE to be re-branded by overriding this default implementation. More detail here:
https://github.com/edx/brand-openedx
* Removing unused frontend-component-header module.
This app doesn’t use frontend-component-header. That it was a dependency is confusing and led me to believe I needed to wait for its rebrand to continue - not so. Removing the unused dependency.
* Adding quick comment describing the structure of gated_content
* Fixing course exit styling
* Changing LinkedIn icon
* fix: fix Instructor toolbar button styling
* Bumping footer, platform, and paragon versions.
* Using configured logo and favicon.
Co-authored-by: Carla Duarte <cduarte@edx.org>
Remove some edX-specific branding / links (like support URLs) in
favor of values from configuration.
Images (sample certificates) are still branded for now. We can get
them later.
- Adds a non-passing cert learner course exit screen
- Moves all the logic about what course-exit mode we're in into
a utility method in the course-exit folder
- Moves all the logic about how the 'Next' button should read into
a utility method in the course-exit folder
The CourseExit page uses the TabContainer because it seems to be a better solution
than adding it into the paths for the CoursewareContainer, despite the CoursewareContainer
already doing the correct fetch. The reason for this is because within the
CoursewareContainer, it would still be necessary to check for the /course-exit path (due
to the CoursewareContainer trying to greedily match sequenceId (read: it will try and
look up 'course-exit' as a sequence)). That effectively defeats the purpose of using the
routing in the first place so instead, we place it in a TabContainer.
The InstructorToolbar didMount logic became necessary once we had a page (CourseExit) that does a redirect on a quick exit.
As a result, it unmouunts the InstructorToolbar (which will be remounted by the new component),
but the InstructorToolbar's MasqueradeWidget has an outgoing request. Since it is unmounted
during that time, it raises an error about a potential memory leak. By stopping the render
when the InstructorToolbar is unmounted, we avoid the memory leak.
* AA-196 course celebration cert
* AA-196: Course Celebration for passing Verified Learners
Co-authored-by: Dillon Dumesnil <ddumesnil@edx.org>
Note: This PR is being merged in somewhat incomplete as we decided to split off the work into a couple of other tickets. For example, the UI styling is not complete and I plan to also take another look at the routing. These code paths are not in use yet as the `courseExitPageIsActive` will always be False.
to redirect to the current unit’s lmsWebUrl if the MFE is disabled
If we receive an error_code of 'microfrontend_disabled',
go to the equivalent unit in the LMS experience.
Fixes: TNL-7362
Co-authored-by: stvn <stvn@mit.edu>
* Adding testing-library dependencies, and bumping frontend-build to be compatible with them.
* Adding a function to initialize the redux store
We need to use it in a few places. Seems worth not-repeating, since they can easily get out of sync. In general, tests should only test the parts of the store they care about, as well.
* Adding function to initialize a mock application.
Ultimately I’d like to move this to frontend-platform as an alternative to ‘initialize’ for tests. ‘initialize’ is an async function which complicates matters.
* Using more explicit assertions for courseware reducer fields.
This removes the need for the snapshot file, and ensures our test is more resilient to unrelated changes in the store.
Also added a few more stages of assertions to some of the tests, showing that they have the right values over time.
* Adding a helper to build a simple course blocks response.
We can use this in the courseware data tests, and shortly in the tests for CoursewareContainer.
* Modifying sequenceMetadata factory to allow multiple units.
This will help us test sequence navigation’s behavior more fully by having multiple units in a sequence.
* A little linting and cleanup.
* Adding first round of tests for CoursewareContainer.
Tests loading, sequence navigation/unit rendering, and ‘denied’ states.
Subsequent tests will add tests for handlers.
* Moving model-store into “generic” sub-directory.
Also adding a README.md to explain what belongs in “generic”
* Moving user-messages into “generic” sub-directory.
* Moving PageLoading into “generic” sub-directory.
* Moving “tabs” module into “generic” sub-directory.
* Moving InstructorToolbar and MasqueradeWidget up to instructor-toolbar.
The masquerade widget is a sub-module of instructor-toolbar.
* Co-locating celebration APIs with celebration utils.
Also adding an ADR about thunk/API naming conventions and making some other areas of the code adhere to it.
* Moving courseware data (thunks, api) into the courseware module.
Note that cousre-home/data/api still uses normalizeBlocks - this should be fixed so it’s not reaching across. Maybe we pull that particular API up top.
This PR includes a few TODOs for things I saw, as well as a tiny bit of whitespace cleanup.
- Pulled Course Home specific components into `course-home`
- Created a courseHome reducer (and all necessary data files - api, thunks, slice)
- Removed Course Home logic from Courseware's data files (api, thunks, slice, etc.)
- Renamed Outline Tab URL to end in `/home` rather than `/outline` again (per Product)
Co-authored-by: Carla Duarte <cduarte@edx.org>
- Updated the Outline Tab to fetch course blocks from the Outline API.
- Changed naming conventions to more accurately portray the tab naming scheme
(ex. Outline Tab, Dates Tab, etc.)
- Removed logic from `fetchCourses` that was specific to the Outline Tab
Specifically, make sure that the header, footer, and tabs are all
shared code so that they look the same and don't need to be
redefined as we add more tab pages.
* Adding an index.js file for user-messages.
Importing from the module, not its contents.
* Allowing customProps to be passed though AlertList to Alerts.
* UserMessagesProvider can create flash messages.
A flash message is one that will be displayed on the next reload of the page. UserMessagesProvider now provides a “addFlash” function. These messages are stored in localStorage and displayed the next time UserMessagesProvider is mounted, which is generally going to be on the next page refresh.
Once displayed, flash messages are cleared out of localStorage.
* Hooking up Enroll Now button and adding “success” alert.
Success alert is shown as a flash message on next page reload.
* Using ALERT_TYPES constants.
Fixes TNL-7175: Redirect to course home if a user is not unenrolled and the course is private.
- Require authentication to use the app while course blocks api requires it
- Gracefully handle course blocks api request failures allowing app to proceed to it redirection logic
Notable changes:
- selectors related to sequences are more resilient to missing models. In the case the course blocks api returns successfully but empty (in this case of enrolled but course not yet started).
- `fetchCourse` thunk handles failures for fetchCourseMeta and fetchCourseBlocks separately using `Promise.allSettled` instead of `Promise.all`
- `denied` is a new `courseStatus`
- Access denied redirect is done using a component at a new route `redirect/course-home/:courseId`
Now handles cases
- User is unauthenticated > redirect to login
- User is authenticated but not enrolled > redirects to lms course home
- When an enrolled user attempts to access courseware before the course start date they will load the sequence (but unable to load the vertical block). This behavior should be fixed in an update to edx-platform
* Extensive refactor of application data management.
- “course-blocks” and “course-meta” are replaced with “courseware” module. This obscures the difference between the two from the application itself.
- a generic “model-store” module is used to store all course, section, sequence, and unit data in a normalized way, agnostic to the metadata vs. blocks APIs.
- SequenceContainer has been removed, and it’s work is just done in CourseContainer instead.
- UI components are - in general - more responsible for deciding their own behavior during data loading. If they want to show a spinner or nothing, it’s up to their discretion.
- The API layer is responsible for normalizing data into a form the app will want to use, prior to putting it into the model store.
* Organizing into some more sub-modules.
- Bookmarks becomes it’s own module.
- SequenceNavigation becomes another one.
* More modularization of data directories.
- Moving model-store up to the top.
- Moving fetchCourse and fetchSequence up to the top-level data directory, since they’re used by both courseware and outline.
- Moving getBlockCompletion and updateSequencePosition into the courseware/data directory, since they pertain to that page.
* Normalizing on using the word “title”
* Using history.replace instead of history.push
This fixes TNL-7125
* Allowing sub-components to use hooks and redux
This reduces the amount of data we need to pass around, and lets us move some complexity to more natural modules.
* Fixing bug where enrollment alert is shown for undefined isEnrolled
The enrollment alert would inadvertently be shown if a user navigated from the outline to the course. This was because it interpreted an undefined “isEnrolled” flag as false. Instead, we should wait for the isEnrolled flag to be explicitly true or false.
* Organizing modules.
- Renaming “outline” to “course-home”.
- Moving sequence and sequence-navigation modules under the course module.
* Some final application organization and ADR write-ups.
* Final refactoring
- Favoring passing data by ID and looking it up in the store with useModel.
- Moving headers into course-header directory.
* Updating ADRs. Splitting model-store information out into its own ADR.
* refactor: Moving PageLoading up to the top
This way it can be used on both the courseware and outline pages.
* Adding index.js files to data directories, and PropTypes data shapes
- The course-blocks and course-meta data directories now have index files so their exports can be imported from that, rather than reaching into specific files in the directories.
- Also added “shapes” for use in React Components that use PropTypes for the course blocks data structure, and the course metadata data structure.
* Simplifying/refactoring CourseContainer rendering a bit.
* Adding course outline page.
This page is not complete.
- It contains the ‘outline’ itself with links to the Sequences in the course.
- It contains a very basic stab at displaying dates - they’re not even formatted.
- It shows logistration and enrollment alerts for anonymous and unenrolled users.
It does not include any other content in the right-hand sidebar. It also doesn’t include a welcome message, or perhaps any number of other features on the page. This is effectively an initial implementation for discovering how much data we’re missing from our APIs. It should not be used as-is by any means.