review-panel-resolved-thread.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import React, { FC, useCallback, useState } from 'react'
  2. import { useTranslation, Trans } from 'react-i18next'
  3. import { ThreadId } from '../../../../../types/review-panel/review-panel'
  4. import { useThreadsActionsContext } from '../context/threads-context'
  5. import OLTooltip from '@/shared/components/ol/ol-tooltip'
  6. import MaterialIcon from '@/shared/components/material-icon'
  7. import { ExpandableContent } from './review-panel-expandable-content'
  8. import { ReviewPanelCommentContent } from './review-panel-comment-content'
  9. import { Change, CommentOperation } from '../../../../../types/change'
  10. import classNames from 'classnames'
  11. import { debugConsole } from '@/utils/debugging'
  12. import { useModalsContext } from '@/features/ide-react/context/modals-context'
  13. import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
  14. import { useUserContext } from '@/shared/context/user-context'
  15. export const ReviewPanelResolvedThread: FC<{
  16. id: ThreadId
  17. comment: Change<CommentOperation>
  18. docName: string
  19. }> = ({ id, comment, docName }) => {
  20. const { t } = useTranslation()
  21. const { reopenThread, deleteThread } = useThreadsActionsContext()
  22. const [processing, setProcessing] = useState(false)
  23. const { showGenericMessageModal } = useModalsContext()
  24. const permissions = usePermissionsContext()
  25. const user = useUserContext()
  26. const isCommentAuthor = user.id === comment.metadata?.user_id
  27. const canDelete =
  28. permissions.resolveAllComments ||
  29. (permissions.resolveOwnComments && isCommentAuthor)
  30. const canReopen = permissions.comment
  31. const handleReopenThread = useCallback(async () => {
  32. setProcessing(true)
  33. try {
  34. await reopenThread(id)
  35. } catch (err) {
  36. debugConsole.error(err)
  37. showGenericMessageModal(
  38. t('reopen_comment_error_title'),
  39. t('reopen_comment_error_message')
  40. )
  41. } finally {
  42. setProcessing(false)
  43. }
  44. }, [id, reopenThread, showGenericMessageModal, t])
  45. const handleDeleteThread = useCallback(async () => {
  46. setProcessing(true)
  47. try {
  48. await deleteThread(id)
  49. } catch (err) {
  50. debugConsole.error(err)
  51. showGenericMessageModal(
  52. t('delete_comment_error_title'),
  53. t('delete_comment_error_message')
  54. )
  55. } finally {
  56. setProcessing(false)
  57. }
  58. }, [id, deleteThread, showGenericMessageModal, t])
  59. return (
  60. <div
  61. className={classNames('review-panel-resolved-comment', {
  62. 'review-panel-resolved-disabled': processing,
  63. })}
  64. key={id}
  65. >
  66. <div className="review-panel-resolved-comment-header">
  67. <div>
  68. <Trans
  69. i18nKey="from_filename"
  70. components={[
  71. // eslint-disable-next-line react/jsx-key
  72. <span
  73. className="review-panel-resolved-comment-filename"
  74. translate="no"
  75. />,
  76. ]}
  77. values={{ filename: docName }}
  78. shouldUnescape
  79. tOptions={{ interpolation: { escapeValue: true } }}
  80. />
  81. </div>
  82. <div className="review-panel-resolved-comment-buttons">
  83. {canReopen && (
  84. <OLTooltip
  85. id="reopen-thread"
  86. overlayProps={{ placement: 'bottom' }}
  87. description={t('reopen')}
  88. >
  89. <button
  90. type="button"
  91. className="btn"
  92. onClick={handleReopenThread}
  93. >
  94. <MaterialIcon type="refresh" accessibilityLabel={t('reopen')} />
  95. </button>
  96. </OLTooltip>
  97. )}
  98. {canDelete && (
  99. <OLTooltip
  100. id="delete-thread"
  101. overlayProps={{ placement: 'bottom' }}
  102. description={t('delete')}
  103. >
  104. <button
  105. type="button"
  106. className="btn"
  107. onClick={handleDeleteThread}
  108. >
  109. <MaterialIcon type="delete" accessibilityLabel={t('delete')} />
  110. </button>
  111. </OLTooltip>
  112. )}
  113. </div>
  114. </div>
  115. <div className="review-panel-resolved-comment-quoted-text">
  116. <div className="review-panel-resolved-comment-quoted-text-label">
  117. {t('quoted_text')}
  118. </div>
  119. <ExpandableContent
  120. className="review-panel-resolved-comment-quoted-text-quote"
  121. content={comment?.op.c}
  122. checkNewLines
  123. translate="no"
  124. />
  125. </div>
  126. <ReviewPanelCommentContent comment={comment} isResolved />
  127. </div>
  128. )
  129. }