diff --git a/src/sql/media/icons/common-icons.css b/src/sql/media/icons/common-icons.css
index e908539152..ab3fe8663a 100644
--- a/src/sql/media/icons/common-icons.css
+++ b/src/sql/media/icons/common-icons.css
@@ -33,6 +33,13 @@
background: url("database_inverse.svg") center center no-repeat;
}
+.vs-dark .codicon.icon-dashboard-view::before,
+.hc-black .codicon.icon-dashboard-view::before,
+.vs .codicon.icon-dashboard-view::before {
+ -webkit-mask-image: url("dashboard_view.svg");
+ mask-image: url("dashboard_view.svg");
+}
+
.vs .codicon.error,
.vs-dark .codicon.error,
.hc-black .codicon.error {
diff --git a/src/sql/media/icons/dashboard_view.svg b/src/sql/media/icons/dashboard_view.svg
new file mode 100644
index 0000000000..537a84cfc9
--- /dev/null
+++ b/src/sql/media/icons/dashboard_view.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
index 77be99777f..b5ff1550e3 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebook.component.ts
@@ -28,7 +28,7 @@ import { INotebookService, INotebookParams, INotebookEditor, INotebookSection, I
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
import { Deferred } from 'sql/base/common/promise';
import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
-import { AddCellAction, KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction, RunParametersAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
+import { AddCellAction, KernelsDropdown, AttachToDropdown, TrustedAction, RunAllCellsAction, ClearAllOutputsAction, CollapseCellsAction, RunParametersAction, NotebookViewsActionProvider } from 'sql/workbench/contrib/notebook/browser/notebookActions';
import { DropdownMenuActionViewItem } from 'sql/base/browser/ui/buttonMenu/buttonMenu';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
@@ -51,6 +51,7 @@ import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/not
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
+import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
import { MaskedLabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -70,6 +71,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
@ViewChildren(CellToolbarComponent) private cellToolbar: QueryList;
@Input() _model: NotebookModel;
+ @Input() _views: NotebookViewsExtension;
protected _actionBar: Taskbar;
protected isLoading: boolean;
@@ -130,10 +132,14 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
this.notebookService.removeNotebookEditor(this);
}
}
- public get model(): NotebookModel | null {
+ public get model(): NotebookModel | undefined {
return this._model;
}
+ public get views(): NotebookViewsExtension | undefined {
+ return this._views;
+ }
+
public get activeCellId(): string {
return this._model && this._model.activeCell ? this._model.activeCell.id : '';
}
@@ -442,6 +448,28 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
dropdownMenuActionViewItem.render(buttonDropdownContainer);
dropdownMenuActionViewItem.setActionContext(this._notebookParams.notebookUri);
+ let viewsDropdownContainer;
+ if (this._configurationService.getValue('notebookViews.enabled')) {
+ let viewsContainer = document.createElement('li');
+ let viewsActionsProvider = new NotebookViewsActionProvider(viewsContainer, this.views, this.modelReady, this.notebookService, this.notificationService, this.instantiationService);
+ let viewsButton = new Action('notebook.OpenViews', localize('views', "Views"), 'notebook-button masked-pseudo code');
+ viewsDropdownContainer = DOM.$('li.action-item');
+ viewsDropdownContainer.setAttribute('role', 'presentation');
+ let viewsDropdownMenuActionViewItem = new DropdownMenuActionViewItem(
+ viewsButton,
+ viewsActionsProvider,
+ this.contextMenuService,
+ undefined,
+ this._actionBar.actionRunner,
+ undefined,
+ 'codicon notebook-button masked-pseudo masked-pseudo-after icon-dashboard-view dropdown-arrow',
+ localize('editor', "Editor"),
+ undefined
+ );
+ viewsDropdownMenuActionViewItem.render(viewsDropdownContainer);
+ viewsDropdownMenuActionViewItem.setActionContext(this._notebookParams.notebookUri);
+ }
+
this._actionBar.setContent([
{ element: buttonDropdownContainer },
{ action: this._runAllCellsAction },
@@ -449,6 +477,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
{ element: kernelContainer },
{ element: attachToContainer },
{ element: spacerElement },
+ { element: viewsDropdownContainer },
{ action: collapseCellsAction },
{ action: clearResultsButton },
{ action: this._trustedAction },
diff --git a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
index 7aaf60f842..276d83e59f 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts
@@ -6,7 +6,7 @@
import * as azdata from 'azdata';
import * as path from 'vs/base/common/path';
-import { Action } from 'vs/base/common/actions';
+import { Action, IAction, Separator } from 'vs/base/common/actions';
import { localize } from 'vs/nls';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { INotificationService, Severity, INotificationActions } from 'vs/platform/notification/common/notification';
@@ -18,21 +18,25 @@ import { ConnectionProfile } from 'sql/platform/connection/common/connectionProf
import { IConnectionDialogService } from 'sql/workbench/services/connection/common/connectionDialogService';
import { NotebookModel } from 'sql/workbench/services/notebook/browser/models/notebookModel';
import { ICommandService } from 'vs/platform/commands/common/commands';
-import { CellType } from 'sql/workbench/services/notebook/common/contracts';
+import { CellType, NotebookChangeType } from 'sql/workbench/services/notebook/common/contracts';
import { getErrorMessage } from 'vs/base/common/errors';
import { IEditorAction } from 'vs/editor/common/editorCommon';
import { IFindNotebookController } from 'sql/workbench/contrib/notebook/browser/find/notebookFindWidget';
-import { INotebookModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
+import { INotebookModel, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService';
import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils';
import { INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellContext } from 'sql/workbench/contrib/notebook/browser/cellViews/codeActions';
import { URI } from 'vs/base/common/uri';
+import { Emitter, Event } from 'vs/base/common/event';
+import { IActionProvider } from 'vs/base/browser/ui/dropdown/dropdown';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { KernelsLanguage } from 'sql/workbench/services/notebook/common/notebookConstants';
+import { INotebookViews } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
const msgLoading = localize('loading', "Loading kernels...");
export const msgChanging = localize('changing', "Changing kernel...");
@@ -178,6 +182,148 @@ export abstract class ToggleableAction extends Action {
}
}
+export class NotebookViewsActionProvider implements IActionProvider {
+ private _options: Action[] = [];
+ private views: INotebookViews;
+ private viewMode: ViewMode;
+ private readonly _optionsUpdated = new Emitter();
+
+ constructor(
+ container: HTMLElement,
+ views: INotebookViews,
+ modelReady: Promise,
+ @INotebookService private _notebookService: INotebookService,
+ @INotificationService private _notificationService: INotificationService,
+ @IInstantiationService private instantiationService: IInstantiationService) {
+
+ modelReady?.then((model) => {
+ this.views = views;
+ this.viewMode = model.viewMode;
+ this.updateView();
+ })
+ .catch((err) => {
+ this._notificationService.error(getErrorMessage(err));
+ });
+ }
+
+ getActions(): IAction[] {
+ return this._options;
+ }
+
+ public get options(): Action[] {
+ return this._options;
+ }
+
+ /**
+ * Update SelectBox values
+ */
+ public updateView() {
+ const backToNotebookButton = this.instantiationService.createInstance(NotebookViewAction, 'notebookView.backToNotebook', localize('notebookViewLabel', 'Editor'), 'notebook-button');
+ const newViewButton = this.instantiationService.createInstance(CreateNotebookViewAction, 'notebookView.newView', localize('newViewLabel', 'Create New View'), 'notebook-button notebook-button-newview');
+
+ const views = this.views.getViews();
+ this._options = [];
+
+ this._options.push(backToNotebookButton);
+ this._options.push(newViewButton);
+
+ if (views.length) {
+ this._options.push(this.instantiationService.createInstance(Separator));
+ }
+
+ views.forEach((view) => {
+ const option = new DashboardViewAction(view.guid, view.name, 'button', this._notebookService, this._notificationService);
+ this._options.push(option);
+
+ if (this.viewMode === ViewMode.Views && this.views.getActiveView() === view) {
+ option.checked = true;
+ option.enabled = false;
+ }
+ });
+
+ if (this.viewMode === ViewMode.Notebook) {
+ backToNotebookButton.checked = true;
+ backToNotebookButton.enabled = false;
+ }
+
+ this._optionsUpdated.fire(true);
+ }
+
+ public get onUpdated(): Event {
+ return this._optionsUpdated.event;
+ }
+
+ public optionSelected(displayName: string): void {
+ const view = this.views.getViews().find(view => view.name === displayName);
+ this.views.setActiveView(view);
+ }
+}
+
+/**
+ * Action to open a Notebook View
+ */
+export class DashboardViewAction extends Action {
+ constructor(
+ id: string, label: string, cssClass: string,
+ @INotebookService private _notebookService: INotebookService,
+ @INotificationService private _notificationService: INotificationService,
+ ) {
+ super(id, label, cssClass);
+ }
+
+ public override async run(context: URI): Promise {
+ if (context) {
+ const editor = this._notebookService.findNotebookEditor(context);
+ let views = editor.views;
+ const view = views.getViews().find(view => view.guid === this.id);
+
+ if (view) {
+ views.setActiveView(view);
+ editor.model.viewMode = ViewMode.Views;
+ } else {
+ this._notificationService.error(localize('viewNotFound', "Unable to find view: {0}", this.id));
+ }
+ }
+ }
+}
+
+/**
+ * Action to open enter the default notebook editor
+ */
+export class NotebookViewAction extends Action {
+ constructor(
+ id: string, label: string, cssClass: string,
+ @INotebookService private _notebookService: INotebookService
+ ) {
+ super(id, label, cssClass);
+ }
+ public override async run(context: URI): Promise {
+ const editor = this._notebookService.findNotebookEditor(context);
+ editor.model.viewMode = ViewMode.Notebook;
+ }
+}
+
+export class CreateNotebookViewAction extends Action {
+ constructor(
+ id: string, label: string, cssClass: string,
+ @INotebookService private _notebookService: INotebookService
+ ) {
+ super(id, label, cssClass);
+ }
+ public override async run(context: URI): Promise {
+ if (context) {
+ const editor = this._notebookService.findNotebookEditor(context);
+ const views = editor.views;
+
+ const newView = views.createNewView();
+ views.setActiveView(newView);
+
+ editor.model.viewMode = ViewMode.Views;
+ editor.model.serializationStateChanged(NotebookChangeType.MetadataChanged);
+ }
+ }
+}
+
export class TrustedAction extends ToggleableAction {
// Constants
private static readonly trustedLabel = localize('trustLabel', "Trusted");
diff --git a/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.html b/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.html
index 80fc2ad0dc..fd0603203b 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.html
+++ b/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.html
@@ -5,5 +5,5 @@
*--------------------------------------------------------------------------------------------*/
-->
-
+
diff --git a/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.ts b/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.ts
index 3d2a54dd5d..fda0e319bb 100644
--- a/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.ts
+++ b/src/sql/workbench/contrib/notebook/browser/notebookEditor.component.ts
@@ -24,6 +24,7 @@ import { IAction, SubmenuAction } from 'vs/base/common/actions';
import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
export const NOTEBOOKEDITOR_SELECTOR: string = 'notebookeditor-component';
@@ -36,6 +37,8 @@ export class NotebookEditorComponent extends AngularDisposable {
private notebookManagers: INotebookManager[] = [];
private _model: NotebookModel;
+ public views: NotebookViewsExtension;
+
constructor(
@Inject(ILogService) private readonly logService: ILogService,
@Inject(IBootstrapParams) private _notebookParams: INotebookParams,
@@ -104,6 +107,8 @@ export class NotebookEditorComponent extends AngularDisposable {
this._model = this._register(model);
await this.model.loadContents(trusted);
+ this.views = new NotebookViewsExtension(this.model);
+
this._register(model.viewModeChanged((mode) => this.onViewModeChanged()));
this._register(model.contentChanged((change) => this.handleContentChanged(change)));
this._register(model.onCellTypeChanged(() => this.detectChanges()));
diff --git a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
index 0a3224652b..f238b1c42d 100644
--- a/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
+++ b/src/sql/workbench/contrib/notebook/test/browser/notebookActions.test.ts
@@ -7,15 +7,15 @@ import * as assert from 'assert';
import * as azdata from 'azdata';
import * as sinon from 'sinon';
import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService';
-import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, kernelNotSupported, KernelsDropdown, msgChanging, NewNotebookAction, noKernelName, noParameterCell, noParametersInCell, RunAllCellsAction, RunParametersAction, TrustedAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
-import { ClientSessionStub, ContextViewProviderStub, NotebookComponentStub, NotebookModelStub, NotebookServiceStub } from 'sql/workbench/contrib/notebook/test/stubs';
+import { AddCellAction, ClearAllOutputsAction, CollapseCellsAction, CreateNotebookViewAction, DashboardViewAction, kernelNotSupported, KernelsDropdown, msgChanging, NewNotebookAction, noKernelName, noParameterCell, noParametersInCell, NotebookViewAction, NotebookViewsActionProvider, RunAllCellsAction, RunParametersAction, TrustedAction } from 'sql/workbench/contrib/notebook/browser/notebookActions';
+import { ClientSessionStub, ContextViewProviderStub, NotebookComponentStub, NotebookModelStub, NotebookServiceStub, NotebookViewsStub, NotebookViewStub } from 'sql/workbench/contrib/notebook/test/stubs';
import { NotebookEditorStub } from 'sql/workbench/contrib/notebook/test/testCommon';
-import { ICellModel, INotebookModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
+import { ICellModel, INotebookModel, ViewMode } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { IStandardKernelWithProvider } from 'sql/workbench/services/notebook/browser/models/notebookUtils';
import { INotebookEditor, INotebookService } from 'sql/workbench/services/notebook/browser/notebookService';
import { CellType, CellTypes } from 'sql/workbench/services/notebook/common/contracts';
import * as TypeMoq from 'typemoq';
-import { Emitter } from 'vs/base/common/event';
+import { Emitter, Event } from 'vs/base/common/event';
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationChangeEvent, IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -26,6 +26,9 @@ import { workbenchInstantiationService } from 'vs/workbench/test/browser/workben
import { URI } from 'vs/base/common/uri';
import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService';
import { MockQuickInputService } from 'sql/workbench/contrib/notebook/test/common/quickInputServiceMock';
+import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
+import { Separator } from 'vs/base/common/actions';
+import { INotebookView, INotebookViews } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
class TestClientSession extends ClientSessionStub {
private _errorState: boolean = false;
@@ -519,6 +522,50 @@ suite('Notebook Actions', function (): void {
assert.strictEqual(actualMsg, expectedMsg);
});
+ test('notebookViewsActionProvider', async () => {
+ const testGuid = '1';
+ const testName = 'Notebook-0';
+
+ const testNotebookModel: INotebookModel = {
+ viewMode: ViewMode.Notebook
+ };
+
+ const notebookEditor = new NotebookEditorStub({ model: testNotebookModel });
+
+ const mockNotification = TypeMoq.Mock.ofType(TestNotificationService);
+ const notebookViews = TypeMoq.Mock.ofType(NotebookViewsStub);
+
+ const notebookView = TypeMoq.Mock.ofType(NotebookViewStub);
+ notebookView.setup(x => x.guid).returns(() => testGuid);
+ notebookView.setup(x => x.name).returns(() => testName);
+ const views: INotebookView[] = [notebookView.object];
+
+ notebookViews.setup(x => x.getViews()).returns(() => views);
+ notebookViews.setup(x => x.getActiveView()).returns(() => undefined);
+
+ const notebookViewAction = new NotebookViewAction('notebookView.backToNotebook', 'Editor', 'notebook-button', mockNotebookService.object);
+ const createNotebookViewAction = new CreateNotebookViewAction('notebookView.newView', 'Create New View', 'notebook-button notebook-button-newview', mockNotebookService.object);
+ const separator = new Separator();
+
+ // Create a mocked out instantiation service
+ const mockInstantiationService = TypeMoq.Mock.ofType(InstantiationService, TypeMoq.MockBehavior.Strict);
+ mockInstantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(NotebookViewAction), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => notebookViewAction);
+ mockInstantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(CreateNotebookViewAction), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => createNotebookViewAction);
+ mockInstantiationService.setup(x => x.createInstance(TypeMoq.It.isValue(Separator))).returns(() => separator);
+
+ const viewsContainer = document.createElement('li');
+ const viewsActionsProvider = new NotebookViewsActionProvider(viewsContainer, notebookViews.object, notebookEditor.modelReady, mockNotebookService.object, mockNotification.object, mockInstantiationService.object);
+
+ await Event.toPromise(viewsActionsProvider.onUpdated);
+
+ const actions = viewsActionsProvider.getActions();
+
+ // It includes all the options
+ assert.strictEqual(actions.filter(a => a instanceof DashboardViewAction).length, 1);
+ assert.strictEqual(actions.filter(a => a instanceof NotebookViewAction).length, 1);
+ assert.strictEqual(actions.filter(a => a instanceof CreateNotebookViewAction).length, 1);
+ });
+
suite('Kernels dropdown', async () => {
let kernelsDropdown: KernelsDropdown;
let contextViewProvider: ContextViewProviderStub;
diff --git a/src/sql/workbench/contrib/notebook/test/electron-browser/notebookEditorModel.test.ts b/src/sql/workbench/contrib/notebook/test/electron-browser/notebookEditorModel.test.ts
index c30958638c..c5cfa72836 100644
--- a/src/sql/workbench/contrib/notebook/test/electron-browser/notebookEditorModel.test.ts
+++ b/src/sql/workbench/contrib/notebook/test/electron-browser/notebookEditorModel.test.ts
@@ -132,6 +132,7 @@ suite('Notebook Editor Model', function (): void {
notebookParams: undefined,
modelReady: undefined,
model: notebookModel,
+ views: undefined,
isDirty: undefined,
isActive: undefined,
isVisible: undefined,
diff --git a/src/sql/workbench/contrib/notebook/test/stubs.ts b/src/sql/workbench/contrib/notebook/test/stubs.ts
index 98230df695..b597ec947f 100644
--- a/src/sql/workbench/contrib/notebook/test/stubs.ts
+++ b/src/sql/workbench/contrib/notebook/test/stubs.ts
@@ -19,6 +19,8 @@ import { QueryTextEditor } from 'sql/workbench/browser/modelComponents/queryText
import { IContextViewProvider, IDelegate } from 'vs/base/browser/ui/contextview/contextview';
import { IEditorPane } from 'vs/workbench/common/editor';
import { INotebookShowOptions } from 'sql/workbench/api/common/sqlExtHost.protocol';
+import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
+import { INotebookView, INotebookViewCell, INotebookViews } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
export class NotebookModelStub implements INotebookModel {
constructor(private _languageInfo?: nb.ILanguageInfo, private _cells?: ICellModel[], private _testContents?: nb.INotebookContents) {
@@ -490,6 +492,9 @@ export class NotebookComponentStub implements INotebookEditor {
get model(): INotebookModel {
throw new Error('Method not implemented.');
}
+ get views(): NotebookViewsExtension {
+ throw new Error('Method not implemented.');
+ }
isDirty(): boolean {
throw new Error('Method not implemented.');
}
@@ -684,6 +689,7 @@ export class NotebookEditorStub implements INotebookEditor {
cellEditors: CellEditorProviderStub[];
modelReady: Promise;
model: INotebookModel;
+ views: NotebookViewsExtension;
viewMode: string;
isDirty(): boolean {
throw new Error('Method not implemented.');
@@ -754,3 +760,77 @@ export class ContextViewProviderStub implements IContextViewProvider {
throw new Error('Method not implemented.');
}
}
+
+export class NotebookViewStub implements INotebookView {
+ isNew: boolean;
+ name: string = '';
+ guid: string = '';
+ cells: readonly ICellModel[] = [];
+ hiddenCells: readonly ICellModel[];
+ displayedCells: readonly ICellModel[];
+
+ onDeleted: vsEvent.Event;
+ initialize(): void {
+ throw new Error('Method not implemented.');
+ }
+ nameAvailable(name: string): boolean {
+ throw new Error('Method not implemented.');
+ }
+ getCellMetadata(cell: ICellModel): INotebookViewCell {
+ throw new Error('Method not implemented.');
+ }
+ hideCell(cell: ICellModel): void {
+ throw new Error('Method not implemented.');
+ }
+ moveCell(cell: ICellModel, x: number, y: number): void {
+ throw new Error('Method not implemented.');
+ }
+ resizeCell(cell: ICellModel, width: number, height: number): void {
+ throw new Error('Method not implemented.');
+ }
+ compactCells() {
+ throw new Error('Method not implemented.');
+ }
+ markAsViewed(): void {
+ throw new Error('Method not implemented.');
+ }
+ getCell(guid: string): Readonly {
+ throw new Error('Method not implemented.');
+ }
+ insertCell(cell: ICellModel): void {
+ throw new Error('Method not implemented.');
+ }
+ save(): void {
+ throw new Error('Method not implemented.');
+ }
+ delete(): void {
+ throw new Error('Method not implemented.');
+ }
+}
+
+export class NotebookViewsStub implements INotebookViews {
+ notebook: INotebookModel;
+ onViewDeleted: vsEvent.Event;
+ createNewView(name?: string): INotebookView {
+ throw new Error('Method not implemented.');
+ }
+ removeView(guid: string): void {
+ throw new Error('Method not implemented.');
+ }
+ generateDefaultViewName(): string {
+ throw new Error('Method not implemented.');
+ }
+ getViews(): INotebookView[] {
+ throw new Error('Method not implemented.');
+ }
+ getActiveView(): INotebookView {
+ throw new Error('Method not implemented.');
+ }
+ setActiveView(view: INotebookView): void {
+ throw new Error('Method not implemented.');
+ }
+ viewNameIsTaken(name: string): boolean {
+ throw new Error('Method not implemented.');
+ }
+
+}
diff --git a/src/sql/workbench/contrib/notebook/test/testCommon.ts b/src/sql/workbench/contrib/notebook/test/testCommon.ts
index d4552598e6..4c4256c814 100644
--- a/src/sql/workbench/contrib/notebook/test/testCommon.ts
+++ b/src/sql/workbench/contrib/notebook/test/testCommon.ts
@@ -13,15 +13,17 @@ import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtil
import { TestThemeService } from 'vs/platform/theme/test/common/testThemeService';
import { TestEditorGroupsService, TestEditorService, TestTextResourceConfigurationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
+import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
// Typically you will pass in either editor or the instantiationService parameter.
// Leave both undefined when you want the underlying object(s) to have an undefined editor.
export class NotebookEditorStub extends stubs.NotebookEditorStub {
// Normally one needs to provide either the editor or the instantiationService as the constructor parameter
- constructor({ cellGuid, instantiationService, editor, model, notebookParams }: { cellGuid?: string; instantiationService?: IInstantiationService; editor?: QueryTextEditor; model?: INotebookModel, notebookParams?: INotebookParams } = {}) {
+ constructor({ cellGuid, instantiationService, editor, model, views, notebookParams }: { cellGuid?: string; instantiationService?: IInstantiationService; editor?: QueryTextEditor; model?: INotebookModel, views?: NotebookViewsExtension, notebookParams?: INotebookParams } = {}) {
super();
this.cells = [];
this.model = model;
+ this.views = views;
this.notebookParams = notebookParams;
this.cellEditors = [new CellEditorProviderStub({ cellGuid: cellGuid, instantiationService: instantiationService, editor: editor })];
this.id = this.notebookParams?.notebookUri?.toString();
diff --git a/src/sql/workbench/services/notebook/browser/notebookService.ts b/src/sql/workbench/services/notebook/browser/notebookService.ts
index d603044e45..d48b4ef38f 100644
--- a/src/sql/workbench/services/notebook/browser/notebookService.ts
+++ b/src/sql/workbench/services/notebook/browser/notebookService.ts
@@ -20,6 +20,7 @@ import { Range } from 'vs/editor/common/core/range';
import { IEditorPane } from 'vs/workbench/common/editor';
import { INotebookInput } from 'sql/workbench/services/notebook/browser/interface';
import { INotebookShowOptions } from 'sql/workbench/api/common/sqlExtHost.protocol';
+import { NotebookViewsExtension } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension';
export const SERVICE_ID = 'sqlNotebookService';
export const INotebookService = createDecorator(SERVICE_ID);
@@ -210,6 +211,7 @@ export interface INotebookEditor {
readonly cellEditors: ICellEditorProvider[];
readonly modelReady: Promise;
readonly model: INotebookModel | null;
+ readonly views: NotebookViewsExtension | null;
isDirty(): boolean;
isActive(): boolean;
isVisible(): boolean;
diff --git a/src/sql/workbench/services/notebook/browser/notebookViews/notebookViews.d.ts b/src/sql/workbench/services/notebook/browser/notebookViews/notebookViews.d.ts
index befac71e27..449884f92e 100644
--- a/src/sql/workbench/services/notebook/browser/notebookViews/notebookViews.d.ts
+++ b/src/sql/workbench/services/notebook/browser/notebookViews/notebookViews.d.ts
@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
+import { ICellModel, INotebookModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces';
import { Event } from 'vs/base/common/event';
export type CellChangeEventType = 'hide' | 'insert' | 'active';
@@ -62,3 +62,16 @@ export interface INotebookViewMetadata {
export interface INotebookViewCellMetadata {
views: INotebookViewCell[];
}
+
+export interface INotebookViews {
+ onViewDeleted: Event;
+ notebook: INotebookModel;
+
+ createNewView(name?: string): INotebookView;
+ removeView(guid: string): void;
+ generateDefaultViewName(): string;
+ getViews(): INotebookView[];
+ getActiveView(): INotebookView;
+ setActiveView(view: INotebookView): void;
+ viewNameIsTaken(name: string): boolean;
+}
diff --git a/src/sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension.ts b/src/sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension.ts
index 676c8be03c..853d345b0d 100644
--- a/src/sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension.ts
+++ b/src/sql/workbench/services/notebook/browser/notebookViews/notebookViewsExtension.ts
@@ -9,9 +9,9 @@ import { Emitter, Event } from 'vs/base/common/event';
import { localize } from 'vs/nls';
import { NotebookViewModel } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViewModel';
import { NotebookExtension } from 'sql/workbench/services/notebook/browser/models/notebookExtension';
-import { INotebookView, INotebookViewCell, INotebookViewCellMetadata, INotebookViewMetadata } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
+import { INotebookView, INotebookViewCell, INotebookViewCellMetadata, INotebookViewMetadata, INotebookViews } from 'sql/workbench/services/notebook/browser/notebookViews/notebookViews';
-export class NotebookViewsExtension extends NotebookExtension {
+export class NotebookViewsExtension extends NotebookExtension implements INotebookViews {
static readonly defaultViewName = localize('notebookView.untitledView', "Untitled View");
readonly maxNameIterationAttempts = 100;