focalboard/webapp/src/components/boardCard.tsx

136 lines
4.9 KiB
TypeScript
Raw Normal View History

2020-10-20 21:50:53 +02:00
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
2020-10-20 21:52:56 +02:00
import React from 'react'
import {injectIntl, IntlShape} from 'react-intl'
2020-10-20 21:52:56 +02:00
import {IPropertyTemplate} from '../blocks/board'
import {Card} from '../blocks/card'
import mutator from '../mutator'
2020-11-13 03:48:59 +01:00
import IconButton from '../widgets/buttons/iconButton'
import DeleteIcon from '../widgets/icons/delete'
import DuplicateIcon from '../widgets/icons/duplicate'
2020-11-13 03:48:59 +01:00
import OptionsIcon from '../widgets/icons/options'
import Menu from '../widgets/menu'
import MenuWrapper from '../widgets/menuWrapper'
2020-10-26 12:43:16 +01:00
import './boardCard.scss'
2020-11-13 03:48:59 +01:00
import PropertyValueElement from './propertyValueElement'
2020-10-08 18:21:27 +02:00
type BoardCardProps = {
2020-10-20 21:50:53 +02:00
card: Card
visiblePropertyTemplates: IPropertyTemplate[]
isSelected: boolean
2020-10-28 18:46:36 +01:00
isDropZone?: boolean
2020-10-20 21:50:53 +02:00
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
2020-12-17 21:02:12 +01:00
readonly: boolean
2020-10-08 18:21:27 +02:00
}
type BoardCardState = {
2020-10-20 21:50:53 +02:00
isDragged?: boolean
2020-10-28 18:46:36 +01:00
isDragOver?: boolean
2020-10-08 18:21:27 +02:00
}
class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
2020-10-20 21:50:53 +02:00
constructor(props: BoardCardProps) {
super(props)
this.state = {}
}
2020-10-08 18:21:27 +02:00
2020-10-22 23:10:38 +02:00
shouldComponentUpdate(): boolean {
return true
}
render(): JSX.Element {
const {card, intl} = this.props
2020-10-20 21:50:53 +02:00
const visiblePropertyTemplates = this.props.visiblePropertyTemplates || []
2020-10-28 18:46:36 +01:00
let className = this.props.isSelected ? 'BoardCard selected' : 'BoardCard'
if (this.props.isDropZone && this.state.isDragOver) {
className += ' dragover'
}
2020-10-22 23:10:38 +02:00
const element = (
<div
className={className}
2020-12-17 21:02:12 +01:00
draggable={!this.props.readonly}
2020-10-20 21:50:53 +02:00
style={{opacity: this.state.isDragged ? 0.5 : 1}}
onClick={this.props.onClick}
onDragStart={(e) => {
2020-10-22 23:10:38 +02:00
this.setState({isDragged: true})
this.props.onDragStart(e)
2020-10-20 21:50:53 +02:00
}}
onDragEnd={(e) => {
2020-10-22 23:10:38 +02:00
this.setState({isDragged: false})
this.props.onDragEnd(e)
2020-10-20 21:50:53 +02:00
}}
2020-10-28 18:46:36 +01:00
2020-11-12 23:17:13 +01:00
onDragOver={() => {
2020-11-09 19:02:54 +01:00
if (!this.state.isDragOver) {
this.setState({isDragOver: true})
}
2020-10-28 18:46:36 +01:00
}}
2020-11-12 23:17:13 +01:00
onDragEnter={() => {
2020-11-09 19:02:54 +01:00
if (!this.state.isDragOver) {
this.setState({isDragOver: true})
}
2020-10-28 18:46:36 +01:00
}}
2020-11-12 23:17:13 +01:00
onDragLeave={() => {
2020-10-28 18:46:36 +01:00
this.setState({isDragOver: false})
}}
onDrop={(e) => {
this.setState({isDragOver: false})
if (this.props.isDropZone) {
this.props.onDrop(e)
}
}}
2020-10-20 21:50:53 +02:00
>
2020-12-17 21:02:12 +01:00
{!this.props.readonly &&
<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.duplicateCard(card.id)
}}
/>
</Menu>
</MenuWrapper>
}
2020-10-08 18:21:27 +02:00
2020-10-20 21:50:53 +02:00
<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>
2020-10-20 21:50:53 +02:00
</div>
2020-10-26 12:43:16 +01:00
{visiblePropertyTemplates.map((template) => (
<PropertyValueElement
key={template.id}
readOnly={true}
card={card}
propertyTemplate={template}
emptyDisplayValue=''
/>
))}
2020-10-22 23:10:38 +02:00
</div>
)
2020-10-08 18:21:27 +02:00
2020-10-20 21:50:53 +02:00
return element
}
2020-10-08 18:21:27 +02:00
}
export default injectIntl(BoardCard)