From b36c0266fdcb21f85b6b5ec8c8dbac93a8f22cde Mon Sep 17 00:00:00 2001 From: Kshitij Sobti Date: Wed, 6 Dec 2023 17:50:28 +0530 Subject: [PATCH] fix: null error at useRouteMatch when running on tutor (#613) tutor sets the PUBLIC_PATH to '/discussions' which causes frontend-platform to treat all URLs for matching etc to be relative to this path. Since many places include '/discussions' in the match it causes those matches to break. This change makes the default PUBLIC_PATH in .env.development to match the one set by tutor and removes it from the base path of the router letting frontend platform handle the prefix. This also allows for deployments to customise this path to be something other than 'discussions'. --- src/data/constants.js | 5 ++++- .../post-comments/PostCommentsView.test.jsx | 14 ++++++++++++++ .../posts/data/__factories__/threads.factory.js | 1 + src/discussions/posts/post/Post.jsx | 7 +++---- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/data/constants.js b/src/data/constants.js index d0c7960c..dc786b43 100644 --- a/src/data/constants.js +++ b/src/data/constants.js @@ -1,6 +1,9 @@ import { getConfig } from '@edx/frontend-platform'; export const getApiBaseUrl = () => getConfig().LMS_BASE_URL; +export const getFullUrl = (path) => ( + new URL(`${getConfig().PUBLIC_PATH.replace(/\/$/, '')}/${path}`, window.location.origin).href +); /** * Enum for thread types. @@ -137,7 +140,7 @@ export const DiscussionProvider = { OPEN_EDX: 'openedx', }; -const BASE_PATH = `${getConfig().PUBLIC_PATH}:courseId`; +const BASE_PATH = '/:courseId'; export const Routes = { DISCUSSIONS: { diff --git a/src/discussions/post-comments/PostCommentsView.test.jsx b/src/discussions/post-comments/PostCommentsView.test.jsx index cda49291..07540f4a 100644 --- a/src/discussions/post-comments/PostCommentsView.test.jsx +++ b/src/discussions/post-comments/PostCommentsView.test.jsx @@ -442,6 +442,20 @@ describe('ThreadView', () => { assertLastUpdateData({ pinned: false }); }); + it('should allow copying a link to the post', async () => { + await waitFor(() => renderComponent(discussionPostId)); + const post = await screen.findByTestId('post-thread-1'); + const hoverCard = within(post).getByTestId('hover-card-thread-1'); + Object.assign(navigator, { clipboard: { writeText: jest.fn() } }); + await act(async () => { + fireEvent.click(within(hoverCard).getByRole('button', { name: /actions menu/i })); + }); + await act(async () => { + fireEvent.click(within(hoverCard).getByRole('button', { name: /copy link/i })); + }); + expect(navigator.clipboard.writeText).toHaveBeenCalledWith(`http://localhost/${courseId}/posts/${discussionPostId}`); + }); + it('should allow reporting the post', async () => { await waitFor(() => renderComponent(discussionPostId)); const post = await screen.findByTestId('post-thread-1'); diff --git a/src/discussions/posts/data/__factories__/threads.factory.js b/src/discussions/posts/data/__factories__/threads.factory.js index fbd9aab3..b072860c 100644 --- a/src/discussions/posts/data/__factories__/threads.factory.js +++ b/src/discussions/posts/data/__factories__/threads.factory.js @@ -26,6 +26,7 @@ Factory.define('thread') 'type', 'voted', 'pinned', + 'copy_link', ], author: 'test_user', author_label: 'Staff', diff --git a/src/discussions/posts/post/Post.jsx b/src/discussions/posts/post/Post.jsx index 7ec90218..721397bb 100644 --- a/src/discussions/posts/post/Post.jsx +++ b/src/discussions/posts/post/Post.jsx @@ -11,7 +11,7 @@ import { useIntl } from '@edx/frontend-platform/i18n'; import { Hyperlink, useToggle } from '@edx/paragon'; import HTMLLoader from '../../../components/HTMLLoader'; -import { ContentActions } from '../../../data/constants'; +import { ContentActions, getFullUrl } from '../../../data/constants'; import { selectorForUnitSubsection, selectTopicContext } from '../../../data/selectors'; import { AlertBanner, Confirmation } from '../../common'; import { DiscussionContext } from '../../common/context'; @@ -37,7 +37,7 @@ const Post = ({ handleAddResponseButton }) => { const location = useLocation(); const history = useHistory(); const dispatch = useDispatch(); - const courseId = useSelector((state) => state.config.id); + const { courseId } = useContext(DiscussionContext); const topic = useSelector(selectTopic(topicId)); const getTopicSubsection = useSelector(selectorForUnitSubsection); const topicContext = useSelector(selectTopicContext(topicId)); @@ -75,8 +75,7 @@ const Post = ({ handleAddResponseButton }) => { }, [closed, postId, showClosePostModal]); const handlePostCopyLink = useCallback(() => { - const postURL = new URL(`${getConfig().PUBLIC_PATH}${courseId}/posts/${postId}`, window.location.origin); - navigator.clipboard.writeText(postURL.href); + navigator.clipboard.writeText(getFullUrl(`${courseId}/posts/${postId}`)); }, [window.location.origin, postId, courseId]); const handlePostPin = useCallback(() => dispatch(