1717
1818import React from "react" ;
1919import PropTypes from "prop-types" ;
20- import { DragSource } from "react-dnd" ;
20+ import { DragSource , DropTarget } from "react-dnd" ;
2121import classNames from "classnames" ;
2222import { modifier } from "modifier-keys" ;
2323import Callstack from "../Callstack" ;
@@ -28,20 +28,89 @@ import MoreButton from "../ActionButtons/More";
2828import "./style.css" ;
2929
3030export const Type = "test" ;
31+
3132const testSource = {
3233 beginDrag ( props ) {
3334 return {
3435 id : props . test . id ,
35- suite : props . suite . id
36+ index : props . index ,
37+ test : props . test ,
38+ suite : props . suite
3639 } ;
40+ } ,
41+ isDragging ( props , monitor ) {
42+ return ( props . test . id === monitor . getItem ( ) . id ) ;
3743 }
3844} ;
39- function collect ( connect , monitor ) {
45+
46+ function collectSource ( connect , monitor ) {
4047 return {
4148 connectDragSource : connect . dragSource ( ) ,
4249 isDragging : monitor . isDragging ( )
4350 } ;
4451}
52+
53+ const testTarget = {
54+ canDrop ( props , monitor ) {
55+ const test = monitor . getItem ( ) . test ;
56+ const suite = props . suite ;
57+ return ! suite . containsTest ( test ) ;
58+ } ,
59+ hover ( props , monitor , component ) {
60+ // check if they are different suites
61+ const dragged = monitor . getItem ( ) ;
62+ if ( monitor . canDrop ( ) && props . suite !== dragged . suite ) {
63+ dragged . suite . removeTestCase ( dragged . test ) ;
64+ props . suite . addTestCase ( dragged . test ) ;
65+ dragged . suite = props . suite ;
66+ dragged . index = props . suite . tests . length - 1 ;
67+ return ;
68+ }
69+ const dragIndex = dragged . index ;
70+ const hoverIndex = props . index ;
71+
72+ // Don't replace items with themselves
73+ if ( dragIndex === hoverIndex ) {
74+ return ;
75+ }
76+
77+ // Determine rectangle on screen
78+ const hoverBoundingRect = component . decoratedComponentInstance . node . getBoundingClientRect ( ) ;
79+
80+ // Get vertical middle
81+ const hoverMiddleY = ( hoverBoundingRect . bottom - hoverBoundingRect . top ) / 2 ;
82+
83+ // Determine mouse position
84+ const clientOffset = monitor . getClientOffset ( ) ;
85+
86+ // Get pixels to the top
87+ const hoverClientY = clientOffset . y - hoverBoundingRect . top ;
88+
89+ // Only perform the move when the mouse has crossed half of the items height
90+ // When dragging downwards, only move when the cursor is below 50%
91+ // When dragging upwards, only move when the cursor is above 50%
92+
93+ // Dragging downwards
94+ if ( dragIndex < hoverIndex && hoverClientY < hoverMiddleY ) {
95+ return ;
96+ }
97+
98+ // Dragging upwards
99+ if ( dragIndex > hoverIndex && hoverClientY > hoverMiddleY ) {
100+ return ;
101+ }
102+
103+ props . swapTests ( dragIndex , hoverIndex ) ;
104+
105+ // save time on index lookups
106+ monitor . getItem ( ) . index = hoverIndex ;
107+ }
108+ } ;
109+
110+ const collectTarget = ( connect ) => ( {
111+ connectDropTarget : connect . dropTarget ( )
112+ } ) ;
113+
45114export default class Test extends React . Component {
46115 static propTypes = {
47116 className : PropTypes . string ,
@@ -58,6 +127,7 @@ export default class Test extends React.Component {
58127 selectTest : PropTypes . func . isRequired ,
59128 renameTest : PropTypes . func ,
60129 removeTest : PropTypes . func ,
130+ connectDropTarget : PropTypes . func ,
61131 connectDragSource : PropTypes . func ,
62132 moveSelectionUp : PropTypes . func ,
63133 moveSelectionDown : PropTypes . func ,
@@ -127,7 +197,7 @@ export default class Test extends React.Component {
127197 tabIndex = { this . props . selected ? "0" : "-1" }
128198 onContextMenu = { this . props . onContextMenu }
129199 style = { {
130- display : this . props . isDragging ? "none " : "block "
200+ opacity : this . props . isDragging ? "0 " : "1 "
131201 } } >
132202 < a
133203 ref = { ( button ) => { this . button = button ; } }
@@ -144,7 +214,7 @@ export default class Test extends React.Component {
144214 onClick = { this . handleCallstackClick . bind ( this , this . props . test , this . props . suite ) }
145215 /> : undefined }
146216 </ div > ;
147- return ( this . props . connectDragSource ? this . props . connectDragSource ( rendered ) : rendered ) ;
217+ return ( this . props . connectDragSource ? this . props . connectDropTarget ( this . props . connectDragSource ( rendered ) ) : rendered ) ;
148218 }
149219}
150220
@@ -164,4 +234,5 @@ export class MenuTest extends React.Component {
164234 }
165235}
166236
167- export const DraggableTest = DragSource ( Type , testSource , collect ) ( Test ) ;
237+
238+ export const DraggableTest = DropTarget ( Type , testTarget , collectTarget ) ( DragSource ( Type , testSource , collectSource ) ( Test ) ) ;
0 commit comments