commentsList.tsx
TLDR
This file, located at src/components/cardDetail/commentsList.tsx
, contains the CommentsList
component. The component displays a list of comments and allows users to add new comments. It also provides functionality to delete comments based on user permissions.
Methods
onSendClicked
This method is triggered when the user clicks the send button to submit a new comment. It retrieves the comment text, creates a new comment block, and inserts it into the board. The method also clears the new comment input field.
Classes
None
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useState} from 'react'
import {FormattedMessage, useIntl} from 'react-intl'
import {CommentBlock, createCommentBlock} from '../../blocks/commentBlock'
import mutator from '../../mutator'
import {useAppSelector} from '../../store/hooks'
import {Utils} from '../../utils'
import Button from '../../widgets/buttons/button'
import {MarkdownEditor} from '../markdownEditor'
import {IUser} from '../../user'
import {getMe} from '../../store/users'
import {useHasCurrentBoardPermissions} from '../../hooks/permissions'
import {Permission} from '../../constants'
import AddCommentTourStep from '../onboardingTour/addComments/addComments'
import Comment from './comment'
import './commentsList.scss'
type Props = {
comments: readonly CommentBlock[]
boardId: string
cardId: string
readonly: boolean
}
const CommentsList = (props: Props) => {
const [newComment, setNewComment] = useState('')
const me = useAppSelector<IUser|null>(getMe)
const canDeleteOthersComments = useHasCurrentBoardPermissions([Permission.DeleteOthersComments])
const onSendClicked = () => {
const commentText = newComment
if (commentText) {
const {cardId, boardId} = props
Utils.log(`Send comment: ${commentText}`)
Utils.assertValue(cardId)
const comment = createCommentBlock()
comment.parentId = cardId
comment.boardId = boardId
comment.title = commentText
mutator.insertBlock(boardId, comment, 'add comment')
setNewComment('')
}
}
const {comments} = props
const intl = useIntl()
const newCommentComponent = (
<div className='CommentsList__new'>
<img
className='comment-avatar'
src={Utils.getProfilePicture(me?.id)}
/>
<MarkdownEditor
className='newcomment'
text={newComment}
placeholderText={intl.formatMessage({id: 'CardDetail.new-comment-placeholder', defaultMessage: 'Add a comment...'})}
onChange={(value: string) => {
if (newComment !== value) {
setNewComment(value)
}
}}
/>
{newComment &&
<Button
filled={true}
onClick={onSendClicked}
>
<FormattedMessage
id='CommentsList.send'
defaultMessage='Send'
/>
</Button>
}
<AddCommentTourStep/>
</div>
)
return (
<div className='CommentsList'>
{/* New comment */}
{!props.readonly && newCommentComponent}
{comments.slice(0).reverse().map((comment) => {
// Only modify _own_ comments, EXCEPT for Admins, which can delete _any_ comment
// NOTE: editing comments will exist in the future (in addition to deleting)
const canDeleteComment: boolean = canDeleteOthersComments || me?.id === comment.modifiedBy
return (
<Comment
key={comment.id}
comment={comment}
userImageUrl={Utils.getProfilePicture(comment.modifiedBy)}
userId={comment.modifiedBy}
readonly={props.readonly || !canDeleteComment}
/>
)
})}
{/* horizontal divider below comments */}
{!(comments.length === 0 && props.readonly) && <hr className='CommentsList__divider'/>}
</div>
)
}
export default React.memo(CommentsList)