diff --git a/extensions/sql-migration/src/constants/strings.ts b/extensions/sql-migration/src/constants/strings.ts index 2bb94050b1..c257ce6454 100644 --- a/extensions/sql-migration/src/constants/strings.ts +++ b/extensions/sql-migration/src/constants/strings.ts @@ -34,8 +34,9 @@ export const SUBSCRIPTION_SELECTION_AZURE_ACCOUNT_TITLE = localize('sql.migratio export const SUBSCRIPTION_SELECTION_AZURE_SUBSCRIPTION_TITLE = localize('sql.migration.wizard.subscription.azure.subscription.title', "Azure Subscription"); export const SUBSCRIPTION_SELECTION_AZURE_PRODUCT_TITLE = localize('sql.migration.wizard.subscription.azure.product.title', "Azure Product"); -export const CONGRATULATIONS = localize('sql.migration.generic.congratulations', "Congratulations!"); - +export const ASSESSMENT_COMPLETED = (serverName: string): string => { + return localize('sql.migration.generic.congratulations', "We have completed the assessment of your SQL Server Instance '{0}'.", serverName); +}; // Accounts page export const ACCOUNTS_SELECTION_PAGE_TITLE = localize('sql.migration.wizard.account.title', "Azure Account"); diff --git a/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts b/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts index fbb5344e51..c2b5acfa1d 100644 --- a/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts +++ b/extensions/sql-migration/src/dialog/assessmentResults/assessmentResultsDialog.ts @@ -31,10 +31,10 @@ export class AssessmentResultsDialog { private _tree: SqlDatabaseTree; - constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private skuRecommendationPage: SKURecommendationPage) { + constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private skuRecommendationPage: SKURecommendationPage, migrationType: string) { this._model = model; let assessmentData = this.parseData(this._model); - this._tree = new SqlDatabaseTree(this._model, assessmentData); + this._tree = new SqlDatabaseTree(this._model, assessmentData, migrationType); } private async initializeDialog(dialog: azdata.window.Dialog): Promise { diff --git a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts index 7299e6065c..12edee7320 100644 --- a/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts +++ b/extensions/sql-migration/src/dialog/assessmentResults/sqlDatabasesTree.ts @@ -31,11 +31,16 @@ export class SqlDatabaseTree extends AssessmentDialogComponent { private _objectDetailsName!: azdata.TextComponent; private _objectDetailsSample!: azdata.TextComponent; private _moreInfo!: azdata.TextComponent; + private _assessmentType!: string; - constructor(model: MigrationStateModel, assessmentData: Map) { + constructor(model: MigrationStateModel, assessmentData: Map, assessmentType: string) { super(); this._assessmentData = assessmentData; this._model = model; + this._assessmentType = assessmentType; + if (this._assessmentType === 'vm') { + this._assessmentData.clear(); + } } async createComponent(view: azdata.ModelView): Promise { @@ -147,7 +152,7 @@ export class SqlDatabaseTree extends AssessmentDialogComponent { this.databaseTable.component().dataValues?.push( [ { - value: false, + value: true, style: styleLeft }, { diff --git a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts index 40fa81a035..088628a2f5 100644 --- a/extensions/sql-migration/src/wizard/skuRecommendationPage.ts +++ b/extensions/sql-migration/src/wizard/skuRecommendationPage.ts @@ -34,6 +34,8 @@ export class SKURecommendationPage extends MigrationWizardPage { private _resourceDropdown!: azdata.DropDownComponent; private _view: azdata.ModelView | undefined; private _rbg!: azdata.RadioCardGroupComponent; + private _dbCount!: number; + private _serverName!: string; private async initialState(view: azdata.ModelView) { this._view = view; @@ -42,6 +44,7 @@ export class SKURecommendationPage extends MigrationWizardPage { this._chooseTargetComponent = this.createChooseTargetComponent(view); this._azureSubscriptionText = this.createAzureSubscriptionText(view); + const managedInstanceSubscriptionDropdownLabel = view.modelBuilder.text().withProps({ value: constants.SUBSCRIPTION }).component(); @@ -104,6 +107,15 @@ export class SKURecommendationPage extends MigrationWizardPage { ] ); + let data = connectionUri.split('|'); + data.forEach(element => { + if (element.startsWith('server:')) { + let serverArray = element.split(':'); + this._serverName = serverArray[1]; + } + }); + this._dbCount = (await azdata.connection.listDatabases(this.migrationStateModel.sourceConnectionId)).length; + await view.initializeModel(formContainer.component()); } @@ -111,7 +123,7 @@ export class SKURecommendationPage extends MigrationWizardPage { const component = view.modelBuilder.text().withProperties({ value: '', CSSStyles: { - 'font-size': '18px' + 'font-size': '14px' } }); @@ -143,13 +155,26 @@ export class SKURecommendationPage extends MigrationWizardPage { private constructDetails(): void { this._chooseTargetComponent?.component.clearItems(); - + this._igComponent!.component.value = constants.ASSESSMENT_COMPLETED(this._serverName); if (this.migrationStateModel.assessmentResults) { + // need to parse assessment results before this, multiple assessment results present for same DB + let dbIssueCount = 0; + let last = ''; + this.migrationStateModel.assessmentResults.forEach(element => { + if (element.targetName !== this._serverName && element.targetName !== last) { + dbIssueCount += 1; + last = element.targetName; + } + }); + if (dbIssueCount === this._dbCount) { + this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_NONE_SUCCESSFUL; + } else if (dbIssueCount > 0) { + this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_SOME_SUCCESSFUL(this._dbCount - dbIssueCount, this._dbCount); + } else { + this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_ALL_SUCCESSFUL(this._dbCount); + } } - this._igComponent!.component.value = constants.CONGRATULATIONS; - // either: SKU_RECOMMENDATION_ALL_SUCCESSFUL or SKU_RECOMMENDATION_SOME_SUCCESSFUL or SKU_RECOMMENDATION_NONE_SUCCESSFUL - this._detailsComponent!.component.value = constants.SKU_RECOMMENDATION_SOME_SUCCESSFUL(1, 1); this.constructTargets(); } @@ -166,8 +191,13 @@ export class SKURecommendationPage extends MigrationWizardPage { }).component(); products.forEach((product) => { - const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'images', product.icon ?? 'ads.svg'); - const dbCount = this.migrationStateModel._migrationDbs.length; + const imagePath = path.resolve(this.migrationStateModel.getExtensionPath(), 'media', product.icon ?? 'ads.svg'); + let dbCount = 0; + if (product.type === 'AzureSQLVM') { + dbCount = this._dbCount; + } else { + dbCount = this.migrationStateModel._migrationDbs.length; + } const descriptions: azdata.RadioCardDescription[] = [ { textValue: product.name, @@ -212,13 +242,26 @@ export class SKURecommendationPage extends MigrationWizardPage { descriptions }); }); + let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this, 'mi'); + let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this, 'vm'); this._rbg.onLinkClick(async (value) => { //check which card is being selected, and open correct dialog based on link console.log(value); - let dialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, 'Assessment Dialog', this); - await dialog.openDialog(); + if (value.description.linkDisplayValue === 'View/Change') { + if (value.cardId === 'AzureSQLVM') { + await vmDialog.openDialog(); + } else if (value.cardId === 'AzureSQLMI') { + await miDialog.openDialog(); + } + } else if (value.description.linkDisplayValue === 'Learn more') { + if (value.cardId === 'AzureSQLVM') { + vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/sql-server-on-azure-vm-iaas-what-is-overview')); + } else if (value.cardId === 'AzureSQLMI') { + vscode.env.openExternal(vscode.Uri.parse('https://docs.microsoft.com/en-us/azure/azure-sql/managed-instance/sql-managed-instance-paas-overview ')); + } + } }); this._rbg.onSelectionChanged((value) => {