Skip to content

Commit 0226b4c

Browse files
authored
Add title option to plot wizard (#4786)
1 parent 509fec2 commit 0226b4c

File tree

6 files changed

+74
-21
lines changed

6 files changed

+74
-21
lines changed

extension/src/fileSystem/index.test.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ describe('addPlotToDvcYamlFile', () => {
608608
' eval/prc/test.json: precision'
609609
]
610610
const mockNewPlotLines = [
611-
' - simple_plot:',
611+
' - Simple Plot:',
612612
' template: simple',
613613
' x: epochs',
614614
' y:',
@@ -624,6 +624,7 @@ describe('addPlotToDvcYamlFile', () => {
624624

625625
addPlotToDvcYamlFile('/', {
626626
template: 'simple',
627+
title: 'Simple Plot',
627628
x: { file: 'data.json', key: 'epochs' },
628629
y: { file: 'data.json', key: 'accuracy' }
629630
})
@@ -652,6 +653,7 @@ describe('addPlotToDvcYamlFile', () => {
652653

653654
addPlotToDvcYamlFile('/', {
654655
template: 'simple',
656+
title: 'simple_plot',
655657
x: { file: 'data.json', key: 'epochs' },
656658
y: { file: 'acc.json', key: 'accuracy' }
657659
})
@@ -670,6 +672,7 @@ describe('addPlotToDvcYamlFile', () => {
670672

671673
addPlotToDvcYamlFile('/', {
672674
template: 'simple',
675+
title: 'Simple Plot',
673676
x: { file: 'data.json', key: 'epochs' },
674677
y: { file: 'data.json', key: 'accuracy' }
675678
})
@@ -692,6 +695,7 @@ describe('addPlotToDvcYamlFile', () => {
692695

693696
addPlotToDvcYamlFile('/', {
694697
template: 'simple',
698+
title: 'Simple Plot',
695699
x: { file: 'data.json', key: 'epochs' },
696700
y: { file: 'data.json', key: 'accuracy' }
697701
})
@@ -729,6 +733,7 @@ describe('addPlotToDvcYamlFile', () => {
729733

730734
addPlotToDvcYamlFile('/', {
731735
template: 'simple',
736+
title: 'simple_plot',
732737
x: { file: 'data.json', key: 'epochs' },
733738
y: { file: 'data.json', key: 'accuracy' }
734739
})

extension/src/fileSystem/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,9 @@ const loadYamlAsDoc = (
215215
}
216216

217217
const getPlotYamlObj = (plot: PlotConfigData) => {
218-
const { x, y, template } = plot
219-
const plotName = `${template}_plot`
218+
const { x, y, template, title } = plot
220219
return {
221-
[plotName]: {
220+
[title]: {
222221
template,
223222
x: x.file === y.file ? x.key : { [x.file]: x.key },
224223
y: { [y.file]: y.key }

extension/src/pipeline/quickPick.test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { QuickPickItemKind } from 'vscode'
22
import { pickPlotConfiguration } from './quickPick'
3+
import { getInput } from '../vscode/inputBox'
34
import { pickFiles } from '../vscode/resourcePicker'
45
import { quickPickOne, quickPickValue } from '../vscode/quickPick'
56
import { getFileExtension, loadDataFiles } from '../fileSystem'
@@ -9,13 +10,15 @@ import { Toast } from '../vscode/toast'
910
const mockedPickFiles = jest.mocked(pickFiles)
1011
const mockedLoadDataFiles = jest.mocked(loadDataFiles)
1112
const mockedGetFileExt = jest.mocked(getFileExtension)
13+
const mockedGetInput = jest.mocked(getInput)
1214
const mockedQuickPickOne = jest.mocked(quickPickOne)
1315
const mockedQuickPickValue = jest.mocked(quickPickValue)
1416
const mockedToast = jest.mocked(Toast)
1517
const mockedShowError = jest.fn()
1618
mockedToast.showError = mockedShowError
1719

1820
jest.mock('../fileSystem')
21+
jest.mock('../vscode/inputBox')
1922
jest.mock('../vscode/resourcePicker')
2023
jest.mock('../vscode/quickPick')
2124

@@ -250,7 +253,7 @@ describe('pickPlotConfiguration', () => {
250253
expect(mockedShowError).not.toHaveBeenCalled()
251254
})
252255

253-
it('should let the user pick a template, x field, and y field', async () => {
256+
it('should let the user pick a template, x field, y field and title', async () => {
254257
mockedPickFiles.mockResolvedValueOnce(['/file.json'])
255258
mockedLoadDataFiles.mockResolvedValueOnce([
256259
{ data: mockValidData, file: '/file.json' }
@@ -259,6 +262,7 @@ describe('pickPlotConfiguration', () => {
259262
mockedQuickPickValue
260263
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
261264
.mockResolvedValueOnce({ file: 'file.json', key: 'prob' })
265+
mockedGetInput.mockResolvedValueOnce('Simple Plot')
262266

263267
const result = await pickPlotConfiguration('/')
264268

@@ -304,8 +308,13 @@ describe('pickPlotConfiguration', () => {
304308
title: Title.SELECT_PLOT_Y_METRIC
305309
}
306310
)
311+
expect(mockedGetInput).toHaveBeenCalledWith(
312+
Title.ENTER_PLOT_TITLE,
313+
'actual vs prob'
314+
)
307315
expect(result).toStrictEqual({
308316
template: 'simple',
317+
title: 'Simple Plot',
309318
x: { file: 'file.json', key: 'actual' },
310319
y: { file: 'file.json', key: 'prob' }
311320
})
@@ -318,6 +327,7 @@ describe('pickPlotConfiguration', () => {
318327
{ data: mockValidData, file: '/file2.json' }
319328
])
320329
mockedQuickPickOne.mockResolvedValueOnce('simple')
330+
mockedGetInput.mockResolvedValueOnce('simple_plot')
321331
mockedQuickPickValue
322332
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
323333
.mockResolvedValueOnce({ file: 'file2.json', key: 'prob' })
@@ -367,6 +377,7 @@ describe('pickPlotConfiguration', () => {
367377
)
368378
expect(result).toStrictEqual({
369379
template: 'simple',
380+
title: 'simple_plot',
370381
x: { file: 'file.json', key: 'actual' },
371382
y: { file: 'file2.json', key: 'prob' }
372383
})
@@ -392,6 +403,7 @@ describe('pickPlotConfiguration', () => {
392403
{ data: mockValidData, file: 'file.json' }
393404
])
394405
mockedQuickPickOne.mockResolvedValueOnce('simple')
406+
mockedGetInput.mockResolvedValueOnce('simple_plot')
395407
mockedQuickPickValue.mockResolvedValueOnce(undefined)
396408

397409
const result = await pickPlotConfiguration('/')
@@ -406,6 +418,7 @@ describe('pickPlotConfiguration', () => {
406418
{ data: mockValidData, file: 'file.json' }
407419
])
408420
mockedQuickPickOne.mockResolvedValueOnce('simple')
421+
mockedGetInput.mockResolvedValueOnce('simple_plot')
409422
mockedQuickPickValue
410423
.mockResolvedValueOnce('actual')
411424
.mockResolvedValueOnce(undefined)
@@ -415,4 +428,21 @@ describe('pickPlotConfiguration', () => {
415428
expect(mockedQuickPickValue).toHaveBeenCalledTimes(2)
416429
expect(result).toStrictEqual(undefined)
417430
})
431+
432+
it('should return early if the user does not pick a title', async () => {
433+
mockedPickFiles.mockResolvedValueOnce(['/file.json'])
434+
mockedLoadDataFiles.mockResolvedValueOnce([
435+
{ data: mockValidData, file: 'file.json' }
436+
])
437+
mockedQuickPickOne.mockResolvedValueOnce('linear')
438+
mockedQuickPickValue
439+
.mockResolvedValueOnce({ file: 'file.json', key: 'actual' })
440+
.mockResolvedValueOnce({ file: 'file.json', key: 'prob' })
441+
mockedGetInput.mockResolvedValueOnce(undefined)
442+
443+
const result = await pickPlotConfiguration('/')
444+
445+
expect(mockedGetInput).toHaveBeenCalledTimes(1)
446+
expect(result).toStrictEqual(undefined)
447+
})
418448
})

extension/src/pipeline/quickPick.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import { quickPickOne, quickPickValue } from '../vscode/quickPick'
1212
import { pickFiles } from '../vscode/resourcePicker'
1313
import { Title } from '../vscode/title'
1414
import { Toast } from '../vscode/toast'
15+
import { getInput } from '../vscode/inputBox'
1516

1617
export type PlotConfigData = {
1718
x: { file: string; key: string }
1819
template: string
20+
title: string
1921
y: { file: string; key: string }
2022
}
2123

@@ -28,15 +30,9 @@ const pickDataFiles = (): Promise<string[] | undefined> =>
2830
'Data Formats': ['json', 'csv', 'tsv', 'yaml']
2931
})
3032

31-
const pickTemplateAndFields = async (
33+
const pickFields = async (
3234
fileFields: FileFields
33-
): Promise<PlotConfigData | undefined> => {
34-
const template = await quickPickOne(PLOT_TEMPLATES, 'Pick a Plot Template')
35-
36-
if (!template) {
37-
return
38-
}
39-
35+
): Promise<Omit<PlotConfigData, 'title' | 'template'> | undefined> => {
4036
const items = []
4137

4238
for (const { file, fields } of fileFields) {
@@ -65,7 +61,34 @@ const pickTemplateAndFields = async (
6561
return
6662
}
6763

68-
return { template, x, y }
64+
return { x, y }
65+
}
66+
67+
const pickPlotConfigData = async (
68+
fileFields: FileFields
69+
): Promise<PlotConfigData | undefined> => {
70+
const template = await quickPickOne(PLOT_TEMPLATES, 'Pick a Plot Template')
71+
72+
if (!template) {
73+
return
74+
}
75+
76+
const fields = await pickFields(fileFields)
77+
78+
if (!fields) {
79+
return
80+
}
81+
82+
const title = await getInput(
83+
Title.ENTER_PLOT_TITLE,
84+
`${fields.x.key} vs ${fields.y.key}`
85+
)
86+
87+
if (!title) {
88+
return
89+
}
90+
91+
return { template, title, ...fields }
6992
}
7093

7194
const joinList = (items: string[]) => {
@@ -222,11 +245,5 @@ export const pickPlotConfiguration = async (
222245
return
223246
}
224247

225-
const templateAndFields = await pickTemplateAndFields(validFileFields)
226-
227-
if (!templateAndFields) {
228-
return
229-
}
230-
231-
return { ...templateAndFields }
248+
return pickPlotConfigData(validFileFields)
232249
}

extension/src/test/suite/pipeline/index.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ suite('Pipeline Test Suite', () => {
311311

312312
mockPickPlotConfiguration.onSecondCall().resolves({
313313
template: 'simple',
314+
title: 'Great Plot Name',
314315
x: { file: 'results.json', key: 'step' },
315316
y: { file: 'results.json', key: 'acc' }
316317
})

extension/src/vscode/title.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export enum Title {
1010
ENTER_REMOTE_NAME = 'Enter a Name for the Remote',
1111
ENTER_REMOTE_URL = 'Enter the URL for the Remote',
1212
ENTER_PATH_OR_CHOOSE_FILE = 'Enter the path to your training script or select it',
13+
ENTER_PLOT_TITLE = 'Enter a Name for Your Plot',
1314
ENTER_STUDIO_USERNAME = 'Enter your Studio username',
1415
ENTER_STUDIO_TOKEN = 'Enter your Studio access token',
1516
ENTER_STAGE_NAME = 'Enter a Name for the Main Stage of your Pipeline',

0 commit comments

Comments
 (0)