ReplyComments.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { type JSX, useState } from 'react';
  2. import type { IUser } from '@growi/core';
  3. import { useAtomValue } from 'jotai';
  4. import { Collapse } from 'reactstrap';
  5. import type { ICommentHasId, ICommentHasIdList } from '~/interfaces/comment';
  6. import type { RendererOptions } from '~/interfaces/renderer-options';
  7. import { isAllReplyShownAtom } from '~/states/server-configurations';
  8. import { Comment } from './Comment';
  9. import styles from './ReplyComments.module.scss';
  10. type ReplycommentsProps = {
  11. rendererOptions: RendererOptions;
  12. isReadOnly: boolean;
  13. revisionId: string;
  14. revisionCreatedAt: Date;
  15. currentUser: IUser;
  16. replyList: ICommentHasIdList;
  17. pageId: string;
  18. pagePath: string;
  19. deleteBtnClicked: (comment: ICommentHasId) => void;
  20. onComment: () => void;
  21. };
  22. export const ReplyComments = (props: ReplycommentsProps): JSX.Element => {
  23. const {
  24. rendererOptions,
  25. isReadOnly,
  26. revisionId,
  27. revisionCreatedAt,
  28. currentUser,
  29. replyList,
  30. pageId,
  31. pagePath,
  32. deleteBtnClicked,
  33. onComment,
  34. } = props;
  35. const isAllReplyShown = useAtomValue(isAllReplyShownAtom);
  36. const [isOlderRepliesShown, setIsOlderRepliesShown] = useState(false);
  37. const renderReply = (reply: ICommentHasId) => {
  38. return (
  39. <div
  40. key={reply._id}
  41. className={`${styles['page-comment-reply']} mt-2 ms-4 ms-sm-5`}
  42. >
  43. <Comment
  44. rendererOptions={rendererOptions}
  45. comment={reply}
  46. revisionId={revisionId}
  47. revisionCreatedAt={revisionCreatedAt}
  48. currentUser={currentUser}
  49. isReadOnly={isReadOnly}
  50. pageId={pageId}
  51. pagePath={pagePath}
  52. deleteBtnClicked={deleteBtnClicked}
  53. onComment={onComment}
  54. />
  55. </div>
  56. );
  57. };
  58. if (isAllReplyShown) {
  59. return (
  60. <>
  61. {replyList.map((reply) => {
  62. return renderReply(reply);
  63. })}
  64. </>
  65. );
  66. }
  67. const areThereHiddenReplies = replyList.length > 2;
  68. const toggleButtonIconName = isOlderRepliesShown
  69. ? 'expand_less'
  70. : 'more_vert';
  71. const toggleButtonIcon = (
  72. <span className="material-symbols-outlined me-1">
  73. {toggleButtonIconName}
  74. </span>
  75. );
  76. const toggleButtonLabel = isOlderRepliesShown ? '' : 'more';
  77. const shownReplies = replyList.slice(replyList.length - 2, replyList.length);
  78. const hiddenReplies = replyList.slice(0, replyList.length - 2);
  79. const hiddenElements = hiddenReplies.map((reply) => {
  80. return renderReply(reply);
  81. });
  82. const shownElements = shownReplies.map((reply) => {
  83. return renderReply(reply);
  84. });
  85. return (
  86. <>
  87. {areThereHiddenReplies && (
  88. <div className={`${styles['page-comments-hidden-replies']}`}>
  89. <Collapse isOpen={isOlderRepliesShown}>
  90. <div>{hiddenElements}</div>
  91. </Collapse>
  92. <div className="text-center">
  93. <button
  94. type="button"
  95. className="btn btn-link"
  96. onClick={() => setIsOlderRepliesShown(!isOlderRepliesShown)}
  97. >
  98. {toggleButtonIcon} {toggleButtonLabel}
  99. </button>
  100. </div>
  101. </div>
  102. )}
  103. {shownElements}
  104. </>
  105. );
  106. };