Skip to content

Commit 6fe4461

Browse files
authored
Fix row selection (duplicate experiments) (#3921)
* Fix row selection (duplicate experiments) * Return unique list of ids
1 parent 53b2346 commit 6fe4461

File tree

4 files changed

+39
-20
lines changed

4 files changed

+39
-20
lines changed

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

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { createContext, useState } from 'react'
22
import { RowProp } from '../../util/interfaces'
3+
import { getCompositeId } from '../../util/rows'
34

45
interface RowSelectionContextValue {
56
selectedRows: Record<string, RowProp | undefined>
@@ -28,14 +29,16 @@ export const RowSelectionProvider: React.FC<{ children: React.ReactNode }> = ({
2829
const toggleRowSelected = (rowProp: RowProp) => {
2930
const {
3031
row: {
31-
original: { id }
32+
original: { id, branch }
3233
}
3334
} = rowProp
35+
const compositeId = getCompositeId(id, branch)
36+
3437
setSelectedRows({
3538
...selectedRows,
36-
[id]: selectedRows[id] ? undefined : rowProp
39+
[compositeId]: selectedRows[compositeId] ? undefined : rowProp
3740
})
38-
setSelectionHistory([id, ...selectionHistory])
41+
setSelectionHistory([compositeId, ...selectionHistory])
3942
}
4043

4144
const batchSelection = (batch: RowProp[]) => {
@@ -44,21 +47,22 @@ export const RowSelectionProvider: React.FC<{ children: React.ReactNode }> = ({
4447
for (const rowProp of batch) {
4548
const {
4649
row: {
47-
original: { id }
50+
original: { id, branch }
4851
}
4952
} = rowProp
50-
selectedRowsCopy[id] = rowProp
53+
const compositeId = getCompositeId(id, branch)
54+
selectedRowsCopy[compositeId] = rowProp
5155
}
5256

5357
setSelectedRows(selectedRowsCopy)
5458
setSelectionHistory([
5559
...batch.map(
5660
({
5761
row: {
58-
original: { id }
62+
original: { id, branch }
5963
}
6064
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
61-
}) => id
65+
}) => getCompositeId(id, branch)
6266
),
6367
...selectionHistory
6468
])

webview/src/experiments/components/table/body/Row.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { ContextMenu } from '../../../../shared/components/contextMenu/ContextMe
1212
import { HandlerFunc } from '../../../../util/props'
1313
import { ExperimentsState } from '../../../store'
1414
import { toggleExperiment, toggleStarred } from '../../../util/messages'
15+
import { getCompositeId } from '../../../util/rows'
1516

1617
export type BatchSelectionProp = {
1718
batchRowSelection: (prop: RowProp) => void
@@ -24,14 +25,15 @@ export const RowContent: React.FC<
2425
(state: ExperimentsState) => state.tableData.changes
2526
)
2627
const { getVisibleCells, original, index, getIsExpanded, subRows } = row
27-
const { displayColor, error, starred, id, status, selected } = original
28+
const { branch, displayColor, error, starred, id, status, selected } =
29+
original
2830
const [firstCell, ...cells] = getVisibleCells()
2931
const isWorkspace = id === EXPERIMENT_WORKSPACE_ID
3032
const changesIfWorkspace = isWorkspace ? changes : undefined
3133

3234
const { toggleRowSelected, selectedRows } = useContext(RowSelectionContext)
3335

34-
const isRowSelected = !!selectedRows[id]
36+
const isRowSelected = !!selectedRows[getCompositeId(id, branch)]
3537

3638
const toggleRowSelection = useCallback<HandlerFunc<HTMLElement>>(
3739
args => {
@@ -52,7 +54,12 @@ export const RowContent: React.FC<
5254
subRows?.filter(subRow => subRow.original.selected).length ?? 0
5355

5456
const selections =
55-
subRows?.filter(subRow => selectedRows[subRow.original.id]).length ?? 0
57+
subRows?.filter(
58+
subRow =>
59+
selectedRows[
60+
getCompositeId(subRow.original.id, subRow.original.branch)
61+
]
62+
).length ?? 0
5663

5764
return {
5865
plotSelections,

webview/src/experiments/components/table/body/RowContextMenu.tsx

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { MessagesMenu } from '../../../../shared/components/messagesMenu/Message
1414
import { MessagesMenuOptionProps } from '../../../../shared/components/messagesMenu/MessagesMenuOption'
1515
import { cond } from '../../../../util/helpers'
1616
import { ExperimentsState } from '../../../store'
17+
import { getCompositeId } from '../../../util/rows'
1718

1819
const experimentMenuOption = (
1920
payload: string | string[] | { id: string; executor?: string | null }[],
@@ -107,47 +108,50 @@ const getMultiSelectMenuOptions = (
107108
unstarredExperimentIds
108109
} = collectDisabledOptions(selectedRowsList, hasRunningWorkspaceExperiment)
109110

110-
const toggleStarOption = (ids: string[], label: string) =>
111-
experimentMenuOption(
112-
ids,
111+
const toggleStarOption = (ids: string[], label: string) => {
112+
return experimentMenuOption(
113+
[...new Set(ids)],
113114
label,
114115
MessageFromWebviewType.TOGGLE_EXPERIMENT_STAR,
115116
ids.length === 0
116117
)
118+
}
119+
120+
const ids = [...new Set(selectedIds)]
117121

118122
return [
119123
toggleStarOption(unstarredExperimentIds, 'Star'),
120124
toggleStarOption(starredExperimentIds, 'Unstar'),
121125
experimentMenuOption(
122-
selectedIds,
126+
ids,
123127
'Plot',
124128
MessageFromWebviewType.SET_EXPERIMENTS_FOR_PLOTS,
125129
disablePlotOption,
126130
true
127131
),
128132
experimentMenuOption(
129-
selectedIds,
133+
ids,
130134
'Plot and Show',
131135
MessageFromWebviewType.SET_EXPERIMENTS_AND_OPEN_PLOTS,
132136
disablePlotOption,
133137
false
134138
),
135139
experimentMenuOption(
136-
selectedIds,
140+
ids,
137141
'Stop',
138142
MessageFromWebviewType.STOP_EXPERIMENTS,
139143
disableStopOption,
140144
true
141145
),
142146
experimentMenuOption(
143-
selectedIds,
147+
ids,
144148
'Push Selected',
145149
MessageFromWebviewType.PUSH_EXPERIMENT,
146150
disableExperimentOnlyOption,
147151
true
148152
),
149153
experimentMenuOption(
150-
selectedIds,
154+
ids,
151155
'Remove Selected',
152156
MessageFromWebviewType.REMOVE_EXPERIMENT,
153157
disableExperimentOnlyOption,
@@ -287,6 +291,7 @@ const getSingleSelectMenuOptions = (
287291

288292
const getContextMenuOptions = (
289293
id: string,
294+
branch: string | undefined,
290295
isWorkspace: boolean,
291296
projectHasCheckpoints: boolean,
292297
hasRunningWorkspaceExperiment: boolean,
@@ -296,7 +301,7 @@ const getContextMenuOptions = (
296301
starred?: boolean,
297302
executor?: string | null
298303
) => {
299-
const isFromSelection = !!selectedRows[id]
304+
const isFromSelection = !!selectedRows[getCompositeId(id, branch)]
300305
const selectedRowsList = Object.values(selectedRows).filter(
301306
value => value !== undefined
302307
) as RowProp[]
@@ -324,7 +329,7 @@ const getContextMenuOptions = (
324329

325330
export const RowContextMenu: React.FC<RowProp> = ({
326331
row: {
327-
original: { status, starred, id, executor },
332+
original: { branch, status, starred, id, executor },
328333
depth
329334
}
330335
}) => {
@@ -339,6 +344,7 @@ export const RowContextMenu: React.FC<RowProp> = ({
339344
const contextMenuOptions = useMemo(() => {
340345
return getContextMenuOptions(
341346
id,
347+
branch,
342348
isWorkspace,
343349
projectHasCheckpoints,
344350
hasRunningWorkspaceExperiment,
@@ -349,6 +355,7 @@ export const RowContextMenu: React.FC<RowProp> = ({
349355
executor
350356
)
351357
}, [
358+
branch,
352359
executor,
353360
status,
354361
starred,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const getCompositeId = (id: string, branch = '') => `${id}-${branch}`

0 commit comments

Comments
 (0)