Skip to content

Commit

Permalink
feat: upgrade react router to v6 (openedx#519)
Browse files Browse the repository at this point in the history
[React Router Upgrade to v6](openedx/platform-roadmap#276).

This PR upgrades React Router from `v5` to `v6`.
  • Loading branch information
Syed-Ali-Abbas-Zaidi authored and bra-i-am committed Apr 30, 2024
1 parent 4592c0d commit 84b8f12
Show file tree
Hide file tree
Showing 35 changed files with 9,125 additions and 8,375 deletions.
16,795 changes: 8,787 additions & 8,008 deletions package-lock.json

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@
"@edx/brand": "npm:@edx/brand-openedx@1.1.0",
"@edx/frontend-component-footer": "^12.3.0",
"@edx/frontend-component-header": "^4.7.0",
"@edx/frontend-enterprise-hotjar": "^1.2.1",
"@edx/frontend-lib-content-components": "^1.174.0",
"@edx/frontend-platform": "4.2.0",
"@edx/frontend-enterprise-hotjar": "^2.0.0",
"@edx/frontend-lib-content-components": "1.175.0",
"@edx/frontend-platform": "5.6.1",
"@edx/paragon": "^20.45.4",
"@fortawesome/fontawesome-svg-core": "1.2.28",
"@fortawesome/free-brands-svg-icons": "5.11.2",
"@fortawesome/free-regular-svg-icons": "5.11.2",
"@fortawesome/free-solid-svg-icons": "5.11.2",
"@fortawesome/react-fontawesome": "0.1.9",
"@reduxjs/toolkit": "1.5.0",
"@tanstack/react-query": "4.36.1",
"classnames": "2.2.6",
"core-js": "3.8.1",
"email-validator": "2.0.4",
Expand All @@ -60,10 +61,10 @@
"react-datepicker": "^4.13.0",
"react-dom": "16.14.0",
"react-helmet": "^6.1.0",
"react-redux": "7.1.3",
"react-responsive": "8.1.0",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-redux": "7.2.9",
"react-responsive": "9.0.2",
"react-router": "6.16.0",
"react-router-dom": "6.16.0",
"react-textarea-autosize": "^8.4.1",
"react-transition-group": "4.4.1",
"redux": "4.0.5",
Expand Down
149 changes: 71 additions & 78 deletions src/CourseAuthoringRoutes.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Switch, useRouteMatch } from 'react-router';
import { PageRoute } from '@edx/frontend-platform/react';
import { Routes, Route, useParams } from 'react-router-dom';
import { PageWrap } from '@edx/frontend-platform/react';
import Placeholder from '@edx/frontend-lib-content-components';
import CourseAuthoringPage from './CourseAuthoringPage';
import { PagesAndResources } from './pages-and-resources';
Expand Down Expand Up @@ -34,85 +33,79 @@ import CourseImportPage from './import-page/CourseImportPage';
* can move the Header/Footer rendering to this component and likely pull the course detail loading
* in as well, and it'd feel a bit better-factored and the roles would feel more clear.
*/
const CourseAuthoringRoutes = ({ courseId }) => {
const { path } = useRouteMatch();
const CourseAuthoringRoutes = () => {
const { courseId } = useParams();

return (
<CourseAuthoringPage courseId={courseId}>
<Switch>
<PageRoute path={`${path}/outline`}>
{process.env.ENABLE_NEW_COURSE_OUTLINE_PAGE === 'true'
&& (
<Placeholder />
)}
</PageRoute>
<PageRoute path={`${path}/course_info`}>
<CourseUpdates courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/assets`}>
<FilesAndUploads courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/videos`}>
{process.env.ENABLE_NEW_VIDEO_UPLOAD_PAGE === 'true'
&& (
<Placeholder />
)}
</PageRoute>
<PageRoute path={`${path}/pages-and-resources`}>
<PagesAndResources courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/proctored-exam-settings`}>
<ProctoredExamSettings courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/custom-pages`}>
<CustomPages courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/container/:blockId`}>
{process.env.ENABLE_UNIT_PAGE === 'true'
&& (
<Placeholder />
)}
</PageRoute>
<PageRoute path={`${path}/editor/course-videos/:blockId`}>
{process.env.ENABLE_NEW_EDITOR_PAGES === 'true'
&& (
<VideoSelectorContainer
courseId={courseId}
/>
)}
</PageRoute>
<PageRoute path={`${path}/editor/:blockType/:blockId?`}>
{process.env.ENABLE_NEW_EDITOR_PAGES === 'true'
&& (
<EditorContainer
courseId={courseId}
/>
)}
</PageRoute>
<PageRoute path={`${path}/settings/details`}>
<ScheduleAndDetails courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/settings/grading`}>
<GradingSettings courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/course_team`}>
<CourseTeam courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/settings/advanced`}>
<AdvancedSettings courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/import`}>
<CourseImportPage courseId={courseId} />
</PageRoute>
<PageRoute path={`${path}/export`}>
<CourseExportPage courseId={courseId} />
</PageRoute>
</Switch>
<Routes>
<Route
path="outline"
element={process.env.ENABLE_NEW_COURSE_OUTLINE_PAGE === 'true' ? <PageWrap><Placeholder /></PageWrap> : null}
/>
<Route
path="course_info"
element={<PageWrap><CourseUpdates courseId={courseId} /></PageWrap>}
/>
<Route
path="assets"
element={<PageWrap><FilesAndUploads courseId={courseId} /></PageWrap>}
/>
<Route
path="videos"
element={process.env.ENABLE_NEW_VIDEO_UPLOAD_PAGE === 'true' ? <PageWrap><Placeholder /></PageWrap> : null}
/>
<Route
path="pages-and-resources/*"
element={<PageWrap><PagesAndResources courseId={courseId} /></PageWrap>}
/>
<Route
path="proctored-exam-settings"
element={<PageWrap><ProctoredExamSettings courseId={courseId} /></PageWrap>}
/>
<Route
path="custom-pages/*"
element={<PageWrap><CustomPages courseId={courseId} /></PageWrap>}
/>
<Route
path="/container/:blockId"
element={process.env.ENABLE_UNIT_PAGE === 'true' ? <PageWrap><Placeholder /></PageWrap> : null}
/>
<Route
path="editor/course-videos/:blockId"
element={process.env.ENABLE_NEW_EDITOR_PAGES === 'true' ? <PageWrap><VideoSelectorContainer courseId={courseId} /></PageWrap> : null}
/>
<Route
path="editor/:blockType/:blockId?"
element={process.env.ENABLE_NEW_EDITOR_PAGES === 'true' ? <PageWrap><EditorContainer courseId={courseId} /></PageWrap> : null}
/>
<Route
path="settings/details"
element={<PageWrap><ScheduleAndDetails courseId={courseId} /></PageWrap>}
/>
<Route
path="settings/grading"
element={<PageWrap><GradingSettings courseId={courseId} /></PageWrap>}
/>
<Route
path="course_team"
element={<PageWrap><CourseTeam courseId={courseId} /></PageWrap>}
/>
<Route
path="settings/advanced"
element={<PageWrap><AdvancedSettings courseId={courseId} /></PageWrap>}
/>
<Route
path="import"
element={<PageWrap><CourseImportPage courseId={courseId} /></PageWrap>}
/>
<Route
path="export"
element={<PageWrap><CourseExportPage courseId={courseId} /></PageWrap>}
/>
</Routes>
</CourseAuthoringPage>
);
};

CourseAuthoringRoutes.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default CourseAuthoringRoutes;
37 changes: 19 additions & 18 deletions src/CourseAuthoringRoutes.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ const customPagesMockText = 'Custom Pages';
let store;
const mockComponentFn = jest.fn();

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useParams: () => ({
courseId,
}),
}));

// Mock the TinyMceWidget from frontend-lib-content-components
jest.mock('@edx/frontend-lib-content-components', () => ({
TinyMceWidget: () => <div>Widget</div>,
Expand All @@ -25,12 +32,6 @@ jest.mock('@edx/frontend-lib-content-components', () => ({
})),
}));

jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
useRouteMatch: () => ({
path: `/course/${courseId}`,
}),
}));
jest.mock('./pages-and-resources/PagesAndResources', () => (props) => {
mockComponentFn(props);
return pagesAndResourcesMockText;
Expand Down Expand Up @@ -67,9 +68,9 @@ describe('<CourseAuthoringRoutes>', () => {

fit('renders the PagesAndResources component when the pages and resources route is active', () => {
render(
<AppProvider store={store}>
<MemoryRouter initialEntries={[`/course/${courseId}/pages-and-resources`]}>
<CourseAuthoringRoutes courseId={courseId} />
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/pages-and-resources']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
Expand All @@ -85,9 +86,9 @@ describe('<CourseAuthoringRoutes>', () => {

it('renders the ProctoredExamSettings component when the proctored exam settings route is active', () => {
render(
<AppProvider store={store}>
<MemoryRouter initialEntries={[`/course/${courseId}/proctored-exam-settings`]}>
<CourseAuthoringRoutes courseId={courseId} />
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/proctored-exam-settings']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
Expand All @@ -103,9 +104,9 @@ describe('<CourseAuthoringRoutes>', () => {

it('renders the EditorContainer component when the course editor route is active', () => {
render(
<AppProvider store={store}>
<MemoryRouter initialEntries={[`/course/${courseId}/editor/video/block-id`]}>
<CourseAuthoringRoutes courseId={courseId} />
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/editor/video/block-id']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
Expand All @@ -121,9 +122,9 @@ describe('<CourseAuthoringRoutes>', () => {

it('renders the VideoSelectorContainer component when the course videos route is active', () => {
render(
<AppProvider store={store}>
<MemoryRouter initialEntries={[`/course/${courseId}/editor/course-videos/block-id`]}>
<CourseAuthoringRoutes courseId={courseId} />
<AppProvider store={store} wrapWithRouter={false}>
<MemoryRouter initialEntries={['/editor/course-videos/block-id']}>
<CourseAuthoringRoutes />
</MemoryRouter>
</AppProvider>,
);
Expand Down
6 changes: 3 additions & 3 deletions src/course-rerun/CourseRerun.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { useSelector } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
import { history, initializeMockApp } from '@edx/frontend-platform';
import { initializeMockApp } from '@edx/frontend-platform';
import { IntlProvider, injectIntl } from '@edx/frontend-platform/i18n';
import { AppProvider } from '@edx/frontend-platform/react';
import {
Expand Down Expand Up @@ -35,7 +35,7 @@ jest.mock('react-router-dom', () => ({

const RootWrapper = () => (
<MemoryRouter>
<AppProvider store={store}>
<AppProvider store={store} wrapWithRouter={false}>
<IntlProvider locale="en">
<CourseRerun intl={injectIntl} />
</IntlProvider>
Expand Down Expand Up @@ -71,7 +71,7 @@ describe('<CourseRerun />', () => {

fireEvent.click(cancelButton);
waitFor(() => {
expect(history.location.pathname).toBe('/home');
expect(window.location.pathname).toBe('/home');
});
});

Expand Down
5 changes: 3 additions & 2 deletions src/course-rerun/hooks.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { history } from '@edx/frontend-platform';
import { useIntl } from '@edx/frontend-platform/i18n';
import { useNavigate } from 'react-router-dom';

import { RequestStatus } from '../data/constants';
import { updateSavingStatus } from '../generic/data/slice';
Expand All @@ -17,6 +17,7 @@ import { fetchStudioHomeData } from '../studio-home/data/thunks';
const useCourseRerun = (courseId) => {
const intl = useIntl();
const dispatch = useDispatch();
const navigate = useNavigate();
const savingStatus = useSelector(getSavingStatus);
const courseData = useSelector(getCourseData);
const courseRerunData = useSelector(getCourseRerunData);
Expand Down Expand Up @@ -47,7 +48,7 @@ const useCourseRerun = (courseId) => {
dispatch(updateSavingStatus({ status: '' }));
const { url } = redirectUrlObj;
if (url) {
history.push('/home');
navigate('/home');
}
}
}, [savingStatus]);
Expand Down
13 changes: 5 additions & 8 deletions src/course-rerun/index.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import React from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import {
Container,
Layout,
Stack,
ActionRow,
Button,
} from '@edx/paragon';
import { history } from '@edx/frontend-platform';
import { StudioFooter } from '@edx/frontend-component-footer';
import { useNavigate, useParams } from 'react-router-dom';

import Header from '../header';
import Loading from '../generic/Loading';
Expand All @@ -21,7 +20,9 @@ import CourseRerunSideBar from './course-rerun-sidebar';
import messages from './messages';
import { useCourseRerun } from './hooks';

const CourseRerun = ({ courseId }) => {
const CourseRerun = () => {
const { courseId } = useParams();
const navigate = useNavigate();
const {
intl,
displayName,
Expand All @@ -36,7 +37,7 @@ const CourseRerun = ({ courseId }) => {
}

const handleRerunCourseCancel = () => {
history.push('/home');
navigate('/home');
};

return (
Expand Down Expand Up @@ -92,8 +93,4 @@ const CourseRerun = ({ courseId }) => {
);
};

CourseRerun.propTypes = {
courseId: PropTypes.string.isRequired,
};

export default CourseRerun;

0 comments on commit 84b8f12

Please sign in to comment.