[SQL Migration] Improve IR registration experience (#22926)

* Add registration instructions to IR page

* Clean up

* Typo

* Fix typo

* Replace link with aka.ms link

* Refactor + implement regenerate auth keys

* Update strings and clean up comments

* Fix sqlMigrationServiceDetailsDialog

* Fix sqlMigrationServiceDetailsDialog width

* Extract helpers to utils

* Add IR registration instructions to sqlMigrationServiceDetailsDialog

* Update SHIR description slightly
This commit is contained in:
Raymond Truong
2023-05-03 16:43:00 -04:00
committed by GitHub
parent 844ed758a5
commit 0d2ed6e517
5 changed files with 280 additions and 447 deletions

View File

@@ -5,15 +5,13 @@
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { createSqlMigrationService, getResourceName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlMigrationService } from '../../api/azure';
import { createSqlMigrationService, getResourceName, getSqlMigrationService, getSqlMigrationServiceMonitoringData, SqlMigrationService } from '../../api/azure';
import { MigrationStateModel } from '../../models/stateMachine';
import { logError, TelemetryViews } from '../../telemetry';
import * as constants from '../../constants/strings';
import * as os from 'os';
import { azureResource } from 'azurecore';
import { IconPathHelper } from '../../constants/iconPathHelper';
import { CreateResourceGroupDialog } from '../createResourceGroup/createResourceGroupDialog';
import { createAuthenticationKeyTable } from '../../wizard/integrationRuntimePage';
import * as EventEmitter from 'events';
import * as utils from '../../api/utils';
import * as styles from '../../constants/styles';
@@ -33,10 +31,6 @@ export class CreateSqlMigrationServiceDialog {
private _refreshLoadingComponent!: azdata.LoadingComponent;
private migrationServiceAuthKeyTable!: azdata.DeclarativeTableComponent;
private _connectionStatus!: azdata.InfoBoxComponent;
private _copyKey1Button!: azdata.ButtonComponent;
private _copyKey2Button!: azdata.ButtonComponent;
private _refreshKey1Button!: azdata.ButtonComponent;
private _refreshKey2Button!: azdata.ButtonComponent;
private _setupContainer!: azdata.FlexContainer;
private _resourceGroupPreset!: string;
@@ -119,7 +113,17 @@ export class CreateSqlMigrationServiceDialog {
};
} else {
await this.refreshStatus();
await this.refreshAuthTable();
await utils.refreshAuthenticationKeyTable(
this._view,
this.migrationServiceAuthKeyTable,
this._model._azureAccount,
subscription,
resourceGroup.name,
location,
this._createdMigrationService);
this._setupContainer.display = 'inline';
this._testConnectionButton.hidden = false;
}
@@ -214,7 +218,7 @@ export class CreateSqlMigrationServiceDialog {
private async migrationServiceDropdownContainer(): Promise<azdata.FlexContainer> {
const dialogDescription = this._view.modelBuilder.text().withProps({
value: constants.MIGRATION_SERVICE_DIALOG_DESCRIPTION,
value: constants.MIGRATION_SERVICE_DIALOG_DESCRIPTION(!this._model.isSqlDbTarget),
CSSStyles: {
...styles.BODY_CSS
}
@@ -410,56 +414,7 @@ export class CreateSqlMigrationServiceDialog {
}
private createServiceStatus(): azdata.FlexContainer {
const setupIRHeadingText = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_CONTAINER_HEADING,
CSSStyles: {
...styles.LABEL_CSS
}
}).component();
const setupIRdescription1 = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_CONTAINER_DESCRIPTION1,
CSSStyles: {
...styles.BODY_CSS
}
}).component();
const setupIRdescription2 = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_CONTAINER_DESCRIPTION2,
CSSStyles: {
...styles.BODY_CSS
}
}).component();
const irSetupStep1Text = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_STEP1,
CSSStyles: {
...styles.BODY_CSS
},
links: [
{
text: constants.SERVICE_STEP1_LINK,
url: 'https://www.microsoft.com/download/details.aspx?id=39717'
}
]
}).component();
const irSetupStep2Text = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_STEP2,
CSSStyles: {
...styles.BODY_CSS
}
}).component();
const irSetupStep3Text = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_STEP3,
CSSStyles: {
'margin-top': '10px',
'margin-bottom': '10px',
...styles.BODY_CSS
}
}).component();
const instructions = utils.createRegistrationInstructions(this._view, true);
this._connectionStatus = this._view.modelBuilder.infoBox().withProps({
text: '',
@@ -480,17 +435,12 @@ export class CreateSqlMigrationServiceDialog {
}
}).component();
this.migrationServiceAuthKeyTable = createAuthenticationKeyTable(this._view);
this.migrationServiceAuthKeyTable = utils.createAuthenticationKeyTable(this._view, '50px', '500px');
this._setupContainer = this._view.modelBuilder.flexContainer().withItems(
[
setupIRHeadingText,
setupIRdescription1,
setupIRdescription2,
irSetupStep1Text,
irSetupStep2Text,
instructions,
this.migrationServiceAuthKeyTable,
irSetupStep3Text,
this._connectionStatus,
this._refreshLoadingComponent
], {
@@ -550,16 +500,16 @@ export class CreateSqlMigrationServiceDialog {
if (state === 'Online') {
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.SERVICE_READY(this._createdMigrationService!.name, this.irNodes.join(', ')),
text: constants.SERVICE_READY(this._createdMigrationService!.name, this.irNodes.join(', '), false),
style: 'success',
CSSStyles: {
...styles.BODY_CSS
}
});
} else {
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name);
this._connectionStatus.text = constants.SERVICE_NOT_READY(this._createdMigrationService!.name, false);
await this._connectionStatus.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.SERVICE_NOT_READY(this._createdMigrationService!.name),
text: constants.SERVICE_NOT_READY(this._createdMigrationService!.name, false),
style: 'warning',
CSSStyles: {
...styles.BODY_CSS
@@ -570,89 +520,6 @@ export class CreateSqlMigrationServiceDialog {
}
}
private async refreshAuthTable(): Promise<void> {
const subscription = this._model._sqlMigrationServiceSubscription;
const resourceGroupId = (this.migrationServiceResourceGroupDropdown.value as azdata.CategoryValue).name;
const resourceGroup = getResourceName(resourceGroupId);
const location = this._model._location.name;
const keys = await getSqlMigrationServiceAuthKeys(
this._model._azureAccount,
subscription,
resourceGroup,
location,
this._createdMigrationService!.name);
this._copyKey1Button = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY1,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY1,
}).component();
this._disposables.push(this._copyKey1Button.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}));
this._copyKey2Button = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY2,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY2,
}).component();
this._disposables.push(this._copyKey2Button.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}));
this._refreshKey1Button = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY1,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY1,
}).component();
this._disposables.push(this._refreshKey1Button.onDidClick((e) => {
//TODO: add refresh logic
}));
this._refreshKey2Button = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY2,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY2,
}).component();
this._disposables.push(this._refreshKey2Button.onDidClick((e) => {
//TODO: add refresh logic
}));
await this.migrationServiceAuthKeyTable.updateProperties({
dataValues: [
[
{
value: constants.SERVICE_KEY1_LABEL
},
{
value: keys.authKey1
},
{
value: this._view.modelBuilder.flexContainer().withItems([this._copyKey1Button, this._refreshKey1Button]).component()
}
],
[
{
value: constants.SERVICE_KEY2_LABEL
},
{
value: keys.authKey2
},
{
value: this._view.modelBuilder.flexContainer().withItems([this._copyKey2Button, this._refreshKey2Button]).component()
}
]
]
});
}
private setDialogMessage(message: string, level: azdata.window.MessageLevel = azdata.window.MessageLevel.Error): void {
this._dialogObject.message = {
text: message,