Merge pull request #346 from openedx/INF-626

fix: Icons for responses to endorse and mark as answered added
This commit is contained in:
ayesha waris
2022-11-21 13:43:49 +05:00
committed by GitHub
6 changed files with 60 additions and 23 deletions

View File

@@ -5,14 +5,17 @@ import classNames from 'classnames';
import { useSelector } from 'react-redux';
import { injectIntl } from '@edx/frontend-platform/i18n';
import { Avatar, Icon } from '@edx/paragon';
import { CheckCircle, Verified } from '@edx/paragon/icons';
import { logError } from '@edx/frontend-platform/logging';
import {
Avatar, Icon,
} from '@edx/paragon';
import { AvatarOutlineAndLabelColors, ThreadType } from '../../../data/constants';
import { AvatarOutlineAndLabelColors, EndorsementStatus, ThreadType } from '../../../data/constants';
import { AuthorLabel } from '../../common';
import ActionsDropdown from '../../common/ActionsDropdown';
import { useAlertBannerVisible } from '../../data/hooks';
import { selectAuthorAvatars } from '../../posts/data/selectors';
import { useActions } from '../../utils';
import { commentShape } from './proptypes';
function CommentHeader({
@@ -24,6 +27,20 @@ function CommentHeader({
const colorClass = AvatarOutlineAndLabelColors[comment.authorLabel];
const hasAnyAlert = useAlertBannerVisible(comment);
const actions = useActions({
...comment,
postType,
});
const actionIcons = actions.find(({ action }) => action === EndorsementStatus.ENDORSED);
const handleIcons = (action) => {
const actionFunction = actionHandlers[action];
if (actionFunction) {
actionFunction();
} else {
logError(`Unknown or unimplemented action ${action}`);
}
};
return (
<div className={classNames('d-flex flex-row justify-content-between', {
'mt-2': hasAnyAlert,
@@ -47,15 +64,23 @@ function CommentHeader({
/>
</div>
<div className="d-flex align-items-center">
{comment.endorsed && (
<span className="btn-icon btn-icon-sm mr-1 align-items-center">
{
postType === 'question'
? <Icon src={CheckCircle} className="text-success" data-testid="check-icon" />
: <Icon src={Verified} className="text-dark-500" data-testid="verified-icon" />
}
</span>
{actionIcons && (
<span className="btn-icon btn-icon-sm mr-1 align-items-center">
<Icon
data-testid="check-icon"
onClick={
() => {
handleIcons(actionIcons.action);
}
}
src={actionIcons.icon}
className={['endorse', 'unendorse'].includes(actionIcons.id) ? 'text-dark-500' : 'text-success-500'}
size="sm"
/>
</span>
)}
<ActionsDropdown
commentOrPost={{
...comment,

View File

@@ -30,7 +30,7 @@ const mockComment = {
author: 'abc123',
authorLabel: 'ABC 123',
endorsed: true,
editableFields: [],
editableFields: ['endorsed'],
};
describe('Comment Header', () => {
@@ -48,7 +48,7 @@ describe('Comment Header', () => {
it('should render verified icon for endorsed discussion posts', () => {
renderComponent(mockComment, 'discussion', {});
expect(screen.queryAllByTestId('verified-icon')).toHaveLength(1);
expect(screen.queryAllByTestId('check-icon')).toHaveLength(1);
});
it('should render check icon for endorsed question posts', () => {
renderComponent(mockComment, 'question', {});

View File

@@ -20,6 +20,7 @@ function AuthorLabel({
authorLabel,
linkToProfile,
labelColor,
alert,
}) {
const location = useLocation();
const { courseId } = useContext(DiscussionContext);
@@ -46,8 +47,8 @@ function AuthorLabel({
<div className={className}>
<span
className={classNames('mr-1 font-size-14 font-style-normal font-family-inter font-weight-500', {
'text-primary-500': !authorLabelMessage && !isRetiredUser,
'text-gray-700': isRetiredUser,
'text-primary-500': !authorLabelMessage && !isRetiredUser && !alert,
})}
role="heading"
aria-level="2"
@@ -66,7 +67,8 @@ function AuthorLabel({
{authorLabelMessage && (
<span
className={classNames('mr-1 font-size-14 font-style-normal font-family-inter font-weight-500', {
'text-primary-500': !authorLabelMessage,
'text-primary-500': !authorLabelMessage && !isRetiredUser && !alert,
'text-gray-700': isRetiredUser,
})}
style={{ marginLeft: '2px' }}
>
@@ -97,12 +99,14 @@ AuthorLabel.propTypes = {
authorLabel: PropTypes.string,
linkToProfile: PropTypes.bool,
labelColor: PropTypes.string,
alert: PropTypes.bool,
};
AuthorLabel.defaultProps = {
linkToProfile: false,
authorLabel: null,
labelColor: '',
alert: false,
};
export default injectIntl(AuthorLabel);

View File

@@ -39,14 +39,19 @@ function EndorsedAlertBanner({
)}
</strong>
<span className="d-flex align-items-center mr-1 flex-wrap">
<span className="mr-2">
<span className="mr-1">
{intl.formatMessage(
isQuestion
? messages.answeredLabel
: messages.endorsedLabel,
)}
</span>
<AuthorLabel author={content.endorsedBy} authorLabel={content.endorsedByLabel} linkToProfile />
<AuthorLabel
author={content.endorsedBy}
authorLabel={content.endorsedByLabel}
linkToProfile
alert={content.endorsed}
/>
{intl.formatMessage(messages.time, { time: timeago.format(content.endorsedAt, 'time-locale') })}
</span>
</div>

View File

@@ -63,7 +63,7 @@ const messages = defineMessages({
},
markAnsweredAction: {
id: 'discussions.actions.markAnswered',
defaultMessage: 'Mark as Answered',
defaultMessage: 'Mark as answered',
description: 'Action to mark a comment as answering a post',
},
unmarkAnsweredAction: {

View File

@@ -5,7 +5,9 @@ import { generatePath, useRouteMatch } from 'react-router';
import { getConfig } from '@edx/frontend-platform';
import {
Delete, Edit, Pin, QuestionAnswer, Report, VerifiedBadge,
CheckCircle,
CheckCircleOutline,
Delete, Edit, Pin, QuestionAnswer, Report, Verified, VerifiedOutline,
} from '@edx/paragon/icons';
import { InsertLink } from '../components/icons';
@@ -101,7 +103,7 @@ export const ACTIONS_LIST = [
{
id: 'endorse',
action: ContentActions.ENDORSE,
icon: VerifiedBadge,
icon: VerifiedOutline,
label: messages.endorseAction,
conditions: {
endorsed: false,
@@ -111,7 +113,7 @@ export const ACTIONS_LIST = [
{
id: 'unendorse',
action: ContentActions.ENDORSE,
icon: VerifiedBadge,
icon: Verified,
label: messages.unendorseAction,
conditions: {
endorsed: true,
@@ -121,7 +123,7 @@ export const ACTIONS_LIST = [
{
id: 'answer',
action: ContentActions.ENDORSE,
icon: VerifiedBadge,
icon: CheckCircleOutline,
label: messages.markAnsweredAction,
conditions: {
endorsed: false,
@@ -131,7 +133,7 @@ export const ACTIONS_LIST = [
{
id: 'unanswer',
action: ContentActions.ENDORSE,
icon: VerifiedBadge,
icon: CheckCircle,
label: messages.unmarkAnsweredAction,
conditions: {
endorsed: true,
@@ -183,6 +185,7 @@ export function useActions(content) {
.every(condition => condition === true)
: true
);
return ACTIONS_LIST.filter(
({
action,