import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import ReactDOM from 'react-dom';
import { DragSource, DropTarget } from 'react-dnd';
import classnames from 'classnames';
import Highlight from '../base/highlight';
import RequestGroupActionsDropdown from '../dropdowns/request-group-actions-dropdown';
import SidebarRequestRow from './sidebar-request-row';
import * as misc from '../../../common/misc';
@autobind
class SidebarRequestGroupRow extends PureComponent {
constructor(props) {
super(props);
this.state = {
dragDirection: 0,
};
}
_setRequestGroupActionsDropdownRef(n) {
this._requestGroupActionsDropdown = n;
}
_setExpandTagRef(n) {
this._expandTag = n;
}
getExpandTag() {
return this._expandTag;
}
_handleCollapse() {
const { requestGroup, handleSetRequestGroupCollapsed, isCollapsed } = this.props;
handleSetRequestGroupCollapsed(requestGroup._id, !isCollapsed);
}
_handleShowActions(e) {
e.preventDefault();
this._requestGroupActionsDropdown.show();
}
setDragDirection(dragDirection) {
if (dragDirection !== this.state.dragDirection) {
this.setState({ dragDirection });
}
}
render() {
const {
connectDragSource,
connectDropTarget,
filter,
moveDoc,
children,
requestGroup,
isCollapsed,
isActive,
handleCreateRequest,
handleCreateRequestGroup,
handleDuplicateRequestGroup,
handleMoveRequestGroup,
isDragging,
isDraggingOver,
workspace,
hotKeyRegistry,
activeEnvironment,
} = 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 (
{!isCollapsed && children.length > 0 ? (
children
) : (
)}
);
}
}
SidebarRequestGroupRow.propTypes = {
// Functions
handleSetRequestGroupCollapsed: PropTypes.func.isRequired,
handleDuplicateRequestGroup: PropTypes.func.isRequired,
handleMoveRequestGroup: PropTypes.func.isRequired,
moveDoc: PropTypes.func.isRequired,
handleActivateRequest: PropTypes.func.isRequired,
handleCreateRequest: PropTypes.func.isRequired,
handleCreateRequestGroup: PropTypes.func.isRequired,
// Other
filter: PropTypes.string.isRequired,
isActive: PropTypes.bool.isRequired,
isCollapsed: PropTypes.bool.isRequired,
workspace: PropTypes.object.isRequired,
requestGroup: PropTypes.object.isRequired,
hotKeyRegistry: PropTypes.object.isRequired,
// React DnD
isDragging: PropTypes.bool,
isDraggingOver: PropTypes.bool,
connectDragSource: PropTypes.func,
connectDropTarget: PropTypes.func,
// Optional
children: PropTypes.node,
activeEnvironment: PropTypes.object,
};
/**
* Implements the drag source contract.
*/
const dragSource = {
beginDrag(props) {
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;
}
function isOnExpandTag(monitor, component) {
const rect = component.getExpandTag().getBoundingClientRect();
const pointer = monitor.getClientOffset();
return (
rect.left <= pointer.x &&
pointer.x <= rect.right &&
rect.top <= pointer.y &&
pointer.y <= rect.bottom
);
}
const dragTarget = {
drop(props, monitor, component) {
const movingDoc = monitor.getItem().requestGroup || monitor.getItem().request;
const parentId = props.requestGroup.parentId;
const targetId = props.requestGroup._id;
if (isAbove(monitor, component)) {
props.moveDoc(movingDoc, parentId, targetId, 1);
} else {
props.moveDoc(movingDoc, parentId, targetId, -1);
}
},
hover(props, monitor, component) {
if (props.isCollapsed && isOnExpandTag(monitor, component)) {
component.props.handleSetRequestGroupCollapsed(props.requestGroup._id, false);
component.setDragDirection(0);
} else if (isAbove(monitor, component)) {
component.setDragDirection(1);
} else {
component.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_ROW', dragSource, sourceCollect)(SidebarRequestGroupRow);
export default DropTarget('SIDEBAR_REQUEST_ROW', dragTarget, targetCollect)(source);