mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-31 09:35:39 -05:00
sql-migration: update migration status page latest design (#16099)
* add migrations status context menu and commands * add migration status images * remove test code, add account validation * fix command registration to occure once * fix typo
This commit is contained in:
@@ -39,13 +39,11 @@ export class MigrationCutoverDialog {
|
||||
private _lastAppliedLSN!: azdata.TextComponent;
|
||||
private _lastAppliedBackupFile!: azdata.TextComponent;
|
||||
private _lastAppliedBackupTakenOn!: azdata.TextComponent;
|
||||
|
||||
private _fileCount!: azdata.TextComponent;
|
||||
|
||||
private fileTable!: azdata.TableComponent;
|
||||
private _autoRefreshHandle!: any;
|
||||
readonly _infoFieldWidth: string = '250px';
|
||||
|
||||
readonly _infoFieldWidth: string = '250px';
|
||||
|
||||
constructor(migration: MigrationContext) {
|
||||
this._model = new MigrationCutoverDialogModel(migration);
|
||||
@@ -55,244 +53,233 @@ export class MigrationCutoverDialog {
|
||||
async initialize(): Promise<void> {
|
||||
let tab = azdata.window.createTab('');
|
||||
tab.registerContent(async (view: azdata.ModelView) => {
|
||||
this._view = view;
|
||||
const sourceDatabase = this.createInfoField(loc.SOURCE_DATABASE, '');
|
||||
const sourceDetails = this.createInfoField(loc.SOURCE_SERVER, '');
|
||||
const sourceVersion = this.createInfoField(loc.SOURCE_VERSION, '');
|
||||
try {
|
||||
this._view = view;
|
||||
const sourceDatabase = this.createInfoField(loc.SOURCE_DATABASE, '');
|
||||
const sourceDetails = this.createInfoField(loc.SOURCE_SERVER, '');
|
||||
const sourceVersion = this.createInfoField(loc.SOURCE_VERSION, '');
|
||||
|
||||
this._sourceDatabase = sourceDatabase.text;
|
||||
this._serverName = sourceDetails.text;
|
||||
this._serverVersion = sourceVersion.text;
|
||||
this._sourceDatabase = sourceDatabase.text;
|
||||
this._serverName = sourceDetails.text;
|
||||
this._serverVersion = sourceVersion.text;
|
||||
|
||||
const flexServer = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
const flexServer = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
|
||||
flexServer.addItem(sourceDatabase.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexServer.addItem(sourceDetails.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexServer.addItem(sourceVersion.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
const targetDatabase = this.createInfoField(loc.TARGET_DATABASE_NAME, '');
|
||||
const targetServer = this.createInfoField(loc.TARGET_SERVER, '');
|
||||
const targetVersion = this.createInfoField(loc.TARGET_VERSION, '');
|
||||
|
||||
this._targetDatabase = targetDatabase.text;
|
||||
this._targetServer = targetServer.text;
|
||||
this._targetVersion = targetVersion.text;
|
||||
|
||||
const flexTarget = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
|
||||
flexTarget.addItem(targetDatabase.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexTarget.addItem(targetServer.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexTarget.addItem(targetVersion.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
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'
|
||||
}).component();
|
||||
|
||||
flexStatus.addItem(migrationStatus.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexStatus.addItem(fullBackupFileOn.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexStatus.addItem(backupLocation.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
const lastSSN = this.createInfoField(loc.LAST_APPLIED_LSN, '');
|
||||
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;
|
||||
|
||||
const flexFile = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
flexFile.addItem(lastSSN.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexFile.addItem(lastAppliedBackup.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexFile.addItem(lastAppliedBackupOn.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
const flexInfo = view.modelBuilder.flexContainer().withProps({
|
||||
width: 1000
|
||||
}).component();
|
||||
|
||||
flexInfo.addItem(flexServer, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexTarget, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexStatus, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexFile, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
this._fileCount = view.modelBuilder.text().withProps({
|
||||
width: '500px',
|
||||
CSSStyles: {
|
||||
'font-size': '14px',
|
||||
'font-weight': 'bold'
|
||||
}
|
||||
}).component();
|
||||
|
||||
this.fileTable = view.modelBuilder.table().withProps({
|
||||
columns: [
|
||||
{
|
||||
value: loc.ACTIVE_BACKUP_FILES,
|
||||
width: 230,
|
||||
type: azdata.ColumnType.text,
|
||||
},
|
||||
{
|
||||
value: loc.TYPE,
|
||||
width: 90,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.STATUS,
|
||||
width: 60,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.DATA_UPLOADED,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.COPY_THROUGHPUT,
|
||||
width: 150,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.BACKUP_START_TIME,
|
||||
width: 130,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.FIRST_LSN,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.LAST_LSN,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
flexServer.addItem(sourceDatabase.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
],
|
||||
data: [],
|
||||
width: '1100px',
|
||||
height: '300px',
|
||||
fontSize: '12px'
|
||||
}).component();
|
||||
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[
|
||||
{
|
||||
component: this.migrationContainerHeader()
|
||||
},
|
||||
{
|
||||
component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component()
|
||||
},
|
||||
{
|
||||
component: flexInfo
|
||||
},
|
||||
{
|
||||
component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component()
|
||||
},
|
||||
{
|
||||
component: this._fileCount
|
||||
},
|
||||
{
|
||||
component: this.fileTable
|
||||
});
|
||||
flexServer.addItem(sourceDetails.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
],
|
||||
{
|
||||
horizontal: false
|
||||
}
|
||||
);
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
this._view.onClosed(e => {
|
||||
clearInterval(this._autoRefreshHandle);
|
||||
});
|
||||
return view.initializeModel(form).then((value) => {
|
||||
this.refreshStatus();
|
||||
});
|
||||
});
|
||||
flexServer.addItem(sourceVersion.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
const targetDatabase = this.createInfoField(loc.TARGET_DATABASE_NAME, '');
|
||||
const targetServer = this.createInfoField(loc.TARGET_SERVER, '');
|
||||
const targetVersion = this.createInfoField(loc.TARGET_VERSION, '');
|
||||
|
||||
this._targetDatabase = targetDatabase.text;
|
||||
this._targetServer = targetServer.text;
|
||||
this._targetVersion = targetVersion.text;
|
||||
|
||||
const flexTarget = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
|
||||
flexTarget.addItem(targetDatabase.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexTarget.addItem(targetServer.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexTarget.addItem(targetVersion.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
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'
|
||||
}).component();
|
||||
|
||||
flexStatus.addItem(migrationStatus.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexStatus.addItem(fullBackupFileOn.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexStatus.addItem(backupLocation.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
const lastSSN = this.createInfoField(loc.LAST_APPLIED_LSN, '');
|
||||
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;
|
||||
|
||||
const flexFile = view.modelBuilder.flexContainer().withLayout({
|
||||
flexFlow: 'column'
|
||||
}).component();
|
||||
flexFile.addItem(lastSSN.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexFile.addItem(lastAppliedBackup.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
flexFile.addItem(lastAppliedBackupOn.flexContainer, {
|
||||
CSSStyles: {
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
const flexInfo = view.modelBuilder.flexContainer().withProps({
|
||||
width: 1000
|
||||
}).component();
|
||||
|
||||
flexInfo.addItem(flexServer, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexTarget, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexStatus, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
flexInfo.addItem(flexFile, {
|
||||
flex: '0',
|
||||
CSSStyles: {
|
||||
'flex': '0',
|
||||
'width': this._infoFieldWidth
|
||||
}
|
||||
});
|
||||
|
||||
this._fileCount = view.modelBuilder.text().withProps({
|
||||
width: '500px',
|
||||
CSSStyles: {
|
||||
'font-size': '14px',
|
||||
'font-weight': 'bold'
|
||||
}
|
||||
}).component();
|
||||
|
||||
this.fileTable = view.modelBuilder.table().withProps({
|
||||
columns: [
|
||||
{
|
||||
value: loc.ACTIVE_BACKUP_FILES,
|
||||
width: 230,
|
||||
type: azdata.ColumnType.text,
|
||||
},
|
||||
{
|
||||
value: loc.TYPE,
|
||||
width: 90,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.STATUS,
|
||||
width: 60,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.DATA_UPLOADED,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.COPY_THROUGHPUT,
|
||||
width: 150,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.BACKUP_START_TIME,
|
||||
width: 130,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.FIRST_LSN,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
},
|
||||
{
|
||||
value: loc.LAST_LSN,
|
||||
width: 120,
|
||||
type: azdata.ColumnType.text
|
||||
}
|
||||
],
|
||||
data: [],
|
||||
width: '1100px',
|
||||
height: '300px',
|
||||
fontSize: '12px'
|
||||
}).component();
|
||||
|
||||
const formBuilder = view.modelBuilder.formContainer().withFormItems(
|
||||
[
|
||||
{ component: this.migrationContainerHeader() },
|
||||
{ component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component() },
|
||||
{ component: flexInfo },
|
||||
{ component: this._view.modelBuilder.separator().withProps({ width: 1000 }).component() },
|
||||
{ component: this._fileCount },
|
||||
{ component: this.fileTable }
|
||||
],
|
||||
{ horizontal: false }
|
||||
);
|
||||
const form = formBuilder.withLayout({ width: '100%' }).component();
|
||||
this._view.onClosed(e => {
|
||||
clearInterval(this._autoRefreshHandle);
|
||||
});
|
||||
|
||||
return view.initializeModel(form).then((value) => {
|
||||
this.refreshStatus();
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
});
|
||||
this._dialogObject.content = [tab];
|
||||
|
||||
@@ -305,7 +292,6 @@ export class MigrationCutoverDialog {
|
||||
azdata.window.openDialog(this._dialogObject);
|
||||
}
|
||||
|
||||
|
||||
private migrationContainerHeader(): azdata.FlexContainer {
|
||||
const sqlDatbaseLogo = this._view.modelBuilder.image().withProps({
|
||||
iconPath: IconPathHelper.sqlDatabaseLogo,
|
||||
@@ -404,7 +390,7 @@ export class MigrationCutoverDialog {
|
||||
this._cancelButton.onDidClick((e) => {
|
||||
vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, loc.YES, loc.NO).then(async (v) => {
|
||||
if (v === loc.YES) {
|
||||
await this.cancelMigration();
|
||||
await this._model.cancelMigration();
|
||||
await this.refreshStatus();
|
||||
}
|
||||
});
|
||||
@@ -427,9 +413,8 @@ export class MigrationCutoverDialog {
|
||||
}
|
||||
}).component();
|
||||
|
||||
this._refreshButton.onDidClick((e) => {
|
||||
this.refreshStatus();
|
||||
});
|
||||
this._refreshButton.onDidClick(
|
||||
async (e) => await this.refreshStatus());
|
||||
|
||||
headerActions.addItem(this._refreshButton, {
|
||||
flex: '0',
|
||||
@@ -597,7 +582,7 @@ export class MigrationCutoverDialog {
|
||||
|
||||
this._fileCount.value = loc.ACTIVE_BACKUP_FILES_ITEMS(tableData.length);
|
||||
|
||||
//Sorting files in descending order of backupStartTime
|
||||
// Sorting files in descending order of backupStartTime
|
||||
tableData.sort((file1, file2) => new Date(file1.backupStartTime) > new Date(file2.backupStartTime) ? - 1 : 1);
|
||||
|
||||
this.fileTable.data = tableData.map((row) => {
|
||||
@@ -664,11 +649,6 @@ export class MigrationCutoverDialog {
|
||||
text: textComponent
|
||||
};
|
||||
}
|
||||
|
||||
private async cancelMigration(): Promise<void> {
|
||||
await this._model.cancelMigration();
|
||||
await this.refreshStatus();
|
||||
}
|
||||
}
|
||||
|
||||
interface ActiveBackupFileSchema {
|
||||
|
||||
Reference in New Issue
Block a user