import React, {PropTypes, PureComponent} from 'react'; import ReactDOM from 'react-dom'; import {DragSource, DropTarget} from 'react-dnd'; import classnames from 'classnames'; import RequestGroupActionsDropdown from '../dropdowns/RequestGroupActionsDropdown'; import SidebarRequestRow from './SidebarRequestRow'; import {trackEvent} from '../../../analytics/index'; class SidebarRequestGroupRow extends PureComponent { state = {dragDirection: 0}; _handleCollapse = () => { const {requestGroup, handleSetRequestGroupCollapsed, isCollapsed} = this.props; handleSetRequestGroupCollapsed(requestGroup._id, !isCollapsed); trackEvent('Folder', 'Toggle Visible', !isCollapsed ? 'Close' : 'Open') }; _nullFunction = () => null; setDragDirection (dragDirection) { if (dragDirection !== this.state.dragDirection) { this.setState({dragDirection}) } } render () { const { connectDragSource, connectDropTarget, moveRequest, children, requestGroup, isCollapsed, isActive, handleCreateRequest, handleCreateRequestGroup, handleDuplicateRequestGroup, isDragging, isDraggingOver, workspace, } = this.props; const {dragDirection} = this.state; let folderIconClass = 'fa-folder'; folderIconClass += isCollapsed ? '' : '-open'; folderIconClass += isActive ? '' : '-o'; const classes = classnames('sidebar__row', { 'sidebar__row--dragging': isDragging, 'sidebar__row--dragging-above': isDraggingOver && dragDirection > 0, 'sidebar__row--dragging-below': isDraggingOver && dragDirection < 0 }); // NOTE: We only want the button draggable, not the whole container (ie. no children) const button = connectDragSource(connectDropTarget( )); return (
  • {button}
  • ); } } SidebarRequestGroupRow.propTypes = { // Functions handleSetRequestGroupCollapsed: PropTypes.func.isRequired, handleDuplicateRequestGroup: PropTypes.func.isRequired, moveRequestGroup: PropTypes.func.isRequired, moveRequest: PropTypes.func.isRequired, handleActivateRequest: PropTypes.func.isRequired, handleCreateRequest: PropTypes.func.isRequired, // Other isActive: PropTypes.bool.isRequired, isCollapsed: PropTypes.bool.isRequired, workspace: PropTypes.object.isRequired, requestGroup: PropTypes.object.isRequired, // React DnD isDragging: PropTypes.bool, isDraggingOver: PropTypes.bool, connectDragSource: PropTypes.func, connectDropTarget: PropTypes.func }; /** * Implements the drag source contract. */ const dragSource = { beginDrag(props) { trackEvent('Folder', 'Drag', 'Begin'); return { requestGroup: props.requestGroup }; } }; function isAbove (monitor, component) { const hoveredNode = ReactDOM.findDOMNode(component); const hoveredTop = hoveredNode.getBoundingClientRect().top; const draggedTop = monitor.getSourceClientOffset().y; return hoveredTop > draggedTop; } const dragTarget = { drop (props, monitor, component) { if (isAbove(monitor, component)) { props.moveRequestGroup(monitor.getItem().requestGroup, props.requestGroup, 1); } else { props.moveRequestGroup(monitor.getItem().requestGroup, props.requestGroup, -1); } }, hover (props, monitor, component) { if (isAbove(monitor, component)) { component.decoratedComponentInstance.setDragDirection(1); } else { component.decoratedComponentInstance.setDragDirection(-1); } } }; function sourceCollect (connect, monitor) { return { connectDragSource: connect.dragSource(), isDragging: monitor.isDragging() }; } function targetCollect (connect, monitor) { return { connectDropTarget: connect.dropTarget(), isDraggingOver: monitor.isOver() }; } const source = DragSource('SIDEBAR_REQUEST_GROUP_ROW', dragSource, sourceCollect)(SidebarRequestGroupRow); const target = DropTarget('SIDEBAR_REQUEST_GROUP_ROW', dragTarget, targetCollect)(source); export default target;