Adds build connection info feature (#2192)

* connection string

* formatting

* change serailize reponse type to match connect params

* add connection string serialization

* readd the connection string to the connection widget

* format

* remove unnecessary change

* update serializer to require provider

* update name of function

* fix function name

* bump dataprotocol and sqltools

* revert unnecessary change

* remove more unnecessary chagnes

* bump sqltoolsserivce

* adde configuration for auto parsing the clipboard
This commit is contained in:
Anthony Dresser
2018-08-20 11:50:16 -07:00
committed by Karl Burtram
parent 21c4429c6e
commit 033c8cb8b1
14 changed files with 98 additions and 23 deletions

View File

@@ -135,7 +135,7 @@ export abstract class Modal extends Disposable implements IThemable {
private _name: string,
private _partService: IPartService,
private _telemetryService: ITelemetryService,
private _contextKeyService: IContextKeyService,
_contextKeyService: IContextKeyService,
options?: IModalOptions
) {
super();

View File

@@ -92,5 +92,10 @@ configurationRegistry.registerConfiguration({
'description': localize('sql.defaultEngineDescription', 'Default SQL Engine to use. This drives default language provider in .sql files and the default to use when creating a new connection. Valid option is currently MSSQL'),
'default': 'MSSQL'
},
'connection.parseClipboardForConnectionString': {
'type': 'boolean',
'default': true,
'description': localize('connection.parseClipboardForConnectionStringDescription', 'Attempt to parse the contents of the clipboard when the connection dialog is opened or a paste is performed.')
}
}
});
});

View File

@@ -266,6 +266,11 @@ export interface IConnectionManagementService {
* Get the connection string for the provided connection profile
*/
getConnectionString(ownerUri: string, includePassword: boolean): Thenable<string>;
/**
* Serialize connection string with optional provider
*/
buildConnectionInfo(connectionString: string, provider?: string): Thenable<sqlops.ConnectionInfo>;
}
export const IConnectionDialogService = createDecorator<IConnectionDialogService>('connectionDialogService');

View File

@@ -1366,4 +1366,14 @@ export class ConnectionManagementService extends Disposable implements IConnecti
});
});
}
/**
* Serialize connection with options provider
* TODO this could be a map reduce operation
*/
public buildConnectionInfo(connectionString: string, provider: string): Thenable<sqlops.ConnectionInfo> {
return this._providers.get(provider).onReady.then(e => {
return e.buildConnectionInfo(connectionString);
});
}
}

View File

@@ -34,7 +34,6 @@ import { ITree } from 'vs/base/parts/tree/browser/tree';
import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import * as styler from 'vs/platform/theme/common/styler';
import { TPromise } from 'vs/base/common/winjs.base';
import * as DOM from 'vs/base/browser/dom';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -376,6 +375,7 @@ export class ConnectionDialogWidget extends Modal {
*/
public open(recentConnections: boolean) {
this._panel.showTab(this._recentConnectionTabId);
this.show();
if (recentConnections) {
this._noRecentConnectionBuilder.hide();

View File

@@ -19,6 +19,9 @@ import * as Constants from 'sql/parts/connection/common/constants';
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
import { attachInputBoxStyler, attachButtonStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler';
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { ConnectionProfile } from '../common/connectionProfile';
import * as sqlops from 'sqlops';
@@ -32,6 +35,8 @@ import { OS, OperatingSystem } from 'vs/base/common/platform';
import { Builder, $ } from 'vs/base/browser/builder';
import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
import { endsWith, startsWith } from 'vs/base/common/strings';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export class ConnectionWidget {
private _builder: Builder;
@@ -85,7 +90,12 @@ export class ConnectionWidget {
callbacks: IConnectionComponentCallbacks,
providerName: string,
@IThemeService private _themeService: IThemeService,
@IContextViewService private _contextViewService: IContextViewService) {
@IContextViewService private _contextViewService: IContextViewService,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
@IClipboardService private _clipboardService: IClipboardService,
@IConfigurationService private _configurationService: IConfigurationService
) {
this._callbacks = callbacks;
this._toDispose = [];
this._optionsMaps = {};
@@ -120,9 +130,29 @@ export class ConnectionWidget {
if (this._authTypeSelectBox) {
this.onAuthTypeSelected(this._authTypeSelectBox.value);
}
DOM.addDisposableListener(container, 'paste', e => {
this._handleClipboard();
});
DOM.append(container, this._builder.getHTMLElement());
}
private _handleClipboard(): void {
if (this._configurationService.getValue<boolean>('connection.parseClipboardForConnectionString')) {
let paste = this._clipboardService.readText();
this._connectionManagementService.buildConnectionInfo(paste, this._providerName).then(e => {
if (e) {
let profile = new ConnectionProfile(this._capabilitiesService, this._providerName);
profile.options = e.options;
if (profile.serverName) {
this.initDialog(profile);
}
}
});
}
}
private fillInConnectionForm(): void {
let serverNameOption = this._optionsMaps[ConnectionOptionSpecialType.serverName];
let serverNameBuilder = DialogHelper.appendRow(this._tableContainer, serverNameOption.displayName, 'connection-label', 'connection-input');
@@ -130,7 +160,7 @@ export class ConnectionWidget {
validationOptions: {
validation: (value: string) => {
if (!value) {
return ({ type: MessageType.ERROR, content: localize('connectionWidget.missingRequireField', '{0} is required.', serverNameOption.displayName)});
return ({ type: MessageType.ERROR, content: localize('connectionWidget.missingRequireField', '{0} is required.', serverNameOption.displayName) });
} else if (startsWith(value, ' ') || endsWith(value, ' ')) {
return ({ type: MessageType.WARNING, content: localize('connectionWidget.fieldWillBeTrimmed', '{0} will be trimmed.', serverNameOption.displayName) });
}
@@ -354,6 +384,7 @@ export class ConnectionWidget {
}
public focusOnOpen(): void {
this._handleClipboard();
this._serverNameInputBox.focus();
this.focusPasswordIfNeeded();
this.clearValidationMessages();

4
src/sql/sqlops.d.ts vendored
View File

@@ -327,7 +327,9 @@ declare module 'sqlops' {
rebuildIntelliSenseCache(connectionUri: string): Thenable<void>;
getConnectionString(connectionUri: string, includePassword: boolean): Thenable<string> ;
getConnectionString(connectionUri: string, includePassword: boolean): Thenable<string>;
buildConnectionInfo?(connectionString: string): Thenable<ConnectionInfo>;
registerOnConnectionComplete(handler: (connSummary: ConnectionInfoSummary) => any): void;

View File

@@ -11,6 +11,7 @@ import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { SqlMainContext, MainThreadDataProtocolShape, ExtHostDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import { DataProviderType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { TPromise } from 'vs/base/common/winjs.base';
export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
@@ -185,6 +186,15 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
return this._resolveProvider<sqlops.ConnectionProvider>(handle).getConnectionString(connectionUri, includePassword);
}
$buildConnectionInfo(handle: number, connectionString: string): Thenable<sqlops.ConnectionInfo> {
let provider = this._resolveProvider<sqlops.ConnectionProvider>(handle);
if (provider.buildConnectionInfo) {
return provider.buildConnectionInfo(connectionString);
} else {
return TPromise.as(undefined);
}
}
$rebuildIntelliSenseCache(handle: number, connectionUri: string): Thenable<void> {
return this._resolveProvider<sqlops.ConnectionProvider>(handle).rebuildIntelliSenseCache(connectionUri);
}
@@ -617,7 +627,7 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
/**
* Get Agent Proxies list
*/
$getProxies(handle: number, ownerUri: string): Thenable<sqlops.AgentProxiesResult> {
$getProxies(handle: number, ownerUri: string): Thenable<sqlops.AgentProxiesResult> {
return this._resolveProvider<sqlops.AgentServicesProvider>(handle).getProxies(ownerUri);
}

View File

@@ -27,7 +27,6 @@ import { ISerializationService } from 'sql/services/serialization/serializationS
import { IFileBrowserService } from 'sql/parts/fileBrowser/common/interfaces';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import severity from 'vs/base/common/severity';
/**
* Main thread class for handling data protocol management registration.
@@ -91,6 +90,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
getConnectionString(connectionUri: string, includePassword: boolean): Thenable<string> {
return self._proxy.$getConnectionString(handle, connectionUri, includePassword);
},
buildConnectionInfo(connectionString: string): Thenable<sqlops.ConnectionInfo> {
return self._proxy.$buildConnectionInfo(handle, connectionString);
},
rebuildIntelliSenseCache(connectionUri: string): Thenable<void> {
return self._proxy.$rebuildIntelliSenseCache(handle, connectionUri);
}
@@ -343,7 +345,7 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
public $registerAgentServicesProvider(providerId: string, handle: number): TPromise<any> {
const self = this;
this._jobManagementService.registerProvider(providerId, <sqlops.AgentServicesProvider> {
this._jobManagementService.registerProvider(providerId, <sqlops.AgentServicesProvider>{
providerId: providerId,
getJobs(connectionUri: string): Thenable<sqlops.AgentJobsResult> {
return self._proxy.$getJobs(handle, connectionUri);

View File

@@ -22,7 +22,6 @@ import {
IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails,
IModelViewWizardDetails, IModelViewWizardPageDetails
} from 'sql/workbench/api/common/sqlExtHostTypes';
import { Event, Emitter } from 'vs/base/common/event';
export abstract class ExtHostAccountManagementShape {
$autoOAuthCancelled(handle: number): Thenable<void> { throw ni(); }
@@ -73,6 +72,13 @@ export abstract class ExtHostDataProtocolShape {
*/
$getConnectionString(handle: number, connectionUri: string, includePassword: boolean): Thenable<string> { throw ni(); }
/**
* Serialize connection string
* @param handle the handle to use when looking up a provider
* @param connectionString the connection string to serialize
*/
$buildConnectionInfo(handle: number, connectionString: string): Thenable<sqlops.ConnectionInfo> { throw ni(); }
/**
* Notifies all listeners on the Extension Host side that a language change occurred
* for a dataprotocol language. The sub-flavor is the specific implementation used for query
@@ -609,7 +615,7 @@ export interface ExtHostModelViewTreeViewsShape {
$getChildren(treeViewId: string, treeItemHandle?: string): TPromise<ITreeComponentItem[]>;
$createTreeView(handle: number, componentId: string, options: { treeDataProvider: vscode.TreeDataProvider<any> }): sqlops.TreeComponentView<any>;
$onNodeCheckedChanged(treeViewId: string, treeItemHandle?: string, checked?: boolean): void;
$onNodeSelected(treeViewId: string, nodes: string[]): void;
$onNodeSelected(treeViewId: string, nodes: string[]): void;
}
export interface ExtHostBackgroundTaskManagementShape {