Fixed #4567 adding open connectionDialog when no connection is available (#5581)

* Fixed #4567 adding open connectionDialog when no connection is available
This commit is contained in:
Yurong He
2019-05-23 15:11:10 -07:00
committed by GitHub
parent 34ca0e8671
commit 776e2cf6e7
5 changed files with 65 additions and 44 deletions

View File

@@ -217,9 +217,11 @@ export class CellModel implements ICellModel {
} else {
// TODO update source based on editor component contents
if (kernel.requiresConnection && !this.notebookModel.activeConnection) {
this.sendNotification(notificationService, Severity.Error, localize('kernelRequiresConnection', "Please select a connection to run cells for this kernel"));
let connected = await this.notebookModel.requestConnection();
if (!connected) {
return false;
}
}
let content = this.source;
if (content) {
let future = await kernel.requestExecute({

View File

@@ -16,7 +16,7 @@ import * as notebookUtils from '../notebookUtils';
import { INotebookManager, SQL_NOTEBOOK_PROVIDER, DEFAULT_NOTEBOOK_PROVIDER } from 'sql/workbench/services/notebook/common/notebookService';
import { NotebookContexts } from 'sql/workbench/parts/notebook/models/notebookContexts';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { INotification, Severity } from 'vs/platform/notification/common/notification';
import { INotification, Severity, INotificationService } from 'vs/platform/notification/common/notification';
import { URI } from 'vs/base/common/uri';
import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
@@ -72,11 +72,13 @@ export class NotebookModel extends Disposable implements INotebookModel {
private _oldKernel: nb.IKernel;
private _clientSessionListeners: IDisposable[] = [];
private _connectionUrisToDispose: string[] = [];
public requestConnectionHandler: () => Promise<boolean>;
constructor(
private _notebookOptions: INotebookModelOptions,
public connectionProfile: IConnectionProfile | undefined,
@ILogService private readonly logService: ILogService
@ILogService private readonly logService: ILogService,
@INotificationService private readonly notificationService: INotificationService
) {
super();
if (!_notebookOptions || !_notebookOptions.notebookUri || !_notebookOptions.notebookManagers) {
@@ -301,6 +303,15 @@ export class NotebookModel extends Disposable implements INotebookModel {
}
}
public async requestConnection(): Promise<boolean> {
if (this.requestConnectionHandler) {
return this.requestConnectionHandler();
} else if (this.notificationService) {
this.notificationService.notify({ severity: Severity.Error, message: localize('kernelRequiresConnection', "Please select a connection to run cells for this kernel") });
}
return false;
}
public findCellIndex(cellModel: ICellModel): number {
return this._cells.findIndex((cell) => cell.equals(cellModel));
}

View File

@@ -279,7 +279,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
defaultKernel: this._notebookParams.input.defaultKernel,
layoutChanged: this._notebookParams.input.layoutChanged,
capabilitiesService: this.capabilitiesService
}, this.profile, this.logService);
}, this.profile, this.logService, this.notificationService);
model.onError((errInfo: INotification) => this.handleModelError(errInfo));
let trusted = await this.notebookService.isNotebookTrustCached(this._notebookParams.notebookUri, this.isDirty());
await model.requestModelLoad(trusted);

View File

@@ -350,6 +350,7 @@ export class AttachToDropdown extends SelectBox {
this._register(this.model.contextsLoading(() => {
this.setOptions([msgLoadingContexts], 0);
}));
this.model.requestConnectionHandler = () => this.openConnectionDialog(true);
this.handleContextsChanged();
}
@@ -489,14 +490,20 @@ export class AttachToDropdown extends SelectBox {
* Bind the server value to 'Attach To' drop down
* Connected server is displayed at the top of drop down
**/
public async openConnectionDialog(useProfile: boolean = false): Promise<void> {
public async openConnectionDialog(useProfile: boolean = false): Promise<boolean> {
try {
await this._connectionDialogService.openDialogAndWait(this._connectionManagementService, { connectionType: 1, providers: this.model.getApplicableConnectionProviderIds(this.model.clientSession.kernel.name) }, useProfile ? this.model.connectionProfile : undefined).then(connection => {
let connection = await this._connectionDialogService.openDialogAndWait(this._connectionManagementService,
{
connectionType: 1,
providers: this.model.getApplicableConnectionProviderIds(this.model.clientSession.kernel.name)
},
useProfile ? this.model.connectionProfile : undefined);
let attachToConnections = this.values;
if (!connection) {
this.loadAttachToDropdown(this.model, this.getKernelDisplayName());
this.doChangeContext(undefined, true);
return;
return false;
}
let connectionUri = this._connectionManagementService.getConnectionUri(connection);
let connectionProfile = new ConnectionProfile(this._capabilitiesService, connection);
@@ -505,7 +512,7 @@ export class AttachToDropdown extends SelectBox {
if (attachToConnections.some(val => val === connectedServer)) {
this.loadAttachToDropdown(this.model, this.getKernelDisplayName());
this.doChangeContext();
return;
return true;
}
else {
attachToConnections.unshift(connectedServer);
@@ -524,11 +531,12 @@ export class AttachToDropdown extends SelectBox {
this.model.addAttachToConnectionsToBeDisposed(connectionUri);
// Call doChangeContext to set the newly chosen connection in the model
this.doChangeContext(connectionProfile);
});
return true;
}
catch (error) {
const actions: INotificationActions = { primary: [] };
this._notificationService.notify({ severity: Severity.Error, message: getErrorMessage(error), actions });
return false;
}
}
}

View File

@@ -131,7 +131,7 @@ suite('notebook model', function (): void {
mockContentManager.setup(c => c.getNotebookContents(TypeMoq.It.isAny())).returns(() => Promise.resolve(emptyNotebook));
notebookManagers[0].contentManager = mockContentManager.object;
// When I initialize the model
let model = new NotebookModel(defaultModelOptions, undefined, logService);
let model = new NotebookModel(defaultModelOptions, undefined, logService, undefined);
await model.requestModelLoad();
// Then I expect to have 0 code cell as the contents
@@ -146,7 +146,7 @@ suite('notebook model', function (): void {
mockContentManager.setup(c => c.getNotebookContents(TypeMoq.It.isAny())).returns(() => Promise.resolve(expectedNotebookContent));
notebookManagers[0].contentManager = mockContentManager.object;
// When I initialize the model
let model = new NotebookModel(defaultModelOptions, undefined, logService);
let model = new NotebookModel(defaultModelOptions, undefined, logService, undefined);
await model.requestModelLoad(true);
// Then Trust should be true
@@ -233,7 +233,7 @@ suite('notebook model', function (): void {
let options: INotebookModelOptions = Object.assign({}, defaultModelOptions, <Partial<INotebookModelOptions>>{
factory: mockModelFactory.object
});
let model = new NotebookModel(options, undefined, logService);
let model = new NotebookModel(options, undefined, logService, undefined);
model.onClientSessionReady((session) => actualSession = session);
await model.requestModelLoad();
await model.startSession(notebookManagers[0]);
@@ -251,14 +251,14 @@ suite('notebook model', function (): void {
});
test('Should sanitize kernel display name when IP is included', async function (): Promise<void> {
let model = new NotebookModel(defaultModelOptions, undefined, logService);
let model = new NotebookModel(defaultModelOptions, undefined, logService, undefined);
let displayName = 'PySpark (1.1.1.1)';
let sanitizedDisplayName = model.sanitizeDisplayName(displayName);
should(sanitizedDisplayName).equal('PySpark');
});
test('Should sanitize kernel display name properly when IP is not included', async function (): Promise<void> {
let model = new NotebookModel(defaultModelOptions, undefined, logService);
let model = new NotebookModel(defaultModelOptions, undefined, logService, undefined);
let displayName = 'PySpark';
let sanitizedDisplayName = model.sanitizeDisplayName(displayName);
should(sanitizedDisplayName).equal('PySpark');
@@ -269,7 +269,7 @@ suite('notebook model', function (): void {
let mockContentManager = TypeMoq.Mock.ofType(LocalContentManager);
mockContentManager.setup(c => c.getNotebookContents(TypeMoq.It.isAny())).returns(() => Promise.resolve(expectedNotebookContent));
notebookManagers[0].contentManager = mockContentManager.object;
let model = new NotebookModel(defaultModelOptions, undefined, logService);
let model = new NotebookModel(defaultModelOptions, undefined, logService, undefined);
await model.requestModelLoad(false);
let actualChanged: NotebookContentChange;