diff --git a/.env b/.env index 273646442..9c9dfe5a7 100644 --- a/.env +++ b/.env @@ -22,3 +22,4 @@ USER_INFO_COOKIE_NAME='' SUPPORT_URL='' LEARNER_FEEDBACK_URL='' STAFF_FEEDBACK_URL='' +ENABLE_PROFILE_IMAGE='' diff --git a/.env.development b/.env.development index ae4b3cee5..f6fe6b42b 100644 --- a/.env.development +++ b/.env.development @@ -23,3 +23,4 @@ USER_INFO_COOKIE_NAME='edx-user-info' SUPPORT_URL='https://support.edx.org' LEARNER_FEEDBACK_URL='' STAFF_FEEDBACK_URL='' +ENABLE_PROFILE_IMAGE='true' diff --git a/.env.test b/.env.test index 84bc122cd..a1147f2b5 100644 --- a/.env.test +++ b/.env.test @@ -21,3 +21,4 @@ USER_INFO_COOKIE_NAME='edx-user-info' SUPPORT_URL='https://support.edx.org' LEARNER_FEEDBACK_URL='' STAFF_FEEDBACK_URL='' +ENABLE_PROFILE_IMAGE='' diff --git a/src/discussions/data/hooks.js b/src/discussions/data/hooks.js index 6de5e1f0f..f4deb82a2 100644 --- a/src/discussions/data/hooks.js +++ b/src/discussions/data/hooks.js @@ -33,14 +33,11 @@ import { ContentSelectors } from './constants'; import { selectAreThreadsFiltered, selectEnableInContext, - selectIsCourseAdmin, - selectIsCourseStaff, selectIsPostingEnabled, selectIsUserLearner, selectPostThreadCount, selectUserHasModerationPrivileges, selectUserIsGroupTa, - selectUserIsStaff, } from './selectors'; import fetchCourseConfig from './thunks'; @@ -220,12 +217,9 @@ export const useCurrentDiscussionTopic = () => { export const useUserPostingEnabled = () => { const isPostingEnabled = useSelector(selectIsPostingEnabled); - const isUserAdmin = useSelector(selectUserIsStaff); const userHasModerationPrivileges = useSelector(selectUserHasModerationPrivileges); const isUserGroupTA = useSelector(selectUserIsGroupTa); - const isCourseAdmin = useSelector(selectIsCourseAdmin); - const isCourseStaff = useSelector(selectIsCourseStaff); - const isPrivileged = isUserAdmin || userHasModerationPrivileges || isUserGroupTA || isCourseAdmin || isCourseStaff; + const isPrivileged = userHasModerationPrivileges || isUserGroupTA; return (isPostingEnabled || isPrivileged); }; diff --git a/src/discussions/data/hooks.test.jsx b/src/discussions/data/hooks.test.jsx index ca58ebe82..e5648ce7e 100644 --- a/src/discussions/data/hooks.test.jsx +++ b/src/discussions/data/hooks.test.jsx @@ -19,11 +19,11 @@ const courseConfigApiUrl = getCourseConfigApiUrl(); let store; let axiosMock; -const generateApiResponse = (isPostingEnabled, isCourseAdmin = false) => ({ +const generateApiResponse = (isPostingEnabled, hasModerationPrivileges = false) => ({ isPostingEnabled, - hasModerationPrivileges: false, + hasModerationPrivileges, isGroupTa: false, - isCourseAdmin, + isCourseAdmin: false, isCourseStaff: false, isUserAdmin: false, }); @@ -160,7 +160,7 @@ describe('Hooks', () => { expect(queryByText('false')).toBeInTheDocument(); }); - test('when posting is not disabled and Role is not Learner return true', async () => { + test('when posting is disabled and Role is not Learner return true', async () => { axiosMock.onGet(`${courseConfigApiUrl}${courseId}/`) .reply(200, generateApiResponse(false, true)); await executeThunk(fetchCourseConfig(courseId), store.dispatch, store.getState); diff --git a/src/discussions/post-comments/comments/comment/Comment.jsx b/src/discussions/post-comments/comments/comment/Comment.jsx index c2c5a879b..571f9c653 100644 --- a/src/discussions/post-comments/comments/comment/Comment.jsx +++ b/src/discussions/post-comments/comments/comment/Comment.jsx @@ -43,7 +43,7 @@ const Comment = ({ const { id, parentId, childCount, abuseFlagged, endorsed, threadId, endorsedAt, endorsedBy, endorsedByLabel, renderedBody, voted, following, voteCount, authorLabel, author, createdAt, lastEdit, rawBody, closed, closedBy, closeReason, - editByLabel, closedByLabel, + editByLabel, closedByLabel, users: postUsers, } = comment; const intl = useIntl(); const hasChildren = childCount > 0; @@ -203,6 +203,7 @@ const Comment = ({ closed={closed} createdAt={createdAt} lastEdit={lastEdit} + postUsers={postUsers} /> {isEditing ? ( { const colorClass = AvatarOutlineAndLabelColors[authorLabel]; const hasAnyAlert = useAlertBannerVisible({ @@ -24,6 +27,8 @@ const CommentHeader = ({ closed, }); + const profileImage = getConfig().ENABLE_PROFILE_IMAGE === 'true' && postUsers && Object.values(postUsers)[0].profile.image; + return (
{ const { topicId, abuseFlagged, closed, pinned, voted, hasEndorsed, following, closedBy, voteCount, groupId, groupName, closeReason, authorLabel, type: postType, author, title, createdAt, renderedBody, lastEdit, editByLabel, - closedByLabel, + closedByLabel, users: postUsers, } = useSelector(selectThread(postId)); const intl = useIntl(); const location = useLocation(); @@ -182,6 +182,7 @@ const Post = ({ handleAddResponseButton }) => { lastEdit={lastEdit} postType={postType} title={title} + postUsers={postUsers} />
diff --git a/src/discussions/posts/post/PostHeader.jsx b/src/discussions/posts/post/PostHeader.jsx index eeb38878d..aee32ec95 100644 --- a/src/discussions/posts/post/PostHeader.jsx +++ b/src/discussions/posts/post/PostHeader.jsx @@ -5,6 +5,7 @@ import { Avatar, Badge, Icon } from '@openedx/paragon'; import { Question } from '@openedx/paragon/icons'; import classNames from 'classnames'; +import { getConfig } from '@edx/frontend-platform'; import { useIntl } from '@edx/frontend-platform/i18n'; import { AvatarOutlineAndLabelColors, ThreadType } from '../../../data/constants'; @@ -13,7 +14,7 @@ import { useAlertBannerVisible } from '../../data/hooks'; import messages from './messages'; export const PostAvatar = React.memo(({ - author, postType, authorLabel, fromPostLink, read, + author, postType, authorLabel, fromPostLink, read, postUsers, }) => { const outlineColor = AvatarOutlineAndLabelColors[authorLabel]; @@ -37,6 +38,8 @@ export const PostAvatar = React.memo(({ return spacing; }, [postType]); + const profileImage = getConfig().ENABLE_PROFILE_IMAGE === 'true' && postUsers && Object.values(postUsers)[0].profile.image; + return (
{postType === ThreadType.QUESTION && ( @@ -59,6 +62,7 @@ export const PostAvatar = React.memo(({ height: avatarSize, width: avatarSize, }} + src={profileImage?.hasImage ? profileImage?.imageUrlSmall : undefined} alt={author} />
@@ -71,6 +75,7 @@ PostAvatar.propTypes = { authorLabel: PropTypes.string, fromPostLink: PropTypes.bool, read: PropTypes.bool, + postUsers: PropTypes.shape({}).isRequired, }; PostAvatar.defaultProps = { @@ -90,6 +95,7 @@ const PostHeader = ({ title, postType, preview, + postUsers, }) => { const intl = useIntl(); const showAnsweredBadge = preview && hasEndorsed && postType === ThreadType.QUESTION; @@ -101,7 +107,7 @@ const PostHeader = ({ return (
- +
@@ -151,6 +157,7 @@ PostHeader.propTypes = { reason: PropTypes.string, }), closed: PropTypes.bool, + postUsers: PropTypes.shape({}).isRequired, }; PostHeader.defaultProps = { diff --git a/src/discussions/posts/post/PostLink.jsx b/src/discussions/posts/post/PostLink.jsx index 366f1dfa6..c522fc9a1 100644 --- a/src/discussions/posts/post/PostLink.jsx +++ b/src/discussions/posts/post/PostLink.jsx @@ -36,6 +36,7 @@ const PostLink = ({ const { topicId, hasEndorsed, type, author, authorLabel, abuseFlagged, abuseFlaggedCount, read, commentCount, unreadCommentCount, id, pinned, previewBody, title, voted, voteCount, following, groupId, groupName, createdAt, + users: postUsers, } = useSelector(selectThread(postId)); const { pathname } = discussionsPath(Routes.COMMENTS.PAGES[page], { 0: enableInContextSidebar ? 'in-context' : undefined, @@ -83,6 +84,7 @@ const PostLink = ({ authorLabel={authorLabel} fromPostLink read={isPostRead} + postUsers={postUsers} />
diff --git a/src/index.jsx b/src/index.jsx index 9ad349991..77f2e58f0 100755 --- a/src/index.jsx +++ b/src/index.jsx @@ -40,6 +40,7 @@ initialize({ LEARNING_BASE_URL: process.env.LEARNING_BASE_URL, LEARNER_FEEDBACK_URL: process.env.LEARNER_FEEDBACK_URL, STAFF_FEEDBACK_URL: process.env.STAFF_FEEDBACK_URL, + ENABLE_PROFILE_IMAGE: process.env.ENABLE_PROFILE_IMAGE, }, 'DiscussionsConfig'); }, },