Edit Connection Feature added, edit existing connection in connection tree. (#10214)

* Added Edit Connection Command

* Wip changes for new connection dialog

* Testing

* WIP commit

* added ID check to ensure connection

* wip commit

* model id check implemented

* addfooterbutton now accepts events

* wip commit

* message explaining check

* temporary change

* connectionManagementService restored

* Revert "connectionManagementService restored"

This reverts commit 9704a63184a06a33bee2648ef0a899229d117cc0.

* formatting test

* editConnection promise testing

* edit existing connection command added

* WIP Connection Edit

* disconnect added to editConnection promise

* WIP on editExistingConnection

* changed isEdit to true

* Amir/edit connection (#10112)

* Get edit connection working

* Delete unused code

* check for isEdit as well

* connection tree test added

* WIP connection management tests

* comment out test to find out what's wrong

* fix for one error

* added note about test skipped

* changed signature of saveprofile

* saveprofile fixed

* wrote working test

* added additional test

* changed message

* Fixes made

* fix for matcher

Co-authored-by: Amir Omidi <amomidi@microsoft.com>
This commit is contained in:
Alex Ma
2020-05-05 13:21:05 -07:00
committed by GitHub
parent 5fe72d318b
commit 921e546fd7
12 changed files with 234 additions and 59 deletions

View File

@@ -7,7 +7,7 @@ import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilit
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
import { UNSAVED_GROUP_ID } from 'sql/platform/connection/common/constants';
import { IConnectionProfile, IConnectionProfileStore } from 'sql/platform/connection/common/interfaces';
import { IConnectionProfile, IConnectionProfileStore, ProfileMatcher } from 'sql/platform/connection/common/interfaces';
import * as Utils from 'sql/platform/connection/common/utils';
import { generateUuid } from 'vs/base/common/uuid';
import * as nls from 'vs/nls';
@@ -61,7 +61,7 @@ export class ConnectionConfig {
/**
* Add a new connection to the connection config.
*/
public addConnection(profile: IConnectionProfile): Promise<IConnectionProfile> {
public addConnection(profile: IConnectionProfile, matcher: ProfileMatcher = ConnectionProfile.matchesProfile): Promise<IConnectionProfile> {
if (profile.saveProfile) {
return this.addGroupFromProfile(profile).then(groupId => {
let profiles = deepClone(this.configurationService.inspect<IConnectionProfileStore[]>(CONNECTIONS_CONFIG_KEY).userValue);
@@ -75,7 +75,7 @@ export class ConnectionConfig {
// Remove the profile if already set
let sameProfileInList = find(profiles, value => {
let providerConnectionProfile = ConnectionProfile.createFromStoredProfile(value, this._capabilitiesService);
return providerConnectionProfile.matches(connectionProfile);
return matcher(providerConnectionProfile, connectionProfile);
});
if (sameProfileInList) {
let profileIndex = firstIndex(profiles, value => value === sameProfileInList);

View File

@@ -77,6 +77,11 @@ export interface IConnectionManagementService {
// Properties
providerNameToDisplayNameMap: { [providerDisplayName: string]: string };
/**
* Opens the edit connection dialog to change connection.
*/
showEditConnectionDialog(model: IConnectionProfile): Promise<void>;
/**
* Opens the connection dialog to create new connection
*/
@@ -300,6 +305,7 @@ export interface INewConnectionParams {
querySelection?: azdata.ISelectionData;
showDashboard?: boolean;
providers?: string[];
isEditConnection?: boolean;
}
export interface IConnectableInput {

View File

@@ -69,18 +69,23 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa
this.options['databaseDisplayName'] = this.databaseName;
}
public matches(other: interfaces.IConnectionProfile): boolean {
return other
&& this.providerName === other.providerName
&& this.nullCheckEqualsIgnoreCase(this.serverName, other.serverName)
&& this.nullCheckEqualsIgnoreCase(this.databaseName, other.databaseName)
&& this.nullCheckEqualsIgnoreCase(this.userName, other.userName)
&& this.nullCheckEqualsIgnoreCase(this.options['databaseDisplayName'], other.options['databaseDisplayName'])
&& this.authenticationType === other.authenticationType
&& this.groupId === other.groupId;
public static matchesProfile(a: interfaces.IConnectionProfile, b: interfaces.IConnectionProfile): boolean {
return a && b
&& a.providerName === b.providerName
&& ConnectionProfile.nullCheckEqualsIgnoreCase(a.serverName, b.serverName)
&& ConnectionProfile.nullCheckEqualsIgnoreCase(a.databaseName, b.databaseName)
&& ConnectionProfile.nullCheckEqualsIgnoreCase(a.userName, b.userName)
&& ConnectionProfile.nullCheckEqualsIgnoreCase(a.options['databaseDisplayName'], b.options['databaseDisplayName'])
&& a.authenticationType === b.authenticationType
&& a.groupId === b.groupId;
}
private nullCheckEqualsIgnoreCase(a: string, b: string) {
public matches(other: interfaces.IConnectionProfile): boolean {
return ConnectionProfile.matchesProfile(this, other);
}
private static nullCheckEqualsIgnoreCase(a: string, b: string) {
let bothNull: boolean = !a && !b;
return bothNull ? bothNull : equalsIgnoreCase(a, b);
}

View File

@@ -9,7 +9,7 @@ import { ConnectionConfig } from 'sql/platform/connection/common/connectionConfi
import { fixupConnectionCredentials } from 'sql/platform/connection/common/connectionInfo';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { IConnectionProfile, ProfileMatcher } from 'sql/platform/connection/common/interfaces';
import { ICredentialsService } from 'sql/platform/credentials/common/credentialsService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
@@ -103,21 +103,18 @@ export class ConnectionStore {
* @param whether the plaintext password should be written to the settings file
* @returns a Promise that returns the original profile, for help in chaining calls
*/
public saveProfile(profile: IConnectionProfile, forceWritePlaintextPassword?: boolean): Promise<IConnectionProfile> {
public async saveProfile(profile: IConnectionProfile, forceWritePlaintextPassword?: boolean, matcher?: ProfileMatcher): Promise<IConnectionProfile> {
// Add the profile to the saved list, taking care to clear out the password field if necessary
const savedProfile = forceWritePlaintextPassword ? profile : this.getProfileWithoutPassword(profile);
return this.saveProfileToConfig(savedProfile)
.then(savedConnectionProfile => {
profile.groupId = savedConnectionProfile.groupId;
profile.id = savedConnectionProfile.id;
// Only save if we successfully added the profile
return this.saveProfilePasswordIfNeeded(profile);
}).then(() => {
// Add necessary default properties before returning
// this is needed to support immediate connections
fixupConnectionCredentials(profile);
return profile;
});
const savedConnectionProfile = await this.saveProfileToConfig(savedProfile, matcher);
profile.groupId = savedConnectionProfile.groupId;
profile.id = savedConnectionProfile.id;
// Only save if we successfully added the profile
await this.saveProfilePasswordIfNeeded(profile);
// Add necessary default properties before returning
// this is needed to support immediate connections
fixupConnectionCredentials(profile);
return profile;
}
public savePassword(profile: IConnectionProfile): Promise<boolean> {
@@ -134,9 +131,9 @@ export class ConnectionStore {
return this.connectionConfig.addGroup(profile);
}
private saveProfileToConfig(profile: IConnectionProfile): Promise<IConnectionProfile> {
private saveProfileToConfig(profile: IConnectionProfile, matcher?: ProfileMatcher): Promise<IConnectionProfile> {
if (profile.saveProfile) {
return this.connectionConfig.addConnection(profile);
return this.connectionConfig.addConnection(profile, matcher);
} else {
return Promise.resolve(profile);
}

View File

@@ -5,6 +5,9 @@
import * as azdata from 'azdata';
// Used to allow various methods of matching profiles
export type ProfileMatcher = (a: IConnectionProfile, b: IConnectionProfile) => boolean;
export interface IConnectionProfile extends azdata.IConnectionProfile {
getOptionsKey(): string;
matches(profile: azdata.IConnectionProfile): boolean;

View File

@@ -59,6 +59,10 @@ export class TestConnectionManagementService implements IConnectionManagementSer
return undefined!;
}
showEditConnectionDialog(model: IConnectionProfile): Promise<void> {
return undefined!;
}
onConnectionComplete(handle: number, connectionInfoSummary: azdata.ConnectionInfoSummary): void {
}