Compare commits
4 Commits
dependabot
...
aansari/is
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e216d847eb | ||
|
|
911b8b3fc5 | ||
|
|
4917da3245 | ||
|
|
e5388690b2 |
10
package-lock.json
generated
10
package-lock.json
generated
@@ -19,7 +19,7 @@
|
|||||||
"@tinymce/tinymce-react": "5.1.1",
|
"@tinymce/tinymce-react": "5.1.1",
|
||||||
"babel-polyfill": "6.26.0",
|
"babel-polyfill": "6.26.0",
|
||||||
"classnames": "2.5.1",
|
"classnames": "2.5.1",
|
||||||
"core-js": "3.21.1",
|
"core-js": "3.47.0",
|
||||||
"dompurify": "^2.4.3",
|
"dompurify": "^2.4.3",
|
||||||
"formik": "2.4.9",
|
"formik": "2.4.9",
|
||||||
"lodash.snakecase": "4.1.1",
|
"lodash.snakecase": "4.1.1",
|
||||||
@@ -10222,11 +10222,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.21.1",
|
"version": "3.47.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.21.1.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz",
|
||||||
"integrity": "sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig==",
|
"integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==",
|
||||||
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/core-js"
|
"url": "https://opencollective.com/core-js"
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
"@tinymce/tinymce-react": "5.1.1",
|
"@tinymce/tinymce-react": "5.1.1",
|
||||||
"babel-polyfill": "6.26.0",
|
"babel-polyfill": "6.26.0",
|
||||||
"classnames": "2.5.1",
|
"classnames": "2.5.1",
|
||||||
"core-js": "3.21.1",
|
"core-js": "3.47.0",
|
||||||
"dompurify": "^2.4.3",
|
"dompurify": "^2.4.3",
|
||||||
"formik": "2.4.9",
|
"formik": "2.4.9",
|
||||||
"lodash.snakecase": "4.1.1",
|
"lodash.snakecase": "4.1.1",
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ const FilterBar = ({
|
|||||||
<ActionItem
|
<ActionItem
|
||||||
key={toString(cohort.id)}
|
key={toString(cohort.id)}
|
||||||
id={toString(cohort.id)}
|
id={toString(cohort.id)}
|
||||||
label={capitalize(cohort.name)}
|
label={cohort.name}
|
||||||
value={toString(cohort.id)}
|
value={toString(cohort.id)}
|
||||||
selected={selectedFilters.cohort}
|
selected={selectedFilters.cohort}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
import { breakpoints, useWindowSize } from '@openedx/paragon';
|
import { breakpoints, useWindowSize } from '@openedx/paragon';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
matchPath, useLocation, useMatch, useNavigate,
|
matchPath, useLocation, useMatch, useNavigate,
|
||||||
@@ -20,10 +21,13 @@ import { ContentActions, RequestStatus, Routes } from '../../data/constants';
|
|||||||
import { selectTopicsUnderCategory } from '../../data/selectors';
|
import { selectTopicsUnderCategory } from '../../data/selectors';
|
||||||
import fetchCourseBlocks from '../../data/thunks';
|
import fetchCourseBlocks from '../../data/thunks';
|
||||||
import DiscussionContext from '../common/context';
|
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 PostCommentsContext from '../post-comments/postCommentsContext';
|
||||||
import { clearRedirect } from '../posts/data';
|
import { clearRedirect } from '../posts/data';
|
||||||
import { threadsLoadingStatus } from '../posts/data/selectors';
|
import { threadsLoadingStatus } from '../posts/data/selectors';
|
||||||
import { selectTopics } from '../topics/data/selectors';
|
import { selectTopics } from '../topics/data/selectors';
|
||||||
|
import fetchCourseTopics from '../topics/data/thunks';
|
||||||
import tourCheckpoints from '../tours/constants';
|
import tourCheckpoints from '../tours/constants';
|
||||||
import selectTours from '../tours/data/selectors';
|
import selectTours from '../tours/data/selectors';
|
||||||
import { updateTourShowStatus } from '../tours/data/thunks';
|
import { updateTourShowStatus } from '../tours/data/thunks';
|
||||||
@@ -32,6 +36,7 @@ import { checkPermissions, discussionsPath } from '../utils';
|
|||||||
import { ContentSelectors } from './constants';
|
import { ContentSelectors } from './constants';
|
||||||
import {
|
import {
|
||||||
selectAreThreadsFiltered,
|
selectAreThreadsFiltered,
|
||||||
|
selectDiscussionProvider,
|
||||||
selectEnableInContext,
|
selectEnableInContext,
|
||||||
selectIsPostingEnabled,
|
selectIsPostingEnabled,
|
||||||
selectIsUserLearner,
|
selectIsUserLearner,
|
||||||
@@ -104,6 +109,21 @@ export function useCourseBlockData(courseId) {
|
|||||||
}, [courseId, isEnrolled, courseStatus, isUserLearner]);
|
}, [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) {
|
export function useRedirectToThread(courseId, enableInContextSidebar) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { ALL_ROUTES, DiscussionProvider, Routes as ROUTES } from '../../data/con
|
|||||||
import DiscussionContext from '../common/context';
|
import DiscussionContext from '../common/context';
|
||||||
import ContentUnavailable from '../content-unavailable/ContentUnavailable';
|
import ContentUnavailable from '../content-unavailable/ContentUnavailable';
|
||||||
import {
|
import {
|
||||||
useCourseBlockData, useCourseDiscussionData, useIsOnTablet, useRedirectToThread, useSidebarVisible,
|
useCourseBlockData, useCourseDiscussionData, useIsOnTablet, useRedirectToThread, useSidebarVisible, useTopicsData,
|
||||||
} from '../data/hooks';
|
} from '../data/hooks';
|
||||||
import { selectDiscussionProvider, selectEnableInContext, selectIsUserLearner } from '../data/selectors';
|
import { selectDiscussionProvider, selectEnableInContext, selectIsUserLearner } from '../data/selectors';
|
||||||
import { EmptyLearners, EmptyTopics } from '../empty-posts';
|
import { EmptyLearners, EmptyTopics } from '../empty-posts';
|
||||||
@@ -62,6 +62,7 @@ const DiscussionsHome = () => {
|
|||||||
useCourseDiscussionData(courseId);
|
useCourseDiscussionData(courseId);
|
||||||
useRedirectToThread(courseId, enableInContextSidebar);
|
useRedirectToThread(courseId, enableInContextSidebar);
|
||||||
useCourseBlockData(courseId);
|
useCourseBlockData(courseId);
|
||||||
|
useTopicsData(courseId, enableInContextSidebar);
|
||||||
useFeedbackWrapper();
|
useFeedbackWrapper();
|
||||||
/* Display the content area if we are currently viewing/editing a post or creating one.
|
/* 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.
|
If the window is larger than a particular size, show the sidebar for navigating between posts/topics.
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ import { fetchThreads } from '../posts/data/thunks';
|
|||||||
import fetchCourseTopics from '../topics/data/thunks';
|
import fetchCourseTopics from '../topics/data/thunks';
|
||||||
import DiscussionsHome from './DiscussionsHome';
|
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 '../../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();
|
const courseConfigApiUrl = getCourseConfigApiUrl();
|
||||||
let axiosMock;
|
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 () => {
|
it('should display post editor form when click on add a post button in legacy topics view', async () => {
|
||||||
axiosMock.onGet(getDiscussionsConfigUrl(courseId)).reply(200, {
|
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 executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState);
|
||||||
await renderComponent(`/${courseId}/topics`);
|
await renderComponent(`/${courseId}/topics`);
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import React, {
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
useCallback, useContext, useEffect, useMemo,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
import { Spinner } from '@openedx/paragon';
|
import { Spinner } from '@openedx/paragon';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
@@ -9,8 +7,7 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||||||
|
|
||||||
import SearchInfo from '../../components/SearchInfo';
|
import SearchInfo from '../../components/SearchInfo';
|
||||||
import { RequestStatus } from '../../data/constants';
|
import { RequestStatus } from '../../data/constants';
|
||||||
import DiscussionContext from '../common/context';
|
import { selectAreThreadsFiltered } from '../data/selectors';
|
||||||
import { selectAreThreadsFiltered, selectDiscussionProvider } from '../data/selectors';
|
|
||||||
import { clearFilter, clearSort } from '../posts/data/slices';
|
import { clearFilter, clearSort } from '../posts/data/slices';
|
||||||
import NoResults from '../posts/NoResults';
|
import NoResults from '../posts/NoResults';
|
||||||
import { handleKeyDown } from '../utils';
|
import { handleKeyDown } from '../utils';
|
||||||
@@ -19,7 +16,6 @@ import {
|
|||||||
selectNonCoursewareTopics, selectTopicFilter, selectTopics,
|
selectNonCoursewareTopics, selectTopicFilter, selectTopics,
|
||||||
} from './data/selectors';
|
} from './data/selectors';
|
||||||
import { setFilter } from './data/slices';
|
import { setFilter } from './data/slices';
|
||||||
import fetchCourseTopicsV3 from './data/thunks';
|
|
||||||
import { ArchivedBaseGroup, SectionBaseGroup, Topic } from './topic';
|
import { ArchivedBaseGroup, SectionBaseGroup, Topic } from './topic';
|
||||||
|
|
||||||
const TopicsList = () => {
|
const TopicsList = () => {
|
||||||
@@ -71,20 +67,12 @@ const TopicsList = () => {
|
|||||||
|
|
||||||
const TopicsView = () => {
|
const TopicsView = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { courseId } = useContext(DiscussionContext);
|
|
||||||
const provider = useSelector(selectDiscussionProvider);
|
|
||||||
const topicFilter = useSelector(selectTopicFilter);
|
const topicFilter = useSelector(selectTopicFilter);
|
||||||
const filteredTopics = useSelector(selectFilteredTopics);
|
const filteredTopics = useSelector(selectFilteredTopics);
|
||||||
const loadingStatus = useSelector(selectLoadingStatus);
|
const loadingStatus = useSelector(selectLoadingStatus);
|
||||||
const isPostsFiltered = useSelector(selectAreThreadsFiltered);
|
const isPostsFiltered = useSelector(selectAreThreadsFiltered);
|
||||||
const topics = useSelector(selectTopics);
|
const topics = useSelector(selectTopics);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (provider) {
|
|
||||||
dispatch(fetchCourseTopicsV3(courseId));
|
|
||||||
}
|
|
||||||
}, [provider]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isPostsFiltered) {
|
if (isPostsFiltered) {
|
||||||
dispatch(clearFilter());
|
dispatch(clearFilter());
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {
|
import {
|
||||||
useCallback, useContext, useEffect, useMemo,
|
useCallback, useContext, useEffect, useMemo,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
|
|
||||||
import { Button, Spinner } from '@openedx/paragon';
|
import { Button, Spinner } from '@openedx/paragon';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|||||||
@@ -1,19 +1,11 @@
|
|||||||
import React, {
|
import React, { useCallback, useContext, useMemo } from 'react';
|
||||||
useCallback, useContext, useEffect, useMemo,
|
|
||||||
} from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import isEmpty from 'lodash/isEmpty';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import SearchInfo from '../../components/SearchInfo';
|
import SearchInfo from '../../components/SearchInfo';
|
||||||
import { selectCurrentCategoryGrouping, selectTopicsUnderCategory } from '../../data/selectors';
|
import { selectCurrentCategoryGrouping, selectTopicsUnderCategory } from '../../data/selectors';
|
||||||
import DiscussionContext from '../common/context';
|
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 { handleKeyDown } from '../utils';
|
||||||
import { selectAllThreadsIds, selectTopicThreadsIds } from './data/selectors';
|
import { selectAllThreadsIds, selectTopicThreadsIds } from './data/selectors';
|
||||||
import { setSearchQuery } from './data/slices';
|
import { setSearchQuery } from './data/slices';
|
||||||
@@ -51,27 +43,12 @@ CategoryPostsList.propTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const PostsView = () => {
|
const PostsView = () => {
|
||||||
const {
|
const { topicId, category } = useContext(DiscussionContext);
|
||||||
topicId,
|
|
||||||
category,
|
|
||||||
courseId,
|
|
||||||
enableInContextSidebar,
|
|
||||||
} = useContext(DiscussionContext);
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const enableInContext = useSelector(selectEnableInContext);
|
|
||||||
const searchString = useSelector(({ threads }) => threads.filters.search);
|
const searchString = useSelector(({ threads }) => threads.filters.search);
|
||||||
const resultsFound = useSelector(({ threads }) => threads.totalThreads);
|
const resultsFound = useSelector(({ threads }) => threads.totalThreads);
|
||||||
const textSearchRewrite = useSelector(({ threads }) => threads.textSearchRewrite);
|
const textSearchRewrite = useSelector(({ threads }) => threads.textSearchRewrite);
|
||||||
const loadingStatus = useSelector(({ threads }) => threads.status);
|
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(() => {
|
const handleOnClear = useCallback(() => {
|
||||||
dispatch(setSearchQuery(''));
|
dispatch(setSearchQuery(''));
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
@@ -232,7 +230,7 @@ describe('PostsView', () => {
|
|||||||
|
|
||||||
test('test that the cohorts filter works', async () => {
|
test('test that the cohorts filter works', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
fireEvent.click(screen.getByLabelText('Cohort 1'));
|
fireEvent.click(screen.getByLabelText('cohort 1'));
|
||||||
});
|
});
|
||||||
|
|
||||||
dropDownButton = screen.getByRole('button', {
|
dropDownButton = screen.getByRole('button', {
|
||||||
@@ -280,7 +278,7 @@ describe('PostsView', () => {
|
|||||||
queryParam: { group_id: undefined },
|
queryParam: { group_id: undefined },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Cohort 1',
|
label: 'cohort 1',
|
||||||
queryParam: { group_id: 'cohort-1' },
|
queryParam: { group_id: 'cohort-1' },
|
||||||
},
|
},
|
||||||
])(
|
])(
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export const postThread = async (
|
|||||||
content,
|
content,
|
||||||
{
|
{
|
||||||
following,
|
following,
|
||||||
cohort,
|
groupId,
|
||||||
anonymous,
|
anonymous,
|
||||||
anonymousToPeers,
|
anonymousToPeers,
|
||||||
notifyAllLearners,
|
notifyAllLearners,
|
||||||
@@ -114,7 +114,7 @@ export const postThread = async (
|
|||||||
following,
|
following,
|
||||||
anonymous,
|
anonymous,
|
||||||
anonymousToPeers,
|
anonymousToPeers,
|
||||||
groupId: cohort,
|
groupId,
|
||||||
enableInContextSidebar,
|
enableInContextSidebar,
|
||||||
notifyAllLearners,
|
notifyAllLearners,
|
||||||
captchaToken: recaptchaToken,
|
captchaToken: recaptchaToken,
|
||||||
@@ -154,6 +154,7 @@ export const updateThread = async (threadId, {
|
|||||||
pinned,
|
pinned,
|
||||||
editReasonCode,
|
editReasonCode,
|
||||||
closeReasonCode,
|
closeReasonCode,
|
||||||
|
groupId,
|
||||||
} = {}) => {
|
} = {}) => {
|
||||||
const url = `${getThreadsApiUrl()}${threadId}/`;
|
const url = `${getThreadsApiUrl()}${threadId}/`;
|
||||||
const patchData = snakeCaseObject({
|
const patchData = snakeCaseObject({
|
||||||
@@ -169,6 +170,7 @@ export const updateThread = async (threadId, {
|
|||||||
pinned,
|
pinned,
|
||||||
editReasonCode,
|
editReasonCode,
|
||||||
closeReasonCode,
|
closeReasonCode,
|
||||||
|
groupId,
|
||||||
});
|
});
|
||||||
const { data } = await getAuthenticatedHttpClient()
|
const { data } = await getAuthenticatedHttpClient()
|
||||||
.patch(url, patchData, { headers: { 'Content-Type': 'application/merge-patch+json' } });
|
.patch(url, patchData, { headers: { 'Content-Type': 'application/merge-patch+json' } });
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export function createNewThread({
|
|||||||
following,
|
following,
|
||||||
anonymous,
|
anonymous,
|
||||||
anonymousToPeers,
|
anonymousToPeers,
|
||||||
cohort,
|
groupId,
|
||||||
enableInContextSidebar,
|
enableInContextSidebar,
|
||||||
notifyAllLearners,
|
notifyAllLearners,
|
||||||
recaptchaToken,
|
recaptchaToken,
|
||||||
@@ -224,12 +224,12 @@ export function createNewThread({
|
|||||||
following,
|
following,
|
||||||
anonymous,
|
anonymous,
|
||||||
anonymousToPeers,
|
anonymousToPeers,
|
||||||
cohort,
|
groupId,
|
||||||
notifyAllLearners,
|
notifyAllLearners,
|
||||||
recaptchaToken,
|
recaptchaToken,
|
||||||
}));
|
}));
|
||||||
const data = await postThread(courseId, topicId, type, title, content, {
|
const data = await postThread(courseId, topicId, type, title, content, {
|
||||||
cohort,
|
groupId,
|
||||||
following,
|
following,
|
||||||
anonymous,
|
anonymous,
|
||||||
anonymousToPeers,
|
anonymousToPeers,
|
||||||
@@ -252,7 +252,8 @@ export function createNewThread({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function updateExistingThread(threadId, {
|
export function updateExistingThread(threadId, {
|
||||||
flagged, voted, read, topicId, type, title, content, following, closed, pinned, closeReasonCode, editReasonCode,
|
flagged, voted, read, topicId, type, title, content, following,
|
||||||
|
closed, pinned, closeReasonCode, editReasonCode, groupId,
|
||||||
}) {
|
}) {
|
||||||
return async (dispatch) => {
|
return async (dispatch) => {
|
||||||
try {
|
try {
|
||||||
@@ -270,6 +271,7 @@ export function updateExistingThread(threadId, {
|
|||||||
pinned,
|
pinned,
|
||||||
editReasonCode,
|
editReasonCode,
|
||||||
closeReasonCode,
|
closeReasonCode,
|
||||||
|
groupId,
|
||||||
}));
|
}));
|
||||||
const data = await updateThread(threadId, {
|
const data = await updateThread(threadId, {
|
||||||
flagged,
|
flagged,
|
||||||
@@ -284,6 +286,7 @@ export function updateExistingThread(threadId, {
|
|||||||
pinned,
|
pinned,
|
||||||
editReasonCode,
|
editReasonCode,
|
||||||
closeReasonCode,
|
closeReasonCode,
|
||||||
|
groupId,
|
||||||
});
|
});
|
||||||
dispatch(updateThreadSuccess(camelCaseObject(data)));
|
dispatch(updateThreadSuccess(camelCaseObject(data)));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ const PostEditor = ({
|
|||||||
notifyAllLearners: false,
|
notifyAllLearners: false,
|
||||||
anonymous: allowAnonymous ? false : undefined,
|
anonymous: allowAnonymous ? false : undefined,
|
||||||
anonymousToPeers: allowAnonymousToPeers ? false : undefined,
|
anonymousToPeers: allowAnonymousToPeers ? false : undefined,
|
||||||
cohort: post?.cohort || 'default',
|
cohort: post?.groupId || 'default',
|
||||||
editReasonCode: post?.lastEdit?.reasonCode || (
|
editReasonCode: post?.lastEdit?.reasonCode || (
|
||||||
userIsStaff && canDisplayEditReason ? 'violates-guidelines' : undefined
|
userIsStaff && canDisplayEditReason ? 'violates-guidelines' : undefined
|
||||||
),
|
),
|
||||||
@@ -175,6 +175,8 @@ const PostEditor = ({
|
|||||||
|
|
||||||
const submitForm = useCallback(async (values, { resetForm }) => {
|
const submitForm = useCallback(async (values, { resetForm }) => {
|
||||||
let recaptchaToken;
|
let recaptchaToken;
|
||||||
|
const groupId = canSelectCohort(values.topic) ? selectedCohort(values.cohort) : undefined;
|
||||||
|
|
||||||
if (shouldRequireCaptcha && executeRecaptcha) {
|
if (shouldRequireCaptcha && executeRecaptcha) {
|
||||||
try {
|
try {
|
||||||
recaptchaToken = await executeRecaptcha('submit_post');
|
recaptchaToken = await executeRecaptcha('submit_post');
|
||||||
@@ -196,10 +198,9 @@ const PostEditor = ({
|
|||||||
title: values.title,
|
title: values.title,
|
||||||
content: values.comment,
|
content: values.comment,
|
||||||
editReasonCode: values.editReasonCode || undefined,
|
editReasonCode: values.editReasonCode || undefined,
|
||||||
|
groupId,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
const cohort = canSelectCohort(values.topic) ? selectedCohort(values.cohort) : undefined;
|
|
||||||
|
|
||||||
await dispatchSubmit(createNewThread({
|
await dispatchSubmit(createNewThread({
|
||||||
courseId,
|
courseId,
|
||||||
topicId: values.topic,
|
topicId: values.topic,
|
||||||
@@ -209,7 +210,7 @@ const PostEditor = ({
|
|||||||
following: values.follow,
|
following: values.follow,
|
||||||
anonymous: allowAnonymous ? values.anonymous : undefined,
|
anonymous: allowAnonymous ? values.anonymous : undefined,
|
||||||
anonymousToPeers: allowAnonymousToPeers ? values.anonymousToPeers : undefined,
|
anonymousToPeers: allowAnonymousToPeers ? values.anonymousToPeers : undefined,
|
||||||
cohort,
|
groupId,
|
||||||
enableInContextSidebar,
|
enableInContextSidebar,
|
||||||
notifyAllLearners: values.notifyAllLearners,
|
notifyAllLearners: values.notifyAllLearners,
|
||||||
...(shouldRequireCaptcha && recaptchaToken ? { recaptchaToken } : {}),
|
...(shouldRequireCaptcha && recaptchaToken ? { recaptchaToken } : {}),
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ const PostFilterBar = () => {
|
|||||||
<ActionItem
|
<ActionItem
|
||||||
key={cohort.id}
|
key={cohort.id}
|
||||||
id={toString(cohort.id)}
|
id={toString(cohort.id)}
|
||||||
label={capitalize(cohort.name)}
|
label={cohort.name}
|
||||||
value={toString(cohort.id)}
|
value={toString(cohort.id)}
|
||||||
selected={currentFilters.cohort}
|
selected={currentFilters.cohort}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,19 +1,15 @@
|
|||||||
import React, {
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
useCallback, useContext, useEffect, useMemo,
|
|
||||||
} from 'react';
|
|
||||||
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import SearchInfo from '../../components/SearchInfo';
|
import SearchInfo from '../../components/SearchInfo';
|
||||||
import { RequestStatus } from '../../data/constants';
|
import { RequestStatus } from '../../data/constants';
|
||||||
import DiscussionContext from '../common/context';
|
|
||||||
import { selectDiscussionProvider } from '../data/selectors';
|
import { selectDiscussionProvider } from '../data/selectors';
|
||||||
import NoResults from '../posts/NoResults';
|
import NoResults from '../posts/NoResults';
|
||||||
import { handleKeyDown } from '../utils';
|
import { handleKeyDown } from '../utils';
|
||||||
import { selectCategories, selectNonCoursewareTopics, selectTopicFilter } from './data/selectors';
|
import { selectCategories, selectNonCoursewareTopics, selectTopicFilter } from './data/selectors';
|
||||||
import { setFilter, setTopicsCount } from './data/slices';
|
import { setFilter, setTopicsCount } from './data/slices';
|
||||||
import fetchCourseTopics from './data/thunks';
|
|
||||||
import LegacyTopicGroup from './topic-group/LegacyTopicGroup';
|
import LegacyTopicGroup from './topic-group/LegacyTopicGroup';
|
||||||
import Topic from './topic-group/topic/Topic';
|
import Topic from './topic-group/topic/Topic';
|
||||||
import countFilteredTopics from './utils';
|
import countFilteredTopics from './utils';
|
||||||
@@ -64,19 +60,11 @@ const TopicsView = () => {
|
|||||||
const topicsSelector = useSelector(({ topics }) => topics);
|
const topicsSelector = useSelector(({ topics }) => topics);
|
||||||
const filteredTopicsCount = useSelector(({ topics }) => topics.results.count);
|
const filteredTopicsCount = useSelector(({ topics }) => topics.results.count);
|
||||||
const loadingStatus = useSelector(({ topics }) => topics.status);
|
const loadingStatus = useSelector(({ topics }) => topics.status);
|
||||||
const { courseId } = useContext(DiscussionContext);
|
|
||||||
|
|
||||||
const handleOnClear = useCallback(() => {
|
const handleOnClear = useCallback(() => {
|
||||||
dispatch(setFilter(''));
|
dispatch(setFilter(''));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Don't load till the provider information is available
|
|
||||||
if (provider) {
|
|
||||||
dispatch(fetchCourseTopics(courseId));
|
|
||||||
}
|
|
||||||
}, [provider]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const count = countFilteredTopics(topicsSelector, provider);
|
const count = countFilteredTopics(topicsSelector, provider);
|
||||||
dispatch(setTopicsCount(count));
|
dispatch(setTopicsCount(count));
|
||||||
|
|||||||
Reference in New Issue
Block a user