From b9a2f348afddac97406b90dd65a922c7d18ab888 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Fri, 5 Aug 2022 14:10:49 -0400 Subject: [PATCH 1/2] Remove drop targets when exiting a section that is not the starting one --- webview/src/plots/components/App.test.tsx | 35 +++++++++++++++++++ .../templatePlots/TemplatePlots.tsx | 9 ++++- .../components/dragDrop/DragDropContainer.tsx | 31 +++++++++------- .../components/dragDrop/dragDropSlice.ts | 11 +++++- 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/webview/src/plots/components/App.test.tsx b/webview/src/plots/components/App.test.tsx index c763065f48..943a6fc210 100644 --- a/webview/src/plots/components/App.test.tsx +++ b/webview/src/plots/components/App.test.tsx @@ -867,6 +867,41 @@ describe('App', () => { expect(plots[1].style.display).toBe('none') }) + it('should remove the drop target after exiting a section after dragging in and out of it', () => { + renderAppWithOptionalData({ + template: complexTemplatePlotsFixture + }) + + const bottomSection = screen.getByTestId(NewSectionBlock.BOTTOM) + const aSingleViewPlot = screen.getByTestId(join('plot_other', 'plot.tsv')) + + dragAndDrop(aSingleViewPlot, bottomSection) + + const movedPlot = screen.getByTestId(join('plot_other', 'plot.tsv')) + const otherSingleSection = screen.getByTestId(join('plot_logs', 'loss.tsv')) + + dragEnter(movedPlot, otherSingleSection.id, DragEnterDirection.LEFT) + + const topSection = screen.getByTestId('plots-section_template-single_0') + + let topSectionPlots = within(topSection) + .getAllByTestId(/^plot_/) + .map(plot => plot.id) + expect(topSectionPlots.includes('plot-drop-target')).toBe(true) + + const previousSection = screen.getByTestId( + 'plots-section_template-single_2' + ) + act(() => { + previousSection.dispatchEvent(createBubbledEvent('dragenter')) + }) + + topSectionPlots = within(topSection) + .getAllByTestId(/^plot_/) + .map(plot => plot.id) + expect(topSectionPlots.includes('plot-drop-target')).toBe(false) + }) + it('should open a modal with the plot zoomed in when clicking a template plot', () => { renderAppWithOptionalData({ template: complexTemplatePlotsFixture diff --git a/webview/src/plots/components/templatePlots/TemplatePlots.tsx b/webview/src/plots/components/templatePlots/TemplatePlots.tsx index 1e3d64bf63..09feb54621 100644 --- a/webview/src/plots/components/templatePlots/TemplatePlots.tsx +++ b/webview/src/plots/components/templatePlots/TemplatePlots.tsx @@ -5,7 +5,7 @@ import { } from 'dvc/src/plots/webview/contract' import React, { DragEvent, useState, useEffect, useRef } from 'react' import cx from 'classnames' -import { useSelector } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { MessageFromWebviewType } from 'dvc/src/webview/contract' import { AddedSection } from './AddedSection' import { TemplatePlotsGrid } from './TemplatePlotsGrid' @@ -17,6 +17,7 @@ import { shouldUseVirtualizedGrid } from '../util' import { useNbItemsPerRow } from '../../hooks/useNbItemsPerRow' import { PlotsState } from '../../store' import { plotDataStore } from '../plotDataStore' +import { setDraggedOverGroup } from '../../../shared/components/dragDrop/dragDropSlice' export enum NewSectionBlock { TOP = 'drop-section-top', @@ -31,6 +32,7 @@ export const TemplatePlots: React.FC = () => { const [hoveredSection, setHoveredSection] = useState('') const nbItemsPerRow = useNbItemsPerRow(size) const shouldSendMessage = useRef(true) + const dispatch = useDispatch() useEffect(() => { shouldSendMessage.current = false @@ -126,6 +128,10 @@ export const TemplatePlots: React.FC = () => { setSections(updatedSections) } + const handleEnteringSection = (groupId: string) => { + dispatch(setDraggedOverGroup(groupId)) + } + const newDropSection = { acceptedGroups: Object.values(TemplatePlotGroup), hoveredSection, @@ -162,6 +168,7 @@ export const TemplatePlots: React.FC = () => { id={groupId} data-testid={`plots-section_${groupId}`} className={classes} + onDragEnter={() => handleEnteringSection(groupId)} > = ({ const [draggedOverId, setDraggedOverId] = useState('') const [draggedId, setDraggedId] = useState('') const [direction, setDirection] = useState(DragEnterDirection.LEFT) - const { draggedRef } = useSelector((state: PlotsState) => state.dragAndDrop) + const { draggedRef, draggedOverGroup } = useSelector( + (state: PlotsState) => state.dragAndDrop + ) const draggedOverIdTimeout = useRef(0) const dispatch = useDispatch() @@ -198,6 +200,7 @@ export const DragDropContainer: React.FC = ({ ) { setDraggedOverId(id) setDirection(getDragEnterDirection(e)) + dispatch(setDraggedOverGroup(group)) } } } @@ -244,17 +247,19 @@ export const DragDropContainer: React.FC = ({ const createItemWithDropTarget = (id: string, item: JSX.Element) => { const isEnteringRight = direction === DragEnterDirection.RIGHT - const target = ( - - {dropTarget} - - ) + const target = + draggedOverGroup === group || draggedRef?.group === group ? ( + + {dropTarget} + + ) : null + const itemWithTag = shouldShowOnDrag ? (
) : ( diff --git a/webview/src/shared/components/dragDrop/dragDropSlice.ts b/webview/src/shared/components/dragDrop/dragDropSlice.ts index 95596f5874..d9f40ac296 100644 --- a/webview/src/shared/components/dragDrop/dragDropSlice.ts +++ b/webview/src/shared/components/dragDrop/dragDropSlice.ts @@ -18,9 +18,11 @@ export type GroupStates = { export interface DragDropState { draggedRef: DraggedInfo groups: GroupStates + draggedOverGroup: string } export const dragDropInitialState: DragDropState = { + draggedOverGroup: '', draggedRef: undefined, groups: {} } @@ -35,6 +37,12 @@ export const dragDropSlice = createSlice({ draggedRef: action.payload } }, + setDraggedOverGroup: (state, action: PayloadAction) => { + return { + ...state, + draggedOverGroup: action.payload + } + }, setGroup: ( state, action: PayloadAction<{ id: string; group: DragDropGroupState }> @@ -47,6 +55,7 @@ export const dragDropSlice = createSlice({ } }) -export const { changeRef, setGroup } = dragDropSlice.actions +export const { changeRef, setGroup, setDraggedOverGroup } = + dragDropSlice.actions export default dragDropSlice.reducer From c69e1c4a5084e249a8371a5a487f4666a6e0a803 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Fri, 5 Aug 2022 16:27:17 -0400 Subject: [PATCH 2/2] Apply review comments --- webview/src/plots/components/App.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/webview/src/plots/components/App.test.tsx b/webview/src/plots/components/App.test.tsx index 943a6fc210..1fbdbef575 100644 --- a/webview/src/plots/components/App.test.tsx +++ b/webview/src/plots/components/App.test.tsx @@ -872,12 +872,14 @@ describe('App', () => { template: complexTemplatePlotsFixture }) + const movingPlotId = join('plot_other', 'plot.tsv') + const bottomSection = screen.getByTestId(NewSectionBlock.BOTTOM) - const aSingleViewPlot = screen.getByTestId(join('plot_other', 'plot.tsv')) + const aSingleViewPlot = screen.getByTestId(movingPlotId) dragAndDrop(aSingleViewPlot, bottomSection) - const movedPlot = screen.getByTestId(join('plot_other', 'plot.tsv')) + const movedPlot = screen.getByTestId(movingPlotId) const otherSingleSection = screen.getByTestId(join('plot_logs', 'loss.tsv')) dragEnter(movedPlot, otherSingleSection.id, DragEnterDirection.LEFT)