Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 = () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function ExperimentsTable has 73 lines of code (exceeds 30 allowed). Consider refactoring.

const {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 3 locations. Consider refactoring.

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