focalboard/webapp/src/components/boardCard.tsx
2020-11-09 10:02:54 -08:00

133 lines
4.7 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react'
import {injectIntl, IntlShape} from 'react-intl'
import {MutableBlock} from '../blocks/block'
import {IPropertyTemplate} from '../blocks/board'
import {Card} from '../blocks/card'
import mutator from '../mutator'
import MenuWrapper from '../widgets/menuWrapper'
import Menu from '../widgets/menu'
import OptionsIcon from '../widgets/icons/options'
import DeleteIcon from '../widgets/icons/delete'
import DuplicateIcon from '../widgets/icons/duplicate'
import IconButton from '../widgets/buttons/iconButton'
import PropertyValueElement from './propertyValueElement'
import './boardCard.scss'
type BoardCardProps = {
card: Card
visiblePropertyTemplates: IPropertyTemplate[]
isSelected: boolean
isDropZone?: boolean
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void
onDragEnd?: (e: React.DragEvent<HTMLDivElement>) => void
onDrop?: (e: React.DragEvent<HTMLDivElement>) => void
intl: IntlShape
}
type BoardCardState = {
isDragged?: boolean
isDragOver?: boolean
}
class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
constructor(props: BoardCardProps) {
super(props)
this.state = {}
}
shouldComponentUpdate(): boolean {
return true
}
render(): JSX.Element {
const {card, intl} = this.props
const visiblePropertyTemplates = this.props.visiblePropertyTemplates || []
let className = this.props.isSelected ? 'BoardCard selected' : 'BoardCard'
if (this.props.isDropZone && this.state.isDragOver) {
className += ' dragover'
}
const element = (
<div
className={className}
draggable={true}
style={{opacity: this.state.isDragged ? 0.5 : 1}}
onClick={this.props.onClick}
onDragStart={(e) => {
this.setState({isDragged: true})
this.props.onDragStart(e)
}}
onDragEnd={(e) => {
this.setState({isDragged: false})
this.props.onDragEnd(e)
}}
onDragOver={(e) => {
if (!this.state.isDragOver) {
this.setState({isDragOver: true})
}
}}
onDragEnter={(e) => {
if (!this.state.isDragOver) {
this.setState({isDragOver: true})
}
}}
onDragLeave={(e) => {
this.setState({isDragOver: false})
}}
onDrop={(e) => {
this.setState({isDragOver: false})
if (this.props.isDropZone) {
this.props.onDrop(e)
}
}}
>
<MenuWrapper
className='optionsMenu'
stopPropagationOnToggle={true}
>
<IconButton icon={<OptionsIcon/>}/>
<Menu position='left'>
<Menu.Text
icon={<DeleteIcon/>}
id='delete'
name={intl.formatMessage({id: 'BoardCard.delete', defaultMessage: 'Delete'})}
onClick={() => mutator.deleteBlock(card, 'delete card')}
/>
<Menu.Text
icon={<DuplicateIcon/>}
id='duplicate'
name={intl.formatMessage({id: 'BoardCard.duplicate', defaultMessage: 'Duplicate'})}
onClick={() => mutator.insertBlock(MutableBlock.duplicate(card), 'duplicate card')}
/>
</Menu>
</MenuWrapper>
<div className='octo-icontitle'>
{ card.icon ? <div className='octo-icon'>{card.icon}</div> : undefined }
<div key='__title'>{card.title || intl.formatMessage({id: 'BoardCard.untitled', defaultMessage: 'Untitled'})}</div>
</div>
{visiblePropertyTemplates.map((template) => (
<PropertyValueElement
key={template.id}
readOnly={true}
card={card}
propertyTemplate={template}
emptyDisplayValue=''
/>
))}
</div>
)
return element
}
}
export default injectIntl(BoardCard)