- {postInstances}
+ {postInstances(pinnedPosts)}
+ {postInstances(unpinnedPosts)}
{loadingStatus !== RequestStatus.IN_PROGRESS && posts?.length === 0 &&
}
{loadingStatus === RequestStatus.IN_PROGRESS ? (
diff --git a/src/discussions/learners/LearnersView.jsx b/src/discussions/learners/LearnersView.jsx
index 067f8711..8340be19 100644
--- a/src/discussions/learners/LearnersView.jsx
+++ b/src/discussions/learners/LearnersView.jsx
@@ -57,10 +57,18 @@ function LearnersView({ intl }) {
};
return (
-
- { !usernameSearch &&
}
- { usernameSearch &&
dispatch(setUsernameSearch(''))} /> }
-
+
+ {!usernameSearch &&
}
+
+ {usernameSearch && (
+
dispatch(setUsernameSearch(''))}
+ />
+ )}
+
{courseConfigLoadingStatus === RequestStatus.SUCCESSFUL && !learnersTabEnabled && (
setOpen(!isOpen)}
- className="collapsible-card-lg border-right-0"
+ className="filter-bar collapsible-card-lg border-0"
>
diff --git a/src/discussions/posts/PostsList.jsx b/src/discussions/posts/PostsList.jsx
index 134557ae..34cf3515 100644
--- a/src/discussions/posts/PostsList.jsx
+++ b/src/discussions/posts/PostsList.jsx
@@ -1,7 +1,8 @@
-import React, { useContext, useEffect } from 'react';
+import React, {
+ useCallback, useContext, useEffect, useMemo,
+} from 'react';
import PropTypes from 'prop-types';
-import uniqBy from 'lodash/uniqBy';
import { useDispatch, useSelector } from 'react-redux';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -12,6 +13,7 @@ import { RequestStatus } from '../../data/constants';
import { DiscussionContext } from '../common/context';
import { selectconfigLoadingStatus, selectUserHasModerationPrivileges, selectUserIsStaff } from '../data/selectors';
import messages from '../messages';
+import { filterPosts } from '../utils';
import {
selectThreadFilters, selectThreadNextPage, selectThreadSorting, threadsLoadingStatus,
} from './data/selectors';
@@ -53,28 +55,25 @@ function PostsList({ posts, topics, intl }) {
}, [courseId, orderBy, filters, page, JSON.stringify(topics), configStatus]);
const checkIsSelected = (id) => window.location.pathname.includes(id);
+ const pinnedPosts = useMemo(() => filterPosts(posts, 'pinned'), [posts]);
+ const unpinnedPosts = useMemo(() => filterPosts(posts, 'unpinned'), [posts]);
- let lastPinnedIdx = null;
- const sortedPosts = uniqBy(posts, 'id').sort((a, b) => b.pinned - a.pinned);
-
- const postInstances = sortedPosts.map((post, idx) => {
- if (post.pinned && lastPinnedIdx !== false) {
- lastPinnedIdx = idx;
- } else if (lastPinnedIdx != null && lastPinnedIdx !== false) {
- lastPinnedIdx = false;
- // Add a spacing after the group of pinned posts
- return (
-
-
-
- );
- }
- return ();
- });
+ const postInstances = useCallback((sortedPosts) => (
+ sortedPosts.map((post, idx) => (
+
+ ))
+ ), []);
return (
<>
- {postInstances}
+ {postInstances(pinnedPosts)}
+ {postInstances(unpinnedPosts)}
{posts?.length === 0 && loadingStatus === RequestStatus.SUCCESSFUL && }
{loadingStatus === RequestStatus.IN_PROGRESS ? (
diff --git a/src/discussions/posts/PostsView.jsx b/src/discussions/posts/PostsView.jsx
index 094ed4e4..d55739ad 100644
--- a/src/discussions/posts/PostsView.jsx
+++ b/src/discussions/posts/PostsView.jsx
@@ -80,6 +80,7 @@ function PostsView() {
searchString &&
dispatch(setSearchQuery(''))} />
}
+
handleKeyDown(e)}>
{postsListComponent}
diff --git a/src/discussions/posts/post-actions-bar/PostActionsBar.jsx b/src/discussions/posts/post-actions-bar/PostActionsBar.jsx
index 3d40ce0e..10d0548a 100644
--- a/src/discussions/posts/post-actions-bar/PostActionsBar.jsx
+++ b/src/discussions/posts/post-actions-bar/PostActionsBar.jsx
@@ -29,6 +29,7 @@ function PostActionsBar({
{!inContext && (
<>
+
>
)}
{inContext && (
@@ -39,7 +40,7 @@ function PostActionsBar({
@@ -126,6 +132,7 @@ function PostLink({
+ {!showDivider && post.pinned && }
>
);
@@ -142,7 +149,7 @@ PostLink.propTypes = {
PostLink.defaultProps = {
learnerTab: false,
- showDivider: false,
+ showDivider: true,
idx: -1,
};
diff --git a/src/discussions/utils.js b/src/discussions/utils.js
index bafca548..28f4b964 100644
--- a/src/discussions/utils.js
+++ b/src/discussions/utils.js
@@ -1,5 +1,6 @@
/* eslint-disable import/prefer-default-export */
import { getIn } from 'formik';
+import { orderBy, uniqBy } from 'lodash';
import { generatePath, useRouteMatch } from 'react-router';
import { getConfig } from '@edx/frontend-platform';
@@ -238,3 +239,17 @@ export const isPostPreviewAvailable = (htmlNode) => {
}
return true;
};
+
+/**
+ * Helper function to filter posts
+ * @param {array} posts arrays of posts
+ * @param {string} filterBy name of post object attribute. un will use for reverse
+ * condition. like pinned attribute for pinned post and unpinned for non pinned posts.
+ * @param {string} sortBy name of post object attribute
+ * @param {string} order order of the sorting list
+ */
+export const filterPosts = (posts, filterBy, sortBy = 'createdAt', order = 'desc') => orderBy(
+ uniqBy(posts, 'id').filter(
+ post => (filterBy.startsWith('un') ? !post[filterBy.slice(2)] : post[filterBy]),
+ ), [sortBy], [order],
+);
diff --git a/src/index.scss b/src/index.scss
index e8745223..62f69192 100755
--- a/src/index.scss
+++ b/src/index.scss
@@ -160,4 +160,8 @@ header {
.pointer-cursor-hover :hover{
cursor: pointer;
-}
\ No newline at end of file
+}
+
+.filter-bar:focus-visible, .filter-bar:focus {
+ outline: none;
+}