make the designer event based (#17472)

* make the designer event based

* pr comments
This commit is contained in:
Alan Ren
2021-10-22 17:25:12 -07:00
committed by GitHub
parent 70f6eebc5a
commit 4ba192a5c3
7 changed files with 284 additions and 128 deletions

View File

@@ -3,12 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { DesignerComponentInput, DesignerEditType, DesignerTab, DesignerEdit, DesignerEditIdentifier, DesignerViewModel, DesignerDataPropertyInfo, DesignerTableComponentRowData, DesignerTableProperties, InputBoxProperties, DropDownProperties, CheckBoxProperties, DesignerComponentTypeName } from 'sql/base/browser/ui/designer/interfaces';
import { DesignerComponentInput, DesignerEditType, DesignerTab, DesignerEdit, DesignerEditIdentifier, DesignerViewModel, DesignerDataPropertyInfo, DesignerTableComponentRowData, DesignerTableProperties, InputBoxProperties, DropDownProperties, CheckBoxProperties, DesignerComponentTypeName, DesignerEditProcessedEventArgs, DesignerStateChangedEventArgs, DesignerAction, DesignerUIState } from 'sql/base/browser/ui/designer/interfaces';
import { IPanelTab, ITabbedPanelStyles, TabbedPanel } from 'sql/base/browser/ui/panel/panel';
import * as DOM from 'vs/base/browser/dom';
import { Event } from 'vs/base/common/event';
import { Orientation, Sizing, SplitView } from 'vs/base/browser/ui/splitview/splitview';
import { Disposable } from 'vs/base/common/lifecycle';
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IInputBoxStyles, InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import 'vs/css!./media/designer';
@@ -63,6 +63,8 @@ export class Designer extends Disposable implements IThemable {
private _tableCellEditorFactory: TableCellEditorFactory;
private _propertiesPane: DesignerPropertiesPane;
private _buttons: Button[] = [];
private _inputDisposable: DisposableStore;
private _loadingTimeoutHandle: any;
constructor(private readonly _container: HTMLElement,
private readonly _contextViewProvider: IContextViewProvider) {
@@ -72,8 +74,8 @@ export class Designer extends Disposable implements IThemable {
valueGetter: (item, column): string => {
return item[column.field].value;
},
valueSetter: async (context: string, row: number, item: DesignerTableComponentRowData, column: Slick.Column<Slick.SlickData>, value: string): Promise<void> => {
await this.handleEdit({
valueSetter: (context: string, row: number, item: DesignerTableComponentRowData, column: Slick.Column<Slick.SlickData>, value: string): void => {
this.handleEdit({
type: DesignerEditType.Update,
property: {
parentProperty: context,
@@ -196,37 +198,127 @@ export class Designer extends Disposable implements IThemable {
}
public async setInput(input: DesignerComponentInput): Promise<void> {
public setInput(input: DesignerComponentInput): void {
// Save state
if (this._input) {
this._input.designerUIState = this.getUIState();
}
// Clean up
if (this._loadingTimeoutHandle) {
this.stopLoading();
}
this._buttons = [];
this._componentMap.clear();
DOM.clearNode(this._topContentContainer);
this._tabbedPanel.clearTabs();
this._propertiesPane.clear();
this._inputDisposable?.dispose();
// Initialize with new input
this._input = input;
await this.initializeDesignerView();
this._inputDisposable = new DisposableStore();
this._inputDisposable.add(this._input.onInitialized(() => {
this.initializeDesigner();
}));
this._inputDisposable.add(this._input.onEditProcessed((args) => {
this.handleEditProcessedEvent(args);
}));
this._inputDisposable.add(this._input.onStateChange((args) => {
this.handleInputStateChangedEvent(args);
}));
if (this._input.view === undefined) {
this._input.initialize();
} else {
this.initializeDesigner();
}
if (this._input.pendingAction) {
this.updateLoadingStatus(this._input.pendingAction, true, false);
}
}
private async initializeDesignerView(): Promise<void> {
this._propertiesPane.clear();
DOM.clearNode(this._topContentContainer);
// For initialization, we would want to show the loading indicator immediately.
const handle = this.startLoading(localize('designer.loadingDesigner', "Loading designer..."), 0);
const view = await this._input.getView();
this.stopLoading(handle, localize('designer.loadingDesignerCompleted', "Loading designer completed"));
public override dispose(): void {
super.dispose();
this._inputDisposable?.dispose();
}
private initializeDesigner(): void {
const view = this._input.view;
if (view.components) {
view.components.forEach(component => {
this.createComponent(this._topContentContainer, component, component.propertyName, true, true);
});
}
this._tabbedPanel.clearTabs();
view.tabs.forEach(tab => {
this._tabbedPanel.pushTab(this.createTabView(tab));
});
this.layoutTabbedPanel();
await this.updateComponentValues();
this.updateComponentValues();
this.restoreUIState();
}
private handleEditProcessedEvent(args: DesignerEditProcessedEventArgs): void {
const edit = args.edit;
const result = args.result;
if (result.isValid) {
this._supressEditProcessing = true;
this.updateComponentValues();
if (edit.type === DesignerEditType.Add) {
// Move focus to the first cell of the newly added row.
const propertyName = edit.property as string;
const tableData = this._input.viewModel[propertyName] as DesignerTableProperties;
const table = this._componentMap.get(propertyName).component as Table<Slick.SlickData>;
table.setActiveCell(tableData.data.length - 1, 0);
}
this._supressEditProcessing = false;
} else {
//TODO: add error notification
}
}
private handleInputStateChangedEvent(args: DesignerStateChangedEventArgs): void {
if (args.previousState.pendingAction !== args.currentState.pendingAction) {
const showLoading = args.currentState.pendingAction !== undefined;
const action = args.currentState.pendingAction || args.previousState.pendingAction;
this.updateLoadingStatus(action, showLoading, true);
}
}
private updateLoadingStatus(action: DesignerAction, showLoading: boolean, useDelay: boolean): void {
let message;
let timeout;
switch (action) {
case 'save':
message = showLoading ? localize('designer.savingChanges', "Saving changes...") : localize('designer.savingChangesCompleted', "Changes have been saved");
timeout = 0;
break;
case 'initialize':
message = showLoading ? localize('designer.loadingDesigner', "Loading designer...") : localize('designer.loadingDesignerCompleted', "Designer is loaded");
timeout = 0;
break;
case 'processEdit':
message = showLoading ? localize('designer.processingChanges', "Processing changes...") : localize('designer.processingChangesCompleted', "Changes have been processed");
// To make the edit experience smoother, only show the loading indicator if the request is not returning in 500ms.
timeout = 500;
break;
default:
return;
}
if (showLoading) {
this.startLoading(message, useDelay ? timeout : 0);
} else {
this.stopLoading(message);
}
}
private layoutTabbedPanel() {
this._tabbedPanel.layout(new DOM.Dimension(this._tabbedPanelContainer.clientWidth, this._tabbedPanelContainer.clientHeight));
}
private async updatePropertiesPane(newContext: PropertiesPaneObjectContext): Promise<void> {
const viewModel = await this._input.getViewModel();
private updatePropertiesPane(newContext: PropertiesPaneObjectContext): void {
const viewModel = this._input.viewModel;
let type: string;
let components: DesignerDataPropertyInfo[];
let inputViewModel: DesignerViewModel;
@@ -260,42 +352,25 @@ export class Designer extends Disposable implements IThemable {
}
}
private async updateComponentValues(): Promise<void> {
const viewModel = await this._input.getViewModel();
private updateComponentValues(): void {
const viewModel = this._input.viewModel;
// data[ScriptPropertyName] -- todo- set the script editor
this._componentMap.forEach((value) => {
this.setComponentValue(value.defintion, value.component, viewModel);
});
await this.updatePropertiesPane(this._propertiesPane.context ?? 'root');
this.updatePropertiesPane(this._propertiesPane.context ?? 'root');
}
private async handleEdit(edit: DesignerEdit): Promise<void> {
private handleEdit(edit: DesignerEdit): void {
if (this._supressEditProcessing) {
return;
}
await this.applyEdit(edit);
const handle = this.startLoading(localize('designer.processingChanges', "Processing changes..."));
const result = await this._input.processEdit(edit);
this.stopLoading(handle, localize('designer.processingChangesCompleted', "Processing changes completed"));
if (result.isValid) {
this._supressEditProcessing = true;
await this.updateComponentValues();
if (edit.type === DesignerEditType.Add) {
// Move focus to the first cell of the newly added row.
const data = await this._input.getViewModel();
const propertyName = edit.property as string;
const tableData = data[propertyName] as DesignerTableProperties;
const table = this._componentMap.get(propertyName).component as Table<Slick.SlickData>;
table.setActiveCell(tableData.data.length - 1, 0);
}
this._supressEditProcessing = false;
} else {
//TODO: add error notification
}
this.applyEdit(edit);
this._input.processEdit(edit);
}
private async applyEdit(edit: DesignerEdit): Promise<void> {
const viewModel = await this._input.getViewModel();
private applyEdit(edit: DesignerEdit): void {
const viewModel = this._input.viewModel;
switch (edit.type) {
case DesignerEditType.Update:
if (typeof edit.property === 'string') {
@@ -423,9 +498,9 @@ export class Designer extends Disposable implements IThemable {
ariaLabel: inputProperties.title,
type: inputProperties.inputType,
});
input.onLoseFocus(async (args) => {
input.onLoseFocus((args) => {
if (args.hasChanged) {
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: args.value });
this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: args.value });
}
});
if (setWidth && inputProperties.width !== undefined) {
@@ -440,8 +515,8 @@ export class Designer extends Disposable implements IThemable {
const dropdown = new SelectBox(dropdownProperties.values as string[], undefined, this._contextViewProvider, undefined);
dropdown.render(dropdownContainer);
dropdown.selectElem.style.height = '25px';
dropdown.onDidSelect(async (e) => {
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: e.selected });
dropdown.onDidSelect((e) => {
this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: e.selected });
});
component = dropdown;
break;
@@ -452,8 +527,8 @@ export class Designer extends Disposable implements IThemable {
const checkbox = new Checkbox(checkboxContainer, {
label: checkboxProperties.title
});
checkbox.onChange(async (newValue) => {
await this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: newValue });
checkbox.onChange((newValue) => {
this.handleEdit({ type: DesignerEditType.Update, property: editIdentifier, value: newValue });
});
component = checkbox;
break;
@@ -465,8 +540,8 @@ export class Designer extends Disposable implements IThemable {
title: addNewText,
secondary: true
});
addRowButton.onDidClick(async () => {
await this.handleEdit({
addRowButton.onDidClick(() => {
this.handleEdit({
type: DesignerEditType.Add,
property: componentDefinition.propertyName,
});
@@ -502,8 +577,8 @@ export class Designer extends Disposable implements IThemable {
width: propertyDefinition.componentProperties.width as number
});
table.registerPlugin(checkboxColumn);
checkboxColumn.onChange(async (e) => {
await this.handleEdit({
checkboxColumn.onChange((e) => {
this.handleEdit({
type: DesignerEditType.Update,
property: {
parentProperty: componentDefinition.propertyName,
@@ -540,10 +615,9 @@ export class Designer extends Disposable implements IThemable {
resizable: false,
isFontIcon: true
});
deleteRowColumn.onClick(async (e) => {
const viewModel = await this._input.getViewModel();
(viewModel[componentDefinition.propertyName] as DesignerTableProperties).data.splice(e.row, 1);
await this.handleEdit({
deleteRowColumn.onClick((e) => {
(this._input.viewModel[componentDefinition.propertyName] as DesignerTableProperties).data.splice(e.row, 1);
this.handleEdit({
type: DesignerEditType.Remove,
property: componentDefinition.propertyName,
value: e.item
@@ -555,9 +629,9 @@ export class Designer extends Disposable implements IThemable {
table.grid.onBeforeEditCell.subscribe((e, data): boolean => {
return data.item[data.column.field].enabled !== false;
});
table.grid.onActiveCellChanged.subscribe(async (e, data) => {
table.grid.onActiveCellChanged.subscribe((e, data) => {
if (data.row !== undefined) {
await this.updatePropertiesPane({
this.updatePropertiesPane({
parentProperty: componentDefinition.propertyName,
index: data.row
});
@@ -578,21 +652,37 @@ export class Designer extends Disposable implements IThemable {
return component;
}
private startLoading(message: string, timeout: number = 500): any {
// To make the experience smoother, only show the loading indicator if the request is not returning in 500ms(default value).
return setTimeout(() => {
private startLoading(message: string, timeout: number): void {
this._loadingTimeoutHandle = setTimeout(() => {
this._loadingSpinner.loadingMessage = message;
this._loadingSpinner.loading = true;
this._container.removeChild(this._verticalSplitViewContainer);
if (this._container.contains(this._verticalSplitViewContainer)) {
this._container.removeChild(this._verticalSplitViewContainer);
}
}, timeout);
}
private stopLoading(handle: any, message: string): void {
clearTimeout(handle);
private stopLoading(message: string = ''): void {
clearTimeout(this._loadingTimeoutHandle);
this._loadingTimeoutHandle = undefined;
if (this._loadingSpinner.loading) {
this._loadingSpinner.loadingCompletedMessage = message;
this._loadingSpinner.loading = false;
this._container.appendChild(this._verticalSplitViewContainer);
if (!this._container.contains(this._verticalSplitViewContainer)) {
this._container.appendChild(this._verticalSplitViewContainer);
}
}
}
private getUIState(): DesignerUIState {
return {
activeTabId: this._tabbedPanel.activeTabId
};
}
private restoreUIState(): void {
if (this._input.designerUIState) {
this._tabbedPanel.showTab(this._input.designerUIState.activeTabId);
}
}
}

View File

@@ -3,34 +3,50 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { PanelTabIdentifier } from 'sql/base/browser/ui/panel/panel';
import { Event } from 'vs/base/common/event';
export interface DesignerComponentInput {
/**
* The event that is triggerd when the designer state changes.
*/
readonly onStateChange: Event<DesignerState>;
readonly onStateChange: Event<DesignerStateChangedEventArgs>;
/**
* The event that is triggerd when the designer information is loaded.
*/
readonly onInitialized: Event<void>;
/**
* The event that is triggerd when an edit is processed.
*/
readonly onEditProcessed: Event<DesignerEditProcessedEventArgs>;
/**
* Gets the object type display name.
*/
readonly objectTypeDisplayName: string;
/**
* Gets the designer view specification.
*/
getView(): Promise<DesignerView>;
readonly view: DesignerView;
/**
* Gets the view model.
*/
getViewModel(): Promise<DesignerViewModel>;
readonly viewModel: DesignerViewModel;
/**
* Process the edit made in the designer.
* Start initilizing the designer input object.
*/
initialize(): void;
/**
* Start processing the edit made in the designer, the OnEditProcessed event will be fired when the processing is done.
* @param edit the information about the edit.
*/
processEdit(edit: DesignerEdit): Promise<DesignerEditResult>;
processEdit(edit: DesignerEdit): void;
/**
* A boolean value indicating whether the current state is valid.
@@ -43,16 +59,35 @@ export interface DesignerComponentInput {
readonly dirty: boolean;
/**
* A boolean value indicating whether the changes are being saved.
* Current in progress action.
*/
readonly saving: boolean;
readonly pendingAction?: DesignerAction;
/**
* The UI state of the designer, used to restore the state.
*/
designerUIState?: DesignerUIState;
}
export interface DesignerUIState {
activeTabId: PanelTabIdentifier;
}
export type DesignerAction = 'save' | 'initialize' | 'processEdit';
export interface DesignerEditProcessedEventArgs {
result: DesignerEditResult;
edit: DesignerEdit
}
export interface DesignerStateChangedEventArgs {
currentState: DesignerState,
previousState: DesignerState
}
export interface DesignerState {
valid: boolean;
dirty: boolean;
saving: boolean;
processing: boolean;
pendingAction?: DesignerAction
}
export const NameProperty = 'name';

View File

@@ -108,6 +108,10 @@ export class TabbedPanel extends Disposable {
return this.parent;
}
public get activeTabId(): string | undefined {
return this._shownTabId;
}
public override dispose() {
this.header.remove();
this.tabList.remove();

View File

@@ -7,7 +7,7 @@ import * as DOM from 'vs/base/browser/dom';
export interface ITableCellEditorOptions {
valueGetter?: (item: Slick.SlickData, column: Slick.Column<Slick.SlickData>) => string,
valueSetter?: (context: any, row: number, item: Slick.SlickData, column: Slick.Column<Slick.SlickData>, value: string) => Promise<void>,
valueSetter?: (context: any, row: number, item: Slick.SlickData, column: Slick.Column<Slick.SlickData>, value: string) => void,
optionsGetter?: (item: Slick.SlickData, column: Slick.Column<Slick.SlickData>) => string[],
editorStyler: (component: InputBox | SelectBox) => void
}
@@ -72,9 +72,9 @@ export class TableCellEditorFactory {
this._input.value = this._originalValue;
}
public async applyValue(item: Slick.SlickData, state: string): Promise<void> {
public applyValue(item: Slick.SlickData, state: string): void {
const activeCell = this._args.grid.getActiveCell();
await self._options.valueSetter(context, activeCell.row, item, this._args.column, state);
self._options.valueSetter(context, activeCell.row, item, this._args.column, state);
}
public isValueChanged(): boolean {

View File

@@ -29,7 +29,9 @@ export class TableDesignerInput extends EditorInput {
super();
this._designerComponentInput = this._instantiationService.createInstance(TableDesignerComponentInput, this._provider, this._tableInfo);
this._register(this._designerComponentInput.onStateChange((e) => {
this._onDidChangeDirty.fire();
if (e.currentState.dirty !== e.previousState.dirty) {
this._onDidChangeDirty.fire();
}
}));
const existingNames = editorService.editors.map(editor => editor.getName());
@@ -66,7 +68,7 @@ export class TableDesignerInput extends EditorInput {
}
override isSaving(): boolean {
return this._designerComponentInput.saving;
return this._designerComponentInput.pendingAction === 'save';
}
override async save(group: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {

View File

@@ -34,7 +34,7 @@ export class SaveTableChangesAction extends Action {
}
private updateState(): void {
this.enabled = this._input.dirty && this._input.valid && !this._input.processing;
this.enabled = this._input.dirty && this._input.valid && this._input.pendingAction === undefined;
}
override dispose() {

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { DesignerViewModel, DesignerEdit, DesignerEditResult, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerState } from 'sql/base/browser/ui/designer/interfaces';
import { DesignerViewModel, DesignerEdit, DesignerComponentInput, DesignerView, DesignerTab, DesignerDataPropertyInfo, DropDownProperties, DesignerTableProperties, DesignerEditProcessedEventArgs, DesignerAction, DesignerStateChangedEventArgs } from 'sql/base/browser/ui/designer/interfaces';
import { TableDesignerProvider } from 'sql/workbench/services/tableDesigner/common/interface';
import { localize } from 'vs/nls';
import { designers } from 'sql/workbench/api/common/sqlExtHostTypes';
@@ -17,11 +17,14 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
private _view: DesignerView;
private _valid: boolean = true;
private _dirty: boolean = false;
private _saving: boolean = false;
private _processing: boolean = false;
private _onStateChange = new Emitter<DesignerState>();
private _pendingAction?: DesignerAction = undefined;
private _onStateChange = new Emitter<DesignerStateChangedEventArgs>();
private _onInitialized = new Emitter<void>();
private _onEditProcessed = new Emitter<DesignerEditProcessedEventArgs>();
public readonly onStateChange: Event<DesignerState> = this._onStateChange.event;
public readonly onInitialized: Event<void> = this._onInitialized.event;
public readonly onEditProcessed: Event<DesignerEditProcessedEventArgs> = this._onEditProcessed.event;
public readonly onStateChange: Event<DesignerStateChangedEventArgs> = this._onStateChange.event;
constructor(private readonly _provider: TableDesignerProvider,
private _tableInfo: azdata.designers.TableInfo,
@@ -36,43 +39,44 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
return this._dirty;
}
get saving(): boolean {
return this._saving;
}
get processing(): boolean {
return this._processing;
get pendingAction(): DesignerAction | undefined {
return this._pendingAction;
}
get objectTypeDisplayName(): string {
return localize('tableDesigner.tableObjectType', "Table");
}
async getView(): Promise<DesignerView> {
if (!this._view) {
await this.initialize();
}
get view(): DesignerView {
return this._view;
}
async getViewModel(): Promise<DesignerViewModel> {
if (!this._viewModel) {
await this.initialize();
}
get viewModel(): DesignerViewModel {
return this._viewModel;
}
async processEdit(edit: DesignerEdit): Promise<DesignerEditResult> {
this.updateState(this.valid, this.dirty, this.saving, true);
const result = await this._provider.processTableEdit(this._tableInfo, this._viewModel!, edit);
if (result.isValid) {
this._viewModel = result.viewModel;
}
this.updateState(result.isValid, true, this.saving, false);
return {
isValid: result.isValid,
errors: result.errors
};
processEdit(edit: DesignerEdit): void {
this.updateState(this.valid, this.dirty, 'processEdit');
this._provider.processTableEdit(this._tableInfo, this._viewModel!, edit).then(
result => {
if (result.isValid) {
this._viewModel = result.viewModel;
}
this.updateState(result.isValid, true, undefined);
this._onEditProcessed.fire({
edit: edit,
result: {
isValid: result.isValid,
errors: result.errors
}
});
},
error => {
this._notificationService.error(localize('tableDesigner.errorProcessingEdit', "An error occured while processing the change: {0}", error?.message ?? error));
this.updateState(this.valid, this.dirty);
}
);
}
async save(): Promise<void> {
@@ -81,40 +85,61 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
message: localize('tableDesigner.savingChanges', "Saving table designer changes...")
});
try {
this.updateState(this.valid, this.dirty, true, true);
this.updateState(this.valid, this.dirty, 'save');
await this._provider.saveTable(this._tableInfo, this._viewModel);
this.updateState(true, false, false, false);
this.updateState(true, false);
notificationHandle.updateMessage(localize('tableDesigner.savedChangeSuccess', "The changes have been successfully saved."));
} catch (error) {
notificationHandle.updateSeverity(Severity.Error);
notificationHandle.updateMessage(localize('tableDesigner.saveChangeError', "An error occured while saving changes: {0}", error?.message ?? error));
this.updateState(this.valid, this.dirty, false, false);
this.updateState(this.valid, this.dirty);
}
}
async revert(): Promise<void> {
this.updateState(true, false, false, false);
this.updateState(true, false);
}
private updateState(valid: boolean, dirty: boolean, saving: boolean, processing: boolean): void {
if (this._dirty !== dirty || this._valid !== valid || this._saving !== saving || this._processing !== processing) {
this._dirty = dirty;
this._valid = valid;
this._saving = saving;
this._processing = processing;
this._onStateChange.fire({
private updateState(valid: boolean, dirty: boolean, pendingAction?: DesignerAction): void {
if (this._dirty !== dirty || this._valid !== valid || this._pendingAction !== pendingAction) {
const previousState = {
valid: this._valid,
dirty: this._dirty,
saving: this._saving,
processing: this._processing
pendingAction: this._pendingAction
};
this._dirty = dirty;
this._valid = valid;
this._pendingAction = pendingAction;
const currentState = {
valid: this._valid,
dirty: this._dirty,
pendingAction: this._pendingAction
};
this._onStateChange.fire({
currentState,
previousState,
});
}
}
private async initialize(): Promise<void> {
this.updateState(this.valid, this.dirty, this.saving, true);
const designerInfo = await this._provider.getTableDesignerInfo(this._tableInfo);
this.updateState(this.valid, this.dirty, this.saving, false);
initialize(): void {
if (this._view !== undefined || this.pendingAction === 'initialize') {
return;
}
this.updateState(this.valid, this.dirty, 'initialize');
this._provider.getTableDesignerInfo(this._tableInfo).then(result => {
this.doInitialization(result);
this._onInitialized.fire();
}, error => {
this._notificationService.error(localize('tableDesigner.errorInitializingTableDesigner', "An error occured while initializing the table designer: {0}", error?.message ?? error));
});
}
private doInitialization(designerInfo: azdata.designers.TableDesignerInfo): void {
this.updateState(true, false);
this._viewModel = designerInfo.viewModel;
this.setDefaultData();