mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-24 09:35:37 -05:00
add delete migration method in migration list and details pages (#22243)
* add delete migraiton, fix stale token detection * address pr comments, fix api error response format
This commit is contained in:
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import * as loc from '../constants/strings';
|
||||
import { getSqlServerName, getMigrationStatusImage } from '../api/utils';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import { canCancelMigration, canCutoverMigration, canRetryMigration, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation } from '../constants/helper';
|
||||
import { canCancelMigration, canCutoverMigration, canDeleteMigration, canRetryMigration, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation } from '../constants/helper';
|
||||
import { getResourceName } from '../api/azure';
|
||||
import { InfoFieldSchema, infoFieldWidth, MigrationDetailsTabBase, MigrationTargetTypeName } from './migrationDetailsTabBase';
|
||||
import { EmptySettingValue } from './tabBase';
|
||||
@@ -37,7 +37,7 @@ export class MigrationDetailsBlobContainerTab extends MigrationDetailsTabBase<Mi
|
||||
public async create(
|
||||
context: vscode.ExtensionContext,
|
||||
view: azdata.ModelView,
|
||||
openMigrationsListFcn: () => Promise<void>,
|
||||
openMigrationsListFcn: (refresh?: boolean) => Promise<void>,
|
||||
statusBar: DashboardStatusBar,
|
||||
): Promise<MigrationDetailsBlobContainerTab> {
|
||||
|
||||
@@ -115,6 +115,7 @@ export class MigrationDetailsBlobContainerTab extends MigrationDetailsTabBase<Mi
|
||||
|
||||
this.cutoverButton.enabled = canCutoverMigration(migration);
|
||||
this.cancelButton.enabled = canCancelMigration(migration);
|
||||
this.deleteButton.enabled = canDeleteMigration(migration);
|
||||
this.retryButton.enabled = canRetryMigration(migration);
|
||||
|
||||
this.refreshLoader.loading = false;
|
||||
|
||||
@@ -10,7 +10,7 @@ import * as loc from '../constants/strings';
|
||||
import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, getMigrationStatusImage } from '../api/utils';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import * as styles from '../constants/styles';
|
||||
import { canCancelMigration, canCutoverMigration, canRetryMigration, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation } from '../constants/helper';
|
||||
import { canCancelMigration, canCutoverMigration, canDeleteMigration, canRetryMigration, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation } from '../constants/helper';
|
||||
import { getResourceName } from '../api/azure';
|
||||
import { EmptySettingValue } from './tabBase';
|
||||
import { InfoFieldSchema, infoFieldWidth, MigrationDetailsTabBase, MigrationTargetTypeName } from './migrationDetailsTabBase';
|
||||
@@ -56,7 +56,7 @@ export class MigrationDetailsFileShareTab extends MigrationDetailsTabBase<Migrat
|
||||
public async create(
|
||||
context: vscode.ExtensionContext,
|
||||
view: azdata.ModelView,
|
||||
openMigrationsListFcn: () => Promise<void>,
|
||||
openMigrationsListFcn: (refresh?: boolean) => Promise<void>,
|
||||
statusBar: DashboardStatusBar): Promise<MigrationDetailsFileShareTab> {
|
||||
|
||||
this.view = view;
|
||||
@@ -182,6 +182,7 @@ export class MigrationDetailsFileShareTab extends MigrationDetailsTabBase<Migrat
|
||||
|
||||
this.cutoverButton.enabled = canCutoverMigration(migration);
|
||||
this.cancelButton.enabled = canCancelMigration(migration);
|
||||
this.deleteButton.enabled = canDeleteMigration(migration);
|
||||
this.retryButton.enabled = canRetryMigration(migration);
|
||||
} catch (e) {
|
||||
await this.statusBar.showError(
|
||||
|
||||
@@ -9,13 +9,16 @@ import { IconPathHelper } from '../constants/iconPathHelper';
|
||||
import { MigrationServiceContext } from '../models/migrationLocalStorage';
|
||||
import * as loc from '../constants/strings';
|
||||
import * as styles from '../constants/styles';
|
||||
import { DatabaseMigration } from '../api/azure';
|
||||
import { DatabaseMigration, deleteMigration } from '../api/azure';
|
||||
import { TabBase } from './tabBase';
|
||||
import { MigrationCutoverDialogModel } from '../dialog/migrationCutover/migrationCutoverDialogModel';
|
||||
import { ConfirmCutoverDialog } from '../dialog/migrationCutover/confirmCutoverDialog';
|
||||
import { RetryMigrationDialog } from '../dialog/retryMigration/retryMigrationDialog';
|
||||
import { MigrationTargetType } from '../models/stateMachine';
|
||||
import { DashboardStatusBar } from './DashboardStatusBar';
|
||||
import { canDeleteMigration } from '../constants/helper';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import { MenuCommands } from '../api/utils';
|
||||
|
||||
export const infoFieldLgWidth: string = '330px';
|
||||
export const infoFieldWidth: string = '250px';
|
||||
@@ -38,10 +41,11 @@ export abstract class MigrationDetailsTabBase<T> extends TabBase<T> {
|
||||
protected model!: MigrationCutoverDialogModel;
|
||||
protected databaseLabel!: azdata.TextComponent;
|
||||
protected serviceContext!: MigrationServiceContext;
|
||||
protected openMigrationsListFcn!: () => Promise<void>;
|
||||
protected openMigrationsListFcn!: (refresh?: boolean) => Promise<void>;
|
||||
protected cutoverButton!: azdata.ButtonComponent;
|
||||
protected refreshButton!: azdata.ButtonComponent;
|
||||
protected cancelButton!: azdata.ButtonComponent;
|
||||
protected deleteButton!: azdata.ButtonComponent;
|
||||
protected refreshLoader!: azdata.LoadingComponent;
|
||||
protected copyDatabaseMigrationDetails!: azdata.ButtonComponent;
|
||||
protected newSupportRequest!: azdata.ButtonComponent;
|
||||
@@ -51,7 +55,7 @@ export abstract class MigrationDetailsTabBase<T> extends TabBase<T> {
|
||||
public abstract create(
|
||||
context: vscode.ExtensionContext,
|
||||
view: azdata.ModelView,
|
||||
openMigrationsListFcn: () => Promise<void>,
|
||||
openMigrationsListFcn: (refresh?: boolean) => Promise<void>,
|
||||
statusBar: DashboardStatusBar): Promise<T>;
|
||||
|
||||
protected abstract migrationInfoGrid(): Promise<azdata.FlexContainer>;
|
||||
@@ -186,6 +190,46 @@ export abstract class MigrationDetailsTabBase<T> extends TabBase<T> {
|
||||
});
|
||||
}));
|
||||
|
||||
this.deleteButton = this.view.modelBuilder.button()
|
||||
.withProps({
|
||||
iconPath: IconPathHelper.discard,
|
||||
iconHeight: '16px',
|
||||
iconWidth: '16px',
|
||||
label: loc.DELETE_MIGRATION,
|
||||
height: buttonHeight,
|
||||
enabled: false,
|
||||
}).component();
|
||||
|
||||
this.disposables.push(
|
||||
this.deleteButton.onDidClick(
|
||||
async (e) => {
|
||||
await this.statusBar.clearError();
|
||||
try {
|
||||
if (canDeleteMigration(this.model.migration)) {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
loc.DELETE_MIGRATION_CONFIRMATION,
|
||||
{ modal: true },
|
||||
loc.YES,
|
||||
loc.NO);
|
||||
if (response === loc.YES) {
|
||||
await deleteMigration(
|
||||
this.serviceContext.azureAccount!,
|
||||
this.serviceContext.subscription!,
|
||||
this.model.migration.id);
|
||||
await this.openMigrationsListFcn(true);
|
||||
}
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_DELETE);
|
||||
logError(TelemetryViews.MigrationDetailsTab, MenuCommands.DeleteMigration, "cannot delete migration");
|
||||
}
|
||||
} catch (e) {
|
||||
await this.statusBar.showError(
|
||||
loc.MIGRATION_DELETE_ERROR,
|
||||
loc.MIGRATION_DELETE_ERROR,
|
||||
e.message);
|
||||
logError(TelemetryViews.MigrationDetailsTab, MenuCommands.DeleteMigration, e);
|
||||
}
|
||||
}));
|
||||
|
||||
this.retryButton = this.view.modelBuilder.button()
|
||||
.withProps({
|
||||
@@ -266,6 +310,7 @@ export abstract class MigrationDetailsTabBase<T> extends TabBase<T> {
|
||||
toolbarContainer.addToolbarItems([
|
||||
<azdata.ToolbarComponent>{ component: this.cutoverButton },
|
||||
<azdata.ToolbarComponent>{ component: this.cancelButton },
|
||||
<azdata.ToolbarComponent>{ component: this.deleteButton },
|
||||
<azdata.ToolbarComponent>{ component: this.retryButton },
|
||||
<azdata.ToolbarComponent>{ component: this.copyDatabaseMigrationDetails, toolbarSeparatorAfter: true },
|
||||
<azdata.ToolbarComponent>{ component: this.newSupportRequest, toolbarSeparatorAfter: true },
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as vscode from 'vscode';
|
||||
import * as loc from '../constants/strings';
|
||||
import { getSqlServerName, getMigrationStatusImage, getPipelineStatusImage, debounce } from '../api/utils';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import { canCancelMigration, canCutoverMigration, canRetryMigration, formatDateTimeString, formatNumber, formatSizeBytes, formatSizeKb, formatTime, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation, PipelineStatusCodes } from '../constants/helper';
|
||||
import { canCancelMigration, canCutoverMigration, canDeleteMigration, canRetryMigration, formatDateTimeString, formatNumber, formatSizeBytes, formatSizeKb, formatTime, getMigrationStatusString, getMigrationTargetTypeEnum, isOfflineMigation, PipelineStatusCodes } from '../constants/helper';
|
||||
import { CopyProgressDetail, getResourceName } from '../api/azure';
|
||||
import { InfoFieldSchema, infoFieldLgWidth, MigrationDetailsTabBase, MigrationTargetTypeName } from './migrationDetailsTabBase';
|
||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||
@@ -63,7 +63,7 @@ export class MigrationDetailsTableTab extends MigrationDetailsTabBase<MigrationD
|
||||
public async create(
|
||||
context: vscode.ExtensionContext,
|
||||
view: azdata.ModelView,
|
||||
openMigrationsListFcn: () => Promise<void>,
|
||||
openMigrationsListFcn: (refresh?: boolean) => Promise<void>,
|
||||
statusBar: DashboardStatusBar): Promise<MigrationDetailsTableTab> {
|
||||
|
||||
this.view = view;
|
||||
@@ -162,6 +162,7 @@ export class MigrationDetailsTableTab extends MigrationDetailsTabBase<MigrationD
|
||||
|
||||
this.cutoverButton.enabled = canCutoverMigration(migration);
|
||||
this.cancelButton.enabled = canCancelMigration(migration);
|
||||
this.deleteButton.enabled = canDeleteMigration(migration);
|
||||
this.retryButton.enabled = canRetryMigration(migration);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { IconPathHelper } from '../constants/iconPathHelper';
|
||||
import { getCurrentMigrations, getSelectedServiceStatus } from '../models/migrationLocalStorage';
|
||||
import * as loc from '../constants/strings';
|
||||
import { filterMigrations, getMigrationDuration, getMigrationStatusImage, getMigrationStatusWithErrors, getMigrationTime, MenuCommands } from '../api/utils';
|
||||
import { getMigrationTargetType, getMigrationMode, canCancelMigration, canCutoverMigration } from '../constants/helper';
|
||||
import { getMigrationTargetType, getMigrationMode, canCancelMigration, canCutoverMigration, canDeleteMigration } from '../constants/helper';
|
||||
import { DatabaseMigration, getResourceName } from '../api/azure';
|
||||
import { logError, TelemetryViews } from '../telemetry';
|
||||
import { SelectMigrationServiceDialog } from '../dialog/selectMigrationService/selectMigrationServiceDialog';
|
||||
@@ -598,6 +598,10 @@ export class MigrationsListTab extends TabBase<MigrationsListTab> {
|
||||
menuCommands.push(MenuCommands.CancelMigration);
|
||||
}
|
||||
|
||||
if (canDeleteMigration(migration)) {
|
||||
menuCommands.push(MenuCommands.DeleteMigration);
|
||||
}
|
||||
|
||||
return menuCommands;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,12 @@ export class MigrationsTab extends TabBase<MigrationsTab> {
|
||||
this.statusBar);
|
||||
this.disposables.push(this._migrationsListTab);
|
||||
|
||||
const openMigrationsListTab = async (): Promise<void> => {
|
||||
const openMigrationsListTab = async (refresh?: boolean): Promise<void> => {
|
||||
await this.statusBar.clearError();
|
||||
await this._openTab(this._migrationsListTab);
|
||||
if (refresh) {
|
||||
await this._migrationsListTab.refresh();
|
||||
}
|
||||
};
|
||||
|
||||
this._migrationDetailsBlobTab = await new MigrationDetailsBlobContainerTab().create(
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import { promises as fs } from 'fs';
|
||||
import { DatabaseMigration, getMigrationDetails } from '../api/azure';
|
||||
import { DatabaseMigration, deleteMigration, getMigrationDetails } from '../api/azure';
|
||||
import { MenuCommands, SqlMigrationExtensionId } from '../api/utils';
|
||||
import { canCancelMigration, canCutoverMigration, canRetryMigration } from '../constants/helper';
|
||||
import { canCancelMigration, canCutoverMigration, canDeleteMigration, canRetryMigration } from '../constants/helper';
|
||||
import { IconPathHelper } from '../constants/iconPathHelper';
|
||||
import { MigrationNotebookInfo, NotebookPathHelper } from '../constants/notebookPathHelper';
|
||||
import * as loc from '../constants/strings';
|
||||
@@ -41,6 +41,7 @@ export class DashboardWidget {
|
||||
private readonly _onServiceContextChanged: vscode.EventEmitter<ServiceContextChangeEvent>;
|
||||
private readonly _migrationDetailsEvent: vscode.EventEmitter<MigrationDetailsEvent>;
|
||||
private readonly _errorEvent: vscode.EventEmitter<ErrorEvent>;
|
||||
private _migrationsTab!: MigrationsTab;
|
||||
|
||||
constructor(context: vscode.ExtensionContext) {
|
||||
this._context = context;
|
||||
@@ -94,11 +95,11 @@ export class DashboardWidget {
|
||||
if (!migrationsTabInitialized) {
|
||||
migrationsTabInitialized = true;
|
||||
tabs.selectTab(MigrationsTabId);
|
||||
await migrationsTab.setMigrationFilter(AdsMigrationStatus.ALL);
|
||||
await migrationsTab.refresh();
|
||||
await migrationsTab.setMigrationFilter(filter);
|
||||
await this._migrationsTab.setMigrationFilter(AdsMigrationStatus.ALL);
|
||||
await this._migrationsTab.refresh();
|
||||
await this._migrationsTab.setMigrationFilter(filter);
|
||||
} else {
|
||||
const promise = migrationsTab.setMigrationFilter(filter);
|
||||
const promise = this._migrationsTab.setMigrationFilter(filter);
|
||||
tabs.selectTab(MigrationsTabId);
|
||||
await promise;
|
||||
}
|
||||
@@ -111,16 +112,16 @@ export class DashboardWidget {
|
||||
statusBar);
|
||||
disposables.push(dashboardTab);
|
||||
|
||||
const migrationsTab = await new MigrationsTab().create(
|
||||
this._migrationsTab = await new MigrationsTab().create(
|
||||
this._context,
|
||||
view,
|
||||
this._onServiceContextChanged,
|
||||
this._migrationDetailsEvent,
|
||||
statusBar);
|
||||
disposables.push(migrationsTab);
|
||||
disposables.push(this._migrationsTab);
|
||||
|
||||
const tabs = view.modelBuilder.tabbedPanel()
|
||||
.withTabs([dashboardTab, migrationsTab])
|
||||
.withTabs([dashboardTab, this._migrationsTab])
|
||||
.withLayout({ alwaysShowTabs: true, orientation: azdata.TabOrientation.Horizontal })
|
||||
.withProps({
|
||||
CSSStyles: {
|
||||
@@ -137,7 +138,7 @@ export class DashboardWidget {
|
||||
await this.clearError(await getSourceConnectionId());
|
||||
if (tabId === MigrationsTabId && !migrationsTabInitialized) {
|
||||
migrationsTabInitialized = true;
|
||||
await migrationsTab.refresh();
|
||||
await this._migrationsTab.refresh();
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -210,8 +211,10 @@ export class DashboardWidget {
|
||||
async (args: MenuCommandArgs) => {
|
||||
try {
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
const url = 'https://portal.azure.com/#resource/' + migration!.properties.scope;
|
||||
await vscode.env.openExternal(vscode.Uri.parse(url));
|
||||
if (migration) {
|
||||
const url = 'https://portal.azure.com/#resource/' + migration.properties.scope;
|
||||
await vscode.env.openExternal(vscode.Uri.parse(url));
|
||||
}
|
||||
} catch (e) {
|
||||
await this.showError(
|
||||
args.connectionId,
|
||||
@@ -229,10 +232,13 @@ export class DashboardWidget {
|
||||
try {
|
||||
await this.clearError(args.connectionId);
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
const dialog = new SqlMigrationServiceDetailsDialog(
|
||||
await MigrationLocalStorage.getMigrationServiceContext(),
|
||||
migration!);
|
||||
await dialog.initialize();
|
||||
const serviceContext = await MigrationLocalStorage.getMigrationServiceContext();
|
||||
if (migration && serviceContext) {
|
||||
const dialog = new SqlMigrationServiceDetailsDialog(
|
||||
serviceContext,
|
||||
migration);
|
||||
await dialog.initialize();
|
||||
}
|
||||
} catch (e) {
|
||||
await this.showError(
|
||||
args.connectionId,
|
||||
@@ -269,40 +275,81 @@ export class DashboardWidget {
|
||||
}
|
||||
}));
|
||||
|
||||
this._context.subscriptions.push(vscode.commands.registerCommand(
|
||||
MenuCommands.CancelMigration,
|
||||
async (args: MenuCommandArgs) => {
|
||||
try {
|
||||
await this.clearError(args.connectionId);
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
if (canCancelMigration(migration)) {
|
||||
void vscode.window.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, loc.YES, loc.NO)
|
||||
.then(async (v) => {
|
||||
if (v === loc.YES) {
|
||||
const cutoverDialogModel = new MigrationCutoverDialogModel(
|
||||
await MigrationLocalStorage.getMigrationServiceContext(),
|
||||
migration!);
|
||||
await cutoverDialogModel.fetchStatus();
|
||||
await cutoverDialogModel.cancelMigration();
|
||||
this._context.subscriptions.push(
|
||||
vscode.commands.registerCommand(
|
||||
MenuCommands.CancelMigration,
|
||||
async (args: MenuCommandArgs) => {
|
||||
try {
|
||||
await this.clearError(args.connectionId);
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
if (migration && canCancelMigration(migration)) {
|
||||
void vscode.window
|
||||
.showInformationMessage(loc.CANCEL_MIGRATION_CONFIRMATION, loc.YES, loc.NO)
|
||||
.then(async (v) => {
|
||||
if (v === loc.YES) {
|
||||
const cutoverDialogModel = new MigrationCutoverDialogModel(
|
||||
await MigrationLocalStorage.getMigrationServiceContext(),
|
||||
migration!);
|
||||
await cutoverDialogModel.fetchStatus();
|
||||
await cutoverDialogModel.cancelMigration();
|
||||
|
||||
if (cutoverDialogModel.CancelMigrationError) {
|
||||
void vscode.window.showErrorMessage(loc.MIGRATION_CANNOT_CANCEL);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.CancelMigration, cutoverDialogModel.CancelMigrationError);
|
||||
if (cutoverDialogModel.CancelMigrationError) {
|
||||
void vscode.window.showErrorMessage(loc.MIGRATION_CANNOT_CANCEL);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.CancelMigration, cutoverDialogModel.CancelMigrationError);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_CANCEL);
|
||||
});
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_CANCEL);
|
||||
}
|
||||
} catch (e) {
|
||||
await this.showError(
|
||||
args.connectionId,
|
||||
loc.MIGRATION_CANCELLATION_ERROR,
|
||||
loc.MIGRATION_CANCELLATION_ERROR,
|
||||
e.message);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.CancelMigration, e);
|
||||
}
|
||||
} catch (e) {
|
||||
await this.showError(
|
||||
args.connectionId,
|
||||
loc.MIGRATION_CANCELLATION_ERROR,
|
||||
loc.MIGRATION_CANCELLATION_ERROR,
|
||||
e.message);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.CancelMigration, e);
|
||||
}
|
||||
}));
|
||||
}));
|
||||
|
||||
this._context.subscriptions.push(
|
||||
vscode.commands.registerCommand(
|
||||
MenuCommands.DeleteMigration,
|
||||
async (args: MenuCommandArgs) => {
|
||||
await this.clearError(args.connectionId);
|
||||
try {
|
||||
const service = await MigrationLocalStorage.getMigrationServiceContext();
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
// get migration details can return undefined when the migration has been auto-cleaned
|
||||
// however, since the migration is still returned in getlist, we make a best effort to delete by id.
|
||||
if (service && (
|
||||
(migration && canDeleteMigration(migration)) ||
|
||||
(migration === undefined && args.migrationId?.length > 0))) {
|
||||
const response = await vscode.window.showInformationMessage(
|
||||
loc.DELETE_MIGRATION_CONFIRMATION,
|
||||
{ modal: true },
|
||||
loc.YES,
|
||||
loc.NO);
|
||||
if (response === loc.YES) {
|
||||
await deleteMigration(
|
||||
service.azureAccount!,
|
||||
service.subscription!,
|
||||
args.migrationId);
|
||||
await this._migrationsTab.refresh();
|
||||
}
|
||||
} else {
|
||||
await vscode.window.showInformationMessage(loc.MIGRATION_CANNOT_DELETE);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.DeleteMigration, "cannot delete migration");
|
||||
}
|
||||
} catch (e) {
|
||||
await this.showError(
|
||||
args.connectionId,
|
||||
loc.MIGRATION_DELETE_ERROR,
|
||||
loc.MIGRATION_DELETE_ERROR,
|
||||
e.message);
|
||||
logError(TelemetryViews.MigrationsTab, MenuCommands.DeleteMigration, e);
|
||||
}
|
||||
}));
|
||||
|
||||
this._context.subscriptions.push(
|
||||
vscode.commands.registerCommand(
|
||||
@@ -311,11 +358,11 @@ export class DashboardWidget {
|
||||
try {
|
||||
await this.clearError(args.connectionId);
|
||||
const migration = await this._getMigrationById(args.migrationId, args.migrationOperationId);
|
||||
if (canRetryMigration(migration)) {
|
||||
if (migration && canRetryMigration(migration)) {
|
||||
const retryMigrationDialog = new RetryMigrationDialog(
|
||||
this._context,
|
||||
await MigrationLocalStorage.getMigrationServiceContext(),
|
||||
migration!,
|
||||
migration,
|
||||
this._onServiceContextChanged);
|
||||
await retryMigrationDialog.openDialog();
|
||||
}
|
||||
@@ -418,11 +465,16 @@ export class DashboardWidget {
|
||||
private async _getMigrationById(migrationId: string, migrationOperationId: string): Promise<DatabaseMigration | undefined> {
|
||||
const context = await MigrationLocalStorage.getMigrationServiceContext();
|
||||
if (context.azureAccount && context.subscription) {
|
||||
return getMigrationDetails(
|
||||
context.azureAccount,
|
||||
context.subscription,
|
||||
migrationId,
|
||||
migrationOperationId);
|
||||
try {
|
||||
const migration = getMigrationDetails(
|
||||
context.azureAccount,
|
||||
context.subscription,
|
||||
migrationId,
|
||||
migrationOperationId);
|
||||
return migration;
|
||||
} catch (error) {
|
||||
logError(TelemetryViews.MigrationsTab, "_getMigrationById", error);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user