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
6 changes: 3 additions & 3 deletions src/client/common/application/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ export interface ICommandNameArgumentTypeMapping extends ICommandNameWithoutArgu
[DSCommands.ScrollToCell]: [string, string];
[DSCommands.ViewJupyterOutput]: [];
[DSCommands.ExportAsPythonScript]: [INotebookModel];
[DSCommands.ExportToHTML]: [INotebookModel];
[DSCommands.ExportToPDF]: [INotebookModel];
[DSCommands.Export]: [INotebookModel];
[DSCommands.ExportToHTML]: [INotebookModel, string | undefined];
[DSCommands.ExportToPDF]: [INotebookModel, string | undefined];
[DSCommands.Export]: [INotebookModel, string | undefined];
[DSCommands.SwitchJupyterKernel]: [INotebook | undefined, 'raw' | 'jupyter'];
[DSCommands.SelectJupyterCommandLine]: [undefined | Uri];
[DSCommands.SaveNotebookNonCustomEditor]: [Uri];
Expand Down
31 changes: 20 additions & 11 deletions src/client/datascience/commands/exportCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ export class ExportCommands implements IDisposable {
) {}
public register() {
this.registerCommand(Commands.ExportAsPythonScript, (model) => this.export(model, ExportFormat.python));
this.registerCommand(Commands.ExportToHTML, (model) => this.export(model, ExportFormat.html));
this.registerCommand(Commands.ExportToPDF, (model) => this.export(model, ExportFormat.pdf));
this.registerCommand(Commands.Export, (model) => this.export(model));
this.registerCommand(Commands.ExportToHTML, (model, defaultFileName?) =>
this.export(model, ExportFormat.html, defaultFileName)
);
this.registerCommand(Commands.ExportToPDF, (model, defaultFileName?) =>
this.export(model, ExportFormat.pdf, defaultFileName)
);
this.registerCommand(Commands.Export, (model, defaultFileName?) =>
this.export(model, undefined, defaultFileName)
);
}

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

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

if (exportMethod) {
await this.exportManager.export(exportMethod, model);
await this.exportManager.export(exportMethod, model, defaultFileName);
} else {
// if we don't have an export method we need to ask for one and display the
// quickpick menu
const pickedItem = await this.showExportQuickPickMenu(model).then((item) => item);
const pickedItem = await this.showExportQuickPickMenu(model, defaultFileName).then((item) => item);
if (pickedItem !== undefined) {
pickedItem.handler();
} else {
Expand All @@ -78,7 +84,7 @@ export class ExportCommands implements IDisposable {
}
}

private getExportQuickPickItems(model: INotebookModel): IExportQuickPickItem[] {
private getExportQuickPickItems(model: INotebookModel, defaultFileName?: string): IExportQuickPickItem[] {
return [
{
label: DataScience.exportPythonQuickPickLabel(),
Expand All @@ -97,7 +103,7 @@ export class ExportCommands implements IDisposable {
sendTelemetryEvent(Telemetry.ClickedExportNotebookAsQuickPick, undefined, {
format: ExportFormat.html
});
this.commandManager.executeCommand(Commands.ExportToHTML, model);
this.commandManager.executeCommand(Commands.ExportToHTML, model, defaultFileName);
}
},
{
Expand All @@ -107,14 +113,17 @@ export class ExportCommands implements IDisposable {
sendTelemetryEvent(Telemetry.ClickedExportNotebookAsQuickPick, undefined, {
format: ExportFormat.pdf
});
this.commandManager.executeCommand(Commands.ExportToPDF, model);
this.commandManager.executeCommand(Commands.ExportToPDF, model, defaultFileName);
}
}
];
}

private async showExportQuickPickMenu(model: INotebookModel): Promise<IExportQuickPickItem | undefined> {
const items = this.getExportQuickPickItems(model);
private async showExportQuickPickMenu(
model: INotebookModel,
defaultFileName?: string
): Promise<IExportQuickPickItem | undefined> {
const items = this.getExportQuickPickItems(model, defaultFileName);

const options: QuickPickOptions = {
ignoreFocusOut: false,
Expand Down
8 changes: 6 additions & 2 deletions src/client/datascience/export/exportManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ export class ExportManager implements IExportManager {
@inject(ExportUtil) private readonly exportUtil: ExportUtil
) {}

public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
public async export(
format: ExportFormat,
model: INotebookModel,
defaultFileName?: string
): Promise<Uri | undefined> {
let target;

if (format !== ExportFormat.python) {
target = await this.filePicker.getExportFileLocation(format, model.file);
target = await this.filePicker.getExportFileLocation(format, model.file, defaultFileName);
if (!target) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export class ExportManagerDependencyChecker implements IExportManager {
@inject(ProgressReporter) private readonly progressReporter: ProgressReporter
) {}

public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
public async export(
format: ExportFormat,
model: INotebookModel,
defaultFileName?: string
): Promise<Uri | undefined> {
// Before we try the import, see if we don't support it, if we don't give a chance to install dependencies
const reporter = this.progressReporter.createProgressIndicator(`Exporting to ${format}`);
try {
Expand All @@ -29,6 +33,6 @@ export class ExportManagerDependencyChecker implements IExportManager {
} finally {
reporter.dispose();
}
return this.manager.export(format, model);
return this.manager.export(format, model, defaultFileName);
}
}
8 changes: 6 additions & 2 deletions src/client/datascience/export/exportManagerFileOpener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ export class ExportManagerFileOpener implements IExportManager {
@inject(IBrowserService) private readonly browserService: IBrowserService
) {}

public async export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined> {
public async export(
format: ExportFormat,
model: INotebookModel,
defaultFileName?: string
): Promise<Uri | undefined> {
let uri: Uri | undefined;
try {
uri = await this.manager.export(format, model);
uri = await this.manager.export(format, model, defaultFileName);
} catch (e) {
let msg = e;
traceError('Export failed', e);
Expand Down
11 changes: 9 additions & 2 deletions src/client/datascience/export/exportManagerFilePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ export class ExportManagerFilePicker implements IExportManagerFilePicker {
@inject(IMemento) @named(WORKSPACE_MEMENTO) private workspaceStorage: Memento
) {}

public async getExportFileLocation(format: ExportFormat, source: Uri): Promise<Uri | undefined> {
public async getExportFileLocation(
format: ExportFormat,
source: Uri,
defaultFileName?: string
): Promise<Uri | undefined> {
// map each export method to a set of file extensions
let fileExtensions;
switch (format) {
Expand All @@ -40,7 +44,10 @@ export class ExportManagerFilePicker implements IExportManagerFilePicker {
return;
}

const notebookFileName = path.basename(source.fsPath, path.extname(source.fsPath));
const notebookFileName = defaultFileName
? defaultFileName
: path.basename(source.fsPath, path.extname(source.fsPath));

const dialogUri = Uri.file(path.join(this.getLastFileSaveLocation().fsPath, notebookFileName));
const options: SaveDialogOptions = {
defaultUri: dialogUri,
Expand Down
4 changes: 2 additions & 2 deletions src/client/datascience/export/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export enum ExportFormat {

export const IExportManager = Symbol('IExportManager');
export interface IExportManager {
export(format: ExportFormat, model: INotebookModel): Promise<Uri | undefined>;
export(format: ExportFormat, model: INotebookModel, defaultFileName?: string): Promise<Uri | undefined>;
}

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

export const IExportManagerFilePicker = Symbol('IExportManagerFilePicker');
export interface IExportManagerFilePicker {
getExportFileLocation(format: ExportFormat, source: Uri): Promise<Uri | undefined>;
getExportFileLocation(format: ExportFormat, source: Uri, defaultFileName?: string): Promise<Uri | undefined>;
}
2 changes: 1 addition & 1 deletion src/client/datascience/interactive-ipynb/nativeEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ export class NativeEditor extends InteractiveBase implements INotebookEditor {
if (!activeEditor || !activeEditor.model) {
return;
}
this.commandManager.executeCommand(Commands.Export, activeEditor.model);
this.commandManager.executeCommand(Commands.Export, activeEditor.model, undefined);
}

private logNativeCommand(args: INativeCommand) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,11 @@ export class InteractiveWindow extends InteractiveBase implements IInteractiveWi
this.stopProgress();
}
if (model) {
this.commandManager.executeCommand(Commands.Export, model);
let defaultFileName;
if (this.lastFile) {
defaultFileName = path.basename(this.lastFile, path.extname(this.lastFile));
}
this.commandManager.executeCommand(Commands.Export, model, defaultFileName);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/test/datascience/export/exportManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ suite('Data Science - Export Manager', () => {
exportPdf = mock<IExport>();

// tslint:disable-next-line: no-any
when(filePicker.getExportFileLocation(anything(), anything())).thenReturn(
when(filePicker.getExportFileLocation(anything(), anything(), anything())).thenReturn(
Promise.resolve(Uri.file('test.pdf'))
);
// tslint:disable-next-line: no-empty
Expand Down
12 changes: 6 additions & 6 deletions src/test/datascience/export/exportManagerFileOpener.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,20 @@ suite('Data Science - Export File Opener', () => {

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

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

verify(documentManager.showTextDocument(anything())).once();
});
test('HTML File opened if yes button pressed', async () => {
const uri = Uri.file('test.html');
when(exporter.export(anything(), anything())).thenResolve(uri);
when(exporter.export(anything(), anything(), anything())).thenResolve(uri);
when(applicationShell.showInformationMessage(anything(), anything(), anything())).thenReturn(
Promise.resolve(getLocString('DataScience.openExportFileYes', 'Yes'))
);
Expand All @@ -82,14 +82,14 @@ suite('Data Science - Export File Opener', () => {
verify(browserService.launch(anything())).never();
});
test('Exporting to PDF displays message if operation fails', async () => {
when(exporter.export(anything(), anything())).thenThrow(new Error('Export failed...'));
when(exporter.export(anything(), anything(), anything())).thenThrow(new Error('Export failed...'));
when(applicationShell.showErrorMessage(anything())).thenResolve();
await fileOpener.export(ExportFormat.pdf, model);
verify(applicationShell.showErrorMessage(anything())).once();
});
test('PDF File opened if yes button pressed', async () => {
const uri = Uri.file('test.pdf');
when(exporter.export(anything(), anything())).thenResolve(uri);
when(exporter.export(anything(), anything(), anything())).thenResolve(uri);
when(applicationShell.showInformationMessage(anything(), anything(), anything())).thenReturn(
Promise.resolve(getLocString('DataScience.openExportFileYes', 'Yes'))
);
Expand Down
2 changes: 1 addition & 1 deletion src/test/datascience/nativeEditor.functional.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ df.head()`;
const model = editor!.model!;
ioc.serviceManager.rebindInstance<ICommandManager>(ICommandManager, commandManager.object);
commandManager
.setup((cmd) => cmd.executeCommand(Commands.Export, model))
.setup((cmd) => cmd.executeCommand(Commands.Export, model, undefined))
.returns(() => {
commandFired.resolve();
return Promise.resolve();
Expand Down