@bigfishtv/cockpit
Version:
134 lines (123 loc) • 4.24 kB
JavaScript
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { DragSource, DropTarget } from 'react-dnd'
import { getEmptyImage } from 'react-dnd-html5-backend'
import classnames from 'classnames'
import TreeCell from '../tree/TreeCell'
import Breadrumb from '../breadcrumb/Breadcrumb'
// we define this because react-docgen fails when defaultProp directly references an imported component
const DefaultTreeCell = props => <TreeCell {...props} />
const treeItemSource = {
beginDrag(props, monitor, component) {
if (props.treeItemSource && props.treeItemSource.beginDrag)
return props.treeItemSource.beginDrag(props, monitor, component)
else return { id: props.id }
},
endDrag(props, monitor, component) {
if (props.treeItemSource && props.treeItemSource.endDrag)
return props.treeItemSource.endDrag(props, monitor, component)
},
canDrag(props, monitor) {
if (props.treeItemSource && props.treeItemSource.canDrag) return props.treeItemSource.canDrag(props, monitor)
else return true
},
isDragging(props, monitor) {
if (props.treeItemSource && props.treeItemSource.isDragging) return props.treeItemSource.isDragging(props, monitor)
return props.id === monitor.getItem().id
},
}
const treeItemTarget = {
drop(props, monitor, component) {
if (props.treeItemTarget && props.treeItemTarget.drop) return props.treeItemTarget.drop(props, monitor, component)
},
hover(props, monitor, component) {
if (props.treeItemTarget && props.treeItemTarget.hover) return props.treeItemTarget.hover(props, monitor, component)
},
canDrop(props, monitor, component) {
if (props.treeItemTarget && props.treeItemTarget.canDrop)
return props.treeItemTarget.canDrop(props, monitor, component)
else return true
},
}
/**
* Component used in tree, wraps the main TreeCell component with dragging functionality
*/
(props => props.dropTargetType, treeItemTarget, (connect, monitor) => {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver({ shallow: true }),
currentDragType: monitor.getItemType(),
}
})
(props => props.dragTargetType, treeItemSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
}))
export default class TreeItem extends Component {
static propTypes = {
/** Disregard -- provided by react-dnd */
beginDrag: PropTypes.func.isRequired,
/** Disregard -- provided by react-dnd */
endDrag: PropTypes.func.isRequired,
/** Disregard -- provided by react-dnd */
connectDragSource: PropTypes.func.isRequired,
/** Disregard -- provided by react-dnd */
connectDropTarget: PropTypes.func.isRequired,
/** Disregard -- provided by react-dnd */
isOver: PropTypes.bool.isRequired,
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
onCollapse: PropTypes.func,
/** Cell component to use instead of default TreeCell */
TreeCell: PropTypes.func,
}
static defaultProps = {
TreeCell: DefaultTreeCell,
}
componentDidMount() {
this.props.connectDragPreview(getEmptyImage(), { captureDraggingState: true })
}
handleIndicatorClick = event => {
event.stopPropagation()
this.props.onCollapse && this.props.onCollapse()
}
handleIndicatorDoubleClick = event => {
event.stopPropagation()
}
render() {
const {
TreeCell,
children,
connectDragSource,
connectDropTarget,
title,
isOver,
position,
collapsed,
forceExpand,
currentDragType,
dropTargetType,
selected,
breadcrumbs,
} = this.props
const dragging = currentDragType === dropTargetType
const isCollapsed = dragging && forceExpand ? false : collapsed
const selectedDrag = dragging && selected
return connectDragSource(
connectDropTarget(
<div className={classnames('tree-node', isOver && 'drag-' + position)}>
<Breadrumb title={children && breadcrumbs ? title : null}>
<TreeCell
{...this.props}
isCollapsed={isCollapsed}
selectedDrag={selectedDrag}
onIndicatorClick={this.handleIndicatorClick}
onIndicatorDoubleClick={this.handleIndicatorDoubleClick}
/>
{!isCollapsed && <div className="tree-children">{children}</div>}
</Breadrumb>
</div>
)
)
}
}