Add close method to ModelView dashboards (#14812)

* Add close method to ModelView dashboards

* fix closing

* remove accessors

* Update errors
This commit is contained in:
Charles Gagnon
2021-03-22 10:17:16 -07:00
committed by GitHub
parent 98ba49304e
commit 72295d46c2
24 changed files with 95 additions and 51 deletions

View File

@@ -63,7 +63,7 @@ describe('postgresOverviewPage', () => {
// Setup the PostgresOverviewPage
const { modelViewMock } = createModelViewMock();
postgresOverview = new PostgresOverviewPage(modelViewMock.object, controllerModel, postgresModel);
postgresOverview = new PostgresOverviewPage(modelViewMock.object, undefined!, controllerModel, postgresModel);
// Call the getter to initialize toolbar, but we don't need to use it for anything
// eslint-disable-next-line code-no-unused-expressions
postgresOverview['toolbarContainer'];

View File

@@ -7,7 +7,7 @@ import * as azdata from 'azdata';
export abstract class Dashboard {
private dashboard!: azdata.window.ModelViewDashboard;
protected dashboard!: azdata.window.ModelViewDashboard;
constructor(protected title: string, protected readonly name: string) { }
@@ -16,6 +16,10 @@ export abstract class Dashboard {
await this.dashboard.open();
}
public async closeDashboard(): Promise<void> {
await this.dashboard.close();
}
protected createDashboard(): azdata.window.ModelViewDashboard {
const dashboard = azdata.window.createModelViewDashboard(this.title, this.name);
dashboard.registerTabs(async modelView => {

View File

@@ -11,7 +11,7 @@ export abstract class DashboardPage extends InitializingComponent {
protected disposables: vscode.Disposable[] = [];
constructor(protected modelView: azdata.ModelView) {
constructor(protected modelView: azdata.ModelView, protected dashboard: azdata.window.ModelViewDashboard) {
super();
this.disposables.push(modelView.onClosed(() => {
// Clean up best we can

View File

@@ -22,7 +22,7 @@ export class ControllerDashboard extends Dashboard {
}
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new ControllerDashboardOverviewPage(modelView, this._controllerModel);
const overviewPage = new ControllerDashboardOverviewPage(modelView, this.dashboard, this._controllerModel);
return [
overviewPage.tab
];

View File

@@ -35,8 +35,8 @@ export class ControllerDashboardOverviewPage extends DashboardPage {
instanceNamespace: '-',
};
constructor(modelView: azdata.ModelView, private _controllerModel: ControllerModel) {
super(modelView);
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel) {
super(modelView, dashboard);
this._azurecoreApi = vscode.extensions.getExtension(azurecore.extension.name)?.exports;

View File

@@ -32,8 +32,8 @@ export class MiaaComputeAndStoragePage extends DashboardPage {
private readonly _azdataApi: azdataExt.IExtension;
constructor(protected modelView: azdata.ModelView, private _miaaModel: MiaaModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _miaaModel: MiaaModel) {
super(modelView, dashboard);
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
this.initializeConfigurationBoxes();

View File

@@ -16,8 +16,8 @@ export class MiaaConnectionStringsPage extends DashboardPage {
private _keyValueContainer!: KeyValueContainer;
private _connectionStringsMessage!: azdata.TextComponent;
constructor(modelView: azdata.ModelView, private _miaaModel: MiaaModel) {
super(modelView);
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _miaaModel: MiaaModel) {
super(modelView, dashboard);
this.disposables.push(this._miaaModel.onConfigUpdated(_ =>
this.eventuallyRunOnInitialized(() => this.updateConnectionStrings())));
}

View File

@@ -26,9 +26,9 @@ export class MiaaDashboard extends Dashboard {
}
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new MiaaDashboardOverviewPage(modelView, this._controllerModel, this._miaaModel);
const connectionStringsPage = new MiaaConnectionStringsPage(modelView, this._miaaModel);
const computeAndStoragePage = new MiaaComputeAndStoragePage(modelView, this._miaaModel);
const overviewPage = new MiaaDashboardOverviewPage(modelView, this.dashboard, this._controllerModel, this._miaaModel);
const connectionStringsPage = new MiaaConnectionStringsPage(modelView, this.dashboard, this._miaaModel);
const computeAndStoragePage = new MiaaComputeAndStoragePage(modelView, this.dashboard, this._miaaModel);
return [
overviewPage.tab,
{

View File

@@ -48,8 +48,8 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
vCores: ''
};
constructor(modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) {
super(modelView);
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _miaaModel: MiaaModel) {
super(modelView, dashboard);
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
this._azurecoreApi = vscode.extensions.getExtension(azurecore.extension.name)?.exports;
@@ -250,11 +250,17 @@ export class MiaaDashboardOverviewPage extends DashboardPage {
} finally {
session.dispose();
}
}
);
await this._controllerModel.refreshTreeNode();
vscode.window.showInformationMessage(loc.instanceDeleted(this._miaaModel.info.name));
try {
await this.dashboard.close();
} catch (err) {
// Failures closing the dashboard aren't something we need to show users
console.log('Error closing MIAA dashboard ', err);
}
}
} catch (error) {
vscode.window.showErrorMessage(loc.instanceDeletionFailed(this._miaaModel.info.name, error));

View File

@@ -47,8 +47,8 @@ export class PostgresComputeAndStoragePage extends DashboardPage {
private readonly _azdataApi: azdataExt.IExtension;
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
this.initializeConfigurationBoxes();

View File

@@ -14,8 +14,8 @@ export class PostgresConnectionStringsPage extends DashboardPage {
private keyValueContainer?: KeyValueContainer;
private connectionStringsLoading!: azdata.LoadingComponent;
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(this._postgresModel.onConfigUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleServiceUpdated())));

View File

@@ -11,8 +11,8 @@ import { PostgresModel } from '../../../models/postgresModel';
export class PostgresCoordinatorNodeParametersPage extends PostgresParametersPage {
constructor(protected modelView: azdata.ModelView, _postgresModel: PostgresModel) {
super(modelView, _postgresModel);
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, postgresModel: PostgresModel) {
super(modelView, dashboard, postgresModel);
}
protected get title(): string {

View File

@@ -32,16 +32,16 @@ export class PostgresDashboard extends Dashboard {
}
protected async registerTabs(modelView: azdata.ModelView): Promise<(azdata.DashboardTab | azdata.DashboardTabGroup)[]> {
const overviewPage = new PostgresOverviewPage(modelView, this._controllerModel, this._postgresModel);
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this._postgresModel);
const computeAndStoragePage = new PostgresComputeAndStoragePage(modelView, this._postgresModel);
const propertiesPage = new PostgresPropertiesPage(modelView, this._controllerModel, this._postgresModel);
const overviewPage = new PostgresOverviewPage(modelView, this.dashboard, this._controllerModel, this._postgresModel);
const connectionStringsPage = new PostgresConnectionStringsPage(modelView, this.dashboard, this._postgresModel);
const computeAndStoragePage = new PostgresComputeAndStoragePage(modelView, this.dashboard, this._postgresModel);
const propertiesPage = new PostgresPropertiesPage(modelView, this.dashboard, this._controllerModel, this._postgresModel);
// TODO Add dashboard once backend is able to be connected for per role server parameter edits.
// const coordinatorNodeParametersPage = new PostgresCoordinatorNodeParametersPage(modelView, this._postgresModel);
const workerNodeParametersPage = new PostgresWorkerNodeParametersPage(modelView, this._postgresModel);
const diagnoseAndSolveProblemsPage = new PostgresDiagnoseAndSolveProblemsPage(modelView, this._context, this._postgresModel);
const supportRequestPage = new PostgresSupportRequestPage(modelView, this._controllerModel, this._postgresModel);
const resourceHealthPage = new PostgresResourceHealthPage(modelView, this._postgresModel);
const workerNodeParametersPage = new PostgresWorkerNodeParametersPage(modelView, this.dashboard, this._postgresModel);
const diagnoseAndSolveProblemsPage = new PostgresDiagnoseAndSolveProblemsPage(modelView, this.dashboard, this._context, this._postgresModel);
const supportRequestPage = new PostgresSupportRequestPage(modelView, this.dashboard, this._controllerModel, this._postgresModel);
const resourceHealthPage = new PostgresResourceHealthPage(modelView, this.dashboard, this._postgresModel);
return [
overviewPage.tab,

View File

@@ -11,8 +11,8 @@ import { DashboardPage } from '../../components/dashboardPage';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresDiagnoseAndSolveProblemsPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, private _context: vscode.ExtensionContext, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _context: vscode.ExtensionContext, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
}
protected get title(): string {

View File

@@ -37,8 +37,8 @@ export class PostgresOverviewPage extends DashboardPage {
private readonly _azdataApi: azdataExt.IExtension;
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;
this.disposables.push(
@@ -270,6 +270,13 @@ export class PostgresOverviewPage extends DashboardPage {
);
await this._controllerModel.refreshTreeNode();
vscode.window.showInformationMessage(loc.instanceDeleted(this._postgresModel.info.name));
try {
await this.dashboard.close();
} catch (err) {
// Failures closing the dashboard aren't something we need to show users
console.log('Error closing Arc Postgres dashboard ', err);
}
}
} catch (error) {
vscode.window.showErrorMessage(loc.instanceDeletionFailed(this._postgresModel.info.name, error));

View File

@@ -36,8 +36,8 @@ export abstract class PostgresParametersPage extends DashboardPage {
protected readonly _azdataApi: azdataExt.IExtension;
constructor(protected modelView: azdata.ModelView, protected _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, protected _postgresModel: PostgresModel) {
super(modelView, dashboard);
this._azdataApi = vscode.extensions.getExtension(azdataExt.extension.name)?.exports;

View File

@@ -17,8 +17,8 @@ export class PostgresPropertiesPage extends DashboardPage {
private loading?: azdata.LoadingComponent;
private keyValueContainer?: KeyValueContainer;
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(this._postgresModel.onConfigUpdated(
() => this.eventuallyRunOnInitialized(() => this.handleServiceUpdated())));

View File

@@ -36,8 +36,8 @@ export class PostgresResourceHealthPage extends DashboardPage {
private coordinatorData: PodHealthModel[] = [];
private podsData: PodHealthModel[] = [];
constructor(protected modelView: azdata.ModelView, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
this.disposables.push(
this._postgresModel.onConfigUpdated(() => this.eventuallyRunOnInitialized(() => this.handleConfigUpdated())));

View File

@@ -13,8 +13,8 @@ import { ResourceType } from 'arc';
import { PostgresModel } from '../../../models/postgresModel';
export class PostgresSupportRequestPage extends DashboardPage {
constructor(protected modelView: azdata.ModelView, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView);
constructor(protected modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, private _controllerModel: ControllerModel, private _postgresModel: PostgresModel) {
super(modelView, dashboard);
}
protected get title(): string {

View File

@@ -12,8 +12,8 @@ import { PostgresModel } from '../../../models/postgresModel';
export class PostgresWorkerNodeParametersPage extends PostgresParametersPage {
constructor(protected modelView: azdata.ModelView, _postgresModel: PostgresModel) {
super(modelView, _postgresModel);
constructor(modelView: azdata.ModelView, dashboard: azdata.window.ModelViewDashboard, postgresModel: PostgresModel) {
super(modelView, dashboard, postgresModel);
}
protected get title(): string {

View File

@@ -525,6 +525,7 @@ declare module 'azdata' {
export interface ModelViewDashboard {
registerTabs(handler: (view: ModelView) => Thenable<(DashboardTab | DashboardTabGroup)[]>): void;
open(): Thenable<void>;
close(): Thenable<void>;
updateTabs(tabs: (DashboardTab | DashboardTabGroup)[]): void;
selectTab(id: string): void;
}

View File

@@ -19,6 +19,7 @@ import * as azdata from 'azdata';
import { assign } from 'vs/base/common/objects';
import { TelemetryView, TelemetryAction } from 'sql/platform/telemetry/common/telemetryKeys';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { IEditorInput, IEditorPane } from 'vs/workbench/common/editor';
@extHostNamedCustomer(SqlMainContext.MainThreadModelViewDialog)
export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape {
@@ -30,6 +31,7 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
private readonly _wizardPageHandles = new Map<WizardPage, number>();
private readonly _wizards = new Map<number, Wizard>();
private readonly _editorInputModels = new Map<number, ModelViewInputModel>();
private readonly _editors = new Map<number, { pane: IEditorPane, input: IEditorInput }>();
private _dialogService: CustomDialogService;
constructor(
@@ -58,8 +60,15 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
this._telemetryService.createActionEvent(TelemetryView.Shell, TelemetryAction.ModelViewDashboardOpened)
.withAdditionalProperties({ name: name })
.send();
this._editorService.openEditor(input, editorOptions, position as any).then((editor) => {
this._editorService.openEditor(input, editorOptions, position as any).then((editorPane) => {
this._editorInputModels.set(handle, model);
this._editors.set(handle, { pane: editorPane, input: editorPane.input });
const disposable = this._editorService.onDidCloseEditor(e => {
if (e.editor === input) {
this._editors.delete(handle);
disposable.dispose();
}
});
resolve();
}, error => {
reject(error);
@@ -67,6 +76,18 @@ export class MainThreadModelViewDialog implements MainThreadModelViewDialogShape
});
}
public $closeEditor(handle: number): Thenable<void> {
return new Promise<void>((resolve, reject) => {
const editor = this._editors.get(handle);
if (editor) {
editor.pane.group.closeEditor(editor.input).then(() => {
resolve();
}).catch(e => reject(e));
}
reject(new Error(`Could not find editor with handle ${handle}`));
});
}
private handleSave(handle: number): Thenable<boolean> {
return this._proxy.$handleSave(handle);
}

View File

@@ -23,7 +23,7 @@ const PREVIOUS_LABEL = nls.localize('dialogPreviousLabel', "Previous");
class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
private _modelView: azdata.ModelView;
private _handle: number;
public handle: number;
protected _modelViewId: string;
protected _valid: boolean = true;
protected _onValidityChanged: vscode.Event<boolean>;
@@ -38,7 +38,7 @@ class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
public registerContent(handler: (view: azdata.ModelView) => Thenable<void>): void {
if (!this._modelViewId) {
let viewId = this._viewType + this._handle;
let viewId = this._viewType + this.handle;
this.setModelViewId(viewId);
this._extHostModelView.$registerProvider(viewId, modelView => {
this._modelView = modelView;
@@ -47,10 +47,6 @@ class ModelViewPanelImpl implements azdata.window.ModelViewPanel {
}
}
public set handle(value: number) {
this._handle = value;
}
public setModelViewId(value: string) {
this._modelViewId = value;
}
@@ -93,6 +89,10 @@ class ModelViewEditorImpl extends ModelViewPanelImpl implements azdata.workspace
return this._proxy.$openEditor(this.handle, this._modelViewId, this._title, this._name, this._options, position);
}
public closeEditor(): Thenable<void> {
return this._proxy.$closeEditor(this.handle);
}
public get isDirty(): boolean {
return this._isDirty;
}
@@ -568,6 +568,10 @@ class ModelViewDashboardImpl implements azdata.window.ModelViewDashboard {
return this._editor.openEditor();
}
close(): Thenable<void> {
return this._editor.closeEditor();
}
createTab(tab: azdata.DashboardTab, view: azdata.ModelView): azdata.Tab {
if (tab.toolbar) {
const flexContainer = view.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();

View File

@@ -820,6 +820,7 @@ export interface ExtHostModelViewDialogShape {
export interface MainThreadModelViewDialogShape extends IDisposable {
$openEditor(handle: number, modelViewId: string, title: string, name?: string, options?: azdata.ModelViewEditorOptions, position?: vscode.ViewColumn): Thenable<void>;
$closeEditor(handle: number): Thenable<void>;
$openDialog(handle: number, dialogName?: string): Thenable<void>;
$closeDialog(handle: number): Thenable<void>;
$setDialogDetails(handle: number, details: IModelViewDialogDetails): Thenable<void>;