From e5b7bff7b4c4c04d943636db19acc0d4170b1dd2 Mon Sep 17 00:00:00 2001 From: Sai Avishkar Sreerama <74571829+ssreerama@users.noreply.github.com> Date: Wed, 16 Aug 2023 12:00:18 -0500 Subject: [PATCH] Enabling Database scoped configurations tab to DB Properties (#23890) * initial changes for loadin dsc table with real values from smo * Displaying diff columns for DSC for diff sql server * checkbox maiants the selection * elevate option fails to load correct value when set to when_supported option * all working till maxdop, todo pause option, save * commented MAXDOP changes, as it is causing issues * primary,sec,checkbox working as expected, TODO:MaxDop etc options,saving,tests * Undo MAXDOP commented code * refactored with service data * column header width adjustments * Maxdop and pause resume options completed, apply button is failing now * Removed option names from loc and using Id instead as names may change in future like in doc * Apply button fixed * refactored to reduce table reload * Ledger digest completed * refactor done: maxdop secondary shows wrong data from pause_resume * refactor more: all working but table focus disturbs on update table * adds conditions for unsupported dsc to <2016 server * maxdop secondary checkbox fix * rows still loses focus after value change due to update table row data * Fixed updating secondary dropdown value * reusing the private method and removed the duplicated codes * Enter key in input type allows the change to update the table data, reduces the live update issues * Setting focus to the current row * using the existed setTableData method * code review comment updates * Input type checkbox update table additional validation * fixing the input type focus and reverting the enterKeyPress logic * fixing the flickering issue with data refresh * moving code inline and using actual component * cleanup * addressing code review comments * addressing code review comment for using loc var instead of duplicated line of code to get the rowinfo * vBump STS and fixing required field causing the apply button not enable for other options on main branch --- extensions/mssql/config.json | 2 +- .../mssql/src/objectManagement/constants.ts | 1 + .../mssql/src/objectManagement/interfaces.ts | 11 + .../objectManagement/localizedConstants.ts | 6 +- .../objectManagementService.ts | 22 +- .../src/objectManagement/ui/databaseDialog.ts | 388 +++++++++++++++++- 6 files changed, 419 insertions(+), 11 deletions(-) diff --git a/extensions/mssql/config.json b/extensions/mssql/config.json index cdb48fd76b..8871e9d221 100644 --- a/extensions/mssql/config.json +++ b/extensions/mssql/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "4.9.0.13", + "version": "4.9.0.14", "downloadFileNames": { "Windows_86": "win-x86-net7.0.zip", "Windows_64": "win-x64-net7.0.zip", diff --git a/extensions/mssql/src/objectManagement/constants.ts b/extensions/mssql/src/objectManagement/constants.ts index 4cefd9f1ac..49acced250 100644 --- a/extensions/mssql/src/objectManagement/constants.ts +++ b/extensions/mssql/src/objectManagement/constants.ts @@ -34,6 +34,7 @@ export const DetachDatabaseDocUrl = 'https://go.microsoft.com/fwlink/?linkid=224 export const DatabaseGeneralPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-general-page'; export const DatabaseOptionsPropertiesDocUrl = 'https://learn.microsoft.com/sql/relational-databases/databases/database-properties-options-page' export const DropDatabaseDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/drop-database-transact-sql'; +export const DatabaseScopedConfigurationPropertiesDocUrl = 'https://learn.microsoft.com/sql/t-sql/statements/alter-database-scoped-configuration-transact-sql' export const enum TelemetryActions { CreateObject = 'CreateObject', diff --git a/extensions/mssql/src/objectManagement/interfaces.ts b/extensions/mssql/src/objectManagement/interfaces.ts index 73eeb953bc..8d1905252f 100644 --- a/extensions/mssql/src/objectManagement/interfaces.ts +++ b/extensions/mssql/src/objectManagement/interfaces.ts @@ -454,6 +454,7 @@ export interface Database extends ObjectManagement.SqlObject { databaseReadOnly?: boolean; encryptionEnabled: boolean; restrictAccess?: string; + databaseScopedConfigurations: DatabaseScopedConfigurationsInfo[]; } export interface DatabaseViewInfo extends ObjectManagement.ObjectViewInfo { @@ -472,6 +473,16 @@ export interface DatabaseViewInfo extends ObjectManagement.ObjectViewInfo{ + collationNames: { defaultValueIndex: 0, options: ['Latin1_General_100_CI_AS_KS_WS', 'Latin1_General_100_CI_AS_KS_WS_SC'] }, + compatibilityLevels: { defaultValueIndex: 0, options: ['SQL Server 2008', 'SQL Server 2012', 'SQL Server 2014', 'SQL Server 2016', 'SQL Server 2017', 'SQL Server 2019'] }, + containmentTypes: { defaultValueIndex: 0, options: ['NONE', 'PARTIAL'] }, + restrictAccessOptions: ['MULTI_USER', 'RESTRICTED_USER', 'SINGLE_USER'], + recoveryModels: { defaultValueIndex: 0, options: ['FULL', 'SIMPLE', 'BULK_LOGGED'] }, + pageVerifyOptions: ['CHECKSUM', 'NONE', 'TORN_PAGE_DETECTION'], + dscElevateOptions: ['OFF', 'WHEN_SUPPORTED', 'FAIL_UNSUPPORTED'], + dscEnableDisableOptions: ['ENABLED', 'DISABLED'], + dscOnOffOptions: ['ON', 'OFF'], objectInfo: { name: 'Database Properties1', collationName: 'Latin1_General_100_CI_AS_KS_WS', @@ -491,8 +500,19 @@ export class TestObjectManagementService implements IObjectManagementService { databaseReadOnly: true, encryptionEnabled: false, restrictAccess: 'SINGLE_USER', + databaseScopedConfigurations: [ + { name: 'MAXDOP', valueForPrimary: '', valueForSecondary: '' }, + { name: 'legacy_cardinality_estimation', valueForPrimary: 'ON', valueForSecondary: 'ON' }, + { name: 'parameter_sniffing', valueForPrimary: 'ON', valueForSecondary: 'OFF' }, + { name: 'query_optimizer_hotfixes', valueForPrimary: 'ON', valueForSecondary: 'OFF' }, + { name: 'identity_cache', valueForPrimary: 'ON', valueForSecondary: 'ON' }, + { name: 'interleaved_execution_tvf', valueForPrimary: 'ON', valueForSecondary: 'ON' }, + { name: 'batch_mode_memory_grant_feedback', valueForPrimary: 'OFF', valueForSecondary: 'OFF' }, + { name: 'batch_mode_adaptive_joins', valueForPrimary: 'OFF', valueForSecondary: 'ON' }, + { name: 'tsql_scalar_udf_inlining', valueForPrimary: 'ON', valueForSecondary: 'ON' } + ] } - }; + } } private delayAndResolve(obj?: any): Promise { diff --git a/extensions/mssql/src/objectManagement/ui/databaseDialog.ts b/extensions/mssql/src/objectManagement/ui/databaseDialog.ts index 56c32c97a4..bdaee2c7bf 100644 --- a/extensions/mssql/src/objectManagement/ui/databaseDialog.ts +++ b/extensions/mssql/src/objectManagement/ui/databaseDialog.ts @@ -5,19 +5,26 @@ import * as azdata from 'azdata'; import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase'; -import { DefaultInputWidth } from '../../ui/dialogBase'; +import { DefaultInputWidth, DefaultTableWidth, getTableHeight } from '../../ui/dialogBase'; import { IObjectManagementService } from 'mssql'; import * as localizedConstants from '../localizedConstants'; -import { CreateDatabaseDocUrl, DatabaseGeneralPropertiesDocUrl, DatabaseOptionsPropertiesDocUrl } from '../constants'; -import { Database, DatabaseViewInfo } from '../interfaces'; +import { CreateDatabaseDocUrl, DatabaseGeneralPropertiesDocUrl, DatabaseOptionsPropertiesDocUrl, DatabaseScopedConfigurationPropertiesDocUrl } from '../constants'; +import { Database, DatabaseScopedConfigurationsInfo, DatabaseViewInfo } from '../interfaces'; import { convertNumToTwoDecimalStringInMB } from '../utils'; import { isUndefinedOrNull } from '../../types'; +import { deepClone } from '../../util/objects'; + +const MAXDOP_Max_Limit = 32767; +const PAUSED_RESUMABLE_INDEX_Max_Limit = 71582; +const DscTableRowLength = 15; export class DatabaseDialog extends ObjectManagementDialogBase { // Database Properties tabs private generalTab: azdata.Tab; private optionsTab: azdata.Tab; + private dscTab: azdata.Tab; private optionsTabSectionsContainer: azdata.Component[] = []; + private activeTabId: string; // Database properties options // General Tab @@ -49,8 +56,26 @@ export class DatabaseDialog extends ObjectManagementDialogBase { @@ -503,6 +548,333 @@ export class DatabaseDialog extends ObjectManagementDialogBase { + this.dscOriginalData = deepClone(this.objectInfo.databaseScopedConfigurations); + const dscNameColumn: azdata.TableColumn = { + type: azdata.ColumnType.text, + value: localizedConstants.DatabaseScopedOptionsColumnHeader, + width: 220 + }; + const primaryValueColumn: azdata.TableColumn = { + type: azdata.ColumnType.text, + value: localizedConstants.ValueForPrimaryColumnHeader, + width: 105 + }; + const secondaryValueColumn: azdata.TableColumn = { + type: azdata.ColumnType.text, + value: localizedConstants.ValueForSecondaryColumnHeader, + width: 105 + }; + + this.dscTable = this.modelView.modelBuilder.table().withProps({ + columns: [dscNameColumn, primaryValueColumn, secondaryValueColumn], + data: this.objectInfo.databaseScopedConfigurations.map(metaData => { + return [metaData.name, + metaData.valueForPrimary, + metaData.valueForSecondary] + }), + height: getTableHeight(this.objectInfo.databaseScopedConfigurations.length, 1, DscTableRowLength), + width: DefaultTableWidth + }).component(); + + this.dscTabSectionsContainer.push(this.createGroup('', [this.dscTable], true)); + this.disposables.push( + this.dscTable.onRowSelected( + async () => { + // When refreshing the data on primary/secondary updates, we dont need to validate/toggle inputs again + if (this.currentRowId !== this.dscTable.selectedRows[0]) { + this.currentRowId = this.dscTable.selectedRows[0]; + await this.validateUpdateToggleDscPrimaryAndSecondaryOptions(); + } + + // This sets the focus to the primary/secondary inputs on data refresh + if (!isUndefinedOrNull(this.setFocusToInput)) { + await this.setFocusToInput.focus(); + } + } + ) + ); + } + + /** + * Validating the selected database scoped configuration and updating the primary and secondary dropdown options and their selected values + */ + private async validateUpdateToggleDscPrimaryAndSecondaryOptions(): Promise { + // Update the primary and secondary dropdown options based on the selected database scoped configuration + this.currentRowObjectInfo = this.objectInfo.databaseScopedConfigurations[this.currentRowId]; + const isSecondaryCheckboxChecked = this.currentRowObjectInfo.valueForPrimary === this.currentRowObjectInfo.valueForSecondary; + await this.hideDropdownAndInputSections(); + + // Cannot set the 'ELEVATE_ONLINE (11) and ELEVATE_RESUMABLE (12)' option for the secondaries replica while this option is only allowed to be set for the primary + if (this.currentRowObjectInfo.id === 11 || this.currentRowObjectInfo.id === 12) { + await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' }); + if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscElevateOptions) || + this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) { + await this.valueForPrimaryDropdown.updateProperties({ + values: this.viewInfo.dscElevateOptions + , value: this.currentRowObjectInfo.valueForPrimary + }); + } + } + // MAXDOP (1) option accepts both number and 'OFF' as primary values, and secondary value accepts only PRIMARY as value + else if (this.currentRowObjectInfo.id === 1) { + await this.showInputSection(isSecondaryCheckboxChecked); + await this.valueForPrimaryInput.updateProperties({ + value: this.currentRowObjectInfo.valueForPrimary + , max: MAXDOP_Max_Limit + }); + await this.valueForSecondaryInput.updateProperties({ + value: this.currentRowObjectInfo.valueForSecondary + , max: MAXDOP_Max_Limit + }); + } + // Cannot set the 'AUTO_ABORT_PAUSED_INDEX (25)' option for the secondaries replica while this option is only allowed to be set for the primary. + else if (this.currentRowObjectInfo.id === 25) { + await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-175px' }); + await this.valueForPrimaryInput.updateProperties({ + value: this.currentRowObjectInfo.valueForPrimary + , max: PAUSED_RESUMABLE_INDEX_Max_Limit + }); + } + // Can only set OFF/Azure blob storage endpoint to the 'LEDGER_DIGEST_STORAGE_ENDPOINT (38)'s primary and secondary values + else if (this.currentRowObjectInfo.id === 38) { + await this.showDropdownsSection(isSecondaryCheckboxChecked); + if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify([this.viewInfo.dscOnOffOptions[1]]) || + this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) { + await this.valueForPrimaryDropdown.updateProperties({ + values: [this.viewInfo.dscOnOffOptions[1]] // Only OFF is allowed for primary value + , value: this.currentRowObjectInfo.valueForPrimary + , editable: true // This is to allow the user to enter the Azure blob storage endpoint + }); + } + if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify([this.viewInfo.dscOnOffOptions[1]]) || + this.valueForSecondaryDropdown.value !== this.currentRowObjectInfo.valueForSecondary) { + await this.valueForSecondaryDropdown.updateProperties({ + values: [this.viewInfo.dscOnOffOptions[1]] // Only OFF is allowed for secondary value + , value: this.currentRowObjectInfo.valueForSecondary + , editable: true // This is to allow the user to enter the Azure blob storage endpoint + }); + } + } + // Cannot set the 'IDENTITY_CACHE (6)' option for the secondaries replica while this option is only allowed to be set for the primary. + // Cannot set the 'GLOBAL_TEMPORARY_TABLE_AUTO_DROP (21)' option for the secondaries replica while this option is only allowed to be set for the primary. + else if (this.currentRowObjectInfo.id === 6 || this.currentRowObjectInfo.id === 21) { + await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' }); + if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) || + this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) { + await this.valueForPrimaryDropdown.updateProperties({ + values: this.viewInfo.dscOnOffOptions + , value: this.currentRowObjectInfo.valueForPrimary + }); + } + } + // DW_COMPATIBILITY_LEVEL (26) options accepts 1(Enabled) or 0(Disabled) values as primary and secondary values + else if (this.currentRowObjectInfo.id === 26) { + await this.showDropdownsSection(isSecondaryCheckboxChecked); + if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscEnableDisableOptions) || + this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) { + await this.valueForPrimaryDropdown.updateProperties({ + values: this.viewInfo.dscEnableDisableOptions + , value: this.currentRowObjectInfo.valueForPrimary + }); + } + if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify(this.viewInfo.dscEnableDisableOptions) || + this.valueForSecondaryDropdown.value !== this.currentRowObjectInfo.valueForSecondary) { + await this.valueForSecondaryDropdown.updateProperties({ + values: this.viewInfo.dscEnableDisableOptions + , value: this.currentRowObjectInfo.valueForSecondary + }); + } + } + // All other options accepts primary and seconday values as ON/OFF/PRIMARY(only secondary) + else { + await this.showDropdownsSection(isSecondaryCheckboxChecked); + if (JSON.stringify(this.valueForPrimaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) || + this.valueForPrimaryDropdown.value !== this.currentRowObjectInfo.valueForPrimary) { + await this.valueForPrimaryDropdown.updateProperties({ + values: this.viewInfo.dscOnOffOptions + , value: this.currentRowObjectInfo.valueForPrimary + }); + } + if (JSON.stringify(this.valueForSecondaryDropdown.values) !== JSON.stringify(this.viewInfo.dscOnOffOptions) || + this.valueForSecondaryDropdown.value !== this.currentRowObjectInfo.valueForSecondary) { + await this.valueForSecondaryDropdown.updateProperties({ + values: this.viewInfo.dscOnOffOptions + , value: this.currentRowObjectInfo.valueForSecondary + }); + } + } + } + + /** + * Initializes primary and secondary values of Input type + * @returns GroupContainer for primary value and secondary value + */ + private async initializeDscValueInputTypeSection(): Promise { + // Primary value + this.valueForPrimaryInput = this.createInputBox(async (newValue) => { + if (this.currentRowObjectInfo.valueForPrimary !== newValue) { + this.currentRowObjectInfo.valueForPrimary = newValue; + if (this.dscTable.data[this.currentRowId][1] !== newValue) { + this.dscTable.data[this.currentRowId][1] = newValue; + } + // Update the secondary value with the primary, when the set seconadry checkbox is checked + if (this.setSecondaryCheckboxForInputType.checked && this.currentRowObjectInfo.id !== 25) { + this.currentRowObjectInfo.valueForSecondary = newValue; + this.dscTable.data[this.currentRowId][2] = newValue; + } + await this.updateDscTable(this.dscTable.data, this.valueForPrimaryInput); + } + }, { + ariaLabel: localizedConstants.ValueForPrimaryColumnHeader, + inputType: 'number', + enabled: true, + value: '', + width: 150, + min: 0 + }); + const primaryContainer = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryInput); + this.dscPrimaryValueInputGroup = this.createGroup('', [primaryContainer], false, true); + await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden' }); + + // Apply Primary To Secondary checkbox + this.setSecondaryCheckboxForInputType = this.createCheckbox(localizedConstants.SetSecondaryText, async (checked) => { + await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': checked ? 'hidden' : 'visible' }); + this.currentRowObjectInfo.valueForSecondary = checked ? this.currentRowObjectInfo.valueForPrimary : this.dscOriginalData[this.currentRowId].valueForSecondary; + await this.valueForSecondaryInput.updateProperties({ value: this.currentRowObjectInfo.valueForSecondary }); + if (this.dscTable.data[this.currentRowId][2] !== this.currentRowObjectInfo.valueForSecondary) { + this.dscTable.data[this.currentRowId][2] = this.currentRowObjectInfo.valueForSecondary; + await this.updateDscTable(this.dscTable.data); + } + }, true); + this.dscSecondaryCheckboxForInputGroup = this.createGroup('', [this.setSecondaryCheckboxForInputType], false, true); + await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'hidden' }); + + // Value for Secondary + this.valueForSecondaryInput = this.createInputBox(async (newValue) => { + this.currentRowObjectInfo.valueForSecondary = newValue; + if (this.dscTable.data[this.currentRowId][2] !== newValue) { + this.dscTable.data[this.currentRowId][2] = newValue; + await this.updateDscTable(this.dscTable.data, this.valueForSecondaryInput); + } + }, { + ariaLabel: localizedConstants.ValueForSecondaryColumnHeader, + inputType: 'number', + enabled: true, + value: '', + width: 150, + min: 0 + }); + const secondaryContainer = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryInput); + this.dscSecondaryValueInputGroup = this.createGroup('', [secondaryContainer], false, true); + await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden' }); + + const maxDopGroup = this.createGroup('', [this.dscPrimaryValueInputGroup, this.dscSecondaryCheckboxForInputGroup, this.dscSecondaryValueInputGroup], false, true); + await maxDopGroup.updateCssStyles({ 'margin-left': '-10px' }); + return maxDopGroup; + } + + /** + * Initializes primary and secondary values of Dropdown type + * @returns GroupContainer of primary and secondary values + */ + private async initializeDscValueDropdownTypeSection(): Promise { + // Configurations that won't support secondary value update + const dscConfigurationsWithoutSecondaryValue = [6, 11, 12, 21]; + // Value for Primary + this.valueForPrimaryDropdown = this.createDropdown(localizedConstants.ValueForPrimaryColumnHeader, async (newValue) => { + if (this.currentRowObjectInfo.valueForPrimary !== newValue) { + this.currentRowObjectInfo.valueForPrimary = newValue; + this.dscTable.data[this.currentRowId][1] = newValue; + // Update the secondary value with the primary, when the set seconadry checkbox is checked + if (this.setSecondaryCheckboxForDropdowns.checked && + !dscConfigurationsWithoutSecondaryValue.includes(this.currentRowObjectInfo.id)) { + this.currentRowObjectInfo.valueForSecondary = newValue; + this.dscTable.data[this.currentRowId][2] = newValue; + } + await this.updateDscTable(this.dscTable.data); + } + }, [], '', true, 150) + const primaryContainer = this.createLabelInputContainer(localizedConstants.ValueForPrimaryColumnHeader, this.valueForPrimaryDropdown); + this.dscPrimaryValueDropdownGroup = this.createGroup('', [primaryContainer], false, true); + await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + + // Apply Primary To Secondary checkbox + this.setSecondaryCheckboxForDropdowns = this.createCheckbox(localizedConstants.SetSecondaryText, async (checked) => { + await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': checked ? 'hidden' : 'visible' }); + this.currentRowObjectInfo.valueForSecondary = checked ? this.currentRowObjectInfo.valueForPrimary : this.dscOriginalData[this.currentRowId].valueForSecondary; + await this.valueForSecondaryDropdown.updateProperties({ value: this.currentRowObjectInfo.valueForSecondary }); + }, true); + this.dscSecondaryCheckboxForDropdownGroup = this.createGroup('', [this.setSecondaryCheckboxForDropdowns], false, true); + await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + + // Value for Secondary + this.valueForSecondaryDropdown = this.createDropdown(localizedConstants.ValueForSecondaryColumnHeader, async (newValue) => { + if (!isUndefinedOrNull(newValue)) { + this.currentRowObjectInfo.valueForSecondary = newValue as string; + if (this.dscTable.data[this.currentRowId][2] !== newValue) { + this.dscTable.data[this.currentRowId][2] = newValue; + await this.updateDscTable(this.dscTable.data); + } + } + }, [], '', true, 150); + const secondaryContainer = this.createLabelInputContainer(localizedConstants.ValueForSecondaryColumnHeader, this.valueForSecondaryDropdown); + this.dscSecondaryValueDropdownGroup = this.createGroup('', [secondaryContainer], false, true); + await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + + const valueGroup = this.createGroup('', [this.dscPrimaryValueDropdownGroup, this.dscSecondaryCheckboxForDropdownGroup, this.dscSecondaryValueDropdownGroup], true, true); + await valueGroup.updateCssStyles({ 'margin-left': '-10px' }); + return valueGroup; + } + + /** + * Make the dropdowns section for the selected database scoped configuration visible + * @param isSecondaryCheckboxChecked - Whether the secondary checkbox is checked or not + */ + private async showDropdownsSection(isSecondaryCheckboxChecked: boolean): Promise { + this.setSecondaryCheckboxForDropdowns.checked = isSecondaryCheckboxChecked; + await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'visible' }); + await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'visible' }); + await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': isSecondaryCheckboxChecked ? 'hidden' : 'visible' }); + } + + /** + * Make the input section for the selected database scoped configuration visible + * @param isSecondaryCheckboxChecked - Whether the secondary checkbox is checked or not + */ + private async showInputSection(isSecondaryCheckboxChecked: boolean): Promise { + this.setSecondaryCheckboxForInputType.checked = isSecondaryCheckboxChecked; + await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-175px' }); + await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'visible', 'margin-top': '-120px' }); + await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': isSecondaryCheckboxChecked ? 'hidden' : 'visible', 'margin-top': '-85px' }); + } + + /** + * Set all primary and secondary groups to hidden + */ + private async hideDropdownAndInputSections(): Promise { + await this.dscPrimaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' }); + await this.dscSecondaryCheckboxForInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' }); + await this.dscSecondaryValueInputGroup.updateCssStyles({ 'visibility': 'hidden', 'margin-top': '0px' }); + await this.dscPrimaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + await this.dscSecondaryCheckboxForDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + await this.dscSecondaryValueDropdownGroup.updateCssStyles({ 'visibility': 'hidden' }); + } + + /** + * Updates the data to the table and sets the focus to the selected row + * @param data - Modified data to be set in the table + */ + private async updateDscTable(data: any[][], inputToBeFocused: azdata.InputBoxComponent = undefined): Promise { + // Set the focus to the selected input box + this.setFocusToInput = inputToBeFocused; + await this.setTableData(this.dscTable, data, DscTableRowLength); + // Restore the focus to previously selected row. + this.dscTable.setActiveCell(this.currentRowId, 0); + } + // #endregion + private initializeConfigureSLOSection(): azdata.GroupContainer { let containers: azdata.Component[] = []; if (this.viewInfo.azureEditions?.length > 0) {