@@ -59,6 +67,7 @@ function TopicsView() {
const topicFilter = useSelector(selectTopicFilter);
const filteredTopics = useSelector(selectFilteredTopics);
const loadingStatus = useSelector(selectLoadingStatus);
+ const isPostsFiltered = useSelector(selectAreThreadsFiltered);
useEffect(() => {
if (provider) {
@@ -66,6 +75,13 @@ function TopicsView() {
}
}, [provider]);
+ useEffect(() => {
+ if (isPostsFiltered) {
+ dispatch(clearFilter());
+ dispatch(clearSort());
+ }
+ }, [isPostsFiltered]);
+
return (
{topicFilter && (
diff --git a/src/discussions/in-context-topics/data/selectors.js b/src/discussions/in-context-topics/data/selectors.js
index 38bf7f20..824d8fbd 100644
--- a/src/discussions/in-context-topics/data/selectors.js
+++ b/src/discussions/in-context-topics/data/selectors.js
@@ -18,6 +18,22 @@ export const selectSubsectionUnits = subsectionId => state => state.inContextTop
unit => unit.parentId === subsectionId,
);
+export const selectSubsection = category => createSelector(
+ selectCoursewareTopics,
+ (coursewareTopics) => (
+ coursewareTopics?.map((topic) => topic?.children)?.flat()?.find((topic) => topic.id === category)
+ ),
+);
+
+export const selectArchivedTopics = state => state.inContextTopics.archivedTopics;
+
+export const selectArchivedTopic = topic => createSelector(
+ selectArchivedTopics,
+ (archivedTopics) => (
+ archivedTopics?.find((archivedTopic) => archivedTopic.id === topic)
+ ),
+);
+
export const selectLoadingStatus = state => state.inContextTopics.status;
export const selectFilteredTopics = createSelector(
diff --git a/src/discussions/in-context-topics/data/slices.js b/src/discussions/in-context-topics/data/slices.js
index ac43c945..95c76fa2 100644
--- a/src/discussions/in-context-topics/data/slices.js
+++ b/src/discussions/in-context-topics/data/slices.js
@@ -12,6 +12,7 @@ const topicsSlice = createSlice({
nonCoursewareTopics: [],
nonCoursewareIds: [],
units: [],
+ archivedTopics: [],
filter: '',
},
reducers: {
@@ -25,6 +26,7 @@ const topicsSlice = createSlice({
state.nonCoursewareTopics = payload.nonCoursewareTopics;
state.nonCoursewareIds = payload.nonCoursewareIds;
state.units = payload.units;
+ state.archivedTopics = payload.archivedTopics;
},
fetchCourseTopicsFailed: (state) => {
state.status = RequestStatus.FAILED;
diff --git a/src/discussions/in-context-topics/data/thunks.js b/src/discussions/in-context-topics/data/thunks.js
index b47907c0..34c1ec42 100644
--- a/src/discussions/in-context-topics/data/thunks.js
+++ b/src/discussions/in-context-topics/data/thunks.js
@@ -29,8 +29,15 @@ function normalizeTopicsV3(topics) {
return arrayOfUnits;
}, []);
+ const archivedTopics = reduce(topics, (arrayOfArchivedTopics, topic) => {
+ if (topic.id === 'archived') {
+ return topic.children;
+ }
+ return arrayOfArchivedTopics;
+ }, []);
+
const coursewareTopics = topics.filter((topic) => topic.courseware);
- const nonCoursewareTopics = topics.filter((topic) => !topic.courseware);
+ const nonCoursewareTopics = topics.filter((topic) => !topic.courseware && topic.enabledInContext);
const nonCoursewareIds = nonCoursewareTopics?.map((topic) => topic.id);
return {
@@ -39,6 +46,7 @@ function normalizeTopicsV3(topics) {
coursewareTopics,
nonCoursewareTopics,
nonCoursewareIds,
+ archivedTopics,
};
}
diff --git a/src/discussions/in-context-topics/messages.js b/src/discussions/in-context-topics/messages.js
index 87886cf6..8ae99e6e 100644
--- a/src/discussions/in-context-topics/messages.js
+++ b/src/discussions/in-context-topics/messages.js
@@ -69,6 +69,11 @@ const messages = defineMessages({
defaultMessage: 'Nothing here yet',
description: 'Helping Text to display if nothing here yet',
},
+ archivedTopics: {
+ id: 'discussions.topics.archived.label',
+ defaultMessage: 'Archived',
+ description: 'Heading for displaying topics that are archived.',
+ },
});
export default messages;
diff --git a/src/discussions/in-context-topics/topic/ArchivedBaseGroup.jsx b/src/discussions/in-context-topics/topic/ArchivedBaseGroup.jsx
new file mode 100644
index 00000000..eef9fcd0
--- /dev/null
+++ b/src/discussions/in-context-topics/topic/ArchivedBaseGroup.jsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+
+import messages from '../messages';
+import Topic, { topicShape } from './Topic';
+
+function ArchivedBaseGroup({
+ archivedTopics,
+ showDivider,
+ intl,
+}) {
+ return (
+ <>
+ {showDivider && (
+ <>
+
+
+ >
+ )}
+
+
{intl.formatMessage(messages.archivedTopics)}
+ {archivedTopics?.map((topic, index) => (
+
+ ))}
+
+ >
+ );
+}
+
+ArchivedBaseGroup.propTypes = {
+ archivedTopics: PropTypes.arrayOf(topicShape).isRequired,
+ showDivider: PropTypes.bool,
+ intl: intlShape.isRequired,
+};
+
+ArchivedBaseGroup.defaultProps = {
+ showDivider: false,
+};
+export default injectIntl(ArchivedBaseGroup);
diff --git a/src/discussions/in-context-topics/topic/index.js b/src/discussions/in-context-topics/topic/index.js
index 28f8a040..ef5526f7 100644
--- a/src/discussions/in-context-topics/topic/index.js
+++ b/src/discussions/in-context-topics/topic/index.js
@@ -1,3 +1,4 @@
/* eslint-disable import/prefer-default-export */
+export { default as ArchivedBaseGroup } from './ArchivedBaseGroup';
export { default as SectionBaseGroup } from './SectionBaseGroup';
export { default as Topic } from './Topic';
diff --git a/src/discussions/posts/data/slices.js b/src/discussions/posts/data/slices.js
index 6501f9ff..8d3c5a55 100644
--- a/src/discussions/posts/data/slices.js
+++ b/src/discussions/posts/data/slices.js
@@ -217,6 +217,19 @@ const threadsSlice = createSlice({
clearRedirect: (state) => {
state.redirectToThread = null;
},
+ clearFilter: (state) => {
+ state.filters = {
+ status: PostsStatusFilter.ALL,
+ postType: ThreadType.ALL,
+ cohort: '',
+ search: '',
+ };
+ state.pages = [];
+ },
+ clearSort: (state) => {
+ state.sortedBy = ThreadOrdering.BY_LAST_ACTIVITY;
+ state.pages = [];
+ },
},
});
@@ -253,6 +266,8 @@ export const {
hidePostEditor,
clearRedirect,
clearPostsPages,
+ clearFilter,
+ clearSort,
} = threadsSlice.actions;
export const threadsReducer = threadsSlice.reducer;
diff --git a/src/discussions/posts/post-editor/PostEditor.jsx b/src/discussions/posts/post-editor/PostEditor.jsx
index 91700979..adffc4fc 100644
--- a/src/discussions/posts/post-editor/PostEditor.jsx
+++ b/src/discussions/posts/post-editor/PostEditor.jsx
@@ -36,6 +36,7 @@ import {
} from '../../data/selectors';
import { EmptyPage } from '../../empty-posts';
import {
+ selectArchivedTopics,
selectCoursewareTopics as inContextCourseware,
selectNonCoursewareIds as inContextCoursewareIds,
selectNonCoursewareTopics as inContextNonCourseware,
@@ -114,6 +115,7 @@ function PostEditor({
const { allowAnonymous, allowAnonymousToPeers } = useSelector(selectAnonymousPostingConfig);
const { reasonCodesEnabled, editReasons } = useSelector(selectModerationSettings);
const userIsStaff = useSelector(selectUserIsStaff);
+ const archivedTopics = useSelector(selectArchivedTopics);
const canDisplayEditReason = (reasonCodesEnabled && editExisting
&& (userHasModerationPrivileges || userIsGroupTa || userIsStaff)
@@ -317,7 +319,8 @@ function PostEditor({
))}
{enableInContext ? (
- coursewareTopics?.map(section => (
+ <>
+ {coursewareTopics?.map(section => (
section?.children?.map(subsection => (