cardBadges.tsx
TLDR
This file, cardBadges.tsx
, is a React component that renders badges for a card. The badges indicate if the card has a description, comments, or checkboxes. The component receives a card
object as a prop and calculates the badges based on the card's contents and comments. If there are no badges to display, the component returns null
. The file also imports and uses various other components, hooks, and utilities.
Methods
There are no methods defined in this file.
Classes
There are no classes defined in this file.
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {useMemo} from 'react'
import {useIntl} from 'react-intl'
import {Card} from '../blocks/card'
import {useAppSelector} from '../store/hooks'
import {getCardContents} from '../store/contents'
import {getCardComments} from '../store/comments'
import {ContentBlock} from '../blocks/contentBlock'
import {CommentBlock} from '../blocks/commentBlock'
import TextIcon from '../widgets/icons/text'
import MessageIcon from '../widgets/icons/message'
import CheckIcon from '../widgets/icons/check'
import {Utils} from '../utils'
import './cardBadges.scss'
type Props = {
card: Card
className?: string
}
type Checkboxes = {
total: number
checked: number
}
type Badges = {
description: boolean
comments: number
checkboxes: Checkboxes
}
const hasBadges = (badges: Badges): boolean => {
return badges.description || badges.comments > 0 || badges.checkboxes.total > 0
}
type ContentsType = Array<ContentBlock | ContentBlock[]>
const calculateBadges = (contents: ContentsType, comments: CommentBlock[]): Badges => {
let text = 0
let total = 0
let checked = 0
const updateCounters = (block: ContentBlock) => {
if (block.type === 'text') {
text++
const checkboxes = Utils.countCheckboxesInMarkdown(block.title)
total += checkboxes.total
checked += checkboxes.checked
} else if (block.type === 'checkbox') {
total++
if (block.fields.value) {
checked++
}
}
}
for (const content of contents) {
if (Array.isArray(content)) {
content.forEach(updateCounters)
} else {
updateCounters(content)
}
}
return {
description: text > 0,
comments: comments.length,
checkboxes: {
total,
checked,
},
}
}
const CardBadges = (props: Props) => {
const {card, className} = props
const contents = useAppSelector(getCardContents(card.id))
const comments = useAppSelector(getCardComments(card.id))
const badges = useMemo(() => calculateBadges(contents, comments), [contents, comments])
if (!hasBadges(badges)) {
return null
}
const intl = useIntl()
const {checkboxes} = badges
return (
<div className={`CardBadges ${className || ''}`}>
{badges.description &&
<span title={intl.formatMessage({id: 'CardBadges.title-description', defaultMessage: 'This card has a description'})}>
<TextIcon/>
</span>}
{badges.comments > 0 &&
<span title={intl.formatMessage({id: 'CardBadges.title-comments', defaultMessage: 'Comments'})}>
<MessageIcon/>
{badges.comments}
</span>}
{checkboxes.total > 0 &&
<span title={intl.formatMessage({id: 'CardBadges.title-checkboxes', defaultMessage: 'Checkboxes'})}>
<CheckIcon/>
{`${checkboxes.checked}/${checkboxes.total}`}
</span>}
</div>
)
}
export default React.memo(CardBadges)