import React, { useEffect, useMemo, useState, type JSX, } from 'react'; import { isPopulated, type IUser } from '@growi/core'; import * as pathUtils from '@growi/core/dist/utils/path-utils'; import { UserPicture } from '@growi/ui/dist/components'; import { format, parseISO } from 'date-fns'; import { useTranslation } from 'next-i18next'; import Link from 'next/link'; import { UncontrolledTooltip } from 'reactstrap'; import urljoin from 'url-join'; import type { RendererOptions } from '~/interfaces/renderer-options'; import RevisionRenderer from '../../../components/PageView/RevisionRenderer'; import { Username } from '../../../components/User/Username'; import type { ICommentHasId } from '../../../interfaces/comment'; import FormattedDistanceDate from '../FormattedDistanceDate'; import { CommentControl } from './CommentControl'; import { CommentEditor } from './CommentEditor'; import styles from './Comment.module.scss'; type CommentProps = { comment: ICommentHasId, rendererOptions: RendererOptions, revisionId: string, revisionCreatedAt: Date, currentUser: IUser, isReadOnly: boolean, pageId: string, pagePath: string, deleteBtnClicked: (comment: ICommentHasId) => void, onComment: () => void, } export const Comment = (props: CommentProps): JSX.Element => { const { comment, rendererOptions, revisionId, revisionCreatedAt, currentUser, isReadOnly, pageId, pagePath, deleteBtnClicked, onComment, } = props; const { returnPathForURL } = pathUtils; const { t } = useTranslation(); const [markdown, setMarkdown] = useState(''); const [isReEdit, setIsReEdit] = useState(false); const commentId = comment._id; const creator = isPopulated(comment.creator) ? comment.creator : undefined; const createdAt = new Date(comment.createdAt); const updatedAt = new Date(comment.updatedAt); const isEdited = createdAt < updatedAt; useEffect(() => { if (revisionId == null) { return; } setMarkdown(comment.comment); const isCurrentRevision = () => { return comment.revision === revisionId; }; isCurrentRevision(); }, [comment, revisionId]); const isCurrentUserEqualsToAuthor = () => { const { creator }: any = comment; if (creator == null || currentUser == null) { return false; } return creator.username === currentUser.username; }; const getRootClassName = (comment: ICommentHasId) => { let className = 'page-comment flex-column'; // TODO: fix so that `comment.createdAt` to be type Date https://redmine.weseek.co.jp/issues/113876 const commentCreatedAtFixed = typeof comment.createdAt === 'string' ? parseISO(comment.createdAt) : comment.createdAt; const revisionCreatedAtFixed = typeof revisionCreatedAt === 'string' ? parseISO(revisionCreatedAt) : revisionCreatedAt; // Conditional for called from SearchResultContext if (revisionId != null && revisionCreatedAt != null) { if (comment.revision === revisionId) { className += ' page-comment-current'; } else if (commentCreatedAtFixed.getTime() > revisionCreatedAtFixed.getTime()) { className += ' page-comment-newer'; } else { className += ' page-comment-older'; } } if (isCurrentUserEqualsToAuthor()) { className += ' page-comment-me'; } return className; }; const deleteBtnClickedHandler = () => { deleteBtnClicked(comment); }; const commentBody = useMemo(() => { if (rendererOptions == null) { return <>; } return ( ); }, [markdown, rendererOptions]); const rootClassName = getRootClassName(comment); const revHref = `?revisionId=${comment.revision}`; const editedDateId = `editedDate-${comment._id}`; const editedDateFormatted = isEdited ? format(updatedAt, 'yyyy/MM/dd HH:mm') : null; return (
{ (isReEdit && !isReadOnly) ? ( setIsReEdit(false)} onCommented={() => { setIsReEdit(false); onComment(); }} revisionId={revisionId} /> ) : (
history {t('page_comment.display_the_page_when_posting_this_comment')}
{commentBody}
{ isEdited && ( <>  (edited) {editedDateFormatted} ) }
{ (isCurrentUserEqualsToAuthor() && !isReadOnly) && ( setIsReEdit(true)} /> ) }
) }
); };