All files / client/components/Comment Comment.tsx

0% Statements 0/36
0% Branches 0/12
0% Functions 0/7
0% Lines 0/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                                                                                                                                                                                                 
import React, { FC, useState, useEffect } from 'react'
import styled from 'styled-components'
import CommentLists from './CommentLists'
import CommentForm from './CommentForm'
import Crowi from 'client/util/Crowi'
import { CommonProps } from 'client/types/component'
import { Comment as CommentType } from 'client/types/crowi'
 
const PageComments = styled.div<Props>`
  margin: 8px 0 0 0;
`
 
function useFetchComments(crowi, pageId, revisionId, revisionCreatedAt, isSharePage) {
  const [comments, setComments] = useState<{
    current: CommentType[]
    newer: CommentType[]
    older: CommentType[]
  }>({ current: [], newer: [], older: [] })
 
  const fetchComments = async () => {
    if (isSharePage) return
 
    const { ok, comments }: { ok: boolean; comments: CommentType[] } = await crowi.apiGet('/comments.get', { page_id: pageId })
    const [current, newer, older]: [CommentType[], CommentType[], CommentType[]] = [[], [], []]
    if (ok) {
      comments.forEach(comment => {
        const { revision, createdAt } = comment
        const isCurrent = revision === revisionId
        const isNewer = Date.parse(createdAt) / 1000 > revisionCreatedAt
 
        const target = isCurrent ? current : isNewer ? newer : older
        target.push(comment)
      })
      setComments({ current, newer, older })
    }
  }
 
  return [comments, fetchComments] as const
}
 
function usePostComment(crowi, pageId, revisionId, fetchComments) {
  const [posting, setPosting] = useState(false)
  const [message, setMessage] = useState('')
 
  const postComment = async (comment: string) => {
    try {
      setPosting(true)
      const { ok, error } = await crowi.apiPost('/comments.add', {
        commentForm: {
          comment,
          page_id: pageId,
          revision_id: revisionId,
        },
      })
      if (ok) {
        setMessage('')
        fetchComments()
      } else {
        setMessage(error)
      }
    } catch (err) {
      setMessage(err.message)
    } finally {
      setPosting(false)
    }
  }
 
  return [{ posting, message }, { postComment }] as const
}
 
type Props = CommonProps & {
  crowi: Crowi
  pageId: string | null
  revisionId: string | null
  revisionCreatedAt: string | null
  isSharePage: boolean
}
 
const Comment: FC<Props> = props => {
  const { crowi, pageId, revisionId, revisionCreatedAt, isSharePage, ...others } = props
  const [comments, fetchComments] = useFetchComments(crowi, pageId, revisionId, revisionCreatedAt, isSharePage)
  const [{ posting, message }, { postComment }] = usePostComment(crowi, pageId, revisionId, fetchComments)
 
  useEffect(() => {
    fetchComments()
  }, [])
 
  return !isSharePage ? (
    <PageComments {...others}>
      <CommentForm posting={posting} message={message} postComment={postComment} />
      <CommentLists crowi={crowi} comments={comments} revisionId={revisionId} />
    </PageComments>
  ) : null
}
 
export default Comment