mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 01:25:39 -05:00
Add SQL DB offline migration wizard experience (#20403)
* sql db wizard with target selection * add database table selection * add sqldb to service and IR page * Code complete * navigation bug fixes * fix target db selection * improve sqldb error and status reporting * fix error count bug * remove table status inference * address review feedback * update resource strings and content * fix migraton status string, use localized value * fix ux navigation issues * fix back/fwd w/o changes from changing data
This commit is contained in:
125
extensions/sql-migration/src/dashboard/DashboardStatusBar.ts
Normal file
125
extensions/sql-migration/src/dashboard/DashboardStatusBar.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as azdata from 'azdata';
|
||||
import * as vscode from 'vscode';
|
||||
import * as loc from '../constants/strings';
|
||||
|
||||
export interface ErrorEvent {
|
||||
connectionId: string;
|
||||
title: string;
|
||||
label: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export class DashboardStatusBar implements vscode.Disposable {
|
||||
private _errorTitle: string = '';
|
||||
private _errorLabel: string = '';
|
||||
private _errorDescription: string = '';
|
||||
private _errorDialogIsOpen: boolean = false;
|
||||
private _statusInfoBox: azdata.InfoBoxComponent;
|
||||
private _context: vscode.ExtensionContext;
|
||||
private _errorEvent: vscode.EventEmitter<ErrorEvent> = new vscode.EventEmitter<ErrorEvent>();
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
|
||||
constructor(context: vscode.ExtensionContext, connectionId: string, statusInfoBox: azdata.InfoBoxComponent, errorEvent: vscode.EventEmitter<ErrorEvent>) {
|
||||
this._context = context;
|
||||
this._statusInfoBox = statusInfoBox;
|
||||
this._errorEvent = errorEvent;
|
||||
|
||||
this._disposables.push(
|
||||
this._errorEvent.event(
|
||||
async (e) => {
|
||||
if (e.connectionId === connectionId) {
|
||||
return (e.title.length > 0 && e.label.length > 0)
|
||||
? await this.showError(e.title, e.label, e.message)
|
||||
: await this.clearError();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._disposables.forEach(
|
||||
d => { try { d.dispose(); } catch { } });
|
||||
}
|
||||
|
||||
public async showError(errorTitle: string, errorLabel: string, errorDescription: string): Promise<void> {
|
||||
this._errorTitle = errorTitle;
|
||||
this._errorLabel = errorLabel;
|
||||
this._errorDescription = errorDescription;
|
||||
this._statusInfoBox.style = 'error';
|
||||
this._statusInfoBox.text = errorTitle;
|
||||
this._statusInfoBox.ariaLabel = errorTitle;
|
||||
|
||||
await this._updateStatusDisplay(this._statusInfoBox, true);
|
||||
}
|
||||
|
||||
public async clearError(): Promise<void> {
|
||||
await this._updateStatusDisplay(this._statusInfoBox, false);
|
||||
this._errorTitle = '';
|
||||
this._errorLabel = '';
|
||||
this._errorDescription = '';
|
||||
this._statusInfoBox.style = 'success';
|
||||
this._statusInfoBox.text = '';
|
||||
}
|
||||
|
||||
public async openErrorDialog(): Promise<void> {
|
||||
if (this._errorDialogIsOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const tab = azdata.window.createTab(this._errorTitle);
|
||||
tab.registerContent(async (view) => {
|
||||
const flex = view.modelBuilder.flexContainer()
|
||||
.withItems([
|
||||
view.modelBuilder.text()
|
||||
.withProps({ value: this._errorLabel, CSSStyles: { 'margin': '0px 0px 5px 5px' } })
|
||||
.component(),
|
||||
view.modelBuilder.inputBox()
|
||||
.withProps({
|
||||
value: this._errorDescription,
|
||||
readOnly: true,
|
||||
multiline: true,
|
||||
height: 400,
|
||||
inputType: 'text',
|
||||
display: 'inline-block',
|
||||
CSSStyles: { 'overflow': 'hidden auto', 'margin': '0px 0px 0px 5px' },
|
||||
})
|
||||
.component()])
|
||||
.withLayout({ flexFlow: 'column', width: 420, })
|
||||
.withProps({ CSSStyles: { 'margin': '0 10px 0 10px' } })
|
||||
.component();
|
||||
|
||||
await view.initializeModel(flex);
|
||||
});
|
||||
|
||||
const dialog = azdata.window.createModelViewDialog(
|
||||
this._errorTitle,
|
||||
'errorDialog',
|
||||
450,
|
||||
'flyout');
|
||||
dialog.content = [tab];
|
||||
dialog.okButton.label = loc.ERROR_DIALOG_CLEAR_BUTTON_LABEL;
|
||||
dialog.okButton.focused = true;
|
||||
dialog.cancelButton.label = loc.CLOSE;
|
||||
this._context.subscriptions.push(
|
||||
dialog.onClosed(async e => {
|
||||
if (e === 'ok') {
|
||||
await this.clearError();
|
||||
}
|
||||
this._errorDialogIsOpen = false;
|
||||
}));
|
||||
|
||||
azdata.window.openDialog(dialog);
|
||||
} catch (error) {
|
||||
this._errorDialogIsOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
private async _updateStatusDisplay(control: azdata.Component, visible: boolean): Promise<void> {
|
||||
await control.updateCssStyles({ 'display': visible ? 'inline' : 'none' });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user