Skip to content

Commit 4afab75

Browse files
authored
table dnd cleanup, reset drop zone on leave (#2965)
1 parent 31386e8 commit 4afab75

File tree

8 files changed

+72
-34
lines changed

8 files changed

+72
-34
lines changed

webview/src/experiments/components/table/Table.test.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
getHeaders,
3131
tableData as sortingTableDataFixture
3232
} from '../../../test/sort'
33-
import { dragAndDrop } from '../../../test/dragDrop'
33+
import { dragAndDrop, dragEnter, dragLeave } from '../../../test/dragDrop'
3434
import { DragEnterDirection } from '../../../shared/components/dragDrop/util'
3535
import { experimentsReducers } from '../../store'
3636
import { customQueries } from '../../../test/queries'
@@ -463,5 +463,29 @@ describe('Table', () => {
463463
headers.indexOf('test')
464464
)
465465
})
466+
467+
it('should remove the drop zone when hovering out a target column header', async () => {
468+
const { getDraggableHeaderFromText } = renderExperimentsTable({
469+
...tableDataFixture
470+
})
471+
472+
await getHeaders()
473+
474+
const startingNode = screen.getByText('process')
475+
const targetNode = getDraggableHeaderFromText('loss')
476+
const header = screen.getByTestId('header-metrics:summary.json:loss')
477+
478+
dragEnter(startingNode, targetNode.id, DragEnterDirection.AUTO)
479+
480+
expect(
481+
header?.classList.contains(styles.headerCellDropTarget)
482+
).toBeTruthy()
483+
484+
dragLeave(targetNode)
485+
486+
expect(
487+
header?.classList.contains(styles.headerCellDropTarget)
488+
).toBeFalsy()
489+
})
466490
})
467491
})

webview/src/experiments/components/table/header/MergeHeaderGroups.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,22 @@ export const MergedHeaderGroups: React.FC<{
1010
headerGroup: HeaderGroup<Experiment>
1111
columns: HeaderGroup<Experiment>[]
1212
orderedColumns: Column[]
13-
onDragUpdate: DragFunction
13+
onDragEnter: DragFunction
1414
onDragStart: DragFunction
1515
onDragEnd: DragFunction
1616
onDrop: DragFunction
17+
onDragLeave: DragFunction
1718
setExpColumnNeedsShadow: (needsShadow: boolean) => void
1819
root: HTMLElement | null
1920
}> = ({
2021
headerGroup,
2122
columns,
2223
orderedColumns,
23-
onDragUpdate,
24+
onDragEnter,
2425
onDragEnd,
2526
onDragStart,
2627
onDrop,
28+
onDragLeave,
2729
root,
2830
setExpColumnNeedsShadow
2931
}) => {
@@ -40,10 +42,11 @@ export const MergedHeaderGroups: React.FC<{
4042
orderedColumns={orderedColumns}
4143
column={column}
4244
columns={columns}
43-
onDragEnter={onDragUpdate}
45+
onDragEnter={onDragEnter}
4446
onDragStart={onDragStart}
4547
onDragEnd={onDragEnd}
4648
onDrop={onDrop}
49+
onDragLeave={onDragLeave}
4750
root={root}
4851
/>
4952
))}

webview/src/experiments/components/table/header/TableHead.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export const TableHead = ({
8282
displacedHeader && cb(displacedHeader)
8383
}
8484

85-
const onDragUpdate = (e: DragEvent<HTMLElement>) => {
85+
const onDragEnter = (e: DragEvent<HTMLElement>) => {
8686
findDisplacedHeader(e.currentTarget.id, displacedHeader => {
8787
if (!isExperimentColumn(displacedHeader.id)) {
8888
dispatch(setDropTarget(displacedHeader.id))
@@ -96,6 +96,12 @@ export const TableHead = ({
9696
dispatch(setDropTarget(''))
9797
}
9898

99+
const onDragLeave = () => {
100+
// note: for this to work it's important to have `pointer-events: none;`
101+
// on text children to avoid duplicate dragEnter and dragLeave events fired
102+
dispatch(setDropTarget(''))
103+
}
104+
99105
const onDrop = () => {
100106
const fullOrder = fullColumnOrder.current
101107
const displacer = draggingIds.current
@@ -130,9 +136,10 @@ export const TableHead = ({
130136
headerGroup={headerGroup}
131137
columns={allHeaders}
132138
onDragStart={onDragStart}
133-
onDragUpdate={onDragUpdate}
139+
onDragEnter={onDragEnter}
134140
onDragEnd={onDragEnd}
135141
onDrop={onDrop}
142+
onDragLeave={onDragLeave}
136143
root={root}
137144
setExpColumnNeedsShadow={setExpColumnNeedsShadow}
138145
/>

webview/src/experiments/components/table/header/TableHeader.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface TableHeaderProps {
1414
onDragEnd: DragFunction
1515
onDragStart: DragFunction
1616
onDrop: DragFunction
17+
onDragLeave: DragFunction
1718
setExpColumnNeedsShadow: (needsShadow: boolean) => void
1819
root: HTMLElement | null
1920
}
@@ -26,6 +27,7 @@ export const TableHeader: React.FC<TableHeaderProps> = ({
2627
onDragEnd,
2728
onDragStart,
2829
onDrop,
30+
onDragLeave,
2931
root,
3032
setExpColumnNeedsShadow
3133
}) => {
@@ -43,6 +45,7 @@ export const TableHeader: React.FC<TableHeaderProps> = ({
4345
onDragEnd={onDragEnd}
4446
onDragStart={onDragStart}
4547
onDrop={onDrop}
48+
onDragLeave={onDragLeave}
4649
root={root}
4750
setExpColumnNeedsShadow={setExpColumnNeedsShadow}
4851
/>

webview/src/experiments/components/table/header/TableHeaderCell.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export const TableHeaderCell: React.FC<{
9393
onDragEnd: DragFunction
9494
onDragStart: DragFunction
9595
onDrop: DragFunction
96+
onDragLeave: DragFunction
9697
setExpColumnNeedsShadow: (needsShadow: boolean) => void
9798
root: HTMLElement | null
9899
}> = ({
@@ -104,6 +105,7 @@ export const TableHeaderCell: React.FC<{
104105
onDragEnd,
105106
onDragStart,
106107
onDrop,
108+
onDragLeave,
107109
root,
108110
setExpColumnNeedsShadow
109111
}) => {
@@ -140,6 +142,7 @@ export const TableHeaderCell: React.FC<{
140142
onDragStart={onDragStart}
141143
onDragEnd={onDragEnd}
142144
onDrop={onDrop}
145+
onDragLeave={onDragLeave}
143146
canResize={canResize}
144147
setMenuSuppressed={setMenuSuppressed}
145148
resizerHeight={resizerHeight}

webview/src/experiments/components/table/header/TableHeaderCellContents.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,16 @@ export const ColumnDragHandle: React.FC<{
3535
onDragStart: DragFunction
3636
onDrop: DragFunction
3737
onDragEnd: DragFunction
38-
}> = ({ disabled, column, onDragEnter, onDragStart, onDragEnd, onDrop }) => {
39-
const DropTarget = <span>{column?.name}</span>
40-
38+
onDragLeave: DragFunction
39+
}> = ({
40+
disabled,
41+
column,
42+
onDragEnter,
43+
onDragStart,
44+
onDragEnd,
45+
onDrop,
46+
onDragLeave
47+
}) => {
4148
return (
4249
<span
4350
data-testid="rendered-header"
@@ -49,11 +56,11 @@ export const ColumnDragHandle: React.FC<{
4956
id={column.id}
5057
disabled={disabled}
5158
group={'experiment-table'}
52-
dropTarget={DropTarget}
5359
onDragEnter={onDragEnter}
5460
onDragStart={onDragStart}
5561
onDragEnd={onDragEnd}
5662
onDrop={onDrop}
63+
onDragLeave={onDragLeave}
5764
>
5865
<span>{column?.render('Header')}</span>
5966
</Draggable>
@@ -72,6 +79,7 @@ export const TableHeaderCellContents: React.FC<{
7279
onDragEnd: DragFunction
7380
onDragStart: DragFunction
7481
onDrop: DragFunction
82+
onDragLeave: DragFunction
7583
canResize: boolean
7684
setMenuSuppressed: (menuSuppressed: boolean) => void
7785
resizerHeight: string
@@ -86,6 +94,7 @@ export const TableHeaderCellContents: React.FC<{
8694
onDragEnd,
8795
onDragStart,
8896
onDrop,
97+
onDragLeave,
8998
canResize,
9099
setMenuSuppressed,
91100
resizerHeight
@@ -117,6 +126,7 @@ export const TableHeaderCellContents: React.FC<{
117126
onDragStart={onDragStart}
118127
onDrop={onDrop}
119128
onDragEnd={onDragEnd}
129+
onDragLeave={onDragLeave}
120130
/>
121131
{canResize && (
122132
<div

webview/src/experiments/components/table/styles.module.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,11 @@ $bullet-size: calc(var(--design-unit) * 4px);
349349
@extend %truncateLeftParent;
350350
direction: rtl;
351351
opacity: 0.6;
352+
353+
span {
354+
// to prevent extra dragLeave and dragEnter fired
355+
pointer-events: none;
356+
}
352357
}
353358
.cellContents {
354359
@extend %truncateLeftChild;

webview/src/shared/components/dragDrop/Draggable.tsx

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { DragEvent } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
33
import { setGroup } from './dragDropSlice'
4-
import { DropTarget } from './DropTarget'
54
import { ExperimentsState } from '../../../experiments/store'
65

76
export type DragFunction = (e: DragEvent<HTMLElement>) => void
@@ -11,29 +10,29 @@ export interface DraggableProps {
1110
group: string
1211
disabled: boolean
1312
children: JSX.Element
14-
dropTarget: JSX.Element
1513
onDrop: DragFunction
1614
onDragStart: DragFunction
1715
onDragEnter: DragFunction
1816
onDragEnd: DragFunction
17+
onDragLeave: DragFunction
1918
}
2019

2120
export const Draggable: React.FC<DraggableProps> = ({
2221
id,
2322
group,
2423
children,
2524
disabled,
26-
dropTarget,
2725
onDrop,
2826
onDragEnter,
2927
onDragStart,
30-
onDragEnd
28+
onDragEnd,
29+
onDragLeave
3130
}) => {
3231
const groupState = useSelector(
3332
(state: ExperimentsState) => state.dragAndDrop.groups[group] || {}
3433
)
3534
const dispatch = useDispatch()
36-
const { draggedOverId, draggedId } = groupState
35+
const { draggedId } = groupState
3736

3837
const modifyGroup = (id: string) => {
3938
dispatch(
@@ -60,9 +59,7 @@ export const Draggable: React.FC<DraggableProps> = ({
6059
const handleDragEnter = (e: DragEvent<HTMLElement>) => {
6160
if (draggedId) {
6261
const { id } = e.currentTarget
63-
64-
if (id !== draggedId && id !== draggedOverId) {
65-
modifyGroup(id)
62+
if (id !== draggedId) {
6663
onDragEnter(e)
6764
}
6865
}
@@ -77,33 +74,19 @@ export const Draggable: React.FC<DraggableProps> = ({
7774
setGroup({
7875
group: {
7976
...groupState,
80-
draggedId: undefined,
81-
draggedOverId: undefined
77+
draggedId: undefined
8278
},
8379
id: group
8480
})
8581
)
8682
onDragEnd(e)
8783
}
8884

89-
if (dropTarget && id === draggedOverId) {
90-
return (
91-
<DropTarget
92-
onDragOver={handleDragOver}
93-
onDragEnd={onDragEnd}
94-
onDrop={onDrop}
95-
id={id}
96-
key="drop-target"
97-
>
98-
{dropTarget}
99-
</DropTarget>
100-
)
101-
}
102-
10385
return (
10486
<children.type
10587
{...children.props}
10688
id={id}
89+
onDragLeave={onDragLeave}
10790
onDragStart={handleDragStart}
10891
onDragEnd={handleDragEnd}
10992
onDragOver={handleDragOver}

0 commit comments

Comments
 (0)