| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- import { memo, useCallback, useMemo, useState } from 'react'
- import { Change, CommentOperation } from '../../../../../types/change'
- import {
- useThreadsActionsContext,
- useThreadsContext,
- } from '../context/threads-context'
- import classnames from 'classnames'
- import { ReviewPanelEntry } from './review-panel-entry'
- import { ReviewPanelCommentContent } from './review-panel-comment-content'
- import {
- CommentId,
- ThreadId,
- } from '../../../../../types/review-panel/review-panel'
- import { useModalsContext } from '@/features/ide-react/context/modals-context'
- import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
- import { useTranslation } from 'react-i18next'
- import { debugConsole } from '@/utils/debugging'
- export const ReviewPanelComment = memo<{
- comment: Change<CommentOperation>
- docId: string
- top?: number
- hoverRanges?: boolean
- handleEnter?: (changeId: string) => void
- handleLeave?: (changeId: string) => void
- hovered?: boolean
- }>(
- ({ comment, top, hovered, handleEnter, handleLeave, docId, hoverRanges }) => {
- const threads = useThreadsContext()
- const {
- resolveThread,
- editMessage,
- deleteMessage,
- deleteOwnMessage,
- deleteThread,
- addMessage,
- } = useThreadsActionsContext()
- const { showGenericMessageModal } = useModalsContext()
- const { t } = useTranslation()
- const permissions = usePermissionsContext()
- const [processing, setProcessing] = useState(false)
- const handleResolveComment = useCallback(async () => {
- setProcessing(true)
- try {
- await resolveThread(comment.op.t)
- } catch (err) {
- debugConsole.error(err)
- showGenericMessageModal(
- t('resolve_comment_error_title'),
- t('resolve_comment_error_message')
- )
- } finally {
- setProcessing(false)
- }
- }, [comment.op.t, resolveThread, showGenericMessageModal, t])
- const handleEditMessage = useCallback(
- async (commentId: CommentId, content: string) => {
- setProcessing(true)
- try {
- await editMessage(comment.op.t, commentId, content)
- } catch (err) {
- debugConsole.error(err)
- showGenericMessageModal(
- t('edit_comment_error_title'),
- t('edit_comment_error_message')
- )
- } finally {
- setProcessing(false)
- }
- },
- [comment.op.t, editMessage, showGenericMessageModal, t]
- )
- const handleDeleteMessage = useCallback(
- async (commentId: CommentId) => {
- setProcessing(true)
- try {
- if (permissions.resolveAllComments) {
- // Owners and editors can delete any message
- await deleteMessage(comment.op.t, commentId)
- } else if (permissions.resolveOwnComments) {
- // Reviewers can only delete their own messages
- await deleteOwnMessage(comment.op.t, commentId)
- }
- } catch (err) {
- debugConsole.error(err)
- showGenericMessageModal(
- t('delete_comment_error_title'),
- t('delete_comment_error_message')
- )
- } finally {
- setProcessing(false)
- }
- },
- [
- comment.op.t,
- deleteMessage,
- deleteOwnMessage,
- showGenericMessageModal,
- t,
- permissions.resolveOwnComments,
- permissions.resolveAllComments,
- ]
- )
- const handleDeleteThread = useCallback(
- async (commentId: ThreadId) => {
- setProcessing(true)
- try {
- await deleteThread(commentId)
- } catch (err) {
- debugConsole.error(err)
- showGenericMessageModal(
- t('delete_comment_error_title'),
- t('delete_comment_error_message')
- )
- } finally {
- setProcessing(false)
- }
- },
- [deleteThread, showGenericMessageModal, t]
- )
- const handleSubmitReply = useCallback(
- async (content: string) => {
- setProcessing(true)
- try {
- await addMessage(comment.op.t, content)
- } catch (err) {
- debugConsole.error(err)
- showGenericMessageModal(
- t('add_comment_error_title'),
- t('add_comment_error_message')
- )
- throw err
- } finally {
- setProcessing(false)
- }
- },
- [addMessage, comment.op.t, showGenericMessageModal, t]
- )
- const { handleMouseEnter, handleMouseLeave } = useMemo(() => {
- return {
- handleMouseEnter: handleEnter && (() => handleEnter(comment.id)),
- handleMouseLeave: handleLeave && (() => handleLeave(comment.id)),
- }
- }, [comment.id, handleEnter, handleLeave])
- const thread = threads?.[comment.op.t]
- if (!thread || thread.resolved || thread.messages.length === 0) {
- return null
- }
- return (
- <ReviewPanelEntry
- className={classnames('review-panel-entry-comment', {
- 'review-panel-entry-loaded': !!threads?.[comment.op.t],
- 'review-panel-entry-hover': hovered,
- })}
- docId={docId}
- top={top}
- op={comment.op}
- position={comment.op.p}
- hoverRanges={hoverRanges}
- disabled={processing}
- handleEnter={handleMouseEnter}
- handleLeave={handleMouseLeave}
- entryIndicator="comment"
- >
- <ReviewPanelCommentContent
- comment={comment}
- isResolved={false}
- onLeave={handleMouseLeave}
- onEnter={handleMouseEnter}
- onResolve={handleResolveComment}
- onEdit={handleEditMessage}
- onDeleteMessage={handleDeleteMessage}
- onDeleteThread={handleDeleteThread}
- onReply={handleSubmitReply}
- />
- </ReviewPanelEntry>
- )
- }
- )
- ReviewPanelComment.displayName = 'ReviewPanelComment'
|