Dev/brih/hotfix status page (#16407)

* add dispose pattern, fix migration status enum

* format strings

* add dispose handler to more events
This commit is contained in:
brian-harris
2021-07-22 22:20:10 -07:00
committed by GitHub
parent 107023c7d0
commit df5ed2c889
22 changed files with 351 additions and 249 deletions

View File

@@ -422,7 +422,7 @@ export interface DatabaseMigration {
export interface DatabaseMigrationProperties { export interface DatabaseMigrationProperties {
scope: string; scope: string;
provisioningState: 'Succeeded' | 'Failed' | 'Creating'; provisioningState: 'Succeeded' | 'Failed' | 'Creating';
migrationStatus: 'InProgress' | 'Failed' | 'Succeeded' | 'Creating' | 'Completing' | 'Cancelling'; migrationStatus: 'InProgress' | 'Failed' | 'Succeeded' | 'Creating' | 'Completing' | 'Canceling';
migrationStatusDetails?: MigrationStatusDetails; migrationStatusDetails?: MigrationStatusDetails;
startedOn: string; startedOn: string;
endedOn: string; endedOn: string;

View File

@@ -395,10 +395,10 @@ export const FINISH_TIME = localize('sql.migration.finish.time', "Finish Time");
export function STATUS_VALUE(status: string, count: number): string { export function STATUS_VALUE(status: string, count: number): string {
if (count > 0) { if (count > 0) {
return localize('sql.migration.status.error.count.some', "{0} (", StatusLookup[status]); return localize('sql.migration.status.error.count.some', "{0} (", StatusLookup[status] ?? status);
} }
return localize('sql.migration.status.error.count.none', "{0}", StatusLookup[status]); return localize('sql.migration.status.error.count.none', "{0}", StatusLookup[status] ?? status);
} }
export interface LookupTable<T> { export interface LookupTable<T> {
@@ -410,7 +410,7 @@ export const StatusLookup: LookupTable<string | undefined> = {
['Succeeded']: localize('sql.migration.status.succeeded', 'Succeeded'), ['Succeeded']: localize('sql.migration.status.succeeded', 'Succeeded'),
['Creating']: localize('sql.migration.status.creating', 'Creating'), ['Creating']: localize('sql.migration.status.creating', 'Creating'),
['Completing']: localize('sql.migration.status.completing', 'Completing'), ['Completing']: localize('sql.migration.status.completing', 'Completing'),
['Cancelling']: localize('sql.migration.status.cancelling', 'Cancelling'), ['Canceling']: localize('sql.migration.status.canceling', 'Canceling'),
['Failed']: localize('sql.migration.status.failed', 'Failed'), ['Failed']: localize('sql.migration.status.failed', 'Failed'),
default: undefined, default: undefined,
}; };

View File

@@ -37,7 +37,6 @@ export class DashboardWidget {
private _migrationStatusCardLoadingContainer!: azdata.LoadingComponent; private _migrationStatusCardLoadingContainer!: azdata.LoadingComponent;
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _inProgressMigrationButton!: StatusCard; private _inProgressMigrationButton!: StatusCard;
private _inProgressWarningMigrationButton!: StatusCard; private _inProgressWarningMigrationButton!: StatusCard;
private _successfulMigrationButton!: StatusCard; private _successfulMigrationButton!: StatusCard;
@@ -48,6 +47,7 @@ export class DashboardWidget {
private _viewAllMigrationsButton!: azdata.ButtonComponent; private _viewAllMigrationsButton!: azdata.ButtonComponent;
private _autoRefreshHandle!: NodeJS.Timeout; private _autoRefreshHandle!: NodeJS.Timeout;
private _disposables: vscode.Disposable[] = [];
constructor() { constructor() {
} }
@@ -94,10 +94,13 @@ export class DashboardWidget {
'margin-top': '20px' 'margin-top': '20px'
} }
}); });
await view.initializeModel(container); this._disposables.push(this._view.onClosed(e => {
this._view.onClosed((e) => {
clearInterval(this._autoRefreshHandle); clearInterval(this._autoRefreshHandle);
}); this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(container);
this.refreshMigrations(); this.refreshMigrations();
}); });
} }
@@ -184,9 +187,9 @@ export class DashboardWidget {
} }
}).component(); }).component();
preRequisiteLearnMoreLink.onDidClick((value) => { this._disposables.push(preRequisiteLearnMoreLink.onDidClick((value) => {
vscode.window.showInformationMessage(loc.COMING_SOON); vscode.window.showInformationMessage(loc.COMING_SOON);
}); }));
const preReqContainer = view.modelBuilder.flexContainer().withItems([ const preReqContainer = view.modelBuilder.flexContainer().withItems([
preRequisiteListTitle, preRequisiteListTitle,
@@ -233,11 +236,11 @@ export class DashboardWidget {
'border': '1px solid' 'border': '1px solid'
} }
}).component(); }).component();
buttonContainer.onDidClick(async () => { this._disposables.push(buttonContainer.onDidClick(async () => {
if (taskMetaData.command) { if (taskMetaData.command) {
await vscode.commands.executeCommand(taskMetaData.command); await vscode.commands.executeCommand(taskMetaData.command);
} }
}); }));
return view.modelBuilder.divContainer().withItems([buttonContainer]).component(); return view.modelBuilder.divContainer().withItems([buttonContainer]).component();
} }
@@ -558,10 +561,10 @@ export class DashboardWidget {
} }
}).component(); }).component();
this._viewAllMigrationsButton.onDidClick(async (e) => { this._disposables.push(this._viewAllMigrationsButton.onDidClick(async (e) => {
const migrationStatus = await this.getCurrentMigrations(); const migrationStatus = await this.getCurrentMigrations();
new MigrationStatusDialog(migrationStatus ? migrationStatus : await this.getMigrations(), AdsMigrationStatus.ALL).initialize(); new MigrationStatusDialog(migrationStatus ? migrationStatus : await this.getMigrations(), AdsMigrationStatus.ALL).initialize();
}); }));
const refreshButton = view.modelBuilder.hyperlink().withProps({ const refreshButton = view.modelBuilder.hyperlink().withProps({
label: loc.REFRESH, label: loc.REFRESH,
@@ -573,11 +576,11 @@ export class DashboardWidget {
} }
}).component(); }).component();
refreshButton.onDidClick(async (e) => { this._disposables.push(refreshButton.onDidClick(async (e) => {
refreshButton.enabled = false; refreshButton.enabled = false;
await this.refreshMigrations(); await this.refreshMigrations();
refreshButton.enabled = true; refreshButton.enabled = true;
}); }));
const buttonContainer = view.modelBuilder.flexContainer().withLayout({ const buttonContainer = view.modelBuilder.flexContainer().withLayout({
justifyContent: 'flex-end', justifyContent: 'flex-end',
@@ -614,10 +617,10 @@ export class DashboardWidget {
IconPathHelper.inProgressMigration, IconPathHelper.inProgressMigration,
loc.MIGRATION_IN_PROGRESS loc.MIGRATION_IN_PROGRESS
); );
this._inProgressMigrationButton.container.onDidClick(async (e) => { this._disposables.push(this._inProgressMigrationButton.container.onDidClick(async (e) => {
const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.ONGOING); const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.ONGOING);
dialog.initialize(); dialog.initialize();
}); }));
this._migrationStatusCardsContainer.addItem( this._migrationStatusCardsContainer.addItem(
this._inProgressMigrationButton.container this._inProgressMigrationButton.container
@@ -628,10 +631,10 @@ export class DashboardWidget {
loc.MIGRATION_IN_PROGRESS, loc.MIGRATION_IN_PROGRESS,
'' ''
); );
this._inProgressWarningMigrationButton.container.onDidClick(async (e) => { this._disposables.push(this._inProgressWarningMigrationButton.container.onDidClick(async (e) => {
const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.ONGOING); const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.ONGOING);
dialog.initialize(); dialog.initialize();
}); }));
this._migrationStatusCardsContainer.addItem( this._migrationStatusCardsContainer.addItem(
this._inProgressWarningMigrationButton.container this._inProgressWarningMigrationButton.container
@@ -641,10 +644,10 @@ export class DashboardWidget {
IconPathHelper.completedMigration, IconPathHelper.completedMigration,
loc.MIGRATION_COMPLETED loc.MIGRATION_COMPLETED
); );
this._successfulMigrationButton.container.onDidClick(async (e) => { this._disposables.push(this._successfulMigrationButton.container.onDidClick(async (e) => {
const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.SUCCEEDED); const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.SUCCEEDED);
dialog.initialize(); dialog.initialize();
}); }));
this._migrationStatusCardsContainer.addItem( this._migrationStatusCardsContainer.addItem(
this._successfulMigrationButton.container this._successfulMigrationButton.container
); );
@@ -654,10 +657,10 @@ export class DashboardWidget {
IconPathHelper.completingCutover, IconPathHelper.completingCutover,
loc.MIGRATION_CUTOVER_CARD loc.MIGRATION_CUTOVER_CARD
); );
this._completingMigrationButton.container.onDidClick(async (e) => { this._disposables.push(this._completingMigrationButton.container.onDidClick(async (e) => {
const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.COMPLETING); const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.COMPLETING);
dialog.initialize(); dialog.initialize();
}); }));
this._migrationStatusCardsContainer.addItem( this._migrationStatusCardsContainer.addItem(
this._completingMigrationButton.container this._completingMigrationButton.container
); );
@@ -666,10 +669,10 @@ export class DashboardWidget {
IconPathHelper.error, IconPathHelper.error,
loc.MIGRATION_FAILED loc.MIGRATION_FAILED
); );
this._failedMigrationButton.container.onDidClick(async (e) => { this._disposables.push(this._failedMigrationButton.container.onDidClick(async (e) => {
const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.FAILED); const dialog = new MigrationStatusDialog(await this.getCurrentMigrations(), AdsMigrationStatus.FAILED);
dialog.initialize(); dialog.initialize();
}); }));
this._migrationStatusCardsContainer.addItem( this._migrationStatusCardsContainer.addItem(
this._failedMigrationButton.container this._failedMigrationButton.container
); );
@@ -678,9 +681,9 @@ export class DashboardWidget {
IconPathHelper.notStartedMigration, IconPathHelper.notStartedMigration,
loc.MIGRATION_NOT_STARTED loc.MIGRATION_NOT_STARTED
); );
this._notStartedMigrationCard.container.onDidClick((e) => { this._disposables.push(this._notStartedMigrationCard.container.onDidClick((e) => {
vscode.window.showInformationMessage('Feature coming soon'); vscode.window.showInformationMessage('Feature coming soon');
}); }));
this._migrationStatusCardLoadingContainer = view.modelBuilder.loadingComponent().withItem(this._migrationStatusCardsContainer).component(); this._migrationStatusCardLoadingContainer = view.modelBuilder.loadingComponent().withItem(this._migrationStatusCardsContainer).component();
@@ -843,11 +846,11 @@ export class DashboardWidget {
'margin': '0px' 'margin': '0px'
} }
}).component(); }).component();
video1Container.onDidClick(async () => { this._disposables.push(video1Container.onDidClick(async () => {
if (linkMetaData.link) { if (linkMetaData.link) {
await vscode.env.openExternal(vscode.Uri.parse(linkMetaData.link)); await vscode.env.openExternal(vscode.Uri.parse(linkMetaData.link));
} }
}); }));
videosContainer.addItem(video1Container, { videosContainer.addItem(video1Container, {
CSSStyles: { CSSStyles: {
'background-image': `url(${vscode.Uri.file(<string>linkMetaData.iconPath?.light)})`, 'background-image': `url(${vscode.Uri.file(<string>linkMetaData.iconPath?.light)})`,

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine'; import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
import { SqlDatabaseTree } from './sqlDatabasesTree'; import { SqlDatabaseTree } from './sqlDatabasesTree';
import { SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql'; import { SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
@@ -26,9 +27,8 @@ export class AssessmentResultsDialog {
// Dialog Name for Telemetry // Dialog Name for Telemetry
public dialogName: string | undefined; public dialogName: string | undefined;
private _tree: SqlDatabaseTree; private _tree: SqlDatabaseTree;
private _disposables: vscode.Disposable[] = [];
constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private _skuRecommendationPage: SKURecommendationPage, private _targetType: MigrationTargetType) { constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private _skuRecommendationPage: SKURecommendationPage, private _targetType: MigrationTargetType) {
this._model = model; this._model = model;
@@ -46,6 +46,11 @@ export class AssessmentResultsDialog {
}).component(); }).component();
flex.addItem(await this._tree.createRootContainer(view), { flex: '1 1 auto' }); flex.addItem(await this._tree.createRootContainer(view), { flex: '1 1 auto' });
this._disposables.push(view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(flex); await view.initializeModel(flex);
resolve(); resolve();
} catch (ex) { } catch (ex) {
@@ -61,10 +66,10 @@ export class AssessmentResultsDialog {
this.dialog = azdata.window.createModelViewDialog(this.title, this.title, 'wide'); this.dialog = azdata.window.createModelViewDialog(this.title, this.title, 'wide');
this.dialog.okButton.label = AssessmentResultsDialog.OkButtonText; this.dialog.okButton.label = AssessmentResultsDialog.OkButtonText;
this.dialog.okButton.onClick(async () => await this.execute()); this._disposables.push(this.dialog.okButton.onClick(async () => await this.execute()));
this.dialog.cancelButton.label = AssessmentResultsDialog.CancelButtonText; this.dialog.cancelButton.label = AssessmentResultsDialog.CancelButtonText;
this.dialog.cancelButton.onClick(async () => await this.cancel()); this._disposables.push(this.dialog.cancelButton.onClick(async () => await this.cancel()));
const dialogSetupPromises: Thenable<void>[] = []; const dialogSetupPromises: Thenable<void>[] = [];

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 * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql'; import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine'; import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
import * as constants from '../../constants/strings'; import * as constants from '../../constants/strings';
@@ -77,6 +78,7 @@ export class SqlDatabaseTree {
private _serverName!: string; private _serverName!: string;
private _dbNames!: string[]; private _dbNames!: string[];
private _databaseCount!: azdata.TextComponent; private _databaseCount!: azdata.TextComponent;
private _disposables: vscode.Disposable[] = [];
constructor( constructor(
private _model: MigrationStateModel, private _model: MigrationStateModel,
@@ -99,6 +101,10 @@ export class SqlDatabaseTree {
this._rootContainer.addItem(this._resultComponent, { flex: '0 0 auto' }); this._rootContainer.addItem(this._resultComponent, { flex: '0 0 auto' });
this._rootContainer.addItem(selectDbMessage, { flex: '1 1 auto' }); this._rootContainer.addItem(selectDbMessage, { flex: '1 1 auto' });
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return this._rootContainer; return this._rootContainer;
} }
@@ -167,12 +173,14 @@ export class SqlDatabaseTree {
] ]
} }
).component(); ).component();
this._databaseTable.onDataChanged(() => {
this._disposables.push(this._databaseTable.onDataChanged(() => {
this._databaseCount.updateProperties({ this._databaseCount.updateProperties({
'value': constants.DATABASES(this.selectedDbs().length, this._model._databaseAssessment.length) 'value': constants.DATABASES(this.selectedDbs().length, this._model._databaseAssessment.length)
}); });
}); }));
this._databaseTable.onRowSelected(async (e) => {
this._disposables.push(this._databaseTable.onRowSelected(async (e) => {
if (this._targetType === MigrationTargetType.SQLMI) { if (this._targetType === MigrationTargetType.SQLMI) {
this._activeIssues = this._model._assessmentResults?.databaseAssessments[e.row].issues; this._activeIssues = this._model._assessmentResults?.databaseAssessments[e.row].issues;
} else { } else {
@@ -188,7 +196,7 @@ export class SqlDatabaseTree {
'display': 'none' 'display': 'none'
}); });
await this.refreshResults(); await this.refreshResults();
}); }));
const tableContainer = this._view.modelBuilder.divContainer().withItems([this._databaseTable]).withProps({ const tableContainer = this._view.modelBuilder.divContainer().withItems([this._databaseTable]).withProps({
CSSStyles: { CSSStyles: {
@@ -206,7 +214,7 @@ export class SqlDatabaseTree {
width: 200 width: 200
}).component(); }).component();
resourceSearchBox.onTextChanged(value => this._filterTableList(value)); this._disposables.push(resourceSearchBox.onTextChanged(value => this._filterTableList(value)));
const searchContainer = this._view.modelBuilder.divContainer().withItems([resourceSearchBox]).withProps({ const searchContainer = this._view.modelBuilder.divContainer().withItems([resourceSearchBox]).withProps({
CSSStyles: { CSSStyles: {
@@ -270,7 +278,7 @@ export class SqlDatabaseTree {
} }
}).component(); }).component();
this._instanceTable.onRowSelected(async (e) => { this._disposables.push(this._instanceTable.onRowSelected(async (e) => {
this._activeIssues = this._model._assessmentResults?.issues; this._activeIssues = this._model._assessmentResults?.issues;
this._dbName.value = this._serverName; this._dbName.value = this._serverName;
this._resultComponent.updateCssStyles({ this._resultComponent.updateCssStyles({
@@ -284,7 +292,7 @@ export class SqlDatabaseTree {
if (this._targetType === MigrationTargetType.SQLMI) { if (this._targetType === MigrationTargetType.SQLMI) {
await this.refreshResults(); await this.refreshResults();
} }
}); }));
return instanceContainer; return instanceContainer;
} }
@@ -506,10 +514,10 @@ export class SqlDatabaseTree {
} }
).component(); ).component();
this._impactedObjectsTable.onRowSelected((e) => { this._disposables.push(this._impactedObjectsTable.onRowSelected((e) => {
const impactedObject = e.row > -1 ? this._impactedObjects[e.row] : undefined; const impactedObject = e.row > -1 ? this._impactedObjects[e.row] : undefined;
this.refreshImpactedObject(impactedObject); this.refreshImpactedObject(impactedObject);
}); }));
const objectDetailsTitle = this._view.modelBuilder.text().withProps({ const objectDetailsTitle = this._view.modelBuilder.text().withProps({
value: constants.OBJECT_DETAILS, value: constants.OBJECT_DETAILS,
@@ -714,10 +722,10 @@ export class SqlDatabaseTree {
} }
).component(); ).component();
this._assessmentResultsTable.onRowSelected(async (e) => { this._disposables.push(this._assessmentResultsTable.onRowSelected(async (e) => {
const selectedIssue = e.row > -1 ? this._activeIssues[e.row] : undefined; const selectedIssue = e.row > -1 ? this._activeIssues[e.row] : undefined;
await this.refreshAssessmentDetails(selectedIssue); await this.refreshAssessmentDetails(selectedIssue);
}); }));
const container = this._view.modelBuilder.flexContainer().withItems([this._assessmentResultsTable]).withLayout({ const container = this._view.modelBuilder.flexContainer().withItems([this._assessmentResultsTable]).withLayout({
flexFlow: 'column', flexFlow: 'column',

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { azureResource } from 'azureResource'; import { azureResource } from 'azureResource';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { createResourceGroup } from '../../api/azure'; import { createResourceGroup } from '../../api/azure';
@@ -13,6 +14,7 @@ export class CreateResourceGroupDialog {
private _dialogObject!: azdata.window.Dialog; private _dialogObject!: azdata.window.Dialog;
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _creationEvent: EventEmitter = new EventEmitter; private _creationEvent: EventEmitter = new EventEmitter;
private _disposables: vscode.Disposable[] = [];
constructor(private _azureAccount: azdata.Account, private _subscription: azureResource.AzureResourceSubscription, private _location: string) { constructor(private _azureAccount: azdata.Account, private _subscription: azureResource.AzureResourceSubscription, private _location: string) {
this._dialogObject = azdata.window.createModelViewDialog( this._dialogObject = azdata.window.createModelViewDialog(
@@ -63,11 +65,11 @@ export class CreateResourceGroupDialog {
return valid; return valid;
}).component(); }).component();
resourceGroupName.onTextChanged(e => { this._disposables.push(resourceGroupName.onTextChanged(e => {
errorBox.updateCssStyles({ errorBox.updateCssStyles({
'display': 'none' 'display': 'none'
}); });
}); }));
const okButton = view.modelBuilder.button().withProps({ const okButton = view.modelBuilder.button().withProps({
label: constants.OK, label: constants.OK,
@@ -75,7 +77,7 @@ export class CreateResourceGroupDialog {
enabled: false enabled: false
}).component(); }).component();
okButton.onDidClick(async e => { this._disposables.push(okButton.onDidClick(async e => {
errorBox.updateCssStyles({ errorBox.updateCssStyles({
'display': 'none' 'display': 'none'
}); });
@@ -95,16 +97,16 @@ export class CreateResourceGroupDialog {
} finally { } finally {
loading.loading = false; loading.loading = false;
} }
}); }));
const cancelButton = view.modelBuilder.button().withProps({ const cancelButton = view.modelBuilder.button().withProps({
label: constants.CANCEL, label: constants.CANCEL,
width: '80px' width: '80px'
}).component(); }).component();
cancelButton.onDidClick(e => { this._disposables.push(cancelButton.onDidClick(e => {
this._creationEvent.emit('done', undefined); this._creationEvent.emit('done', undefined);
}); }));
const loading = view.modelBuilder.loadingComponent().withProps({ const loading = view.modelBuilder.loadingComponent().withProps({
loading: false, loading: false,
@@ -174,6 +176,12 @@ export class CreateResourceGroupDialog {
'padding': '0px !important' 'padding': '0px !important'
} }
}).component(); }).component();
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return view.initializeModel(form).then(v => { return view.initializeModel(form).then(v => {
resourceGroupName.focus(); resourceGroupName.focus();
}); });

View File

@@ -47,6 +47,7 @@ export class CreateSqlMigrationServiceDialog {
private _isBlobContainerUsed: boolean = false; private _isBlobContainerUsed: boolean = false;
private irNodes: string[] = []; private irNodes: string[] = [];
private _disposables: vscode.Disposable[] = [];
public async createNewDms(migrationStateModel: MigrationStateModel, resourceGroupPreset: string): Promise<CreateSqlMigrationServiceDialogResult> { public async createNewDms(migrationStateModel: MigrationStateModel, resourceGroupPreset: string): Promise<CreateSqlMigrationServiceDialogResult> {
this._model = migrationStateModel; this._model = migrationStateModel;
@@ -64,7 +65,7 @@ export class CreateSqlMigrationServiceDialog {
width: '80px' width: '80px'
}).component(); }).component();
this._formSubmitButton.onDidClick(async (e) => { this._disposables.push(this._formSubmitButton.onDidClick(async (e) => {
this._dialogObject.message = { this._dialogObject.message = {
text: '' text: ''
}; };
@@ -122,7 +123,7 @@ export class CreateSqlMigrationServiceDialog {
this.setFormEnabledState(true); this.setFormEnabledState(true);
return; return;
} }
}); }));
this._statusLoadingComponent = view.modelBuilder.loadingComponent().withProps({ this._statusLoadingComponent = view.modelBuilder.loadingComponent().withProps({
loadingText: constants.LOADING_MIGRATION_SERVICES, loadingText: constants.LOADING_MIGRATION_SERVICES,
@@ -153,6 +154,11 @@ export class CreateSqlMigrationServiceDialog {
const form = formBuilder.withLayout({ width: '100%' }).component(); const form = formBuilder.withLayout({ width: '100%' }).component();
this._disposables.push(view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return view.initializeModel(form).then(() => { return view.initializeModel(form).then(() => {
this.populateSubscriptions(); this.populateSubscriptions();
}); });
@@ -160,7 +166,7 @@ export class CreateSqlMigrationServiceDialog {
this._testConnectionButton = azdata.window.createButton(constants.TEST_CONNECTION); this._testConnectionButton = azdata.window.createButton(constants.TEST_CONNECTION);
this._testConnectionButton.hidden = true; this._testConnectionButton.hidden = true;
this._testConnectionButton.onClick(async (e) => { this._disposables.push(this._testConnectionButton.onClick(async (e) => {
this._refreshLoadingComponent.loading = true; this._refreshLoadingComponent.loading = true;
this._connectionStatus.updateCssStyles({ this._connectionStatus.updateCssStyles({
'display': 'none' 'display': 'none'
@@ -174,17 +180,16 @@ export class CreateSqlMigrationServiceDialog {
'display': 'inline' 'display': 'inline'
}); });
this._refreshLoadingComponent.loading = false; this._refreshLoadingComponent.loading = false;
}); }));
this._dialogObject.customButtons = [this._testConnectionButton]; this._dialogObject.customButtons = [this._testConnectionButton];
this._dialogObject.content = [tab]; this._dialogObject.content = [tab];
this._dialogObject.okButton.enabled = false; this._dialogObject.okButton.enabled = false;
azdata.window.openDialog(this._dialogObject); azdata.window.openDialog(this._dialogObject);
this._dialogObject.cancelButton.onClick((e) => { this._disposables.push(this._dialogObject.cancelButton.onClick((e) => { }));
}); this._disposables.push(this._dialogObject.okButton.onClick((e) => {
this._dialogObject.okButton.onClick((e) => {
this._doneButtonEvent.emit('done', this._createdMigrationService, this._selectedResourceGroup); this._doneButtonEvent.emit('done', this._createdMigrationService, this._selectedResourceGroup);
}); }));
this._isBlobContainerUsed = this._model._databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER; this._isBlobContainerUsed = this._model._databaseBackup.networkContainerType === NetworkContainerType.BLOB_CONTAINER;
@@ -249,7 +254,7 @@ export class CreateSqlMigrationServiceDialog {
url: '' url: ''
}).component(); }).component();
this._createResourceGroupLink.onDidClick(async e => { this._disposables.push(this._createResourceGroupLink.onDidClick(async e => {
const createResourceGroupDialog = new CreateResourceGroupDialog(this._model._azureAccount, this._model._targetSubscription, this._model._targetServerInstance.location); const createResourceGroupDialog = new CreateResourceGroupDialog(this._model._azureAccount, this._model._targetSubscription, this._model._targetServerInstance.location);
const createdResourceGroup = await createResourceGroupDialog.initialize(); const createdResourceGroup = await createResourceGroupDialog.initialize();
if (createdResourceGroup) { if (createdResourceGroup) {
@@ -265,7 +270,7 @@ export class CreateSqlMigrationServiceDialog {
this.migrationServiceResourceGroupDropdown.loading = false; this.migrationServiceResourceGroupDropdown.loading = false;
this.migrationServiceResourceGroupDropdown.focus(); this.migrationServiceResourceGroupDropdown.focus();
} }
}); }));
this.migrationServiceNameText = this._view.modelBuilder.inputBox().component(); this.migrationServiceNameText = this._view.modelBuilder.inputBox().component();
@@ -549,10 +554,10 @@ export class CreateSqlMigrationServiceDialog {
ariaLabel: constants.COPY_KEY1, ariaLabel: constants.COPY_KEY1,
}).component(); }).component();
this._copyKey1Button.onDidClick((e) => { this._disposables.push(this._copyKey1Button.onDidClick((e) => {
vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value); vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![0][1].value);
vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}); }));
this._copyKey2Button = this._view.modelBuilder.button().withProps({ this._copyKey2Button = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY2, title: constants.COPY_KEY2,
@@ -560,10 +565,10 @@ export class CreateSqlMigrationServiceDialog {
ariaLabel: constants.COPY_KEY2, ariaLabel: constants.COPY_KEY2,
}).component(); }).component();
this._copyKey2Button.onDidClick((e) => { this._disposables.push(this._copyKey2Button.onDidClick((e) => {
vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value); vscode.env.clipboard.writeText(<string>this.migrationServiceAuthKeyTable.dataValues![1][1].value);
vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}); }));
this._refreshKey1Button = this._view.modelBuilder.button().withProps({ this._refreshKey1Button = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY1, title: constants.REFRESH_KEY1,
@@ -571,8 +576,9 @@ export class CreateSqlMigrationServiceDialog {
ariaLabel: constants.REFRESH_KEY1, ariaLabel: constants.REFRESH_KEY1,
}).component(); }).component();
this._refreshKey1Button.onDidClick((e) => {//TODO: add refresh logic this._disposables.push(this._refreshKey1Button.onDidClick((e) => {
}); //TODO: add refresh logic
}));
this._refreshKey2Button = this._view.modelBuilder.button().withProps({ this._refreshKey2Button = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY2, title: constants.REFRESH_KEY2,
@@ -580,8 +586,9 @@ export class CreateSqlMigrationServiceDialog {
ariaLabel: constants.REFRESH_KEY2, ariaLabel: constants.REFRESH_KEY2,
}).component(); }).component();
this._refreshKey2Button.onDidClick((e) => { //TODO: add refresh logic this._disposables.push(this._refreshKey2Button.onDidClick((e) => {
}); //TODO: add refresh logic
}));
this.migrationServiceAuthKeyTable.updateProperties({ this.migrationServiceAuthKeyTable.updateProperties({
dataValues: [ dataValues: [

View File

@@ -4,14 +4,15 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationCutoverDialogModel } from './migrationCutoverDialogModel'; import { MigrationCutoverDialogModel } from './migrationCutoverDialogModel';
import * as constants from '../../constants/strings'; import * as constants from '../../constants/strings';
import * as vscode from 'vscode';
import { SqlManagedInstance } from '../../api/azure'; import { SqlManagedInstance } from '../../api/azure';
export class ConfirmCutoverDialog { export class ConfirmCutoverDialog {
private _dialogObject!: azdata.window.Dialog; private _dialogObject!: azdata.window.Dialog;
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _disposables: vscode.Disposable[] = [];
constructor(private migrationCutoverModel: MigrationCutoverDialogModel) { constructor(private migrationCutoverModel: MigrationCutoverDialogModel) {
this._dialogObject = azdata.window.createModelViewDialog('', 'ConfirmCutoverDialog', 500); this._dialogObject = azdata.window.createModelViewDialog('', 'ConfirmCutoverDialog', 500);
@@ -74,9 +75,9 @@ export class ConfirmCutoverDialog {
label: constants.CONFIRM_CUTOVER_CHECKBOX, label: constants.CONFIRM_CUTOVER_CHECKBOX,
}).component(); }).component();
confirmCheckbox.onChanged(e => { this._disposables.push(confirmCheckbox.onChanged(e => {
this._dialogObject.okButton.enabled = e; this._dialogObject.okButton.enabled = e;
}); }));
const cutoverWarning = this._view.modelBuilder.infoBox().withProps({ const cutoverWarning = this._view.modelBuilder.infoBox().withProps({
text: constants.COMPLETING_CUTOVER_WARNING, text: constants.COMPLETING_CUTOVER_WARNING,
@@ -119,10 +120,10 @@ export class ConfirmCutoverDialog {
this._dialogObject.okButton.enabled = false; this._dialogObject.okButton.enabled = false;
this._dialogObject.okButton.label = constants.COMPLETE_CUTOVER; this._dialogObject.okButton.label = constants.COMPLETE_CUTOVER;
this._dialogObject.okButton.onClick((e) => { this._disposables.push(this._dialogObject.okButton.onClick((e) => {
this.migrationCutoverModel.startCutover(); this.migrationCutoverModel.startCutover();
vscode.window.showInformationMessage(constants.CUTOVER_IN_PROGRESS(this.migrationCutoverModel._migration.migrationContext.properties.sourceDatabaseName)); vscode.window.showInformationMessage(constants.CUTOVER_IN_PROGRESS(this.migrationCutoverModel._migration.migrationContext.properties.sourceDatabaseName));
}); }));
const formBuilder = view.modelBuilder.formContainer().withFormItems( const formBuilder = view.modelBuilder.formContainer().withFormItems(
[ [
@@ -135,6 +136,12 @@ export class ConfirmCutoverDialog {
} }
); );
const form = formBuilder.withLayout({ width: '100%' }).component(); const form = formBuilder.withLayout({ width: '100%' }).component();
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return view.initializeModel(form); return view.initializeModel(form);
}); });
this._dialogObject.content = [tab]; this._dialogObject.content = [tab];

View File

@@ -4,13 +4,13 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { IconPathHelper } from '../../constants/iconPathHelper'; import { IconPathHelper } from '../../constants/iconPathHelper';
import { MigrationContext } from '../../models/migrationLocalStorage'; import { MigrationContext } from '../../models/migrationLocalStorage';
import { MigrationCutoverDialogModel, MigrationStatus } from './migrationCutoverDialogModel'; import { MigrationCutoverDialogModel, MigrationStatus } from './migrationCutoverDialogModel';
import * as loc from '../../constants/strings'; import * as loc from '../../constants/strings';
import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, SupportedAutoRefreshIntervals } from '../../api/utils'; import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, SupportedAutoRefreshIntervals } from '../../api/utils';
import { EOL } from 'os'; import { EOL } from 'os';
import * as vscode from 'vscode';
import { ConfirmCutoverDialog } from './confirmCutoverDialog'; import { ConfirmCutoverDialog } from './confirmCutoverDialog';
const refreshFrequency: SupportedAutoRefreshIntervals = 30000; const refreshFrequency: SupportedAutoRefreshIntervals = 30000;
@@ -42,6 +42,7 @@ export class MigrationCutoverDialog {
private _fileCount!: azdata.TextComponent; private _fileCount!: azdata.TextComponent;
private fileTable!: azdata.TableComponent; private fileTable!: azdata.TableComponent;
private _autoRefreshHandle!: any; private _autoRefreshHandle!: any;
private _disposables: vscode.Disposable[] = [];
readonly _infoFieldWidth: string = '250px'; readonly _infoFieldWidth: string = '250px';
@@ -270,9 +271,12 @@ export class MigrationCutoverDialog {
{ horizontal: false } { horizontal: false }
); );
const form = formBuilder.withLayout({ width: '100%' }).component(); const form = formBuilder.withLayout({ width: '100%' }).component();
this._view.onClosed(e => {
this._disposables.push(this._view.onClosed(e => {
clearInterval(this._autoRefreshHandle); clearInterval(this._autoRefreshHandle);
}); this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return view.initializeModel(form).then((value) => { return view.initializeModel(form).then((value) => {
this.refreshStatus(); this.refreshStatus();
@@ -286,9 +290,9 @@ export class MigrationCutoverDialog {
this._dialogObject.cancelButton.hidden = true; this._dialogObject.cancelButton.hidden = true;
this._dialogObject.okButton.label = loc.CLOSE; this._dialogObject.okButton.label = loc.CLOSE;
this._dialogObject.okButton.onClick(e => { this._disposables.push(this._dialogObject.okButton.onClick(e => {
clearInterval(this._autoRefreshHandle); clearInterval(this._autoRefreshHandle);
}); }));
azdata.window.openDialog(this._dialogObject); azdata.window.openDialog(this._dialogObject);
} }
@@ -364,12 +368,12 @@ export class MigrationCutoverDialog {
} }
}).component(); }).component();
this._cutoverButton.onDidClick(async (e) => { this._disposables.push(this._cutoverButton.onDidClick(async (e) => {
await this.refreshStatus(); await this.refreshStatus();
const dialog = new ConfirmCutoverDialog(this._model); const dialog = new ConfirmCutoverDialog(this._model);
await dialog.initialize(); await dialog.initialize();
await this.refreshStatus(); await this.refreshStatus();
}); }));
headerActions.addItem(this._cutoverButton, { headerActions.addItem(this._cutoverButton, {
flex: '0' flex: '0'
@@ -387,14 +391,14 @@ export class MigrationCutoverDialog {
} }
}).component(); }).component();
this._cancelButton.onDidClick((e) => { this._disposables.push(this._cancelButton.onDidClick((e) => {
vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, { modal: true }, loc.YES, loc.NO).then(async (v) => { vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, { modal: true }, loc.YES, loc.NO).then(async (v) => {
if (v === loc.YES) { if (v === loc.YES) {
await this._model.cancelMigration(); await this._model.cancelMigration();
await this.refreshStatus(); await this.refreshStatus();
} }
}); });
}); }));
headerActions.addItem(this._cancelButton, { headerActions.addItem(this._cancelButton, {
flex: '0' flex: '0'
@@ -413,8 +417,8 @@ export class MigrationCutoverDialog {
} }
}).component(); }).component();
this._refreshButton.onDidClick( this._disposables.push(this._refreshButton.onDidClick(
async (e) => await this.refreshStatus()); async (e) => await this.refreshStatus()));
headerActions.addItem(this._refreshButton, { headerActions.addItem(this._refreshButton, {
flex: '0', flex: '0',
@@ -432,7 +436,7 @@ export class MigrationCutoverDialog {
} }
}).component(); }).component();
this._copyDatabaseMigrationDetails.onDidClick(async (e) => { this._disposables.push(this._copyDatabaseMigrationDetails.onDidClick(async (e) => {
await this.refreshStatus(); await this.refreshStatus();
if (this._model.migrationOpStatus) { if (this._model.migrationOpStatus) {
vscode.env.clipboard.writeText(JSON.stringify({ vscode.env.clipboard.writeText(JSON.stringify({
@@ -444,7 +448,7 @@ export class MigrationCutoverDialog {
} }
vscode.window.showInformationMessage(loc.DETAILS_COPIED); vscode.window.showInformationMessage(loc.DETAILS_COPIED);
}); }));
headerActions.addItem(this._copyDatabaseMigrationDetails, { headerActions.addItem(this._copyDatabaseMigrationDetails, {
flex: '0', flex: '0',

View File

@@ -31,6 +31,7 @@ export class MigrationStatusDialog {
private _statusTable!: azdata.DeclarativeTableComponent; private _statusTable!: azdata.DeclarativeTableComponent;
private _refreshLoader!: azdata.LoadingComponent; private _refreshLoader!: azdata.LoadingComponent;
private _autoRefreshHandle!: NodeJS.Timeout; private _autoRefreshHandle!: NodeJS.Timeout;
private _disposables: vscode.Disposable[] = [];
constructor(migrations: MigrationContext[], private _filter: AdsMigrationStatus) { constructor(migrations: MigrationContext[], private _filter: AdsMigrationStatus) {
this._model = new MigrationStatusDialogModel(migrations); this._model = new MigrationStatusDialogModel(migrations);
@@ -48,9 +49,9 @@ export class MigrationStatusDialog {
width: '220px' width: '220px'
}).component(); }).component();
this._statusDropdown.onValueChanged((value) => { this._disposables.push(this._statusDropdown.onValueChanged((value) => {
this.populateMigrationTable(); this.populateMigrationTable();
}); }));
if (this._filter) { if (this._filter) {
this._statusDropdown.value = (<azdata.CategoryValue[]>this._statusDropdown.values).find((value) => { this._statusDropdown.value = (<azdata.CategoryValue[]>this._statusDropdown.values).find((value) => {
@@ -76,17 +77,20 @@ export class MigrationStatusDialog {
} }
); );
const form = formBuilder.withLayout({ width: '100%' }).component(); const form = formBuilder.withLayout({ width: '100%' }).component();
this._view.onClosed(e => { this._disposables.push(this._view.onClosed(e => {
clearInterval(this._autoRefreshHandle); clearInterval(this._autoRefreshHandle);
}); this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
return view.initializeModel(form); return view.initializeModel(form);
}); });
this._dialogObject.content = [tab]; this._dialogObject.content = [tab];
this._dialogObject.cancelButton.hidden = true; this._dialogObject.cancelButton.hidden = true;
this._dialogObject.okButton.label = loc.CLOSE; this._dialogObject.okButton.label = loc.CLOSE;
this._dialogObject.okButton.onClick(e => { this._disposables.push(this._dialogObject.okButton.onClick(e => {
clearInterval(this._autoRefreshHandle); clearInterval(this._autoRefreshHandle);
}); }));
azdata.window.openDialog(this._dialogObject); azdata.window.openDialog(this._dialogObject);
} }
@@ -100,9 +104,9 @@ export class MigrationStatusDialog {
width: '360px' width: '360px'
}).component(); }).component();
this._searchBox.onTextChanged((value) => { this._disposables.push(this._searchBox.onTextChanged((value) => {
this.populateMigrationTable(); this.populateMigrationTable();
}); }));
this._refresh = this._view.modelBuilder.button().withProps({ this._refresh = this._view.modelBuilder.button().withProps({
iconPath: { iconPath: {
@@ -115,9 +119,9 @@ export class MigrationStatusDialog {
label: loc.REFRESH_BUTTON_LABEL, label: loc.REFRESH_BUTTON_LABEL,
}).component(); }).component();
this._refresh.onDidClick((e) => { this._disposables.push(this._refresh.onDidClick((e) => {
this.refreshTable(); this.refreshTable();
}); }));
const flexContainer = this._view.modelBuilder.flexContainer().withProps({ const flexContainer = this._view.modelBuilder.flexContainer().withProps({
width: 900, width: 900,
@@ -170,7 +174,7 @@ export class MigrationStatusDialog {
} }
private registerCommands(): void { private registerCommands(): void {
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.cutover', 'sqlmigration.cutover',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -186,9 +190,9 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.view.database', 'sqlmigration.view.database',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -198,9 +202,9 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.view.target', 'sqlmigration.view.target',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -210,9 +214,9 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.view.service', 'sqlmigration.view.service',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -222,9 +226,9 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.copy.migration', 'sqlmigration.copy.migration',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -244,9 +248,9 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
vscode.commands.registerCommand( this._disposables.push(vscode.commands.registerCommand(
'sqlmigration.cancel.migration', 'sqlmigration.cancel.migration',
async (migrationId: string) => { async (migrationId: string) => {
try { try {
@@ -265,7 +269,7 @@ export class MigrationStatusDialog {
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} }
}); }));
} }
private async populateMigrationTable(): Promise<void> { private async populateMigrationTable(): Promise<void> {
@@ -336,8 +340,8 @@ export class MigrationStatusDialog {
CSSStyles: statusCellStyles CSSStyles: statusCellStyles
}).component(); }).component();
databaseHyperLink.onDidClick( this._disposables.push(databaseHyperLink.onDidClick(
async (e) => await (new MigrationCutoverDialog(migration)).initialize()); async (e) => await (new MigrationCutoverDialog(migration)).initialize()));
return this._view.modelBuilder return this._view.modelBuilder
.flexContainer() .flexContainer()
@@ -563,7 +567,7 @@ export class MigrationStatusDialog {
return IconPathHelper.notStartedMigration; return IconPathHelper.notStartedMigration;
case 'Completing': case 'Completing':
return IconPathHelper.completingCutover; return IconPathHelper.completingCutover;
case 'Cancelling': case 'Canceling':
return IconPathHelper.cancel; return IconPathHelper.cancel;
case 'Failed': case 'Failed':
default: default:

View File

@@ -30,6 +30,7 @@ export class SqlMigrationServiceDetailsDialog {
private _dialog: azdata.window.Dialog; private _dialog: azdata.window.Dialog;
private _migrationServiceAuthKeyTable!: azdata.DeclarativeTableComponent; private _migrationServiceAuthKeyTable!: azdata.DeclarativeTableComponent;
private _disposables: vscode.Disposable[] = [];
constructor(private migrationContext: MigrationContext) { constructor(private migrationContext: MigrationContext) {
this._dialog = azdata.window.createModelViewDialog( this._dialog = azdata.window.createModelViewDialog(
@@ -41,9 +42,16 @@ export class SqlMigrationServiceDetailsDialog {
async initialize(): Promise<void> { async initialize(): Promise<void> {
this._dialog.registerContent( this._dialog.registerContent(
async (view: azdata.ModelView) => await this.createServiceContent( async (view: azdata.ModelView) => {
view, this._disposables.push(view.onClosed(e => {
this.migrationContext)); this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await this.createServiceContent(
view,
this.migrationContext);
});
this._dialog.okButton.label = constants.SQL_MIGRATION_SERVICE_DETAILS_BUTTON_LABEL; this._dialog.okButton.label = constants.SQL_MIGRATION_SERVICE_DETAILS_BUTTON_LABEL;
this._dialog.okButton.focused = true; this._dialog.okButton.focused = true;
@@ -238,10 +246,10 @@ export class SqlMigrationServiceDetailsDialog {
}) })
.component(); .component();
copyKey1Button.onDidClick((e) => { this._disposables.push(copyKey1Button.onDidClick((e) => {
vscode.env.clipboard.writeText(keys.authKey1); vscode.env.clipboard.writeText(keys.authKey1);
vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}); }));
const copyKey2Button = view.modelBuilder const copyKey2Button = view.modelBuilder
.button() .button()
@@ -254,10 +262,10 @@ export class SqlMigrationServiceDetailsDialog {
}) })
.component(); .component();
copyKey2Button.onDidClick((e) => { this._disposables.push(copyKey2Button.onDidClick((e) => {
vscode.env.clipboard.writeText(keys.authKey2); vscode.env.clipboard.writeText(keys.authKey2);
vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}); }));
const refreshKey1Button = view.modelBuilder const refreshKey1Button = view.modelBuilder
.button() .button()
@@ -269,8 +277,8 @@ export class SqlMigrationServiceDetailsDialog {
ariaLabel: constants.REFRESH_KEY1, ariaLabel: constants.REFRESH_KEY1,
}) })
.component(); .component();
refreshKey1Button.onDidClick( this._disposables.push(refreshKey1Button.onDidClick(
async (e) => await this._regenerateAuthKey(view, migrationContext, AUTH_KEY1)); async (e) => await this._regenerateAuthKey(view, migrationContext, AUTH_KEY1)));
const refreshKey2Button = view.modelBuilder const refreshKey2Button = view.modelBuilder
.button() .button()
@@ -282,8 +290,8 @@ export class SqlMigrationServiceDetailsDialog {
ariaLabel: constants.REFRESH_KEY2, ariaLabel: constants.REFRESH_KEY2,
}) })
.component(); .component();
refreshKey2Button.onDidClick( this._disposables.push(refreshKey2Button.onDidClick(
async (e) => await this._regenerateAuthKey(view, migrationContext, AUTH_KEY2)); async (e) => await this._regenerateAuthKey(view, migrationContext, AUTH_KEY2)));
this._migrationServiceAuthKeyTable.updateProperties({ this._migrationServiceAuthKeyTable.updateProperties({
dataValues: [ dataValues: [

View File

@@ -36,7 +36,7 @@ class SQLMigration {
input.items = NotebookPathHelper.getAllMigrationNotebooks(); input.items = NotebookPathHelper.getAllMigrationNotebooks();
input.onDidAccept(async (e) => { this.context.subscriptions.push(input.onDidAccept(async (e) => {
const selectedNotebook = input.selectedItems[0]; const selectedNotebook = input.selectedItems[0];
if (selectedNotebook) { if (selectedNotebook) {
try { try {
@@ -50,7 +50,7 @@ class SQLMigration {
} }
input.hide(); input.hide();
} }
}); }));
input.show(); input.show();
}), }),

View File

@@ -16,6 +16,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
private _azureAccountsDropdown!: azdata.DropDownComponent; private _azureAccountsDropdown!: azdata.DropDownComponent;
private _accountTenantDropdown!: azdata.DropDownComponent; private _accountTenantDropdown!: azdata.DropDownComponent;
private _accountTenantFlexContainer!: azdata.FlexContainer; private _accountTenantFlexContainer!: azdata.FlexContainer;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.ACCOUNTS_SELECTION_PAGE_TITLE), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.ACCOUNTS_SELECTION_PAGE_TITLE), migrationStateModel);
@@ -32,6 +33,9 @@ export class AccountsSelectionPage extends MigrationWizardPage {
); );
await view.initializeModel(form.component()); await view.initializeModel(form.component());
await this.populateAzureAccountsDropdown(); await this.populateAzureAccountsDropdown();
this._disposables.push(view.onClosed(e =>
this._disposables.forEach(
d => { try { d.dispose(); } catch { } })));
} }
private createAzureAccountsDropdown(view: azdata.ModelView): azdata.FormComponent { private createAzureAccountsDropdown(view: azdata.ModelView): azdata.FormComponent {
@@ -74,7 +78,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
return false; return false;
}).component(); }).component();
this._azureAccountsDropdown.onValueChanged(async (value) => { this._disposables.push(this._azureAccountsDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._azureAccountsDropdown, value); const selectedIndex = findDropDownItemIndex(this._azureAccountsDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
const selectedAzureAccount = this.migrationStateModel.getAccount(selectedIndex); const selectedAzureAccount = this.migrationStateModel.getAccount(selectedIndex);
@@ -97,7 +101,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this.migrationStateModel._databaseBackup.subscription = undefined!; this.migrationStateModel._databaseBackup.subscription = undefined!;
await this._azureAccountsDropdown.validate(); await this._azureAccountsDropdown.validate();
} }
}); }));
const linkAccountButton = view.modelBuilder.hyperlink() const linkAccountButton = view.modelBuilder.hyperlink()
.withProps({ .withProps({
@@ -109,14 +113,14 @@ export class AccountsSelectionPage extends MigrationWizardPage {
}) })
.component(); .component();
linkAccountButton.onDidClick(async (event) => { this._disposables.push(linkAccountButton.onDidClick(async (event) => {
await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount'); await vscode.commands.executeCommand('workbench.actions.modal.linkedAccount');
await this.populateAzureAccountsDropdown(); await this.populateAzureAccountsDropdown();
this.wizard.message = { this.wizard.message = {
text: '' text: ''
}; };
this._azureAccountsDropdown.validate(); this._azureAccountsDropdown.validate();
}); }));
const flexContainer = view.modelBuilder.flexContainer() const flexContainer = view.modelBuilder.flexContainer()
.withLayout({ .withLayout({
@@ -152,7 +156,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._accountTenantDropdown.onValueChanged(value => { this._disposables.push(this._accountTenantDropdown.onValueChanged(value => {
/** /**
* 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
@@ -164,7 +168,7 @@ export class AccountsSelectionPage extends MigrationWizardPage {
this.migrationStateModel._targetSubscription = undefined!; this.migrationStateModel._targetSubscription = undefined!;
this.migrationStateModel._databaseBackup.subscription = undefined!; this.migrationStateModel._databaseBackup.subscription = undefined!;
} }
}); }));
this._accountTenantFlexContainer = view.modelBuilder.flexContainer() this._accountTenantFlexContainer = view.modelBuilder.flexContainer()
.withLayout({ .withLayout({

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { EOL } from 'os'; import { EOL } from 'os';
import { getStorageAccountAccessKeys } from '../api/azure'; import { getStorageAccountAccessKeys } from '../api/azure';
import { MigrationWizardPage } from '../models/migrationWizardPage'; import { MigrationWizardPage } from '../models/migrationWizardPage';
@@ -48,8 +49,8 @@ export class DatabaseBackupPage extends MigrationWizardPage {
private _networkShareTargetDatabaseNames: azdata.InputBoxComponent[] = []; private _networkShareTargetDatabaseNames: azdata.InputBoxComponent[] = [];
private _blobContainerTargetDatabaseNames: azdata.InputBoxComponent[] = []; private _blobContainerTargetDatabaseNames: azdata.InputBoxComponent[] = [];
private _existingDatabases: string[] = []; private _existingDatabases: string[] = [];
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_PAGE_TITLE), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_PAGE_TITLE), migrationStateModel);
@@ -87,9 +88,13 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
] ]
); );
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(form.component()); await view.initializeModel(form.component());
} }
private createBackupLocationComponent(): azdata.FlexContainer { private createBackupLocationComponent(): azdata.FlexContainer {
@@ -111,11 +116,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
}).component(); }).component();
networkShareButton.onDidChangeCheckedState((e) => { this._disposables.push(networkShareButton.onDidChangeCheckedState((e) => {
if (e) { if (e) {
this.switchNetworkContainerFields(NetworkContainerType.NETWORK_SHARE); this.switchNetworkContainerFields(NetworkContainerType.NETWORK_SHARE);
} }
}); }));
const blobContainerButton = this._view.modelBuilder.radioButton() const blobContainerButton = this._view.modelBuilder.radioButton()
.withProps({ .withProps({
@@ -126,11 +131,11 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
}).component(); }).component();
blobContainerButton.onDidChangeCheckedState((e) => { this._disposables.push(blobContainerButton.onDidChangeCheckedState((e) => {
if (e) { if (e) {
this.switchNetworkContainerFields(NetworkContainerType.BLOB_CONTAINER); this.switchNetworkContainerFields(NetworkContainerType.BLOB_CONTAINER);
} }
}); }));
const flexContainer = this._view.modelBuilder.flexContainer().withItems( const flexContainer = this._view.modelBuilder.flexContainer().withItems(
[ [
@@ -189,9 +194,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
enabled: false, enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH
}).component(); }).component();
this._sqlSourceUsernameInput.onTextChanged(value => { this._disposables.push(this._sqlSourceUsernameInput.onTextChanged(value => {
this.migrationStateModel._sqlServerUsername = value; this.migrationStateModel._sqlServerUsername = value;
}); }));
const sqlPasswordLabel = this._view.modelBuilder.text().withProps({ const sqlPasswordLabel = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL, value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL,
@@ -206,9 +211,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
inputType: 'password', inputType: 'password',
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH
}).component(); }).component();
this._sqlSourcepassword.onTextChanged(value => { this._disposables.push(this._sqlSourcepassword.onTextChanged(value => {
this.migrationStateModel._sqlServerPassword = value; this.migrationStateModel._sqlServerPassword = value;
}); }));
const networkShareHeading = this._view.modelBuilder.text().withProps({ const networkShareHeading = this._view.modelBuilder.text().withProps({
@@ -254,10 +259,10 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
return true; return true;
}).component(); }).component();
this._networkSharePath.onTextChanged((value) => { this._disposables.push(this._networkSharePath.onTextChanged((value) => {
this.validateFields(); this.validateFields();
this.migrationStateModel._databaseBackup.networkShare.networkShareLocation = value; this.migrationStateModel._databaseBackup.networkShare.networkShareLocation = value;
}); }));
const networkShareInfoBox = this._view.modelBuilder.infoBox().withProps({ const networkShareInfoBox = this._view.modelBuilder.infoBox().withProps({
text: constants.DATABASE_SERVICE_ACCOUNT_INFO_TEXT, text: constants.DATABASE_SERVICE_ACCOUNT_INFO_TEXT,
@@ -295,9 +300,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
return true; return true;
}).component(); }).component();
this._windowsUserAccountText.onTextChanged((value) => { this._disposables.push(this._windowsUserAccountText.onTextChanged((value) => {
this.migrationStateModel._databaseBackup.networkShare.windowsUser = value; this.migrationStateModel._databaseBackup.networkShare.windowsUser = value;
}); }));
const passwordLabel = this._view.modelBuilder.text() const passwordLabel = this._view.modelBuilder.text()
.withProps({ .withProps({
@@ -315,12 +320,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
required: true, required: true,
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH
}).component(); }).component();
this._passwordText.onTextChanged((value) => { this._disposables.push(this._passwordText.onTextChanged((value) => {
this.migrationStateModel._databaseBackup.networkShare.password = value; this.migrationStateModel._databaseBackup.networkShare.password = value;
}); }));
const flexContainer = this._view.modelBuilder.flexContainer().withItems( const flexContainer = this._view.modelBuilder.flexContainer().withItems(
[ [
@@ -560,13 +562,13 @@ export class DatabaseBackupPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._networkShareStorageAccountResourceGroupDropdown.onValueChanged(async (value) => { this._disposables.push(this._networkShareStorageAccountResourceGroupDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._networkShareStorageAccountResourceGroupDropdown, value); const selectedIndex = findDropDownItemIndex(this._networkShareStorageAccountResourceGroupDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
this.migrationStateModel._databaseBackup.networkShare.resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex); this.migrationStateModel._databaseBackup.networkShare.resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
await this.loadNetworkShareStorageDropdown(); await this.loadNetworkShareStorageDropdown();
} }
}); }));
const storageAccountLabel = this._view.modelBuilder.text() const storageAccountLabel = this._view.modelBuilder.text()
.withProps({ .withProps({
@@ -585,12 +587,12 @@ export class DatabaseBackupPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => { this._disposables.push(this._networkShareContainerStorageAccountDropdown.onValueChanged((value) => {
const selectedIndex = findDropDownItemIndex(this._networkShareContainerStorageAccountDropdown, value); const selectedIndex = findDropDownItemIndex(this._networkShareContainerStorageAccountDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
this.migrationStateModel._databaseBackup.networkShare.storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex); this.migrationStateModel._databaseBackup.networkShare.storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex);
} }
}); }));
this._networkShareContainerStorageAccountRefreshButton = this._view.modelBuilder.button().withProps({ this._networkShareContainerStorageAccountRefreshButton = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.refresh, iconPath: IconPathHelper.refresh,
@@ -600,9 +602,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
ariaLabel: constants.REFRESH, ariaLabel: constants.REFRESH,
}).component(); }).component();
this._networkShareContainerStorageAccountRefreshButton.onDidClick(async (value) => { this._disposables.push(this._networkShareContainerStorageAccountRefreshButton.onDidClick(async (value) => {
await this.loadNetworkShareStorageDropdown(); await this.loadNetworkShareStorageDropdown();
}); }));
const storageAccountContainer = this._view.modelBuilder.flexContainer().component(); const storageAccountContainer = this._view.modelBuilder.flexContainer().component();
@@ -685,10 +687,10 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
return true; return true;
}).component(); }).component();
targetDatabaseInput.onTextChanged((value) => { this._disposables.push(targetDatabaseInput.onTextChanged((value) => {
this.migrationStateModel._targetDatabaseNames[index] = value.trim(); this.migrationStateModel._targetDatabaseNames[index] = value.trim();
this.validateFields(); this.validateFields();
}); }));
this._networkShareTargetDatabaseNames.push(targetDatabaseInput); this._networkShareTargetDatabaseNames.push(targetDatabaseInput);
const blobtargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({ const blobtargetDatabaseInput = this._view.modelBuilder.inputBox().withProps({
@@ -710,9 +712,9 @@ export class DatabaseBackupPage extends MigrationWizardPage {
} }
return true; return true;
}).component(); }).component();
blobtargetDatabaseInput.onTextChanged((value) => { this._disposables.push(blobtargetDatabaseInput.onTextChanged((value) => {
this.migrationStateModel._targetDatabaseNames[index] = value.trim(); this.migrationStateModel._targetDatabaseNames[index] = value.trim();
}); }));
this._blobContainerTargetDatabaseNames.push(blobtargetDatabaseInput); this._blobContainerTargetDatabaseNames.push(blobtargetDatabaseInput);
const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({ const blobContainerResourceDropdown = this._view.modelBuilder.dropDown().withProps({
@@ -721,14 +723,14 @@ export class DatabaseBackupPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
blobContainerResourceDropdown.onValueChanged(async (value) => { this._disposables.push(blobContainerResourceDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(blobContainerResourceDropdown, value); const selectedIndex = findDropDownItemIndex(blobContainerResourceDropdown, value);
if (selectedIndex > -1 && value !== constants.RESOURCE_GROUP_NOT_FOUND) { if (selectedIndex > -1 && value !== constants.RESOURCE_GROUP_NOT_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex); this.migrationStateModel._databaseBackup.blobs[index].resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
} }
await 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()
@@ -739,13 +741,13 @@ export class DatabaseBackupPage extends MigrationWizardPage {
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
blobContainerStorageAccountDropdown.onValueChanged(async (value) => { this._disposables.push(blobContainerStorageAccountDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(blobContainerStorageAccountDropdown, value); const selectedIndex = findDropDownItemIndex(blobContainerStorageAccountDropdown, value);
if (selectedIndex > -1 && value !== constants.NO_STORAGE_ACCOUNT_FOUND) { if (selectedIndex > -1 && value !== constants.NO_STORAGE_ACCOUNT_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex); this.migrationStateModel._databaseBackup.blobs[index].storageAccount = this.migrationStateModel.getStorageAccount(selectedIndex);
} }
await this.loadBlobContainerDropdown(index); await this.loadBlobContainerDropdown(index);
}); }));
this._blobContainerStorageAccountDropdowns.push(blobContainerStorageAccountDropdown); this._blobContainerStorageAccountDropdowns.push(blobContainerStorageAccountDropdown);
const blobContainerDropdown = this._view.modelBuilder.dropDown() const blobContainerDropdown = this._view.modelBuilder.dropDown()
@@ -755,12 +757,12 @@ export class DatabaseBackupPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
blobContainerDropdown.onValueChanged(value => { this._disposables.push(blobContainerDropdown.onValueChanged(value => {
const selectedIndex = findDropDownItemIndex(blobContainerDropdown, value); const selectedIndex = findDropDownItemIndex(blobContainerDropdown, value);
if (selectedIndex > -1 && value !== constants.NO_BLOBCONTAINERS_FOUND) { if (selectedIndex > -1 && value !== constants.NO_BLOBCONTAINERS_FOUND) {
this.migrationStateModel._databaseBackup.blobs[index].blobContainer = this.migrationStateModel.getBlobContainer(selectedIndex); this.migrationStateModel._databaseBackup.blobs[index].blobContainer = this.migrationStateModel.getBlobContainer(selectedIndex);
} }
}); }));
this._blobContainerDropdowns.push(blobContainerDropdown); this._blobContainerDropdowns.push(blobContainerDropdown);
}); });

View File

@@ -4,10 +4,11 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage'; 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 { IconPath, IconPathHelper } from '../constants/iconPathHelper'; // import { IconPath, IconPathHelper } from '../constants/iconPathHelper';
import { debounce } from '../api/utils'; import { debounce } from '../api/utils';
const headerLeft: azdata.CssStyles = { const headerLeft: azdata.CssStyles = {
@@ -41,6 +42,7 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
private _dbNames!: string[]; private _dbNames!: string[];
private _dbCount!: azdata.TextComponent; private _dbCount!: azdata.TextComponent;
private _databaseTableValues!: azdata.DeclarativeTableCellValue[][]; private _databaseTableValues!: azdata.DeclarativeTableCellValue[][];
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel);
@@ -56,6 +58,11 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
}).component(); }).component();
flex.addItem(await this.createRootContainer(view), { flex: '1 1 auto' }); flex.addItem(await this.createRootContainer(view), { flex: '1 1 auto' });
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(flex); await view.initializeModel(flex);
} }
@@ -82,7 +89,7 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
width: 200 width: 200
}).component(); }).component();
resourceSearchBox.onTextChanged(value => this._filterTableList(value)); this._disposables.push(resourceSearchBox.onTextChanged(value => this._filterTableList(value)));
const searchContainer = this._view.modelBuilder.divContainer().withItems([resourceSearchBox]).withProps({ const searchContainer = this._view.modelBuilder.divContainer().withItems([resourceSearchBox]).withProps({
CSSStyles: { CSSStyles: {
@@ -142,7 +149,8 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
enabled: selectable enabled: selectable
}, },
{ {
value: this.createIconTextCell(IconPathHelper.sqlDatabaseLogo, finalResult[index].options.name), // value: this.createIconTextCell(IconPathHelper.sqlDatabaseLogo, finalResult[index].options.name),
value: finalResult[index].options.name,
style: styleLeft style: styleLeft
}, },
{ {
@@ -207,7 +215,8 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
}, },
{ {
displayName: constants.DATABASE, displayName: constants.DATABASE,
valueType: azdata.DeclarativeDataType.component, // valueType: azdata.DeclarativeDataType.component,
valueType: azdata.DeclarativeDataType.string,
width: 100, width: 100,
isReadOnly: true, isReadOnly: true,
headerCssStyles: headerLeft headerCssStyles: headerLeft
@@ -238,11 +247,11 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
).component(); ).component();
await this._databaseSelectorTable.setDataValues(this._databaseTableValues); await this._databaseSelectorTable.setDataValues(this._databaseTableValues);
this._databaseSelectorTable.onDataChanged(() => { this._disposables.push(this._databaseSelectorTable.onDataChanged(() => {
this._dbCount.updateProperties({ this._dbCount.updateProperties({
'value': constants.DATABASES_SELECTED(this.selectedDbs().length, this._databaseTableValues.length) 'value': constants.DATABASES_SELECTED(this.selectedDbs().length, this._databaseTableValues.length)
}); });
}); }));
const flex = view.modelBuilder.flexContainer().withLayout({ const flex = view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column', flexFlow: 'column',
height: '100%', height: '100%',
@@ -271,42 +280,41 @@ export class DatabaseSelectorPage extends MigrationWizardPage {
return result; return result;
} }
private createIconTextCell(icon: IconPath, text: string): azdata.FlexContainer { // private createIconTextCell(icon: IconPath, text: string): azdata.FlexContainer {
// const iconComponent = this._view.modelBuilder.image().withProps({
// iconPath: icon,
// iconWidth: '16px',
// iconHeight: '16px',
// width: '20px',
// height: '20px'
// }).component();
// const textComponent = this._view.modelBuilder.text().withProps({
// value: text,
// title: text,
// CSSStyles: {
// 'margin': '0px',
// 'width': '110px'
// }
// }).component();
const iconComponent = this._view.modelBuilder.image().withProps({ // const cellContainer = this._view.modelBuilder.flexContainer().withProps({
iconPath: icon, // CSSStyles: {
iconWidth: '16px', // 'justify-content': 'left'
iconHeight: '16px', // }
width: '20px', // }).component();
height: '20px' // cellContainer.addItem(iconComponent, {
}).component(); // flex: '0',
const textComponent = this._view.modelBuilder.text().withProps({ // CSSStyles: {
value: text, // 'width': '32px'
title: text, // }
CSSStyles: { // });
'margin': '0px', // cellContainer.addItem(textComponent, {
'width': '110px' // CSSStyles: {
} // 'width': 'auto'
}).component(); // }
// });
const cellContainer = this._view.modelBuilder.flexContainer().withProps({ // return cellContainer;
CSSStyles: { // }
'justify-content': 'left'
}
}).component();
cellContainer.addItem(iconComponent, {
flex: '0',
CSSStyles: {
'width': '32px'
}
});
cellContainer.addItem(textComponent, {
CSSStyles: {
'width': 'auto'
}
});
return cellContainer;
}
} }

View File

@@ -34,6 +34,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
private _copy2!: azdata.ButtonComponent; private _copy2!: azdata.ButtonComponent;
private _refresh1!: azdata.ButtonComponent; private _refresh1!: azdata.ButtonComponent;
private _refresh2!: azdata.ButtonComponent; private _refresh2!: azdata.ButtonComponent;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.IR_PAGE_TITLE), migrationStateModel);
@@ -50,14 +51,14 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
} }
}).component(); }).component();
createNewMigrationService.onDidClick(async (e) => { this._disposables.push(createNewMigrationService.onDidClick(async (e) => {
const dialog = new CreateSqlMigrationServiceDialog(); const dialog = new CreateSqlMigrationServiceDialog();
const createdDmsResult = await dialog.createNewDms(this.migrationStateModel, (<azdata.CategoryValue>this._resourceGroupDropdown.value).displayName); const createdDmsResult = await dialog.createNewDms(this.migrationStateModel, (<azdata.CategoryValue>this._resourceGroupDropdown.value).displayName);
this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup; this.migrationStateModel._sqlMigrationServiceResourceGroup = createdDmsResult.resourceGroup;
this.migrationStateModel._sqlMigrationService = createdDmsResult.service; this.migrationStateModel._sqlMigrationService = createdDmsResult.service;
await this.loadResourceGroupDropdown(); await this.loadResourceGroupDropdown();
await this.populateDms(createdDmsResult.resourceGroup); await this.populateDms(createdDmsResult.resourceGroup);
}); }));
this._statusLoadingComponent = view.modelBuilder.loadingComponent().withItem(this.createDMSDetailsContainer()).component(); this._statusLoadingComponent = view.modelBuilder.loadingComponent().withItem(this.createDMSDetailsContainer()).component();
@@ -91,6 +92,12 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
] ]
); );
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(this._form.component()); await view.initializeModel(this._form.component());
} }
@@ -187,12 +194,12 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._resourceGroupDropdown.onValueChanged(async (value) => { this._disposables.push(this._resourceGroupDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._resourceGroupDropdown, value); const selectedIndex = findDropDownItemIndex(this._resourceGroupDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
await this.populateDms(value); await this.populateDms(value);
} }
}); }));
const migrationServcieDropdownLabel = this._view.modelBuilder.text().withProps({ const migrationServcieDropdownLabel = this._view.modelBuilder.text().withProps({
value: constants.IR_PAGE_TITLE, value: constants.IR_PAGE_TITLE,
@@ -209,7 +216,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._dmsDropdown.onValueChanged(async (value) => { this._disposables.push(this._dmsDropdown.onValueChanged(async (value) => {
if (value && value !== constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR) { if (value && value !== constants.SQL_MIGRATION_SERVICE_NOT_FOUND_ERROR) {
if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) { if (this.migrationStateModel._databaseBackup.networkContainerType === NetworkContainerType.NETWORK_SHARE) {
this._dmsInfoContainer.display = 'inline'; this._dmsInfoContainer.display = 'inline';
@@ -225,7 +232,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
} else { } else {
this._dmsInfoContainer.display = 'none'; this._dmsInfoContainer.display = 'none';
} }
}); }));
const flexContainer = this._view.modelBuilder.flexContainer().withItems([ const flexContainer = this._view.modelBuilder.flexContainer().withItems([
descriptionText, descriptionText,
@@ -267,14 +274,14 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
ariaLabel: constants.REFRESH, ariaLabel: constants.REFRESH,
}).component(); }).component();
this._refreshButton.onDidClick(async (e) => { this._disposables.push(this._refreshButton.onDidClick(async (e) => {
this._connectionStatusLoader.loading = true; this._connectionStatusLoader.loading = true;
try { try {
await this.loadStatus(); await this.loadStatus();
} finally { } finally {
this._connectionStatusLoader.loading = false; this._connectionStatusLoader.loading = false;
} }
}); }));
const connectionLabelContainer = this._view.modelBuilder.flexContainer().withProps({ const connectionLabelContainer = this._view.modelBuilder.flexContainer().withProps({
CSSStyles: { CSSStyles: {
@@ -318,10 +325,10 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
ariaLabel: constants.COPY_KEY1, ariaLabel: constants.COPY_KEY1,
}).component(); }).component();
this._copy1.onDidClick(async (e) => { this._disposables.push(this._copy1.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![0][1].value); await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![0][1].value);
vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY1_COPIED_HELP);
}); }));
this._copy2 = this._view.modelBuilder.button().withProps({ this._copy2 = this._view.modelBuilder.button().withProps({
title: constants.COPY_KEY2, title: constants.COPY_KEY2,
@@ -329,10 +336,10 @@ export class IntergrationRuntimePage extends MigrationWizardPage {
ariaLabel: constants.COPY_KEY2, ariaLabel: constants.COPY_KEY2,
}).component(); }).component();
this._copy2.onDidClick(async (e) => { this._disposables.push(this._copy2.onDidClick(async (e) => {
await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![1][1].value); await vscode.env.clipboard.writeText(<string>this._authKeyTable.dataValues![1][1].value);
vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP); vscode.window.showInformationMessage(constants.SERVICE_KEY2_COPIED_HELP);
}); }));
this._refresh1 = this._view.modelBuilder.button().withProps({ this._refresh1 = this._view.modelBuilder.button().withProps({
title: constants.REFRESH_KEY1, title: constants.REFRESH_KEY1,

View File

@@ -11,6 +11,7 @@ import * as constants from '../constants/strings';
export class MigrationModePage extends MigrationWizardPage { export class MigrationModePage extends MigrationWizardPage {
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL, 'MigrationModePage'), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.DATABASE_BACKUP_MIGRATION_MODE_LABEL, 'MigrationModePage'), migrationStateModel);
@@ -25,6 +26,11 @@ export class MigrationModePage extends MigrationWizardPage {
this.migrationModeContainer(), this.migrationModeContainer(),
] ]
); );
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(form.component()); await view.initializeModel(form.component());
} }
@@ -64,11 +70,11 @@ export class MigrationModePage extends MigrationWizardPage {
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.ONLINE; this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.ONLINE;
onlineButton.onDidChangeCheckedState((e) => { this._disposables.push(onlineButton.onDidChangeCheckedState((e) => {
if (e) { if (e) {
this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.ONLINE; this.migrationStateModel._databaseBackup.migrationMode = MigrationMode.ONLINE;
} }
}); }));
const offlineButton = this._view.modelBuilder.radioButton().withProps({ const offlineButton = this._view.modelBuilder.radioButton().withProps({
label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL, label: constants.DATABASE_BACKUP_MIGRATION_MODE_OFFLINE_LABEL,
@@ -88,13 +94,13 @@ export class MigrationModePage extends MigrationWizardPage {
}).component(); }).component();
offlineButton.onDidChangeCheckedState((e) => { this._disposables.push(offlineButton.onDidChangeCheckedState((e) => {
if (e) { if (e) {
vscode.window.showInformationMessage('Feature coming soon'); vscode.window.showInformationMessage('Feature coming soon');
onlineButton.checked = true; onlineButton.checked = true;
//this.migrationStateModel._databaseBackup.migrationCutover = MigrationCutover.OFFLINE; TODO: Enable when offline mode is supported. //this.migrationStateModel._databaseBackup.migrationCutover = MigrationCutover.OFFLINE; TODO: Enable when offline mode is supported.
} }
}); }));
const flexContainer = this._view.modelBuilder.flexContainer().withItems( const flexContainer = this._view.modelBuilder.flexContainer().withItems(
[ [

View File

@@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage'; import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationStateModel, MigrationTargetType, StateChangeEvent } from '../models/stateMachine'; import { MigrationStateModel, MigrationTargetType, StateChangeEvent } from '../models/stateMachine';
import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog'; import { AssessmentResultsDialog } from '../dialog/assessmentResults/assessmentResultsDialog';
import * as constants from '../constants/strings'; import * as constants from '../constants/strings';
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';
@@ -46,6 +46,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
private _databaseSelectedHelperText!: azdata.TextComponent; private _databaseSelectedHelperText!: azdata.TextComponent;
private assessmentGroupContainer!: azdata.FlexContainer; private assessmentGroupContainer!: azdata.FlexContainer;
private _targetContainer!: azdata.FlexContainer; private _targetContainer!: azdata.FlexContainer;
private _disposables: vscode.Disposable[] = [];
private _supportedProducts: Product[] = [ private _supportedProducts: Product[] = [
{ {
@@ -148,6 +149,11 @@ export class SKURecommendationPage extends MigrationWizardPage {
this._rootContainer.addItem(this._assessmentComponent, { flex: '0 0 auto' }); this._rootContainer.addItem(this._assessmentComponent, { flex: '0 0 auto' });
this._rootContainer.addItem(this._formContainer.component(), { flex: '0 0 auto' }); this._rootContainer.addItem(this._formContainer.component(), { flex: '0 0 auto' });
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await this._view.initializeModel(this._rootContainer); await this._view.initializeModel(this._rootContainer);
} }
@@ -209,12 +215,12 @@ export class SKURecommendationPage extends MigrationWizardPage {
}); });
}); });
this._rbg.onSelectionChanged((value) => { this._disposables.push(this._rbg.onSelectionChanged((value) => {
if (value) { if (value) {
this.assessmentGroupContainer.display = 'inline'; this.assessmentGroupContainer.display = 'inline';
this.changeTargetType(value.cardId); this.changeTargetType(value.cardId);
} }
}); }));
this._rbgLoader = this._view.modelBuilder.loadingComponent().withItem( this._rbgLoader = this._view.modelBuilder.loadingComponent().withItem(
this._rbg this._rbg
@@ -247,7 +253,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLMI); let miDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLMI);
let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLVM); let vmDialog = new AssessmentResultsDialog('ownerUri', this.migrationStateModel, constants.ASSESSMENT_TILE(serverName), this, MigrationTargetType.SQLVM);
button.onDidClick(async (e) => { this._disposables.push(button.onDidClick(async (e) => {
if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) { if (this._rbg.selectedCardId === MigrationTargetType.SQLVM) {
this._rbg.selectedCardId = MigrationTargetType.SQLVM; this._rbg.selectedCardId = MigrationTargetType.SQLVM;
await vmDialog.openDialog(); await vmDialog.openDialog();
@@ -255,7 +261,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
this._rbg.selectedCardId = MigrationTargetType.SQLMI; this._rbg.selectedCardId = MigrationTargetType.SQLMI;
await miDialog.openDialog(); await miDialog.openDialog();
} }
}); }));
this._databaseSelectedHelperText = this._view.modelBuilder.text().withProps({ this._databaseSelectedHelperText = this._view.modelBuilder.text().withProps({
CSSStyles: { CSSStyles: {
@@ -296,7 +302,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._managedInstanceSubscriptionDropdown.onValueChanged(async (value) => { this._disposables.push(this._managedInstanceSubscriptionDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._managedInstanceSubscriptionDropdown, value); const selectedIndex = findDropDownItemIndex(this._managedInstanceSubscriptionDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex); this.migrationStateModel._targetSubscription = this.migrationStateModel.getSubscription(selectedIndex);
@@ -304,7 +310,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
this.migrationStateModel._sqlMigrationService = undefined!; this.migrationStateModel._sqlMigrationService = undefined!;
await this.populateLocationAndResourceGroupDropdown(); await this.populateLocationAndResourceGroupDropdown();
} }
}); }));
const azureLocationLabel = this._view.modelBuilder.text().withProps({ const azureLocationLabel = this._view.modelBuilder.text().withProps({
value: constants.LOCATION, value: constants.LOCATION,
@@ -320,13 +326,13 @@ export class SKURecommendationPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._azureLocationDropdown.onValueChanged(async (value) => { this._disposables.push(this._azureLocationDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._azureLocationDropdown, value); const selectedIndex = findDropDownItemIndex(this._azureLocationDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
this.migrationStateModel._location = this.migrationStateModel.getLocation(selectedIndex); this.migrationStateModel._location = this.migrationStateModel.getLocation(selectedIndex);
await this.populateResourceInstanceDropdown(); await this.populateResourceInstanceDropdown();
} }
}); }));
const azureResourceGroupLabel = this._view.modelBuilder.text().withProps({ const azureResourceGroupLabel = this._view.modelBuilder.text().withProps({
value: constants.RESOURCE_GROUP, value: constants.RESOURCE_GROUP,
@@ -342,13 +348,13 @@ export class SKURecommendationPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._azureResourceGroupDropdown.onValueChanged(async (value) => { this._disposables.push(this._azureResourceGroupDropdown.onValueChanged(async (value) => {
const selectedIndex = findDropDownItemIndex(this._azureResourceGroupDropdown, value); const selectedIndex = findDropDownItemIndex(this._azureResourceGroupDropdown, value);
if (selectedIndex > -1) { if (selectedIndex > -1) {
this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex); this.migrationStateModel._resourceGroup = this.migrationStateModel.getAzureResourceGroup(selectedIndex);
await this.populateResourceInstanceDropdown(); await this.populateResourceInstanceDropdown();
} }
}); }));
this._resourceDropdownLabel = this._view.modelBuilder.text().withProps({ this._resourceDropdownLabel = this._view.modelBuilder.text().withProps({
value: constants.MANAGED_INSTANCE, value: constants.MANAGED_INSTANCE,
width: WIZARD_INPUT_COMPONENT_WIDTH, width: WIZARD_INPUT_COMPONENT_WIDTH,
@@ -364,7 +370,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
editable: true, editable: true,
fireOnTextChange: true, fireOnTextChange: true,
}).component(); }).component();
this._resourceDropdown.onValueChanged(value => { this._disposables.push(this._resourceDropdown.onValueChanged(value => {
const selectedIndex = findDropDownItemIndex(this._resourceDropdown, value); const selectedIndex = findDropDownItemIndex(this._resourceDropdown, value);
if (selectedIndex > -1 && if (selectedIndex > -1 &&
value !== constants.NO_MANAGED_INSTANCE_FOUND && value !== constants.NO_MANAGED_INSTANCE_FOUND &&
@@ -376,7 +382,7 @@ export class SKURecommendationPage extends MigrationWizardPage {
this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(selectedIndex); this.migrationStateModel._targetServerInstance = this.migrationStateModel.getManagedInstance(selectedIndex);
} }
} }
}); }));
return this._view.modelBuilder.flexContainer().withItems( return this._view.modelBuilder.flexContainer().withItems(
[ [

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage'; import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationSourceAuthenticationType, MigrationStateModel, StateChangeEvent } from '../models/stateMachine'; import { MigrationSourceAuthenticationType, MigrationStateModel, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../constants/strings'; import * as constants from '../constants/strings';
@@ -13,6 +14,7 @@ export class SqlSourceConfigurationPage extends MigrationWizardPage {
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _usernameInput!: azdata.InputBoxComponent; private _usernameInput!: azdata.InputBoxComponent;
private _password!: azdata.InputBoxComponent; private _password!: azdata.InputBoxComponent;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.SOURCE_CONFIGURATION, 'MigrationModePage'), migrationStateModel);
@@ -26,6 +28,12 @@ export class SqlSourceConfigurationPage extends MigrationWizardPage {
await this.createSourceCredentialContainer(), await this.createSourceCredentialContainer(),
] ]
); );
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(form.component()); await view.initializeModel(form.component());
} }
@@ -107,9 +115,9 @@ export class SqlSourceConfigurationPage extends MigrationWizardPage {
enabled: false, enabled: false,
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH
}).component(); }).component();
this._usernameInput.onTextChanged(value => { this._disposables.push(this._usernameInput.onTextChanged(value => {
this.migrationStateModel._sqlServerUsername = value; this.migrationStateModel._sqlServerUsername = value;
}); }));
const passwordLabel = this._view.modelBuilder.text().withProps({ const passwordLabel = this._view.modelBuilder.text().withProps({
value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL, value: constants.DATABASE_BACKUP_NETWORK_SHARE_PASSWORD_LABEL,
@@ -125,9 +133,9 @@ export class SqlSourceConfigurationPage extends MigrationWizardPage {
inputType: 'password', inputType: 'password',
width: WIZARD_INPUT_COMPONENT_WIDTH width: WIZARD_INPUT_COMPONENT_WIDTH
}).component(); }).component();
this._password.onTextChanged(value => { this._disposables.push(this._password.onTextChanged(value => {
this.migrationStateModel._sqlServerPassword = value; this.migrationStateModel._sqlServerPassword = value;
}); }));
const container = this._view.modelBuilder.flexContainer().withItems( const container = this._view.modelBuilder.flexContainer().withItems(
[ [

View File

@@ -179,7 +179,7 @@ export class SubscriptionSelectionPage extends MigrationWizardPage {
} }
public async onPageLeave(): Promise<void> { public async onPageLeave(): Promise<void> {
this.disposables.forEach(d => d.dispose()); this.disposables.forEach(d => { try { d.dispose(); } catch { } });
} }
protected async handleStateChange(e: StateChangeEvent): Promise<void> { protected async handleStateChange(e: StateChangeEvent): Promise<void> {

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata'; import * as azdata from 'azdata';
import * as vscode from 'vscode';
import { MigrationWizardPage } from '../models/migrationWizardPage'; import { MigrationWizardPage } from '../models/migrationWizardPage';
import { MigrationMode, MigrationStateModel, MigrationTargetType, NetworkContainerType, StateChangeEvent } from '../models/stateMachine'; import { MigrationMode, MigrationStateModel, MigrationTargetType, NetworkContainerType, StateChangeEvent } from '../models/stateMachine';
import * as constants from '../constants/strings'; import * as constants from '../constants/strings';
@@ -14,6 +15,7 @@ import { TargetDatabaseSummaryDialog } from '../dialog/targetDatabaseSummary/tar
export class SummaryPage extends MigrationWizardPage { export class SummaryPage extends MigrationWizardPage {
private _view!: azdata.ModelView; private _view!: azdata.ModelView;
private _flexContainer!: azdata.FlexContainer; private _flexContainer!: azdata.FlexContainer;
private _disposables: vscode.Disposable[] = [];
constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) { constructor(wizard: azdata.window.Wizard, migrationStateModel: MigrationStateModel) {
super(wizard, azdata.window.createWizardPage(constants.SUMMARY_PAGE_TITLE), migrationStateModel); super(wizard, azdata.window.createWizardPage(constants.SUMMARY_PAGE_TITLE), migrationStateModel);
@@ -32,6 +34,12 @@ export class SummaryPage extends MigrationWizardPage {
} }
] ]
); );
this._disposables.push(this._view.onClosed(e => {
this._disposables.forEach(
d => { try { d.dispose(); } catch { } });
}));
await view.initializeModel(form.component()); await view.initializeModel(form.component());
} }
@@ -48,9 +56,9 @@ export class SummaryPage extends MigrationWizardPage {
} }
}).component(); }).component();
targetDatabaseHyperlink.onDidClick(e => { this._disposables.push(targetDatabaseHyperlink.onDidClick(e => {
targetDatabaseSummary.initialize(); targetDatabaseSummary.initialize();
}); }));
const targetDatabaseRow = this._view.modelBuilder.flexContainer() const targetDatabaseRow = this._view.modelBuilder.flexContainer()
.withLayout( .withLayout(

View File

@@ -9,7 +9,6 @@ import { MigrationStateModel } from '../models/stateMachine';
import * as loc from '../constants/strings'; import * as loc from '../constants/strings';
import { MigrationWizardPage } from '../models/migrationWizardPage'; import { MigrationWizardPage } from '../models/migrationWizardPage';
import { SKURecommendationPage } from './skuRecommendationPage'; import { SKURecommendationPage } from './skuRecommendationPage';
// import { SubscriptionSelectionPage } from './subscriptionSelectionPage';
import { DatabaseBackupPage } from './databaseBackupPage'; import { DatabaseBackupPage } from './databaseBackupPage';
import { AccountsSelectionPage } from './accountsSelectionPage'; import { AccountsSelectionPage } from './accountsSelectionPage';
import { IntergrationRuntimePage } from './integrationRuntimePage'; import { IntergrationRuntimePage } from './integrationRuntimePage';
@@ -61,13 +60,13 @@ export class WizardController {
wizardSetupPromises.push(...pages.map(p => p.registerWizardContent())); wizardSetupPromises.push(...pages.map(p => p.registerWizardContent()));
wizardSetupPromises.push(wizard.open()); wizardSetupPromises.push(wizard.open());
wizard.onPageChanged(async (pageChangeInfo: azdata.window.WizardPageChangeInfo) => { this.extensionContext.subscriptions.push(wizard.onPageChanged(async (pageChangeInfo: azdata.window.WizardPageChangeInfo) => {
const newPage = pageChangeInfo.newPage; const newPage = pageChangeInfo.newPage;
const lastPage = pageChangeInfo.lastPage; const lastPage = pageChangeInfo.lastPage;
await pages[lastPage]?.onPageLeave(); await pages[lastPage]?.onPageLeave();
await pages[newPage]?.onPageEnter(); await pages[newPage]?.onPageEnter();
}); }));
wizard.registerNavigationValidator(async validator => { wizard.registerNavigationValidator(async validator => {
// const lastPage = validator.lastPage; // const lastPage = validator.lastPage;
@@ -82,9 +81,9 @@ export class WizardController {
await Promise.all(wizardSetupPromises); await Promise.all(wizardSetupPromises);
await pages[0].onPageEnter(); await pages[0].onPageEnter();
wizard.doneButton.onClick(async (e) => { this.extensionContext.subscriptions.push(wizard.doneButton.onClick(async (e) => {
await stateModel.startMigration(); await stateModel.startMigration();
}); }));
} }
} }