Skip to content

Commit

Permalink
Merge pull request #3 from Pearson-Advance/vue/PADV-269
Browse files Browse the repository at this point in the history
PADV-269 Adding the interaction with the sidebar MFE.
  • Loading branch information
anfbermudezme authored and Jacatove committed Nov 23, 2023
2 parents 2d6a041 + 6686161 commit 3f19a99
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 33 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ TERMS_OF_SERVICE_URL=''
TWITTER_HASHTAG=''
TWITTER_URL=''
USER_INFO_COOKIE_NAME=''
DISABLE_SELF_ENROLLMENT='false'
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ TWITTER_HASHTAG='myedxjourney'
TWITTER_URL='https://twitter.com/edXOnline'
USER_INFO_COOKIE_NAME='edx-user-info'
SESSION_COOKIE_DOMAIN='localhost'
DISABLE_SELF_ENROLLMENT='false'
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ TERMS_OF_SERVICE_URL='https://www.edx.org/edx-terms-service'
TWITTER_HASHTAG='myedxjourney'
TWITTER_URL='https://twitter.com/edXOnline'
USER_INFO_COOKIE_NAME='edx-user-info'
DISABLE_SELF_ENROLLMENT='false'
3 changes: 2 additions & 1 deletion src/alerts/enrollment-alert/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {
useContext, useMemo,
} from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { getConfig } from '@edx/frontend-platform';

import { useAlert } from '../../generic/user-messages';
import { useModel } from '../../generic/model-store';
Expand All @@ -23,7 +24,7 @@ export function useEnrollmentAlert(courseId) {
*/
const isVisible = !enrolledUser && authenticatedUser !== null && privateOutline;
const payload = {
canEnroll: outline && outline.enrollAlert ? outline.enrollAlert.canEnroll : false,
canEnroll: getConfig().DISABLE_ENROLL_BUTTON === 'true' && outline && outline.enrollAlert ? outline.enrollAlert.canEnroll : false,
courseId,
extraText: outline && outline.enrollAlert ? outline.enrollAlert.extraText : '',
isStaff: course && course.isStaff,
Expand Down
3 changes: 3 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* eslint-disable import/prefer-default-export */

export const SIDEBAREVENT = 'outline_event';
38 changes: 20 additions & 18 deletions src/course-home/outline-tab/OutlineTab.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -541,26 +541,28 @@ describe('Outline Tab', () => {
const alert = await screen.findByTestId('private-course-alert');
expect(alert).toHaveAttribute('role', 'alert');

expect(screen.getByRole('button', { name: 'Enroll now' })).toBeInTheDocument();
// Enroll Now button should be disabled to avoid self enrollments.
// expect(screen.getByRole('button', { name: 'Enroll now' })).toBeInTheDocument();
});

it('handles button click', async () => {
const { location } = window;
delete window.location;
window.location = {
reload: jest.fn(),
};
await fetchAndRender();

const button = await screen.findByRole('button', { name: 'Enroll now' });
fireEvent.click(button);
await waitFor(() => expect(axiosMock.history.post).toHaveLength(1));
expect(axiosMock.history.post[0].data)
.toEqual(JSON.stringify({ course_details: { course_id: courseId } }));
expect(window.location.reload).toHaveBeenCalledTimes(1);

window.location = location;
});
// Enroll Now button should be disabled to avoid self enrollments.
// it('handles button click', async () => {
// const { location } = window;
// delete window.location;
// window.location = {
// reload: jest.fn(),
// };
// await fetchAndRender();

// const button = await screen.findByRole('button', { name: 'Enroll now' });
// fireEvent.click(button);
// await waitFor(() => expect(axiosMock.history.post).toHaveLength(1));
// expect(axiosMock.history.post[0].data)
// .toEqual(JSON.stringify({ course_details: { course_id: courseId } }));
// expect(window.location.reload).toHaveBeenCalledTimes(1);

// window.location = location;
// });
});

describe('Access Expiration Alert', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable import/prefer-default-export */
import React, { useContext, useMemo } from 'react';
import { AppContext } from '@edx/frontend-platform/react';
import { getConfig } from '@edx/frontend-platform';
import { ALERT_TYPES, useAlert } from '../../../../generic/user-messages';
import { useModel } from '../../../../generic/model-store';

Expand All @@ -20,7 +21,7 @@ export function usePrivateCourseAlert(courseId) {
const isVisible = !enrolledUser && (privateOutline || authenticatedUser !== null);
const payload = {
anonymousUser: authenticatedUser === null,
canEnroll: outline && outline.enrollAlert ? outline.enrollAlert.canEnroll : false,
canEnroll: getConfig().DISABLE_ENROLL_BUTTON === 'true' && outline && outline.enrollAlert ? outline.enrollAlert.canEnroll : false,
courseId,
};

Expand Down
31 changes: 30 additions & 1 deletion src/courseware/CoursewareContainer.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { history } from '@edx/frontend-platform';
import { history, getConfig } from '@edx/frontend-platform';
import { createSelector } from '@reduxjs/toolkit';
import { defaultMemoize as memoize } from 'reselect';
import { postEventToIframe } from 'eventsHandler';
import { SIDEBAREVENT } from 'constants';

import {
checkBlockCompletion,
Expand Down Expand Up @@ -269,6 +271,13 @@ class CoursewareContainer extends Component {
if (nextSequence !== null) {
history.push(`/course/${courseId}/${nextSequence.id}/first`);

// Function to send the event to Outline Navigation SIdebar.
postEventToIframe(
document.getElementById('OutlineSidebar'),
SIDEBAREVENT,
[getConfig().SIDEBAR_MFE_BASE_URL],
);

const celebrateFirstSection = course && course.celebrations && course.celebrations.firstSection;
if (celebrateFirstSection && sequence.sectionId !== nextSequence.sectionId) {
handleNextSectionCelebration(sequenceId, nextSequence.id);
Expand All @@ -278,11 +287,30 @@ class CoursewareContainer extends Component {

handlePreviousSequenceClick = () => {
const { previousSequence, courseId } = this.props;

if (previousSequence !== null) {
history.push(`/course/${courseId}/${previousSequence.id}/last`);

// Function to send the event to Outline Navigation SIdebar.
postEventToIframe(
document.getElementById('OutlineSidebar'),
SIDEBAREVENT,
[getConfig().SIDEBAR_MFE_BASE_URL],
);
}
}

handleOutlineSidebarNavigationClick = (id) => {
const {
courseId,
sequenceId,
} = this.props;

if (id !== null && id !== sequenceId) {
history.push(`/course/${courseId}/${id}/first`);
}
};

render() {
const {
courseStatus,
Expand Down Expand Up @@ -310,6 +338,7 @@ class CoursewareContainer extends Component {
nextSequenceHandler={this.handleNextSequenceClick}
previousSequenceHandler={this.handlePreviousSequenceClick}
unitNavigationHandler={this.handleUnitNavigationClick}
sidebarNavigationClickHandler={this.handleOutlineSidebarNavigationClick}
/>
</TabPage>
);
Expand Down
32 changes: 21 additions & 11 deletions src/courseware/course/Course.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { useDispatch } from 'react-redux';
import { getConfig } from '@edx/frontend-platform';
import { breakpoints, useWindowSize } from '@edx/paragon';

import OutlineSidebar from 'courseware/course/sidebar/sidebars/outline/OutlineSidebar';
import SidebarOutlineTrigger from 'courseware/course/sidebar/SidebarOutlineTrigger';
import { AlertList } from '../../generic/user-messages';

import Sequence from './sequence';
Expand All @@ -14,7 +16,6 @@ import ContentTools from './content-tools';
import CourseBreadcrumbs from './CourseBreadcrumbs';
import SidebarProvider from './sidebar/SidebarContextProvider';
import SidebarTriggers from './sidebar/SidebarTriggers';
import SidebarOutlineTrigger from './sidebar/SidebarOutlineTrigger';

import { useModel } from '../../generic/model-store';
import { getSessionStorage, setSessionStorage } from '../../data/sessionStorage';
Expand All @@ -29,6 +30,7 @@ function Course({
nextSequenceHandler,
previousSequenceHandler,
unitNavigationHandler,
sidebarNavigationClickHandler,
windowWidth,
}) {
const course = useModel('coursewareMeta', courseId);
Expand Down Expand Up @@ -101,16 +103,22 @@ function Course({
</section>

<AlertList topic="sequence" />
<Sequence
unitId={unitId}
sequenceId={sequenceId}
courseId={courseId}
unitNavigationHandler={unitNavigationHandler}
nextSequenceHandler={nextSequenceHandler}
previousSequenceHandler={previousSequenceHandler}
//* * [MM-P2P] Experiment */
mmp2p={MMP2P}
/>
<section className="sequence-container d-inline-flex flex-row">
<OutlineSidebar />
<section className="sequence w-100">
<Sequence
unitId={unitId}
sequenceId={sequenceId}
courseId={courseId}
unitNavigationHandler={unitNavigationHandler}
nextSequenceHandler={nextSequenceHandler}
previousSequenceHandler={previousSequenceHandler}
sidebarNavigationClickHandler={sidebarNavigationClickHandler}
//* * [MM-P2P] Experiment */
mmp2p={MMP2P}
/>
</section>
</section>
<CelebrationModal
courseId={courseId}
isOpen={firstSectionCelebrationOpen}
Expand All @@ -136,13 +144,15 @@ Course.propTypes = {
nextSequenceHandler: PropTypes.func.isRequired,
previousSequenceHandler: PropTypes.func.isRequired,
unitNavigationHandler: PropTypes.func.isRequired,
sidebarNavigationClickHandler: PropTypes.func,
windowWidth: PropTypes.number.isRequired,
};

Course.defaultProps = {
courseId: null,
sequenceId: null,
unitId: null,
sidebarNavigationClickHandler: null,
};

function CourseWrapper(props) {
Expand Down
3 changes: 3 additions & 0 deletions src/courseware/course/Course.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ describe('Course', () => {
const nextSequenceHandler = jest.fn();
const previousSequenceHandler = jest.fn();
const unitNavigationHandler = jest.fn();
const sidebarNavigationClickHandler = jest.fn();

const courseMetadata = Factory.build('courseMetadata');
const unitBlocks = Array.from({ length: 3 }).map(() => Factory.build(
Expand All @@ -207,6 +208,7 @@ describe('Course', () => {
nextSequenceHandler,
previousSequenceHandler,
unitNavigationHandler,
sidebarNavigationClickHandler,
};
render(<Course {...testData} />, { store: testStore });

Expand All @@ -219,6 +221,7 @@ describe('Course', () => {
expect(previousSequenceHandler).not.toHaveBeenCalled();
expect(nextSequenceHandler).not.toHaveBeenCalled();
expect(unitNavigationHandler).toHaveBeenCalledTimes(4);
expect(sidebarNavigationClickHandler).not.toHaveBeenCalled();
});

describe('Sequence alerts display', () => {
Expand Down
17 changes: 16 additions & 1 deletion src/courseware/course/sequence/Sequence.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ function Sequence({
unitNavigationHandler,
nextSequenceHandler,
previousSequenceHandler,
sidebarNavigationClickHandler,
intl,
mmp2p,
}) {
Expand Down Expand Up @@ -77,6 +78,20 @@ function Sequence({
unitNavigationHandler(destinationUnitId);
};

function handleSidebarNavigation(event) {
if (event.data.message === 'outline_sidebar_navigation_started') {
sidebarNavigationClickHandler(event.data.subsection_id);
}
}
// Event Listener for frontend-app-sidebar-navigation
useEffect(() => {
window.addEventListener('message', handleSidebarNavigation);
// Cleanup eventListener
return () => {
window.removeEventListener('message', handleSidebarNavigation);
};
});

const logEvent = (eventName, widgetPlacement, targetUnitId) => {
// Note: tabs are tracked with a 1-indexed position
// as opposed to a 0-index used throughout this MFE
Expand Down Expand Up @@ -157,7 +172,6 @@ function Sequence({

const defaultContent = (
<div className="sequence-container d-inline-flex flex-row">
{isOutlineActive ? <Sidebar /> : null}
<div className={classNames('sequence w-100', { 'position-relative': shouldDisplayNotificationTriggerInSequence })}>
<SequenceNavigation
sequenceId={sequenceId}
Expand Down Expand Up @@ -253,6 +267,7 @@ Sequence.propTypes = {
unitNavigationHandler: PropTypes.func.isRequired,
nextSequenceHandler: PropTypes.func.isRequired,
previousSequenceHandler: PropTypes.func.isRequired,
sidebarNavigationClickHandler: PropTypes.func.isRequired,
intl: intlShape.isRequired,

/** [MM-P2P] Experiment */
Expand Down
Loading

0 comments on commit 3f19a99

Please sign in to comment.