Comments.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import React, { useEffect, useRef } from 'react';
  2. import type { IRevisionHasId } from '@growi/core';
  3. import { pagePathUtils } from '@growi/core/dist/utils';
  4. import dynamic from 'next/dynamic';
  5. import { ROOT_ELEM_ID as PageCommentRootElemId, type PageCommentProps } from '~/components/PageComment';
  6. import { useSWRxPageComment } from '~/stores/comment';
  7. import { useIsTrashPage, useSWRMUTxPageInfo } from '~/stores/page';
  8. import { useCurrentUser } from '../stores/context';
  9. import type { CommentEditorProps } from './PageComment/CommentEditor';
  10. const { isTopPage } = pagePathUtils;
  11. const PageComment = dynamic<PageCommentProps>(() => import('~/components/PageComment').then(mod => mod.PageComment), { ssr: false });
  12. const CommentEditor = dynamic<CommentEditorProps>(() => import('./PageComment/CommentEditor').then(mod => mod.CommentEditor), { ssr: false });
  13. export type CommentsProps = {
  14. pageId: string,
  15. pagePath: string,
  16. revision: IRevisionHasId,
  17. onLoaded?: () => void,
  18. }
  19. export const Comments = (props: CommentsProps): JSX.Element => {
  20. const {
  21. pageId, pagePath, revision, onLoaded,
  22. } = props;
  23. const { mutate } = useSWRxPageComment(pageId);
  24. const { trigger: mutatePageInfo } = useSWRMUTxPageInfo(pageId);
  25. const { data: isDeleted } = useIsTrashPage();
  26. const { data: currentUser } = useCurrentUser();
  27. const pageCommentParentRef = useRef<HTMLDivElement>(null);
  28. useEffect(() => {
  29. const parent = pageCommentParentRef.current;
  30. if (parent == null) return;
  31. const observerCallback = (mutationRecords: MutationRecord[]) => {
  32. mutationRecords.forEach((record: MutationRecord) => {
  33. const target = record.target as HTMLElement;
  34. for (const child of Array.from(target.children)) {
  35. const childId = (child as HTMLElement).id;
  36. if (childId === PageCommentRootElemId) {
  37. onLoaded?.();
  38. break;
  39. }
  40. }
  41. });
  42. };
  43. const observer = new MutationObserver(observerCallback);
  44. observer.observe(parent, { childList: true });
  45. return () => {
  46. observer.disconnect();
  47. };
  48. }, [onLoaded]);
  49. const isTopPagePath = isTopPage(pagePath);
  50. if (pageId == null || isTopPagePath) {
  51. return <></>;
  52. }
  53. const onCommentButtonClickHandler = () => {
  54. mutate();
  55. mutatePageInfo();
  56. };
  57. return (
  58. <div className="page-comments-row mt-5 py-4 d-edit-none d-print-none">
  59. <div className="container-lg">
  60. <div id="page-comments-list" className="page-comments-list" ref={pageCommentParentRef}>
  61. <PageComment
  62. pageId={pageId}
  63. pagePath={pagePath}
  64. revision={revision}
  65. currentUser={currentUser}
  66. isReadOnly={false}
  67. titleAlign="left"
  68. hideIfEmpty={false}
  69. />
  70. </div>
  71. {!isDeleted && (
  72. <div id="page-comment-write">
  73. <CommentEditor
  74. pageId={pageId}
  75. isForNewComment
  76. onCommentButtonClicked={onCommentButtonClickHandler}
  77. revisionId={revision._id}
  78. />
  79. </div>
  80. )}
  81. </div>
  82. </div>
  83. );
  84. };