Merge pull request #114 from openedx/kshitij/tnl-9585/navigation-hints

feat: send message to learning MFE on navigation [BD-38] [TNL-9585]
This commit is contained in:
AsadAzam
2022-04-04 17:27:09 +05:00
committed by GitHub
5 changed files with 43 additions and 24 deletions

View File

@@ -4,7 +4,6 @@ import { useContext, useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory, useLocation, useRouteMatch } from 'react-router';
import { getConfig } from '@edx/frontend-platform';
import { AppContext } from '@edx/frontend-platform/react';
import { breakpoints, useWindowSize } from '@edx/paragon';
@@ -13,7 +12,7 @@ import { fetchCourseBlocks } from '../../data/thunks';
import { clearRedirect } from '../posts/data';
import { selectTopics } from '../topics/data/selectors';
import { fetchCourseTopics } from '../topics/data/thunks';
import { discussionsPath } from '../utils';
import { discussionsPath, postMessageToParent } from '../utils';
import { selectAreThreadsFiltered, selectPostThreadCount } from './selectors';
import { fetchCourseConfig } from './thunks';
@@ -111,12 +110,7 @@ function getOuterHeight(element) {
*/
export function useContainerSizeForParent(refContainer) {
function postResizeMessage(height) {
window.parent.postMessage({
type: 'plugin.resize',
payload: {
height,
},
}, getConfig().LEARNING_BASE_URL);
postMessageToParent('plugin.resize', { height });
}
const location = useLocation();

View File

@@ -5,7 +5,7 @@ import { IntlProvider } from 'react-intl';
import { Context as ResponsiveContext } from 'react-responsive';
import { MemoryRouter } from 'react-router';
import { initializeMockApp } from '@edx/frontend-platform';
import { getConfig, initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { initializeStore } from '../../store';
@@ -50,13 +50,14 @@ describe('Hooks', () => {
delete window.parent;
window.parent = { ...window, postMessage: jest.fn() };
const { unmount } = renderComponent();
await waitFor(() => expect(window.parent.postMessage).toHaveBeenCalledTimes(1));
// Once for LMS and one for learning MFE
await waitFor(() => expect(window.parent.postMessage).toHaveBeenCalledTimes(2));
// Test that size is reset on unmount
unmount();
await waitFor(() => expect(window.parent.postMessage).toHaveBeenCalledTimes(2));
await waitFor(() => expect(window.parent.postMessage).toHaveBeenCalledTimes(4));
expect(window.parent.postMessage).toHaveBeenLastCalledWith(
{ type: 'plugin.resize', payload: { height: null } },
'http://localhost:2000',
getConfig().LMS_BASE_URL,
);
});
test('useContainerSizeForParent disabled', async () => {

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import {
@@ -9,15 +9,13 @@ import { PostActionsBar } from '../../components';
import { ALL_ROUTES, DiscussionProvider, Routes } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import {
useCourseDiscussionData,
useIsOnDesktop,
useRedirectToThread,
useSidebarVisible,
useCourseDiscussionData, useIsOnDesktop, useRedirectToThread, useSidebarVisible,
} from '../data/hooks';
import { selectDiscussionProvider } from '../data/selectors';
import { EmptyPosts, EmptyTopics } from '../empty-posts';
import messages from '../messages';
import { BreadcrumbMenu, LegacyBreadcrumbMenu, NavigationBar } from '../navigation';
import { postMessageToParent } from '../utils';
import DiscussionContent from './DiscussionContent';
import DiscussionSidebar from './DiscussionSidebar';
@@ -29,6 +27,7 @@ export default function DiscussionsHome() {
const {
params: { page },
} = useRouteMatch(`${Routes.COMMENTS.PAGE}?`);
const { params: { path } } = useRouteMatch(`${Routes.DISCUSSIONS.PATH}/:path*`);
const { params } = useRouteMatch(ALL_ROUTES);
const {
courseId,
@@ -42,8 +41,7 @@ export default function DiscussionsHome() {
// Display the content area if we are currently viewing/editing a post or creating one.
const displayContentArea = postId || postEditorVisible || learnerUsername;
const isSidebarVisible = useSidebarVisible();
let displaySidebar = isSidebarVisible;
let displaySidebar = useSidebarVisible();
const isOnDesktop = useIsOnDesktop();
@@ -56,6 +54,11 @@ export default function DiscussionsHome() {
const provider = useSelector(selectDiscussionProvider);
useCourseDiscussionData(courseId);
useRedirectToThread(courseId);
useEffect(() => {
if (path && path !== 'undefined') {
postMessageToParent('discussions.navigate', { path });
}
}, [path]);
return (
<DiscussionContext.Provider value={{

View File

@@ -5,7 +5,6 @@ import { useDispatch } from 'react-redux';
import { useHistory } from 'react-router';
import { useLocation } from 'react-router-dom';
import { getConfig } from '@edx/frontend-platform';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import {
Button, Icon, IconButton, SearchField,
@@ -14,7 +13,7 @@ import { Close } from '@edx/paragon/icons';
import { Routes } from '../../../data/constants';
import { DiscussionContext } from '../../common/context';
import { discussionsPath } from '../../utils';
import { discussionsPath, postMessageToParent } from '../../utils';
import { setSearchQuery, showPostEditor } from '../data';
import messages from './messages';
@@ -29,9 +28,7 @@ function PostActionsBar({
const location = useLocation();
const history = useHistory();
const handleCloseInContext = () => {
if (window.parent !== window) {
window.parent.postMessage({ type: 'learning.events.sidebar.close' }, getConfig().LEARNING_BASE_URL);
}
postMessageToParent('learning.events.sidebar.close');
};
return (
<div className="d-flex justify-content-end py-1 flex-grow-1">

View File

@@ -2,6 +2,7 @@
import { getIn } from 'formik';
import { generatePath, useRouteMatch } from 'react-router';
import { getConfig } from '@edx/frontend-platform';
import {
Delete, Edit, Flag, Pin, QuestionAnswer, VerifiedBadge,
} from '@edx/paragon/icons';
@@ -200,3 +201,26 @@ export const discussionsPath = (path, params) => {
const pathname = generatePath(path, params);
return (location) => ({ ...location, pathname });
};
/**
* Helper function to make a postMessage call
* @param {string} type message type
* @param {object} payload data to send in message
*/
export function postMessageToParent(type, payload = {}) {
if (window.parent !== window) {
const messageTargets = [
getConfig().LEARNING_BASE_URL,
getConfig().LMS_BASE_URL,
];
messageTargets.forEach(target => {
window.parent.postMessage(
{
type,
payload,
},
target,
);
});
}
}