Merge pull request #346 from openedx/INF-626
fix: Icons for responses to endorse and mark as answered added
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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', {});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user