From 300bce40704b097948048b905b4e7d69b6574d94 Mon Sep 17 00:00:00 2001 From: Aasim Khan Date: Tue, 26 Jan 2021 10:50:02 -0800 Subject: [PATCH] Adding a temporary target selection page for sql migration (#14053) * Adding a temporary target selection page * Fixed the wizard page title --- .../sql-migration/src/models/strings.ts | 4 + .../src/wizard/tempTargetSelectionPage.ts | 138 ++++++++++++++++++ .../src/wizard/wizardController.ts | 3 + 3 files changed, 145 insertions(+) create mode 100644 extensions/sql-migration/src/wizard/tempTargetSelectionPage.ts diff --git a/extensions/sql-migration/src/models/strings.ts b/extensions/sql-migration/src/models/strings.ts index 24fab0d461..e7b5842a92 100644 --- a/extensions/sql-migration/src/models/strings.ts +++ b/extensions/sql-migration/src/models/strings.ts @@ -126,6 +126,10 @@ export const INVALID_CONTROLLER_NAME_ERROR = localize('sql.migration.invalid.con export const CONTROLLER_NOT_FOUND = localize('sql.migration.controller.not.found', "No Migration Controllers found. Please create a new one."); export const CONTROLLER_NOT_SETUP_ERROR = localize('sql.migration.controller.not.setup', "Please add a migration controller to proceed."); +export const MANAGED_INSTANCE = localize('sql.migration.managed.instance', "Azure SQL managed instance"); +export const NO_MANAGED_INSTANCE_FOUND = localize('sql.migration.no.managedInstance.found', "No managed instance found"); +export const TARGET_SELECTION_PAGE_TITLE = localize('sql.migration.target.page.title', "Choose the target Azure SQL"); + // common strings export const LEARN_MORE = localize('sql.migration.learn.more', "Learn more"); export const SUBSCRIPTION = localize('sql.migration.subscription', "Subscription"); diff --git a/extensions/sql-migration/src/wizard/tempTargetSelectionPage.ts b/extensions/sql-migration/src/wizard/tempTargetSelectionPage.ts new file mode 100644 index 0000000000..36a4b323ce --- /dev/null +++ b/extensions/sql-migration/src/wizard/tempTargetSelectionPage.ts @@ -0,0 +1,138 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as azdata from 'azdata'; +import { azureResource } from 'azureResource'; +import { getAvailableManagedInstanceProducts, getSubscriptions, SqlManagedInstance, Subscription } from '../api/azure'; +import { MigrationWizardPage } from '../models/migrationWizardPage'; +import { MigrationStateModel, StateChangeEvent } from '../models/stateMachine'; +import * as constants from '../models/strings'; + +export class TempTargetSelectionPage extends MigrationWizardPage { + + private _managedInstanceSubscriptionDropdown!: azdata.DropDownComponent; + private _managedInstanceDropdown!: azdata.DropDownComponent; + private _subscriptionDropdownValues: azdata.CategoryValue[] = []; + private _subscriptionMap: Map = new Map(); + + + constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { + super(wizard, azdata.window.createWizardPage(constants.TARGET_SELECTION_PAGE_TITLE), migrationStateModel); + } + + protected async registerContent(view: azdata.ModelView): Promise { + + const managedInstanceSubscriptionDropdownLabel = view.modelBuilder.text().withProps({ + value: constants.SUBSCRIPTION + }).component(); + this._managedInstanceSubscriptionDropdown = view.modelBuilder.dropDown().component(); + this._managedInstanceSubscriptionDropdown.onValueChanged((e) => { + this.populateManagedInstanceDropdown(); + }); + const managedInstanceDropdownLabel = view.modelBuilder.text().withProps({ + value: constants.MANAGED_INSTANCE + }).component(); + this._managedInstanceDropdown = view.modelBuilder.dropDown().component(); + + const targetContainer = view.modelBuilder.flexContainer().withItems( + [ + managedInstanceSubscriptionDropdownLabel, + this._managedInstanceSubscriptionDropdown, + managedInstanceDropdownLabel, + this._managedInstanceDropdown + ] + ).withLayout({ + flexFlow: 'column' + }).component(); + + const form = view.modelBuilder.formContainer() + .withFormItems( + [ + { + component: targetContainer + } + ] + ); + await view.initializeModel(form.component()); + } + public async onPageEnter(): Promise { + this.populateSubscriptionDropdown(); + } + public async onPageLeave(): Promise { + } + protected async handleStateChange(e: StateChangeEvent): Promise { + } + + private async populateSubscriptionDropdown(): Promise { + this._managedInstanceSubscriptionDropdown.loading = true; + this._managedInstanceDropdown.loading = true; + let subscriptions: azureResource.AzureResourceSubscription[] = []; + try { + subscriptions = await getSubscriptions(this.migrationStateModel.azureAccount); + subscriptions.forEach((subscription) => { + this._subscriptionMap.set(subscription.id, subscription); + this._subscriptionDropdownValues.push({ + name: subscription.id, + displayName: subscription.name + ' - ' + subscription.id, + }); + }); + + if (!this._subscriptionDropdownValues || this._subscriptionDropdownValues.length === 0) { + this._subscriptionDropdownValues = [ + { + displayName: constants.NO_SUBSCRIPTIONS_FOUND, + name: '' + } + ]; + } + + this._managedInstanceSubscriptionDropdown.values = this._subscriptionDropdownValues; + } catch (error) { + this.setEmptyDropdownPlaceHolder(this._managedInstanceSubscriptionDropdown, constants.NO_SUBSCRIPTIONS_FOUND); + this._managedInstanceDropdown.loading = false; + } + this.populateManagedInstanceDropdown(); + this._managedInstanceSubscriptionDropdown.loading = false; + } + + private async populateManagedInstanceDropdown(): Promise { + this._managedInstanceDropdown.loading = true; + let mis: SqlManagedInstance[] = []; + let miValues: azdata.CategoryValue[] = []; + try { + const subscriptionId = (this._managedInstanceSubscriptionDropdown.value).name; + + mis = await getAvailableManagedInstanceProducts(this.migrationStateModel.azureAccount, this._subscriptionMap.get(subscriptionId)!); + mis.forEach((mi) => { + miValues.push({ + name: mi.name, + displayName: mi.name + }); + }); + + if (!miValues || miValues.length === 0) { + miValues = [ + { + displayName: constants.NO_MANAGED_INSTANCE_FOUND, + name: '' + } + ]; + } + + this._managedInstanceDropdown.values = miValues; + } catch (error) { + this.setEmptyDropdownPlaceHolder(this._managedInstanceDropdown, constants.NO_MANAGED_INSTANCE_FOUND); + } + + this._managedInstanceDropdown.loading = false; + } + + private setEmptyDropdownPlaceHolder(dropDown: azdata.DropDownComponent, placeholder: string): void { + dropDown.values = [{ + displayName: placeholder, + name: '' + }]; + } +} diff --git a/extensions/sql-migration/src/wizard/wizardController.ts b/extensions/sql-migration/src/wizard/wizardController.ts index 5a49ecb874..46e8d96dd5 100644 --- a/extensions/sql-migration/src/wizard/wizardController.ts +++ b/extensions/sql-migration/src/wizard/wizardController.ts @@ -14,6 +14,7 @@ import { SKURecommendationPage } from './skuRecommendationPage'; import { DatabaseBackupPage } from './databaseBackupPage'; import { AccountsSelectionPage } from './accountsSelectionPage'; import { IntergrationRuntimePage } from './integrationRuntimePage'; +import { TempTargetSelectionPage } from './tempTargetSelectionPage'; export class WizardController { constructor(private readonly extensionContext: vscode.ExtensionContext) { @@ -38,12 +39,14 @@ export class WizardController { const skuRecommendationPage = new SKURecommendationPage(wizard, stateModel); // const subscriptionSelectionPage = new SubscriptionSelectionPage(wizard, stateModel); const azureAccountsPage = new AccountsSelectionPage(wizard, stateModel); + const tempTargetSelectionPage = new TempTargetSelectionPage(wizard, stateModel); const databaseBackupPage = new DatabaseBackupPage(wizard, stateModel); const integrationRuntimePage = new IntergrationRuntimePage(wizard, stateModel); const pages: MigrationWizardPage[] = [ // subscriptionSelectionPage, azureAccountsPage, + tempTargetSelectionPage, sourceConfigurationPage, skuRecommendationPage, databaseBackupPage,