Skip to content

Commit 6bd129a

Browse files
authored
Changed default save name when exporting from interactive window (#12815)
* changed default export file name from interactice window * fixed naming issue * refactor * fixed tests * hopefully fixed test
1 parent ca921a6 commit 6bd129a

File tree

12 files changed

+66
-34
lines changed

12 files changed

+66
-34
lines changed

src/client/common/application/commands.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ export interface ICommandNameArgumentTypeMapping extends ICommandNameWithoutArgu
173173
[DSCommands.ScrollToCell]: [string, string];
174174
[DSCommands.ViewJupyterOutput]: [];
175175
[DSCommands.ExportAsPythonScript]: [INotebookModel];
176-
[DSCommands.ExportToHTML]: [INotebookModel];
177-
[DSCommands.ExportToPDF]: [INotebookModel];
178-
[DSCommands.Export]: [INotebookModel];
176+
[DSCommands.ExportToHTML]: [INotebookModel, string | undefined];
177+
[DSCommands.ExportToPDF]: [INotebookModel, string | undefined];
178+
[DSCommands.Export]: [INotebookModel, string | undefined];
179179
[DSCommands.SwitchJupyterKernel]: [INotebook | undefined, 'raw' | 'jupyter'];
180180
[DSCommands.SelectJupyterCommandLine]: [undefined | Uri];
181181
[DSCommands.SaveNotebookNonCustomEditor]: [Uri];

src/client/datascience/commands/exportCommands.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,15 @@ export class ExportCommands implements IDisposable {
3131
) {}
3232
public register() {
3333
this.registerCommand(Commands.ExportAsPythonScript, (model) => this.export(model, ExportFormat.python));
34-
this.registerCommand(Commands.ExportToHTML, (model) => this.export(model, ExportFormat.html));
35-
this.registerCommand(Commands.ExportToPDF, (model) => this.export(model, ExportFormat.pdf));
36-
this.registerCommand(Commands.Export, (model) => this.export(model));
34+
this.registerCommand(Commands.ExportToHTML, (model, defaultFileName?) =>
35+
this.export(model, ExportFormat.html, defaultFileName)
36+
);
37+
this.registerCommand(Commands.ExportToPDF, (model, defaultFileName?) =>
38+
this.export(model, ExportFormat.pdf, defaultFileName)
39+
);
40+
this.registerCommand(Commands.Export, (model, defaultFileName?) =>
41+
this.export(model, undefined, defaultFileName)
42+
);
3743
}
3844

3945
public dispose() {
@@ -49,7 +55,7 @@ export class ExportCommands implements IDisposable {
4955
this.disposables.push(disposable);
5056
}
5157

52-
private async export(model: INotebookModel, exportMethod?: ExportFormat) {
58+
private async export(model: INotebookModel, exportMethod?: ExportFormat, defaultFileName?: string) {
5359
if (!model) {
5460
// if no model was passed then this was called from the command pallete,
5561
// so we need to get the active editor
@@ -65,11 +71,11 @@ export class ExportCommands implements IDisposable {
6571
}
6672

6773
if (exportMethod) {
68-
await this.exportManager.export(exportMethod, model);
74+
await this.exportManager.export(exportMethod, model, defaultFileName);
6975
} else {
7076
// if we don't have an export method we need to ask for one and display the
7177
// quickpick menu
72-
const pickedItem = await this.showExportQuickPickMenu(model).then((item) => item);
78+
const pickedItem = await this.showExportQuickPickMenu(model, defaultFileName).then((item) => item);
7379
if (pickedItem !== undefined) {
7480
pickedItem.handler();
7581
} else {
@@ -78,7 +84,7 @@ export class ExportCommands implements IDisposable {
7884
}
7985
}
8086

81-
private getExportQuickPickItems(model: INotebookModel): IExportQuickPickItem[] {
87+
private getExportQuickPickItems(model: INotebookModel, defaultFileName?: string): IExportQuickPickItem[] {
8288
return [
8389
{
8490
label: DataScience.exportPythonQuickPickLabel(),
@@ -97,7 +103,7 @@ export class ExportCommands implements IDisposable {
97103
sendTelemetryEvent(Telemetry.ClickedExportNotebookAsQuickPick, undefined, {
98104
format: ExportFormat.html
99105
});
100-
this.commandManager.executeCommand(Commands.ExportToHTML, model);
106+
this.commandManager.executeCommand(Commands.ExportToHTML, model, defaultFileName);
101107
}
102108
},
103109
{
@@ -107,14 +113,17 @@ export class ExportCommands implements IDisposable {
107113
sendTelemetryEvent(Telemetry.ClickedExportNotebookAsQuickPick, undefined, {
108114
format: ExportFormat.pdf
109115
});
110-
this.commandManager.executeCommand(Commands.ExportToPDF, model);
116+
this.commandManager.executeCommand(Commands.ExportToPDF, model, defaultFileName);
111117
}
112118
}
113119
];
114120
}
115121

116-
private async showExportQuickPickMenu(model: INotebookModel): Promise<IExportQuickPickItem | undefined> {
117-
const items = this.getExportQuickPickItems(model);
122+
private async showExportQuickPickMenu(
123+
model: INotebookModel,
124+
defaultFileName?: string
125+
): Promise<IExportQuickPickItem | undefined> {
126+
const items = this.getExportQuickPickItems(model, defaultFileName);
118127

119128
const options: QuickPickOptions = {
120129
ignoreFocusOut: false,

src/client/datascience/export/exportManager.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,15 @@ export class ExportManager implements IExportManager {
1919
@inject(ExportUtil) private readonly exportUtil: ExportUtil
2020
) {}
2121

22-
public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
22+
public async export(
23+
format: ExportFormat,
24+
model: INotebookModel,
25+
defaultFileName?: string
26+
): Promise<Uri | undefined> {
2327
let target;
2428

2529
if (format !== ExportFormat.python) {
26-
target = await this.filePicker.getExportFileLocation(format, model.file);
30+
target = await this.filePicker.getExportFileLocation(format, model.file, defaultFileName);
2731
if (!target) {
2832
return;
2933
}

src/client/datascience/export/exportManagerDependencyChecker.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ export class ExportManagerDependencyChecker implements IExportManager {
1616
@inject(ProgressReporter) private readonly progressReporter: ProgressReporter
1717
) {}
1818

19-
public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
19+
public async export(
20+
format: ExportFormat,
21+
model: INotebookModel,
22+
defaultFileName?: string
23+
): Promise<Uri | undefined> {
2024
// Before we try the import, see if we don't support it, if we don't give a chance to install dependencies
2125
const reporter = this.progressReporter.createProgressIndicator(`Exporting to ${format}`);
2226
try {
@@ -29,6 +33,6 @@ export class ExportManagerDependencyChecker implements IExportManager {
2933
} finally {
3034
reporter.dispose();
3135
}
32-
return this.manager.export(format, model);
36+
return this.manager.export(format, model, defaultFileName);
3337
}
3438
}

src/client/datascience/export/exportManagerFileOpener.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ export class ExportManagerFileOpener implements IExportManager {
2222
@inject(IBrowserService) private readonly browserService: IBrowserService
2323
) {}
2424

25-
public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
25+
public async export(
26+
format: ExportFormat,
27+
model: INotebookModel,
28+
defaultFileName?: string
29+
): Promise<Uri | undefined> {
2630
let uri: Uri | undefined;
2731
try {
28-
uri = await this.manager.export(format, model);
32+
uri = await this.manager.export(format, model, defaultFileName);
2933
} catch (e) {
3034
let msg = e;
3135
traceError('Export failed', e);

src/client/datascience/export/exportManagerFilePicker.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@ export class ExportManagerFilePicker implements IExportManagerFilePicker {
2020
@inject(IMemento) @named(WORKSPACE_MEMENTO) private workspaceStorage: Memento
2121
) {}
2222

23-
public async getExportFileLocation(format: ExportFormat, source: Uri): Promise<Uri | undefined> {
23+
public async getExportFileLocation(
24+
format: ExportFormat,
25+
source: Uri,
26+
defaultFileName?: string
27+
): Promise<Uri | undefined> {
2428
// map each export method to a set of file extensions
2529
let fileExtensions;
2630
switch (format) {
@@ -40,7 +44,10 @@ export class ExportManagerFilePicker implements IExportManagerFilePicker {
4044
return;
4145
}
4246

43-
const notebookFileName = path.basename(source.fsPath, path.extname(source.fsPath));
47+
const notebookFileName = defaultFileName
48+
? defaultFileName
49+
: path.basename(source.fsPath, path.extname(source.fsPath));
50+
4451
const dialogUri = Uri.file(path.join(this.getLastFileSaveLocation().fsPath, notebookFileName));
4552
const options: SaveDialogOptions = {
4653
defaultUri: dialogUri,

src/client/datascience/export/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export enum ExportFormat {
99

1010
export const IExportManager = Symbol('IExportManager');
1111
export interface IExportManager {
12-
export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined>;
12+
export(format: ExportFormat, model: INotebookModel, defaultFileName?: string): Promise<Uri | undefined>;
1313
}
1414

1515
export const IExport = Symbol('IExport');
@@ -19,5 +19,5 @@ export interface IExport {
1919

2020
export const IExportManagerFilePicker = Symbol('IExportManagerFilePicker');
2121
export interface IExportManagerFilePicker {
22-
getExportFileLocation(format: ExportFormat, source: Uri): Promise<Uri | undefined>;
22+
getExportFileLocation(format: ExportFormat, source: Uri, defaultFileName?: string): Promise<Uri | undefined>;
2323
}

src/client/datascience/interactive-ipynb/nativeEditor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
730730
if (!activeEditor || !activeEditor.model) {
731731
return;
732732
}
733-
this.commandManager.executeCommand(Commands.Export, activeEditor.model);
733+
this.commandManager.executeCommand(Commands.Export, activeEditor.model, undefined);
734734
}
735735

736736
private logNativeCommand(args: INativeCommand) {

src/client/datascience/interactive-window/interactiveWindow.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,11 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi
437437
this.stopProgress();
438438
}
439439
if (model) {
440-
this.commandManager.executeCommand(Commands.Export, model);
440+
let defaultFileName;
441+
if (this.lastFile) {
442+
defaultFileName = path.basename(this.lastFile, path.extname(this.lastFile));
443+
}
444+
this.commandManager.executeCommand(Commands.Export, model, defaultFileName);
441445
}
442446
}
443447

src/test/datascience/export/exportManager.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ suite('Data Science - Export Manager', () => {
3333
exportPdf = mock<IExport>();
3434

3535
// tslint:disable-next-line: no-any
36-
when(filePicker.getExportFileLocation(anything(), anything())).thenReturn(
36+
when(filePicker.getExportFileLocation(anything(), anything(), anything())).thenReturn(
3737
Promise.resolve(Uri.file('test.pdf'))
3838
);
3939
// tslint:disable-next-line: no-empty

src/test/datascience/export/exportManagerFileOpener.unit.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,20 @@ suite('Data Science - Export File Opener', () => {
4848

4949
test('No file is opened if nothing is exported', async () => {
5050
when(exporter.export(anything(), anything())).thenResolve();
51-
await fileOpener.export(ExportFormat.python, model);
51+
await fileOpener.export(ExportFormat.python, model, undefined);
5252

5353
verify(documentManager.showTextDocument(anything())).never();
5454
});
5555
test('Python File is opened if exported', async () => {
5656
const uri = Uri.file('test.python');
57-
when(exporter.export(anything(), anything())).thenResolve(uri);
58-
await fileOpener.export(ExportFormat.python, model);
57+
when(exporter.export(anything(), anything(), anything())).thenResolve(uri);
58+
await fileOpener.export(ExportFormat.python, model, undefined);
5959

6060
verify(documentManager.showTextDocument(anything())).once();
6161
});
6262
test('HTML File opened if yes button pressed', async () => {
6363
const uri = Uri.file('test.html');
64-
when(exporter.export(anything(), anything())).thenResolve(uri);
64+
when(exporter.export(anything(), anything(), anything())).thenResolve(uri);
6565
when(applicationShell.showInformationMessage(anything(), anything(), anything())).thenReturn(
6666
Promise.resolve(getLocString('DataScience.openExportFileYes', 'Yes'))
6767
);
@@ -82,14 +82,14 @@ suite('Data Science - Export File Opener', () => {
8282
verify(browserService.launch(anything())).never();
8383
});
8484
test('Exporting to PDF displays message if operation fails', async () => {
85-
when(exporter.export(anything(), anything())).thenThrow(new Error('Export failed...'));
85+
when(exporter.export(anything(), anything(), anything())).thenThrow(new Error('Export failed...'));
8686
when(applicationShell.showErrorMessage(anything())).thenResolve();
8787
await fileOpener.export(ExportFormat.pdf, model);
8888
verify(applicationShell.showErrorMessage(anything())).once();
8989
});
9090
test('PDF File opened if yes button pressed', async () => {
9191
const uri = Uri.file('test.pdf');
92-
when(exporter.export(anything(), anything())).thenResolve(uri);
92+
when(exporter.export(anything(), anything(), anything())).thenResolve(uri);
9393
when(applicationShell.showInformationMessage(anything(), anything(), anything())).thenReturn(
9494
Promise.resolve(getLocString('DataScience.openExportFileYes', 'Yes'))
9595
);

src/test/datascience/nativeEditor.functional.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ df.head()`;
630630
const model = editor!.model!;
631631
ioc.serviceManager.rebindInstance<ICommandManager>(ICommandManager, commandManager.object);
632632
commandManager
633-
.setup((cmd) => cmd.executeCommand(Commands.Export, model))
633+
.setup((cmd) => cmd.executeCommand(Commands.Export, model, undefined))
634634
.returns(() => {
635635
commandFired.resolve();
636636
return Promise.resolve();

0 commit comments

Comments
 (0)