2024-08-12 05:50:54 -04:00
|
|
|
import { FC, useCallback, useState } from 'react'
|
|
|
|
import {
|
2024-10-10 09:01:30 -04:00
|
|
|
CommentId,
|
2024-08-12 05:50:54 -04:00
|
|
|
ReviewPanelCommentThreadMessage,
|
|
|
|
} from '../../../../../types/review-panel/review-panel'
|
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
|
import { formatTimeBasedOnYear } from '@/features/utils/format-date'
|
2024-10-18 06:14:45 -04:00
|
|
|
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
2024-08-12 05:50:54 -04:00
|
|
|
import MaterialIcon from '@/shared/components/material-icon'
|
|
|
|
import AutoExpandingTextArea from '@/shared/components/auto-expanding-text-area'
|
|
|
|
import { buildName } from '../utils/build-name'
|
|
|
|
import ReviewPanelCommentOptions from './review-panel-comment-options'
|
|
|
|
import { ExpandableContent } from './review-panel-expandable-content'
|
|
|
|
import ReviewPanelDeleteCommentModal from './review-panel-delete-comment-modal'
|
2024-10-21 04:54:39 -04:00
|
|
|
import { useUserContext } from '@/shared/context/user-context'
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
export const ReviewPanelMessage: FC<{
|
|
|
|
message: ReviewPanelCommentThreadMessage
|
|
|
|
hasReplies: boolean
|
|
|
|
isReply: boolean
|
2024-10-10 09:01:30 -04:00
|
|
|
onResolve?: () => Promise<void>
|
|
|
|
onEdit?: (commentId: CommentId, content: string) => Promise<void>
|
2024-10-21 04:58:39 -04:00
|
|
|
onDelete?: () => void
|
2024-08-19 09:16:56 -04:00
|
|
|
isThreadResolved: boolean
|
|
|
|
}> = ({
|
|
|
|
message,
|
|
|
|
isReply,
|
|
|
|
hasReplies,
|
|
|
|
onResolve,
|
2024-10-10 09:01:30 -04:00
|
|
|
onEdit,
|
|
|
|
onDelete,
|
2024-08-19 09:16:56 -04:00
|
|
|
isThreadResolved,
|
|
|
|
}) => {
|
2024-08-12 05:50:54 -04:00
|
|
|
const { t } = useTranslation()
|
|
|
|
const [editing, setEditing] = useState(false)
|
|
|
|
const [deleting, setDeleting] = useState(false)
|
|
|
|
const [content, setContent] = useState(message.content)
|
2024-10-21 04:54:39 -04:00
|
|
|
const user = useUserContext()
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
const handleEditOption = useCallback(() => setEditing(true), [])
|
|
|
|
const showDeleteModal = useCallback(() => setDeleting(true), [])
|
|
|
|
const hideDeleteModal = useCallback(() => setDeleting(false), [])
|
|
|
|
|
2024-10-10 09:01:30 -04:00
|
|
|
const handleSubmit = useCallback(() => {
|
|
|
|
onEdit?.(message.id, content)
|
|
|
|
setEditing(false)
|
|
|
|
}, [content, message.id, onEdit])
|
2024-08-12 05:50:54 -04:00
|
|
|
|
2024-10-10 09:01:30 -04:00
|
|
|
const handleDelete = useCallback(() => {
|
2024-10-21 04:58:39 -04:00
|
|
|
onDelete?.()
|
2024-10-10 09:01:30 -04:00
|
|
|
setDeleting(false)
|
2024-10-21 04:58:39 -04:00
|
|
|
}, [onDelete])
|
2024-08-12 05:50:54 -04:00
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="review-panel-comment">
|
|
|
|
<div className="review-panel-entry-header">
|
|
|
|
<div>
|
|
|
|
<div className="review-panel-entry-user">
|
|
|
|
{buildName(message.user)}
|
|
|
|
</div>
|
|
|
|
<div className="review-panel-entry-time">
|
|
|
|
{formatTimeBasedOnYear(message.timestamp)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="review-panel-entry-actions">
|
2024-10-25 09:20:08 -04:00
|
|
|
{!editing && !isReply && !isThreadResolved && (
|
2024-10-18 06:14:45 -04:00
|
|
|
<OLTooltip
|
2024-08-12 05:50:54 -04:00
|
|
|
id="resolve-thread"
|
|
|
|
overlayProps={{ placement: 'bottom' }}
|
|
|
|
description={t('resolve_comment')}
|
2024-10-02 07:58:46 -04:00
|
|
|
tooltipProps={{ className: 'review-panel-tooltip' }}
|
2024-08-12 05:50:54 -04:00
|
|
|
>
|
2024-10-18 06:14:45 -04:00
|
|
|
<button type="button" className="btn" onClick={onResolve}>
|
2024-08-12 05:50:54 -04:00
|
|
|
<MaterialIcon
|
|
|
|
type="check"
|
|
|
|
className="review-panel-entry-actions-icon"
|
|
|
|
accessibilityLabel={t('resolve_comment')}
|
|
|
|
/>
|
2024-10-18 06:14:45 -04:00
|
|
|
</button>
|
|
|
|
</OLTooltip>
|
2024-08-12 05:50:54 -04:00
|
|
|
)}
|
|
|
|
|
2024-10-25 09:20:08 -04:00
|
|
|
{!editing && !isThreadResolved && (
|
2024-08-19 09:16:56 -04:00
|
|
|
<ReviewPanelCommentOptions
|
2024-10-21 04:54:39 -04:00
|
|
|
belongsToCurrentUser={user.id === message.user.id}
|
2024-08-19 09:16:56 -04:00
|
|
|
onEdit={handleEditOption}
|
|
|
|
onDelete={showDeleteModal}
|
2024-10-18 06:14:45 -04:00
|
|
|
id={message.id}
|
2024-08-19 09:16:56 -04:00
|
|
|
/>
|
|
|
|
)}
|
2024-08-12 05:50:54 -04:00
|
|
|
</div>
|
|
|
|
</div>
|
2024-10-25 09:20:08 -04:00
|
|
|
{editing ? (
|
|
|
|
<AutoExpandingTextArea
|
|
|
|
className="review-panel-comment-input review-panel-comment-edit"
|
|
|
|
onBlur={handleSubmit}
|
|
|
|
onChange={e => setContent(e.target.value)}
|
|
|
|
onKeyDown={e => {
|
|
|
|
if (
|
|
|
|
e.key === 'Enter' &&
|
|
|
|
!e.shiftKey &&
|
|
|
|
!e.ctrlKey &&
|
|
|
|
!e.metaKey &&
|
|
|
|
content
|
|
|
|
) {
|
|
|
|
e.preventDefault()
|
|
|
|
;(e.target as HTMLTextAreaElement).blur()
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
value={content}
|
|
|
|
autoFocus // eslint-disable-line jsx-a11y/no-autofocus
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<ExpandableContent className="review-panel-comment-body">
|
|
|
|
{message.content}
|
|
|
|
</ExpandableContent>
|
|
|
|
)}
|
|
|
|
|
2024-08-12 05:50:54 -04:00
|
|
|
{deleting && (
|
|
|
|
<ReviewPanelDeleteCommentModal
|
|
|
|
onHide={hideDeleteModal}
|
|
|
|
onDelete={handleDelete}
|
|
|
|
title={hasReplies ? t('delete_comment_thread') : t('delete_comment')}
|
|
|
|
message={
|
|
|
|
hasReplies
|
|
|
|
? t('delete_comment_thread_message')
|
|
|
|
: t('delete_comment_message')
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|