Uses new API features for preview, deleting, pinning, and closing. Refactors and improves styling to match new mockups. Adds the new post filter bar element.
74 lines
2.7 KiB
JavaScript
74 lines
2.7 KiB
JavaScript
import React, { useState } from 'react';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import * as timeago from 'timeago.js';
|
|
|
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
|
import { Avatar } from '@edx/paragon';
|
|
|
|
import { ContentActions } from '../../../data/constants';
|
|
import ActionsDropdown from '../../common/ActionsDropdown';
|
|
import AlertBanner from '../../common/AlertBanner';
|
|
import AuthorLabel from '../../common/AuthorLabel';
|
|
import { selectAuthorAvatars } from '../../posts/data/selectors';
|
|
import { editComment, removeComment } from '../data/thunks';
|
|
import CommentEditor from './CommentEditor';
|
|
import { commentShape } from './proptypes';
|
|
|
|
function Reply({
|
|
reply,
|
|
postType,
|
|
intl,
|
|
}) {
|
|
const dispatch = useDispatch();
|
|
const [isEditing, setEditing] = useState(false);
|
|
const actionHandlers = {
|
|
[ContentActions.EDIT_CONTENT]: () => setEditing(true),
|
|
[ContentActions.ENDORSE]: () => dispatch(editComment(reply.id, { endorsed: !reply.endorsed })),
|
|
// TODO: Add flow to confirm before deleting
|
|
[ContentActions.DELETE]: () => dispatch(removeComment(reply.id)),
|
|
[ContentActions.REPORT]: () => dispatch(editComment(reply.id, { flagged: !reply.abuseFlagged })),
|
|
};
|
|
const authorAvatars = useSelector(selectAuthorAvatars(reply.author));
|
|
return (
|
|
<div className="d-flex my-2 flex-column">
|
|
<div className="d-flex flex-fill ml-6">
|
|
<AlertBanner postType={null} content={reply} intl={intl} />
|
|
</div>
|
|
<div className="d-flex">
|
|
|
|
<div className="d-flex m-3">
|
|
<Avatar alt={reply.author} src={authorAvatars?.imageUrlSmall} />
|
|
</div>
|
|
<div className="rounded bg-light-300 px-4 py-2 flex-fill">
|
|
<div className="d-flex flex-row justify-content-between align-items-center">
|
|
<AuthorLabel author={reply.author} authorLabel={reply.authorLabel} />
|
|
<ActionsDropdown
|
|
commentOrPost={{
|
|
...reply,
|
|
postType,
|
|
}}
|
|
actionHandlers={actionHandlers}
|
|
/>
|
|
</div>
|
|
{isEditing
|
|
? <CommentEditor comment={reply} onCloseEditor={() => setEditing(false)} />
|
|
// eslint-disable-next-line react/no-danger
|
|
: <div dangerouslySetInnerHTML={{ __html: reply.renderedBody }} />}
|
|
</div>
|
|
|
|
</div>
|
|
<div className="text-gray-500 align-self-end mt-2" title={reply.createdAt}>
|
|
{timeago.format(reply.createdAt, intl.locale)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
Reply.propTypes = {
|
|
postType: PropTypes.oneOf(['discussion', 'question']).isRequired,
|
|
reply: commentShape.isRequired,
|
|
intl: intlShape.isRequired,
|
|
};
|
|
export default injectIntl(Reply);
|