diff --git a/src/discussions/data/hooks.js b/src/discussions/data/hooks.js index ca3cf58b..d9f55a2a 100644 --- a/src/discussions/data/hooks.js +++ b/src/discussions/data/hooks.js @@ -4,6 +4,7 @@ import { } from 'react'; import { breakpoints, useWindowSize } from '@openedx/paragon'; +import isEmpty from 'lodash/isEmpty'; import { useDispatch, useSelector } from 'react-redux'; import { matchPath, useLocation, useMatch, useNavigate, @@ -20,10 +21,13 @@ import { ContentActions, RequestStatus, Routes } from '../../data/constants'; import { selectTopicsUnderCategory } from '../../data/selectors'; import fetchCourseBlocks from '../../data/thunks'; import DiscussionContext from '../common/context'; +import { selectTopics as selectInContextTopics } from '../in-context-topics/data/selectors'; +import fetchCourseTopicsV3 from '../in-context-topics/data/thunks'; import PostCommentsContext from '../post-comments/postCommentsContext'; import { clearRedirect } from '../posts/data'; import { threadsLoadingStatus } from '../posts/data/selectors'; import { selectTopics } from '../topics/data/selectors'; +import fetchCourseTopics from '../topics/data/thunks'; import tourCheckpoints from '../tours/constants'; import selectTours from '../tours/data/selectors'; import { updateTourShowStatus } from '../tours/data/thunks'; @@ -32,6 +36,7 @@ import { checkPermissions, discussionsPath } from '../utils'; import { ContentSelectors } from './constants'; import { selectAreThreadsFiltered, + selectDiscussionProvider, selectEnableInContext, selectIsPostingEnabled, selectIsUserLearner, @@ -104,6 +109,21 @@ export function useCourseBlockData(courseId) { }, [courseId, isEnrolled, courseStatus, isUserLearner]); } +export function useTopicsData(courseId, enableInContextSidebar) { + const dispatch = useDispatch(); + const enableInContext = useSelector(selectEnableInContext); + const provider = useSelector(selectDiscussionProvider); + const topics = useSelector(enableInContext ? selectInContextTopics : selectTopics); + + useEffect(() => { + if (isEmpty(topics) && provider) { + dispatch((enableInContext || enableInContextSidebar) + ? fetchCourseTopicsV3(courseId) + : fetchCourseTopics(courseId)); + } + }, [topics, provider, enableInContext, enableInContextSidebar]); +} + export function useRedirectToThread(courseId, enableInContextSidebar) { const dispatch = useDispatch(); const navigate = useNavigate(); diff --git a/src/discussions/discussions-home/DiscussionsHome.jsx b/src/discussions/discussions-home/DiscussionsHome.jsx index d09c3548..bef5b368 100644 --- a/src/discussions/discussions-home/DiscussionsHome.jsx +++ b/src/discussions/discussions-home/DiscussionsHome.jsx @@ -16,7 +16,7 @@ import { ALL_ROUTES, DiscussionProvider, Routes as ROUTES } from '../../data/con import DiscussionContext from '../common/context'; import ContentUnavailable from '../content-unavailable/ContentUnavailable'; import { - useCourseBlockData, useCourseDiscussionData, useIsOnTablet, useRedirectToThread, useSidebarVisible, + useCourseBlockData, useCourseDiscussionData, useIsOnTablet, useRedirectToThread, useSidebarVisible, useTopicsData, } from '../data/hooks'; import { selectDiscussionProvider, selectEnableInContext, selectIsUserLearner } from '../data/selectors'; import { EmptyLearners, EmptyTopics } from '../empty-posts'; @@ -62,6 +62,7 @@ const DiscussionsHome = () => { useCourseDiscussionData(courseId); useRedirectToThread(courseId, enableInContextSidebar); useCourseBlockData(courseId); + useTopicsData(courseId, enableInContextSidebar); useFeedbackWrapper(); /* Display the content area if we are currently viewing/editing a post or creating one. If the window is larger than a particular size, show the sidebar for navigating between posts/topics. diff --git a/src/discussions/discussions-home/DiscussionsHome.test.jsx b/src/discussions/discussions-home/DiscussionsHome.test.jsx index 6a5cb0f6..d195fcb7 100644 --- a/src/discussions/discussions-home/DiscussionsHome.test.jsx +++ b/src/discussions/discussions-home/DiscussionsHome.test.jsx @@ -27,10 +27,10 @@ import { fetchThreads } from '../posts/data/thunks'; import fetchCourseTopics from '../topics/data/thunks'; import DiscussionsHome from './DiscussionsHome'; -import '../posts/data/__factories__/threads.factory'; -import '../in-context-topics/data/__factories__/inContextTopics.factory'; -import '../topics/data/__factories__/topics.factory'; import '../../components/NavigationBar/data/__factories__/navigationBar.factory'; +import '../in-context-topics/data/__factories__/inContextTopics.factory'; +import '../posts/data/__factories__/threads.factory'; +import '../topics/data/__factories__/topics.factory'; const courseConfigApiUrl = getCourseConfigApiUrl(); let axiosMock; @@ -224,7 +224,7 @@ describe('DiscussionsHome', () => { it('should display post editor form when click on add a post button in legacy topics view', async () => { axiosMock.onGet(getDiscussionsConfigUrl(courseId)).reply(200, { - enable_in_context: false, hasModerationPrivileges: true, isEmailVerified: true, + enable_in_context: false, hasModerationPrivileges: true, isEmailVerified: true, provider: 'legacy', }); await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState); await renderComponent(`/${courseId}/topics`); diff --git a/src/discussions/in-context-topics/TopicsView.jsx b/src/discussions/in-context-topics/TopicsView.jsx index e4c02ea9..a5c84806 100644 --- a/src/discussions/in-context-topics/TopicsView.jsx +++ b/src/discussions/in-context-topics/TopicsView.jsx @@ -1,6 +1,4 @@ -import React, { - useCallback, useContext, useEffect, useMemo, -} from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { Spinner } from '@openedx/paragon'; import classNames from 'classnames'; @@ -9,8 +7,7 @@ import { useDispatch, useSelector } from 'react-redux'; import SearchInfo from '../../components/SearchInfo'; import { RequestStatus } from '../../data/constants'; -import DiscussionContext from '../common/context'; -import { selectAreThreadsFiltered, selectDiscussionProvider } from '../data/selectors'; +import { selectAreThreadsFiltered } from '../data/selectors'; import { clearFilter, clearSort } from '../posts/data/slices'; import NoResults from '../posts/NoResults'; import { handleKeyDown } from '../utils'; @@ -19,7 +16,6 @@ import { selectNonCoursewareTopics, selectTopicFilter, selectTopics, } from './data/selectors'; import { setFilter } from './data/slices'; -import fetchCourseTopicsV3 from './data/thunks'; import { ArchivedBaseGroup, SectionBaseGroup, Topic } from './topic'; const TopicsList = () => { @@ -71,20 +67,12 @@ const TopicsList = () => { const TopicsView = () => { const dispatch = useDispatch(); - const { courseId } = useContext(DiscussionContext); - const provider = useSelector(selectDiscussionProvider); const topicFilter = useSelector(selectTopicFilter); const filteredTopics = useSelector(selectFilteredTopics); const loadingStatus = useSelector(selectLoadingStatus); const isPostsFiltered = useSelector(selectAreThreadsFiltered); const topics = useSelector(selectTopics); - useEffect(() => { - if (provider) { - dispatch(fetchCourseTopicsV3(courseId)); - } - }, [provider]); - useEffect(() => { if (isPostsFiltered) { dispatch(clearFilter()); diff --git a/src/discussions/learners/LearnerPostsView.jsx b/src/discussions/learners/LearnerPostsView.jsx index 9122b457..28c87510 100644 --- a/src/discussions/learners/LearnerPostsView.jsx +++ b/src/discussions/learners/LearnerPostsView.jsx @@ -1,4 +1,4 @@ -import React, { +import { useCallback, useContext, useEffect, useMemo, } from 'react'; diff --git a/src/discussions/learners/LearnersView.jsx b/src/discussions/learners/LearnersView.jsx index f80e5221..d5b2718f 100644 --- a/src/discussions/learners/LearnersView.jsx +++ b/src/discussions/learners/LearnersView.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { Button, Spinner } from '@openedx/paragon'; import { useDispatch, useSelector } from 'react-redux'; diff --git a/src/discussions/posts/PostsView.jsx b/src/discussions/posts/PostsView.jsx index b2fa7d20..74dade51 100644 --- a/src/discussions/posts/PostsView.jsx +++ b/src/discussions/posts/PostsView.jsx @@ -1,19 +1,11 @@ -import React, { - useCallback, useContext, useEffect, useMemo, -} from 'react'; +import React, { useCallback, useContext, useMemo } from 'react'; import PropTypes from 'prop-types'; -import isEmpty from 'lodash/isEmpty'; import { useDispatch, useSelector } from 'react-redux'; import SearchInfo from '../../components/SearchInfo'; import { selectCurrentCategoryGrouping, selectTopicsUnderCategory } from '../../data/selectors'; import DiscussionContext from '../common/context'; -import { selectEnableInContext } from '../data/selectors'; -import { selectTopics as selectInContextTopics } from '../in-context-topics/data/selectors'; -import fetchCourseTopicsV3 from '../in-context-topics/data/thunks'; -import { selectTopics } from '../topics/data/selectors'; -import fetchCourseTopics from '../topics/data/thunks'; import { handleKeyDown } from '../utils'; import { selectAllThreadsIds, selectTopicThreadsIds } from './data/selectors'; import { setSearchQuery } from './data/slices'; @@ -51,27 +43,12 @@ CategoryPostsList.propTypes = { }; const PostsView = () => { - const { - topicId, - category, - courseId, - enableInContextSidebar, - } = useContext(DiscussionContext); + const { topicId, category } = useContext(DiscussionContext); const dispatch = useDispatch(); - const enableInContext = useSelector(selectEnableInContext); const searchString = useSelector(({ threads }) => threads.filters.search); const resultsFound = useSelector(({ threads }) => threads.totalThreads); const textSearchRewrite = useSelector(({ threads }) => threads.textSearchRewrite); const loadingStatus = useSelector(({ threads }) => threads.status); - const topics = useSelector(enableInContext ? selectInContextTopics : selectTopics); - - useEffect(() => { - if (isEmpty(topics)) { - dispatch((enableInContext || enableInContextSidebar) - ? fetchCourseTopicsV3(courseId) - : fetchCourseTopics(courseId)); - } - }, [topics]); const handleOnClear = useCallback(() => { dispatch(setSearchQuery('')); diff --git a/src/discussions/topics/TopicsView.jsx b/src/discussions/topics/TopicsView.jsx index 5ea4622d..bb111dd9 100644 --- a/src/discussions/topics/TopicsView.jsx +++ b/src/discussions/topics/TopicsView.jsx @@ -1,19 +1,15 @@ -import React, { - useCallback, useContext, useEffect, useMemo, -} from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useParams } from 'react-router-dom'; import SearchInfo from '../../components/SearchInfo'; import { RequestStatus } from '../../data/constants'; -import DiscussionContext from '../common/context'; import { selectDiscussionProvider } from '../data/selectors'; import NoResults from '../posts/NoResults'; import { handleKeyDown } from '../utils'; import { selectCategories, selectNonCoursewareTopics, selectTopicFilter } from './data/selectors'; import { setFilter, setTopicsCount } from './data/slices'; -import fetchCourseTopics from './data/thunks'; import LegacyTopicGroup from './topic-group/LegacyTopicGroup'; import Topic from './topic-group/topic/Topic'; import countFilteredTopics from './utils'; @@ -64,19 +60,11 @@ const TopicsView = () => { const topicsSelector = useSelector(({ topics }) => topics); const filteredTopicsCount = useSelector(({ topics }) => topics.results.count); const loadingStatus = useSelector(({ topics }) => topics.status); - const { courseId } = useContext(DiscussionContext); const handleOnClear = useCallback(() => { dispatch(setFilter('')); }, []); - useEffect(() => { - // Don't load till the provider information is available - if (provider) { - dispatch(fetchCourseTopics(courseId)); - } - }, [provider]); - useEffect(() => { const count = countFilteredTopics(topicsSelector, provider); dispatch(setTopicsCount(count));