oglimmer/linky

View on GitHub
src/components/TreeDropzone.js

Summary

Maintainability
A
0 mins
Test Coverage
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { DropTarget } from 'react-dnd';
import classnames from 'classnames';

import treeState from './TreeState';

const equalOrOnPathToRoot = (dragInProgress, parentNode) => {
  const listOfParents = [parentNode.hierarchyLevelName];
  let parentWalker = parentNode.parent;
  while (parentWalker) {
    listOfParents.push(parentWalker.hierarchyLevelName);
    parentWalker = parentWalker.parent;
  }
  return listOfParents.find(p => dragInProgress === p);
};

const legalDropTarget = (props) => {
  if (!props.dragInProgress) {
    return true;
  }
  const { next, prev, parentNode } = props.ele.dropTargetInfo;
  return !equalOrOnPathToRoot(props.dragInProgress, parentNode)
    && props.dragInProgress !== next
    && props.dragInProgress !== prev;
};

@connect(state => ({
  dragInProgress: state.tagHierarchyData.dragInProgress,
}), () => ({
}))
@DropTarget('link', {
  drop(props) {
    const { next, prev, parentNode } = props.ele.dropTargetInfo;
    return { next, prev, parentNode };
  },
  canDrop(props) {
    return legalDropTarget(props);
  },
}, (conn, monitor) => ({
  connectDropTarget: conn.dropTarget(),
  isOver: monitor.isOver(),
}))
export default class TreeDragableLink extends Component {
  static propTypes = {
    ele: PropTypes.shape().isRequired,
    level: PropTypes.number.isRequired,
    connectDropTarget: PropTypes.func.isRequired,
    paddingLeft: PropTypes.number.isRequired,
    dragInProgress: PropTypes.string,
    isOver: PropTypes.bool.isRequired,
    // ele: PropTypes.shape().isRequired,
    // beginDrag: PropTypes.func.isRequired,
    // endDrag: PropTypes.func.isRequired,
  };
  static defaultProps = {
    dragInProgress: null,
  };

  calcClass() {
    const isLegalDropTarget = legalDropTarget(this.props);
    const hidden = !this.props.dragInProgress || !isLegalDropTarget;
    const dropzoneActiveNew =
      !hidden && !treeState.wasCalled(this.props.ele.hierarchyLevelName);
    if (!hidden) {
      treeState.setCalled(this.props.ele.hierarchyLevelName);
    }
    return classnames({
      link: true,
      dropzoneHidden: hidden,
      dropzoneActive: !hidden && !this.props.isOver,
      dropzoneActiveNew,
      dropzoneOver: !hidden && this.props.isOver,
    });
  }

  calcStyle() {
    return {
      marginLeft: `${this.props.paddingLeft * this.props.level}px`,
    };
  }

  render() {
    return this.props.connectDropTarget(
      <div style={this.calcStyle()} className={this.calcClass()} />,
    );
  }
}