diff --git a/src/sql/parts/notebook/models/notebookModel.ts b/src/sql/parts/notebook/models/notebookModel.ts index aebce2daea..1842b09d1c 100644 --- a/src/sql/parts/notebook/models/notebookModel.ts +++ b/src/sql/parts/notebook/models/notebookModel.ts @@ -49,6 +49,7 @@ export class NotebookModel extends Disposable implements INotebookModel { private _activeClientSession: IClientSession; private _sessionLoadFinished: Promise; private _onClientSessionReady = new Emitter(); + private _onProviderIdChanged = new Emitter(); private _activeContexts: IDefaultConnection; private _trustedMode: boolean; @@ -75,6 +76,7 @@ export class NotebookModel extends Disposable implements INotebookModel { } this._trustedMode = false; this._providerId = notebookOptions.providerId; + this._onProviderIdChanged.fire(this._providerId); this.notebookOptions.standardKernels.forEach(kernel => { this._kernelDisplayNameToConnectionProviderIds.set(kernel.name, kernel.connectionProviderIds); this._kernelDisplayNameToNotebookProviderIds.set(kernel.name, kernel.notebookProvider); @@ -209,6 +211,10 @@ export class NotebookModel extends Disposable implements INotebookModel { return this._onClientSessionReady.event; } + public get onProviderIdChange(): Event { + return this._onProviderIdChanged.event; + } + public getApplicableConnectionProviderIds(kernelDisplayName: string): string[] { let ids = []; if (kernelDisplayName) { @@ -605,7 +611,10 @@ export class NotebookModel extends Disposable implements INotebookModel { let index = this.notebookManagers[i].sessionManager.specs.kernels.findIndex(kernel => kernel.name === kernelSpec.name); if (index >= 0) { this._activeClientSession = this._clientSessions[i]; - this._providerId = this.notebookManagers[i].providerId; + if (this.notebookManagers[i].providerId !== this._providerId) { + this._providerId = this.notebookManagers[i].providerId; + this._onProviderIdChanged.fire(this._providerId); + } sessionManagerFound = true; break; } @@ -617,6 +626,7 @@ export class NotebookModel extends Disposable implements INotebookModel { let provider = this._kernelDisplayNameToNotebookProviderIds.get(kernelSpec.display_name); if (provider) { this._providerId = provider; + this._onProviderIdChanged.fire(this._providerId); } } } diff --git a/src/sql/parts/notebook/notebook.component.ts b/src/sql/parts/notebook/notebook.component.ts index f8145d3c30..98b2d91be2 100644 --- a/src/sql/parts/notebook/notebook.component.ts +++ b/src/sql/parts/notebook/notebook.component.ts @@ -17,7 +17,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler'; import { MenuId, IMenuService, MenuItemAction } from 'vs/platform/actions/common/actions'; import { IAction, Action, IActionItem } from 'vs/base/common/actions'; -import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { fillInActions, LabeledMenuItemActionItem } from 'vs/platform/actions/browser/menuItemActionItem'; import { Schemas } from 'vs/base/common/network'; @@ -70,6 +70,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe private _modelRegisteredDeferred = new Deferred(); private profile: IConnectionProfile; private _trustedAction: TrustedAction; + private _providerRelatedActions: IAction[] = []; constructor( @@ -231,6 +232,9 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe private async loadModel(): Promise { await this.awaitNonDefaultProvider(); + let providerId = notebookUtils.sqlNotebooksEnabled() ? 'sql' : this._notebookParams.providers.find(provider => provider !== DEFAULT_NOTEBOOK_PROVIDER); // this is tricky; really should also depend on the connection profile + this.setContextKeyServiceWithProviderId(providerId); + this.fillInActionsForCurrentContext(); for (let providerId of this._notebookParams.providers) { let notebookManager = await this.notebookService.getOrCreateNotebookManager(providerId, this._notebookParams.notebookUri); this.notebookManagers.push(notebookManager); @@ -249,6 +253,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe model.onError((errInfo: INotification) => this.handleModelError(errInfo)); await model.requestModelLoad(this._notebookParams.isTrusted); model.contentChanged((change) => this.handleContentChanged(change)); + model.onProviderIdChange((provider) => this.handleProviderIdChanged(provider)); this._model = this._register(model); this.updateToolbarComponents(this._model.trustedMode); this._modelRegisteredDeferred.resolve(this._model); @@ -310,6 +315,16 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe this._changeRef.detectChanges(); } + private handleProviderIdChanged(providerId: string) { + // If there are any actions that were related to the previous provider, + // disable them in the actionBar + this._providerRelatedActions.forEach(action => { + action.enabled = false; + }); + this.setContextKeyServiceWithProviderId(providerId); + this.fillInActionsForCurrentContext(); + } + findCellIndex(cellModel: ICellModel): number { return this._model.cells.findIndex((cell) => cell.id === cellModel.id); } @@ -345,17 +360,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe let saveNotebookButton = this.instantiationService.createInstance(SaveNotebookAction, 'notebook.SaveNotebook', localize('save', 'Save'), 'notebook-button icon-save'); - // Get all of the menu contributions that use the ID 'notebook/toolbar'. - // Then, find all groups (currently we don't leverage the contributed - // groups functionality for the notebook toolbar), and fill in the 'primary' - // array with items that don't list a group. Finally, add any actions from - // the primary array to the end of the toolbar. - const notebookBarMenu = this.menuService.createMenu(MenuId.NotebookToolbar, this.contextKeyService); - let groups = notebookBarMenu.getActions({ arg: null, shouldForwardArgs: true }); - let primary: IAction[] = []; - let secondary: IAction[] = []; - fillInActions(groups, { primary, secondary }, false, (group: string) => group === undefined); - let taskbar = this.toolbar.nativeElement; this._actionBar = new Taskbar(taskbar, this.contextMenuService, { actionItemProvider: action => this.actionItemProvider(action as Action) }); this._actionBar.context = this; @@ -368,11 +372,6 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe { action: this._trustedAction } ]); - // Primary actions are categorized as those that are added to the 'horizontal' group. - // For the vertical toolbar, we can do the same thing and instead use the 'vertical' group. - for (let action of primary) { - this._actionBar.addAction(action); - } } // Gets file path from recent workspace in local @@ -473,6 +472,40 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe return undefined; } + /** + * Get all of the menu contributions that use the ID 'notebook/toolbar'. + * Then, find all groups (currently we don't leverage the contributed + * groups functionality for the notebook toolbar), and fill in the 'primary' + * array with items that don't list a group. Finally, add any actions from + * the primary array to the end of the toolbar. + */ + private fillInActionsForCurrentContext(): void { + let primary: IAction[] = []; + let secondary: IAction[] = []; + let notebookBarMenu = this.menuService.createMenu(MenuId.NotebookToolbar, this.contextKeyService); + let groups = notebookBarMenu.getActions({ arg: null, shouldForwardArgs: true }); + fillInActions(groups, {primary, secondary}, false, (group: string) => group === undefined); + this.addPrimaryContributedActions(primary); + } + + private addPrimaryContributedActions(primary: IAction[]) { + for (let action of primary) { + // Need to ensure that we don't add the same action multiple times + let foundIndex = this._providerRelatedActions.findIndex(act => act.id === action.id); + if (foundIndex < 0) { + this._actionBar.addAction(action); + this._providerRelatedActions.push(action); + } else { + this._providerRelatedActions[foundIndex].enabled = true; + } + } + } + + private setContextKeyServiceWithProviderId(providerId: string) { + let provider = new RawContextKey('providerId', providerId); + provider.bindTo(this.contextKeyService); + } + public get notebookParams(): INotebookParams { return this._notebookParams; }