Run All Cells Notebook Implementation (#4713)

* runAllCells API

* add comment

* more run cells fixes

* Add integration test

* Add multiple cell SQL notebook test

* Comment out python tests as they fail in the lab

* remove unused imports

* PR comments

* Remove localize

* Return true instead of promise.resolve(true)
This commit is contained in:
Chris LaFreniere
2019-04-02 16:47:00 -07:00
committed by GitHub
parent 219dfe66d0
commit 07166fb3cd
13 changed files with 165 additions and 11 deletions

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1{fill:none;}.cls-2{fill:#fff;}.cls-3{clip-path:url(#clip-path);}</style><clipPath id="clip-path"><rect class="cls-1" x="-552.55" y="-7.09" width="15.81" height="13.48"/></clipPath></defs><title>run_cells_inverse</title><path class="cls-2" d="M8,15.92a8,8,0,1,1,8-8A8,8,0,0,1,8,15.92ZM8,1a7,7,0,1,0,7,7A7,7,0,0,0,8,1Z"/><polygon class="cls-2" points="10.7 8 6.67 11 6.67 5 10.7 8 10.7 8"/></svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}</style><clipPath id="clip-path"><rect class="cls-1" x="-579.3" y="-7.09" width="15.81" height="13.48"/></clipPath></defs><title>run_cells</title><path d="M8,15.92a8,8,0,1,1,8-8A8,8,0,0,1,8,15.92ZM8,1a7,7,0,1,0,7,7A7,7,0,0,0,8,1Z"/><polygon points="10.7 8 6.67 11 6.67 5 10.7 8 10.7 8"/></svg>

After

Width:  |  Height:  |  Size: 494 B

View File

@@ -33,7 +33,7 @@ import * as notebookUtils from 'sql/parts/notebook/notebookUtils';
import { Deferred } from 'sql/base/common/promise';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, ClearAllOutputsAction } from 'sql/parts/notebook/notebookActions';
import { KernelsDropdown, AttachToDropdown, AddCellAction, TrustedAction, RunAllCellsAction, ClearAllOutputsAction } from 'sql/parts/notebook/notebookActions';
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/common/objectExplorerService';
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
@@ -63,6 +63,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
private _modelRegisteredDeferred = new Deferred<NotebookModel>();
private profile: IConnectionProfile;
private _trustedAction: TrustedAction;
private _runAllCellsAction: RunAllCellsAction;
private _providerRelatedActions: IAction[] = [];
private _scrollTop: number;
@@ -372,6 +373,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
let addTextCellButton = new AddCellAction('notebook.AddTextCell', localize('text', 'Text'), 'notebook-button icon-add');
addTextCellButton.cellType = CellTypes.Markdown;
this._runAllCellsAction = new RunAllCellsAction('notebook.runAllCells', localize('runAll', 'Run Cells'), 'notebook-button icon-run-cells');
let clearResultsButton = new ClearAllOutputsAction('notebook.ClearAllOutputs', localize('clearResults', 'Clear Results'), 'notebook-button icon-clear-results');
this._trustedAction = this.instantiationService.createInstance(TrustedAction, 'notebook.Trusted');
@@ -386,6 +388,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
{ action: addCodeCellButton },
{ action: addTextCellButton },
{ action: this._trustedAction },
{ action: this._runAllCellsAction },
{ action: clearResultsButton }
]);
@@ -483,6 +486,20 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
}
}
public async runAllCells(): Promise<boolean> {
await this.modelReady;
let codeCells = this._model.cells.filter(cell => cell.cellType === CellTypes.Code);
if (codeCells && codeCells.length) {
for (let i = 0; i < codeCells.length; i++) {
let cellStatus = await this.runCell(codeCells[i]);
if (!cellStatus) {
return Promise.reject(new Error(localize('cellRunFailed', 'running cell id {0} failed', codeCells[i].id)));
}
}
}
return true;
}
public async clearAllOutputs(): Promise<boolean> {
try {
await this.modelReady;

View File

@@ -50,6 +50,15 @@
background-image: url("./media/dark/add_inverse.svg");
}
.notebookEditor .notebook-button.icon-run-cells{
background-image: url("./media/light/run_cells.svg");
}
.vs-dark .notebookEditor .notebook-button.icon-run-cells,
.hc-black .notebookEditor .notebook-button.icon-run-cells{
background-image: url("./media/dark/run_cells_inverse.svg");
}
.notebookEditor .notebook-button.icon-trusted{
background-image: url("./media/light/trusted.svg");
}

View File

@@ -227,6 +227,25 @@ export class TrustedAction extends ToggleableAction {
}
}
// Action to run all code cells in a notebook.
export class RunAllCellsAction extends Action {
constructor(
id: string, label: string, cssClass: string
) {
super(id, label, cssClass);
}
public run(context: NotebookComponent): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
try {
context.runAllCells();
resolve(true);
} catch (e) {
reject(e);
}
});
}
}
export class KernelsDropdown extends SelectBox {
private model: NotebookModel;
constructor(container: HTMLElement, contextViewProvider: IContextViewProvider, modelReady: Promise<INotebookModel>) {