-
- PlaceHolder for Toolbar
-
+
diff --git a/src/sql/parts/notebook/notebook.component.ts b/src/sql/parts/notebook/notebook.component.ts
index 9faa7d490d..33c2f74ecc 100644
--- a/src/sql/parts/notebook/notebook.component.ts
+++ b/src/sql/parts/notebook/notebook.component.ts
@@ -28,6 +28,11 @@ import { ModelFactory } from 'sql/parts/notebook/models/modelFactory';
import * as notebookUtils from './notebookUtils';
import { Deferred } from 'sql/base/common/promise';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
+import { Taskbar } from 'sql/base/browser/ui/taskbar/taskbar';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
+import { AddCellAction, KernelsDropdown, AttachToDropdown } from 'sql/parts/notebook/notebookActions';
+import { attachSelectBoxStyler } from 'vs/platform/theme/common/styler';
export const NOTEBOOK_SELECTOR: string = 'notebook-component';
@@ -41,10 +46,12 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
private _model: NotebookModel;
private _isInErrorState: boolean = false;
private _errorMessage: string;
+ protected _actionBar: Taskbar;
private _activeCell: ICellModel;
protected isLoading: boolean;
private notebookManager: INotebookManager;
private _modelReadyDeferred = new Deferred();
+ private _modelRegisteredDeferred = new Deferred();
private profile: IConnectionProfile;
@@ -55,7 +62,10 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
@Inject(IConnectionManagementService) private connectionManagementService: IConnectionManagementService,
@Inject(INotificationService) private notificationService: INotificationService,
@Inject(INotebookService) private notebookService: INotebookService,
- @Inject(IBootstrapParams) private notebookParams: INotebookParams
+ @Inject(IBootstrapParams) private notebookParams: INotebookParams,
+ @Inject(IInstantiationService) private instantiationService: IInstantiationService,
+ @Inject(IContextMenuService) private contextMenuService: IContextMenuService,
+ @Inject(IContextViewService) private contextViewService: IContextViewService
) {
super();
this.profile = this.notebookParams!.profile;
@@ -65,9 +75,14 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
ngOnInit() {
this._register(this.themeService.onDidColorThemeChange(this.updateTheme, this));
this.updateTheme(this.themeService.getColorTheme());
+ this.initActionBar();
this.doLoad();
}
+ public get modelRegistered(): Promise {
+ return this._modelRegisteredDeferred.promise;
+ }
+
protected get cells(): ReadonlyArray {
return this._model ? this._model.cells : [];
}
@@ -135,11 +150,12 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
notebookManager: this.notebookManager
}, false, this.profile);
model.onError((errInfo: INotification) => this.handleModelError(errInfo));
- model.backgroundStartSession();
await model.requestModelLoad(this.notebookParams.isTrusted);
model.contentChanged((change) => this.handleContentChanged(change));
this._model = model;
this._register(model);
+ this._modelRegisteredDeferred.resolve(this._model);
+ model.backgroundStartSession();
this._changeRef.detectChanges();
}
@@ -170,6 +186,38 @@ export class NotebookComponent extends AngularDisposable implements OnInit {
this.notificationService.error(error);
}
+ protected initActionBar() {
+ let kernelInfoText = document.createElement('div');
+ kernelInfoText.className ='notebook-info-label';
+ kernelInfoText.innerText = 'Kernel: ';
+
+ let kernelsDropdown = new KernelsDropdown(this.contextViewService, this.modelRegistered);
+ let kernelsDropdownTemplateContainer = document.createElement('div');
+ kernelsDropdownTemplateContainer.className = 'notebook-toolbar-dropdown';
+ kernelsDropdown.render(kernelsDropdownTemplateContainer);
+ attachSelectBoxStyler(kernelsDropdown, this.themeService);
+
+ let attachToDropdown = new AttachToDropdown(this.contextViewService);
+ let attachToDropdownTemplateContainer = document.createElement('div');
+ attachToDropdownTemplateContainer.className = 'notebook-toolbar-dropdown';
+ attachToDropdown.render(attachToDropdownTemplateContainer);
+ attachSelectBoxStyler(attachToDropdown, this.themeService);
+
+ let attachToInfoText = document.createElement('div');
+ attachToInfoText.className ='notebook-info-label';
+ attachToInfoText.innerText = 'Attach To: ';
+
+ let taskbar = this.toolbar.nativeElement;
+ this._actionBar = new Taskbar(taskbar, this.contextMenuService);
+ this._actionBar.context = this;
+ this._actionBar.setContent([
+ { element: kernelInfoText },
+ { element: kernelsDropdownTemplateContainer },
+ { element: attachToInfoText },
+ { element: attachToDropdownTemplateContainer }
+ ]);
+ }
+
public async save(): Promise {
try {
let saved = await this._model.saveModel();
diff --git a/src/sql/parts/notebook/notebook.contribution.ts b/src/sql/parts/notebook/notebook.contribution.ts
index bcb6df8259..e194b0598a 100644
--- a/src/sql/parts/notebook/notebook.contribution.ts
+++ b/src/sql/parts/notebook/notebook.contribution.ts
@@ -10,13 +10,12 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Action } from 'vs/base/common/actions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { TPromise } from 'vs/base/common/winjs.base';
-import * as nls from 'vs/nls';
import { Schemas } from 'vs/base/common/network';
+import URI from 'vs/base/common/uri';
+import { localize } from 'vs/nls';
import { NotebookInput, NotebookInputModel } from 'sql/parts/notebook/notebookInput';
import { NotebookEditor } from 'sql/parts/notebook/notebookEditor';
-import URI from 'vs/base/common/uri';
-
let counter = 0;
@@ -27,7 +26,7 @@ let counter = 0;
export class OpenNotebookAction extends Action {
public static ID = 'OpenNotebookAction';
- public static LABEL = nls.localize('OpenNotebookAction', 'Open Notebook editor');
+ public static LABEL = localize('OpenNotebookAction', 'Open Notebook editor');
constructor(
id: string,
@@ -67,4 +66,6 @@ actionRegistry.registerWorkbenchAction(
OpenNotebookAction.LABEL
),
OpenNotebookAction.LABEL
-);
\ No newline at end of file
+);
+
+
diff --git a/src/sql/parts/notebook/notebook.css b/src/sql/parts/notebook/notebook.css
index ce0d058eed..7e63bd1b1a 100644
--- a/src/sql/parts/notebook/notebook.css
+++ b/src/sql/parts/notebook/notebook.css
@@ -12,3 +12,15 @@
border-width: 1px;
border-style: solid;
}
+
+.notebookEditor .notebook-toolbar-dropdown {
+ width: 150px;
+ padding-right: 10px;
+}
+
+.notebookEditor .notebook-info-label {
+ padding-right: 5px;
+ text-align: center;
+ display: flex;
+ align-items: center;
+}
\ No newline at end of file
diff --git a/src/sql/parts/notebook/notebookActions.ts b/src/sql/parts/notebook/notebookActions.ts
new file mode 100644
index 0000000000..65b1535894
--- /dev/null
+++ b/src/sql/parts/notebook/notebookActions.ts
@@ -0,0 +1,87 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+ import * as sqlops from 'sqlops';
+
+import { Action } from 'vs/base/common/actions';
+import { TPromise } from 'vs/base/common/winjs.base';
+import { localize } from 'vs/nls';
+import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
+
+import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
+import { INotebookModel } from 'sql/parts/notebook/models/modelInterfaces';
+
+const msgLoading = localize('loading', 'Loading kernels...');
+export class AddCellAction extends Action {
+ public static ID = 'notebook.addCell';
+ public static LABEL = 'Cell';
+
+ constructor(
+ ) {
+ super(AddCellAction.ID, AddCellAction.LABEL, 'newStepIcon');
+ }
+
+ public run(context: any): TPromise {
+ return new TPromise((resolve, reject) => {
+ try {
+ resolve(true);
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+}
+
+export class KernelsDropdown extends SelectBox {
+ private model: INotebookModel;
+ constructor(contextViewProvider: IContextViewProvider, modelRegistered: Promise
+ ) {
+ super( [msgLoading], msgLoading, contextViewProvider);
+ if (modelRegistered) {
+ modelRegistered
+ .then((model) => this.updateModel(model))
+ .catch((err) => {
+ // No-op for now
+ });
+ }
+
+ this.onDidSelect(e => this.doChangeKernel(e.selected));
+ }
+
+ updateModel(model: INotebookModel): void {
+ this.model = model;
+ model.kernelsChanged((defaultKernel) => {
+ this.updateKernel(defaultKernel);
+ });
+ if (model.clientSession) {
+ model.clientSession.kernelChanged((changedArgs: sqlops.nb.IKernelChangedArgs) => {
+ if (changedArgs.newValue) {
+ this.updateKernel(changedArgs.newValue);
+ }
+ });
+ }
+ }
+
+ // Update SelectBox values
+ private updateKernel(defaultKernel: sqlops.nb.IKernelSpec) {
+ let specs = this.model.specs;
+ if (specs && specs.kernels) {
+ let index = specs.kernels.findIndex((kernel => kernel.name === defaultKernel.name));
+ this.setOptions(specs.kernels.map(kernel => kernel.display_name), index);
+ }
+ }
+
+ public doChangeKernel(displayName: string): void {
+ this.model.changeKernel(displayName);
+ }
+}
+
+export class AttachToDropdown extends SelectBox {
+ constructor(contextViewProvider: IContextViewProvider
+ ) {
+ let options: string[] = ['localhost'];
+ super(options, 'localhost', contextViewProvider);
+ }
+}
\ No newline at end of file
diff --git a/src/sql/services/notebook/sessionManager.ts b/src/sql/services/notebook/sessionManager.ts
index 5ac4dc1f0a..dda6f17735 100644
--- a/src/sql/services/notebook/sessionManager.ts
+++ b/src/sql/services/notebook/sessionManager.ts
@@ -1,31 +1,141 @@
'use strict';
import { nb } from 'sqlops';
-import { Session } from 'electron';
+import { localize } from 'vs/nls';
+
+const noKernel: string = localize('noKernel', 'No Kernel');
+let noKernelSpec: nb.IKernelSpec = ({
+ name: noKernel,
+ language: 'python',
+ display_name: noKernel
+});
export class SessionManager implements nb.SessionManager {
- private _sessionManager: nb.SessionManager;
-
- constructor() {
-
- }
public get isReady(): boolean {
- return this._sessionManager.isReady;
+ return true;
}
public get ready(): Thenable {
- return this._sessionManager.ready;
+ return Promise.resolve();
}
+
public get specs(): nb.IAllKernels {
- return this._sessionManager.specs;
+ let allKernels: nb.IAllKernels = {
+ defaultKernel: noKernel,
+ kernels: [noKernelSpec]
+ };
+ return allKernels;
}
startNew(options: nb.ISessionOptions): Thenable {
- return this._sessionManager.startNew(options);
+ let session = new EmptySession(options);
+ return Promise.resolve(session);
}
shutdown(id: string): Thenable {
- return this.shutdown(id);
+ return Promise.resolve();
+ }
+}
+
+class EmptySession implements nb.ISession {
+ private _kernel: EmptyKernel;
+ private _defaultKernelLoaded = false;
+
+ public set defaultKernelLoaded(value) {
+ this._defaultKernelLoaded = value;
}
+ public get defaultKernelLoaded(): boolean {
+ return this._defaultKernelLoaded;
+ }
+
+ constructor(private options: nb.ISessionOptions) {
+ this._kernel = new EmptyKernel();
+ }
+
+ public get canChangeKernels(): boolean {
+ return true;
+ }
+
+ public get id(): string {
+ return this.options.kernelId || '';
+ }
+
+ public get path(): string {
+ return this.options.path;
+ }
+
+ public get name(): string {
+ return this.options.name || '';
+ }
+
+ public get type(): string {
+ return this.options.type || '';
+ }
+
+ public get status(): nb.KernelStatus {
+ return 'connected';
+ }
+
+ public get kernel(): nb.IKernel {
+ return this._kernel;
+ }
+
+ changeKernel(kernelInfo: nb.IKernelSpec): Thenable {
+ return Promise.resolve(this.kernel);
+ }
}
+
+class EmptyKernel implements nb.IKernel {
+ public get id(): string {
+ return '-1';
+ }
+
+ public get name(): string {
+ return noKernel;
+ }
+
+ public get supportsIntellisense(): boolean {
+ return false;
+ }
+
+ public get isReady(): boolean {
+ return true;
+ }
+
+ public get ready(): Thenable {
+ return Promise.resolve();
+ }
+
+ public get info(): nb.IInfoReply {
+ let info: nb.IInfoReply = {
+ protocol_version: '',
+ implementation: '',
+ implementation_version: '',
+ language_info: {
+ name: '',
+ version: '',
+ },
+ banner: '',
+ help_links: [{
+ text: '',
+ url: ''
+ }]
+ };
+
+ return info;
+ }
+ getSpec(): Thenable {
+ return Promise.resolve(noKernelSpec);
+ }
+
+ requestExecute(content: nb.IExecuteRequest, disposeOnDone?: boolean): nb.IFuture {
+ throw new Error('Method not implemented.');
+ }
+
+ requestComplete(content: nb.ICompleteRequest): Thenable {
+ let response: Partial = { };
+ return Promise.resolve(response as nb.ICompleteReplyMsg);
+ }
+
+}
\ No newline at end of file