From 725deb5652cc6f0f3fce89638e30c42a69e22e3b Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 25 Jul 2022 14:52:23 -0400 Subject: [PATCH 1/5] Prefix plots store export to avoid name clashing with the experiments store --- webview/src/plots/components/App.test.tsx | 4 ++-- webview/src/plots/components/App.tsx | 6 +++--- webview/src/plots/components/Plots.tsx | 10 +++++----- .../components/checkpointPlots/CheckpointPlot.tsx | 4 ++-- .../components/checkpointPlots/CheckpointPlots.tsx | 4 ++-- .../checkpointPlots/CheckpointPlotsWrapper.tsx | 4 ++-- .../comparisonTable/ComparisonTable.test.tsx | 4 ++-- .../components/comparisonTable/ComparisonTable.tsx | 6 +++--- .../components/comparisonTable/ComparisonTableHead.tsx | 4 ++-- .../comparisonTable/ComparisonTableRow.test.tsx | 4 ++-- .../components/comparisonTable/ComparisonTableRow.tsx | 4 ++-- .../comparisonTable/ComparisonTableWrapper.tsx | 4 ++-- webview/src/plots/components/ribbon/Ribbon.tsx | 4 ++-- .../plots/components/templatePlots/AddedSection.tsx | 4 ++-- .../plots/components/templatePlots/TemplatePlots.tsx | 4 ++-- .../components/templatePlots/TemplatePlotsWrapper.tsx | 4 ++-- webview/src/plots/index.tsx | 4 ++-- webview/src/plots/store.ts | 10 +++++----- .../shared/components/dragDrop/DragDropContainer.tsx | 4 ++-- webview/src/stories/ComparisonTable.stories.tsx | 4 ++-- webview/src/stories/Plots.stories.tsx | 4 ++-- 21 files changed, 50 insertions(+), 50 deletions(-) diff --git a/webview/src/plots/components/App.test.tsx b/webview/src/plots/components/App.test.tsx index f2904bfd3a..f9a7358b33 100644 --- a/webview/src/plots/components/App.test.tsx +++ b/webview/src/plots/components/App.test.tsx @@ -36,7 +36,7 @@ import { act } from 'react-dom/test-utils' import { App } from './App' import { NewSectionBlock } from './templatePlots/TemplatePlots' import { SectionDescription } from './PlotsContainer' -import { storeReducers } from '../store' +import { plotsReducers } from '../store' import { vsCodeApi } from '../../shared/api' import { createBubbledEvent, dragAndDrop, dragEnter } from '../../test/dragDrop' import { DragEnterDirection } from '../../shared/components/dragDrop/util' @@ -113,7 +113,7 @@ describe('App', () => { } const renderAppWithOptionalData = (data?: PlotsData) => { - const store = configureStore({ reducer: storeReducers }) + const store = configureStore({ reducer: plotsReducers }) render( diff --git a/webview/src/plots/components/App.tsx b/webview/src/plots/components/App.tsx index 79d911d905..33b3050dde 100644 --- a/webview/src/plots/components/App.tsx +++ b/webview/src/plots/components/App.tsx @@ -30,12 +30,12 @@ import { updateHasSelectedPlots, updateSelectedRevisions } from './webviewSlice' -import { AppDispatch } from '../store' +import { PlotsDispatch } from '../store' import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging' const dispatchCollapsedSections = ( sections: SectionCollapsed, - dispatch: AppDispatch + dispatch: PlotsDispatch ) => { if (sections) { dispatch(setCheckpointPlotsCollapsed(sections[Section.CHECKPOINT_PLOTS])) @@ -46,7 +46,7 @@ const dispatchCollapsedSections = ( export const feedStore = ( data: MessageToWebview, - dispatch: AppDispatch + dispatch: PlotsDispatch // eslint-disable-next-line sonarjs/cognitive-complexity ) => { if (data.data) { diff --git a/webview/src/plots/components/Plots.tsx b/webview/src/plots/components/Plots.tsx index 8658705a41..e2f1f8e8e5 100644 --- a/webview/src/plots/components/Plots.tsx +++ b/webview/src/plots/components/Plots.tsx @@ -11,7 +11,7 @@ import { EmptyState } from '../../shared/components/emptyState/EmptyState' import { Modal } from '../../shared/components/modal/Modal' import { WebviewWrapper } from '../../shared/components/webviewWrapper/WebviewWrapper' import { GetStarted } from '../../shared/components/getStarted/GetStarted' -import { RootState } from '../store' +import { PlotsState } from '../store' // eslint-disable-next-line sonarjs/cognitive-complexity const PlotsContent = () => { @@ -22,15 +22,15 @@ const PlotsContent = () => { hasSelectedPlots, selectedRevisions, zoomedInPlot - } = useSelector((state: RootState) => state.webview) + } = useSelector((state: PlotsState) => state.webview) const hasCheckpointData = useSelector( - (state: RootState) => state.checkpoint.hasData + (state: PlotsState) => state.checkpoint.hasData ) const hasComparisonData = useSelector( - (state: RootState) => state.comparison.hasData + (state: PlotsState) => state.comparison.hasData ) const hasTemplateData = useSelector( - (state: RootState) => state.template.hasData + (state: PlotsState) => state.template.hasData ) if (!hasData) { diff --git a/webview/src/plots/components/checkpointPlots/CheckpointPlot.tsx b/webview/src/plots/components/checkpointPlots/CheckpointPlot.tsx index ec09d3c5a8..b062b9bf11 100644 --- a/webview/src/plots/components/checkpointPlots/CheckpointPlot.tsx +++ b/webview/src/plots/components/checkpointPlots/CheckpointPlot.tsx @@ -6,7 +6,7 @@ import { ZoomablePlot } from '../ZoomablePlot' import styles from '../styles.module.scss' import { withScale } from '../../../util/styles' import { plotDataStore } from '../plotDataStore' -import { RootState } from '../../store' +import { PlotsState } from '../../store' interface CheckpointPlotProps { id: string @@ -18,7 +18,7 @@ export const CheckpointPlot: React.FC = ({ colors }) => { const plotSnapshot = useSelector( - (state: RootState) => state.checkpoint.plotsSnapshots[id] + (state: PlotsState) => state.checkpoint.plotsSnapshots[id] ) const [plot, setPlot] = useState(plotDataStore.checkpoint[id]) const spec = useMemo(() => (id && createSpec(id, colors)) || {}, [id, colors]) diff --git a/webview/src/plots/components/checkpointPlots/CheckpointPlots.tsx b/webview/src/plots/components/checkpointPlots/CheckpointPlots.tsx index 9a0493ec07..9f6e0b385d 100644 --- a/webview/src/plots/components/checkpointPlots/CheckpointPlots.tsx +++ b/webview/src/plots/components/checkpointPlots/CheckpointPlots.tsx @@ -16,7 +16,7 @@ import { DropTarget } from '../DropTarget' import { VirtualizedGrid } from '../../../shared/components/virtualizedGrid/VirtualizedGrid' import { shouldUseVirtualizedGrid } from '../util' import { useNbItemsPerRow } from '../../hooks/useNbItemsPerRow' -import { RootState } from '../../store' +import { PlotsState } from '../../store' interface CheckpointPlotsProps { plotsIds: string[] @@ -28,7 +28,7 @@ export const CheckpointPlots: React.FC = ({ colors }) => { const [order, setOrder] = useState(plotsIds) - const { size } = useSelector((state: RootState) => state.checkpoint) + const { size } = useSelector((state: PlotsState) => state.checkpoint) const nbItemsPerRow = useNbItemsPerRow(size) useEffect(() => { diff --git a/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx b/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx index 7e22f90f12..5f6e824997 100644 --- a/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx +++ b/webview/src/plots/components/checkpointPlots/CheckpointPlotsWrapper.tsx @@ -6,12 +6,12 @@ import { CheckpointPlots } from './CheckpointPlots' import { changeSize } from './checkpointPlotsSlice' import { PlotsContainer } from '../PlotsContainer' import { sendMessage } from '../../../shared/vscode' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export const CheckpointPlotsWrapper: React.FC = () => { const dispatch = useDispatch() const { plotsIds, size, selectedMetrics, isCollapsed, colors } = useSelector( - (state: RootState) => state.checkpoint + (state: PlotsState) => state.checkpoint ) const [metrics, setMetrics] = useState([]) const [selectedPlots, setSelectedPlots] = useState([]) diff --git a/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx b/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx index 6719a29d96..22c91199c4 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTable.test.tsx @@ -26,7 +26,7 @@ import { } from '../../../test/dragDrop' import { vsCodeApi } from '../../../shared/api' import { DragEnterDirection } from '../../../shared/components/dragDrop/util' -import { storeReducers } from '../../store' +import { plotsReducers } from '../../store' import { webviewInitialState } from '../webviewSlice' const getHeaders = () => screen.getAllByRole('columnheader') @@ -70,7 +70,7 @@ describe('ComparisonTable', () => { zoomedInPlot: undefined } }, - reducer: storeReducers + reducer: plotsReducers })} > diff --git a/webview/src/plots/components/comparisonTable/ComparisonTable.tsx b/webview/src/plots/components/comparisonTable/ComparisonTable.tsx index 308fcb56cf..537f73dbbd 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTable.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTable.tsx @@ -11,13 +11,13 @@ import { import plotsStyles from '../styles.module.scss' import { withScale } from '../../../util/styles' import { sendMessage } from '../../../shared/vscode' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export const ComparisonTable: React.FC = () => { - const { plots } = useSelector((state: RootState) => state.comparison) + const { plots } = useSelector((state: PlotsState) => state.comparison) const { selectedRevisions: revisions } = useSelector( - (state: RootState) => state.webview + (state: PlotsState) => state.webview ) const pinnedColumn = useRef('') diff --git a/webview/src/plots/components/comparisonTable/ComparisonTableHead.tsx b/webview/src/plots/components/comparisonTable/ComparisonTableHead.tsx index 4942215865..cb66599be6 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTableHead.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTableHead.tsx @@ -6,7 +6,7 @@ import styles from './styles.module.scss' import { DropTarget } from './DropTarget' import { ComparisonTableHeader } from './ComparisonTableHeader' import { DragDropContainer } from '../../../shared/components/dragDrop/DragDropContainer' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export type ComparisonTableColumn = Revision @@ -24,7 +24,7 @@ export const ComparisonTableHead: React.FC = ({ setPinnedColumn }) => { const draggedId = useSelector( - (state: RootState) => state.dragAndDrop.draggedRef?.itemId + (state: PlotsState) => state.dragAndDrop.draggedRef?.itemId ) const items = columns.map(({ revision, displayColor, group }) => { diff --git a/webview/src/plots/components/comparisonTable/ComparisonTableRow.test.tsx b/webview/src/plots/components/comparisonTable/ComparisonTableRow.test.tsx index b27543f77a..1d6ffee048 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTableRow.test.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTableRow.test.tsx @@ -13,7 +13,7 @@ import { ComparisonTableRowProps } from './ComparisonTableRow' import styles from '../styles.module.scss' -import { storeReducers } from '../../store' +import { plotsReducers } from '../../store' jest.mock('../../../shared/api') @@ -37,7 +37,7 @@ describe('ComparisonTableRow', () => { render( diff --git a/webview/src/plots/components/comparisonTable/ComparisonTableRow.tsx b/webview/src/plots/components/comparisonTable/ComparisonTableRow.tsx index 1bfe353dbf..9cb6be58cf 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTableRow.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTableRow.tsx @@ -8,7 +8,7 @@ import { Icon } from '../../../shared/components/Icon' import { RefreshButton } from '../../../shared/components/button/RefreshButton' import { sendMessage } from '../../../shared/vscode' import { ChevronDown, ChevronRight } from '../../../shared/components/icons' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export interface ComparisonTableRowProps { path: string @@ -24,7 +24,7 @@ export const ComparisonTableRow: React.FC = ({ pinnedColumn }) => { const draggedId = useSelector( - (state: RootState) => state.dragAndDrop.draggedRef?.itemId + (state: PlotsState) => state.dragAndDrop.draggedRef?.itemId ) const [isShown, setIsShown] = useState(true) diff --git a/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx b/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx index 7df1fbeb52..fef18cae05 100644 --- a/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx +++ b/webview/src/plots/components/comparisonTable/ComparisonTableWrapper.tsx @@ -4,12 +4,12 @@ import { useSelector, useDispatch } from 'react-redux' import { ComparisonTable } from './ComparisonTable' import { changeSize } from './comparisonTableSlice' import { PlotsContainer } from '../PlotsContainer' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export const ComparisonTableWrapper: React.FC = () => { const dispatch = useDispatch() const { size, isCollapsed } = useSelector( - (state: RootState) => state.comparison + (state: PlotsState) => state.comparison ) const handleResize = (size: PlotSize) => { dispatch(changeSize(size)) diff --git a/webview/src/plots/components/ribbon/Ribbon.tsx b/webview/src/plots/components/ribbon/Ribbon.tsx index 278df8e3ed..42c4eb45e9 100644 --- a/webview/src/plots/components/ribbon/Ribbon.tsx +++ b/webview/src/plots/components/ribbon/Ribbon.tsx @@ -7,14 +7,14 @@ import { RibbonBlock } from './RibbonBlock' import { sendMessage } from '../../../shared/vscode' import { IconButton } from '../../../shared/components/button/IconButton' import { performOrderedUpdate } from '../../../util/objects' -import { RootState } from '../../store' +import { PlotsState } from '../../store' import { Lines, Refresh } from '../../../shared/components/icons' const MAX_NB_EXP = 7 export const Ribbon: React.FC = () => { const revisions = useSelector( - (state: RootState) => state.webview.selectedRevisions + (state: PlotsState) => state.webview.selectedRevisions ) const [order, setOrder] = useState([]) const reorderId = 'id' diff --git a/webview/src/plots/components/templatePlots/AddedSection.tsx b/webview/src/plots/components/templatePlots/AddedSection.tsx index 8bbd6ff418..cf904696f0 100644 --- a/webview/src/plots/components/templatePlots/AddedSection.tsx +++ b/webview/src/plots/components/templatePlots/AddedSection.tsx @@ -4,7 +4,7 @@ import cx from 'classnames' import { TemplatePlotSection } from 'dvc/src/plots/webview/contract' import styles from '../styles.module.scss' import { getIDWithoutIndex } from '../../../util/ids' -import { RootState } from '../../store' +import { PlotsState } from '../../store' import { Icon } from '../../../shared/components/Icon' import { GraphLine } from '../../../shared/components/icons' @@ -25,7 +25,7 @@ export const AddedSection: React.FC = ({ closestSection, acceptedGroups }) => { - const { draggedRef } = useSelector((state: RootState) => state.dragAndDrop) + const { draggedRef } = useSelector((state: PlotsState) => state.dragAndDrop) const handleDragLeave = () => { setHoveredSection('') } diff --git a/webview/src/plots/components/templatePlots/TemplatePlots.tsx b/webview/src/plots/components/templatePlots/TemplatePlots.tsx index 46941c9097..1e3d64bf63 100644 --- a/webview/src/plots/components/templatePlots/TemplatePlots.tsx +++ b/webview/src/plots/components/templatePlots/TemplatePlots.tsx @@ -15,7 +15,7 @@ import { createIDWithIndex, getIDIndex } from '../../../util/ids' import styles from '../styles.module.scss' import { shouldUseVirtualizedGrid } from '../util' import { useNbItemsPerRow } from '../../hooks/useNbItemsPerRow' -import { RootState } from '../../store' +import { PlotsState } from '../../store' import { plotDataStore } from '../plotDataStore' export enum NewSectionBlock { @@ -25,7 +25,7 @@ export enum NewSectionBlock { export const TemplatePlots: React.FC = () => { const { plotsSnapshot, size } = useSelector( - (state: RootState) => state.template + (state: PlotsState) => state.template ) const [sections, setSections] = useState([]) const [hoveredSection, setHoveredSection] = useState('') diff --git a/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx b/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx index 18ef4accd0..82122b2c0f 100644 --- a/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx +++ b/webview/src/plots/components/templatePlots/TemplatePlotsWrapper.tsx @@ -4,12 +4,12 @@ import { useSelector, useDispatch } from 'react-redux' import { TemplatePlots } from './TemplatePlots' import { changeSize } from './templatePlotsSlice' import { PlotsContainer } from '../PlotsContainer' -import { RootState } from '../../store' +import { PlotsState } from '../../store' export const TemplatePlotsWrapper: React.FC = () => { const dispatch = useDispatch() const { size, isCollapsed } = useSelector( - (state: RootState) => state.template + (state: PlotsState) => state.template ) const handleResize = (size: PlotSize) => { diff --git a/webview/src/plots/index.tsx b/webview/src/plots/index.tsx index 49ff56c31e..a38c0b39dc 100644 --- a/webview/src/plots/index.tsx +++ b/webview/src/plots/index.tsx @@ -4,11 +4,11 @@ import { Provider } from 'react-redux' import '../shared/style.scss' import { App } from './components/App' import '../util/wdyr' -import { store } from './store' +import { plotsStore } from './store' const root = ReactDOM.createRoot(document.querySelector('#root') as HTMLElement) root.render( - + ) diff --git a/webview/src/plots/store.ts b/webview/src/plots/store.ts index 36befd5557..4ce12b234d 100644 --- a/webview/src/plots/store.ts +++ b/webview/src/plots/store.ts @@ -5,7 +5,7 @@ import templatePlotsReducer from './components/templatePlots/templatePlotsSlice' import webviewReducer from './components/webviewSlice' import dragAndDropReducer from '../shared/components/dragDrop/dragDropSlice' -export const storeReducers = { +export const plotsReducers = { checkpoint: checkpointPlotsReducer, comparison: comparisonTableReducer, dragAndDrop: dragAndDropReducer, @@ -13,9 +13,9 @@ export const storeReducers = { webview: webviewReducer } -export const store = configureStore({ - reducer: storeReducers +export const plotsStore = configureStore({ + reducer: plotsReducers }) -export type RootState = ReturnType -export type AppDispatch = typeof store.dispatch +export type PlotsState = ReturnType +export type PlotsDispatch = typeof plotsStore.dispatch diff --git a/webview/src/shared/components/dragDrop/DragDropContainer.tsx b/webview/src/shared/components/dragDrop/DragDropContainer.tsx index f07e94239c..743ae04a4c 100644 --- a/webview/src/shared/components/dragDrop/DragDropContainer.tsx +++ b/webview/src/shared/components/dragDrop/DragDropContainer.tsx @@ -12,7 +12,7 @@ import { changeRef } from './dragDropSlice' import styles from './styles.module.scss' import { getIDIndex, getIDWithoutIndex } from '../../../util/ids' import { Any } from '../../../util/objects' -import { RootState } from '../../../plots/store' +import { PlotsState } from '../../../plots/store' const orderIdxTune = (direction: DragEnterDirection, isAfter: boolean) => { if (direction === DragEnterDirection.RIGHT) { @@ -86,7 +86,7 @@ export const DragDropContainer: React.FC = ({ const [draggedOverId, setDraggedOverId] = useState('') const [draggedId, setDraggedId] = useState('') const [direction, setDirection] = useState(DragEnterDirection.LEFT) - const { draggedRef } = useSelector((state: RootState) => state.dragAndDrop) + const { draggedRef } = useSelector((state: PlotsState) => state.dragAndDrop) const draggedOverIdTimeout = useRef(0) const dispatch = useDispatch() diff --git a/webview/src/stories/ComparisonTable.stories.tsx b/webview/src/stories/ComparisonTable.stories.tsx index 69035dadec..3b9a2f8708 100644 --- a/webview/src/stories/ComparisonTable.stories.tsx +++ b/webview/src/stories/ComparisonTable.stories.tsx @@ -15,7 +15,7 @@ import { ComparisonTable } from '../plots/components/comparisonTable/ComparisonT import { WebviewWrapper } from '../shared/components/webviewWrapper/WebviewWrapper' import { update } from '../plots/components/comparisonTable/comparisonTableSlice' import { updateSelectedRevisions } from '../plots/components/webviewSlice' -import { storeReducers } from '../plots/store' +import { plotsReducers } from '../plots/store' const MockedState: React.FC<{ data: PlotsComparisonData @@ -37,7 +37,7 @@ export default { const Template: Story = ({ plots, revisions }) => { const store = configureStore({ - reducer: storeReducers + reducer: plotsReducers }) return ( diff --git a/webview/src/stories/Plots.stories.tsx b/webview/src/stories/Plots.stories.tsx index be1df04a5d..0203084872 100644 --- a/webview/src/stories/Plots.stories.tsx +++ b/webview/src/stories/Plots.stories.tsx @@ -23,7 +23,7 @@ import './test-vscode-styles.scss' import '../shared/style.scss' import '../plots/components/styles.module.scss' import { feedStore } from '../plots/components/App' -import { storeReducers } from '../plots/store' +import { plotsReducers } from '../plots/store' const MockedState: React.FC<{ data: PlotsData; children: React.ReactNode }> = ({ children, @@ -55,7 +55,7 @@ export default { const Template: Story<{ data?: PlotsData }> = ({ data }) => { - const store = configureStore({ reducer: storeReducers }) + const store = configureStore({ reducer: plotsReducers }) return ( From 9ee361d8997cf19c538ce707ae457035f004f1c5 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 25 Jul 2022 16:01:26 -0400 Subject: [PATCH 2/5] Use Redux for experiments table drag and drop --- .../experiments/components/Experiments.tsx | 9 +-- .../components/table/Table.test.tsx | 22 +++++- webview/src/experiments/index.tsx | 8 +- webview/src/experiments/store.ts | 13 ++++ .../components/dragDrop/DragDropContext.tsx | 76 ------------------- .../components/dragDrop/DragDropWorkbench.tsx | 65 ++++++++++------ .../components/dragDrop/dragDropSlice.ts | 23 +++++- webview/src/test/experimentsTable.tsx | 9 ++- 8 files changed, 111 insertions(+), 114 deletions(-) create mode 100644 webview/src/experiments/store.ts delete mode 100644 webview/src/shared/components/dragDrop/DragDropContext.tsx diff --git a/webview/src/experiments/components/Experiments.tsx b/webview/src/experiments/components/Experiments.tsx index 10e6832ec2..821fde2774 100644 --- a/webview/src/experiments/components/Experiments.tsx +++ b/webview/src/experiments/components/Experiments.tsx @@ -26,7 +26,6 @@ import buildDynamicColumns from '../util/buildDynamicColumns' import { sendMessage } from '../../shared/vscode' import { WebviewWrapper } from '../../shared/components/webviewWrapper/WebviewWrapper' import { GetStarted } from '../../shared/components/getStarted/GetStarted' -import { DragDropProvider } from '../../shared/components/dragDrop/DragDropContext' import { EmptyState } from '../../shared/components/emptyState/EmptyState' const DEFAULT_COLUMN_WIDTH = 90 @@ -224,11 +223,9 @@ export const ExperimentsTable: React.FC<{ } return ( - - -
- - + +
+ ) } diff --git a/webview/src/experiments/components/table/Table.test.tsx b/webview/src/experiments/components/table/Table.test.tsx index bc840c43ac..3063876c3f 100644 --- a/webview/src/experiments/components/table/Table.test.tsx +++ b/webview/src/experiments/components/table/Table.test.tsx @@ -3,7 +3,9 @@ */ /* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectHeaders"] }] */ import '@testing-library/jest-dom/extend-expect' +import { configureStore } from '@reduxjs/toolkit' import { cleanup, fireEvent, render, screen } from '@testing-library/react' +import { Provider } from 'react-redux' import { Experiment, TableData } from 'dvc/src/experiments/webview/contract' import { MessageFromWebviewType } from 'dvc/src/webview/contract' import React from 'react' @@ -14,7 +16,6 @@ import { Table } from './Table' import styles from './styles.module.scss' import { ExperimentsTable } from '../Experiments' import * as ColumnOrder from '../../hooks/useColumnOrder' - import { vsCodeApi } from '../../../shared/api' import { expectHeaders, @@ -23,6 +24,7 @@ import { } from '../../../test/sort' import { dragAndDrop } from '../../../test/dragDrop' import { DragEnterDirection } from '../../../shared/components/dragDrop/util' +import { experimentsReducers } from '../../store' jest.mock('../../../shared/api') const { postMessage } = vsCodeApi @@ -116,12 +118,20 @@ describe('Table', () => { } const renderTable = (testData = {}, tableInstance = instance) => { const tableData = { ...dummyTableData, ...testData } - return render(
) + return render( + +
+ + ) } const renderExperimentsTable = ( data: TableData = sortingTableDataFixture ) => { - return render() + return render( + + + + ) } beforeAll(() => { @@ -330,7 +340,11 @@ describe('Table', () => { ...sortingTableDataFixture, columnWidths } - render() + render( + + + + ) const [experimentColumnResizeHandle] = await screen.findAllByRole( 'separator' ) diff --git a/webview/src/experiments/index.tsx b/webview/src/experiments/index.tsx index 95de9279c6..75ea6a1fe1 100644 --- a/webview/src/experiments/index.tsx +++ b/webview/src/experiments/index.tsx @@ -1,7 +1,13 @@ import React from 'react' import ReactDOM from 'react-dom/client' +import { Provider } from 'react-redux' import '../shared/style.scss' import { App } from './components/App' +import { experimentsStore } from './store' const root = ReactDOM.createRoot(document.querySelector('#root') as HTMLElement) -root.render() +root.render( + + + +) diff --git a/webview/src/experiments/store.ts b/webview/src/experiments/store.ts new file mode 100644 index 0000000000..933f4dacb2 --- /dev/null +++ b/webview/src/experiments/store.ts @@ -0,0 +1,13 @@ +import { configureStore } from '@reduxjs/toolkit' +import dragAndDropReducer from '../shared/components/dragDrop/dragDropSlice' + +export const experimentsReducers = { + dragAndDrop: dragAndDropReducer +} + +export const experimentsStore = configureStore({ + reducer: experimentsReducers +}) + +export type ExperimentsState = ReturnType +export type ExperimentsDispatch = typeof experimentsStore.dispatch diff --git a/webview/src/shared/components/dragDrop/DragDropContext.tsx b/webview/src/shared/components/dragDrop/DragDropContext.tsx deleted file mode 100644 index bde6b08555..0000000000 --- a/webview/src/shared/components/dragDrop/DragDropContext.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { createContext, useState } from 'react' - -export type DraggedInfo = - | { - itemIndex: string - itemId: string - group?: string - } - | undefined - -export interface DragDropGroupState { - draggedId?: string - draggedOverId?: string -} - -export type GroupStates = { - [group: string]: DragDropGroupState | undefined -} - -export type DragDropContextValue = { - draggedRef: DraggedInfo - setDraggedRef: ((draggedRef: DraggedInfo) => void) | undefined - groupStates?: GroupStates - setGroupState?: (group: string, handlers: DragDropGroupState) => void - removeGroupState?: (group: string) => void -} - -export const DragDropContext = createContext({ - draggedRef: undefined, - groupStates: undefined, - removeGroupState: undefined, - setDraggedRef: undefined, - setGroupState: undefined -}) - -type DragDropProviderProps = { - children: React.ReactNode -} - -export const DragDropProvider: React.FC = ({ - children -}) => { - const [draggedRef, setDraggedRef] = useState(undefined) - - const [groupStates, setGroupStates] = useState({}) - - const changeDraggedRef = (d: DraggedInfo) => setDraggedRef(d) - - const setGroupState = (group: string, handlers: DragDropGroupState) => { - setGroupStates({ - ...groupStates, - [group]: handlers - }) - } - - const removeGroupState = (group: string) => { - setGroupStates({ - ...groupStates, - [group]: undefined - }) - } - - return ( - - {children} - - ) -} diff --git a/webview/src/shared/components/dragDrop/DragDropWorkbench.tsx b/webview/src/shared/components/dragDrop/DragDropWorkbench.tsx index fef1886459..5a7b976e50 100644 --- a/webview/src/shared/components/dragDrop/DragDropWorkbench.tsx +++ b/webview/src/shared/components/dragDrop/DragDropWorkbench.tsx @@ -1,6 +1,8 @@ -import React, { DragEvent, useContext } from 'react' +import React, { DragEvent } from 'react' +import { useDispatch, useSelector } from 'react-redux' import { makeTarget } from './DragDropContainer' -import { DragDropContext, DragDropContextValue } from './DragDropContext' +import { setGroup } from './dragDropSlice' +import { ExperimentsState } from '../../../experiments/store' export type OnDrop = (draggedId: string, draggedOverId: string) => void export type OnDragStart = (draggedId: string) => void @@ -26,21 +28,33 @@ export const Draggable: React.FC = ({ onDrop, onDragOver, onDragStart + // eslint-disable-next-line sonarjs/cognitive-complexity }) => { - const { groupStates, setGroupState } = - useContext(DragDropContext) + const groupStates = useSelector( + (state: ExperimentsState) => state.dragAndDrop.groups + ) + const dispatch = useDispatch() - const groupState = groupStates?.[group] || {} + const groupState = groupStates[group] || {} const { draggedOverId, draggedId } = groupState + const modifyGroup = (id: string) => { + dispatch( + setGroup({ + group: { + ...groupState, + draggedId: id + }, + id: group + }) + ) + } + const handleDragStart = (e: DragEvent) => { const { id } = e.currentTarget e.dataTransfer.effectAllowed = 'move' e.dataTransfer.dropEffect = 'move' - setGroupState?.(group, { - ...groupState, - draggedId: id - }) + modifyGroup(id) onDragStart?.(id) } @@ -52,16 +66,14 @@ export const Draggable: React.FC = ({ } const handleDragEnter = (e: DragEvent) => { - const { id } = e.currentTarget - !disabled && - draggedId && - id !== draggedId && - id !== draggedOverId && - (setGroupState?.(group, { - ...groupState, - draggedOverId: id - }) || - onDragOver?.(draggedId, id)) + if (!disabled && draggedId) { + const { id } = e.currentTarget + + if (id !== draggedId && id !== draggedOverId) { + modifyGroup(id) + onDragOver?.(draggedId, id) + } + } } const handleDragOver = (e: DragEvent) => { @@ -69,11 +81,16 @@ export const Draggable: React.FC = ({ } const handleDragEnd = () => { - setGroupState?.(group, { - ...groupState, - draggedId: undefined, - draggedOverId: undefined - }) + dispatch( + setGroup({ + group: { + ...groupState, + draggedId: undefined, + draggedOverId: undefined + }, + id: group + }) + ) } const item = ( diff --git a/webview/src/shared/components/dragDrop/dragDropSlice.ts b/webview/src/shared/components/dragDrop/dragDropSlice.ts index b547e88cbb..95596f5874 100644 --- a/webview/src/shared/components/dragDrop/dragDropSlice.ts +++ b/webview/src/shared/components/dragDrop/dragDropSlice.ts @@ -7,12 +7,22 @@ export type DraggedInfo = group?: string } | undefined +export interface DragDropGroupState { + draggedId?: string + draggedOverId?: string +} + +export type GroupStates = { + [group: string]: DragDropGroupState | undefined +} export interface DragDropState { draggedRef: DraggedInfo + groups: GroupStates } export const dragDropInitialState: DragDropState = { - draggedRef: undefined + draggedRef: undefined, + groups: {} } export const dragDropSlice = createSlice({ @@ -24,10 +34,19 @@ export const dragDropSlice = createSlice({ ...state, draggedRef: action.payload } + }, + setGroup: ( + state, + action: PayloadAction<{ id: string; group: DragDropGroupState }> + ) => { + return { + ...state, + groups: { ...state.groups, [action.payload.id]: action.payload.group } + } } } }) -export const { changeRef } = dragDropSlice.actions +export const { changeRef, setGroup } = dragDropSlice.actions export default dragDropSlice.reducer diff --git a/webview/src/test/experimentsTable.tsx b/webview/src/test/experimentsTable.tsx index c61a39802d..4550ac4412 100644 --- a/webview/src/test/experimentsTable.tsx +++ b/webview/src/test/experimentsTable.tsx @@ -1,11 +1,14 @@ +import { configureStore } from '@reduxjs/toolkit' import { fireEvent, render, within, screen } from '@testing-library/react' import React from 'react' +import { Provider } from 'react-redux' import deeplyNestedTableDataFixture from 'dvc/src/test/fixtures/expShow/deeplyNested' import tableDataFixture from 'dvc/src/test/fixtures/expShow/tableData' import { MessageToWebviewType } from 'dvc/src/webview/contract' import { tableData as sortingTableDataFixture } from './sort' import { getRow } from './queries' import { App } from '../experiments/components/App' +import { experimentsReducers } from '../experiments/store' export const setTableData = (data = tableDataFixture) => { fireEvent( @@ -20,7 +23,11 @@ export const setTableData = (data = tableDataFixture) => { } export const renderTable = (data = tableDataFixture) => { - render() + render( + + + + ) setTableData(data) } From 074623e5e29fe35c5daa2d925cc0ffbae6f0a7b3 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 25 Jul 2022 16:10:40 -0400 Subject: [PATCH 3/5] Fixes after merge --- .../src/experiments/components/table/Table.test.tsx | 8 +++++--- webview/src/test/experimentsTable.tsx | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/webview/src/experiments/components/table/Table.test.tsx b/webview/src/experiments/components/table/Table.test.tsx index 6ded6cbccb..26b949a319 100644 --- a/webview/src/experiments/components/table/Table.test.tsx +++ b/webview/src/experiments/components/table/Table.test.tsx @@ -137,9 +137,11 @@ describe('Table', () => { return render( - , { - queries: { ...queries, ...customQueries } - }) + , + { + queries: { ...queries, ...customQueries } + } + ) } beforeAll(() => { diff --git a/webview/src/test/experimentsTable.tsx b/webview/src/test/experimentsTable.tsx index a1d955356e..e97a90bd52 100644 --- a/webview/src/test/experimentsTable.tsx +++ b/webview/src/test/experimentsTable.tsx @@ -29,12 +29,14 @@ export const setTableData = (data = tableDataFixture) => { } export const renderTable = (data = tableDataFixture) => { - render( + const renderedTable = render( - , { - queries: { ...queries, ...customQueries } - }) + , + { + queries: { ...queries, ...customQueries } + } + ) setTableData(data) return renderedTable } From e078d9f753686a755ec6df7f6c098bc76569cbee Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 25 Jul 2022 16:26:09 -0400 Subject: [PATCH 4/5] Add redux to table stories --- webview/src/stories/Table.stories.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/webview/src/stories/Table.stories.tsx b/webview/src/stories/Table.stories.tsx index 61aee5aa03..2684ce754e 100644 --- a/webview/src/stories/Table.stories.tsx +++ b/webview/src/stories/Table.stories.tsx @@ -1,4 +1,6 @@ +import { configureStore } from '@reduxjs/toolkit' import React from 'react' +import { Provider } from 'react-redux' import { ComponentStory } from '@storybook/react' import { Meta } from '@storybook/react/types-6-0' import rowsFixture from 'dvc/src/test/fixtures/expShow/rows' @@ -22,6 +24,7 @@ import { setExperimentsAsSelected, setExperimentsAsStarred } from '../test/tableDataFixture' +import { experimentsReducers } from '../experiments/store' const tableData: TableData = { changes: workspaceChangesFixture, @@ -100,7 +103,11 @@ export default { } as Meta const Template: ComponentStory = ({ tableData }) => { - return + return ( + + + + ) } export const WithData = Template.bind({}) From db939826fd777644c715ecb725a9e7645f269ca7 Mon Sep 17 00:00:00 2001 From: Stephanie Roy Date: Mon, 25 Jul 2022 17:02:46 -0400 Subject: [PATCH 5/5] Add missing provider in stories --- webview/src/stories/Table.stories.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/webview/src/stories/Table.stories.tsx b/webview/src/stories/Table.stories.tsx index 2684ce754e..1a6fcdd718 100644 --- a/webview/src/stories/Table.stories.tsx +++ b/webview/src/stories/Table.stories.tsx @@ -203,9 +203,11 @@ WithNoSortsOrFilters.args = { export const Scrolled: ComponentStory = ({ tableData }) => { return ( -
- -
+ +
+ +
+
) } Scrolled.play = async ({ canvasElement }) => {