mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-18 11:01:36 -05:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8eff468100 | ||
|
|
0a2cce3f12 | ||
|
|
2ef4e494c3 | ||
|
|
acb44b8247 | ||
|
|
9d2391c310 | ||
|
|
636771328c | ||
|
|
041bf75121 | ||
|
|
ff10e3a042 | ||
|
|
6092b0a00b | ||
|
|
f996ad0832 | ||
|
|
df4847b517 | ||
|
|
2be85a373f | ||
|
|
75a03a42f5 | ||
|
|
d20d664180 | ||
|
|
bf388cf31a | ||
|
|
0bf439a73e | ||
|
|
1acc00679e | ||
|
|
8e1a288d99 | ||
|
|
5299cd4bbe | ||
|
|
a644558bd0 | ||
|
|
fb807a1d28 | ||
|
|
b6450d553f | ||
|
|
c78b7ca02f | ||
|
|
90fccfda34 | ||
|
|
62ae25d05f | ||
|
|
f7552fb746 | ||
|
|
034d818946 | ||
|
|
94899e6e36 | ||
|
|
a002a8cdec | ||
|
|
1a52c8b0d8 | ||
|
|
949dddfe8c |
@@ -1 +1 @@
|
||||
2023-03-31T12:39:03.753Z
|
||||
2023-07-18T12:39:03.753Z
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#Download base image ubuntu 22.04
|
||||
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:22.04
|
||||
# Download base image ubuntu 20.04
|
||||
FROM mcr.microsoft.com/mirror/docker/library/ubuntu:20.04
|
||||
|
||||
#Set timezone to avoid blocking prompts on docker build
|
||||
# Adding apt repos for g++-7
|
||||
RUN echo "deb http://dk.archive.ubuntu.com/ubuntu/ bionic main" >> /etc/apt/sources.list
|
||||
RUN echo "deb http://dk.archive.ubuntu.com/ubuntu/ bionic universe" >> /etc/apt/sources.list
|
||||
|
||||
# Set timezone to avoid blocking prompts on docker build
|
||||
ENV TZ=America/Los_Angeles
|
||||
RUN ln -snf "/usr/share/zoneinfo/$TZ" /etc/localtime
|
||||
RUN echo "$TZ" > /etc/timezone
|
||||
@@ -14,13 +18,19 @@ RUN apt-get update && apt-get upgrade -y
|
||||
|
||||
RUN apt-get install -y libxkbfile-dev pkg-config libsecret-1-dev libxss1 dbus xvfb libgtk-3-0 \
|
||||
libkrb5-dev git apt-transport-https ca-certificates curl gnupg-agent software-properties-common \
|
||||
libnss3 libasound2 make gcc libx11-dev fakeroot rpm libgconf-2-4 libunwind8 g++ libgbm-dev wget
|
||||
libnss3 libasound2 make gcc libx11-dev fakeroot rpm libgconf-2-4 libunwind8 g++-7 libgbm-dev wget
|
||||
|
||||
|
||||
# make GCC 7 the default compiler
|
||||
RUN rm /usr/bin/gcc
|
||||
RUN ln -s /usr/bin/gcc-7 /usr/bin/gcc
|
||||
RUN ln -s /usr/bin/g++-7 /usr/bin/g++
|
||||
|
||||
# Adding Libssl for dotnet 5.0 and ESRP signing to work
|
||||
RUN wget -c http://security.ubuntu.com/ubuntu/pool/main/o/openssl1.0/libssl1.0.0_1.0.2n-1ubuntu5_amd64.deb
|
||||
RUN dpkg -i libssl1.0.0_1.0.2n-1ubuntu5_amd64.deb
|
||||
|
||||
#docker
|
||||
# docker
|
||||
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
|
||||
RUN apt-key fingerprint 0EBFCD88
|
||||
RUN add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
resources:
|
||||
containers:
|
||||
- container: linux-x64
|
||||
image: sqltoolscontainers.azurecr.io/linux-build-agent:8
|
||||
image: sqltoolscontainers.azurecr.io/linux-build-agent:9
|
||||
endpoint: SqlToolsContainers
|
||||
|
||||
stages:
|
||||
|
||||
@@ -883,6 +883,9 @@ export abstract class AzureAuth implements vscode.Disposable {
|
||||
// unlink both cache files
|
||||
await this.msalCacheProvider.unlinkMsalCache();
|
||||
await this.msalCacheProvider.unlinkLocalCache();
|
||||
|
||||
// Delete Encryption Keys
|
||||
await this.msalCacheProvider.clearCacheEncryptionKeys();
|
||||
}
|
||||
|
||||
public async deleteAllCacheAdal(): Promise<void> {
|
||||
|
||||
@@ -20,6 +20,8 @@ import { Configuration, PublicClientApplication } from '@azure/msal-node';
|
||||
import * as Constants from '../constants';
|
||||
import { Logger } from '../utils/Logger';
|
||||
import { ILoggerCallback, LogLevel as MsalLogLevel } from "@azure/msal-common";
|
||||
import { displayReloadAds } from '../utils';
|
||||
import { reloadPromptCacheClear } from '../localizedConstants';
|
||||
|
||||
let localize = nls.loadMessageBundle();
|
||||
|
||||
@@ -108,8 +110,7 @@ export class AzureAccountProviderService implements vscode.Disposable {
|
||||
return Promise.all(promises)
|
||||
.then(
|
||||
() => {
|
||||
let message = localize('clearTokenCacheSuccess', "Token cache successfully cleared");
|
||||
void vscode.window.showInformationMessage(`${loc.extensionName}: ${message}`);
|
||||
void displayReloadAds(reloadPromptCacheClear);
|
||||
},
|
||||
err => {
|
||||
let message = localize('clearTokenCacheFailure', "Failed to clear token cache");
|
||||
|
||||
@@ -100,10 +100,7 @@ export class FileEncryptionHelper {
|
||||
if (resetOnError) {
|
||||
// Reset IV/Keys if crypto cannot encrypt/decrypt data.
|
||||
// This could be a possible case of corruption of expected iv/key combination
|
||||
await this.deleteEncryptionKey(this._ivCredId);
|
||||
await this.deleteEncryptionKey(this._keyCredId);
|
||||
this._ivBuffer = undefined;
|
||||
this._keyBuffer = undefined;
|
||||
await this.clearEncryptionKeys();
|
||||
await this.init();
|
||||
}
|
||||
// Throw error so cache file can be reset to empty.
|
||||
@@ -111,6 +108,13 @@ export class FileEncryptionHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public async clearEncryptionKeys(): Promise<void> {
|
||||
await this.deleteEncryptionKey(this._ivCredId);
|
||||
await this.deleteEncryptionKey(this._keyCredId);
|
||||
this._ivBuffer = undefined;
|
||||
this._keyBuffer = undefined;
|
||||
}
|
||||
|
||||
protected async readEncryptionKey(credentialId: string): Promise<string | undefined> {
|
||||
return (await this._credentialService.readCredential(credentialId))?.password;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,10 @@ export class MsalCachePluginProvider {
|
||||
return this._fileEncryptionHelper.getEncryptionKeys();
|
||||
}
|
||||
|
||||
public async clearCacheEncryptionKeys(): Promise<void> {
|
||||
await this._fileEncryptionHelper.clearEncryptionKeys();
|
||||
}
|
||||
|
||||
public getCachePlugin(): ICachePlugin {
|
||||
const beforeCacheAccess = async (cacheContext: TokenCacheContext): Promise<void> => {
|
||||
try {
|
||||
|
||||
@@ -293,7 +293,7 @@ async function onDidChangeConfiguration(e: vscode.ConfigurationChangeEvent): Pro
|
||||
if (vscode.workspace.getConfiguration(Constants.AzureSection).get('authenticationLibrary') === 'ADAL') {
|
||||
void vscode.window.showInformationMessage(loc.deprecatedOption);
|
||||
}
|
||||
await displayReloadAds();
|
||||
await utils.displayReloadAds(loc.reloadPrompt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,17 +301,3 @@ function updatePiiLoggingLevel(): void {
|
||||
const piiLogging: boolean = vscode.workspace.getConfiguration(Constants.AzureSection).get('piiLogging', false);
|
||||
Logger.piiLogging = piiLogging;
|
||||
}
|
||||
|
||||
// Display notification with button to reload
|
||||
// return true if button clicked
|
||||
// return false if button not clicked
|
||||
async function displayReloadAds(): Promise<boolean> {
|
||||
const result = await vscode.window.showInformationMessage(loc.reloadPrompt, loc.reloadChoice);
|
||||
if (result === loc.reloadChoice) {
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ export const subscription = localize('azurecore.subscription', "Subscription");
|
||||
export const typeIcon = localize('azurecore.typeIcon', "Type Icon");
|
||||
|
||||
export const reloadPrompt = localize('azurecore.reloadPrompt', "Authentication Library has changed, please reload Azure Data Studio.");
|
||||
export const reloadPromptCacheClear = localize('azurecore.reloadPromptCacheClear', "Token cache has been cleared successfully, please reload Azure Data Studio.");
|
||||
export const reloadChoice = localize('azurecore.reloadChoice', "Reload Azure Data Studio");
|
||||
|
||||
export const deprecatedOption = localize('azurecore.deprecated', "Warning: ADAL has been deprecated, and is scheduled to be removed in the next release. Please use MSAL instead.");
|
||||
|
||||
@@ -200,3 +200,17 @@ export function getProxyEnabledHttpClient(): HttpClient {
|
||||
|
||||
return new HttpClient(proxy, agentOptions);
|
||||
}
|
||||
|
||||
/* Display notification with button to reload
|
||||
* return true if button clicked
|
||||
* return false if button not clicked
|
||||
*/
|
||||
export async function displayReloadAds(message: string): Promise<boolean> {
|
||||
const result = await vscode.window.showInformationMessage(message, loc.reloadChoice);
|
||||
if (result === loc.reloadChoice) {
|
||||
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "4.8.0.39",
|
||||
"version": "4.8.1.5",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-net7.0.zip",
|
||||
"Windows_64": "win-x64-net7.0.zip",
|
||||
|
||||
@@ -83,6 +83,12 @@
|
||||
"title": "%title.newObject%",
|
||||
"icon": "$(add)"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"category": "MSSQL",
|
||||
"title": "%title.newDatabase%",
|
||||
"icon": "$(add)"
|
||||
},
|
||||
{
|
||||
"command": "mssql.objectProperties",
|
||||
"category": "MSSQL",
|
||||
@@ -490,6 +496,10 @@
|
||||
"command": "mssql.newObject",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "mssql.objectProperties",
|
||||
"when": "false"
|
||||
@@ -526,12 +536,22 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.newObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType =~ /^(ServerLevelLogins|Users|ServerLevelServerRoles|ApplicationRoles|DatabaseRoles|Databases)$/ && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType =~ /^(ServerLevelLogins|Users|ServerLevelServerRoles|ApplicationRoles|DatabaseRoles)$/ && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType == Databases && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
@@ -546,7 +566,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.detachDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !isCloud && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !isCloud && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures && (productQualityType =~ /^(insider|dev)$/ || isDevelopment)",
|
||||
"group": "1_objectManagement@2"
|
||||
},
|
||||
{
|
||||
@@ -567,7 +587,7 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.objectProperties",
|
||||
"when": "connectionProvider == MSSQL && serverInfo && !isCloud && nodeType && nodeType =~ /^(Database|Server)$/ && mssql:engineedition != 11 && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && serverInfo && !isCloud && nodeType =~ /^(Database|Server)$/ && mssql:engineedition != 11 && config.workbench.enablePreviewFeatures && (productQualityType =~ /^(insider|dev)$/ || isDevelopment)",
|
||||
"group": "z_objectexplorer@3"
|
||||
},
|
||||
{
|
||||
@@ -613,12 +633,22 @@
|
||||
},
|
||||
{
|
||||
"command": "mssql.newObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType =~ /^(ServerLevelLogins|Users|ServerLevelServerRoles|ApplicationRoles|DatabaseRoles|Databases)$/ && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType =~ /^(ServerLevelLogins|Users|ServerLevelServerRoles|ApplicationRoles|DatabaseRoles)$/ && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newObject",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole|Database)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"when": "connectionProvider == MSSQL && nodeType =~ /^(ServerLevelLogin|User|ServerLevelServerRole|ApplicationRole|DatabaseRole)$/ && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Folder && objectType == Databases && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
"command": "mssql.newDatabase",
|
||||
"when": "connectionProvider == MSSQL && nodeType == Database && !(nodePath =~ /^.*\\/System Databases\\/.*$/) && config.workbench.enablePreviewFeatures",
|
||||
"group": "1_objectManagement@0"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -186,6 +186,7 @@
|
||||
"mssql.objectExplorer.disableGroupBySchemaTitle": "SQL Server: Disable Group By Schema",
|
||||
"mssql.objectExplorer.expandTimeout": "The timeout in seconds for expanding a node in Object Explorer. The default value is 45 seconds.",
|
||||
"title.newObject": "New (Preview)",
|
||||
"title.newDatabase": "New Database (Preview)",
|
||||
"title.objectProperties": "Properties (Preview)",
|
||||
"title.deleteObject": "Delete (Preview)",
|
||||
"title.renameObject": "Rename (Preview)",
|
||||
|
||||
@@ -31,6 +31,9 @@ export function registerObjectManagementCommands(appContext: AppContext) {
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.newObject', async (context: azdata.ObjectExplorerContext) => {
|
||||
await handleNewObjectDialogCommand(context, service);
|
||||
}));
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.newDatabase', async (context: azdata.ObjectExplorerContext) => {
|
||||
await handleNewObjectDialogCommand(context, service);
|
||||
}));
|
||||
appContext.extensionContext.subscriptions.push(vscode.commands.registerCommand('mssql.objectProperties', async (context: azdata.ObjectExplorerContext) => {
|
||||
await handleObjectPropertiesDialogCommand(context, service);
|
||||
}));
|
||||
|
||||
@@ -114,10 +114,17 @@ export class DatabaseDialog extends ObjectManagementDialogBase<Database, Databas
|
||||
//#region Create Database
|
||||
private initializeGeneralSection(): azdata.GroupContainer {
|
||||
let containers: azdata.Component[] = [];
|
||||
this.nameInput = this.createInputBox(localizedConstants.NameText, async () => {
|
||||
// The max length for database names is 128 characters: https://learn.microsoft.com/sql/t-sql/functions/db-name-transact-sql
|
||||
const maxLengthDatabaseName: number = 128;
|
||||
const props: azdata.InputBoxProperties = {
|
||||
ariaLabel: localizedConstants.NameText,
|
||||
required: true,
|
||||
maxLength: maxLengthDatabaseName
|
||||
};
|
||||
|
||||
this.nameInput = this.createInputBoxWithProperties(async () => {
|
||||
this.objectInfo.name = this.nameInput.value;
|
||||
await this.runValidation(false);
|
||||
});
|
||||
}, props);
|
||||
containers.push(this.createLabelInputContainer(localizedConstants.NameText, this.nameInput));
|
||||
|
||||
if (this.viewInfo.loginNames?.length > 0) {
|
||||
|
||||
@@ -26,18 +26,11 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
if (!connectionString) {
|
||||
throw new Error(FailedToGetConnectionStringError);
|
||||
}
|
||||
let titleString = `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`;
|
||||
// append distinguishing options to end to let users know exact connection.
|
||||
let distinguishingOptions = await azdata.connection.getEditorConnectionProfileTitle(context.connectionProfile, true);
|
||||
if (distinguishingOptions !== '') {
|
||||
distinguishingOptions = distinguishingOptions.replace('(', '[').replace(')', ']');
|
||||
titleString += `${distinguishingOptions}`;
|
||||
}
|
||||
const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon;
|
||||
const telemetryInfo = await getTelemetryInfo(context, tableIcon);
|
||||
await azdata.designers.openTableDesigner(sqlProviderName, {
|
||||
title: NewTableText,
|
||||
tooltip: titleString,
|
||||
tooltip: `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`,
|
||||
server: context.connectionProfile!.serverName,
|
||||
database: context.connectionProfile!.databaseName,
|
||||
isNewTable: true,
|
||||
@@ -63,18 +56,11 @@ export function registerTableDesignerCommands(appContext: AppContext) {
|
||||
if (!connectionString) {
|
||||
throw new Error(FailedToGetConnectionStringError);
|
||||
}
|
||||
let titleString = `${server} - ${database} - ${schema}.${name}`;
|
||||
// append distinguishing options to end to let users know exact connection.
|
||||
let distinguishingOptions = await azdata.connection.getEditorConnectionProfileTitle(context.connectionProfile, true);
|
||||
if (distinguishingOptions !== '') {
|
||||
distinguishingOptions = distinguishingOptions.replace('(', '[').replace(')', ']');
|
||||
titleString += `${distinguishingOptions}`;
|
||||
}
|
||||
const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon;
|
||||
const telemetryInfo = await getTelemetryInfo(context, tableIcon);
|
||||
await azdata.designers.openTableDesigner(sqlProviderName, {
|
||||
title: `${schema}.${name}`,
|
||||
tooltip: titleString,
|
||||
tooltip: `${server} - ${database} - ${schema}.${name}`,
|
||||
server: server,
|
||||
database: database,
|
||||
isNewTable: false,
|
||||
|
||||
@@ -147,6 +147,24 @@ export abstract class DialogBase<DialogResult> {
|
||||
return this.createInputBox(ariaLabel, textChangeHandler, value, enabled, 'password', width);
|
||||
}
|
||||
|
||||
protected createInputBoxWithProperties(textChangeHandler: (newValue: string) => Promise<void>, properties: azdata.InputBoxProperties, customValidation?: () => Promise<boolean>): azdata.InputBoxComponent {
|
||||
properties.width = properties.width ?? DefaultInputWidth;
|
||||
properties.inputType = properties.inputType ?? 'text';
|
||||
properties.value = properties.value ?? '';
|
||||
properties.enabled = properties.enabled ?? true;
|
||||
const inputbox = this.modelView.modelBuilder.inputBox().withProps(properties);
|
||||
if (customValidation) {
|
||||
inputbox.withValidation(customValidation);
|
||||
}
|
||||
const inputBoxComponent = inputbox.component();
|
||||
this.disposables.push(inputBoxComponent.onTextChanged(async () => {
|
||||
await textChangeHandler(inputBoxComponent.value!);
|
||||
this.onFormFieldChange();
|
||||
await this.runValidation(false);
|
||||
}));
|
||||
return inputBoxComponent;
|
||||
}
|
||||
|
||||
protected createInputBox(ariaLabel: string, textChangeHandler: (newValue: string) => Promise<void>, value: string = '', enabled: boolean = true, type: azdata.InputBoxInputType = 'text', width: number = DefaultInputWidth, min?: number, max?: number): azdata.InputBoxComponent {
|
||||
const inputbox = this.modelView.modelBuilder.inputBox().withProps({ inputType: type, enabled: enabled, ariaLabel: ariaLabel, value: value, width: width, min: min, max: max }).component();
|
||||
this.disposables.push(inputbox.onTextChanged(async () => {
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
"name": "profiler",
|
||||
"displayName": "%displayName%",
|
||||
"description": "%description%",
|
||||
"version": "0.13.0",
|
||||
"version": "0.14.0",
|
||||
"publisher": "Microsoft",
|
||||
"preview": true,
|
||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/main/LICENSE.txt",
|
||||
"icon": "images/extension.png",
|
||||
"engines": {
|
||||
"vscode": "0.10.0"
|
||||
"vscode": "*",
|
||||
"azdata": ">=1.45.0"
|
||||
},
|
||||
"activationEvents": [
|
||||
"*"
|
||||
|
||||
@@ -51,7 +51,9 @@ export class CreateProjectFromDatabaseDialog {
|
||||
this.dialog.cancelButton.label = constants.cancelButtonText;
|
||||
|
||||
let connected = false;
|
||||
if (this.profile) {
|
||||
|
||||
// make sure the connection profile passed in has sufficient information to attempt to connect
|
||||
if (this.profile && this.profile?.serverName) {
|
||||
const connections = await getAzdataApi()!.connection.getConnections(true);
|
||||
connected = !!connections.find(c => c.connectionId === this.profile!.id);
|
||||
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Ja (empfohlen)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "Erste &&Schritte",
|
||||
"showReleaseNotes": "\"Erste Schritte\" anzeigen"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Verbindung erstellen",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Sí (opción recomendada)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "I&&ntroducción",
|
||||
"showReleaseNotes": "Ver introducción"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Crear una conexión",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Oui (recommandé)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "Pri&&se en main",
|
||||
"showReleaseNotes": "Afficher la mise en route"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Créer une connexion",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Sì (scelta consigliata)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "&&Introduzione",
|
||||
"showReleaseNotes": "Mostra introduzione"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Crea una connessione",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "はい (推奨)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "はじめに(&&S)",
|
||||
"showReleaseNotes": "「はじめに」を表示する"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "接続の作成",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "예(추천)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "시작(&&S)",
|
||||
"showReleaseNotes": "시작 표시"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "연결 만들기",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Sim (recomendado)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "I&&ntrodução",
|
||||
"showReleaseNotes": "Mostrar Introdução"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Criar uma conexão",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "Да (рекомендуется)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "&&Начало работы",
|
||||
"showReleaseNotes": "Показать раздел \"Начало работы\""
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "Создать подключение",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "是(推荐)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "入门(&&S)",
|
||||
"showReleaseNotes": "显示入门指南"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "创建连接",
|
||||
|
||||
@@ -14606,8 +14606,8 @@
|
||||
"enablePreviewFeatures.yes": "是 (建議)"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/gettingStarted/electron-browser/gettingStarted": {
|
||||
"miGettingStarted": "Getting &&Started",
|
||||
"showReleaseNotes": "Show Getting Started"
|
||||
"miGettingStarted": "使用者入門(&&S)",
|
||||
"showReleaseNotes": "顯示使用者入門"
|
||||
},
|
||||
"sql/workbench/contrib/welcome/page/browser/az_data_welcome_page": {
|
||||
"welcomePage.createConnection": "建立連線",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"reportIssueUrl": "https://github.com/Microsoft/azuredatastudio/issues/new",
|
||||
"requestFeatureUrl": "https://go.microsoft.com/fwlink/?linkid=2118021",
|
||||
"privacyStatementUrl": "https://privacy.microsoft.com/privacystatement",
|
||||
"telemetryOptOutUrl": "https://github.com/Microsoft/azuredatastudio/wiki/How-to-Disable-Telemetry-Reporting",
|
||||
"telemetryOptOutUrl": "https://go.microsoft.com/fwlink/?linkid=2241254",
|
||||
"urlProtocol": "azuredatastudio-oss",
|
||||
"enableTelemetry": false,
|
||||
"webviewContentExternalBaseUrlTemplate": "https://{{uuid}}.vscode-cdn.net/insider/3c8520fab514b9f56070214496b26ff68d1b1cb5/out/vs/workbench/contrib/webview/browser/pre/",
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Fehler: {1}</target>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">Erste &&Schritte</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">"Erste Schritte" anzeigen</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</target>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">I&&ntroducción</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">Ver introducción</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Erreur : {1}</target>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">Pri&&se en main</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">Afficher la mise en route</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Errore: {1}</target>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">&&Introduzione</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">Mostra introduzione</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</source>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">はじめに(&&S)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">「はじめに」を表示する</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</source>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">시작(&&S)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">시작 표시</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7097,11 +7097,11 @@ Erro: {1}</target>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">I&&ntrodução</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">Mostrar Introdução</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</source>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">&&Начало работы</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">Показать раздел "Начало работы"</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</source>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">入门(&&S)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">显示入门指南</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
@@ -7096,11 +7096,11 @@ Error: {1}</source>
|
||||
<trans-unit id="miGettingStarted">
|
||||
<source xml:lang="en">Getting &&Started</source>
|
||||
<note>&& denotes a mnemonic</note>
|
||||
<target state="new">Getting &&Started</target>
|
||||
<target state="translated">使用者入門(&&S)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="showReleaseNotes">
|
||||
<source xml:lang="en">Show Getting Started</source>
|
||||
<target state="new">Show Getting Started</target>
|
||||
<target state="translated">顯示使用者入門</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
||||
9
src/sql/azdata.proposed.d.ts
vendored
9
src/sql/azdata.proposed.d.ts
vendored
@@ -508,15 +508,6 @@ declare module 'azdata' {
|
||||
* @returns The new password that is returned from the operation or undefined if unsuccessful.
|
||||
*/
|
||||
export function openChangePasswordDialog(profile: IConnectionProfile): Thenable<string | undefined>;
|
||||
|
||||
/**
|
||||
* Gets the formatted title of the connection profile for display
|
||||
* @param profile The connection profile we want to get the full display info for.
|
||||
* @param getOptionsOnly Provide if you only want to get the differing advanced options (for some titles).
|
||||
* @param includeGroupName Provide if you want to include the groupName as well (in areas that do not display the groupName).
|
||||
* @returns The title formatted with server info in front, with non default options at the end.
|
||||
*/
|
||||
export function getEditorConnectionProfileTitle(profile: IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): Thenable<string>;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -79,7 +79,7 @@ export class Dropdown extends BaseDropdown {
|
||||
}
|
||||
}
|
||||
|
||||
export class DropdownList extends BaseDropdown {
|
||||
export class DropdownList extends Dropdown {
|
||||
protected borderWidth = 1;
|
||||
|
||||
private button?: Button;
|
||||
@@ -145,7 +145,7 @@ export class DropdownList extends BaseDropdown {
|
||||
/**
|
||||
* Render the dropdown contents
|
||||
*/
|
||||
protected renderContents(container: HTMLElement): IDisposable | null {
|
||||
protected override renderContents(container: HTMLElement): IDisposable | null {
|
||||
let div = DOM.append(container, this._contentContainer);
|
||||
div.style.width = (DOM.getTotalWidth(this.element) - this.borderWidth * 2) + 'px'; // Subtract border width
|
||||
return { dispose: () => { } };
|
||||
|
||||
@@ -14,6 +14,7 @@ import * as nls from 'vs/nls';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import { isDisposable } from 'vs/base/common/lifecycle';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
|
||||
export const GROUPS_CONFIG_KEY = 'datasource.connectionGroups';
|
||||
export const CONNECTIONS_CONFIG_KEY = 'datasource.connections';
|
||||
@@ -241,6 +242,11 @@ export class ConnectionConfig {
|
||||
profile.id = generateUuid();
|
||||
changed = true;
|
||||
}
|
||||
// SSMS 19 requires "user", fix any profiles created without user property.
|
||||
if (profile.providerName === 'MSSQL' && isUndefinedOrNull(profile.options.user)) {
|
||||
profile.options.user = '';
|
||||
changed = true;
|
||||
}
|
||||
idsCache[profile.id] = true;
|
||||
}
|
||||
return changed;
|
||||
@@ -359,10 +365,10 @@ export class ConnectionConfig {
|
||||
let profiles = this.getIConnectionProfileStores(true);
|
||||
let existingProfile = profiles.find(p =>
|
||||
p.providerName === profile.providerName &&
|
||||
p.options.authenticationType === profile.options.authenticationType &&
|
||||
p.options.database === profile.options.database &&
|
||||
p.options.server === profile.options.server &&
|
||||
p.options.user === profile.options.user &&
|
||||
this.checkIfAuthenticationOptionsMatch(p, profile) &&
|
||||
p.options.databaseName === profile.options.databaseName &&
|
||||
p.options.serverName === profile.options.serverName &&
|
||||
p.options.userName === profile.options.userName &&
|
||||
p.options.connectionName === profile.options.connectionName &&
|
||||
p.groupId === newGroupID &&
|
||||
this.checkIfNonDefaultOptionsMatch(p, profile));
|
||||
@@ -375,6 +381,10 @@ export class ConnectionConfig {
|
||||
return result;
|
||||
}
|
||||
|
||||
private checkIfAuthenticationOptionsMatch(profileStore: IConnectionProfileStore, profile: ConnectionProfile): boolean {
|
||||
return ((profileStore.options.authenticationType === undefined || profileStore.options.authenticationType === '') && (profile.options.authenticationType === undefined || profile.options.authenticationType === '')) || profileStore.options.authenticationType === profile.options.authenticationType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the connection under the target group with the new ID.
|
||||
*/
|
||||
|
||||
@@ -381,15 +381,6 @@ export interface IConnectionManagementService {
|
||||
* @returns the new valid password that is entered, or undefined if cancelled or errored.
|
||||
*/
|
||||
openChangePasswordDialog(profile: IConnectionProfile): Promise<string | undefined>;
|
||||
|
||||
/**
|
||||
* Gets the formatted title of the connection profile for display.
|
||||
* @param profile The connection profile we want to get the full display info for.
|
||||
* @param getOptionsOnly Provide if you only want to get the differing advanced options (for some titles).
|
||||
* @param includeGroupName Provide if you want to include the groupName as well (in areas that do not display the groupName).
|
||||
* @returns The title formatted with server info in front, with non default options at the end.
|
||||
*/
|
||||
getEditorConnectionProfileTitle(profile: IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): string;
|
||||
}
|
||||
|
||||
export enum RunQueryOnConnectionMode {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ProviderConnectionInfo } from 'sql/platform/connection/common/providerC
|
||||
import * as interfaces from 'sql/platform/connection/common/interfaces';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
import { isString, isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { deepClone } from 'vs/base/common/objects';
|
||||
import * as Constants from 'sql/platform/connection/common/constants';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -81,7 +81,7 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa
|
||||
// Set values for advanced options received in model.
|
||||
Object.keys(model.options).forEach(a => {
|
||||
let option = options.find(opt => opt.name === a);
|
||||
if (option !== undefined) {
|
||||
if (option !== undefined && option.defaultValue?.toString().toLocaleLowerCase() !== model.options[a]?.toString().toLocaleLowerCase()) {
|
||||
this.options[option.name] = model.options[a];
|
||||
}
|
||||
});
|
||||
@@ -358,7 +358,13 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa
|
||||
id: connectionInfo.id
|
||||
};
|
||||
|
||||
profile.options = connectionInfo.options;
|
||||
Object.keys(connectionInfo.options).forEach(element => {
|
||||
// Allow empty strings to ensure "user": "" is populated if empty << Required by SSMS 19.2
|
||||
// Do not change this design until SSMS 19 goes out of support.
|
||||
if (!isUndefinedOrNull(connectionInfo.options[element])) {
|
||||
profile.options[element] = connectionInfo.options[element];
|
||||
}
|
||||
});
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
@@ -326,12 +326,6 @@ export class ConnectionStore {
|
||||
return this.convertToConnectionGroup(groups, profilesInConfiguration);
|
||||
}
|
||||
|
||||
public getAllConnectionsFromConfig(): ConnectionProfile[] {
|
||||
let profilesInConfiguration: ConnectionProfile[] | undefined;
|
||||
profilesInConfiguration = this.connectionConfig.getConnections(true);
|
||||
return profilesInConfiguration;
|
||||
}
|
||||
|
||||
private convertToConnectionGroup(groups: IConnectionProfileGroup[], connections?: ConnectionProfile[], parent?: ConnectionProfileGroup): ConnectionProfileGroup[] {
|
||||
const result: ConnectionProfileGroup[] = [];
|
||||
const children = groups.filter(g => g.parentId === (parent ? parent.id : undefined));
|
||||
|
||||
@@ -134,7 +134,7 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
||||
this.options[name] = value;
|
||||
}
|
||||
|
||||
public getServerInfo() {
|
||||
private getServerInfo() {
|
||||
let title = '';
|
||||
if (this.serverCapabilities) {
|
||||
title = this.serverName;
|
||||
@@ -169,7 +169,7 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
||||
return label;
|
||||
}
|
||||
|
||||
public hasLoaded(): boolean {
|
||||
private hasLoaded(): boolean {
|
||||
return Object.keys(this.capabilitiesService.providers).length > 0;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,8 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
||||
let finalValue = undefined;
|
||||
let options = this.serverCapabilities.connectionOptions.filter(value => value.name === idNames[index]!);
|
||||
if (options.length > 0 && value) {
|
||||
finalValue = value !== options[0].defaultValue ? value : undefined;
|
||||
let defaultValue = options[0].defaultValue ?? '';
|
||||
finalValue = value && value.toString().toLocaleLowerCase() !== defaultValue.toString().toLocaleLowerCase() ? value : undefined;
|
||||
if (options[0].specialValueType === 'appName' && this.providerName === Constants.mssqlProviderName) {
|
||||
finalValue = (value as string).startsWith('azdata') ? undefined : finalValue
|
||||
}
|
||||
@@ -390,7 +391,7 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo {
|
||||
element.specialValueType !== ConnectionOptionSpecialType.password) {
|
||||
if (getNonDefault) {
|
||||
let value = this.getOptionValue(element.name);
|
||||
if (value && value !== element.defaultValue) {
|
||||
if (value && value.toString().toLocaleLowerCase() !== element.defaultValue?.toLocaleLowerCase()) {
|
||||
connectionOptions.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
authenticationType: 'SqlLogin'
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'test',
|
||||
@@ -95,7 +95,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
authenticationType: 'SqlLogin'
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'test',
|
||||
@@ -108,7 +108,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: ''
|
||||
authenticationType: 'SqlLogin'
|
||||
},
|
||||
providerName: 'MSSQL',
|
||||
groupId: 'g3',
|
||||
@@ -296,7 +296,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: undefined,
|
||||
groupId: undefined,
|
||||
@@ -364,7 +364,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: undefined,
|
||||
@@ -509,7 +509,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -541,7 +541,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -580,7 +580,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'newid',
|
||||
@@ -662,7 +662,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -681,7 +681,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -723,7 +723,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -745,7 +745,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -785,7 +785,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -807,7 +807,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -816,7 +816,10 @@ suite('ConnectionConfig', () => {
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { 'testProperty1': 'nonDefault' },
|
||||
options: {
|
||||
'testProperty1': 'nonDefault',
|
||||
'testProperty2': '10'
|
||||
},
|
||||
saveProfile: true,
|
||||
id: 'server3',
|
||||
connectionName: undefined!
|
||||
@@ -850,7 +853,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -872,7 +875,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -912,7 +915,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -1016,7 +1019,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
@@ -1035,7 +1038,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -1054,7 +1057,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -1090,7 +1093,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
@@ -1128,7 +1131,7 @@ suite('ConnectionConfig', () => {
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
authenticationType: 'SqlLogin',
|
||||
savePassword: true,
|
||||
groupFullName: 'test',
|
||||
groupId: 'test',
|
||||
|
||||
@@ -355,10 +355,6 @@ export class TestConnectionManagementService implements IConnectionManagementSer
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getEditorConnectionProfileTitle(profile: IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): string {
|
||||
return undefined!;
|
||||
}
|
||||
|
||||
openCustomErrorDialog(options: azdata.window.IErrorDialogOptions): Promise<string | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -185,10 +185,6 @@ export class MainThreadConnectionManagement extends Disposable implements MainTh
|
||||
return this._connectionManagementService.openChangePasswordDialog(convertedProfile);
|
||||
}
|
||||
|
||||
public $getEditorConnectionProfileTitle(profile: IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): Thenable<string | undefined> {
|
||||
return Promise.resolve(this._connectionManagementService.getEditorConnectionProfileTitle(profile, getOptionsOnly, includeGroupName));
|
||||
}
|
||||
|
||||
public async $listDatabases(connectionId: string): Promise<string[]> {
|
||||
let connectionUri = await this.$getUriForConnection(connectionId);
|
||||
let result = await this._connectionManagementService.listDatabases(connectionUri);
|
||||
|
||||
@@ -78,10 +78,6 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap
|
||||
return this._proxy.$openChangePasswordDialog(profile);
|
||||
}
|
||||
|
||||
public $getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): Thenable<string> {
|
||||
return this._proxy.$getEditorConnectionProfileTitle(profile, getOptionsOnly, includeGroupName);
|
||||
}
|
||||
|
||||
public $listDatabases(connectionId: string): Thenable<string[]> {
|
||||
return this._proxy.$listDatabases(connectionId);
|
||||
}
|
||||
|
||||
@@ -141,9 +141,6 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp
|
||||
openChangePasswordDialog(profile: azdata.IConnectionProfile): Thenable<string | undefined> {
|
||||
return extHostConnectionManagement.$openChangePasswordDialog(profile);
|
||||
},
|
||||
getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): Thenable<string> {
|
||||
return extHostConnectionManagement.$getEditorConnectionProfileTitle(profile, getOptionsOnly, includeGroupName);
|
||||
},
|
||||
listDatabases(connectionId: string): Thenable<string[]> {
|
||||
return extHostConnectionManagement.$listDatabases(connectionId);
|
||||
},
|
||||
|
||||
@@ -729,7 +729,6 @@ export interface MainThreadConnectionManagementShape extends IDisposable {
|
||||
$getServerInfo(connectedId: string): Thenable<azdata.ServerInfo>;
|
||||
$openConnectionDialog(providers: string[], initialConnectionProfile?: azdata.IConnectionProfile, connectionCompletionOptions?: azdata.IConnectionCompletionOptions): Thenable<azdata.connection.Connection>;
|
||||
$openChangePasswordDialog(profile: azdata.IConnectionProfile): Thenable<string | undefined>;
|
||||
$getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): Thenable<string>;
|
||||
$listDatabases(connectionId: string): Thenable<string[]>;
|
||||
$getConnectionString(connectionId: string, includePassword: boolean): Thenable<string>;
|
||||
$getUriForConnection(connectionId: string): Thenable<string>;
|
||||
|
||||
@@ -85,14 +85,11 @@ export class DashboardInput extends EditorInput {
|
||||
}
|
||||
|
||||
let name = this.connectionProfile.connectionName ? this.connectionProfile.connectionName : this.connectionProfile.serverName
|
||||
|
||||
if (!this.connectionProfile.connectionName && this.connectionProfile.databaseName
|
||||
if (this.connectionProfile.databaseName
|
||||
&& !this.isMasterMssql()) {
|
||||
// Only add DB name if this is a non-default, non-master connection
|
||||
name = name + ':' + this.connectionProfile.databaseName;
|
||||
}
|
||||
// Append any differing options if needed.
|
||||
name += this._connectionService.getEditorConnectionProfileTitle(this.connectionProfile, true, true)
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,17 +243,11 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab
|
||||
title = this._description + ' ';
|
||||
}
|
||||
if (profile) {
|
||||
let distinguishedTitle = this.connectionManagementService.getEditorConnectionProfileTitle(profile);
|
||||
if (distinguishedTitle !== '') {
|
||||
title += distinguishedTitle;
|
||||
}
|
||||
else {
|
||||
title += `${profile.serverName}`;
|
||||
if (profile.databaseName) {
|
||||
title += `.${profile.databaseName}`;
|
||||
}
|
||||
title += ` (${profile.userName || profile.authenticationType})`;
|
||||
title += `${profile.serverName}`;
|
||||
if (profile.databaseName) {
|
||||
title += `.${profile.databaseName}`;
|
||||
}
|
||||
title += ` (${profile.userName || profile.authenticationType})`;
|
||||
} else {
|
||||
title += localize('disconnected', "disconnected");
|
||||
}
|
||||
|
||||
@@ -220,11 +220,11 @@ export class Graph implements IInsight {
|
||||
};
|
||||
|
||||
if (options.xAxisMax !== undefined) {
|
||||
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { max: options.xAxisMax } }] }, true, customMixin);
|
||||
retval.scales = mixin(retval.scales, { x: { max: options.xAxisMax } }, true, customMixin);
|
||||
}
|
||||
|
||||
if (options.xAxisMin !== undefined) {
|
||||
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { min: options.xAxisMin } }] }, true, customMixin);
|
||||
retval.scales = mixin(retval.scales, { x: { min: options.xAxisMin } }, true, customMixin);
|
||||
}
|
||||
|
||||
retval.scales.y = {
|
||||
@@ -242,11 +242,11 @@ export class Graph implements IInsight {
|
||||
};
|
||||
|
||||
if (options.yAxisMax !== undefined) {
|
||||
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { max: options.yAxisMax } }] }, true, customMixin);
|
||||
retval.scales = mixin(retval.scales, { y: { max: options.yAxisMax } }, true, customMixin);
|
||||
}
|
||||
|
||||
if (options.yAxisMin !== undefined) {
|
||||
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { min: options.yAxisMin } }] }, true, customMixin);
|
||||
retval.scales = mixin(retval.scales, { y: { min: options.yAxisMin } }, true, customMixin);
|
||||
}
|
||||
|
||||
if (this.originalType === ChartType.TimeSeries) {
|
||||
@@ -254,11 +254,9 @@ export class Graph implements IInsight {
|
||||
if (options.xAxisMax !== undefined) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
max: options.xAxisMax
|
||||
}
|
||||
}],
|
||||
x: {
|
||||
max: options.xAxisMax
|
||||
}
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
@@ -266,11 +264,9 @@ export class Graph implements IInsight {
|
||||
if (options.xAxisMin !== undefined) {
|
||||
retval = mixin(retval, {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
min: options.xAxisMin
|
||||
}
|
||||
}],
|
||||
x: {
|
||||
min: options.xAxisMin
|
||||
}
|
||||
}
|
||||
}, true, customMixin);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/acti
|
||||
import { localize } from 'vs/nls';
|
||||
import { ConnectionStatusbarItem } from 'sql/workbench/contrib/connection/browser/connectionStatus';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||
import { ConnectionType, IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
@@ -21,6 +21,7 @@ import { ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ActiveConnectionsFilterAction, AddServerAction, AddServerGroupAction } from 'sql/workbench/services/objectExplorer/browser/connectionTreeAction';
|
||||
import { CONTEXT_SERVER_TREE_VIEW, CONTEXT_SERVER_TREE_HAS_CONNECTIONS } from 'sql/workbench/contrib/objectExplorer/browser/serverTreeView';
|
||||
import { SqlIconId } from 'sql/base/common/codicons';
|
||||
import * as Utils from 'sql/platform/connection/common/utils';
|
||||
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
|
||||
@@ -132,23 +133,31 @@ CommandsRegistry.registerCommand('azdata.connect',
|
||||
groupFullName: undefined,
|
||||
saveProfile: true,
|
||||
id: undefined,
|
||||
groupId: undefined,
|
||||
groupId: Utils.defaultGroupId,
|
||||
options: args.options
|
||||
};
|
||||
const connectionProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesServices, profile);
|
||||
|
||||
const root = connectionManagementService.getConnectionGroups().filter(g => g.id === Utils.defaultGroupId)[0];
|
||||
connectionProfile.parent = root;
|
||||
connectionProfile.groupFullName = root.fullName;
|
||||
connectionManagementService.connect(connectionProfile, undefined, {
|
||||
saveTheConnection: true,
|
||||
showDashboard: true,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: true
|
||||
showFirewallRuleOnError: true,
|
||||
params: {
|
||||
connectionType: ConnectionType.default,
|
||||
}
|
||||
});
|
||||
} else {
|
||||
connectionManagementService.showConnectionDialog(undefined, {
|
||||
saveTheConnection: true,
|
||||
showDashboard: true,
|
||||
showConnectionDialogOnError: true,
|
||||
showFirewallRuleOnError: true
|
||||
showFirewallRuleOnError: true,
|
||||
params: {
|
||||
connectionType: ConnectionType.default,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -68,30 +68,20 @@ export class ConnectionStatusbarItem extends Disposable implements IWorkbenchCon
|
||||
|
||||
// Set connection info to connection status bar
|
||||
private _setConnectionText(connectionProfile: IConnectionProfile): void {
|
||||
let distinguishedTitle = this.connectionManagementService.getEditorConnectionProfileTitle(connectionProfile);
|
||||
let text: string = '';
|
||||
let tooltip: string = '';
|
||||
if (distinguishedTitle === '') {
|
||||
text = connectionProfile.serverName;
|
||||
if (text) {
|
||||
if (connectionProfile.databaseName && connectionProfile.databaseName !== '') {
|
||||
text = text + ' : ' + connectionProfile.databaseName;
|
||||
} else {
|
||||
text = text + ' : ' + '<default>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tooltip = 'Server: ' + connectionProfile.serverName + '\r\n' +
|
||||
'Database: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '<default>') + '\r\n';
|
||||
|
||||
if (connectionProfile.userName && connectionProfile.userName !== '') {
|
||||
tooltip = tooltip + 'Login: ' + connectionProfile.userName + '\r\n';
|
||||
let text: string = connectionProfile.serverName;
|
||||
if (text) {
|
||||
if (connectionProfile.databaseName && connectionProfile.databaseName !== '') {
|
||||
text = text + ' : ' + connectionProfile.databaseName;
|
||||
} else {
|
||||
text = text + ' : ' + '<default>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
text = distinguishedTitle;
|
||||
tooltip = (connectionProfile as any).serverInfo;
|
||||
|
||||
let tooltip = 'Server: ' + connectionProfile.serverName + '\r\n' +
|
||||
'Database: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '<default>') + '\r\n';
|
||||
|
||||
if (connectionProfile.userName && connectionProfile.userName !== '') {
|
||||
tooltip = tooltip + 'Login: ' + connectionProfile.userName + '\r\n';
|
||||
}
|
||||
|
||||
this.statusItem.update({
|
||||
|
||||
@@ -57,9 +57,7 @@ export class BreadcrumbService implements IBreadcrumbService {
|
||||
}
|
||||
|
||||
private getServerBreadcrumb(profile: ConnectionProfile): MenuItem {
|
||||
let formattedProfileName = profile.connectionName ? profile.connectionName : profile.serverName;
|
||||
formattedProfileName += this.commonService.connectionManagementService.getEditorConnectionProfileTitle(profile, true, true);
|
||||
return { label: formattedProfileName, routerLink: ['server-dashboard'] };
|
||||
return profile.connectionName ? { label: profile.connectionName, routerLink: ['server-dashboard'] } : { label: profile.serverName, routerLink: ['server-dashboard'] };
|
||||
}
|
||||
|
||||
private getDbBreadcrumb(profile: ConnectionProfile): MenuItem {
|
||||
|
||||
@@ -358,7 +358,7 @@ export class ToggleAddCellActionViewItem extends DropdownMenuActionViewItem {
|
||||
{
|
||||
actionRunner,
|
||||
classNames: ToggleAddCellDropdownAction.ICON,
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
anchorAlignmentProvider: () => AnchorAlignment.LEFT
|
||||
});
|
||||
this.setActionContext(cellContext);
|
||||
}
|
||||
@@ -392,7 +392,7 @@ export class CellToggleMoreActionViewItem extends DropdownMenuActionViewItem {
|
||||
{
|
||||
actionRunner,
|
||||
classNames: CellToggleMoreAction.ICON,
|
||||
anchorAlignmentProvider: () => AnchorAlignment.RIGHT
|
||||
anchorAlignmentProvider: () => AnchorAlignment.LEFT
|
||||
});
|
||||
this.setActionContext(this._cellContext);
|
||||
this._actions = [
|
||||
|
||||
@@ -59,6 +59,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { ToggleAddCellDropdownAction } from 'sql/workbench/contrib/notebook/browser/cellToolbarActions';
|
||||
import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
|
||||
export const NOTEBOOK_SELECTOR: string = 'notebook-component';
|
||||
const PRIORITY = 105;
|
||||
@@ -551,7 +552,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
||||
undefined,
|
||||
'codicon masked-pseudo masked-pseudo-after add-new dropdown-arrow',
|
||||
localize('addCell', "Cell"),
|
||||
undefined
|
||||
() => AnchorAlignment.LEFT
|
||||
);
|
||||
dropdownMenuActionViewItem.render(buttonDropdownContainer);
|
||||
dropdownMenuActionViewItem.setActionContext(this._notebookParams.notebookUri);
|
||||
@@ -572,7 +573,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
|
||||
undefined,
|
||||
'codicon notebook-button masked-pseudo masked-pseudo-after icon-dashboard-view dropdown-arrow',
|
||||
localize('editor', "Editor"),
|
||||
undefined
|
||||
() => AnchorAlignment.LEFT
|
||||
);
|
||||
viewsDropdownMenuActionViewItem.render(viewsDropdownContainer);
|
||||
viewsDropdownMenuActionViewItem.setActionContext(this._notebookParams.notebookUri);
|
||||
|
||||
@@ -756,10 +756,7 @@ export class AttachToDropdown extends SelectBox {
|
||||
} else {
|
||||
let connections: string[] = [];
|
||||
if (model.context && model.context.title && (connProviderIds.includes(this.model.context.providerName))) {
|
||||
let textResult = model.context.title;
|
||||
let fullTitleText = this._connectionManagementService.getEditorConnectionProfileTitle(model.context);
|
||||
textResult = fullTitleText.length !== 0 ? fullTitleText : textResult;
|
||||
connections.push(textResult);
|
||||
connections.push(model.context.title);
|
||||
} else if (this._configurationService.getValue(saveConnectionNameConfigName) && model.savedConnectionName) {
|
||||
connections.push(model.savedConnectionName);
|
||||
} else {
|
||||
|
||||
@@ -37,7 +37,8 @@ import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { NotebookSearchWidget } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookSearchWidget';
|
||||
import { ITreeElement, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
|
||||
import { ITreeContextMenuEvent, ObjectTreeElementCollapseState } from 'vs/base/browser/ui/tree/tree';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
import { searchClearIcon, searchCollapseAllIcon, searchExpandAllIcon, searchStopIcon } from 'vs/workbench/contrib/search/browser/searchIcons';
|
||||
import { Action, IAction } from 'vs/base/common/actions';
|
||||
@@ -430,45 +431,49 @@ export class NotebookSearchView extends SearchView {
|
||||
return false;
|
||||
}
|
||||
|
||||
private createSearchResultIterator(collapseResults: ISearchConfigurationProperties['collapseResults']): Iterable<ITreeElement<RenderableMatch>> {
|
||||
private createSearchResultIterator(collapseResults: ISearchConfigurationProperties['collapseResults']): Iterable<ICompressedTreeElement<RenderableMatch>> {
|
||||
const folderMatches = this.searchResult.folderMatches()
|
||||
.filter(fm => !fm.isEmpty())
|
||||
.sort(searchMatchComparer);
|
||||
|
||||
if (folderMatches.length === 1) {
|
||||
return this.createSearchFolderIterator(folderMatches[0], collapseResults);
|
||||
return this.createSearchFolderIterator(folderMatches[0], collapseResults, true);
|
||||
}
|
||||
|
||||
return Iterable.map(folderMatches, folderMatch => {
|
||||
const children = this.createSearchFolderIterator(folderMatch, collapseResults);
|
||||
return <ITreeElement<RenderableMatch>>{ element: folderMatch, children };
|
||||
const children = this.createSearchFolderIterator(folderMatch, collapseResults, true);
|
||||
return <ICompressedTreeElement<RenderableMatch>>{ element: folderMatch, children };
|
||||
});
|
||||
}
|
||||
|
||||
private createSearchFolderIterator(folderMatch: FolderMatch, collapseResults: ISearchConfigurationProperties['collapseResults']): Iterable<ITreeElement<RenderableMatch>> {
|
||||
private createSearchFolderIterator(folderMatch: FolderMatch, collapseResults: ISearchConfigurationProperties['collapseResults'], childFolderIncompressible: boolean): Iterable<ICompressedTreeElement<RenderableMatch>> {
|
||||
const sortOrder = this.searchConfig.sortOrder;
|
||||
const matches = folderMatch.matches().sort((a, b) => searchMatchComparer(a, b, sortOrder));
|
||||
|
||||
return Iterable.map(matches, fileMatch => {
|
||||
//const children = this.createFileIterator(fileMatch);
|
||||
let nodeExists = true;
|
||||
try { this.tree.getNode(fileMatch); } catch (e) { nodeExists = false; }
|
||||
const matchArray = this.isTreeLayoutViewVisible ? folderMatch.matches() : folderMatch.allDownstreamFileMatches();
|
||||
const matches = matchArray.sort((a, b) => searchMatchComparer(a, b, sortOrder));
|
||||
|
||||
const collapsed = nodeExists ? undefined :
|
||||
(collapseResults === 'alwaysCollapse' || (fileMatch.matches().length > 10 && collapseResults !== 'alwaysExpand'));
|
||||
return Iterable.map(matches, match => {
|
||||
let children;
|
||||
if (match instanceof FileMatch) {
|
||||
children = this.createSearchFileIterator(match);
|
||||
} else {
|
||||
children = this.createSearchFolderIterator(match, collapseResults, false);
|
||||
}
|
||||
|
||||
return <ITreeElement<RenderableMatch>>{ element: fileMatch, undefined, collapsed, collapsible: false };
|
||||
const collapsed = (collapseResults === 'alwaysCollapse' || (match.count() > 10 && collapseResults !== 'alwaysExpand')) ? ObjectTreeElementCollapseState.PreserveOrCollapsed : ObjectTreeElementCollapseState.PreserveOrExpanded;
|
||||
|
||||
return <ICompressedTreeElement<RenderableMatch>>{ element: match, children, collapsed, incompressible: (match instanceof FileMatch) ? true : childFolderIncompressible };
|
||||
});
|
||||
}
|
||||
|
||||
private createSearchFileIterator(fileMatch: FileMatch): Iterable<ITreeElement<RenderableMatch>> {
|
||||
private createSearchFileIterator(fileMatch: FileMatch): Iterable<ICompressedTreeElement<RenderableMatch>> {
|
||||
const matches = fileMatch.matches().sort(searchMatchComparer);
|
||||
return Iterable.map(matches, r => (<ITreeElement<RenderableMatch>>{ element: r }));
|
||||
return Iterable.map(matches, r => (<ICompressedTreeElement<RenderableMatch>>{ element: r }));
|
||||
}
|
||||
|
||||
private createSearchIterator(match: FolderMatch | FileMatch | SearchResult, collapseResults: ISearchConfigurationProperties['collapseResults']): Iterable<ITreeElement<RenderableMatch>> {
|
||||
private createSearchIterator(match: FolderMatch | FileMatch | SearchResult, collapseResults: ISearchConfigurationProperties['collapseResults']): Iterable<ICompressedTreeElement<RenderableMatch>> {
|
||||
return match instanceof SearchResult ? this.createSearchResultIterator(collapseResults) :
|
||||
match instanceof FolderMatch ? this.createSearchFolderIterator(match, collapseResults) :
|
||||
match instanceof FolderMatch ? this.createSearchFolderIterator(match, collapseResults, false) :
|
||||
this.createSearchFileIterator(match);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
// get the full ConnectionProfiles with the server info updated properly
|
||||
const treeInput = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!;
|
||||
await this._tree.setInput(treeInput);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
this._treeSelectionHandler.onTreeActionStateChange(false);
|
||||
} else {
|
||||
if (this._connectionManagementService.hasRegisteredServers()) {
|
||||
@@ -273,7 +272,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
if (connectionParentGroup) {
|
||||
connectionParentGroup.addOrReplaceConnection(newConnection);
|
||||
await this._tree.updateChildren(connectionParentGroup);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(newConnection);
|
||||
await this._tree.expand(newConnection);
|
||||
}
|
||||
@@ -288,7 +286,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
await this._tree.rerender(connectionInTree);
|
||||
await this._tree.revealSelectFocusElement(connectionInTree);
|
||||
await this._tree.updateChildren(connectionInTree);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.expand(connectionInTree);
|
||||
}
|
||||
}
|
||||
@@ -301,7 +298,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
if (parentGroup) {
|
||||
parentGroup.removeConnections([e]);
|
||||
await this._tree.updateChildren(parentGroup);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(parentGroup);
|
||||
}
|
||||
}
|
||||
@@ -319,14 +315,12 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
const newProfileParent = <ConnectionProfileGroup>this._tree.getElementById(e.profile.groupId);
|
||||
newProfileParent.addOrReplaceConnection(e.profile);
|
||||
await this._tree.updateChildren(newProfileParent);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(e.profile);
|
||||
await this._tree.expand(e.profile);
|
||||
} else {
|
||||
// If the profile was not moved to a different group then just update the profile in the group.
|
||||
oldProfileParent.replaceConnection(e.profile, e.oldProfileId);
|
||||
await this._tree.updateChildren(oldProfileParent)
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.updateChildren(oldProfileParent);
|
||||
await this._tree.revealSelectFocusElement(e.profile);
|
||||
await this._tree.expand(e.profile);
|
||||
}
|
||||
@@ -338,8 +332,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
const movedConnection = <ConnectionProfile>e.source;
|
||||
const oldParent = <ConnectionProfileGroup>this._tree.getElementById(e.oldGroupId);
|
||||
const newParent = <ConnectionProfileGroup>this._tree.getElementById(e.newGroupId);
|
||||
// Storing the expanded state of children of the moved connection so that they can be expanded after the move.
|
||||
const profileExpandedState = this._tree.getExpandedState(movedConnection);
|
||||
if (oldParent) {
|
||||
oldParent.removeConnections([movedConnection]);
|
||||
await this._tree.updateChildren(oldParent);
|
||||
@@ -351,12 +343,9 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
await this._tree.updateChildren(newParent);
|
||||
await this._tree.expand(newParent);
|
||||
}
|
||||
await this.refreshConnectionTreeTitles();
|
||||
const newConnection = this._tree.getElementById(movedConnection.id);
|
||||
if (newConnection) {
|
||||
await this._tree.revealSelectFocusElement(newConnection);
|
||||
// Expanding the previously expanded children of the moved connection after the move.
|
||||
await this._tree.expandElements(profileExpandedState);
|
||||
}
|
||||
}
|
||||
}));
|
||||
@@ -366,7 +355,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
const parent = <ConnectionProfileGroup>this._tree.getElementById(e.parentId);
|
||||
parent.children = parent.children.filter(c => c.id !== e.id);
|
||||
await this._tree.updateChildren(parent);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(parent);
|
||||
}
|
||||
}));
|
||||
@@ -389,7 +377,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
e.parent = parent;
|
||||
e.parentId = parent.id;
|
||||
await this._tree.updateChildren(parent);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(e);
|
||||
}
|
||||
}));
|
||||
@@ -400,7 +387,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
if (newParent) {
|
||||
newParent.children[newParent.children.findIndex(c => c.id === e.id)] = e;
|
||||
await this._tree.updateChildren(newParent);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(e);
|
||||
}
|
||||
}
|
||||
@@ -411,18 +397,13 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
const movedGroup = <ConnectionProfileGroup>e.source;
|
||||
const oldParent = <ConnectionProfileGroup>this._tree.getElementById(e.oldGroupId);
|
||||
const newParent = <ConnectionProfileGroup>this._tree.getElementById(e.newGroupId);
|
||||
// Storing the expanded state of children of the moved group so that they can be expanded after the move.
|
||||
const profileExpandedState = this._tree.getExpandedState(movedGroup);
|
||||
oldParent.children = oldParent.children.filter(c => c.id !== movedGroup.id);
|
||||
await this._tree.updateChildren(oldParent);
|
||||
newParent.children.push(movedGroup);
|
||||
(<ConnectionProfileGroup>movedGroup).parent = newParent;
|
||||
(<ConnectionProfileGroup>movedGroup).parentId = newParent.id;
|
||||
await this._tree.updateChildren(newParent);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
await this._tree.revealSelectFocusElement(movedGroup);
|
||||
// Expanding the previously expanded children of the moved group after the move.
|
||||
this._tree.expandElements(profileExpandedState);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -706,7 +687,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
return;
|
||||
}
|
||||
await this._tree.setInput(treeInput!);
|
||||
await this.refreshConnectionTreeTitles();
|
||||
if (isHidden(this.messages!)) {
|
||||
this._tree.getFocus();
|
||||
if (this._tree instanceof AsyncServerTree) {
|
||||
@@ -972,13 +952,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView {
|
||||
return actionContext;
|
||||
}
|
||||
|
||||
private async refreshConnectionTreeTitles(): Promise<void> {
|
||||
let treeInput = this._tree.getInput();
|
||||
let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput], this._connectionManagementService, false);
|
||||
treeInput = treeArray[0];
|
||||
await this._tree!.setInput(treeInput);
|
||||
}
|
||||
|
||||
public collapseAllConnections(): void {
|
||||
const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!;
|
||||
const connections = ConnectionProfileGroup.getConnectionsInGroup(root);
|
||||
|
||||
@@ -19,6 +19,7 @@ import { IConnectionDialogService } from 'sql/workbench/services/connection/comm
|
||||
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
CommandsRegistry.registerCommand({
|
||||
id: 'profiler.newProfiler',
|
||||
@@ -107,9 +108,10 @@ CommandsRegistry.registerCommand({
|
||||
const editorService: IEditorService = accessor.get(IEditorService);
|
||||
const fileDialogService: IFileDialogService = accessor.get(IFileDialogService);
|
||||
const profilerService: IProfilerService = accessor.get(IProfilerService);
|
||||
const instantiationService: IInstantiationService = accessor.get(IInstantiationService)
|
||||
const instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
||||
const fileService: IFileService = accessor.get(IFileService);
|
||||
|
||||
const result = await profilerService.openFile(fileDialogService, editorService, instantiationService);
|
||||
const result = await profilerService.openFile(fileDialogService, editorService, instantiationService, fileService);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -770,7 +770,27 @@ abstract class AbstractTreeView extends Disposable implements ITreeView {
|
||||
}
|
||||
},
|
||||
|
||||
getActionsContext: () => (<TreeViewItemHandleArg>{ $treeViewId: this.id, $treeItemHandle: node.handle, $treeItem: node }),
|
||||
getActionsContext: () => {
|
||||
// This context is used in two ways - one is for the original Data Explorer tree view that extensions can register. Items
|
||||
// for the tree view itself don't have a childProvider so are routed directly to the extension. In this case we want to have
|
||||
// the actions behave like VS Code expects them to behave - so we don't pass in a $treeItem at all so it gets handled by the
|
||||
// VS Code logic here :
|
||||
// https://github.com/microsoft/azuredatastudio/blob/f5bed289affca2fce04fee6dd2db3ce02a8f5c83/src/vs/workbench/api/common/extHostTreeViews.ts#L65
|
||||
|
||||
// The other is for the "childProvider" nodes - which come from a registered provider directly. These currently expect that
|
||||
// the node (with its payload) is passed, which gets handled by processors such as https://github.com/microsoft/azuredatastudio/blob/f5bed289affca2fce04fee6dd2db3ce02a8f5c83/src/sql/workbench/api/common/extHostObjectExplorer.ts#L27
|
||||
|
||||
// This should be a temporary fix until further investigation can be done and a fix to the core data explorer logic can be made
|
||||
// (which will likely involve that logic using the treeItemHandle to look up the treeItem itself like VS Code seems to be doing)
|
||||
|
||||
// Have to remove parent, this was added in a VS Code merge to ITreeItem instances, but isn't meant to be serializable over JSON RPC,
|
||||
// so passing it directly will cause the command to fail as there's a loop (child -> parent -> child -> parent ...)
|
||||
// Note: Do NOT make a new object here - the core tree logic expects the tree items to stay as the same object so returning a
|
||||
// different object here will break functionality such as scripting.
|
||||
delete node.parent;
|
||||
const treeItem = node.childProvider ? node : undefined;
|
||||
return (<TreeViewItemHandleArg>{ $treeViewId: this.id, $treeItemHandle: node.handle, $treeItem: treeItem })
|
||||
},
|
||||
|
||||
actionRunner
|
||||
});
|
||||
|
||||
@@ -61,10 +61,6 @@ export class SingleConnectionManagementService {
|
||||
public get connectionInfo(): ConnectionManagementInfo {
|
||||
return this._connectionService.getConnectionInfo(this._uri);
|
||||
}
|
||||
|
||||
public getEditorConnectionProfileTitle(profile: IConnectionProfile, getOptionsOnly?: boolean, includeGroupName?: boolean): string {
|
||||
return this._connectionService.getEditorConnectionProfileTitle(profile, getOptionsOnly, includeGroupName);
|
||||
}
|
||||
}
|
||||
|
||||
export class SingleAdminService {
|
||||
|
||||
@@ -553,12 +553,7 @@ class SavedConnectionNode {
|
||||
}
|
||||
|
||||
getChildren() {
|
||||
let input = TreeUpdateUtils.getTreeInput(this.connectionManagementService);
|
||||
let newInput = [input];
|
||||
if (input instanceof ConnectionProfileGroup) {
|
||||
newInput = TreeUpdateUtils.alterTreeChildrenTitles([input], this.connectionManagementService);
|
||||
}
|
||||
return this.dataSource.getChildren(newInput[0]);
|
||||
return this.dataSource.getChildren(TreeUpdateUtils.getTreeInput(this.connectionManagementService));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -682,8 +682,8 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
connection.options = connectionErrorHandleResult.options;
|
||||
}
|
||||
if (connectionErrorHandleResult.reconnect) {
|
||||
// Attempt reconnect if requested by provider
|
||||
return this.connectWithOptions(connection, uri, options, callbacks);
|
||||
// Attempt reconnect if requested by provider and reset URI to be regenerated.
|
||||
return this.connectWithOptions(connection, undefined, options, callbacks);
|
||||
} else {
|
||||
if (callbacks.onConnectCanceled) {
|
||||
callbacks.onConnectCanceled();
|
||||
@@ -724,183 +724,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
return result;
|
||||
}
|
||||
|
||||
public getEditorConnectionProfileTitle(profile: interfaces.IConnectionProfile, getOptionsOnly?: boolean, includeGroupName: boolean = true): string {
|
||||
let result = '';
|
||||
if (profile) {
|
||||
let tempProfile = new ConnectionProfile(this._capabilitiesService, profile);
|
||||
let trimTitle = tempProfile.getOriginalTitle();
|
||||
let idToFind = tempProfile.id;
|
||||
let isChild = false;
|
||||
let totalConnections: ConnectionProfile[] = [];
|
||||
let allConnections = this.getConnections();
|
||||
|
||||
totalConnections = totalConnections.concat(allConnections);
|
||||
|
||||
let initialSearch = totalConnections.filter(inputProfile => {
|
||||
return inputProfile.id === tempProfile.id;
|
||||
});
|
||||
|
||||
let secondarySearch = totalConnections.filter(inputProfile => {
|
||||
return inputProfile.matches(tempProfile)
|
||||
});
|
||||
|
||||
if (initialSearch.length === 0) {
|
||||
if (secondarySearch.length === 1) {
|
||||
// Sometimes the connection id will change for an object explorer connection, especially when connecting from dashboard,
|
||||
// and it will identify as different from the stored one even without changes. Get the info for the stored version as it's the same profile.
|
||||
idToFind = secondarySearch[0].id;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle case where a profile may have been an edited existing connection (the one retrieved may not be up to date)
|
||||
if (initialSearch.length === 1 && !initialSearch[0].matches(tempProfile)) {
|
||||
// Remove the old profile with outdated information.
|
||||
totalConnections = totalConnections.filter(inputProfile => {
|
||||
return inputProfile.id !== tempProfile.id;
|
||||
});
|
||||
// Replace with up to date version of the profile.
|
||||
totalConnections = totalConnections.concat(tempProfile);
|
||||
}
|
||||
|
||||
let newConnectionTitles = [];
|
||||
|
||||
this.generateEditorConnectionTitles(totalConnections);
|
||||
if (includeGroupName) {
|
||||
this.appendGroupName(totalConnections);
|
||||
}
|
||||
newConnectionTitles = totalConnections;
|
||||
|
||||
let searchResult = newConnectionTitles.filter(inputProfile => inputProfile.id === idToFind);
|
||||
let finalTitle = searchResult[0]?.title;
|
||||
if (finalTitle) {
|
||||
let optionsAppend = finalTitle.substring(trimTitle.length);
|
||||
if (getOptionsOnly) {
|
||||
finalTitle = optionsAppend;
|
||||
}
|
||||
else if (!getOptionsOnly && isChild) {
|
||||
finalTitle = tempProfile.getOriginalTitle() + optionsAppend;
|
||||
}
|
||||
else {
|
||||
finalTitle = searchResult[0].getOriginalTitle() + optionsAppend;
|
||||
}
|
||||
result = finalTitle;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the connection title to display only the unique properties among profiles provided. (used for editors)
|
||||
*/
|
||||
private generateEditorConnectionTitles(inputList: ConnectionProfile[]): void {
|
||||
let profileListMap = new Map<string, number[]>();
|
||||
// Need to reset title to when it was before (as it may have contained a previously generated title)
|
||||
for (let i = 0; i < inputList.length; i++) {
|
||||
inputList[i].title = inputList[i].getOriginalTitle();
|
||||
}
|
||||
|
||||
// Map the indices of profiles that share the same server info
|
||||
for (let i = 0; i < inputList.length; i++) {
|
||||
// do not add if the profile is still loading as that will result in erroneous entries.
|
||||
if (inputList[i].serverCapabilities && inputList[i].hasLoaded()) {
|
||||
let titleKey = inputList[i].getOriginalTitle();
|
||||
if (profileListMap.has(titleKey)) {
|
||||
let profilesForKey = profileListMap.get(titleKey);
|
||||
profilesForKey.push(i);
|
||||
profileListMap.set(titleKey, profilesForKey);
|
||||
}
|
||||
else {
|
||||
profileListMap.set(titleKey, [i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
profileListMap.forEach(function (indexes, titleString) {
|
||||
if (profileListMap.get(titleString)?.length > 1) {
|
||||
let combinedOptions = [];
|
||||
let needSpecial = false;
|
||||
if (titleString === inputList[indexes[0]].connectionName) {
|
||||
// check for potential connections with the same name but technically different connections.
|
||||
let listOfDuplicates = indexes.filter(item => inputList[item].getOptionsKey() !== inputList[indexes[0]].getOptionsKey());
|
||||
if (listOfDuplicates.length > 0) {
|
||||
// if we do find duplicates, we will need to include the special properties.
|
||||
needSpecial = true;
|
||||
}
|
||||
}
|
||||
indexes.forEach((indexValue) => {
|
||||
// Add all possible options across all profiles with the same title to an option list.
|
||||
let valueOptions = inputList[indexValue].getConnectionOptionsList(needSpecial, false);
|
||||
combinedOptions = combinedOptions.concat(valueOptions.filter(item => combinedOptions.indexOf(item) < 0));
|
||||
});
|
||||
|
||||
// Generate list of non default option keys for each profile that shares the same server info.
|
||||
let optionKeyMap = new Map<ConnectionProfile, string[]>();
|
||||
let optionValueOccuranceMap = new Map<string, number>();
|
||||
for (let p = 0; p < indexes.length; p++) {
|
||||
optionKeyMap.set(inputList[indexes[p]], []);
|
||||
for (let i = 0; i < combinedOptions.length; i++) {
|
||||
// See if the option is not default for the inputList profile or is.
|
||||
if (inputList[indexes[p]].getConnectionOptionsList(needSpecial, true).indexOf(combinedOptions[i]) > -1) {
|
||||
let optionValue = inputList[indexes[p]].getOptionValue(combinedOptions[i].name);
|
||||
let currentArray = optionKeyMap.get(inputList[indexes[p]]);
|
||||
let valueString = combinedOptions[i].name + ConnectionProfile.displayNameValueSeparator + optionValue;
|
||||
if (!optionValueOccuranceMap.get(valueString)) {
|
||||
optionValueOccuranceMap.set(valueString, 0);
|
||||
}
|
||||
optionValueOccuranceMap.set(valueString, optionValueOccuranceMap.get(valueString) + 1);
|
||||
currentArray.push(valueString);
|
||||
optionKeyMap.set(inputList[indexes[p]], currentArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out options that are found in ALL the entries with the same server info.
|
||||
optionValueOccuranceMap.forEach(function (count, optionValue) {
|
||||
optionKeyMap.forEach(function (connOptionValues, profile) {
|
||||
if (count === optionKeyMap.size) {
|
||||
optionKeyMap.set(profile, connOptionValues.filter(value => value !== optionValue));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Generate the final unique connection string for each profile in the list.
|
||||
optionKeyMap.forEach(function (connOptionValues, profile) {
|
||||
let uniqueOptionString = connOptionValues.join(ConnectionProfile.displayIdSeparator);
|
||||
if (uniqueOptionString.length > 0) {
|
||||
profile.title = profile.getOriginalTitle() + ' (' + uniqueOptionString + ')';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private appendGroupName(inputList: ConnectionProfile[]): void {
|
||||
let profileListMap = new Map<string, number[]>();
|
||||
|
||||
// Map the indices of profiles that share the same server group
|
||||
for (let i = 0; i < inputList.length; i++) {
|
||||
let groupName = inputList[i].groupFullName;
|
||||
if (profileListMap.has(groupName)) {
|
||||
let profilesForKey = profileListMap.get(groupName);
|
||||
profilesForKey.push(i);
|
||||
profileListMap.set(groupName, profilesForKey);
|
||||
}
|
||||
else {
|
||||
profileListMap.set(groupName, [i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (profileListMap.size > 1) {
|
||||
profileListMap.forEach(function (indexes, groupName) {
|
||||
for (let t = 0; t < indexes.length; t++) {
|
||||
if (groupName !== '') {
|
||||
inputList[indexes[t]].title += nls.localize('connection.connTitleGroupSection', ' (Group: {0})', groupName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private doActionsAfterConnectionComplete(uri: string, options: IConnectionCompletionOptions): void {
|
||||
let connectionManagementInfo = this._connectionStatusManager.findConnection(uri);
|
||||
if (!connectionManagementInfo) {
|
||||
@@ -1368,16 +1191,22 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
});
|
||||
|
||||
await this._extensionService.activateByEvent(`onConnect:${connection.providerName}`);
|
||||
|
||||
if (this._providers.get(connection.providerName) === undefined) {
|
||||
await this.handleUnsupportedProvider(connection.providerName);
|
||||
throw new Error(nls.localize('connection.providerNotFound', "Connection provider '{0}' not found", connection.providerName));
|
||||
}
|
||||
return this._providers.get(connection.providerName).onReady.then((provider) => {
|
||||
provider.connect(uri, connectionInfo);
|
||||
this._onConnectRequestSent.fire();
|
||||
// Connections are made per URI so while there may possibly be multiple editors with
|
||||
// that URI they all share the same state
|
||||
const editor = this._editorService.findEditors(URI.parse(uri))[0]?.editor;
|
||||
// TODO make this generic enough to handle non-SQL languages too
|
||||
const language = editor instanceof QueryEditorInput && editor.state.isSqlCmdMode ? 'sqlcmd' : 'sql';
|
||||
this.doChangeLanguageFlavor(uri, language, connection.providerName);
|
||||
const editors = this._editorService.findEditors(URI.parse(uri));
|
||||
if (editors && editors[0]?.editor) {
|
||||
const editor = editors[0].editor;
|
||||
// TODO make this generic enough to handle non-SQL languages too
|
||||
const language = editor instanceof QueryEditorInput && editor.state.isSqlCmdMode ? 'sqlcmd' : 'sql';
|
||||
this.doChangeLanguageFlavor(uri, language, connection.providerName);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -1602,13 +1431,11 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
return;
|
||||
}
|
||||
this._connectionStatusManager.changeConnectionUri(newUri, oldUri);
|
||||
if (!this._uriToProvider[oldUri]) {
|
||||
this._logService.error(`No provider found for old URI : '${oldUri}'`);
|
||||
throw new Error(nls.localize('connectionManagementService.noProviderForUri', 'Could not find provider for uri: {0}', oldUri));
|
||||
if (this._uriToProvider[oldUri]) {
|
||||
// Provider will persist after disconnect, it is okay to overwrite the map if it exists from a previously deleted connection.
|
||||
this._uriToProvider[newUri] = this._uriToProvider[oldUri];
|
||||
delete this._uriToProvider[oldUri];
|
||||
}
|
||||
// Provider will persist after disconnect, it is okay to overwrite the map if it exists from a previously deleted connection.
|
||||
this._uriToProvider[newUri] = this._uriToProvider[oldUri];
|
||||
delete this._uriToProvider[oldUri];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1644,7 +1471,11 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
||||
});
|
||||
|
||||
// send connection request
|
||||
self.sendConnectRequest(connection, uri).catch((e) => this._logService.error(e));
|
||||
self.sendConnectRequest(connection, uri).catch((e) => {
|
||||
this._logService.error(e);
|
||||
this._connectionStatusManager.removeConnection(uri);
|
||||
reject(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import * as Constants from 'sql/platform/connection/common/constants';
|
||||
import * as Utils from 'sql/platform/connection/common/utils';
|
||||
import { IHandleFirewallRuleResult } from 'sql/workbench/services/resourceProvider/common/resourceProviderService';
|
||||
|
||||
import { IConnectionProfile, ServiceOptionType } from 'sql/platform/connection/common/interfaces';
|
||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
||||
import { TestConnectionProvider } from 'sql/platform/connection/test/common/testConnectionProvider';
|
||||
import { TestResourceProvider } from 'sql/workbench/services/resourceProvider/test/common/testResourceProviderService';
|
||||
@@ -2046,184 +2046,6 @@ suite('SQL ConnectionManagementService tests', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// TODO - need to rework test to match new format.
|
||||
test.skip('getEditorConnectionProfileTitle should return a correctly formatted title for a connection profile', () => {
|
||||
let profile: IConnectionProfile = {
|
||||
connectionName: 'new name',
|
||||
serverName: 'new server',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: Constants.AuthenticationType.Integrated,
|
||||
savePassword: true,
|
||||
groupFullName: 'g2/g2-2',
|
||||
groupId: 'group id',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: () => { return ''; },
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined
|
||||
};
|
||||
|
||||
let capabilitiesService = new TestCapabilitiesService();
|
||||
const testOption1 = {
|
||||
name: 'testOption1',
|
||||
displayName: 'testOption1',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: ServiceOptionType.string,
|
||||
specialValueType: undefined,
|
||||
defaultValue: '',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
const testOption2 = {
|
||||
name: 'testOption2',
|
||||
displayName: 'testOption2',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: ServiceOptionType.number,
|
||||
specialValueType: undefined,
|
||||
defaultValue: '10',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
const testOption3 = {
|
||||
name: 'testOption3',
|
||||
displayName: 'testOption3',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: ServiceOptionType.string,
|
||||
specialValueType: undefined,
|
||||
defaultValue: 'default',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
profile.options['testOption1'] = 'test value';
|
||||
profile.options['testOption2'] = '50';
|
||||
profile.options['testOption3'] = 'default';
|
||||
|
||||
let mainProvider = capabilitiesService.capabilities['MSSQL'];
|
||||
let mainProperties = mainProvider.connection;
|
||||
let mainOptions = mainProperties.connectionOptions;
|
||||
|
||||
mainOptions.push(testOption1);
|
||||
mainOptions.push(testOption2);
|
||||
mainOptions.push(testOption3);
|
||||
|
||||
mainProperties.connectionOptions = mainOptions;
|
||||
mainProvider.connection = mainProperties;
|
||||
|
||||
capabilitiesService.capabilities['MSSQL'] = mainProvider;
|
||||
|
||||
const connectionStoreMock = TypeMoq.Mock.ofType(ConnectionStore, TypeMoq.MockBehavior.Loose, new TestStorageService());
|
||||
const connectionStatusManagerMock = TypeMoq.Mock.ofType(ConnectionStatusManager, TypeMoq.MockBehavior.Loose);
|
||||
connectionStatusManagerMock.setup(x => x.getActiveConnectionProfiles(undefined)).returns(() => {
|
||||
return [];
|
||||
});
|
||||
const testInstantiationService = new TestInstantiationService();
|
||||
testInstantiationService.stub(IStorageService, new TestStorageService());
|
||||
sinon.stub(testInstantiationService, 'createInstance').withArgs(ConnectionStore).returns(connectionStoreMock.object).withArgs(ConnectionStatusManager).returns(connectionStatusManagerMock.object);
|
||||
const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, capabilitiesService, undefined, undefined, undefined, new TestErrorDiagnosticsService(), undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined);
|
||||
|
||||
// We should expect that options by themselves are empty if no other profiles exist.
|
||||
let result = connectionManagementService.getEditorConnectionProfileTitle(profile, true);
|
||||
assert.strictEqual(result, '', `Options appeared when they should not have.`);
|
||||
|
||||
// We should expect that the string contains only the server info (basic) if there is no other connection with the same server info.
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(profile);
|
||||
|
||||
let generatedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile);
|
||||
let expectedNonDefaultOption = ' (testOption1=test value; testOption2=50)';
|
||||
let profileServerInfo = generatedProfile.serverInfo.substring(0, generatedProfile.serverInfo.indexOf(expectedNonDefaultOption));
|
||||
|
||||
assert.strictEqual(result, `${profileServerInfo}`, `getEditorConnectionProfileTitle included a connection name when it shouldn't`);
|
||||
|
||||
connectionStoreMock.setup(x => x.getAllConnectionsFromConfig()).returns(() => {
|
||||
return [generatedProfile];
|
||||
});
|
||||
|
||||
// We should expect that the string only contains the server info (basic) if there is only default options, and another connection with similar title but non default options.
|
||||
profile.options['testOption1'] = undefined;
|
||||
profile.options['testOption2'] = undefined;
|
||||
profile.options['testOption3'] = undefined;
|
||||
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(profile);
|
||||
|
||||
assert.strictEqual(result, `${profileServerInfo}`, `getEditorConnectionProfileTitle included differing connection options when it shouldn't`);
|
||||
|
||||
//Reset profiles for next test and add secondary profile .
|
||||
profile.options['testOption1'] = 'test value';
|
||||
profile.options['testOption2'] = '50';
|
||||
profile.options['testOption3'] = 'default';
|
||||
generatedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile);
|
||||
profile.options['testOption1'] = undefined;
|
||||
profile.options['testOption2'] = undefined;
|
||||
profile.options['testOption3'] = undefined;
|
||||
let emptyGeneratedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile);
|
||||
|
||||
connectionStoreMock.setup(x => x.getAllConnectionsFromConfig()).returns(() => {
|
||||
return [generatedProfile, emptyGeneratedProfile];
|
||||
});
|
||||
|
||||
// We should expect that the string contains the server info appended with differing options, if there's another connection with similar title that has only default options.
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(generatedProfile);
|
||||
|
||||
assert.equal(result, `${generatedProfile.serverInfo}`, `getEditorConnectionProfileTitle did not include differing connection options when it should`);
|
||||
|
||||
connectionStoreMock.setup(x => x.getAllConnectionsFromConfig()).returns(() => {
|
||||
return [generatedProfile, emptyGeneratedProfile];
|
||||
});
|
||||
|
||||
// We should expect that the string contains only the differing options when we ask for options only
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(generatedProfile, true);
|
||||
|
||||
assert.equal(result, expectedNonDefaultOption, `getEditorConnectionProfileTitle did not return differing options only`);
|
||||
|
||||
//Reset profiles for next test and add secondary profile .
|
||||
profile.options['testOption1'] = 'test value';
|
||||
profile.options['testOption2'] = '50';
|
||||
profile.options['testOption3'] = 'default';
|
||||
profile.connectionName = 'New Connection Name';
|
||||
profile.options['connectionName'] = profile.connectionName;
|
||||
generatedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile);
|
||||
profile.options['testOption1'] = undefined;
|
||||
profile.options['testOption2'] = undefined;
|
||||
profile.options['testOption3'] = undefined;
|
||||
profile.connectionName = 'new name';
|
||||
profile.options['connectionName'] = profile.connectionName;
|
||||
emptyGeneratedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile);
|
||||
expectedNonDefaultOption = ' (connectionName=New Connection Name; testOption1=test value; testOption2=50)';
|
||||
|
||||
connectionStoreMock.setup(x => x.getAllConnectionsFromConfig()).returns(() => {
|
||||
return [generatedProfile, emptyGeneratedProfile];
|
||||
});
|
||||
|
||||
// We should expect that the string now contains connectionName, when it is different.
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(generatedProfile, false);
|
||||
|
||||
assert.equal(result, `${profileServerInfo}${expectedNonDefaultOption}`, `getEditorConnectionProfileTitle did not include connectionName in options when it should`);
|
||||
|
||||
connectionStoreMock.setup(x => x.getAllConnectionsFromConfig()).returns(() => {
|
||||
return [generatedProfile, emptyGeneratedProfile];
|
||||
});
|
||||
|
||||
// We should expect that the string contains only the differing options (including Connection Name) against server info when we ask for options only.
|
||||
result = connectionManagementService.getEditorConnectionProfileTitle(generatedProfile, true);
|
||||
|
||||
assert.equal(result, expectedNonDefaultOption, `getEditorConnectionProfileTitle did not include only options with connectionName`);
|
||||
|
||||
});
|
||||
|
||||
export function createConnectionProfile(id: string, password?: string): ConnectionProfile {
|
||||
const capabilitiesService = new TestCapabilitiesService();
|
||||
return new ConnectionProfile(capabilitiesService, {
|
||||
|
||||
@@ -138,7 +138,8 @@ export class DialogModal extends Modal {
|
||||
if (this._doneButton.enabled) {
|
||||
let buttonSpinnerHandler = setTimeout(() => {
|
||||
this._doneButton.enabled = false;
|
||||
this._doneButton.element.innerHTML = ' ';
|
||||
// Temporarily set the label to empty since we're showing a spinner instead
|
||||
this._doneButton.label = ''
|
||||
this._doneButton.element.classList.add('validating');
|
||||
}, 100);
|
||||
if (await this._dialog.validateClose()) {
|
||||
|
||||
@@ -319,7 +319,8 @@ export class WizardModal extends Modal {
|
||||
let button = newPage === undefined ? this._doneButton : this._nextButton;
|
||||
let buttonSpinnerHandler = setTimeout(() => {
|
||||
button.enabled = false;
|
||||
button.element.innerHTML = ' ';
|
||||
// Temporarily set the label to empty since we're showing a spinner instead
|
||||
button.label = '';
|
||||
button.element.classList.add('validating');
|
||||
}, 100);
|
||||
let navigationValid = await this._wizard.validateNavigation(newPage);
|
||||
|
||||
@@ -114,8 +114,8 @@ export class FileBrowserDialog extends Modal {
|
||||
fileValidationServiceType: string,
|
||||
): void {
|
||||
this._viewModel.initialize(ownerUri, expandPath, fileFilters, fileValidationServiceType);
|
||||
this._fileFilterSelectBox.setOptions(this._viewModel.formattedFileFilters);
|
||||
this._fileFilterSelectBox.select(0);
|
||||
this._viewModel.openFileBrowser(0, false).catch(err => onUnexpectedError(err));
|
||||
this._fileFilterSelectBox.setOptions(this._viewModel.formattedFileFilters, 0);
|
||||
this._filePathInputBox.value = expandPath;
|
||||
this._isFolderSelected = true;
|
||||
this.enableOkButton();
|
||||
@@ -125,7 +125,6 @@ export class FileBrowserDialog extends Modal {
|
||||
this._fileBrowserTreeView = this._instantiationService.createInstance(FileBrowserTreeView);
|
||||
this._fileBrowserTreeView.setOnClickedCallback((arg) => this.onClicked(arg));
|
||||
this._fileBrowserTreeView.setOnDoubleClickedCallback((arg) => this.onDoubleClicked(arg));
|
||||
this._viewModel.openFileBrowser(0, false).catch(err => onUnexpectedError(err));
|
||||
}
|
||||
|
||||
/* enter key */
|
||||
|
||||
@@ -120,19 +120,10 @@ export class AsyncServerTree extends WorkbenchAsyncDataTree<ConnectionProfileGro
|
||||
return node;
|
||||
}
|
||||
|
||||
public override async updateChildren(element?: ServerTreeElement, recursive?: boolean, rerender?: boolean, options?: IAsyncDataTreeUpdateChildrenOptions<ServerTreeElement>): Promise<void> {
|
||||
const expandedChildren = this.getExpandedState(element);
|
||||
public override async updateChildren(element?: ServerTreeElement, recursive: boolean = false, rerender: boolean = false, options: IAsyncDataTreeUpdateChildrenOptions<ServerTreeElement> = {
|
||||
diffDepth: 0
|
||||
}): Promise<void> {
|
||||
await super.updateChildren(element, recursive, rerender, options);
|
||||
await this.expandElements(expandedChildren);
|
||||
}
|
||||
|
||||
public async expandElements(elements: ServerTreeElement[]): Promise<void> {
|
||||
for (let element of elements) {
|
||||
const node = this.getDataNode(element, false);
|
||||
if (node) {
|
||||
await this.expand(node.element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -149,7 +149,7 @@ class ConnectionProfileTemplate extends Disposable {
|
||||
this._label.element.setLabel(labelText, '', {
|
||||
matches: createMatches(filterData)
|
||||
});
|
||||
this._root.title = labelText;
|
||||
this._root.title = treeNode?.filters?.length > 0 ? getLabelWithFilteredSuffix(element.serverInfo) : element.serverInfo;
|
||||
const actionProvider = this._objectExplorerService.getServerTreeView().treeActionProvider;
|
||||
if (!this._isCompact) {
|
||||
const tree = this._objectExplorerService.getServerTreeView().tree;
|
||||
|
||||
@@ -235,7 +235,7 @@ export class ServerTreeRenderer implements IRenderer {
|
||||
const treeNode = this._objectExplorerService.getObjectExplorerNode(connection);
|
||||
let label = treeNode?.filters?.length > 0 ? getLabelWithFilteredSuffix(connection.title) : connection.title;
|
||||
templateData.label.textContent = label;
|
||||
templateData.root.title = treeNode?.filters?.length > 0 ? getLabelWithFilteredSuffix(connection.title) : connection.serverInfo;
|
||||
templateData.root.title = treeNode?.filters?.length > 0 ? getLabelWithFilteredSuffix(connection.serverInfo) : connection.serverInfo;
|
||||
templateData.connectionProfile = connection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,10 @@ export class TreeSelectionHandler {
|
||||
}
|
||||
const selectedNode = selection[0];
|
||||
if (selectedNode instanceof ConnectionProfile && !capabilitiesService.getCapabilities(selectedNode.providerName)) {
|
||||
connectionManagementService.handleUnsupportedProvider(selectedNode.providerName).catch(onUnexpectedError);
|
||||
// Async tree handles unsupported providers through the connection management service
|
||||
if (!(tree instanceof AsyncServerTree)) {
|
||||
connectionManagementService.handleUnsupportedProvider(selectedNode.providerName).catch(onUnexpectedError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,21 +47,6 @@ export class TreeUpdateUtils {
|
||||
|
||||
public static isInDragAndDrop: boolean = false;
|
||||
|
||||
/**
|
||||
* Functions to restore/remove the groupId for title generation as they are removed when added to treeInput
|
||||
*/
|
||||
private static restoreGroupId(treeInput: ConnectionProfileGroup, originalProfiles: ConnectionProfile[]) {
|
||||
for (let i = 0; i < treeInput.connections.length; i++) {
|
||||
treeInput.connections[i].groupId = originalProfiles[i].groupId
|
||||
}
|
||||
}
|
||||
|
||||
private static removeGroupId(treeInput: ConnectionProfileGroup) {
|
||||
for (let i = 0; i < treeInput.connections.length; i++) {
|
||||
treeInput.connections[i].groupId = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input for the tree.
|
||||
*/
|
||||
@@ -83,21 +68,11 @@ export class TreeUpdateUtils {
|
||||
if (viewKey === 'recent') {
|
||||
groups = connectionManagementService.getRecentConnections(providers);
|
||||
treeInput.addConnections(groups);
|
||||
this.restoreGroupId(treeInput, connectionManagementService.getRecentConnections(providers));
|
||||
let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput], connectionManagementService);
|
||||
this.removeGroupId(treeInput);
|
||||
treeInput = treeArray[0];
|
||||
} else if (viewKey === 'active') {
|
||||
groups = connectionManagementService.getActiveConnections(providers);
|
||||
treeInput.addConnections(groups);
|
||||
this.restoreGroupId(treeInput, connectionManagementService.getActiveConnections(providers));
|
||||
let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput], connectionManagementService);
|
||||
this.removeGroupId(treeInput);
|
||||
treeInput = treeArray[0];
|
||||
} else if (viewKey === 'saved') {
|
||||
treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService, providers);
|
||||
let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput], connectionManagementService);
|
||||
treeInput = treeArray[0];
|
||||
}
|
||||
const previousTreeInput = tree.getInput();
|
||||
if (treeInput) {
|
||||
@@ -118,29 +93,13 @@ export class TreeUpdateUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls alterConnectionTitles on all levels of the Object Explorer Tree
|
||||
* so that profiles in connection groups can have distinguishing titles too.
|
||||
*/
|
||||
public static alterTreeChildrenTitles(inputGroups: ConnectionProfileGroup[], connectionManagementService: IConnectionManagementService, includeGroupName?: boolean): ConnectionProfileGroup[] {
|
||||
inputGroups.forEach(group => {
|
||||
group.children = TreeUpdateUtils.alterTreeChildrenTitles(group.children, connectionManagementService, includeGroupName);
|
||||
let connections = group.connections;
|
||||
TreeUpdateUtils.alterConnectionTitles(connections, connectionManagementService, includeGroupName);
|
||||
group.connections = connections;
|
||||
});
|
||||
return inputGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set input for the registered servers tree.
|
||||
*/
|
||||
public static async registeredServerUpdate(tree: ITree | AsyncServerTree, connectionManagementService: IConnectionManagementService, elementToSelect?: any): Promise<void> {
|
||||
if (tree instanceof AsyncServerTree) {
|
||||
let treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService);
|
||||
const treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService);
|
||||
if (treeInput) {
|
||||
let treeArray = this.alterTreeChildrenTitles([treeInput], connectionManagementService, false);
|
||||
treeInput = treeArray[0];
|
||||
await tree.setInput(treeInput);
|
||||
}
|
||||
tree.rerender();
|
||||
@@ -169,8 +128,6 @@ export class TreeUpdateUtils {
|
||||
|
||||
let treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService);
|
||||
if (treeInput) {
|
||||
let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput], connectionManagementService, false);
|
||||
treeInput = treeArray[0];
|
||||
const originalInput = tree.getInput();
|
||||
if (treeInput !== originalInput) {
|
||||
return tree.setInput(treeInput).then(async () => {
|
||||
@@ -413,14 +370,4 @@ export class TreeUpdateUtils {
|
||||
}
|
||||
return connectionProfile;
|
||||
}
|
||||
|
||||
private static alterConnectionTitles(inputList: ConnectionProfile[], connectionManagementService: IConnectionManagementService, includeGroupName?: boolean): void {
|
||||
for (let i = 0; i < inputList.length; i++) {
|
||||
let currentConnection = inputList[i];
|
||||
let listOfDuplicates = inputList.filter(connection => connection.getOriginalTitle() === currentConnection.getOriginalTitle());
|
||||
if (listOfDuplicates.length > 1) {
|
||||
inputList[i].title = connectionManagementService.getEditorConnectionProfileTitle(inputList[i], false, includeGroupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,645 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
|
||||
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
|
||||
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
||||
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
||||
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
|
||||
import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils';
|
||||
import * as assert from 'assert';
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
// TODO - Need to fix these tests to match the refactoring of the Connection Title Generation.
|
||||
suite.skip('treeUpdateUtils alterConnection', () => {
|
||||
|
||||
let capabilitiesService: TestCapabilitiesService;
|
||||
|
||||
const testOption1 = {
|
||||
name: 'testOption1',
|
||||
displayName: 'testOption1',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: 'string',
|
||||
specialValueType: undefined,
|
||||
defaultValue: '',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
const testOption2 = {
|
||||
name: 'testOption2',
|
||||
displayName: 'testOption2',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: 'number',
|
||||
specialValueType: undefined,
|
||||
defaultValue: '10',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
const testOption3 = {
|
||||
name: 'testOption3',
|
||||
displayName: 'testOption3',
|
||||
description: 'test description',
|
||||
groupName: 'test group name',
|
||||
valueType: 'string',
|
||||
specialValueType: undefined,
|
||||
defaultValue: 'default',
|
||||
categoryValues: undefined,
|
||||
isIdentity: false,
|
||||
isRequired: false
|
||||
};
|
||||
|
||||
setup(() => {
|
||||
capabilitiesService = new TestCapabilitiesService();
|
||||
let mainProvider = capabilitiesService.capabilities[mssqlProviderName];
|
||||
let mainProperties = mainProvider.connection;
|
||||
let mainOptions = mainProperties.connectionOptions;
|
||||
|
||||
mainOptions.push((testOption1 as azdata.ConnectionOption));
|
||||
mainOptions.push((testOption2 as azdata.ConnectionOption));
|
||||
mainOptions.push((testOption3 as azdata.ConnectionOption));
|
||||
|
||||
mainProperties.connectionOptions = mainOptions;
|
||||
mainProvider.connection = mainProperties;
|
||||
|
||||
capabilitiesService.capabilities['MSSQL'] = mainProvider;
|
||||
});
|
||||
|
||||
test('Default properties should not be added to the altered title', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption3: 'default', testOption2: '10' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
connectionProfileGroup.addConnections([connectionProfile1, connectionProfile2]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
|
||||
assert.equal(connectionProfile1.title, updatedTitleMap[0]);
|
||||
assert.equal(connectionProfile1.title + ' (testOption3=nonDefault)', updatedTitleMap[1]);
|
||||
});
|
||||
|
||||
test('Similar connections should have different titles based on all differing properties', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption2: '15', testOption1: 'test string 1', testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption2: '50', testOption1: 'test string 1', testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile3: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption2: '15', testOption1: 'test string 2', testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile4: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption2: '50', testOption1: 'test string 2', testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let defaultProfile: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption3: 'nonDefault' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let defaultConnectionProfile = new ConnectionProfile(capabilitiesService, defaultProfile);
|
||||
let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2);
|
||||
let connectionProfile3 = new ConnectionProfile(capabilitiesService, profile3);
|
||||
let connectionProfile4 = new ConnectionProfile(capabilitiesService, profile4);
|
||||
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
let originalTitle = defaultConnectionProfile.title;
|
||||
connectionProfileGroup.addConnections([defaultConnectionProfile, connectionProfile1, connectionProfile2, connectionProfile3, connectionProfile4]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
|
||||
assert.equal(originalTitle, updatedTitleMap[0]);
|
||||
assert.equal(originalTitle + ' (testOption1=test string 1; testOption2=15)', updatedTitleMap[1]);
|
||||
assert.equal(originalTitle + ' (testOption1=test string 1; testOption2=50)', updatedTitleMap[2]);
|
||||
assert.equal(originalTitle + ' (testOption1=test string 2; testOption2=15)', updatedTitleMap[3]);
|
||||
assert.equal(originalTitle + ' (testOption1=test string 2; testOption2=50)', updatedTitleMap[4]);
|
||||
});
|
||||
|
||||
test('identical connections should have same title if on different levels', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3-1',
|
||||
groupId: 'g3-1',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile3: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3-2',
|
||||
groupId: 'g3-2',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2);
|
||||
let connectionProfile3 = new ConnectionProfile(capabilitiesService, profile3);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined);
|
||||
let grandChildConnectionProfileGroup = new ConnectionProfileGroup('g3-2', undefined, 'g3-2', undefined, undefined);
|
||||
childConnectionProfileGroup.addConnections([connectionProfile2]);
|
||||
connectionProfileGroup.addConnections([connectionProfile1]);
|
||||
grandChildConnectionProfileGroup.addConnections([connectionProfile3]);
|
||||
childConnectionProfileGroup.addGroups([grandChildConnectionProfileGroup]);
|
||||
connectionProfileGroup.addGroups([childConnectionProfileGroup]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title);
|
||||
let updatedGrandChildTitleMap = updatedProfileGroup[0].children[0].children[0].connections.map(profile => profile.title);
|
||||
|
||||
// Titles should be the same if they're in different levels.
|
||||
assert.equal(updatedTitleMap[0], updatedChildTitleMap[0]);
|
||||
assert.equal(updatedTitleMap[0], updatedGrandChildTitleMap[0]);
|
||||
assert.equal(updatedChildTitleMap[0], updatedGrandChildTitleMap[0]);
|
||||
});
|
||||
|
||||
test('connections should not affect connections on a different level', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value1' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile1a: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value2' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3-1',
|
||||
groupId: 'g3-1',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile1a = new ConnectionProfile(capabilitiesService, profile1a);
|
||||
let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined);
|
||||
|
||||
childConnectionProfileGroup.addConnections([connectionProfile2]);
|
||||
connectionProfileGroup.addConnections([connectionProfile1, connectionProfile1a]);
|
||||
connectionProfileGroup.addGroups([childConnectionProfileGroup]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title);
|
||||
|
||||
// Titles should be altered for the first group only.
|
||||
assert.equal(updatedChildTitleMap[0] + ' (testOption1=value1)', updatedTitleMap[0]);
|
||||
assert.equal(updatedChildTitleMap[0] + ' (testOption1=value2)', updatedTitleMap[1]);
|
||||
});
|
||||
|
||||
test('non default options should only be appended to the connection with non default options', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value1', testOption2: '15' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
|
||||
connectionProfileGroup.addConnections([connectionProfile1, connectionProfile2]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
|
||||
//Title for second profile should be the same as the first but with non default options appended.
|
||||
assert.equal(updatedTitleMap[0] + ' (testOption1=value1; testOption2=15)', updatedTitleMap[1]);
|
||||
});
|
||||
|
||||
test('identical profiles added into one group and separate groups should have the same options appended', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value1', testOption2: '15' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3',
|
||||
groupId: 'g3',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value2', testOption2: '30' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1Base = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2Base = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
|
||||
connectionProfileGroup.addConnections([connectionProfile1Base, connectionProfile2Base]);
|
||||
|
||||
profile1.groupFullName = 'g3-1';
|
||||
profile1.groupId = 'g3-1';
|
||||
profile2.groupFullName = 'g3-1';
|
||||
profile2.groupId = 'g3-1';
|
||||
|
||||
let connectionProfile1Child = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2Child = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined);
|
||||
|
||||
childConnectionProfileGroup.addConnections([connectionProfile1Child, connectionProfile2Child]);
|
||||
|
||||
profile1.groupFullName = 'g3-2';
|
||||
profile1.groupId = 'g3-2';
|
||||
profile2.groupFullName = 'g3-2';
|
||||
profile2.groupId = 'g3-2';
|
||||
|
||||
let connectionProfile1Grandchild = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2Grandchild = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let grandchildConnectionProfileGroup = new ConnectionProfileGroup('g3-2', undefined, 'g3-2', undefined, undefined);
|
||||
|
||||
grandchildConnectionProfileGroup.addConnections([connectionProfile1Grandchild, connectionProfile2Grandchild]);
|
||||
|
||||
childConnectionProfileGroup.addGroups([grandchildConnectionProfileGroup]);
|
||||
|
||||
connectionProfileGroup.addGroups([childConnectionProfileGroup]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title);
|
||||
let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title);
|
||||
let updatedGrandchildTitleMap = updatedProfileGroup[0].children[0].children[0].connections.map(profile => profile.title);
|
||||
|
||||
//Titles for the same profile in different groups should be identical
|
||||
assert.equal(updatedTitleMap[0], updatedChildTitleMap[0]);
|
||||
assert.equal(updatedTitleMap[0], updatedGrandchildTitleMap[0]);
|
||||
assert.equal(updatedTitleMap[1], updatedChildTitleMap[1]);
|
||||
assert.equal(updatedTitleMap[1], updatedGrandchildTitleMap[1]);
|
||||
});
|
||||
|
||||
test('profiles in adjacent groups on the same layer should not affect titles on nearby groups', async () => {
|
||||
let profile1: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3a',
|
||||
groupId: 'g3a',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: {},
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let profile2: IConnectionProfile = {
|
||||
serverName: 'server3',
|
||||
databaseName: 'database',
|
||||
userName: 'user',
|
||||
password: 'password',
|
||||
authenticationType: '',
|
||||
savePassword: true,
|
||||
groupFullName: 'g3a',
|
||||
groupId: 'g3a',
|
||||
serverCapabilities: undefined,
|
||||
getOptionsKey: undefined!,
|
||||
getOptionKeyIdNames: undefined!,
|
||||
matches: undefined!,
|
||||
providerName: 'MSSQL',
|
||||
options: { testOption1: 'value2', testOption2: '30' },
|
||||
saveProfile: true,
|
||||
id: undefined!,
|
||||
connectionName: undefined!
|
||||
};
|
||||
|
||||
let connectionProfile1a = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2a = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined);
|
||||
|
||||
let childConnectionProfileGroup1 = new ConnectionProfileGroup('g3a', undefined, 'g3a', undefined, undefined);
|
||||
childConnectionProfileGroup1.addConnections([connectionProfile1a, connectionProfile2a]);
|
||||
|
||||
profile1.groupFullName = 'g3b';
|
||||
profile1.groupId = 'g3b';
|
||||
profile2.groupFullName = 'g3b';
|
||||
profile2.groupId = 'g3b';
|
||||
|
||||
let connectionProfile1b = new ConnectionProfile(capabilitiesService, profile1);
|
||||
let connectionProfile2b = new ConnectionProfile(capabilitiesService, profile2);
|
||||
|
||||
let childConnectionProfileGroup2 = new ConnectionProfileGroup('g3b', undefined, 'g3b', undefined, undefined);
|
||||
|
||||
childConnectionProfileGroup2.addConnections([connectionProfile1b, connectionProfile2b]);
|
||||
|
||||
connectionProfileGroup.addGroups([childConnectionProfileGroup1]);
|
||||
|
||||
connectionProfileGroup.addGroups([childConnectionProfileGroup2]);
|
||||
|
||||
let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup], undefined);
|
||||
|
||||
let updatedChildATitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title);
|
||||
let updatedChildBTitleMap = updatedProfileGroup[0].children[1].connections.map(profile => profile.title);
|
||||
|
||||
//Check that titles are generated properly for the first group.
|
||||
assert.equal(updatedChildATitleMap[0] + ' (testOption1=value2; testOption2=30)', updatedChildATitleMap[1]);
|
||||
|
||||
//Titles for the same profile in adjacent groups should be identical
|
||||
assert.equal(updatedChildATitleMap[0], updatedChildBTitleMap[0]);
|
||||
assert.equal(updatedChildATitleMap[1], updatedChildBTitleMap[1]);
|
||||
});
|
||||
});
|
||||
@@ -11,6 +11,7 @@ import * as azdata from 'azdata';
|
||||
import { INewProfilerState } from 'sql/workbench/common/editor/profiler/profilerState';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
const PROFILER_SERVICE_ID = 'profilerService';
|
||||
export const IProfilerService = createDecorator<IProfilerService>(PROFILER_SERVICE_ID);
|
||||
@@ -148,7 +149,7 @@ export interface IProfilerService {
|
||||
* @param editorService service to open profiler editor
|
||||
* @param instantiationService service to create profiler instance
|
||||
*/
|
||||
openFile(fileDialogService: IFileDialogService, editorService: IEditorService, instantiationService: IInstantiationService): Promise<boolean>;
|
||||
openFile(fileDialogService: IFileDialogService, editorService: IEditorService, instantiationService: IInstantiationService, fileService: IFileService): Promise<boolean>;
|
||||
}
|
||||
|
||||
export enum ProfilingSessionType {
|
||||
|
||||
@@ -22,6 +22,7 @@ import { ProfilerFilterDialog } from 'sql/workbench/services/profiler/browser/pr
|
||||
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
|
||||
import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { ByteSize, IFileService } from 'vs/platform/files/common/files';
|
||||
|
||||
class TwoWayMap<T, K> {
|
||||
private forwardMap: Map<T, K>;
|
||||
@@ -303,7 +304,7 @@ export class ProfilerService implements IProfilerService {
|
||||
await this._configurationService.updateValue(PROFILER_FILTER_SETTINGS, config, ConfigurationTarget.USER);
|
||||
}
|
||||
|
||||
public async openFile(fileDialogService: IFileDialogService, editorService: IEditorService, instantiationService: IInstantiationService): Promise<boolean> {
|
||||
public async openFile(fileDialogService: IFileDialogService, editorService: IEditorService, instantiationService: IInstantiationService, fileService: IFileService): Promise<boolean> {
|
||||
const fileURIs = await fileDialogService.showOpenDialog({
|
||||
filters: [
|
||||
{
|
||||
@@ -317,6 +318,21 @@ export class ProfilerService implements IProfilerService {
|
||||
if (fileURIs?.length === 1) {
|
||||
const fileURI = fileURIs[0];
|
||||
|
||||
try {
|
||||
const fileSize = (await fileService.stat(fileURI)).size;
|
||||
const fileLimitSize = 1 * ByteSize.GB;
|
||||
const fileOpenWarningSize = 100 * ByteSize.MB;
|
||||
|
||||
if (fileSize > fileLimitSize) {
|
||||
this._notificationService.error(nls.localize('FileTooLarge', "The file is too large to open in profiler. The profiler can open files that are less than 1GB."));
|
||||
return false;
|
||||
} else if (fileSize > fileOpenWarningSize) {
|
||||
this._notificationService.info(nls.localize('LargeFileWait', "Loading the file might take a moment due to the file size."));
|
||||
}
|
||||
} catch (err) {
|
||||
this._notificationService.error(err.message);
|
||||
}
|
||||
|
||||
let profilerInput: ProfilerInput = instantiationService.createInstance(ProfilerInput, undefined, fileURI);
|
||||
await editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP);
|
||||
profilerInput.setConnectionState(false); // Reset connection to be not connected for File session, so that "Start" is not enabled.
|
||||
|
||||
@@ -49,8 +49,6 @@
|
||||
"sql/base/browser/ui/panel/panel.ts",
|
||||
"sql/base/browser/ui/selectBox/selectBox.ts",
|
||||
"sql/base/browser/ui/panel/panel.component.ts",
|
||||
"sql/workbench/services/dialog/browser/dialogModal.ts",
|
||||
"sql/workbench/services/dialog/browser/wizardModal.ts",
|
||||
"sql/base/browser/ui/taskbar/taskbar.ts",
|
||||
"sql/workbench/contrib/notebook/browser/outputs/notebookMarkdown.ts",
|
||||
"sql/workbench/contrib/notebook/browser/cellViews/textCell.component.ts",
|
||||
|
||||
@@ -18,6 +18,23 @@ export class TestConfigurationService implements IConfigurationService {
|
||||
readonly onDidChangeConfiguration = this.onDidChangeConfigurationEmitter.event;
|
||||
|
||||
constructor(configuration?: any) {
|
||||
// {{SQL CARBON EDIT}} - START
|
||||
// Ensures that all configuration services use the DOM renderer. There's an issue
|
||||
// with GPU rendering that is causing unit tests to be flaky and obscuring true failing tests.
|
||||
// This is a temporary fix and should be removed once xterm GPU rendering is working again.
|
||||
if (configuration) {
|
||||
if (configuration.integrated) {
|
||||
configuration.integrated.gpuAcceleration = 'off';
|
||||
}
|
||||
else {
|
||||
configuration.integrated = { gpuAcceleration: 'off' };
|
||||
}
|
||||
}
|
||||
else {
|
||||
configuration = { integrated: { gpuAcceleration: 'off' } };
|
||||
}
|
||||
// {{SQL CARBON EDIT}} - END
|
||||
|
||||
this.configuration = configuration || Object.create(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ export class TestExperimentService extends ExperimentService {
|
||||
}
|
||||
}
|
||||
|
||||
suite.skip('Experiment Service', () => { // {{SQL CARBON EDIT}} Tests are flaky, and have been removed in VS Code so disabling until we catch up
|
||||
suite('Experiment Service', () => {
|
||||
let instantiationService: TestInstantiationService;
|
||||
let testConfigurationService: TestConfigurationService;
|
||||
let testObject: ExperimentService;
|
||||
|
||||
@@ -36,7 +36,7 @@ const defaultTerminalConfig: Partial<ITerminalConfiguration> = {
|
||||
unicodeVersion: '6'
|
||||
};
|
||||
|
||||
suite.skip('Buffer Content Tracker', () => { // {{SQL CARBON EDIT}} skip failing suite
|
||||
suite('Buffer Content Tracker', () => {
|
||||
let instantiationService: TestInstantiationService;
|
||||
let configurationService: TestConfigurationService;
|
||||
let themeService: TestThemeService;
|
||||
|
||||
@@ -94,7 +94,7 @@ suite('TerminalLinkManager', () => {
|
||||
} as Partial<ITerminalCapabilityStore> as any, instantiationService.createInstance(TerminalLinkResolver));
|
||||
});
|
||||
|
||||
suite.skip('getLinks and open recent link', () => { // {{SQL CARBON EDIT}} skip failing suite
|
||||
suite('getLinks and open recent link', () => {
|
||||
test('should return no links', async () => {
|
||||
const links = await linkManager.getLinks();
|
||||
equals(links.webLinks, []);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { TestFileService } from 'vs/workbench/test/browser/workbenchTestServices
|
||||
import { TestExtensionService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||
|
||||
|
||||
suite.skip('Getting Started Markdown Renderer', () => { // {{SQL CARBON EDIT}} - disable suite
|
||||
suite('Getting Started Markdown Renderer', () => {
|
||||
test('renders theme picker markdown with images', async () => {
|
||||
const fileService = new TestFileService();
|
||||
const languageService = new LanguageService();
|
||||
|
||||
@@ -23,7 +23,7 @@ class ConfigurationCache implements IConfigurationCache {
|
||||
async remove({ type, key }: ConfigurationKey): Promise<void> { this.cache.delete(`${type}:${key}`); }
|
||||
}
|
||||
|
||||
suite.skip('DefaultConfiguration', () => { // {{SQL CARBON EDIT}} skip failing suite
|
||||
suite('DefaultConfiguration', () => {
|
||||
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
|
||||
const cacheKey: ConfigurationKey = { type: 'defaults', key: 'configurationDefaultsOverrides' };
|
||||
|
||||
@@ -56,7 +56,7 @@ class ConfigurationCache implements IConfigurationCache {
|
||||
async remove(): Promise<void> { }
|
||||
}
|
||||
|
||||
suite.skip('ConfigurationEditing', () => { // {{SQL CARBON EDIT}} skip suite
|
||||
suite('ConfigurationEditing', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
let userDataProfileService: IUserDataProfileService;
|
||||
|
||||
@@ -1518,7 +1518,7 @@ suite.skip('WorkspaceConfigurationService - Folder', () => { // {{SQL CARBON EDI
|
||||
}));
|
||||
});
|
||||
|
||||
suite.skip('WorkspaceConfigurationService - Profiles', () => { // {{SQL CARBON EDIT}} - skip failing suite
|
||||
suite('WorkspaceConfigurationService - Profiles', () => {
|
||||
|
||||
let testObject: WorkspaceService, workspaceService: WorkspaceService, fileService: IFileService, environmentService: IBrowserWorkbenchEnvironmentService, userDataProfileService: IUserDataProfileService, instantiationService: TestInstantiationService;
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
@@ -2489,7 +2489,7 @@ suite.skip('WorkspaceConfigurationService-Multiroot', () => { // {{SQL CARBON ED
|
||||
|
||||
});
|
||||
|
||||
suite.skip('WorkspaceConfigurationService - Remote Folder', () => { // {{SQL CARBON EDIT}} - disable suite
|
||||
suite('WorkspaceConfigurationService - Remote Folder', () => {
|
||||
|
||||
let testObject: WorkspaceService, folder: URI,
|
||||
machineSettingsResource: URI, remoteSettingsResource: URI, fileSystemProvider: InMemoryFileSystemProvider, resolveRemoteEnvironment: () => void,
|
||||
|
||||
@@ -58,7 +58,7 @@ const nullContext = {
|
||||
getExecPath: () => undefined
|
||||
};
|
||||
|
||||
suite.skip('Configuration Resolver Service', () => { // {{SQL CARBON EDIT}} - skip failing suite
|
||||
suite('Configuration Resolver Service', () => {
|
||||
let configurationResolverService: IConfigurationResolverService | null;
|
||||
const envVariables: { [key: string]: string } = { key1: 'Value for key1', key2: 'Value for key2' };
|
||||
// let environmentService: MockWorkbenchEnvironmentService;
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
|
||||
import { IEditorResolverService, ResolvedStatus, RegisteredEditorPriority } from 'vs/workbench/services/editor/common/editorResolverService';
|
||||
import { createEditorPart, ITestInstantiationService, TestFileEditorInput, TestServiceAccessor, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
|
||||
suite.skip('EditorResolverService', () => { // {{SQL CARBON EDIT}} - disable suite
|
||||
suite('EditorResolverService', () => {
|
||||
|
||||
const TEST_EDITOR_INPUT_ID = 'testEditorInputForEditorResolverService';
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
@@ -111,7 +111,7 @@ export class TestExtensionEnablementService extends ExtensionEnablementService {
|
||||
}
|
||||
}
|
||||
|
||||
suite.skip('ExtensionEnablementService Test', () => {
|
||||
suite('ExtensionEnablementService Test', () => {
|
||||
|
||||
let instantiationService: TestInstantiationService;
|
||||
let testObject: IWorkbenchExtensionEnablementService;
|
||||
|
||||
@@ -128,7 +128,7 @@ suite('BrowserExtensionService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
suite.skip('ExtensionService', () => { // {{SQL CARBON EDIT}} - disable failing suite
|
||||
suite('ExtensionService', () => {
|
||||
|
||||
class MyTestExtensionService extends AbstractExtensionService {
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
suite.skip('HistoryService', function () { // {{SQL CARBON EDIT}} skip suite
|
||||
suite('HistoryService', function () {
|
||||
|
||||
const TEST_EDITOR_ID = 'MyTestEditorForEditorHistory';
|
||||
const TEST_EDITOR_INPUT_ID = 'testEditorInputForHistoyService';
|
||||
|
||||
Reference in New Issue
Block a user