From 3fb8d57d25e0eb079bff352811f4fb409b8cc3d5 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra <13396919+cheenamalhotra@users.noreply.github.com> Date: Fri, 10 Feb 2023 10:34:36 -0800 Subject: [PATCH] Add support for Encrypt=Strict for TDS 8.0 connections with SQL Server 2022 (#21256) --- extensions/cms/package.json | 17 +++- extensions/cms/package.nls.json | 7 +- extensions/mssql/package.json | 30 ++++++- extensions/mssql/package.nls.json | 7 +- resources/xlf/en/cms.xlf | 13 ++- resources/xlf/en/mssql.xlf | 13 ++- src/sql/azdata.proposed.d.ts | 32 ++++++++ src/sql/base/browser/ui/adsWidget.ts | 25 ++++++ src/sql/base/browser/ui/inputBox/inputBox.ts | 10 ++- .../base/browser/ui/selectBox/selectBox.ts | 15 +++- .../platform/connection/common/constants.ts | 14 ++++ .../common/providerConnectionInfo.test.ts | 15 ++++ .../connection/browser/connectionWidget.ts | 82 +++++++++++++++++-- 13 files changed, 256 insertions(+), 24 deletions(-) create mode 100644 src/sql/base/browser/ui/adsWidget.ts diff --git a/extensions/cms/package.json b/extensions/cms/package.json index 4007f4650f..9a2a3b1335 100644 --- a/extensions/cms/package.json +++ b/extensions/cms/package.json @@ -237,10 +237,23 @@ "displayName": "%cms.connectionOptions.encrypt.displayName%", "description": "%cms.connectionOptions.encrypt.description%", "groupName": "%cms.connectionOptions.groupName.security%", - "valueType": "boolean", + "valueType": "category", "defaultValue": "true", "objectType": null, - "categoryValues": null, + "categoryValues": [ + { + "displayName": "%cms.connectionOptions.encrypt.categoryValues.true%", + "name": "true" + }, + { + "displayName": "%cms.connectionOptions.encrypt.categoryValues.strict%", + "name": "strict" + }, + { + "displayName": "%cms.connectionOptions.encrypt.categoryValues.false%", + "name": "false" + } + ], "isRequired": false, "isArray": false, "showOnConnectionDialog": true diff --git a/extensions/cms/package.nls.json b/extensions/cms/package.nls.json index cc04169dd9..94c6759bad 100644 --- a/extensions/cms/package.nls.json +++ b/extensions/cms/package.nls.json @@ -69,13 +69,16 @@ "cms.connectionOptions.columnEncryptionSetting.displayName": "Column encryption", "cms.connectionOptions.columnEncryptionSetting.description": "Default column encryption setting for all the commands on the connection", "cms.connectionOptions.encrypt.displayName": "Encrypt", - "cms.connectionOptions.encrypt.description": "When true, SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed", + "cms.connectionOptions.encrypt.description": "When 'Mandatory' or 'Strict', SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. When set to 'Strict', SQL Server uses TDS 8.0 for all data transfer between the client and server. 'Strict' is supported on SQL Server 2022 onwards.", + "cms.connectionOptions.encrypt.categoryValues.strict": "Strict", + "cms.connectionOptions.encrypt.categoryValues.true": "Mandatory (True)", + "cms.connectionOptions.encrypt.categoryValues.false": "Optional (False)", "cms.connectionOptions.persistSecurityInfo.displayName": "Persist security info", "cms.connectionOptions.persistSecurityInfo.description": "When false, security-sensitive information, such as the password, is not returned as part of the connection", "cms.connectionOptions.hostNameInCertificate.displayName": "Host name in certificate", "cms.connectionOptions.hostNameInCertificate.description": "Indicates the host name specified in TLS certificate that will be used by SQL Server to validate server certificate. When not specified, the server name is used by default for certificate validation.", "cms.connectionOptions.trustServerCertificate.displayName": "Trust server certificate", - "cms.connectionOptions.trustServerCertificate.description": "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate", + "cms.connectionOptions.trustServerCertificate.description": "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate. This property is not supported with Encrypt=Strict.", "cms.connectionOptions.attachedDBFileName.displayName": "Attached DB file name", "cms.connectionOptions.attachedDBFileName.description": "The name of the primary file, including the full path name, of an attachable database", "cms.connectionOptions.contextConnection.displayName": "Context connection", diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index 07c1ed5b10..0d0b6dede6 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -848,13 +848,37 @@ "displayName": "%mssql.connectionOptions.encrypt.displayName%", "description": "%mssql.connectionOptions.encrypt.description%", "groupName": "%mssql.connectionOptions.groupName.security%", - "valueType": "boolean", + "valueType": "category", "defaultValue": "true", "objectType": null, - "categoryValues": null, + "categoryValues": [ + { + "displayName": "%mssql.connectionOptions.encrypt.categoryValues.true%", + "name": "true" + }, + { + "displayName": "%mssql.connectionOptions.encrypt.categoryValues.strict%", + "name": "strict" + }, + { + "displayName": "%mssql.connectionOptions.encrypt.categoryValues.false%", + "name": "false" + } + ], "isRequired": false, "isArray": false, - "showOnConnectionDialog": true + "showOnConnectionDialog": true, + "onSelectionChange": [ + { + "values": ["strict"], + "dependentOptionActions": [ + { + "optionName": "trustServerCertificate", + "action": "hide" + } + ] + } + ] }, { "specialValueType": null, diff --git a/extensions/mssql/package.nls.json b/extensions/mssql/package.nls.json index 557522e261..e40599717d 100644 --- a/extensions/mssql/package.nls.json +++ b/extensions/mssql/package.nls.json @@ -118,13 +118,16 @@ "mssql.connectionOptions.enclaveAttestationUrl.displayName": "Enclave Attestation URL", "mssql.connectionOptions.enclaveAttestationUrl.description": "Specifies an endpoint for attesting a server-side enclave used with Always Encrypted with secure enclaves", "mssql.connectionOptions.encrypt.displayName": "Encrypt", - "mssql.connectionOptions.encrypt.description": "When true, SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed", + "mssql.connectionOptions.encrypt.description": "When 'Mandatory' or 'Strict', SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. When set to 'Strict', SQL Server uses TDS 8.0 for all data transfer between the client and server. 'Strict' is supported on SQL Server 2022 onwards.", + "mssql.connectionOptions.encrypt.categoryValues.strict": "Strict", + "mssql.connectionOptions.encrypt.categoryValues.true": "Mandatory (True)", + "mssql.connectionOptions.encrypt.categoryValues.false": "Optional (False)", "mssql.connectionOptions.persistSecurityInfo.displayName": "Persist security info", "mssql.connectionOptions.persistSecurityInfo.description": "When false, security-sensitive information, such as the password, is not returned as part of the connection", "mssql.connectionOptions.hostNameInCertificate.displayName": "Host name in certificate", "mssql.connectionOptions.hostNameInCertificate.description": "Indicates the host name specified in TLS certificate that will be used by SQL Server to validate server certificate. When not specified, the server name is used by default for certificate validation.", "mssql.connectionOptions.trustServerCertificate.displayName": "Trust server certificate", - "mssql.connectionOptions.trustServerCertificate.description": "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate", + "mssql.connectionOptions.trustServerCertificate.description": "When true (and encrypt=true), SQL Server uses SSL encryption for all data sent between the client and server without validating the server certificate. This property is not supported with Encrypt=Strict.", "mssql.connectionOptions.attachedDBFileName.displayName": "Attached DB file name", "mssql.connectionOptions.attachedDBFileName.description": "The name of the primary file, including the full path name, of an attachable database", "mssql.connectionOptions.contextConnection.displayName": "Context connection", diff --git a/resources/xlf/en/cms.xlf b/resources/xlf/en/cms.xlf index 7ab7f75a99..60909625ed 100644 --- a/resources/xlf/en/cms.xlf +++ b/resources/xlf/en/cms.xlf @@ -168,11 +168,20 @@ Current language - When true, SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed + When 'Mandatory' or 'Strict', SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. When set to 'Strict', SQL Server uses TDS 8.0 for all data transfer between the client and server. 'Strict' encryption is supported on SQL Server 2022 onwards. Encrypt + + Strict + + + Mandatory (True) + + + Optional (False) + The name or network address of the instance of SQL Server that acts as a failover partner @@ -408,4 +417,4 @@ Version - \ No newline at end of file + diff --git a/resources/xlf/en/mssql.xlf b/resources/xlf/en/mssql.xlf index 0c398e5f5d..887d6e427d 100644 --- a/resources/xlf/en/mssql.xlf +++ b/resources/xlf/en/mssql.xlf @@ -270,11 +270,20 @@ Note: A self-signed certificate offers only limited protection and is not a reco Enclave Attestation URL - When true, SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed + When 'Mandatory' or 'Strict', SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. When set to 'Strict', SQL Server uses TDS 8.0 for all data transfer between the client and server. 'Strict' encryption is supported on SQL Server 2022 onwards. Encrypt + + Strict + + + Mandatory (True) + + + Optional (False) + The name or network address of the instance of SQL Server that acts as a failover partner @@ -618,4 +627,4 @@ Note: A self-signed certificate offers only limited protection and is not a reco Show Log File - \ No newline at end of file + diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 9e4072d1a1..edf4859a6c 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -556,6 +556,38 @@ declare module 'azdata' { * and not the Advanced Options window. */ showOnConnectionDialog?: boolean; + + /** + * Used to define list of values based on which another option is rendered visible/hidden. + */ + onSelectionChange?: SelectionChangeEvent[]; + } + + /** + * This change event defines actions + */ + export interface SelectionChangeEvent { + /** + * Values that affect actions defined in this event. + */ + values: string[]; + + /** + * Action to be taken on another option when selected value matches to the list of values provided. + */ + dependentOptionActions: DependentOptionAction[]; + } + + export interface DependentOptionAction { + /** + * Name of option affected by defined action. + */ + optionName: string, + + /** + * Action to be taken, Supported values: 'show', 'hide'. + */ + action: string; } // Object Explorer interfaces -------------------------------- diff --git a/src/sql/base/browser/ui/adsWidget.ts b/src/sql/base/browser/ui/adsWidget.ts new file mode 100644 index 0000000000..500ba54687 --- /dev/null +++ b/src/sql/base/browser/ui/adsWidget.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Widget } from 'vs/base/browser/ui/widget'; +`` +/** + * This interface is implemented by SelectBox and InputBox to provide a common API surface area in connectionWidget.ts + * If more widgets must be used in Connection Dialog, they should implement this interface. + */ +export interface AdsWidget extends Widget { + + get value(): string; + + get id(): string; + + getAriaLabel(): string; + + enable(): void; + + disable(): void; + + hideMessage(): void; +} diff --git a/src/sql/base/browser/ui/inputBox/inputBox.ts b/src/sql/base/browser/ui/inputBox/inputBox.ts index de3d0d277a..32dab4c7c3 100644 --- a/src/sql/base/browser/ui/inputBox/inputBox.ts +++ b/src/sql/base/browser/ui/inputBox/inputBox.ts @@ -7,6 +7,7 @@ import { InputBox as vsInputBox, IInputOptions as vsIInputBoxOptions, IInputBoxS import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview'; import { Color } from 'vs/base/common/color'; import { Event, Emitter } from 'vs/base/common/event'; +import { AdsWidget } from 'sql/base/browser/ui/adsWidget'; export interface OnLoseFocusParams { value: string; @@ -29,7 +30,7 @@ export interface IInputOptions extends vsIInputBoxOptions { ariaDescription?: string; } -export class InputBox extends vsInputBox { +export class InputBox extends vsInputBox implements AdsWidget { private enabledInputBackground?: Color; private enabledInputForeground?: Color; private enabledInputBorder?: Color; @@ -48,7 +49,7 @@ export class InputBox extends vsInputBox { private _isTextAreaInput = false; private _hideErrors = false; - constructor(container: HTMLElement, contextViewProvider: IContextViewProvider, private _sqlOptions?: IInputOptions) { + constructor(container: HTMLElement, contextViewProvider: IContextViewProvider, private _sqlOptions?: IInputOptions, id?: string) { super(container, contextViewProvider, _sqlOptions); this.enabledInputBackground = this.inputBackground; this.enabledInputForeground = this.inputForeground; @@ -74,6 +75,7 @@ export class InputBox extends vsInputBox { if (this._sqlOptions.ariaDescription) { this.inputElement.setAttribute('aria-description', this._sqlOptions.ariaDescription); } + this.inputElement.id = id; } public override style(styles: IInputBoxStyles): void { @@ -197,4 +199,8 @@ export class InputBox extends vsInputBox { this._lastLoseFocusValue = newValue; super.value = newValue; } + + public get id(): string { + return this.input.id; + } } diff --git a/src/sql/base/browser/ui/selectBox/selectBox.ts b/src/sql/base/browser/ui/selectBox/selectBox.ts index f79af0bbe5..f197b9fc4c 100644 --- a/src/sql/base/browser/ui/selectBox/selectBox.ts +++ b/src/sql/base/browser/ui/selectBox/selectBox.ts @@ -17,6 +17,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { SelectBoxList } from 'vs/base/browser/ui/selectBox/selectBoxCustom'; import { Event, Emitter } from 'vs/base/common/event'; +import { AdsWidget } from 'sql/base/browser/ui/adsWidget'; const $ = dom.$; @@ -39,7 +40,7 @@ export interface ISelectBoxStyles extends vsISelectBoxStyles { inputValidationErrorForeground?: Color; } -export class SelectBox extends vsSelectBox { +export class SelectBox extends vsSelectBox implements AdsWidget { private _optionsDictionary: Map; private _dialogOptions: SelectOptionItemSQL[]; private _selectedOption: string; @@ -67,7 +68,7 @@ export class SelectBox extends vsSelectBox { private element?: HTMLElement; - constructor(options: SelectOptionItemSQL[] | string[], selectedOption: string, contextViewProvider: IContextViewProvider, container?: HTMLElement, selectBoxOptions?: ISelectBoxOptions) { + constructor(options: SelectOptionItemSQL[] | string[], selectedOption: string, contextViewProvider: IContextViewProvider, container?: HTMLElement, selectBoxOptions?: ISelectBoxOptions, id?: string) { let optionItems: SelectOptionItemSQL[] = SelectBox.createOptions(options); super(optionItems, 0, contextViewProvider, undefined, selectBoxOptions); @@ -98,6 +99,7 @@ export class SelectBox extends vsSelectBox { this.element = dom.append(container, $('.monaco-selectbox.idle')); } + this.selectElement.id = id; this._selectBoxOptions = selectBoxOptions; let focusTracker = dom.trackFocus(this.selectElement); this._register(focusTracker); @@ -220,7 +222,6 @@ export class SelectBox extends vsSelectBox { }); } - public override setOptions(options: string[] | SelectOptionItemSQL[] | ISelectOptionItem[], selected?: number): void { let selectOptions: SelectOptionItemSQL[] = SelectBox.createOptions(options); this.populateOptionsDictionary(selectOptions); @@ -255,6 +256,14 @@ export class SelectBox extends vsSelectBox { this.applyStyles(); } + public getAriaLabel(): string { + return this.selectElem.ariaLabel; + } + + public get id(): string { + return this.selectElem.id; + } + public hasFocus(): boolean { return document.activeElement === this.selectElement; } diff --git a/src/sql/platform/connection/common/constants.ts b/src/sql/platform/connection/common/constants.ts index 9251bfffb2..191e57ee2a 100644 --- a/src/sql/platform/connection/common/constants.ts +++ b/src/sql/platform/connection/common/constants.ts @@ -57,6 +57,20 @@ export enum AuthenticationType { None = 'None' } +/* +* Actions for the connection dialog to show/hide connection options. +*/ +export enum Actions { + /** + * Shows a connection option + */ + Show = 'show', + /** + * Hides a connection option + */ + Hide = 'hide' +} + /* CMS constants */ export const cmsProviderName = 'MSSQL-CMS'; diff --git a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts index faf1b4065d..74a2308eee 100644 --- a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts +++ b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts @@ -214,6 +214,21 @@ suite('SQL ProviderConnectionInfo tests', () => { assert.strictEqual(conn.options['encrypt'], 'true'); }); + test('constructor should initialize the options with encrypt strict', () => { + let options: { [key: string]: string } = {}; + options['encrypt'] = 'strict'; + let conn2 = Object.assign({}, connectionProfile, { options: options }); + let conn = new ProviderConnectionInfo(capabilitiesService, conn2); + + assert.strictEqual(conn.connectionName, conn2.connectionName); + assert.strictEqual(conn.serverName, conn2.serverName); + assert.strictEqual(conn.databaseName, conn2.databaseName); + assert.strictEqual(conn.authenticationType, conn2.authenticationType); + assert.strictEqual(conn.password, conn2.password); + assert.strictEqual(conn.userName, conn2.userName); + assert.strictEqual(conn.options['encrypt'], 'strict'); + }); + test('getOptionsKey should create a valid unique id', () => { let conn = new ProviderConnectionInfo(capabilitiesService, connectionProfile); // **IMPORTANT** This should NEVER change without thorough review and consideration of side effects. This key controls diff --git a/src/sql/workbench/services/connection/browser/connectionWidget.ts b/src/sql/workbench/services/connection/browser/connectionWidget.ts index 22f476cae0..fb001ba81a 100644 --- a/src/sql/workbench/services/connection/browser/connectionWidget.ts +++ b/src/sql/workbench/services/connection/browser/connectionWidget.ts @@ -35,9 +35,11 @@ import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMess import Severity from 'vs/base/common/severity'; import { ConnectionStringOptions } from 'sql/platform/capabilities/common/capabilitiesService'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; -import { AuthenticationType } from 'sql/platform/connection/common/constants'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { AuthLibrary, filterAccounts } from 'sql/workbench/services/accountManagement/browser/accountDialog'; +import { AuthenticationType, Actions } from 'sql/platform/connection/common/constants'; +import { AdsWidget } from 'sql/base/browser/ui/adsWidget'; +import { createCSSRule } from 'vs/base/browser/dom'; const ConnectionStringText = localize('connectionWidget.connectionString', "Connection string"); @@ -78,7 +80,7 @@ export class ConnectionWidget extends lifecycle.Disposable { protected _providerName: string; protected _connectionNameInputBox: InputBox; protected _databaseNameInputBox: Dropdown; - protected _customOptionWidgets: (InputBox | SelectBox)[]; + protected _customOptionWidgets: AdsWidget[]; protected _advancedButton: Button; private static readonly _authTypes: AuthenticationType[] = [AuthenticationType.AzureMFA, AuthenticationType.AzureMFAAndUser, AuthenticationType.Integrated, AuthenticationType.SqlLogin, AuthenticationType.DSTSAuth, AuthenticationType.None]; @@ -192,6 +194,7 @@ export class ConnectionWidget extends lifecycle.Disposable { this.addConnectionNameOptions(); this.addAdvancedOptions(); this.updateRequiredStateForOptions(); + this.registerOnSelectionChangeEvents(); if (this._connectionStringOptions.isEnabled) { // update the UI based on connection string setting after initialization this.handleConnectionStringOptionChange(); @@ -255,7 +258,8 @@ export class ConnectionWidget extends lifecycle.Disposable { protected addAuthenticationTypeOption(authTypeChanged: boolean = false): void { if (this._optionsMaps[ConnectionOptionSpecialType.authType]) { - let authType = DialogHelper.appendRow(this._tableContainer, this._optionsMaps[ConnectionOptionSpecialType.authType].displayName, 'connection-label', 'connection-input', 'auth-type-row'); + let authType = DialogHelper.appendRow(this._tableContainer, this._optionsMaps[ConnectionOptionSpecialType.authType].displayName, + 'connection-label', 'connection-input', 'auth-type-row'); DialogHelper.appendInputSelectBox(authType, this._authTypeSelectBox); } } @@ -264,10 +268,12 @@ export class ConnectionWidget extends lifecycle.Disposable { if (this._customOptions.length > 0) { this._customOptionWidgets = []; this._customOptions.forEach((option, i) => { - let customOptionsContainer = DialogHelper.appendRow(this._tableContainer, option.displayName, 'connection-label', 'connection-input', 'custom-connection-options', false, option.description, 100); + let customOptionsContainer = DialogHelper.appendRow(this._tableContainer, option.displayName, 'connection-label', 'connection-input', + ['custom-connection-options', `option-${option.name}`], false, option.description, 100); switch (option.valueType) { case ServiceOptionType.boolean: case ServiceOptionType.category: + let selectedValue = option.defaultValue; let options = option.valueType === ServiceOptionType.category @@ -282,7 +288,7 @@ export class ConnectionWidget extends lifecycle.Disposable { return { text: v.displayName, value: v.value } as SelectOptionItemSQL; }); - this._customOptionWidgets[i] = new SelectBox(options, selectedValue, this._contextViewService, customOptionsContainer, { ariaLabel: option.displayName }); + this._customOptionWidgets[i] = new SelectBox(options, selectedValue, this._contextViewService, customOptionsContainer, { ariaLabel: option.displayName }, option.name); DialogHelper.appendInputSelectBox(customOptionsContainer, this._customOptionWidgets[i] as SelectBox); this._register(styler.attachSelectBoxStyler(this._customOptionWidgets[i] as SelectBox, this._themeService)); break; @@ -296,6 +302,70 @@ export class ConnectionWidget extends lifecycle.Disposable { } } + /** + * Registers on selection change event for connection options configured with 'onSelectionChange' property. + * TODO extend this to include collection of other main and advanced option widgets here. + */ + protected registerOnSelectionChangeEvents(): void { + //Register on selection change event for custom options + this._customOptionWidgets.forEach((widget, i) => { + if (widget instanceof SelectBox) { + this._registerSelectionChangeEvents([this._customOptionWidgets], this._customOptions[i], widget); + } + }); + } + + private _registerSelectionChangeEvents(collections: AdsWidget[][], option: azdata.ConnectionOption, widget: SelectBox) { + if (option.onSelectionChange) { + option.onSelectionChange.forEach((event) => { + this._register(widget.onDidSelect(value => { + let selectedValue = value.selected; + event?.dependentOptionActions?.forEach((optionAction) => { + let defaultValue: string | undefined = this._customOptions.find(o => o.name === optionAction.optionName)?.defaultValue; + let widget: AdsWidget | undefined = this._findWidget(collections, optionAction.optionName); + if (widget) { + createCSSRule(`.hide-${widget.id} .option-${widget.id}`, `display: none;`); + this._onValueChangeEvent(selectedValue, event.values, widget, defaultValue, optionAction.action); + } + }); + })); + }); + } + } + + /** + * Finds Widget from provided collection of widgets using option name. + * @param collections collections of widgets to search for the widget with the widget Id + * @param id Widget Id + * @returns Widget if found, undefined otherwise + */ + private _findWidget(collections: AdsWidget[][], id: string): AdsWidget | undefined { + let foundWidget: AdsWidget | undefined; + collections.forEach((collection) => { + if (!foundWidget) { + foundWidget = collection.find(widget => widget.id === id); + } + }); + return foundWidget; + } + + private _onValueChangeEvent(selectedValue: string, acceptedValues: string[], + widget: AdsWidget, defaultValue: string, action: string): void { + if ((acceptedValues.includes(selectedValue.toLocaleLowerCase()) && action === Actions.Show) + || (!acceptedValues.includes(selectedValue.toLocaleLowerCase()) && action === Actions.Hide)) { + this._tableContainer.classList.remove(`hide-${widget.id}`); + } else { + // Support more Widget classes here as needed. + if (widget instanceof SelectBox) { + widget.select(widget.values.indexOf(defaultValue)); + } else if (widget instanceof InputBox) { + widget.value = defaultValue; + } + this._tableContainer.classList.add(`hide-${widget.id}`); + widget.hideMessage(); + } + } + protected addServerNameOption(): void { // Server name let serverNameOption = this._optionsMaps[ConnectionOptionSpecialType.serverName]; @@ -832,7 +902,7 @@ export class ConnectionWidget extends lifecycle.Disposable { if (value !== '') { if (widget instanceof SelectBox) { widget.selectWithOptionName(value); - } else { + } else if (widget instanceof InputBox) { widget.value = value; } }