Add SQL DB offline migration wizard experience (#20403)

* sql db wizard with target selection

* add database table selection

* add sqldb to service and IR page

* Code complete

* navigation bug fixes

* fix target db selection

* improve sqldb error and status reporting

* fix error count bug

* remove table status inference

* address review feedback

* update resource strings and content

* fix migraton status string, use localized value

* fix ux navigation issues

* fix back/fwd w/o changes from changing data
This commit is contained in:
brian-harris
2022-08-19 18:12:34 -07:00
committed by GitHub
parent c0b09dcedd
commit 7a736b76fa
42 changed files with 5716 additions and 4209 deletions

View File

@@ -6,7 +6,7 @@
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
import { MigrationStateModel, MigrationTargetType, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
import { CreateSqlMigrationServiceDialog } from '../dialog/createSqlMigrationService/createSqlMigrationServiceDialog';
import * as constants from '../constants/strings';
import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController';
@@ -17,20 +17,17 @@ import * as utils from '../api/utils';
import * as styles from '../constants/styles';
export class IntergrationRuntimePage extends MigrationWizardPage {
private _view!: azdata.ModelView;
private _statusLoadingComponent!: azdata.LoadingComponent;
private _subscription!: azdata.TextComponent;
private _location!: azdata.TextComponent;
private _resourceGroupDropdown!: azdata.DropDownComponent;
private _dmsDropdown!: azdata.DropDownComponent;
private _dmsInfoContainer!: azdata.FlexContainer;
private _dmsStatusInfoBox!: azdata.InfoBoxComponent;
private _authKeyTable!: azdata.DeclarativeTableComponent;
private _refreshButton!: azdata.ButtonComponent;
private _connectionStatusLoader!: azdata.LoadingComponent;
private _copy1!: azdata.ButtonComponent;
private _copy2!: azdata.ButtonComponent;
private _refresh1!: azdata.ButtonComponent;
@@ -55,31 +52,39 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
const form = view.modelBuilder.formContainer()
.withFormItems([
{ component: this.migrationServiceDropdownContainer() },
{ component: this._dmsInfoContainer }
])
{ component: this._dmsInfoContainer }])
.withProps({ CSSStyles: { 'padding-top': '0' } })
.component();
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
this._disposables.push(
this._view.onClosed(e =>
this._disposables.forEach(
d => { try { d.dispose(); } catch { } })));
await view.initializeModel(form);
}
public async onPageEnter(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
return;
}
this._subscription.value = this.migrationStateModel._targetSubscription.name;
this._location.value = await getLocationDisplayName(this.migrationStateModel._targetServerInstance.location);
this._dmsInfoContainer.display = (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE && this.migrationStateModel._sqlMigrationService) ? 'inline' : 'none';
this._location.value = await getLocationDisplayName(
this.migrationStateModel._targetServerInstance.location);
await utils.updateControlDisplay(
this._dmsInfoContainer,
this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE);
await this.loadResourceGroupDropdown();
this.wizard.registerNavigationValidator((pageChangeInfo) => {
this.wizard.message = { text: '' };
if (pageChangeInfo.newPage < pageChangeInfo.lastPage) {
this.wizard.message = {
text: ''
};
return true;
}
const state = this.migrationStateModel._sqlMigrationService?.properties?.integrationRuntimeState;
if (!this.migrationStateModel._sqlMigrationService) {
this.wizard.message = {
@@ -88,327 +93,325 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
};
return false;
}
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE && state !== 'Online') {
if ((this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE)
&& state !== 'Online') {
this.wizard.message = {
level: azdata.window.MessageLevel.Error,
text: constants.SERVICE_OFFLINE_ERROR
};
return false;
} else {
this.wizard.message = {
text: ''
};
}
return true;
});
}
public async onPageLeave(pageChangeInfo: azdata.window.WizardPageChangeInfo): Promise<void> {
this.wizard.registerNavigationValidator((pageChangeInfo) => {
return true;
});
this.wizard.registerNavigationValidator((pageChangeInfo) => true);
}
protected async handleStateChange(e: StateChangeEvent): Promise<void> {
}
private migrationServiceDropdownContainer(): azdata.FlexContainer {
const descriptionText = this._view.modelBuilder.text().withProps({
value: constants.IR_PAGE_DESCRIPTION,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
...styles.BODY_CSS,
'margin-bottom': '16px'
}
}).component();
const descriptionText = this._view.modelBuilder.text()
.withProps({
value: constants.IR_PAGE_DESCRIPTION,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: { ...styles.BODY_CSS, 'margin-bottom': '16px' }
}).component();
const subscriptionLabel = this._view.modelBuilder.text().withProps({
value: constants.SUBSCRIPTION,
CSSStyles: {
...styles.LABEL_CSS
}
}).component();
this._subscription = this._view.modelBuilder.text().withProps({
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'margin': '0'
}
}).component();
const subscriptionLabel = this._view.modelBuilder.text()
.withProps({
value: constants.SUBSCRIPTION,
CSSStyles: { ...styles.LABEL_CSS }
}).component();
this._subscription = this._view.modelBuilder.text()
.withProps({
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: { 'margin': '0' }
}).component();
const locationLabel = this._view.modelBuilder.text().withProps({
value: constants.LOCATION,
CSSStyles: {
...styles.LABEL_CSS,
'margin-top': '1em'
}
}).component();
this._location = this._view.modelBuilder.text().withProps({
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: {
'margin': '0'
}
}).component();
const locationLabel = this._view.modelBuilder.text()
.withProps({
value: constants.LOCATION,
CSSStyles: { ...styles.LABEL_CSS, 'margin-top': '1em' }
}).component();
this._location = this._view.modelBuilder.text()
.withProps({
enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH,
CSSStyles: { 'margin': '0' }
}).component();
const resourceGroupLabel = this._view.modelBuilder.text().withProps({
value: constants.RESOURCE_GROUP,
requiredIndicator: true,
CSSStyles: {
...styles.LABEL_CSS
}
}).component();
this._resourceGroupDropdown = this._view.modelBuilder.dropDown().withProps({
ariaLabel: constants.RESOURCE_GROUP,
placeholder: constants.SELECT_RESOURCE_GROUP,
width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
required: true,
fireOnTextChange: true,
CSSStyles: {
'margin-top': '-1em'
}
}).component();
this._disposables.push(this._resourceGroupDropdown.onValueChanged(async (value) => {
if (value && value !== 'undefined' && value !== constants.RESOURCE_GROUP_NOT_FOUND) {
const selectedResourceGroup = this.migrationStateModel._resourceGroups.find(rg => rg.name === value);
this.migrationStateModel._sqlMigrationServiceResourceGroup = (selectedResourceGroup)
? selectedResourceGroup
: undefined!;
await this.populateDms();
}
}));
const resourceGroupLabel = this._view.modelBuilder.text()
.withProps({
value: constants.RESOURCE_GROUP,
requiredIndicator: true,
CSSStyles: { ...styles.LABEL_CSS }
}).component();
this._resourceGroupDropdown = this._view.modelBuilder.dropDown()
.withProps({
ariaLabel: constants.RESOURCE_GROUP,
placeholder: constants.SELECT_RESOURCE_GROUP,
width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
required: true,
fireOnTextChange: true,
CSSStyles: { 'margin-top': '-1em' }
}).component();
this._disposables.push(
this._resourceGroupDropdown.onValueChanged(
async (value) => {
if (value && value !== 'undefined' && value !== constants.RESOURCE_GROUP_NOT_FOUND) {
const selectedResourceGroup = this.migrationStateModel._resourceGroups.find(rg => rg.name === value);
this.migrationStateModel._sqlMigrationServiceResourceGroup = (selectedResourceGroup)
? selectedResourceGroup
: undefined!;
this.populateDms();
}
}));
const migrationServiceDropdownLabel = this._view.modelBuilder.text().withProps({
value: constants.IR_PAGE_TITLE,
requiredIndicator: true,
CSSStyles: {
...styles.LABEL_CSS
}
}).component();
this._dmsDropdown = this._view.modelBuilder.dropDown().withProps({
ariaLabel: constants.IR_PAGE_TITLE,
placeholder: constants.SELECT_RESOURCE_GROUP_PROMPT,
width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
required: true,
fireOnTextChange: true,
CSSStyles: {
'margin-top': '-1em'
}
}).component();
this._disposables.push(this._dmsDropdown.onValueChanged(async (value) => {
if (value && value !== 'undefined' && value !== constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR) {
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
this._dmsInfoContainer.display = 'inline';
}
this.wizard.message = {
text: ''
};
const selectedDms = this.migrationStateModel._sqlMigrationServices.find(dms => dms.name === value && dms.properties.resourceGroup.toLowerCase() === this.migrationStateModel._sqlMigrationServiceResourceGroup.name.toLowerCase());
if (selectedDms) {
this.migrationStateModel._sqlMigrationService = selectedDms;
await this.loadMigrationServiceStatus();
}
} else {
this.migrationStateModel._sqlMigrationService = undefined;
this._dmsInfoContainer.display = 'none';
}
}));
const migrationServiceDropdownLabel = this._view.modelBuilder.text()
.withProps({
value: constants.IR_PAGE_TITLE,
requiredIndicator: true,
CSSStyles: { ...styles.LABEL_CSS }
}).component();
this._dmsDropdown = this._view.modelBuilder.dropDown()
.withProps({
ariaLabel: constants.IR_PAGE_TITLE,
placeholder: constants.SELECT_RESOURCE_GROUP_PROMPT,
width: WIZARD_INPUT_COMPONENT_WIDTH,
editable: true,
required: true,
fireOnTextChange: true,
CSSStyles: { 'margin-top': '-1em' }
}).component();
this._disposables.push(
this._dmsDropdown.onValueChanged(
async (value) => {
if (value && value !== 'undefined' && value !== constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR) {
this.wizard.message = { text: '' };
const createNewMigrationService = this._view.modelBuilder.hyperlink().withProps({
label: constants.CREATE_NEW,
ariaLabel: constants.CREATE_NEW_MIGRATION_SERVICE,
url: '',
CSSStyles: {
...styles.BODY_CSS
}
}).component();
await utils.updateControlDisplay(
this._dmsInfoContainer,
this.migrationStateModel._targetType === MigrationTargetType.SQLDB ||
this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE);
this._disposables.push(createNewMigrationService.onDidClick(async (e) => {
const dialog = new CreateSqlMigrationServiceDialog();
const createdDmsResult = await dialog.createNewDms(this.migrationStateModel, (<azdata.CategoryValue>this._resourceGroupDropdown.value).displayName);
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
await this.loadResourceGroupDropdown();
await this.populateDms();
}));
const selectedDms = this.migrationStateModel._sqlMigrationServices.find(
dms => dms.name === value && dms.properties.resourceGroup.toLowerCase() === this.migrationStateModel._sqlMigrationServiceResourceGroup.name.toLowerCase());
if (selectedDms) {
this.migrationStateModel._sqlMigrationService = selectedDms;
await this.loadStatus();
}
} else {
this.migrationStateModel._sqlMigrationService = undefined;
await utils.updateControlDisplay(this._dmsInfoContainer, false);
}
}));
const flexContainer = this._view.modelBuilder.flexContainer().withItems([
descriptionText,
subscriptionLabel,
this._subscription,
locationLabel,
this._location,
resourceGroupLabel,
this._resourceGroupDropdown,
migrationServiceDropdownLabel,
this._dmsDropdown,
createNewMigrationService
]).withLayout({
flexFlow: 'column'
}).component();
return flexContainer;
const createNewMigrationService = this._view.modelBuilder.hyperlink()
.withProps({
label: constants.CREATE_NEW,
ariaLabel: constants.CREATE_NEW_MIGRATION_SERVICE,
url: '',
CSSStyles: { ...styles.BODY_CSS }
}).component();
this._disposables.push(
createNewMigrationService.onDidClick(
async (e) => {
const dialog = new CreateSqlMigrationServiceDialog();
const createdDmsResult = await dialog.createNewDms(
this.migrationStateModel,
(<azdata.CategoryValue>this._resourceGroupDropdown.value).displayName);
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
await this.loadResourceGroupDropdown();
this.populateDms();
}));
return this._view.modelBuilder.flexContainer()
.withItems([
descriptionText,
subscriptionLabel,
this._subscription,
locationLabel,
this._location,
resourceGroupLabel,
this._resourceGroupDropdown,
migrationServiceDropdownLabel,
this._dmsDropdown,
createNewMigrationService])
.withLayout({ flexFlow: 'column' })
.component();
}
private createDMSDetailsContainer(): azdata.FlexContainer {
const container = this._view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column'
}).component();
const container = this._view.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.component();
const connectionStatusLabel = this._view.modelBuilder.text().withProps({
value: constants.SERVICE_CONNECTION_STATUS,
CSSStyles: {
...styles.LABEL_CSS,
'width': '130px'
}
}).component();
const connectionStatusLabel = this._view.modelBuilder.text()
.withProps({
value: constants.SERVICE_CONNECTION_STATUS,
CSSStyles: { ...styles.LABEL_CSS, 'width': '130px' }
}).component();
this._refreshButton = this._view.modelBuilder.button().withProps({
iconWidth: '18px',
iconHeight: '18px',
iconPath: IconPathHelper.refresh,
height: '18px',
width: '18px',
ariaLabel: constants.REFRESH,
}).component();
this._refreshButton = this._view.modelBuilder.button()
.withProps({
iconWidth: '18px',
iconHeight: '18px',
iconPath: IconPathHelper.refresh,
height: '18px',
width: '18px',
ariaLabel: constants.REFRESH,
}).component();
this._disposables.push(this._refreshButton.onDidClick(async (e) => {
this._connectionStatusLoader.loading = true;
try {
await this.loadStatus();
} finally {
this._connectionStatusLoader.loading = false;
}
}));
this._disposables.push(
this._refreshButton.onDidClick(
async (e) => this.loadStatus()));
const connectionLabelContainer = this._view.modelBuilder.flexContainer().component();
connectionLabelContainer.addItem(connectionStatusLabel, {
flex: '0'
});
connectionLabelContainer.addItem(this._refreshButton, {
flex: '0',
CSSStyles: { 'margin-right': '10px' }
});
const connectionLabelContainer = this._view.modelBuilder.flexContainer()
.component();
connectionLabelContainer.addItem(
connectionStatusLabel,
{ flex: '0' });
connectionLabelContainer.addItem(
this._refreshButton,
{ flex: '0', CSSStyles: { 'margin-right': '10px' } });
const statusContainer = this._view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column'
}).component();
const statusContainer = this._view.modelBuilder.flexContainer()
.withLayout({ flexFlow: 'column' })
.component();
this._dmsStatusInfoBox = this._view.modelBuilder.infoBox().withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH,
style: 'error',
text: '',
CSSStyles: {
...styles.BODY_CSS
}
}).component();
this._dmsStatusInfoBox = this._view.modelBuilder.infoBox()
.withProps({
width: WIZARD_INPUT_COMPONENT_WIDTH,
style: 'error',
text: '',
CSSStyles: { ...styles.BODY_CSS }
}).component();
const authenticationKeysLabel = this._view.modelBuilder.text().withProps({
value: constants.AUTHENTICATION_KEYS,
CSSStyles: {
...styles.LABEL_CSS
}
}).component();
const authenticationKeysLabel = this._view.modelBuilder.text()
.withProps({
value: constants.AUTHENTICATION_KEYS,
CSSStyles: { ...styles.LABEL_CSS }
}).component();
this._copy1 = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY1,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY1,
}).component();
this._copy1 = this._view.modelBuilder.button()
.withProps({
title: constants.COPY_KEY1,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY1,
}).component();
this._disposables.push(this._copy1.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![0][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}));
this._disposables.push(
this._copy1.onDidClick(
async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![0][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}));
this._copy2 = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY2,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY2,
}).component();
this._copy2 = this._view.modelBuilder.button()
.withProps({
title: constants.COPY_KEY2,
iconPath: IconPathHelper.copy,
ariaLabel: constants.COPY_KEY2,
}).component();
this._disposables.push(this._copy2.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![1][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}));
this._disposables.push(
this._copy2.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![1][1].value);
void vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}));
this._refresh1 = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY1,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY1,
}).component();
this._refresh1 = this._view.modelBuilder.button()
.withProps({
title: constants.REFRESH_KEY1,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY1,
}).component();
this._refresh2 = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY2,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY2,
}).component();
this._refresh2 = this._view.modelBuilder.button()
.withProps({
title: constants.REFRESH_KEY2,
iconPath: IconPathHelper.refresh,
ariaLabel: constants.REFRESH_KEY2,
}).component();
this._authKeyTable = createAuthenticationKeyTable(this._view);
statusContainer.addItems([
this._dmsStatusInfoBox,
authenticationKeysLabel,
this._authKeyTable
]);
this._authKeyTable]);
this._connectionStatusLoader = this._view.modelBuilder.loadingComponent().withItem(
statusContainer
).withProps({
loading: false
}).component();
this._connectionStatusLoader = this._view.modelBuilder.loadingComponent()
.withItem(statusContainer)
.withProps({ loading: false })
.component();
container.addItems(
[
connectionLabelContainer,
this._connectionStatusLoader
]
);
container.addItems([
connectionLabelContainer,
this._connectionStatusLoader]);
return container;
}
public async loadResourceGroupDropdown(): Promise<void> {
this._resourceGroupDropdown.loading = true;
this._dmsDropdown.loading = true;
try {
this.migrationStateModel._sqlMigrationServices = await utils.getAzureSqlMigrationServices(this.migrationStateModel._azureAccount, this.migrationStateModel._targetSubscription);
this.migrationStateModel._resourceGroups = await utils.getSqlMigrationServiceResourceGroups(this.migrationStateModel._sqlMigrationServices, this.migrationStateModel._location);
this._resourceGroupDropdown.values = await utils.getAzureResourceGroupsDropdownValues(this.migrationStateModel._resourceGroups);
const resourceGroup = (this.migrationStateModel._sqlMigrationService)
this._resourceGroupDropdown.loading = true;
this._dmsDropdown.loading = true;
this.migrationStateModel._sqlMigrationServices = await utils.getAzureSqlMigrationServices(
this.migrationStateModel._azureAccount,
this.migrationStateModel._targetSubscription);
this.migrationStateModel._resourceGroups = utils.getServiceResourceGroupsByLocation(
this.migrationStateModel._sqlMigrationServices,
this.migrationStateModel._location);
this._resourceGroupDropdown.values = utils.getResourceDropdownValues(
this.migrationStateModel._resourceGroups,
constants.RESOURCE_GROUP_NOT_FOUND);
const resourceGroup = this.migrationStateModel._sqlMigrationService
? getFullResourceGroupFromId(this.migrationStateModel._sqlMigrationService?.id)
: undefined;
utils.selectDefaultDropdownValue(this._resourceGroupDropdown, resourceGroup, false);
} finally {
this._dmsDropdown.loading = false;
this._resourceGroupDropdown.loading = false;
this._dmsDropdown.loading = false;
}
}
public async populateDms(): Promise<void> {
this._dmsDropdown.loading = true;
public populateDms(): void {
try {
this._dmsDropdown.values = await utils.getAzureSqlMigrationServicesDropdownValues(this.migrationStateModel._sqlMigrationServices, this.migrationStateModel._location, this.migrationStateModel._sqlMigrationServiceResourceGroup);
utils.selectDefaultDropdownValue(this._dmsDropdown, this.migrationStateModel._sqlMigrationService?.id, false);
this._dmsDropdown.loading = true;
this._dmsDropdown.values = utils.getAzureResourceDropdownValues(
this.migrationStateModel._sqlMigrationServices,
this.migrationStateModel._location,
this.migrationStateModel._sqlMigrationServiceResourceGroup.name,
constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR);
utils.selectDefaultDropdownValue(
this._dmsDropdown,
this.migrationStateModel._sqlMigrationService?.id,
false);
} finally {
this._dmsDropdown.loading = false;
}
}
private async loadMigrationServiceStatus(): Promise<void> {
this._statusLoadingComponent.loading = true;
try {
await this.loadStatus();
} catch (error) {
logError(TelemetryViews.MigrationWizardIntegrationRuntimePage, 'ErrorLoadingMigrationServiceStatus', error);
} finally {
this._statusLoadingComponent.loading = false;
}
}
private async loadStatus(): Promise<void> {
try {
this._statusLoadingComponent.loading = true;
if (this.migrationStateModel._sqlMigrationService) {
const migrationService = await getSqlMigrationService(
this.migrationStateModel._azureAccount,
@@ -436,12 +439,15 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
const state = migrationService.properties.integrationRuntimeState;
if (state === 'Online') {
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.SERVICE_READY(this.migrationStateModel._sqlMigrationService!.name, this.migrationStateModel._nodeNames.join(', ')),
text: constants.SERVICE_READY(
this.migrationStateModel._sqlMigrationService!.name,
this.migrationStateModel._nodeNames.join(', ')),
style: 'success'
});
} else {
await this._dmsStatusInfoBox.updateProperties(<azdata.InfoBoxComponentProperties>{
text: constants.SERVICE_NOT_READY(this.migrationStateModel._sqlMigrationService!.name),
text: constants.SERVICE_NOT_READY(
this.migrationStateModel._sqlMigrationService!.name),
style: 'error'
});
}
@@ -464,65 +470,49 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
.withItems([this._copy2, this._refresh2])
.component()
}
]
];
]];
await this._authKeyTable.setDataValues(data);
}
} catch (e) {
logError(TelemetryViews.IntegrationRuntimePage, 'ErrorLoadingStatus', e);
} finally {
this._statusLoadingComponent.loading = false;
}
}
}
export function createAuthenticationKeyTable(view: azdata.ModelView,): azdata.DeclarativeTableComponent {
const authKeyTable = view.modelBuilder.declarativeTable().withProps({
ariaLabel: constants.DATABASE_MIGRATION_SERVICE_AUTHENTICATION_KEYS,
columns: [
{
displayName: constants.NAME,
valueType: azdata.DeclarativeDataType.string,
width: '50px',
isReadOnly: true,
rowCssStyles: {
...styles.BODY_CSS
const authKeyTable = view.modelBuilder.declarativeTable()
.withProps({
ariaLabel: constants.DATABASE_MIGRATION_SERVICE_AUTHENTICATION_KEYS,
columns: [
{
displayName: constants.NAME,
valueType: azdata.DeclarativeDataType.string,
width: '50px',
isReadOnly: true,
rowCssStyles: { ...styles.BODY_CSS },
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
},
headerCssStyles: {
...styles.BODY_CSS,
'font-weight': '600'
}
},
{
displayName: constants.AUTH_KEY_COLUMN_HEADER,
valueType: azdata.DeclarativeDataType.string,
width: '500px',
isReadOnly: true,
rowCssStyles: {
...styles.BODY_CSS,
{
displayName: constants.AUTH_KEY_COLUMN_HEADER,
valueType: azdata.DeclarativeDataType.string,
width: '500px',
isReadOnly: true,
rowCssStyles: { ...styles.BODY_CSS },
headerCssStyles: { ...styles.BODY_CSS, 'font-weight': '600' }
},
headerCssStyles: {
...styles.BODY_CSS,
'font-weight': '600'
{
displayName: '',
valueType: azdata.DeclarativeDataType.component,
width: '30px',
isReadOnly: true,
rowCssStyles: { ...styles.BODY_CSS },
headerCssStyles: { ...styles.BODY_CSS }
}
},
{
displayName: '',
valueType: azdata.DeclarativeDataType.component,
width: '30px',
isReadOnly: true,
rowCssStyles: {
...styles.BODY_CSS
},
headerCssStyles: {
...styles.BODY_CSS
}
}
],
CSSStyles: {
'margin-top': '5px',
'width': WIZARD_INPUT_COMPONENT_WIDTH
}
}).component();
],
CSSStyles: { 'margin-top': '5px', 'width': WIZARD_INPUT_COMPONENT_WIDTH }
}).component();
return authKeyTable;
}