Files
frontend-app-discussions/src/discussions/post-comments/comments/CommentsView.jsx
Awais Ansari 22474f4b1e feat: add comments sorted by ascending and descending functionality (#408)
* feat: comments sorting option

* feat: create new dropdown for comment sort

* test: fix comments failing test cases

* refactor: update comment sort filter param

* test: update comment sort param in test cases

* refactor: resolve lint issue

* test: add comment sort param in hover test case

* refactor: update comments folder structure

* test: add new test cases for comments sort
2023-02-13 14:25:43 +05:00

131 lines
4.4 KiB
JavaScript

import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import { Button, Spinner } from '@edx/paragon';
import { EndorsementStatus } from '../../../data/constants';
import { useUserCanAddThreadInBlackoutDate } from '../../data/hooks';
import { filterPosts, isLastElementOfList } from '../../utils';
import { usePostComments } from '../data/hooks';
import messages from '../messages';
import { Comment, ResponseEditor } from './comment';
function CommentsView({
postType,
postId,
intl,
endorsed,
isClosed,
}) {
const {
comments,
hasMorePages,
isLoading,
handleLoadMoreResponses,
} = usePostComments(postId, endorsed);
const endorsedComments = useMemo(() => [...filterPosts(comments, 'endorsed')], [comments]);
const unEndorsedComments = useMemo(() => [...filterPosts(comments, 'unendorsed')], [comments]);
const userCanAddThreadInBlackoutDate = useUserCanAddThreadInBlackoutDate();
const [addingResponse, setAddingResponse] = useState(false);
const handleDefinition = (message, commentsLength) => (
<div
className="mx-4 my-14px text-gray-700 font-style"
role="heading"
aria-level="2"
>
{intl.formatMessage(message, { num: commentsLength })}
</div>
);
const handleComments = (postComments, showLoadMoreResponses = false) => (
<div className="mx-4" role="list">
{postComments.map((comment) => (
<Comment
comment={comment}
key={comment.id}
postType={postType}
isClosedPost={isClosed}
marginBottom={isLastElementOfList(postComments, comment)}
/>
))}
{hasMorePages && !isLoading && !showLoadMoreResponses && (
<Button
onClick={handleLoadMoreResponses}
variant="link"
block="true"
className="px-4 mt-3 border-0 line-height-24 py-0 mb-2 font-style font-weight-500 font-size-14"
data-testid="load-more-comments"
>
{intl.formatMessage(messages.loadMoreResponses)}
</Button>
)}
{isLoading && !showLoadMoreResponses && (
<div className="mb-2 mt-3 d-flex justify-content-center">
<Spinner animation="border" variant="primary" className="spinner-dimentions" />
</div>
)}
</div>
);
return (
<>
{((hasMorePages && isLoading) || !isLoading) && (
<>
{endorsedComments.length > 0 && (
<>
{handleDefinition(messages.endorsedResponseCount, endorsedComments.length)}
{endorsed === EndorsementStatus.DISCUSSION
? handleComments(endorsedComments, true)
: handleComments(endorsedComments, false)}
</>
)}
{endorsed !== EndorsementStatus.ENDORSED && (
<>
{handleDefinition(messages.responseCount, unEndorsedComments.length)}
{unEndorsedComments.length === 0 && <br />}
{handleComments(unEndorsedComments, false)}
{(userCanAddThreadInBlackoutDate && !!unEndorsedComments.length && !isClosed) && (
<div className="mx-4">
{!addingResponse && (
<Button
variant="plain"
block="true"
className="card mb-4 px-0 border-0 py-10px mt-2 font-style font-weight-500
line-height-24 font-size-14 text-primary-500"
onClick={() => setAddingResponse(true)}
data-testid="add-response"
>
{intl.formatMessage(messages.addResponse)}
</Button>
)}
<ResponseEditor
postId={postId}
handleCloseEditor={() => setAddingResponse(false)}
addWrappingDiv
addingResponse={addingResponse}
/>
</div>
)}
</>
)}
</>
)}
</>
);
}
CommentsView.propTypes = {
postId: PropTypes.string.isRequired,
postType: PropTypes.string.isRequired,
isClosed: PropTypes.bool.isRequired,
intl: intlShape.isRequired,
endorsed: PropTypes.oneOf([
EndorsementStatus.ENDORSED, EndorsementStatus.UNENDORSED, EndorsementStatus.DISCUSSION,
]).isRequired,
};
export default injectIntl(CommentsView);