Migration extensions - UI fixes and vBump (#15199)

* Fixing Migration Cutover Dialog
Adding support for target file share
Fixing request body
Correcting localized strings

* Redesigned IR page
Adding additional details in migration status dialog

* vbump

* Fixed the perpetual loading

* Fixed duration logic

* Adding icon for migration extension

* Adding helper commenst to util function
localizing some strings
logging console errors

* enabling cutover buttons for  ignored files
This commit is contained in:
Aasim Khan
2021-04-22 10:19:36 -07:00
committed by GitHub
parent fcaaf1cb29
commit 37894c9e96
14 changed files with 694 additions and 426 deletions

View File

@@ -32,6 +32,7 @@ export class MigrationCutoverDialog {
private _targetVersion!: azdata.TextComponent;
private _migrationStatus!: azdata.TextComponent;
private _fullBackupFile!: azdata.TextComponent;
private _backupLocation!: azdata.TextComponent;
private _lastAppliedLSN!: azdata.TextComponent;
private _lastAppliedBackupFile!: azdata.TextComponent;
private _lastAppliedBackupTakenOn!: azdata.TextComponent;
@@ -44,7 +45,7 @@ export class MigrationCutoverDialog {
constructor(migration: MigrationContext) {
this._model = new MigrationCutoverDialogModel(migration);
this._dialogObject = azdata.window.createModelViewDialog(loc.MIGRATION_CUTOVER, 'MigrationCutoverDialog', 1000);
this._dialogObject = azdata.window.createModelViewDialog('', 'MigrationCutoverDialog', 1000);
}
async initialize(): Promise<void> {
@@ -65,17 +66,17 @@ export class MigrationCutoverDialog {
flexServer.addItem(sourceDatabase.flexContainer, {
CSSStyles: {
'width': '150px'
'width': '200px'
}
});
flexServer.addItem(sourceDetails.flexContainer, {
CSSStyles: {
'width': '150px'
'width': '200px'
}
});
flexServer.addItem(sourceVersion.flexContainer, {
CSSStyles: {
'width': '150px'
'width': '200px'
}
});
@@ -93,26 +94,28 @@ export class MigrationCutoverDialog {
flexTarget.addItem(targetDatabase.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
flexTarget.addItem(targetServer.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
flexTarget.addItem(targetVersion.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
const migrationStatus = this.createInfoField(loc.MIGRATION_STATUS, '');
const fullBackupFileOn = this.createInfoField(loc.FULL_BACKUP_FILES, '');
const backupLocation = this.createInfoField(loc.BACKUP_LOCATION, '');
this._migrationStatus = migrationStatus.text;
this._fullBackupFile = fullBackupFileOn.text;
this._backupLocation = backupLocation.text;
const flexStatus = view.modelBuilder.flexContainer().withLayout({
flexFlow: 'column'
@@ -120,12 +123,17 @@ export class MigrationCutoverDialog {
flexStatus.addItem(migrationStatus.flexContainer, {
CSSStyles: {
'width': '180px'
'width': '200px'
}
});
flexStatus.addItem(fullBackupFileOn.flexContainer, {
CSSStyles: {
'width': '180px'
'width': '200px'
}
});
flexStatus.addItem(backupLocation.flexContainer, {
CSSStyles: {
'width': '200px'
}
});
@@ -133,6 +141,7 @@ export class MigrationCutoverDialog {
const lastAppliedBackup = this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES, '');
const lastAppliedBackupOn = this.createInfoField(loc.LAST_APPLIED_BACKUP_FILES_TAKEN_ON, '');
this._lastAppliedLSN = lastSSN.text;
this._lastAppliedBackupFile = lastAppliedBackup.text;
this._lastAppliedBackupTakenOn = lastAppliedBackupOn.text;
@@ -142,22 +151,22 @@ export class MigrationCutoverDialog {
}).component();
flexFile.addItem(lastSSN.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
flexFile.addItem(lastAppliedBackup.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
flexFile.addItem(lastAppliedBackupOn.flexContainer, {
CSSStyles: {
'width': '230px'
'width': '200px'
}
});
const flexInfo = view.modelBuilder.flexContainer().withProps({
CSSStyles: {
'width': '700px'
'width': '800px',
}
}).component();
@@ -165,7 +174,7 @@ export class MigrationCutoverDialog {
flex: '0',
CSSStyles: {
'flex': '0',
'width': '150px'
'width': '200px'
}
});
@@ -173,7 +182,7 @@ export class MigrationCutoverDialog {
flex: '0',
CSSStyles: {
'flex': '0',
'width': '230px'
'width': '200px'
}
});
@@ -181,7 +190,7 @@ export class MigrationCutoverDialog {
flex: '0',
CSSStyles: {
'flex': '0',
'width': '180px'
'width': '200px'
}
});
@@ -240,11 +249,17 @@ export class MigrationCutoverDialog {
const formBuilder = view.modelBuilder.formContainer().withFormItems(
[
{
component: await this.migrationContainerHeader()
component: this.migrationContainerHeader()
},
{
component: this._view.modelBuilder.separator().withProps({ width: '800px' }).component()
},
{
component: flexInfo
},
{
component: this._view.modelBuilder.separator().withProps({ width: '800px' }).component()
},
{
component: this._fileCount
},
@@ -267,30 +282,59 @@ export class MigrationCutoverDialog {
private migrationContainerHeader(): azdata.FlexContainer {
const header = this._view.modelBuilder.flexContainer().withLayout({
const sqlDatbaseLogo = this._view.modelBuilder.image().withProps({
iconPath: IconPathHelper.sqlDatabaseLogo,
iconHeight: '32px',
iconWidth: '32px',
width: '32px',
height: '32px'
}).component();
this._databaseTitleName = this._view.modelBuilder.text().withProps({
CSSStyles: {
'font-size': 'large',
'width': '400px'
'font-size': '16px',
'font-weight': 'bold',
'margin': '0px'
},
value: this._model._migration.migrationContext.name
value: this._model._migration.migrationContext.properties.sourceDatabaseName
}).component();
header.addItem(this._databaseTitleName, {
flex: '0',
const databaseSubTitle = this._view.modelBuilder.text().withProps({
CSSStyles: {
'width': '500px'
'font-size': '10px',
'margin': '5px 0px'
},
value: loc.DATABASE
}).component();
const titleContainer = this._view.modelBuilder.flexContainer().withItems([
this._databaseTitleName,
databaseSubTitle
]).withLayout({
'flexFlow': 'column'
}).component();
const titleLogoContainer = this._view.modelBuilder.flexContainer().component();
titleLogoContainer.addItem(sqlDatbaseLogo, {
flex: '0'
});
titleLogoContainer.addItem(titleContainer, {
CSSStyles: {
'margin-left': '5px'
}
});
const headerActions = this._view.modelBuilder.flexContainer().withLayout({
}).component();
this._cutoverButton = this._view.modelBuilder.button().withProps({
iconPath: IconPathHelper.cutover,
iconHeight: '14px',
iconWidth: '12px',
label: 'Start Cutover',
height: '55px',
height: '20px',
width: '100px',
enabled: false
}).component();
@@ -307,11 +351,8 @@ export class MigrationCutoverDialog {
}
});
header.addItem(this._cutoverButton, {
flex: '0',
CSSStyles: {
'width': '100px'
}
headerActions.addItem(this._cutoverButton, {
flex: '0'
});
this._cancelButton = this._view.modelBuilder.button().withProps({
@@ -319,19 +360,16 @@ export class MigrationCutoverDialog {
iconHeight: '16px',
iconWidth: '16px',
label: loc.CANCEL_MIGRATION,
height: '55px',
width: '130px'
height: '20px',
width: '120px'
}).component();
this._cancelButton.onDidClick((e) => {
this.cancelMigration();
});
header.addItem(this._cancelButton, {
flex: '0',
CSSStyles: {
'width': '130px'
}
headerActions.addItem(this._cancelButton, {
flex: '0'
});
@@ -340,19 +378,16 @@ export class MigrationCutoverDialog {
iconHeight: '16px',
iconWidth: '16px',
label: 'Refresh',
height: '55px',
width: '100px'
height: '20px',
width: '65px'
}).component();
this._refreshButton.onDidClick((e) => {
this.refreshStatus();
});
header.addItem(this._refreshButton, {
headerActions.addItem(this._refreshButton, {
flex: '0',
CSSStyles: {
'width': '100px'
}
});
this._copyDatabaseMigrationDetails = this._view.modelBuilder.button().withProps({
@@ -360,8 +395,8 @@ export class MigrationCutoverDialog {
iconHeight: '16px',
iconWidth: '16px',
label: loc.COPY_MIGRATION_DETAILS,
height: '55px',
width: '100px'
height: '20px',
width: '150px'
}).component();
this._copyDatabaseMigrationDetails.onDidClick(async (e) => {
@@ -378,22 +413,34 @@ export class MigrationCutoverDialog {
vscode.window.showInformationMessage(loc.DETAILS_COPIED);
});
header.addItem(this._copyDatabaseMigrationDetails, {
headerActions.addItem(this._copyDatabaseMigrationDetails, {
flex: '0',
CSSStyles: {
'width': '100px'
'margin-left': '5px'
}
});
this._refreshLoader = this._view.modelBuilder.loadingComponent().withProps({
loading: false,
height: '55px'
height: '15px'
}).component();
header.addItem(this._refreshLoader, {
headerActions.addItem(this._refreshLoader, {
flex: '0',
CSSStyles: {
'margin-top': '15px'
'margin-left': '16px'
}
});
const header = this._view.modelBuilder.flexContainer().withItems([
titleLogoContainer
]).withLayout({
flexFlow: 'column'
}).component();
header.addItem(headerActions, {
'CSSStyles': {
'margin-top': '16px'
}
});
@@ -461,19 +508,19 @@ export class MigrationCutoverDialog {
this._sourceDatabase.value = sourceDatabaseName;
this._serverName.value = sqlServerName;
this._serverVersion.value = `${sqlServerVersion}
${sqlServerInfo.serverVersion}`;
this._serverVersion.value = `${sqlServerVersion} ${sqlServerInfo.serverVersion}`;
this._targetDatabase.value = targetDatabaseName;
this._targetServer.value = targetServerName;
this._targetVersion.value = targetServerVersion;
this._migrationStatus.value = migrationStatusTextValue;
this._fullBackupFile.value = fullBackupFileName!;
this._migrationStatus.value = migrationStatusTextValue ?? '---';
this._fullBackupFile.value = fullBackupFileName! ?? '-';
this._backupLocation.value = this._model._migration.migrationContext.properties.backupConfiguration?.sourceLocation?.fileShare?.path! ?? '-';
this._lastAppliedLSN.value = lastAppliedSSN!;
this._lastAppliedBackupFile.value = this._model.migrationStatus.properties.migrationStatusDetails?.lastRestoredFilename;
this._lastAppliedBackupTakenOn.value = lastAppliedBackupFileTakenOn! ? new Date(lastAppliedBackupFileTakenOn).toLocaleString() : '';
this._lastAppliedLSN.value = lastAppliedSSN! ?? '-';
this._lastAppliedBackupFile.value = this._model.migrationStatus.properties.migrationStatusDetails?.lastRestoredFilename ?? '-';
this._lastAppliedBackupTakenOn.value = lastAppliedBackupFileTakenOn! ? new Date(lastAppliedBackupFileTakenOn).toLocaleString() : '-';
this._fileCount.value = loc.ACTIVE_BACKUP_FILES_ITEMS(tableData.length);
@@ -495,7 +542,7 @@ export class MigrationCutoverDialog {
}
if (migrationStatusTextValue === MigrationStatus.InProgress) {
const fileNotRestored = await tableData.some(file => file.status !== 'Restored');
const fileNotRestored = await tableData.some(file => file.status !== 'Restored' && file.status !== 'Ignored');
this._cutoverButton.enabled = !fileNotRestored;
this._cancelButton.enabled = true;
} else {