mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
[Sql Migration] Stabilize save and close logic and fix related ux bugs (#18579)
* add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo * * add loadSavedInfo function in stateMachine; only open wizard if didLoadSavedInfo * replaced savedInfo.miggrationServiceId string with sqlMigrationServer object * selectDatbasesFromList helper function to check previously selected dbs in dbSelectorPage and sqlDatabaseTree * * remove savedInfo references from targetSelectionPage, migrationModePage * add selectDefaultDropdownValue helper to stateMachine to handle unify savedInfo selection logic * add updateDropdownLoadingStatus to targetSelectionPage * check if values exist before making api calls in statemachine * removed savedInfo references from databaseBackupPage, integrationRuntimePage * databaseBackupPage - targetDatabaseNames, networkShares, blobs need to rely on savedInfo as user may update the list of migrationdbs during the retry/saveAndClose * re-add serverAssessments to savedInfo; only getAssessments if it does not exist or needs to be updated; fix networkShare type savedInfo * rename _assessmentDbs to _databasesForAssessment; _migrationDbs to _databasesForMigration * load blobs/networkshares savedinfo; move selectDefaultDropdownValue to utils * fix selectDefaultDropdownValue; refreshDatabaseBackupPage when user changes target subscription or location
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { MigrationStateModel, MigrationTargetType, Page } from '../../models/stateMachine';
|
||||
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
|
||||
import { SqlDatabaseTree } from './sqlDatabasesTree';
|
||||
import { SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
||||
import { SKURecommendationPage } from '../../wizard/skuRecommendationPage';
|
||||
@@ -32,9 +32,6 @@ export class AssessmentResultsDialog {
|
||||
|
||||
constructor(public ownerUri: string, public model: MigrationStateModel, public title: string, private _skuRecommendationPage: SKURecommendationPage, private _targetType: MigrationTargetType) {
|
||||
this._model = model;
|
||||
if (this._model.resumeAssessment && this._model.savedInfo.closedPage >= Page.DatabaseBackup) {
|
||||
this._model._databaseAssessment = <string[]>this._model.savedInfo.databaseAssessment;
|
||||
}
|
||||
this._tree = new SqlDatabaseTree(this._model, this._targetType);
|
||||
}
|
||||
|
||||
@@ -87,16 +84,31 @@ export class AssessmentResultsDialog {
|
||||
}
|
||||
|
||||
protected async execute() {
|
||||
if (this._targetType === MigrationTargetType.SQLVM) {
|
||||
this._model._vmDbs = this._tree.selectedDbs();
|
||||
} else {
|
||||
this._model._miDbs = this._tree.selectedDbs();
|
||||
const selectedDbs = this._tree.selectedDbs();
|
||||
switch (this._targetType) {
|
||||
case MigrationTargetType.SQLMI: {
|
||||
this.didUpdateDatabasesForMigration(this._model._miDbs, selectedDbs);
|
||||
this._model._miDbs = selectedDbs;
|
||||
break;
|
||||
}
|
||||
|
||||
case MigrationTargetType.SQLVM: {
|
||||
this.didUpdateDatabasesForMigration(this._model._vmDbs, selectedDbs);
|
||||
this._model._vmDbs = selectedDbs;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await this._skuRecommendationPage.refreshCardText();
|
||||
this.model.refreshDatabaseBackupPage = true;
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
private didUpdateDatabasesForMigration(priorDbs: string[], selectedDbs: string[]) {
|
||||
this._model._didUpdateDatabasesForMigration = selectedDbs.length === 0
|
||||
|| selectedDbs.length !== priorDbs.length
|
||||
|| priorDbs.some(db => selectedDbs.indexOf(db) < 0);
|
||||
}
|
||||
|
||||
protected async cancel() {
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,16 @@ export class SavedAssessmentDialog {
|
||||
reject(ex);
|
||||
}
|
||||
});
|
||||
|
||||
dialog.registerCloseValidator(async () => {
|
||||
if (this.stateModel.resumeAssessment) {
|
||||
if (!this.stateModel.loadSavedInfo()) {
|
||||
void vscode.window.showInformationMessage(constants.OPEN_SAVED_INFO_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,14 +77,8 @@ export class SavedAssessmentDialog {
|
||||
}
|
||||
|
||||
protected async execute() {
|
||||
if (this.stateModel.resumeAssessment) {
|
||||
const wizardController = new WizardController(this.context, this.stateModel);
|
||||
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
||||
} else {
|
||||
// normal flow
|
||||
const wizardController = new WizardController(this.context, this.stateModel);
|
||||
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
||||
}
|
||||
const wizardController = new WizardController(this.context, this.stateModel);
|
||||
await wizardController.openWizard(this.stateModel.sourceConnectionId);
|
||||
this._isOpen = false;
|
||||
}
|
||||
|
||||
@@ -90,7 +94,7 @@ export class SavedAssessmentDialog {
|
||||
const buttonGroup = 'resumeMigration';
|
||||
|
||||
const radioStart = view.modelBuilder.radioButton().withProps({
|
||||
label: constants.START_MIGRATION,
|
||||
label: constants.START_NEW_SESSION,
|
||||
name: buttonGroup,
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
@@ -105,7 +109,7 @@ export class SavedAssessmentDialog {
|
||||
}
|
||||
});
|
||||
const radioContinue = view.modelBuilder.radioButton().withProps({
|
||||
label: constants.CONTINUE_MIGRATION,
|
||||
label: constants.RESUME_SESSION,
|
||||
name: buttonGroup,
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
@@ -122,11 +126,9 @@ export class SavedAssessmentDialog {
|
||||
const flex = view.modelBuilder.flexContainer()
|
||||
.withLayout({
|
||||
flexFlow: 'column',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
}).withProps({
|
||||
CSSStyles: {
|
||||
'margin': '20px 15px',
|
||||
'padding': '20px 15px',
|
||||
}
|
||||
}).component();
|
||||
flex.addItem(radioStart, { flex: '0 0 auto' });
|
||||
@@ -134,5 +136,4 @@ export class SavedAssessmentDialog {
|
||||
|
||||
return flex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { SqlMigrationAssessmentResultItem, SqlMigrationImpactedObjectInfo } from '../../../../mssql/src/mssql';
|
||||
import { MigrationStateModel, MigrationTargetType, Page } from '../../models/stateMachine';
|
||||
import { MigrationStateModel, MigrationTargetType } from '../../models/stateMachine';
|
||||
import * as constants from '../../constants/strings';
|
||||
import { debounce } from '../../api/utils';
|
||||
import { IconPath, IconPathHelper } from '../../constants/iconPathHelper';
|
||||
import * as styles from '../../constants/styles';
|
||||
import { EOL } from 'os';
|
||||
import { selectDatabasesFromList } from '../../constants/helper';
|
||||
|
||||
const styleLeft: azdata.CssStyles = {
|
||||
'border': 'none',
|
||||
@@ -142,7 +143,7 @@ export class SqlDatabaseTree {
|
||||
...styles.BOLD_NOTE_CSS,
|
||||
'margin': '0px 15px 0px 15px'
|
||||
},
|
||||
value: constants.DATABASES(0, this._model._databaseAssessment?.length)
|
||||
value: constants.DATABASES(0, this._model._databasesForAssessment?.length)
|
||||
}).component();
|
||||
return this._databaseCount;
|
||||
}
|
||||
@@ -881,7 +882,7 @@ export class SqlDatabaseTree {
|
||||
public async initialize(): Promise<void> {
|
||||
let instanceTableValues: azdata.DeclarativeTableCellValue[][] = [];
|
||||
this._databaseTableValues = [];
|
||||
this._dbNames = this._model._databaseAssessment;
|
||||
this._dbNames = this._model._databasesForAssessment;
|
||||
const selectedDbs = (this._targetType === MigrationTargetType.SQLVM) ? this._model._vmDbs : this._model._miDbs;
|
||||
this._serverName = (await this._model.getSourceConnectionProfile()).serverName;
|
||||
|
||||
@@ -959,25 +960,16 @@ export class SqlDatabaseTree {
|
||||
});
|
||||
}
|
||||
await this._instanceTable.setDataValues(instanceTableValues);
|
||||
if (this._model.resumeAssessment && this._model.savedInfo.closedPage >= Page.SKURecommendation && this._targetType === this._model.savedInfo.migrationTargetType) {
|
||||
await this._databaseTable.setDataValues(this._model.savedInfo.migrationDatabases);
|
||||
} else {
|
||||
if (this._model.retryMigration && this._targetType === this._model.savedInfo.migrationTargetType) {
|
||||
const sourceDatabaseName = this._model.savedInfo.databaseList[0];
|
||||
const sourceDatabaseIndex = this._dbNames.indexOf(sourceDatabaseName);
|
||||
this._databaseTableValues[sourceDatabaseIndex][0].value = true;
|
||||
}
|
||||
|
||||
await this._databaseTable.setDataValues(this._databaseTableValues);
|
||||
await this.updateValuesOnSelection();
|
||||
}
|
||||
this._databaseTableValues = selectDatabasesFromList(this._model._databasesForMigration, this._databaseTableValues);
|
||||
await this._databaseTable.setDataValues(this._databaseTableValues);
|
||||
await this.updateValuesOnSelection();
|
||||
}
|
||||
|
||||
private async updateValuesOnSelection() {
|
||||
await this._databaseCount.updateProperties({
|
||||
'value': constants.DATABASES(this.selectedDbs()?.length, this._model._databaseAssessment?.length)
|
||||
'value': constants.DATABASES(this.selectedDbs()?.length, this._model._databasesForAssessment?.length)
|
||||
});
|
||||
this._model._databaseSelection = <azdata.DeclarativeTableCellValue[][]>this._databaseTable.dataValues;
|
||||
}
|
||||
|
||||
// undo when bug #16445 is fixed
|
||||
|
||||
@@ -12,6 +12,7 @@ import { MigrationMode, MigrationStateModel, NetworkContainerType, SavedInfo } f
|
||||
import { MigrationContext } from '../../models/migrationLocalStorage';
|
||||
import { WizardController } from '../../wizard/wizardController';
|
||||
import { getMigrationModeEnum, getMigrationTargetTypeEnum } from '../../constants/helper';
|
||||
import * as constants from '../../constants/strings';
|
||||
|
||||
export class RetryMigrationDialog {
|
||||
private _context: vscode.ExtensionContext;
|
||||
@@ -30,21 +31,18 @@ export class RetryMigrationDialog {
|
||||
savedInfo = {
|
||||
closedPage: 0,
|
||||
|
||||
// AzureAccount
|
||||
azureAccount: migration.azureAccount,
|
||||
azureTenant: migration.azureAccount.properties.tenants[0],
|
||||
|
||||
// DatabaseSelector
|
||||
selectedDatabases: [],
|
||||
databaseAssessment: [sourceDatabaseName],
|
||||
|
||||
// SKURecommendation
|
||||
databaseAssessment: [],
|
||||
databaseList: [sourceDatabaseName],
|
||||
migrationDatabases: [],
|
||||
serverAssessment: null,
|
||||
skuRecommendation: null,
|
||||
|
||||
migrationTargetType: getMigrationTargetTypeEnum(migration)!,
|
||||
|
||||
// TargetSelection
|
||||
azureAccount: migration.azureAccount,
|
||||
azureTenant: migration.azureAccount.properties.tenants[0],
|
||||
subscription: migration.subscription,
|
||||
location: location,
|
||||
resourceGroup: {
|
||||
@@ -58,14 +56,13 @@ export class RetryMigrationDialog {
|
||||
migrationMode: getMigrationModeEnum(migration),
|
||||
|
||||
// DatabaseBackup
|
||||
targetSubscription: migration.subscription,
|
||||
targetDatabaseNames: [migration.migrationContext.name],
|
||||
networkContainerType: null,
|
||||
networkShares: [],
|
||||
blobs: [],
|
||||
|
||||
// Integration Runtime
|
||||
migrationServiceId: migration.migrationContext.properties.migrationService,
|
||||
sqlMigrationService: migration.controller,
|
||||
};
|
||||
|
||||
const getStorageAccountResourceGroup = (storageAccountResourceId: string) => {
|
||||
@@ -151,7 +148,11 @@ export class RetryMigrationDialog {
|
||||
const api = (await vscode.extensions.getExtension(mssql.extension.name)?.activate()) as mssql.IExtension;
|
||||
const stateModel = this.createMigrationStateModel(this._migration, connectionId, serverName, api, location!);
|
||||
|
||||
const wizardController = new WizardController(this._context, stateModel);
|
||||
await wizardController.openWizard(stateModel.sourceConnectionId);
|
||||
if (stateModel.loadSavedInfo()) {
|
||||
const wizardController = new WizardController(this._context, stateModel);
|
||||
await wizardController.openWizard(stateModel.sourceConnectionId);
|
||||
} else {
|
||||
void vscode.window.showInformationMessage(constants.MIGRATION_CANNOT_RETRY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ export class TargetDatabaseSummaryDialog {
|
||||
this._view = view;
|
||||
|
||||
const databaseCount = this._view.modelBuilder.text().withProps({
|
||||
value: constants.COUNT_DATABASES(this._model._migrationDbs.length),
|
||||
value: constants.COUNT_DATABASES(this._model._databasesForMigration.length),
|
||||
CSSStyles: {
|
||||
...styles.BODY_CSS,
|
||||
'margin-bottom': '20px'
|
||||
@@ -132,7 +132,7 @@ export class TargetDatabaseSummaryDialog {
|
||||
|
||||
const tableRows: azdata.DeclarativeTableCellValue[][] = [];
|
||||
|
||||
this._model._migrationDbs.forEach((db, index) => {
|
||||
this._model._databasesForMigration.forEach((db, index) => {
|
||||
const tableRow: azdata.DeclarativeTableCellValue[] = [];
|
||||
tableRow.push({
|
||||
value: db
|
||||
|
||||
Reference in New Issue
Block a user