From 05f985acbee4062f08cf25ffa51c754cf0dae43c Mon Sep 17 00:00:00 2001 From: qasimgulzar Date: Tue, 27 Aug 2024 15:01:46 +0500 Subject: [PATCH 1/4] fix: Use Paragon Tab Component --- .../dates-tab/timeline/Timeline.jsx | 2 +- src/index.jsx | 9 + src/pages/courseware/components.jsx | 187 ++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/pages/courseware/components.jsx diff --git a/src/course-home/dates-tab/timeline/Timeline.jsx b/src/course-home/dates-tab/timeline/Timeline.jsx index 09073d6fb7..0736d1a471 100644 --- a/src/course-home/dates-tab/timeline/Timeline.jsx +++ b/src/course-home/dates-tab/timeline/Timeline.jsx @@ -20,7 +20,7 @@ const Timeline = () => { const now = new Date(); let foundNextDue = false; let foundToday = false; - courseDateBlocks.forEach(courseDateBlock => { + courseDateBlocks?.forEach(courseDateBlock => { const dateInfo = { ...courseDateBlock }; const parsedDate = new Date(dateInfo.date); diff --git a/src/index.jsx b/src/index.jsx index f390cb3106..23cf834ac8 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -12,6 +12,7 @@ import ReactDOM from 'react-dom'; import { Routes, Route } from 'react-router-dom'; import { Helmet } from 'react-helmet'; +import CoursewarePage from '@src/pages/courseware/components'; import { fetchDiscussionTab, fetchLiveTab } from './course-home/data/thunks'; import DiscussionTab from './course-home/discussion-tab/DiscussionTab'; @@ -48,6 +49,14 @@ subscribe(APP_READY, () => { + + + + )} + /> } /> } /> ((activeTab === 'outline') ? : <>), + dates: (activeTab) => ((activeTab === 'dates') ? : <>), + progress: (activeTab) => ((activeTab === 'progress') ? : <>), +}; +const CoursewarePage = ({ intl }) => { + const dispatch = useDispatch(); + const [activeTabSlug, setActiveTab] = useState('outline'); + const metadataModel = 'courseHomeMeta'; + const unitId = null; + const { courseId: courseIdFromUrl } = useParams(); + useEffect(() => { + dispatch(fetchOutlineTab(courseIdFromUrl)); + dispatch(fetchDatesTab(courseIdFromUrl)); + dispatch(fetchLiveTab(courseIdFromUrl)); + dispatch(fetchDiscussionTab(courseIdFromUrl)); + }, [courseIdFromUrl]); + const { + courseId, + courseStatus, + } = useSelector(state => state.courseHome); + const { + toastBodyLink, + toastBodyText, + toastHeader, + } = useSelector(state => state.courseHome); + + // Logistration and enrollment alerts are only really used for the outline tab, but loaded here to put them above + // breadcrumbs when they are visible. + const logistrationAlert = useLogistrationAlert(courseId); + const enrollmentAlert = useEnrollmentAlert(courseId); + + const { + number, + org, + title, + celebrations, + originalUserIsStaff, + tabs, + verifiedMode, + } = useModel('courseHomeMeta', courseIdFromUrl, courseId); + + const activeTab = tabs ? tabs[0] : {}; + + const streakLengthToCelebrate = celebrations && celebrations.streakLengthToCelebrate; + const streakDiscountCouponEnabled = celebrations && celebrations.streakDiscountEnabled && verifiedMode; + const [isStreakCelebrationOpen, , closeStreakCelebration] = useToggle(streakLengthToCelebrate); + + return ( + <> + + {['loaded', 'denied'].includes(courseStatus) && ( + <> + dispatch(setCallToActionToast({ header: '', link: null, link_text: null }))} + show={!!(toastHeader)} + > + {toastHeader} + + + + )} + +
+ {courseStatus === 'loading' && ( + + )} + + {org && ( + + )} + + {`${activeTab ? `${activeTab.title} | ` : ''}${title} | ${getConfig().SITE_NAME}`} + + {originalUserIsStaff && ( + + )} + +
+ + {(courseStatus === 'loaded' && tabs) && ( + { + if (activeKey === 'teams' || activeKey === 'instructor') { + window.location.replace(tabs.filter(t => (t.slug === activeKey))[0].url); + return; + } + if (activeKey === 'progress') { dispatch(fetchProgressTab(courseIdFromUrl)); } + setActiveTab(activeKey); + }} + > + { tabs?.map(tab => ( + + + {TabComponents[tab.slug] && TabComponents[tab.slug](activeTabSlug)} + + + ))} + + )} +
+ + {/* courseStatus 'failed' and any other unexpected course status. */} + {(!['loading', 'loaded', 'denied'].includes(courseStatus)) && ( +

+ {intl.formatMessage(messages.failure)} +

+ )} + + + ); +}; + +CoursewarePage.defaultProps = { + // unitId: null, +}; + +CoursewarePage.propTypes = { + // activeTabSlug: PropTypes.string.isRequired, + intl: intlShape.isRequired, + // courseStatus: PropTypes.string.isRequired, + // unitId: PropTypes.string, +}; + +export default injectIntl(CoursewarePage); From 8cc78180a2812901569ee70e2873199dbf2069cd Mon Sep 17 00:00:00 2001 From: qasimgulzar Date: Tue, 3 Sep 2024 17:39:51 +0500 Subject: [PATCH 2/4] fix: update the relevant routes --- .../discussion-tab/DiscussionTab.jsx | 24 ++------- src/course-home/outline-tab/OutlineTab.jsx | 2 +- src/index.jsx | 49 ++++--------------- src/pages/courseware/components.jsx | 21 +++++--- 4 files changed, 28 insertions(+), 68 deletions(-) diff --git a/src/course-home/discussion-tab/DiscussionTab.jsx b/src/course-home/discussion-tab/DiscussionTab.jsx index 06ee97cc7c..22af7d22ff 100644 --- a/src/course-home/discussion-tab/DiscussionTab.jsx +++ b/src/course-home/discussion-tab/DiscussionTab.jsx @@ -1,33 +1,17 @@ import { getConfig } from '@edx/frontend-platform'; import { injectIntl } from '@edx/frontend-platform/i18n'; -import React, { useState } from 'react'; +import { useState } from 'react'; import { useSelector } from 'react-redux'; -import { useParams, generatePath, useNavigate } from 'react-router-dom'; -import { useIFrameHeight, useIFramePluginEvents } from '../../generic/hooks'; +import { useParams } from 'react-router-dom'; const DiscussionTab = () => { const { courseId } = useSelector(state => state.courseHome); const { path } = useParams(); const [originalPath] = useState(path); - const navigate = useNavigate(); - const [, iFrameHeight] = useIFrameHeight(); - useIFramePluginEvents({ - 'discussions.navigate': (payload) => { - const basePath = generatePath('/course/:courseId/discussion', { courseId }); - navigate(`${basePath}/${payload.path}`); - }, - }); const discussionsUrl = `${getConfig().DISCUSSIONS_MFE_BASE_URL}/${courseId}/${originalPath}`; - return ( -