Skip to content

Commit

Permalink
Move the table data state to redux (#2112)
Browse files Browse the repository at this point in the history
  • Loading branch information
sroy3 authored Jul 28, 2022
1 parent 1211826 commit dfb8ead
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 162 deletions.
9 changes: 3 additions & 6 deletions webview/src/experiments/components/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@
* @jest-environment jsdom
*/
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "expectHeaders"] }] */
import React from 'react'
import {
cleanup,
createEvent,
fireEvent,
render,
screen,
within
} from '@testing-library/react'
Expand All @@ -17,7 +15,6 @@ import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import { Column, ColumnType, Row } from 'dvc/src/experiments/webview/contract'
import { buildMetricOrParamPath } from 'dvc/src/experiments/columns/paths'
import { dataTypesTableData } from 'dvc/src/test/fixtures/expShow/dataTypes'
import { App } from './App'
import { useIsFullyContained } from './overflowHoverTooltip/useIsFullyContained'
import styles from './table/styles.module.scss'
import { vsCodeApi } from '../../shared/api'
Expand Down Expand Up @@ -119,7 +116,7 @@ describe('App', () => {
})

it('should send a message to the extension on the first render', () => {
render(<App />)
renderTable(undefined, true)
expect(mockPostMessage).toHaveBeenCalledWith({
type: MessageFromWebviewType.INITIALIZED
})
Expand All @@ -128,7 +125,7 @@ describe('App', () => {
})

it('should display the loading state before the experiments are shown', async () => {
render(<App />)
renderTable(undefined, true)

const loadingState = await screen.findByText('Loading Experiments...')
expect(loadingState).toBeInTheDocument()
Expand Down Expand Up @@ -866,7 +863,7 @@ describe('App', () => {

describe('Context Menu Suppression', () => {
it('Suppresses the context menu on a table with no data', () => {
render(<App />)
renderTable(undefined, true)
const target = screen.getByText('Loading Experiments...')
const contextMenuEvent = createEvent.contextMenu(target)
fireEvent(target, contextMenuEvent)
Expand Down
13 changes: 8 additions & 5 deletions webview/src/experiments/components/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import React, { useCallback, useState } from 'react'
import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'
import {
MessageToWebview,
MessageToWebviewType
} from 'dvc/src/webview/contract'
import { TableData } from 'dvc/src/experiments/webview/contract'
import Experiments from './Experiments'
import { update } from './table/tableDataSlice'
import { useVsCodeMessaging } from '../../shared/hooks/useVsCodeMessaging'

export const App: React.FC<Record<string, unknown>> = () => {
const [tableData, setTableData] = useState<TableData>()
const dispatch = useDispatch()

useVsCodeMessaging(
useCallback(
({ data }: { data: MessageToWebview<TableData> }) => {
if (data.type === MessageToWebviewType.SET_DATA) {
setTableData(data.data)
dispatch(update(data.data))
}
},
[setTableData]
[dispatch]
)
)

return <Experiments tableData={tableData} />
return <Experiments />
}
87 changes: 32 additions & 55 deletions webview/src/experiments/components/Experiments.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import React, { useCallback } from 'react'
import {
Column,
Row,
TableData,
InitiallyUndefinedTableData,
ColumnType
} from 'dvc/src/experiments/webview/contract'
import React, { useCallback, useEffect } from 'react'
import { useSelector } from 'react-redux'
import { Column, Row, ColumnType } from 'dvc/src/experiments/webview/contract'
import {
Row as TableRow,
Column as TableColumn,
Expand All @@ -27,6 +22,7 @@ import { sendMessage } from '../../shared/vscode'
import { WebviewWrapper } from '../../shared/components/webviewWrapper/WebviewWrapper'
import { GetStarted } from '../../shared/components/getStarted/GetStarted'
import { EmptyState } from '../../shared/components/emptyState/EmptyState'
import { ExperimentsState } from '../store'

const DEFAULT_COLUMN_WIDTH = 90
const MINIMUM_COLUMN_WIDTH = 90
Expand Down Expand Up @@ -124,55 +120,37 @@ const reportResizedColumn = (state: TableState<Row>) => {
}
}

export const ExperimentsTable: React.FC<{
tableData: InitiallyUndefinedTableData
}> = ({ tableData: initiallyUndefinedTableData }) => {
const defaultColumn: Partial<TableColumn<Row>> = {
minWidth: MINIMUM_COLUMN_WIDTH,
width: DEFAULT_COLUMN_WIDTH
}

export const ExperimentsTable: React.FC = () => {
const {
columns: columnsData,
columnOrder,
columnWidths,
hasColumns,
rows: data
} = useSelector((state: ExperimentsState) => state.tableData)
const columns = getColumns(columnsData)
const initialState = {
columnOrder,
columnResizing: {
columnWidths
}
} as Partial<TableState<Row>>

const getRowId = useCallback(
(experiment: Row, relativeIndex: number, parent?: TableRow<Row>) =>
parent ? [parent.id, experiment.id].join('.') : String(relativeIndex),
[]
)
const [tableData, columns, defaultColumn, initialState] =
React.useMemo(() => {
const tableData: TableData = {
changes: [],
columnOrder: [],
columnWidths: {},
columns: [],
filteredCounts: {
checkpoints: 0,
experiments: 0
},
filters: [],
hasCheckpoints: false,
hasColumns: false,
hasRunningExperiment: false,
rows: [],
sorts: [],
...initiallyUndefinedTableData
}

const initialState = {
columnOrder: tableData.columnOrder,
columnResizing: {
columnWidths: tableData.columnWidths
}
} as Partial<TableState<Row>>

const defaultColumn: Partial<TableColumn<Row>> = {
minWidth: MINIMUM_COLUMN_WIDTH,
width: DEFAULT_COLUMN_WIDTH
}

const columns = getColumns(tableData.columns)
return [tableData, columns, defaultColumn, initialState]
}, [initiallyUndefinedTableData])

const { hasColumns, rows: data } = tableData

const instance = useTable<Row>(
{
autoResetExpanded: false,
autoResetHiddenColumns: false,
autoResetResize: false,
columns,
data,
Expand Down Expand Up @@ -206,7 +184,7 @@ export const ExperimentsTable: React.FC<{

const { toggleAllRowsExpanded } = instance

React.useEffect(() => {
useEffect(() => {
toggleAllRowsExpanded()
}, [toggleAllRowsExpanded])

Expand All @@ -224,18 +202,17 @@ export const ExperimentsTable: React.FC<{

return (
<RowSelectionProvider>
<Table instance={instance} tableData={tableData} />
<Table instance={instance} />
</RowSelectionProvider>
)
}

const Experiments: React.FC<{
tableData?: TableData | null
}> = ({ tableData }) => {
const Experiments: React.FC = () => {
const { hasData } = useSelector((state: ExperimentsState) => state.tableData)
return (
<WebviewWrapper className={styles.experiments}>
{tableData ? (
<ExperimentsTable tableData={tableData} />
{hasData ? (
<ExperimentsTable />
) : (
<EmptyState>Loading Experiments...</EmptyState>
)}
Expand Down
18 changes: 10 additions & 8 deletions webview/src/experiments/components/table/Indicators.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { MouseEventHandler, ReactNode } from 'react'
import { SortDefinition } from 'dvc/src/experiments/model/sortBy'
import { useSelector } from 'react-redux'
import cx from 'classnames'
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import { FilteredCounts } from 'dvc/src/experiments/model/filterBy/collect'
Expand All @@ -15,6 +15,7 @@ import { sendMessage } from '../../../shared/vscode'
import Tooltip from '../../../shared/components/tooltip/Tooltip'
import tooltipStyles from '../../../shared/components/tooltip/styles.module.scss'
import { pluralize } from '../../../util/strings'
import { ExperimentsState } from '../../store'

export type IndicatorTooltipProps = Pick<TippyProps, 'children'> & {
tooltipContent: ReactNode
Expand Down Expand Up @@ -124,16 +125,17 @@ const formatFilteredCountMessage = (filteredCounts: FilteredCounts): string =>
.join(', ')} Filtered`

export const Indicators = ({
selectedForPlotsCount,
sorts,
filters,
filteredCounts
selectedForPlotsCount
}: {
sorts?: SortDefinition[]
filters?: string[]
filteredCounts: FilteredCounts
selectedForPlotsCount: number
}) => {
const filters = useSelector(
(state: ExperimentsState) => state.tableData.filters
)
const sorts = useSelector((state: ExperimentsState) => state.tableData.sorts)
const filteredCounts = useSelector(
(state: ExperimentsState) => state.tableData.filteredCounts
)
const sortsCount = sorts?.length
const filtersCount = filters?.length

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react'
import cx from 'classnames'
import { SortDefinition } from 'dvc/src/experiments/model/sortBy'
import { Experiment, Column } from 'dvc/src/experiments/webview/contract'
import { HeaderGroup } from 'react-table'
import { TableHeader } from './TableHeader'
Expand All @@ -14,8 +13,6 @@ import {
export const MergedHeaderGroups: React.FC<{
headerGroup: HeaderGroup<Experiment>
columns: HeaderGroup<Experiment>[]
sorts: SortDefinition[]
filters: string[]
orderedColumns: Column[]
onDragUpdate: OnDragOver
onDragStart: OnDragStart
Expand All @@ -25,8 +22,6 @@ export const MergedHeaderGroups: React.FC<{
root: HTMLElement | null
}> = ({
headerGroup,
sorts,
filters,
columns,
orderedColumns,
onDragUpdate,
Expand All @@ -50,8 +45,6 @@ export const MergedHeaderGroups: React.FC<{
orderedColumns={orderedColumns}
column={column}
columns={columns}
sorts={sorts}
filters={filters}
onDragOver={onDragUpdate}
onDragStart={onDragStart}
onDrop={onDragEnd}
Expand Down
10 changes: 7 additions & 3 deletions webview/src/experiments/components/table/Row.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from 'react'
import { useSelector } from 'react-redux'
import cx from 'classnames'
import { Experiment } from 'dvc/src/experiments/webview/contract'
import { MessageFromWebviewType } from 'dvc/src/webview/contract'
import { RowProp, WithChanges } from './interfaces'
import { RowProp } from './interfaces'
import styles from './styles.module.scss'
import { FirstCell, CellWrapper } from './Cell'
import { RowSelectionContext } from './RowSelectionContext'
Expand All @@ -12,6 +13,7 @@ import { MessagesMenu } from '../../../shared/components/messagesMenu/MessagesMe
import { MessagesMenuOptionProps } from '../../../shared/components/messagesMenu/MessagesMenuOption'
import { HandlerFunc } from '../../../util/props'
import { cond } from '../../../util/helpers'
import { ExperimentsState } from '../../store'

const getExperimentTypeClass = ({ running, queued, selected }: Experiment) => {
if (running) {
Expand Down Expand Up @@ -311,16 +313,18 @@ export type BatchSelectionProp = {
}

export const RowContent: React.FC<
RowProp & { className?: string } & WithChanges & BatchSelectionProp
RowProp & { className?: string } & BatchSelectionProp
> = ({
row,
className,
changes,
contextMenuDisabled,
projectHasCheckpoints,
hasRunningExperiment,
batchRowSelection
}): JSX.Element => {
const changes = useSelector(
(state: ExperimentsState) => state.tableData.changes
)
const {
getRowProps,
cells: [firstCell, ...cells],
Expand Down
29 changes: 22 additions & 7 deletions webview/src/experiments/components/table/Table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,27 @@ describe('Table', () => {
const renderTable = (testData = {}, tableInstance = instance) => {
const tableData = { ...dummyTableData, ...testData }
return render(
<Provider store={configureStore({ reducer: experimentsReducers })}>
<Table instance={tableInstance} tableData={tableData} />
<Provider
store={configureStore({
preloadedState: { tableData },
reducer: experimentsReducers
})}
>
<Table instance={tableInstance} />
</Provider>
)
}
const renderExperimentsTable = (
data: TableData = sortingTableDataFixture
tableData: TableData = sortingTableDataFixture
) => {
return render(
<Provider store={configureStore({ reducer: experimentsReducers })}>
<ExperimentsTable tableData={data} />
<Provider
store={configureStore({
preloadedState: { tableData },
reducer: experimentsReducers
})}
>
<ExperimentsTable />
</Provider>,
{
queries: { ...queries, ...customQueries }
Expand Down Expand Up @@ -347,8 +357,13 @@ describe('Table', () => {
columnWidths
}
render(
<Provider store={configureStore({ reducer: experimentsReducers })}>
<ExperimentsTable tableData={tableDataWithColumnSetting} />
<Provider
store={configureStore({
preloadedState: { tableData: tableDataWithColumnSetting },
reducer: experimentsReducers
})}
>
<ExperimentsTable />
</Provider>
)
const [experimentColumnResizeHandle] = await screen.findAllByRole(
Expand Down
Loading

0 comments on commit dfb8ead

Please sign in to comment.