Dev/brih/task/make dropdowns searchable (#15615)

* make dropdown controls editable, searchable

* updte method name and return type

* update error message, and dropdown index selection logic

* address review feedback
This commit is contained in:
brian-harris
2021-06-07 17:55:08 -07:00
committed by GitHub
parent f7dc9ec2be
commit d8b693341e
8 changed files with 171 additions and 84 deletions

View File

@@ -3,6 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { CategoryValue, DropDownComponent } from 'azdata';
import { DAYS, HRS, MINUTE, SEC } from '../constants/strings'; import { DAYS, HRS, MINUTE, SEC } from '../constants/strings';
import { AdsMigrationStatus } from '../dialog/migrationStatus/migrationStatusDialogModel'; import { AdsMigrationStatus } from '../dialog/migrationStatus/migrationStatusDialogModel';
import { MigrationContext } from '../models/migrationLocalStorage'; import { MigrationContext } from '../models/migrationLocalStorage';
@@ -120,3 +121,16 @@ export function filterMigrations(databaseMigrations: MigrationContext[], statusF
} }
return filteredMigration; return filteredMigration;
} }
export function selectDropDownIndex(dropDown: DropDownComponent, index: number): void {
if (index >= 0 && dropDown.values && index <= dropDown.values.length - 1) {
const value = dropDown.values[index];
dropDown.value = value as CategoryValue;
}
}
export function findDropDownItemIndex(dropDown: DropDownComponent, value: string): number {
return dropDown.values &&
dropDown.values.findIndex((v: any) => ((v as CategoryValue)?.displayName?.toLowerCase() === value?.toLowerCase())) ||
-1;
}

View File

@@ -12,6 +12,7 @@ import * as os from 'os';
import { azureResource } from 'azureResource'; import { azureResource } from 'azureResource';
import { IntergrationRuntimePage } from '../../wizard/integrationRuntimePage'; import { IntergrationRuntimePage } from '../../wizard/integrationRuntimePage';
import { IconPathHelper } from '../../constants/iconPathHelper'; import { IconPathHelper } from '../../constants/iconPathHelper';
import { selectDropDownIndex } from '../../api/utils';
export class CreateSqlMigrationServiceDialog { export class CreateSqlMigrationServiceDialog {
@@ -174,7 +175,9 @@ export class CreateSqlMigrationServiceDialog {
}).component(); }).component();
this.migrationServiceResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({ this.migrationServiceResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({
required: true required: true,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
const migrationServiceNameLabel = this._view.modelBuilder.text().withProps({ const migrationServiceNameLabel = this._view.modelBuilder.text().withProps({
@@ -252,7 +255,7 @@ export class CreateSqlMigrationServiceDialog {
private async populateSubscriptions(): Promise<void> { private async populateSubscriptions(): Promise<void> {
this.migrationServiceResourceGroupDropdown.loading = true; this.migrationServiceResourceGroupDropdown.loading = true;
this.migrationServiceSubscription.value = this.migrationStateModel._targetSubscription.name; this.migrationServiceSubscription.value = this.migrationStateModel._targetSubscription.name;
this.populateResourceGroups(); await this.populateResourceGroups();
} }
private async populateResourceGroups(): Promise<void> { private async populateResourceGroups(): Promise<void> {
@@ -276,6 +279,7 @@ export class CreateSqlMigrationServiceDialog {
]; ];
} }
this.migrationServiceResourceGroupDropdown.values = resourceGroupDropdownValues; this.migrationServiceResourceGroupDropdown.values = resourceGroupDropdownValues;
selectDropDownIndex(this.migrationServiceResourceGroupDropdown, 0);
this.migrationServiceResourceGroupDropdown.loading = false; this.migrationServiceResourceGroupDropdown.loading = false;
} }

View File

@@ -724,8 +724,9 @@ export class MigrationStateModel implements Model, vscode.Disposable {
vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1} - {2}', this._migrationDbs[i], this._targetServerInstance.name, this._targetDatabaseNames[i])); vscode.window.showInformationMessage(localize("sql.migration.starting.migration.message", 'Starting migration for database {0} to {1} - {2}', this._migrationDbs[i], this._targetServerInstance.name, this._targetDatabaseNames[i]));
} }
} catch (e) { } catch (e) {
vscode.window.showErrorMessage(
localize('sql.migration.starting.migration.error', "An error occurred while starting the migration: '{0}'", e.message));
console.log(e); console.log(e);
vscode.window.showInformationMessage(e);
} }
vscode.commands.executeCommand('sqlmigration.refreshMigrationTiles'); vscode.commands.executeCommand('sqlmigration.refreshMigrationTiles');

View File

@@ -9,7 +9,7 @@ import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine'; import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../constants/strings'; import * as constants from '../constants/strings';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { deepClone } from '../api/utils'; import { deepClone, findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
export class AccountsSelectionPage extends MigrationWizardPage { export class AccountsSelectionPage extends MigrationWizardPage {
private _azureAccountsDropdown!: azdata.DropDownComponent; private _azureAccountsDropdown!: azdata.DropDownComponent;
@@ -45,7 +45,9 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this._azureAccountsDropdown = view.modelBuilder.dropDown() this._azureAccountsDropdown = view.modelBuilder.dropDown()
.withProps({ .withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}) })
.withValidation((c) => { .withValidation((c) => {
if (c.value) { if (c.value) {
@@ -71,13 +73,15 @@ export class AccountsSelectionPage extends MigrationWizardPage {
}).component(); }).component();
this._azureAccountsDropdown.onValueChanged(async (value) => { this._azureAccountsDropdown.onValueChanged(async (value) => {
if (value.selected) { const selectedIndex = findDropDownItemIndex(this._azureAccountsDropdown, value);
const selectedAzureAccount = this.migrationStateModel.getAccount(value.index); if (selectedIndex > -1) {
const selectedAzureAccount = this.migrationStateModel.getAccount(selectedIndex);
// Making a clone of the account object to preserve the original tenants // Making a clone of the account object to preserve the original tenants
this.migrationStateModel._azureAccount = deepClone(selectedAzureAccount); this.migrationStateModel._azureAccount = deepClone(selectedAzureAccount);
if (this.migrationStateModel._azureAccount.properties.tenants.length > 1) { if (this.migrationStateModel._azureAccount.properties.tenants.length > 1) {
this.migrationStateModel._accountTenants = selectedAzureAccount.properties.tenants; this.migrationStateModel._accountTenants = selectedAzureAccount.properties.tenants;
this._accountTenantDropdown.values = await this.migrationStateModel.getTenantValues(); this._accountTenantDropdown.values = await this.migrationStateModel.getTenantValues();
selectDropDownIndex(this._accountTenantDropdown, 0);
this._accountTenantFlexContainer.updateCssStyles({ this._accountTenantFlexContainer.updateCssStyles({
'display': 'inline' 'display': 'inline'
}); });
@@ -89,7 +93,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this.migrationStateModel._subscriptions = undefined!; this.migrationStateModel._subscriptions = undefined!;
this.migrationStateModel._targetSubscription = undefined!; this.migrationStateModel._targetSubscription = undefined!;
this.migrationStateModel._databaseBackup.subscription = undefined!; this.migrationStateModel._databaseBackup.subscription = undefined!;
this._azureAccountsDropdown.validate(); await this._azureAccountsDropdown.validate();
} }
}); });
@@ -140,7 +144,9 @@ export class AccountsSelectionPage extends MigrationWizardPage {
}).component(); }).component();
this._accountTenantDropdown = view.modelBuilder.dropDown().withProps({ this._accountTenantDropdown = view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._accountTenantDropdown.onValueChanged(value => { this._accountTenantDropdown.onValueChanged(value => {
@@ -148,8 +154,9 @@ export class AccountsSelectionPage extends MigrationWizardPage {
* Replacing all the tenants in azure account with the tenant user has selected. * Replacing all the tenants in azure account with the tenant user has selected.
* All azure requests will only run on this tenant from now on * All azure requests will only run on this tenant from now on
*/ */
if (value.selected) { const selectedIndex = findDropDownItemIndex(this._accountTenantDropdown, value);
this.migrationStateModel._azureAccount.properties.tenants = [this.migrationStateModel.getTenant(value.index)]; if (selectedIndex > -1) {
this.migrationStateModel._azureAccount.properties.tenants = [this.migrationStateModel.getTenant(selectedIndex)];
this.migrationStateModel._subscriptions = undefined!; this.migrationStateModel._subscriptions = undefined!;
this.migrationStateModel._targetSubscription = undefined!; this.migrationStateModel._targetSubscription = undefined!;
this.migrationStateModel._databaseBackup.subscription = undefined!; this.migrationStateModel._databaseBackup.subscription = undefined!;
@@ -184,6 +191,8 @@ export class AccountsSelectionPage extends MigrationWizardPage {
} finally { } finally {
this._azureAccountsDropdown.loading = false; this._azureAccountsDropdown.loading = false;
} }
selectDropDownIndex(this._azureAccountsDropdown, 0);
} }
public async onPageEnter(): Promise<void> { public async onPageEnter(): Promise<void> {

View File

@@ -11,6 +11,8 @@ import { Blob, MigrationSourceAuthenticationType, MigrationStateModel, Migration
import * as constants from '../constants/strings'; import * as constants from '../constants/strings';
import { IconPathHelper } from '../constants/iconPathHelper'; import { IconPathHelper } from '../constants/iconPathHelper';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
export class DatabaseBackupPage extends MigrationWizardPage { export class DatabaseBackupPage extends MigrationWizardPage {
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
@@ -392,6 +394,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
private createTargetDatabaseContainer(): azdata.FlexContainer { private createTargetDatabaseContainer(): azdata.FlexContainer {
const WIZARD_INPUT_COMPONENT_WIDTH = '200px';
const headerCssStyles: azdata.CssStyles = { const headerCssStyles: azdata.CssStyles = {
'border': 'none', 'border': 'none',
'font-size': '13px', 'font-size': '13px',
@@ -433,7 +436,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
rowCssStyles: rowCssStyle, rowCssStyles: rowCssStyle,
headerCssStyles: headerCssStyles, headerCssStyles: headerCssStyles,
isReadOnly: true, isReadOnly: true,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}, },
{ {
displayName: constants.TARGET_DATABASE_NAME, displayName: constants.TARGET_DATABASE_NAME,
@@ -441,7 +444,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
rowCssStyles: rowCssStyle, rowCssStyles: rowCssStyle,
headerCssStyles: headerCssStyles, headerCssStyles: headerCssStyles,
isReadOnly: true, isReadOnly: true,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}, },
{ {
displayName: constants.RESOURCE_GROUP, displayName: constants.RESOURCE_GROUP,
@@ -449,7 +452,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
rowCssStyles: rowCssStyle, rowCssStyles: rowCssStyle,
headerCssStyles: headerCssStyles, headerCssStyles: headerCssStyles,
isReadOnly: true, isReadOnly: true,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}, },
{ {
displayName: constants.STORAGE_ACCOUNT, displayName: constants.STORAGE_ACCOUNT,
@@ -457,7 +460,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
rowCssStyles: rowCssStyle, rowCssStyles: rowCssStyle,
headerCssStyles: headerCssStyles, headerCssStyles: headerCssStyles,
isReadOnly: true, isReadOnly: true,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}, },
{ {
displayName: constants.BLOB_CONTAINER, displayName: constants.BLOB_CONTAINER,
@@ -465,7 +468,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
rowCssStyles: rowCssStyle, rowCssStyles: rowCssStyle,
headerCssStyles: headerCssStyles, headerCssStyles: headerCssStyles,
isReadOnly: true, isReadOnly: true,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
} }
] ]
}).component(); }).component();
@@ -551,12 +554,15 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
}).component(); }).component();
this._networkShareStorageAccountResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({ this._networkShareStorageAccountResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._networkShareStorageAccountResourceGroupDropdown.onValueChanged(e => { this._networkShareStorageAccountResourceGroupDropdown.onValueChanged(async (value) => {
if (e.selected) { const selectedIndex = findDropDownItemIndex(this._networkShareStorageAccountResourceGroupDropdown, value);
this.migrationStateModel._databaseBackup.networkShare.resourceGroup = this.migrationStateModel.getAzureResourceGroup(e.index); if (selectedIndex > -1) {
this.loadNetworkShareStorageDropdown(); this.migrationStateModel._databaseBackup.networkShare.resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
await this.loadNetworkShareStorageDropdown();
} }
}); });
@@ -572,11 +578,14 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._networkShareContainerStorageAccountDropdown = this._view.modelBuilder.dropDown() this._networkShareContainerStorageAccountDropdown = this._view.modelBuilder.dropDown()
.withProps({ .withProps({
required: true, required: true,
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => { this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => {
if (value.selected) { const selectedIndex = findDropDownItemIndex(this._networkShareContainerStorageAccountDropdown, value);
this.migrationStateModel._databaseBackup.networkShare.storageAccount = this.migrationStateModel.getStorageAccount(value.index); if (selectedIndex > -1) {
this.migrationStateModel._databaseBackup.networkShare.storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex);
} }
}); });
@@ -587,8 +596,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
height: 25 height: 25
}).component(); }).component();
this._networkShareContainerStorageAccountRefreshButton.onDidClick((e) => { this._networkShareContainerStorageAccountRefreshButton.onDidClick(async (value) => {
this.loadNetworkShareStorageDropdown(); await this.loadNetworkShareStorageDropdown();
}); });
const storageAccountContainer = this._view.modelBuilder.flexContainer().component(); const storageAccountContainer = this._view.modelBuilder.flexContainer().component();
@@ -628,6 +637,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
public async onPageEnter(): Promise<void> { public async onPageEnter(): Promise<void> {
if (this.migrationStateModel.refreshDatabaseBackupPage) { if (this.migrationStateModel.refreshDatabaseBackupPage) {
const WIZARD_INPUT_COMPONENT_WIDTH = '200px';
const connectionProfile = await this.migrationStateModel.getSourceConnectionProfile(); const connectionProfile = await this.migrationStateModel.getSourceConnectionProfile();
const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>((await this.migrationStateModel.getSourceConnectionProfile()).providerId, azdata.DataProviderType.QueryProvider); const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>((await this.migrationStateModel.getSourceConnectionProfile()).providerId, azdata.DataProviderType.QueryProvider);
const query = 'select SUSER_NAME()'; const query = 'select SUSER_NAME()';
@@ -656,7 +666,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
const targetDatabaseInput = this._view.modelBuilder.inputBox().withProps({ const targetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
required: true, required: true,
value: db, value: db,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}).withValidation(c => { }).withValidation(c => {
if (this._networkShareTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values. if (this._networkShareTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR; c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR;
@@ -680,7 +690,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
const blobtargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({ const blobtargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
required: true, required: true,
value: db, value: db,
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH
}).withValidation(c => { }).withValidation(c => {
if (this._blobContainerTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values. if (this._blobContainerTargetDatabaseNames.filter(t => t.value === c.value).length > 1) { //Making sure no databases have duplicate values.
c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR; c.validationErrorMessage = constants.DUPLICATE_NAME_ERROR;
@@ -702,24 +712,31 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._blobContainerTargetDatabaseNames.push(blobtargetDatabaseInput); this._blobContainerTargetDatabaseNames.push(blobtargetDatabaseInput);
const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({ const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
blobContainerResourceDropdown.onValueChanged(e => { blobContainerResourceDropdown.onValueChanged(async (value) => {
if (e.selected && e.selected !== constants.RESOURCE_GROUP_NOT_FOUND) { const selectedIndex = findDropDownItemIndex(blobContainerResourceDropdown, value);
this.migrationStateModel._databaseBackup.blobs[index].resourceGroup = this.migrationStateModel.getAzureResourceGroup(e.index); if (selectedIndex > -1 && value !== constants.RESOURCE_GROUP_NOT_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
} }
this.loadblobStorageDropdown(index);
await this.loadblobStorageDropdown(index);
}); });
this._blobContainerResourceGroupDropdowns.push(blobContainerResourceDropdown); this._blobContainerResourceGroupDropdowns.push(blobContainerResourceDropdown);
const blobContainerStorageAccountDropdown = this._view.modelBuilder.dropDown() const blobContainerStorageAccountDropdown = this._view.modelBuilder.dropDown()
.withProps({ .withProps({
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
blobContainerStorageAccountDropdown.onValueChanged(async (value) => { blobContainerStorageAccountDropdown.onValueChanged(async (value) => {
if (value.selected && value.selected !== constants.NO_STORAGE_ACCOUNT_FOUND) { const selectedIndex = findDropDownItemIndex(blobContainerStorageAccountDropdown, value);
this.migrationStateModel._databaseBackup.blobs[index].storageAccount = this.migrationStateModel.getStorageAccount(value.index); if (selectedIndex > -1 && value !== constants.NO_STORAGE_ACCOUNT_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex);
} }
await this.loadBlobContainerDropdown(index); await this.loadBlobContainerDropdown(index);
}); });
@@ -727,11 +744,14 @@ export class DatabaseBackupPage extends MigrationWizardPage {
const blobContainerDropdown = this._view.modelBuilder.dropDown() const blobContainerDropdown = this._view.modelBuilder.dropDown()
.withProps({ .withProps({
width: '200px' width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
blobContainerDropdown.onValueChanged(async (value) => { blobContainerDropdown.onValueChanged(value => {
if (value.selected && value.selected !== constants.NO_BLOBCONTAINERS_FOUND) { const selectedIndex = findDropDownItemIndex(blobContainerStorageAccountDropdown, value);
this.migrationStateModel._databaseBackup.blobs[index].blobContainer = this.migrationStateModel.getBlobContainer(value.index); if (selectedIndex > -1 && value !== constants.NO_BLOBCONTAINERS_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].blobContainer = this.migrationStateModel.getBlobContainer(selectedIndex);
} }
}); });
this._blobContainerDropdowns.push(blobContainerDropdown); this._blobContainerDropdowns.push(blobContainerDropdown);
@@ -953,11 +973,12 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._networkShareStorageAccountResourceGroupDropdown.loading = true; this._networkShareStorageAccountResourceGroupDropdown.loading = true;
try { try {
this._networkShareStorageAccountResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription); this._networkShareStorageAccountResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
selectDropDownIndex(this._networkShareStorageAccountResourceGroupDropdown, 0);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {
this._networkShareStorageAccountResourceGroupDropdown.loading = false; this._networkShareStorageAccountResourceGroupDropdown.loading = false;
this.loadNetworkShareStorageDropdown(); await this.loadNetworkShareStorageDropdown();
} }
} }
@@ -965,6 +986,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._networkShareContainerStorageAccountDropdown.loading = true; this._networkShareContainerStorageAccountDropdown.loading = true;
try { try {
this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.networkShare.resourceGroup); this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.networkShare.resourceGroup);
selectDropDownIndex(this._networkShareContainerStorageAccountDropdown, 0);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {
@@ -976,7 +998,10 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._blobContainerResourceGroupDropdowns.forEach(v => v.loading = true); this._blobContainerResourceGroupDropdowns.forEach(v => v.loading = true);
try { try {
const resourceGroupValues = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription); const resourceGroupValues = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._databaseBackup.subscription);
this._blobContainerResourceGroupDropdowns.forEach(v => v.values = resourceGroupValues); this._blobContainerResourceGroupDropdowns.forEach(dropDown => {
dropDown.values = resourceGroupValues;
selectDropDownIndex(dropDown, 0);
});
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {
@@ -988,6 +1013,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
this._blobContainerStorageAccountDropdowns[index].loading = true; this._blobContainerStorageAccountDropdowns[index].loading = true;
try { try {
this._blobContainerStorageAccountDropdowns[index].values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index].resourceGroup); this._blobContainerStorageAccountDropdowns[index].values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index].resourceGroup);
selectDropDownIndex(this._blobContainerStorageAccountDropdowns[index], 0);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {
@@ -1000,6 +1026,7 @@ export class DatabaseBackupPage extends MigrationWizardPage {
try { try {
const blobContainerValues = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index].storageAccount); const blobContainerValues = await this.migrationStateModel.getBlobContainerValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.blobs[index].storageAccount);
this._blobContainerDropdowns[index].values = blobContainerValues; this._blobContainerDropdowns[index].values = blobContainerValues;
selectDropDownIndex(this._blobContainerDropdowns[index], 0);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} finally { } finally {

View File

@@ -12,6 +12,7 @@ import * as constants from '../constants/strings';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlManagedInstance, SqlMigrationService } from '../api/azure'; import { getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlManagedInstance, SqlMigrationService } from '../api/azure';
import { IconPathHelper } from '../constants/iconPathHelper'; import { IconPathHelper } from '../constants/iconPathHelper';
import { findDropDownItemIndex } from '../api/utils';
export class IntergrationRuntimePage extends MigrationWizardPage { export class IntergrationRuntimePage extends MigrationWizardPage {
@@ -174,12 +175,14 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
}).component(); }).component();
this._resourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({ this._resourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH, width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._resourceGroupDropdown.onValueChanged(async (value) => { this._resourceGroupDropdown.onValueChanged(async (value) => {
if (value) { const selectedIndex = findDropDownItemIndex(this._resourceGroupDropdown, value);
this.populateDms(value); if (selectedIndex > -1) {
await this.populateDms(value);
} }
}); });
@@ -193,7 +196,8 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
this._dmsDropdown = this._view.modelBuilder.dropDown().withProps({ this._dmsDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH, width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._dmsDropdown.onValueChanged(async (value) => { this._dmsDropdown.onValueChanged(async (value) => {
@@ -201,9 +205,11 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
this.wizard.message = { this.wizard.message = {
text: '' text: ''
}; };
const selectedIndex = (<azdata.CategoryValue[]>this._dmsDropdown.values)?.findIndex((v) => v.displayName === value); const selectedIndex = findDropDownItemIndex(this._dmsDropdown, value);
this.migrationStateModel._sqlMigrationService = this.migrationStateModel.getMigrationService(selectedIndex); if (selectedIndex > -1) {
this.loadMigrationServiceStatus(); this.migrationStateModel._sqlMigrationService = this.migrationStateModel.getMigrationService(selectedIndex);
await this.loadMigrationServiceStatus();
}
} }
}); });
@@ -395,10 +401,11 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
let index = 0; let index = 0;
if (resourceGroupName) { if (resourceGroupName) {
index = (<azdata.CategoryValue[]>this._resourceGroupDropdown.values).findIndex(v => v.displayName.toLowerCase() === resourceGroupName.toLowerCase()); index = findDropDownItemIndex(this._resourceGroupDropdown, resourceGroupName);
} }
if ((<azdata.CategoryValue>this._resourceGroupDropdown.value)?.displayName.toLowerCase() === (<azdata.CategoryValue>this._resourceGroupDropdown.values[index])?.displayName.toLowerCase()) { if ((<azdata.CategoryValue>this._resourceGroupDropdown.value)?.displayName.toLowerCase() === (<azdata.CategoryValue>this._resourceGroupDropdown.values[index])?.displayName.toLowerCase()) {
this.populateDms((<azdata.CategoryValue>this._resourceGroupDropdown.value)?.displayName); await this.populateDms((<azdata.CategoryValue>this._resourceGroupDropdown.value)?.displayName);
} else { } else {
this._resourceGroupDropdown.value = this._resourceGroupDropdown.values[index]; this._resourceGroupDropdown.value = this._resourceGroupDropdown.values[index];
} }
@@ -407,7 +414,6 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
} finally { } finally {
this._resourceGroupDropdown.loading = false; this._resourceGroupDropdown.loading = false;
} }
} }
public async populateDms(resourceGroupName: string): Promise<void> { public async populateDms(resourceGroupName: string): Promise<void> {
@@ -419,9 +425,9 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
this._dmsDropdown.values = await this.migrationStateModel.getSqlMigrationServiceValues(this.migrationStateModel._targetSubscription, <SqlManagedInstance>this.migrationStateModel._targetServerInstance, resourceGroupName); this._dmsDropdown.values = await this.migrationStateModel.getSqlMigrationServiceValues(this.migrationStateModel._targetSubscription, <SqlManagedInstance>this.migrationStateModel._targetServerInstance, resourceGroupName);
let index = -1; let index = -1;
if (this.migrationStateModel._sqlMigrationService) { if (this.migrationStateModel._sqlMigrationService) {
index = (<azdata.CategoryValue[]>this._dmsDropdown.values).findIndex(v => v.displayName.toLowerCase() === this.migrationStateModel._sqlMigrationService.name.toLowerCase()); index = findDropDownItemIndex(this._dmsDropdown, this.migrationStateModel._sqlMigrationService.name);
} }
if (index !== -1) { if (index > -1) {
this._dmsDropdown.value = this._dmsDropdown.values[index]; this._dmsDropdown.value = this._dmsDropdown.values[index];
} else { } else {
this._dmsDropdown.value = this._dmsDropdown.values[0]; this._dmsDropdown.value = this._dmsDropdown.values[0];

View File

@@ -12,6 +12,7 @@ import * as vscode from 'vscode';
import { EOL } from 'os'; import { EOL } from 'os';
import { IconPath, IconPathHelper } from '../constants/iconPathHelper'; import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils';
export interface Product { export interface Product {
type: MigrationTargetType; type: MigrationTargetType;
@@ -291,15 +292,16 @@ export class SKURecommendationPage extends MigrationWizardPage {
}).component(); }).component();
this._managedInstanceSubscriptionDropdown = this._view.modelBuilder.dropDown().withProps({ this._managedInstanceSubscriptionDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH, width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._managedInstanceSubscriptionDropdown.onValueChanged((e) => { this._managedInstanceSubscriptionDropdown.onValueChanged(async (value) => {
if (e) { const selectedIndex = findDropDownItemIndex(this._managedInstanceSubscriptionDropdown, value);
const selectedIndex = (<azdata.CategoryValue[]>this._managedInstanceSubscriptionDropdown.values)?.findIndex(v => v.displayName === e); if (selectedIndex > -1) {
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex); this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex);
this.migrationStateModel._targetServerInstance = undefined!; this.migrationStateModel._targetServerInstance = undefined!;
this.migrationStateModel._sqlMigrationService = undefined!; this.migrationStateModel._sqlMigrationService = undefined!;
this.populateLocationAndResourceGroupDropdown(); await this.populateLocationAndResourceGroupDropdown();
} }
}); });
@@ -312,12 +314,15 @@ export class SKURecommendationPage extends MigrationWizardPage {
} }
}).component(); }).component();
this._azureLocationDropdown = this._view.modelBuilder.dropDown().withProps({ this._azureLocationDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._azureLocationDropdown.onValueChanged((e) => { this._azureLocationDropdown.onValueChanged(async (value) => {
if (e.selected) { const selectedIndex = findDropDownItemIndex(this._azureLocationDropdown, value);
this.migrationStateModel._location = this.migrationStateModel.getLocation(e.index); if (selectedIndex > -1) {
this.populateResourceInstanceDropdown(); this.migrationStateModel._location = this.migrationStateModel.getLocation(selectedIndex);
await this.populateResourceInstanceDropdown();
} }
}); });
@@ -330,12 +335,15 @@ export class SKURecommendationPage extends MigrationWizardPage {
} }
}).component(); }).component();
this._azureResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({ this._azureResourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._azureResourceGroupDropdown.onValueChanged((e) => { this._azureResourceGroupDropdown.onValueChanged(async (value) => {
if (e.selected) { const selectedIndex = findDropDownItemIndex(this._azureResourceGroupDropdown, value);
this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(e.index); if (selectedIndex > -1) {
this.populateResourceInstanceDropdown(); this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
await this.populateResourceInstanceDropdown();
} }
}); });
this._resourceDropdownLabel = this._view.modelBuilder.text().withProps({ this._resourceDropdownLabel = this._view.modelBuilder.text().withProps({
@@ -348,17 +356,20 @@ export class SKURecommendationPage extends MigrationWizardPage {
}).component(); }).component();
this._resourceDropdown = this._view.modelBuilder.dropDown().withProps({ this._resourceDropdown = this._view.modelBuilder.dropDown().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
fireOnTextChange: true,
}).component(); }).component();
this._resourceDropdown.onValueChanged((e) => { this._resourceDropdown.onValueChanged(value => {
if (e?.selected && const selectedIndex = findDropDownItemIndex(this._resourceDropdown, value);
e.selected !== constants.NO_MANAGED_INSTANCE_FOUND && if (selectedIndex > -1 &&
e.selected !== constants.NO_VIRTUAL_MACHINE_FOUND) { value !== constants.NO_MANAGED_INSTANCE_FOUND &&
value !== constants.NO_VIRTUAL_MACHINE_FOUND) {
this.migrationStateModel._sqlMigrationServices = undefined!; this.migrationStateModel._sqlMigrationServices = undefined!;
if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) { if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) {
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getVirtualMachine(e.index); this.migrationStateModel._targetServerInstance = this.migrationStateModel.getVirtualMachine(selectedIndex);
} else { } else {
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(e.index); this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(selectedIndex);
} }
} }
}); });
@@ -425,11 +436,12 @@ export class SKURecommendationPage extends MigrationWizardPage {
this._resourceDropdown.loading = true; this._resourceDropdown.loading = true;
try { try {
this._managedInstanceSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues(); this._managedInstanceSubscriptionDropdown.values = await this.migrationStateModel.getSubscriptionsDropdownValues();
this._managedInstanceSubscriptionDropdown.value = this._managedInstanceSubscriptionDropdown.values[0]; selectDropDownIndex(this._managedInstanceSubscriptionDropdown, 0);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} finally { } finally {
this._managedInstanceSubscriptionDropdown.loading = false; this._managedInstanceSubscriptionDropdown.loading = false;
this._resourceDropdown.loading = false;
} }
} }
} }
@@ -439,7 +451,9 @@ export class SKURecommendationPage extends MigrationWizardPage {
this._azureLocationDropdown.loading = true; this._azureLocationDropdown.loading = true;
try { try {
this._azureResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription); this._azureResourceGroupDropdown.values = await this.migrationStateModel.getAzureResourceGroupDropdownValues(this.migrationStateModel._targetSubscription);
selectDropDownIndex(this._azureResourceGroupDropdown, 0);
this._azureLocationDropdown.values = await this.migrationStateModel.getAzureLocationDropdownValues(this.migrationStateModel._targetSubscription); this._azureLocationDropdown.values = await this.migrationStateModel.getAzureLocationDropdownValues(this.migrationStateModel._targetSubscription);
selectDropDownIndex(this._azureLocationDropdown, 0);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} finally { } finally {
@@ -449,8 +463,8 @@ export class SKURecommendationPage extends MigrationWizardPage {
} }
private async populateResourceInstanceDropdown(): Promise<void> { private async populateResourceInstanceDropdown(): Promise<void> {
this._resourceDropdown.loading = true;
try { try {
this._resourceDropdown.loading = true;
if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) { if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) {
this._resourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE; this._resourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_VIRTUAL_MACHINE;
this._resourceDropdown.values = await this.migrationStateModel.getSqlVirtualMachineValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup); this._resourceDropdown.values = await this.migrationStateModel.getSqlVirtualMachineValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup);
@@ -459,6 +473,8 @@ export class SKURecommendationPage extends MigrationWizardPage {
this._resourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE; this._resourceDropdownLabel.value = constants.AZURE_SQL_DATABASE_MANAGED_INSTANCE;
this._resourceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup); this._resourceDropdown.values = await this.migrationStateModel.getManagedInstanceValues(this.migrationStateModel._targetSubscription, this.migrationStateModel._location, this.migrationStateModel._resourceGroup);
} }
selectDropDownIndex(this._resourceDropdown, 0);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} finally { } finally {

View File

@@ -9,6 +9,7 @@ import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import { SUBSCRIPTION_SELECTION_PAGE_TITLE, SUBSCRIPTION_SELECTION_AZURE_ACCOUNT_TITLE, SUBSCRIPTION_SELECTION_AZURE_PRODUCT_TITLE, SUBSCRIPTION_SELECTION_AZURE_SUBSCRIPTION_TITLE } from '../constants/strings'; import { SUBSCRIPTION_SELECTION_PAGE_TITLE, SUBSCRIPTION_SELECTION_AZURE_ACCOUNT_TITLE, SUBSCRIPTION_SELECTION_AZURE_PRODUCT_TITLE, SUBSCRIPTION_SELECTION_AZURE_SUBSCRIPTION_TITLE } from '../constants/strings';
import { Disposable } from 'vscode'; import { Disposable } from 'vscode';
import { getSubscriptions, Subscription, getAvailableManagedInstanceProducts, AzureProduct, getAvailableSqlServers } from '../api/azure'; import { getSubscriptions, Subscription, getAvailableManagedInstanceProducts, AzureProduct, getAvailableSqlServers } from '../api/azure';
import { selectDropDownIndex } from '../api/utils';
interface GenericValue<T> extends azdata.CategoryValue { interface GenericValue<T> extends azdata.CategoryValue {
value: T; value: T;
@@ -37,7 +38,7 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
private async initialState(view: azdata.ModelView) { private async initialState(view: azdata.ModelView) {
this.accountDropDown = this.createAccountDropDown(view); this.accountDropDown = this.createAccountDropDown(view);
this.subscriptionDropDown = this.createSubscriptionDropDown(view); this.subscriptionDropDown = this.createSubscriptionDropDown(view);
this.productDropDown = this.createProdcutDropDown(view); this.productDropDown = this.createProductDropDown(view);
const form = view.modelBuilder.formContainer().withFormItems( const form = view.modelBuilder.formContainer().withFormItems(
[ [
@@ -53,10 +54,12 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
private createAccountDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> { private createAccountDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> {
const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({ const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({
values: [], values: [],
editable: true,
fireOnTextChange: true,
}); });
this.disposables.push(dropDown.component().onValueChanged(() => { this.disposables.push(dropDown.component().onValueChanged(async () => {
this.accountValueChanged().catch(console.error); await this.accountValueChanged().catch(console.error);
})); }));
return { return {
@@ -68,10 +71,12 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
private createSubscriptionDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> { private createSubscriptionDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> {
const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({ const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({
values: [], values: [],
editable: true,
fireOnTextChange: true,
}); });
this.disposables.push(dropDown.component().onValueChanged(() => { this.disposables.push(dropDown.component().onValueChanged(async () => {
this.subscriptionValueChanged().catch(console.error); await this.subscriptionValueChanged().catch(console.error);
})); }));
return { return {
@@ -80,9 +85,11 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
}; };
} }
private createProdcutDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> { private createProductDropDown(view: azdata.ModelView): azdata.FormComponent<azdata.DropDownComponent> {
const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({ const dropDown = view.modelBuilder.dropDown().withProperties<azdata.DropDownProperties>({
values: [], values: [],
editable: true,
fireOnTextChange: true,
}); });
return { return {
@@ -132,6 +139,7 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
}); });
this.accountDropDown!.component.values = values; this.accountDropDown!.component.values = values;
selectDropDownIndex(this.accountDropDown!.component, 0);
await this.accountValueChanged(); await this.accountValueChanged();
} }
@@ -145,6 +153,7 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
}); });
this.subscriptionDropDown!.component.values = values; this.subscriptionDropDown!.component.values = values;
selectDropDownIndex(this.subscriptionDropDown!.component, 0);
await this.subscriptionValueChanged(); await this.subscriptionValueChanged();
} }
@@ -158,6 +167,7 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
}); });
this.productDropDown!.component.values = values; this.productDropDown!.component.values = values;
selectDropDownIndex(this.productDropDown!.component, 0);
} }
public async onPageEnter(): Promise<void> { public async onPageEnter(): Promise<void> {