mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-20 09:35:38 -05:00
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:
6
src/sql/azdata.proposed.d.ts
vendored
6
src/sql/azdata.proposed.d.ts
vendored
@@ -4035,7 +4035,11 @@ declare module 'azdata' {
|
||||
runCell(cell?: NotebookCell): Thenable<boolean>;
|
||||
|
||||
/**
|
||||
* Clears the outputs of all code cells in a Notebook
|
||||
* Kicks off execution of all code cells. Thenable will resolve only when full execution of all cells is completed.
|
||||
*/
|
||||
runAllCells(): Thenable<boolean>;
|
||||
|
||||
/** Clears the outputs of all code cells in a Notebook
|
||||
* @return A promise that resolves with a value indicating if the outputs are cleared or not.
|
||||
*/
|
||||
clearAllOutputs(): Thenable<boolean>;
|
||||
|
||||
1
src/sql/parts/notebook/media/dark/run_cells_inverse.svg
Normal file
1
src/sql/parts/notebook/media/dark/run_cells_inverse.svg
Normal 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 |
1
src/sql/parts/notebook/media/light/run_cells.svg
Normal file
1
src/sql/parts/notebook/media/light/run_cells.svg
Normal 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 |
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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>) {
|
||||
|
||||
@@ -156,6 +156,10 @@ export class ExtHostNotebookEditor implements azdata.nb.NotebookEditor, IDisposa
|
||||
return this._proxy.$runCell(this._id, uri);
|
||||
}
|
||||
|
||||
public runAllCells(): Thenable<boolean> {
|
||||
return this._proxy.$runAllCells(this._id);
|
||||
}
|
||||
|
||||
public clearAllOutputs(): Thenable<boolean> {
|
||||
return this._proxy.$clearAllOutputs(this._id);
|
||||
}
|
||||
|
||||
@@ -122,10 +122,16 @@ class MainThreadNotebookEditor extends Disposable {
|
||||
if (!this.editor) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this.editor.runCell(cell);
|
||||
}
|
||||
|
||||
public runAllCells(): Promise<boolean> {
|
||||
if (!this.editor) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
return this.editor.runAllCells();
|
||||
}
|
||||
|
||||
public clearAllOutputs(): Promise<boolean> {
|
||||
if (!this.editor) {
|
||||
return Promise.resolve(false);
|
||||
@@ -366,6 +372,14 @@ export class MainThreadNotebookDocumentsAndEditors extends Disposable implements
|
||||
return editor.runCell(cell);
|
||||
}
|
||||
|
||||
$runAllCells(id: string): Promise<boolean> {
|
||||
let editor = this.getEditor(id);
|
||||
if (!editor) {
|
||||
return Promise.reject(disposed(`TextEditor(${id})`));
|
||||
}
|
||||
return editor.runAllCells();
|
||||
}
|
||||
|
||||
$clearAllOutputs(id: string): Promise<boolean> {
|
||||
let editor = this.getEditor(id);
|
||||
if (!editor) {
|
||||
|
||||
@@ -866,6 +866,7 @@ export interface MainThreadNotebookDocumentsAndEditorsShape extends IDisposable
|
||||
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): Promise<string>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleNotebookEditOperation[], opts: IUndoStopOptions): Promise<boolean>;
|
||||
$runCell(id: string, cellUri: UriComponents): Promise<boolean>;
|
||||
$runAllCells(id: string): Promise<boolean>;
|
||||
$clearAllOutputs(id: string): Promise<boolean>;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,5 +109,6 @@ export interface INotebookEditor {
|
||||
isVisible(): boolean;
|
||||
executeEdits(edits: ISingleNotebookEditOperation[]): boolean;
|
||||
runCell(cell: ICellModel): Promise<boolean>;
|
||||
runAllCells(): Promise<boolean>;
|
||||
clearAllOutputs(): Promise<boolean>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user