fix: fetch topics on MFE load (#843)

This commit is contained in:
Awais Ansari
2025-12-18 18:34:27 +05:00
committed by GitHub
parent 1268442415
commit 29da3f5939
8 changed files with 33 additions and 59 deletions

View File

@@ -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();

View File

@@ -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.

View File

@@ -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`);

View File

@@ -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());

View File

@@ -1,4 +1,4 @@
import React, {
import {
useCallback, useContext, useEffect, useMemo,
} from 'react';

View File

@@ -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';

View File

@@ -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(''));

View File

@@ -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));