Skip to content

Commit bc31c48

Browse files
authored
Fix "Image By Step" step number inaccuracy (#4516)
1 parent 86f7790 commit bc31c48

File tree

7 files changed

+87
-25
lines changed

7 files changed

+87
-25
lines changed

extension/src/plots/model/collect.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,9 @@ export type RevisionData = {
134134
[label: string]: RevisionPathData
135135
}
136136

137-
type ComparisonDataImgPlot = ImagePlot & { ind?: number }
138-
139137
export type ComparisonData = {
140138
[label: string]: {
141-
[path: string]: ComparisonDataImgPlot[]
139+
[path: string]: ImagePlot[]
142140
}
143141
}
144142

@@ -171,7 +169,7 @@ const collectImageData = (
171169
acc[id][pathLabel] = []
172170
}
173171

174-
const imgPlot: ComparisonDataImgPlot = { ...plot }
172+
const imgPlot: ImagePlot = { ...plot }
175173

176174
if (isMultiImgPlot) {
177175
imgPlot.ind = getMultiImageInd(path)

extension/src/plots/model/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ import {
3434
PlotHeight,
3535
SmoothPlotValues,
3636
ImagePlot,
37-
ComparisonMultiPlotValues
37+
ComparisonMultiPlotValues,
38+
ComparisonPlotImg
3839
} from '../webview/contract'
3940
import {
4041
EXPERIMENT_WORKSPACE_ID,
@@ -462,11 +463,17 @@ export class PlotsModel extends ModelWithPersistence {
462463
const url = collectImageUrl(image, fetched)
463464
const loading = !fetched && !url
464465

465-
return {
466+
const plot: ComparisonPlotImg = {
466467
errors,
467468
loading,
468469
url
469470
}
471+
472+
if (typeof image.ind === 'number') {
473+
plot.ind = image.ind
474+
}
475+
476+
return plot
470477
},
471478
paths,
472479
selectedRevisionIds

extension/src/plots/webview/contract.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export type ImagePlot = {
124124
revisions?: string[]
125125
type: PlotsType
126126
url: string
127+
ind?: number
127128
}
128129

129130
export const isImagePlot = (plot: Plot): plot is ImagePlot =>
@@ -158,6 +159,7 @@ export type ComparisonPlotImg = {
158159
url: string | undefined
159160
errors: string[] | undefined
160161
loading: boolean
162+
ind?: number
161163
}
162164

163165
export type ComparisonPlot = {

extension/src/test/fixtures/plotsDiff/index.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
PlotsComparisonData,
1515
DEFAULT_PLOT_HEIGHT,
1616
DEFAULT_NB_ITEMS_PER_ROW,
17-
DEFAULT_PLOT_WIDTH
17+
DEFAULT_PLOT_WIDTH,
18+
ComparisonPlotImg
1819
} from '../../../plots/webview/contract'
1920
import { join } from '../../util/path'
2021
import { copyOriginalColors } from '../../../experiments/model/status/colors'
@@ -375,10 +376,14 @@ const getMultiImageData = (
375376
url: string
376377
}[]
377378
} = {}
379+
378380
for (let i = 0; i < 15; i++) {
379381
const key = joinFunc('plots', 'image', `${i}.jpg`)
380382
const values = []
381383
for (const revision of revisions) {
384+
if (revision === 'exp-83425' && i % 2 === 0) {
385+
continue
386+
}
382387
values.push({
383388
type: PlotsType.IMAGE,
384389
revisions: [revision],
@@ -770,6 +775,11 @@ export const getManyTemplatePlotsWebviewMessage = (
770775

771776
export const MOCK_IMAGE_MTIME = 946684800000
772777

778+
const getIndFromComparisonMultiImgPath = (path: string) => {
779+
const pathIndMatches = path.match(/(\d+)\.jpg$/)
780+
return Number((pathIndMatches as string[])[1])
781+
}
782+
773783
export const getComparisonWebviewMessage = (
774784
baseUrl: string,
775785
joinFunc: (...args: string[]) => string = join
@@ -779,7 +789,8 @@ export const getComparisonWebviewMessage = (
779789
} = {}
780790

781791
for (const [path, plots] of Object.entries(getImageData(baseUrl, joinFunc))) {
782-
const pathLabel = path.includes('image') ? join('plots', 'image') : path
792+
const isMulti = path.includes('image')
793+
const pathLabel = isMulti ? join('plots', 'image') : path
783794

784795
if (!plotAcc[pathLabel]) {
785796
plotAcc[pathLabel] = {
@@ -801,11 +812,17 @@ export const getComparisonWebviewMessage = (
801812
}
802813
}
803814

804-
plotAcc[pathLabel].revisions[id].imgs.push({
815+
const img: ComparisonPlotImg = {
805816
url: `${url}?${MOCK_IMAGE_MTIME}`,
806817
errors: undefined,
807818
loading: false
808-
})
819+
}
820+
821+
if (isMulti) {
822+
img.ind = getIndFromComparisonMultiImgPath(path)
823+
}
824+
825+
plotAcc[pathLabel].revisions[id].imgs.push(img)
809826
}
810827
}
811828

webview/src/plots/components/App.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,6 +1880,37 @@ describe('App', () => {
18801880
within(multiImgPlots[1]).queryByRole('img')
18811881
).not.toBeInTheDocument()
18821882
})
1883+
1884+
it('should handle a plot with steps that do not increment by one', () => {
1885+
renderAppWithOptionalData({
1886+
comparison: comparisonTableFixture
1887+
})
1888+
1889+
const unusualRev = 'exp-83425'
1890+
const imgs = comparisonTableFixture.plots[3].revisions[unusualRev].imgs
1891+
const multiImgPlot = screen.getAllByTestId('multi-image-cell')[4]
1892+
1893+
const slider = within(multiImgPlot).getByRole('slider')
1894+
const imgEl = within(multiImgPlot).getByRole('img')
1895+
1896+
expect(slider).toHaveAttribute('max', '6')
1897+
1898+
expect(imgEl).toHaveAttribute('src', imgs[0].url)
1899+
expect(imgEl).toHaveAttribute(
1900+
'alt',
1901+
`1 of ${join('plots', 'image')} (exp-83425)`
1902+
)
1903+
expect(within(multiImgPlot).getByText('1')).toBeInTheDocument()
1904+
1905+
fireEvent.change(slider, { target: { value: 3 } })
1906+
1907+
expect(imgEl).toHaveAttribute('src', imgs[3].url)
1908+
expect(imgEl).toHaveAttribute(
1909+
'alt',
1910+
`7 of ${join('plots', 'image')} (exp-83425)`
1911+
)
1912+
expect(within(multiImgPlot).getByText('7')).toBeInTheDocument()
1913+
})
18831914
})
18841915

18851916
describe('Virtualization', () => {

webview/src/plots/components/comparisonTable/cell/ComparisonTableMultiCell.tsx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import React, { useEffect, useCallback, useRef, useState } from 'react'
22
import { useDispatch, useSelector } from 'react-redux'
3-
import { ComparisonPlot } from 'dvc/src/plots/webview/contract'
3+
import {
4+
ComparisonPlot,
5+
ComparisonPlotImg
6+
} from 'dvc/src/plots/webview/contract'
47
import { ComparisonTableCell } from './ComparisonTableCell'
58
import styles from '../styles.module.scss'
69
import { changeDisabledDragIds } from '../comparisonTableSlice'
@@ -18,6 +21,12 @@ export const ComparisonTableMultiCell: React.FC<{
1821
const dispatch = useDispatch()
1922
const maxStep = plot.imgs.length - 1
2023
const changeDebounceTimer = useRef(0)
24+
const selectedImg: ComparisonPlotImg = plot.imgs[currentStep] || {
25+
errors: undefined,
26+
ind: currentStep,
27+
loading: false,
28+
url: undefined
29+
}
2130

2231
const addDisabled = useCallback(() => {
2332
dispatch(changeDisabledDragIds([path]))
@@ -46,15 +55,9 @@ export const ComparisonTableMultiCell: React.FC<{
4655
path={path}
4756
plot={{
4857
id: plot.id,
49-
imgs: [
50-
plot.imgs[currentStep] || {
51-
errors: undefined,
52-
loading: false,
53-
url: undefined
54-
}
55-
]
58+
imgs: [selectedImg]
5659
}}
57-
imgAlt={`${currentStep} of ${path} (${plot.id})`}
60+
imgAlt={`${selectedImg.ind} of ${path} (${plot.id})`}
5861
/>
5962
<div
6063
className={styles.multiImageSlider}
@@ -76,7 +79,7 @@ export const ComparisonTableMultiCell: React.FC<{
7679
setCurrentStep(Number(event.target.value))
7780
}}
7881
/>
79-
<p>{currentStep}</p>
82+
<p>{selectedImg.ind}</p>
8083
</div>
8184
</div>
8285
)

webview/src/stories/ComparisonTable.stories.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,15 @@ const removeImages = (
8888
filteredRevisionData[id] = {
8989
id,
9090
imgs: isMulti
91-
? (Array.from({ length: revisionsData[id].imgs.length }).fill({
92-
errors: undefined,
93-
loading: false,
94-
url: undefined
95-
}) as ComparisonPlotImg[])
91+
? Array.from({ length: revisionsData[id].imgs.length }).map(
92+
(_, ind) =>
93+
({
94+
errors: undefined,
95+
ind,
96+
loading: false,
97+
url: undefined
98+
}) as ComparisonPlotImg
99+
)
96100
: [
97101
{
98102
errors:

0 commit comments

Comments
 (0)