Skip to content

Commit e5db80f

Browse files
authored
Simplify drag and drop integrations (#2126)
* Simplify drag and drop integrations * Fix lnt issues * Remove eslint for sonar
1 parent d2a7378 commit e5db80f

File tree

6 files changed

+106
-101
lines changed

6 files changed

+106
-101
lines changed

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,15 @@ import { Experiment, Column } from 'dvc/src/experiments/webview/contract'
44
import { HeaderGroup } from 'react-table'
55
import { TableHeader } from './TableHeader'
66
import styles from './styles.module.scss'
7-
import {
8-
OnDragOver,
9-
OnDragStart,
10-
OnDrop
11-
} from '../../../shared/components/dragDrop/DragDropWorkbench'
7+
import { DragFunction } from '../../../shared/components/dragDrop/Draggable'
128

139
export const MergedHeaderGroups: React.FC<{
1410
headerGroup: HeaderGroup<Experiment>
1511
columns: HeaderGroup<Experiment>[]
1612
orderedColumns: Column[]
17-
onDragUpdate: OnDragOver
18-
onDragStart: OnDragStart
19-
onDragEnd: OnDrop
13+
onDragUpdate: DragFunction
14+
onDragStart: DragFunction
15+
onDragEnd: DragFunction
2016
firstExpColumnCellId: string
2117
setExpColumnNeedsShadow: (needsShadow: boolean) => void
2218
root: HTMLElement | null
@@ -45,7 +41,7 @@ export const MergedHeaderGroups: React.FC<{
4541
orderedColumns={orderedColumns}
4642
column={column}
4743
columns={columns}
48-
onDragOver={onDragUpdate}
44+
onDragEnter={onDragUpdate}
4945
onDragStart={onDragStart}
5046
onDrop={onDragEnd}
5147
root={root}

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Experiment } from 'dvc/src/experiments/webview/contract'
22
import cx from 'classnames'
3-
import React, { useRef } from 'react'
3+
import React, { DragEvent, useRef } from 'react'
44
import { useSelector } from 'react-redux'
55
import { HeaderGroup, TableInstance } from 'react-table'
66
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
@@ -12,10 +12,7 @@ import { useColumnOrder } from '../../hooks/useColumnOrder'
1212
import { ExperimentsState } from '../../store'
1313
import { sendMessage } from '../../../shared/vscode'
1414
import { leafColumnIds, reorderColumnIds } from '../../util/columns'
15-
import {
16-
OnDragOver,
17-
OnDragStart
18-
} from '../../../shared/components/dragDrop/DragDropWorkbench'
15+
import { DragFunction } from '../../../shared/components/dragDrop/Draggable'
1916
import { getSelectedForPlotsCount } from '../../util/rows'
2017
interface TableHeadProps {
2118
instance: TableInstance<Experiment>
@@ -46,8 +43,10 @@ export const TableHead = ({
4643
const fullColumnOrder = useRef<string[]>()
4744
const draggingIds = useRef<string[]>()
4845

49-
const onDragStart: OnDragStart = draggedId => {
50-
const displacerHeader = allHeaders.find(header => header.id === draggedId)
46+
const onDragStart: DragFunction = ({ currentTarget }) => {
47+
const displacerHeader = allHeaders.find(
48+
header => header.id === currentTarget.id
49+
)
5150
if (displacerHeader) {
5251
draggingIds.current = leafColumnIds(displacerHeader)
5352
fullColumnOrder.current = allColumns.map(({ id }) => id)
@@ -65,10 +64,10 @@ export const TableHead = ({
6564
displacedHeader && cb(displacedHeader)
6665
}
6766

68-
const onDragUpdate: OnDragOver = (_, draggedOverId: string) => {
67+
const onDragUpdate = (e: DragEvent<HTMLElement>) => {
6968
const displacer = draggingIds.current
7069
displacer &&
71-
findDisplacedHeader(draggedOverId, displacedHeader => {
70+
findDisplacedHeader(e.currentTarget.id, displacedHeader => {
7271
const displaced = leafColumnIds(displacedHeader)
7372
if (!displaced.some(id => displacer.includes(id))) {
7473
fullColumnOrder.current &&

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

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@ import { ContextMenu } from '../../../shared/components/contextMenu/ContextMenu'
1616
import { ExperimentsState } from '../../store'
1717
import {
1818
Draggable,
19-
OnDragOver,
20-
OnDragStart,
21-
OnDrop
22-
} from '../../../shared/components/dragDrop/DragDropWorkbench'
19+
DragFunction
20+
} from '../../../shared/components/dragDrop/Draggable'
2321
import { MessagesMenu } from '../../../shared/components/messagesMenu/MessagesMenu'
2422
import { MessagesMenuOptionProps } from '../../../shared/components/messagesMenu/MessagesMenuOption'
2523
import { IconMenu } from '../../../shared/components/iconMenu/IconMenu'
@@ -40,10 +38,10 @@ const possibleOrders = {
4038
export const ColumnDragHandle: React.FC<{
4139
disabled: boolean
4240
column: HeaderGroup<Experiment>
43-
onDragOver: OnDragOver
44-
onDragStart: OnDragStart
45-
onDrop: OnDrop
46-
}> = ({ disabled, column, onDragOver, onDragStart, onDrop }) => {
41+
onDragEnter: DragFunction
42+
onDragStart: DragFunction
43+
onDrop: DragFunction
44+
}> = ({ disabled, column, onDragEnter, onDragStart, onDrop }) => {
4745
const DropTarget = <span>{column?.name}</span>
4846

4947
return (
@@ -61,7 +59,7 @@ export const ColumnDragHandle: React.FC<{
6159
disabled={disabled}
6260
group={'experiment-table'}
6361
dropTarget={DropTarget}
64-
onDragOver={onDragOver}
62+
onDragEnter={onDragEnter}
6563
onDragStart={onDragStart}
6664
onDrop={onDrop}
6765
>
@@ -153,9 +151,9 @@ const TableHeaderCellContents: React.FC<{
153151
hasFilter: boolean
154152
isDraggable: boolean
155153
menuSuppressed: boolean
156-
onDragOver: OnDragOver
157-
onDragStart: OnDragStart
158-
onDrop: OnDrop
154+
onDragEnter: DragFunction
155+
onDragStart: DragFunction
156+
onDrop: DragFunction
159157
canResize: boolean
160158
setMenuSuppressed: (menuSuppressed: boolean) => void
161159
resizerHeight: string
@@ -166,7 +164,7 @@ const TableHeaderCellContents: React.FC<{
166164
hasFilter,
167165
isDraggable,
168166
menuSuppressed,
169-
onDragOver,
167+
onDragEnter,
170168
onDragStart,
171169
onDrop,
172170
canResize,
@@ -181,7 +179,7 @@ const TableHeaderCellContents: React.FC<{
181179
<ColumnDragHandle
182180
column={column}
183181
disabled={!isDraggable || menuSuppressed}
184-
onDragOver={onDragOver}
182+
onDragEnter={onDragEnter}
185183
onDragStart={onDragStart}
186184
onDrop={onDrop}
187185
/>
@@ -207,9 +205,9 @@ const TableHeaderCell: React.FC<{
207205
sortEnabled: boolean
208206
menuDisabled?: boolean
209207
menuContent?: React.ReactNode
210-
onDragOver: OnDragOver
211-
onDragStart: OnDragStart
212-
onDrop: OnDrop
208+
onDragEnter: DragFunction
209+
onDragStart: DragFunction
210+
onDrop: DragFunction
213211
firstExpColumnCellId: string
214212
setExpColumnNeedsShadow: (needsShadow: boolean) => void
215213
root: HTMLElement | null
@@ -222,7 +220,7 @@ const TableHeaderCell: React.FC<{
222220
sortEnabled,
223221
menuContent,
224222
menuDisabled,
225-
onDragOver,
223+
onDragEnter,
226224
onDragStart,
227225
onDrop,
228226
root,
@@ -250,7 +248,7 @@ const TableHeaderCell: React.FC<{
250248
hasFilter={hasFilter}
251249
isDraggable={isDraggable}
252250
menuSuppressed={menuSuppressed}
253-
onDragOver={onDragOver}
251+
onDragEnter={onDragEnter}
254252
onDragStart={onDragStart}
255253
onDrop={onDrop}
256254
canResize={canResize}
@@ -293,9 +291,9 @@ interface TableHeaderProps {
293291
column: HeaderGroup<Experiment>
294292
columns: HeaderGroup<Experiment>[]
295293
orderedColumns: Column[]
296-
onDragOver: OnDragOver
297-
onDragStart: OnDragStart
298-
onDrop: OnDrop
294+
onDragEnter: DragFunction
295+
onDragStart: DragFunction
296+
onDrop: DragFunction
299297
firstExpColumnCellId: string
300298
setExpColumnNeedsShadow: (needsShadow: boolean) => void
301299
root: HTMLElement | null
@@ -305,7 +303,7 @@ export const TableHeader: React.FC<TableHeaderProps> = ({
305303
column,
306304
columns,
307305
orderedColumns,
308-
onDragOver,
306+
onDragEnter,
309307
onDragStart,
310308
onDrop,
311309
root,
@@ -359,7 +357,7 @@ export const TableHeader: React.FC<TableHeaderProps> = ({
359357
sortOrder={sortOrder}
360358
sortEnabled={isSortable}
361359
hasFilter={hasFilter}
362-
onDragOver={onDragOver}
360+
onDragEnter={onDragEnter}
363361
onDragStart={onDragStart}
364362
onDrop={onDrop}
365363
menuDisabled={!isSortable && column.group !== ColumnType.PARAMS}

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

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import React, {
44
useEffect,
55
useState,
66
useRef,
7-
DragEventHandler,
87
CSSProperties
98
} from 'react'
109
import { useDispatch, useSelector } from 'react-redux'
1110
import { DragEnterDirection, getDragEnterDirection } from './util'
1211
import { changeRef } from './dragDropSlice'
1312
import styles from './styles.module.scss'
13+
import { DropTarget } from './DropTarget'
1414
import { getIDIndex, getIDWithoutIndex } from '../../../util/ids'
1515
import { Any } from '../../../util/objects'
1616
import { PlotsState } from '../../../plots/store'
@@ -38,25 +38,6 @@ export type OnDrop = (
3838
groupId: string,
3939
position: number
4040
) => void
41-
42-
export const makeTarget = (
43-
dropTarget: JSX.Element,
44-
handleDragOver: DragEventHandler<HTMLElement>,
45-
handleOnDrop: DragEventHandler<HTMLElement>,
46-
id: string,
47-
className?: string
48-
) => (
49-
<div
50-
data-testid="drop-target"
51-
key="drop-target"
52-
onDragOver={handleDragOver}
53-
onDrop={handleOnDrop}
54-
id={`${id}__drop`}
55-
className={className}
56-
>
57-
{dropTarget}
58-
</div>
59-
)
6041
interface DragDropContainerProps {
6142
order: string[]
6243
setOrder: (order: string[]) => void
@@ -253,20 +234,26 @@ export const DragDropContainer: React.FC<DragDropContainerProps> = ({
253234
/>
254235
)
255236

256-
const createItemWithDropTarget = (id: string, item: JSX.Element) => {
257-
const isEnteringRight = direction === DragEnterDirection.RIGHT
258-
const targetClassName = shouldShowOnDrag
237+
const getDropTargetClassNames = (isEnteringRight: boolean) =>
238+
shouldShowOnDrag
259239
? cx(styles.dropTargetWhenShowingOnDrag, {
260240
[styles.dropTargetWhenShowingOnDragLeft]: !isEnteringRight,
261241
[styles.dropTargetWhenShowingOnDragRight]: isEnteringRight
262242
})
263243
: undefined
264-
const target = makeTarget(
265-
dropTarget,
266-
handleDragOver,
267-
handleOnDrop,
268-
id,
269-
targetClassName
244+
245+
const createItemWithDropTarget = (id: string, item: JSX.Element) => {
246+
const isEnteringRight = direction === DragEnterDirection.RIGHT
247+
const target = (
248+
<DropTarget
249+
key="drop-target"
250+
onDragOver={handleDragOver}
251+
onDrop={handleOnDrop}
252+
id={id}
253+
className={getDropTargetClassNames(isEnteringRight)}
254+
>
255+
{dropTarget}
256+
</DropTarget>
270257
)
271258
const itemWithTag = shouldShowOnDrag ? (
272259
<div key="item" {...item.props} />
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
11
import React, { DragEvent } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
3-
import { makeTarget } from './DragDropContainer'
43
import { setGroup } from './dragDropSlice'
4+
import { DropTarget } from './DropTarget'
55
import { ExperimentsState } from '../../../experiments/store'
66

7-
export type OnDrop = (draggedId: string, draggedOverId: string) => void
8-
export type OnDragStart = (draggedId: string) => void
9-
export type OnDragOver = (draggedId: string, draggedOverId: string) => void
7+
export type DragFunction = (e: DragEvent<HTMLElement>) => void
108

119
export interface DraggableProps {
1210
id: string
1311
group: string
1412
disabled: boolean
15-
dropTarget: JSX.Element
1613
children: JSX.Element
17-
onDrop?: OnDrop
18-
onDragStart?: OnDragStart
19-
onDragOver?: OnDragOver
14+
dropTarget: JSX.Element
15+
onDrop: DragFunction
16+
onDragStart: DragFunction
17+
onDragEnter: DragFunction
2018
}
2119

2220
export const Draggable: React.FC<DraggableProps> = ({
@@ -26,16 +24,13 @@ export const Draggable: React.FC<DraggableProps> = ({
2624
disabled,
2725
dropTarget,
2826
onDrop,
29-
onDragOver,
27+
onDragEnter,
3028
onDragStart
31-
// eslint-disable-next-line sonarjs/cognitive-complexity
3229
}) => {
33-
const groupStates = useSelector(
34-
(state: ExperimentsState) => state.dragAndDrop.groups
30+
const groupState = useSelector(
31+
(state: ExperimentsState) => state.dragAndDrop.groups[group] || {}
3532
)
3633
const dispatch = useDispatch()
37-
38-
const groupState = groupStates[group] || {}
3934
const { draggedOverId, draggedId } = groupState
4035

4136
const modifyGroup = (id: string) => {
@@ -54,15 +49,10 @@ export const Draggable: React.FC<DraggableProps> = ({
5449
const { id } = e.currentTarget
5550
e.dataTransfer.effectAllowed = 'move'
5651
e.dataTransfer.dropEffect = 'move'
52+
e.dataTransfer.setData('itemId', id)
53+
e.dataTransfer.setData('group', group)
5754
modifyGroup(id)
58-
onDragStart?.(id)
59-
}
60-
61-
const handleOnDrop = () => {
62-
!disabled &&
63-
draggedId &&
64-
draggedOverId &&
65-
onDrop?.(draggedId, draggedOverId)
55+
onDragStart(e)
6656
}
6757

6858
const handleDragEnter = (e: DragEvent<HTMLElement>) => {
@@ -71,7 +61,7 @@ export const Draggable: React.FC<DraggableProps> = ({
7161

7262
if (id !== draggedId && id !== draggedOverId) {
7363
modifyGroup(id)
74-
onDragOver?.(draggedId, id)
64+
onDragEnter(e)
7565
}
7666
}
7767
}
@@ -93,21 +83,29 @@ export const Draggable: React.FC<DraggableProps> = ({
9383
)
9484
}
9585

96-
const item = (
86+
if (dropTarget && id === draggedOverId) {
87+
return (
88+
<DropTarget
89+
onDragOver={handleDragOver}
90+
onDrop={onDrop}
91+
id={id}
92+
key="drop-target"
93+
>
94+
{dropTarget}
95+
</DropTarget>
96+
)
97+
}
98+
99+
return (
97100
<children.type
98101
{...children.props}
99102
id={id}
100103
onDragStart={handleDragStart}
101104
onDragEnd={handleDragEnd}
102105
onDragOver={handleDragOver}
103106
onDragEnter={handleDragEnter}
104-
onDrop={handleOnDrop}
107+
onDrop={onDrop}
105108
draggable={!disabled}
106109
/>
107110
)
108-
if (id === draggedOverId) {
109-
return makeTarget(dropTarget, handleDragOver, handleOnDrop, id)
110-
}
111-
112-
return item
113111
}

0 commit comments

Comments
 (0)